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

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

// ignore_for_file: annotate_overrides
// ignore_for_file: deprecated_member_use
// ignore_for_file: deprecated_member_use_from_same_package
// ignore_for_file: unnecessary_brace_in_string_interps
// ignore_for_file: unnecessary_parenthesis
// ignore_for_file: unused_import
// ignore_for_file: unused_shown_name

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'
    show listEqual, mapEqual;
import 'package:analyzer/src/generated/utilities_general.dart';
import 'package:meta/meta.dart';

const jsonEncoder = JsonEncoder.withIndent('    ');

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

  AnnotatedTextEdit(
      {@required this.annotationId,
      @required this.range,
      @required this.newText}) {
    if (annotationId == null) {
      throw 'annotationId is required but was not provided';
    }
    if (range == null) {
      throw 'range is required but was not provided';
    }
    if (newText == null) {
      throw 'newText is required but was not provided';
    }
  }
  static AnnotatedTextEdit fromJson(Map<String, dynamic> json) {
    final annotationId = json['annotationId'];
    final range = json['range'] != null ? Range.fromJson(json['range']) : null;
    final newText = json['newText'];
    return AnnotatedTextEdit(
        annotationId: annotationId, range: range, newText: newText);
  }

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

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

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['annotationId'] =
        annotationId ?? (throw 'annotationId is required but was not set');
    __result['range'] =
        range?.toJson() ?? (throw 'range is required but was not set');
    __result['newText'] =
        newText ?? (throw 'newText is required but was not set');
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, annotationId.hashCode);
    hash = JenkinsSmiHash.combine(hash, range.hashCode);
    hash = JenkinsSmiHash.combine(hash, newText.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  ApplyWorkspaceEditParams({this.label, @required this.edit}) {
    if (edit == null) {
      throw 'edit is required but was not provided';
    }
  }
  static ApplyWorkspaceEditParams fromJson(Map<String, dynamic> json) {
    final label = json['label'];
    final edit =
        json['edit'] != null ? WorkspaceEdit.fromJson(json['edit']) : null;
    return ApplyWorkspaceEditParams(label: label, edit: edit);
  }

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

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (label != null) {
      __result['label'] = label;
    }
    __result['edit'] =
        edit?.toJson() ?? (throw 'edit is required but was not set');
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, label.hashCode);
    hash = JenkinsSmiHash.combine(hash, edit.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  ApplyWorkspaceEditResponse(
      {@required this.applied, this.failureReason, this.failedChange}) {
    if (applied == null) {
      throw 'applied is required but was not provided';
    }
  }
  static ApplyWorkspaceEditResponse fromJson(Map<String, dynamic> json) {
    final applied = json['applied'];
    final failureReason = json['failureReason'];
    final failedChange = json['failedChange'];
    return ApplyWorkspaceEditResponse(
        applied: applied,
        failureReason: failureReason,
        failedChange: failedChange);
  }

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

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

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['applied'] =
        applied ?? (throw 'applied is required but was not set');
    if (failureReason != null) {
      __result['failureReason'] = failureReason;
    }
    if (failedChange != null) {
      __result['failedChange'] = failedChange;
    }
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, applied.hashCode);
    hash = JenkinsSmiHash.combine(hash, failureReason.hashCode);
    hash = JenkinsSmiHash.combine(hash, failedChange.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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, dynamic> json) {
    final dynamicRegistration = json['dynamicRegistration'];
    return CallHierarchyClientCapabilities(
        dynamicRegistration: dynamicRegistration);
  }

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (dynamicRegistration != null) {
      __result['dynamicRegistration'] = dynamicRegistration;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('dynamicRegistration');
      try {
        if (obj['dynamicRegistration'] != null &&
            !(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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}) {
    if (from == null) {
      throw 'from is required but was not provided';
    }
    if (fromRanges == null) {
      throw 'fromRanges is required but was not provided';
    }
  }
  static CallHierarchyIncomingCall fromJson(Map<String, dynamic> json) {
    final from =
        json['from'] != null ? CallHierarchyItem.fromJson(json['from']) : null;
    final fromRanges = json['fromRanges']
        ?.map((item) => item != null ? Range.fromJson(item) : null)
        ?.cast<Range>()
        ?.toList();
    return CallHierarchyIncomingCall(from: from, fromRanges: fromRanges);
  }

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

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['from'] =
        from?.toJson() ?? (throw 'from is required but was not set');
    __result['fromRanges'] =
        fromRanges?.map((item) => item.toJson())?.toList() ??
            (throw 'fromRanges is required but was not set');
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, from.hashCode);
    hash = JenkinsSmiHash.combine(hash, lspHashCode(fromRanges));
    return JenkinsSmiHash.finish(hash);
  }

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

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

  CallHierarchyIncomingCallsParams(
      {@required this.item, this.workDoneToken, this.partialResultToken}) {
    if (item == null) {
      throw 'item is required but was not provided';
    }
  }
  static CallHierarchyIncomingCallsParams fromJson(Map<String, dynamic> json) {
    final item =
        json['item'] != null ? CallHierarchyItem.fromJson(json['item']) : null;
    final workDoneToken = json['workDoneToken'] is num
        ? Either2<num, String>.t1(json['workDoneToken'])
        : (json['workDoneToken'] is String
            ? Either2<num, String>.t2(json['workDoneToken'])
            : (json['workDoneToken'] == null
                ? null
                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
    final partialResultToken = json['partialResultToken'] is num
        ? Either2<num, String>.t1(json['partialResultToken'])
        : (json['partialResultToken'] is String
            ? Either2<num, String>.t2(json['partialResultToken'])
            : (json['partialResultToken'] == null
                ? null
                : (throw '''${json['partialResultToken']} was not one of (num, String)''')));
    return CallHierarchyIncomingCallsParams(
        item: item,
        workDoneToken: workDoneToken,
        partialResultToken: partialResultToken);
  }

  final CallHierarchyItem item;

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

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['item'] =
        item?.toJson() ?? (throw 'item is required but was not set');
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    if (partialResultToken != null) {
      __result['partialResultToken'] = partialResultToken;
    }
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, item.hashCode);
    hash = JenkinsSmiHash.combine(hash, workDoneToken.hashCode);
    hash = JenkinsSmiHash.combine(hash, partialResultToken.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  CallHierarchyItem(
      {@required this.name,
      @required this.kind,
      this.tags,
      this.detail,
      @required this.uri,
      @required this.range,
      @required this.selectionRange,
      this.data}) {
    if (name == null) {
      throw 'name is required but was not provided';
    }
    if (kind == null) {
      throw 'kind is required but was not provided';
    }
    if (uri == null) {
      throw 'uri is required but was not provided';
    }
    if (range == null) {
      throw 'range is required but was not provided';
    }
    if (selectionRange == null) {
      throw 'selectionRange is required but was not provided';
    }
  }
  static CallHierarchyItem fromJson(Map<String, dynamic> json) {
    final name = json['name'];
    final kind =
        json['kind'] != null ? SymbolKind.fromJson(json['kind']) : null;
    final tags = json['tags']
        ?.map((item) => item != null ? SymbolTag.fromJson(item) : null)
        ?.cast<SymbolTag>()
        ?.toList();
    final detail = json['detail'];
    final uri = json['uri'];
    final range = json['range'] != null ? Range.fromJson(json['range']) : null;
    final selectionRange = json['selectionRange'] != null
        ? Range.fromJson(json['selectionRange'])
        : null;
    final data = json['data'];
    return CallHierarchyItem(
        name: name,
        kind: kind,
        tags: tags,
        detail: detail,
        uri: uri,
        range: range,
        selectionRange: selectionRange,
        data: data);
  }

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

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

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

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

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

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

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

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['name'] = name ?? (throw 'name is required but was not set');
    __result['kind'] =
        kind?.toJson() ?? (throw 'kind is required but was not set');
    if (tags != null) {
      __result['tags'] = tags.map((item) => item.toJson()).toList();
    }
    if (detail != null) {
      __result['detail'] = detail;
    }
    __result['uri'] = uri ?? (throw 'uri is required but was not set');
    __result['range'] =
        range?.toJson() ?? (throw 'range is required but was not set');
    __result['selectionRange'] = selectionRange?.toJson() ??
        (throw 'selectionRange is required but was not set');
    if (data != null) {
      __result['data'] = data;
    }
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, name.hashCode);
    hash = JenkinsSmiHash.combine(hash, kind.hashCode);
    hash = JenkinsSmiHash.combine(hash, lspHashCode(tags));
    hash = JenkinsSmiHash.combine(hash, detail.hashCode);
    hash = JenkinsSmiHash.combine(hash, uri.hashCode);
    hash = JenkinsSmiHash.combine(hash, range.hashCode);
    hash = JenkinsSmiHash.combine(hash, selectionRange.hashCode);
    hash = JenkinsSmiHash.combine(hash, data.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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, dynamic> json) {
    if (CallHierarchyRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return CallHierarchyRegistrationOptions.fromJson(json);
    }
    final workDoneProgress = json['workDoneProgress'];
    return CallHierarchyOptions(workDoneProgress: workDoneProgress);
  }

  final bool workDoneProgress;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('workDoneProgress');
      try {
        if (obj['workDoneProgress'] != null &&
            !(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  CallHierarchyOutgoingCall({@required this.to, @required this.fromRanges}) {
    if (to == null) {
      throw 'to is required but was not provided';
    }
    if (fromRanges == null) {
      throw 'fromRanges is required but was not provided';
    }
  }
  static CallHierarchyOutgoingCall fromJson(Map<String, dynamic> json) {
    final to =
        json['to'] != null ? CallHierarchyItem.fromJson(json['to']) : null;
    final fromRanges = json['fromRanges']
        ?.map((item) => item != null ? Range.fromJson(item) : null)
        ?.cast<Range>()
        ?.toList();
    return CallHierarchyOutgoingCall(to: to, fromRanges: fromRanges);
  }

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

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['to'] = to?.toJson() ?? (throw 'to is required but was not set');
    __result['fromRanges'] =
        fromRanges?.map((item) => item.toJson())?.toList() ??
            (throw 'fromRanges is required but was not set');
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, to.hashCode);
    hash = JenkinsSmiHash.combine(hash, lspHashCode(fromRanges));
    return JenkinsSmiHash.finish(hash);
  }

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

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

  CallHierarchyOutgoingCallsParams(
      {@required this.item, this.workDoneToken, this.partialResultToken}) {
    if (item == null) {
      throw 'item is required but was not provided';
    }
  }
  static CallHierarchyOutgoingCallsParams fromJson(Map<String, dynamic> json) {
    final item =
        json['item'] != null ? CallHierarchyItem.fromJson(json['item']) : null;
    final workDoneToken = json['workDoneToken'] is num
        ? Either2<num, String>.t1(json['workDoneToken'])
        : (json['workDoneToken'] is String
            ? Either2<num, String>.t2(json['workDoneToken'])
            : (json['workDoneToken'] == null
                ? null
                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
    final partialResultToken = json['partialResultToken'] is num
        ? Either2<num, String>.t1(json['partialResultToken'])
        : (json['partialResultToken'] is String
            ? Either2<num, String>.t2(json['partialResultToken'])
            : (json['partialResultToken'] == null
                ? null
                : (throw '''${json['partialResultToken']} was not one of (num, String)''')));
    return CallHierarchyOutgoingCallsParams(
        item: item,
        workDoneToken: workDoneToken,
        partialResultToken: partialResultToken);
  }

  final CallHierarchyItem item;

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

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['item'] =
        item?.toJson() ?? (throw 'item is required but was not set');
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    if (partialResultToken != null) {
      __result['partialResultToken'] = partialResultToken;
    }
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, item.hashCode);
    hash = JenkinsSmiHash.combine(hash, workDoneToken.hashCode);
    hash = JenkinsSmiHash.combine(hash, partialResultToken.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  CallHierarchyPrepareParams(
      {@required this.textDocument,
      @required this.position,
      this.workDoneToken}) {
    if (textDocument == null) {
      throw 'textDocument is required but was not provided';
    }
    if (position == null) {
      throw 'position is required but was not provided';
    }
  }
  static CallHierarchyPrepareParams fromJson(Map<String, dynamic> json) {
    final textDocument = json['textDocument'] != null
        ? TextDocumentIdentifier.fromJson(json['textDocument'])
        : null;
    final position =
        json['position'] != null ? Position.fromJson(json['position']) : null;
    final workDoneToken = json['workDoneToken'] is num
        ? Either2<num, String>.t1(json['workDoneToken'])
        : (json['workDoneToken'] is String
            ? Either2<num, String>.t2(json['workDoneToken'])
            : (json['workDoneToken'] == null
                ? null
                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
    return CallHierarchyPrepareParams(
        textDocument: textDocument,
        position: position,
        workDoneToken: workDoneToken);
  }

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

  /// The text document.
  final TextDocumentIdentifier textDocument;

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['textDocument'] = textDocument?.toJson() ??
        (throw 'textDocument is required but was not set');
    __result['position'] =
        position?.toJson() ?? (throw 'position is required but was not set');
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, textDocument.hashCode);
    hash = JenkinsSmiHash.combine(hash, position.hashCode);
    hash = JenkinsSmiHash.combine(hash, workDoneToken.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  CallHierarchyRegistrationOptions(
      {this.documentSelector, this.workDoneProgress, this.id});
  static CallHierarchyRegistrationOptions fromJson(Map<String, dynamic> json) {
    final documentSelector = json['documentSelector']
        ?.map((item) => item != null ? DocumentFilter.fromJson(item) : null)
        ?.cast<DocumentFilter>()
        ?.toList();
    final workDoneProgress = json['workDoneProgress'];
    final id = json['id'];
    return CallHierarchyRegistrationOptions(
        documentSelector: documentSelector,
        workDoneProgress: workDoneProgress,
        id: id);
  }

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

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['documentSelector'] = documentSelector;
    if (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    if (id != null) {
      __result['id'] = id;
    }
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(documentSelector));
    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
    hash = JenkinsSmiHash.combine(hash, id.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  CancelParams({@required this.id}) {
    if (id == null) {
      throw 'id is required but was not provided';
    }
  }
  static CancelParams fromJson(Map<String, dynamic> json) {
    final id = json['id'] is num
        ? Either2<num, String>.t1(json['id'])
        : (json['id'] is String
            ? Either2<num, String>.t2(json['id'])
            : (throw '''${json['id']} was not one of (num, String)'''));
    return CancelParams(id: id);
  }

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['id'] = id ?? (throw 'id is required but was not set');
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('id');
      try {
        if (!obj.containsKey('id')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['id'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!((obj['id'] is num || obj['id'] is String))) {
          reporter.reportError('must be of type Either2<num, 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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, id.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  ChangeAnnotation(
      {@required this.label, this.needsConfirmation, this.description}) {
    if (label == null) {
      throw 'label is required but was not provided';
    }
  }
  static ChangeAnnotation fromJson(Map<String, dynamic> json) {
    final label = json['label'];
    final needsConfirmation = json['needsConfirmation'];
    final description = json['description'];
    return ChangeAnnotation(
        label: label,
        needsConfirmation: needsConfirmation,
        description: description);
  }

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

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

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['label'] = label ?? (throw 'label is required but was not set');
    if (needsConfirmation != null) {
      __result['needsConfirmation'] = needsConfirmation;
    }
    if (description != null) {
      __result['description'] = description;
    }
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, label.hashCode);
    hash = JenkinsSmiHash.combine(hash, needsConfirmation.hashCode);
    hash = JenkinsSmiHash.combine(hash, description.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  ClientCapabilities(
      {this.workspace,
      this.textDocument,
      this.window,
      this.general,
      this.experimental});
  static ClientCapabilities fromJson(Map<String, dynamic> json) {
    final workspace = json['workspace'] != null
        ? ClientCapabilitiesWorkspace.fromJson(json['workspace'])
        : null;
    final textDocument = json['textDocument'] != null
        ? TextDocumentClientCapabilities.fromJson(json['textDocument'])
        : null;
    final window = json['window'] != null
        ? ClientCapabilitiesWindow.fromJson(json['window'])
        : null;
    final general = json['general'] != null
        ? ClientCapabilitiesGeneral.fromJson(json['general'])
        : null;
    final experimental = json['experimental'];
    return ClientCapabilities(
        workspace: workspace,
        textDocument: textDocument,
        window: window,
        general: general,
        experimental: experimental);
  }

  /// Experimental client capabilities.
  final dynamic experimental;

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

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

  /// Window specific client capabilities.
  final ClientCapabilitiesWindow window;

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

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

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('workspace');
      try {
        if (obj['workspace'] != null &&
            !(ClientCapabilitiesWorkspace.canParse(
                obj['workspace'], reporter))) {
          reporter.reportError('must be of type ClientCapabilitiesWorkspace');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (obj['textDocument'] != null &&
            !(TextDocumentClientCapabilities.canParse(
                obj['textDocument'], reporter))) {
          reporter
              .reportError('must be of type TextDocumentClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('window');
      try {
        if (obj['window'] != null &&
            !(ClientCapabilitiesWindow.canParse(obj['window'], reporter))) {
          reporter.reportError('must be of type ClientCapabilitiesWindow');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('general');
      try {
        if (obj['general'] != null &&
            !(ClientCapabilitiesGeneral.canParse(obj['general'], reporter))) {
          reporter.reportError('must be of type ClientCapabilitiesGeneral');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('experimental');
      try {
        if (obj['experimental'] != null && !(true)) {
          reporter.reportError('must be of type dynamic');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ClientCapabilities');
      return false;
    }
  }

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, workspace.hashCode);
    hash = JenkinsSmiHash.combine(hash, textDocument.hashCode);
    hash = JenkinsSmiHash.combine(hash, window.hashCode);
    hash = JenkinsSmiHash.combine(hash, general.hashCode);
    hash = JenkinsSmiHash.combine(hash, experimental.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  ClientCapabilitiesFileOperations(
      {this.dynamicRegistration,
      this.didCreate,
      this.willCreate,
      this.didRename,
      this.willRename,
      this.didDelete,
      this.willDelete});
  static ClientCapabilitiesFileOperations fromJson(Map<String, dynamic> json) {
    final dynamicRegistration = json['dynamicRegistration'];
    final didCreate = json['didCreate'];
    final willCreate = json['willCreate'];
    final didRename = json['didRename'];
    final willRename = json['willRename'];
    final didDelete = json['didDelete'];
    final willDelete = json['willDelete'];
    return ClientCapabilitiesFileOperations(
        dynamicRegistration: dynamicRegistration,
        didCreate: didCreate,
        willCreate: willCreate,
        didRename: didRename,
        willRename: willRename,
        didDelete: didDelete,
        willDelete: willDelete);
  }

  /// The client has support for sending didCreateFiles notifications.
  final bool didCreate;

  /// The client has support for sending didDeleteFiles notifications.
  final bool didDelete;

  /// The client has support for sending didRenameFiles notifications.
  final bool didRename;

  /// Whether the client supports dynamic registration for file
  /// requests/notifications.
  final bool dynamicRegistration;

  /// The client has support for sending willCreateFiles requests.
  final bool willCreate;

  /// The client has support for sending willDeleteFiles requests.
  final bool willDelete;

  /// The client has support for sending willRenameFiles requests.
  final bool willRename;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (dynamicRegistration != null) {
      __result['dynamicRegistration'] = dynamicRegistration;
    }
    if (didCreate != null) {
      __result['didCreate'] = didCreate;
    }
    if (willCreate != null) {
      __result['willCreate'] = willCreate;
    }
    if (didRename != null) {
      __result['didRename'] = didRename;
    }
    if (willRename != null) {
      __result['willRename'] = willRename;
    }
    if (didDelete != null) {
      __result['didDelete'] = didDelete;
    }
    if (willDelete != null) {
      __result['willDelete'] = willDelete;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('dynamicRegistration');
      try {
        if (obj['dynamicRegistration'] != null &&
            !(obj['dynamicRegistration'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('didCreate');
      try {
        if (obj['didCreate'] != null && !(obj['didCreate'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('willCreate');
      try {
        if (obj['willCreate'] != null && !(obj['willCreate'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('didRename');
      try {
        if (obj['didRename'] != null && !(obj['didRename'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('willRename');
      try {
        if (obj['willRename'] != null && !(obj['willRename'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('didDelete');
      try {
        if (obj['didDelete'] != null && !(obj['didDelete'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('willDelete');
      try {
        if (obj['willDelete'] != null && !(obj['willDelete'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ClientCapabilitiesFileOperations');
      return false;
    }
  }

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode);
    hash = JenkinsSmiHash.combine(hash, didCreate.hashCode);
    hash = JenkinsSmiHash.combine(hash, willCreate.hashCode);
    hash = JenkinsSmiHash.combine(hash, didRename.hashCode);
    hash = JenkinsSmiHash.combine(hash, willRename.hashCode);
    hash = JenkinsSmiHash.combine(hash, didDelete.hashCode);
    hash = JenkinsSmiHash.combine(hash, willDelete.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  ClientCapabilitiesGeneral({this.regularExpressions, this.markdown});
  static ClientCapabilitiesGeneral fromJson(Map<String, dynamic> json) {
    final regularExpressions = json['regularExpressions'] != null
        ? RegularExpressionsClientCapabilities.fromJson(
            json['regularExpressions'])
        : null;
    final markdown = json['markdown'] != null
        ? MarkdownClientCapabilities.fromJson(json['markdown'])
        : null;
    return ClientCapabilitiesGeneral(
        regularExpressions: regularExpressions, markdown: markdown);
  }

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

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

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

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, regularExpressions.hashCode);
    hash = JenkinsSmiHash.combine(hash, markdown.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

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

  /// Client capabilities for the show document request.
  ///  @since 3.16.0
  final ShowDocumentClientCapabilities showDocument;

  /// Capabilities specific to the showMessage request
  ///  @since 3.16.0
  final ShowMessageRequestClientCapabilities showMessage;

  /// Whether client supports handling progress notifications. If set servers
  /// are allowed to report in `workDoneProgress` property in the request
  /// specific server capabilities.
  ///  @since 3.15.0
  final bool workDoneProgress;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    if (showMessage != null) {
      __result['showMessage'] = showMessage.toJson();
    }
    if (showDocument != null) {
      __result['showDocument'] = showDocument.toJson();
    }
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
    hash = JenkinsSmiHash.combine(hash, showMessage.hashCode);
    hash = JenkinsSmiHash.combine(hash, showDocument.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  ClientCapabilitiesWorkspace(
      {this.applyEdit,
      this.workspaceEdit,
      this.didChangeConfiguration,
      this.didChangeWatchedFiles,
      this.symbol,
      this.executeCommand,
      this.workspaceFolders,
      this.configuration,
      this.semanticTokens,
      this.codeLens,
      this.fileOperations});
  static ClientCapabilitiesWorkspace fromJson(Map<String, dynamic> json) {
    final applyEdit = json['applyEdit'];
    final workspaceEdit = json['workspaceEdit'] != null
        ? WorkspaceEditClientCapabilities.fromJson(json['workspaceEdit'])
        : null;
    final didChangeConfiguration = json['didChangeConfiguration'] != null
        ? DidChangeConfigurationClientCapabilities.fromJson(
            json['didChangeConfiguration'])
        : null;
    final didChangeWatchedFiles = json['didChangeWatchedFiles'] != null
        ? DidChangeWatchedFilesClientCapabilities.fromJson(
            json['didChangeWatchedFiles'])
        : null;
    final symbol = json['symbol'] != null
        ? WorkspaceSymbolClientCapabilities.fromJson(json['symbol'])
        : null;
    final executeCommand = json['executeCommand'] != null
        ? ExecuteCommandClientCapabilities.fromJson(json['executeCommand'])
        : null;
    final workspaceFolders = json['workspaceFolders'];
    final configuration = json['configuration'];
    final semanticTokens = json['semanticTokens'] != null
        ? SemanticTokensWorkspaceClientCapabilities.fromJson(
            json['semanticTokens'])
        : null;
    final codeLens = json['codeLens'] != null
        ? CodeLensWorkspaceClientCapabilities.fromJson(json['codeLens'])
        : null;
    final fileOperations = json['fileOperations'] != null
        ? ClientCapabilitiesFileOperations.fromJson(json['fileOperations'])
        : null;
    return ClientCapabilitiesWorkspace(
        applyEdit: applyEdit,
        workspaceEdit: workspaceEdit,
        didChangeConfiguration: didChangeConfiguration,
        didChangeWatchedFiles: didChangeWatchedFiles,
        symbol: symbol,
        executeCommand: executeCommand,
        workspaceFolders: workspaceFolders,
        configuration: configuration,
        semanticTokens: semanticTokens,
        codeLens: codeLens,
        fileOperations: fileOperations);
  }

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

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

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

  /// Capabilities specific to the `workspace/didChangeConfiguration`
  /// notification.
  final DidChangeConfigurationClientCapabilities didChangeConfiguration;

  /// Capabilities specific to the `workspace/didChangeWatchedFiles`
  /// notification.
  final DidChangeWatchedFilesClientCapabilities didChangeWatchedFiles;

  /// Capabilities specific to the `workspace/executeCommand` request.
  final ExecuteCommandClientCapabilities executeCommand;

  /// The client has support for file requests/notifications.
  ///  @since 3.16.0
  final ClientCapabilitiesFileOperations fileOperations;

  /// Capabilities specific to the semantic token requests scoped to the
  /// workspace.
  ///  @since 3.16.0
  final SemanticTokensWorkspaceClientCapabilities semanticTokens;

  /// Capabilities specific to the `workspace/symbol` request.
  final WorkspaceSymbolClientCapabilities symbol;

  /// Capabilities specific to `WorkspaceEdit`s
  final WorkspaceEditClientCapabilities workspaceEdit;

  /// The client has support for workspace folders.
  ///  @since 3.6.0
  final bool workspaceFolders;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (applyEdit != null) {
      __result['applyEdit'] = applyEdit;
    }
    if (workspaceEdit != null) {
      __result['workspaceEdit'] = workspaceEdit.toJson();
    }
    if (didChangeConfiguration != null) {
      __result['didChangeConfiguration'] = didChangeConfiguration.toJson();
    }
    if (didChangeWatchedFiles != null) {
      __result['didChangeWatchedFiles'] = didChangeWatchedFiles.toJson();
    }
    if (symbol != null) {
      __result['symbol'] = symbol.toJson();
    }
    if (executeCommand != null) {
      __result['executeCommand'] = executeCommand.toJson();
    }
    if (workspaceFolders != null) {
      __result['workspaceFolders'] = workspaceFolders;
    }
    if (configuration != null) {
      __result['configuration'] = configuration;
    }
    if (semanticTokens != null) {
      __result['semanticTokens'] = semanticTokens.toJson();
    }
    if (codeLens != null) {
      __result['codeLens'] = codeLens.toJson();
    }
    if (fileOperations != null) {
      __result['fileOperations'] = fileOperations.toJson();
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('applyEdit');
      try {
        if (obj['applyEdit'] != null && !(obj['applyEdit'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workspaceEdit');
      try {
        if (obj['workspaceEdit'] != null &&
            !(WorkspaceEditClientCapabilities.canParse(
                obj['workspaceEdit'], reporter))) {
          reporter
              .reportError('must be of type WorkspaceEditClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('didChangeConfiguration');
      try {
        if (obj['didChangeConfiguration'] != null &&
            !(DidChangeConfigurationClientCapabilities.canParse(
                obj['didChangeConfiguration'], reporter))) {
          reporter.reportError(
              'must be of type DidChangeConfigurationClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('didChangeWatchedFiles');
      try {
        if (obj['didChangeWatchedFiles'] != null &&
            !(DidChangeWatchedFilesClientCapabilities.canParse(
                obj['didChangeWatchedFiles'], reporter))) {
          reporter.reportError(
              'must be of type DidChangeWatchedFilesClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('symbol');
      try {
        if (obj['symbol'] != null &&
            !(WorkspaceSymbolClientCapabilities.canParse(
                obj['symbol'], reporter))) {
          reporter
              .reportError('must be of type WorkspaceSymbolClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('executeCommand');
      try {
        if (obj['executeCommand'] != null &&
            !(ExecuteCommandClientCapabilities.canParse(
                obj['executeCommand'], reporter))) {
          reporter
              .reportError('must be of type ExecuteCommandClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workspaceFolders');
      try {
        if (obj['workspaceFolders'] != null &&
            !(obj['workspaceFolders'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('configuration');
      try {
        if (obj['configuration'] != null && !(obj['configuration'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('semanticTokens');
      try {
        if (obj['semanticTokens'] != null &&
            !(SemanticTokensWorkspaceClientCapabilities.canParse(
                obj['semanticTokens'], reporter))) {
          reporter.reportError(
              'must be of type SemanticTokensWorkspaceClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('codeLens');
      try {
        if (obj['codeLens'] != null &&
            !(CodeLensWorkspaceClientCapabilities.canParse(
                obj['codeLens'], reporter))) {
          reporter.reportError(
              'must be of type CodeLensWorkspaceClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('fileOperations');
      try {
        if (obj['fileOperations'] != null &&
            !(ClientCapabilitiesFileOperations.canParse(
                obj['fileOperations'], reporter))) {
          reporter
              .reportError('must be of type ClientCapabilitiesFileOperations');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ClientCapabilitiesWorkspace');
      return false;
    }
  }

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, applyEdit.hashCode);
    hash = JenkinsSmiHash.combine(hash, workspaceEdit.hashCode);
    hash = JenkinsSmiHash.combine(hash, didChangeConfiguration.hashCode);
    hash = JenkinsSmiHash.combine(hash, didChangeWatchedFiles.hashCode);
    hash = JenkinsSmiHash.combine(hash, symbol.hashCode);
    hash = JenkinsSmiHash.combine(hash, executeCommand.hashCode);
    hash = JenkinsSmiHash.combine(hash, workspaceFolders.hashCode);
    hash = JenkinsSmiHash.combine(hash, configuration.hashCode);
    hash = JenkinsSmiHash.combine(hash, semanticTokens.hashCode);
    hash = JenkinsSmiHash.combine(hash, codeLens.hashCode);
    hash = JenkinsSmiHash.combine(hash, fileOperations.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  CodeAction(
      {@required this.title,
      this.kind,
      this.diagnostics,
      this.isPreferred,
      this.disabled,
      this.edit,
      this.command,
      this.data}) {
    if (title == null) {
      throw 'title is required but was not provided';
    }
  }
  static CodeAction fromJson(Map<String, dynamic> json) {
    final title = json['title'];
    final kind =
        json['kind'] != null ? CodeActionKind.fromJson(json['kind']) : null;
    final diagnostics = json['diagnostics']
        ?.map((item) => item != null ? Diagnostic.fromJson(item) : null)
        ?.cast<Diagnostic>()
        ?.toList();
    final isPreferred = json['isPreferred'];
    final disabled = json['disabled'] != null
        ? CodeActionDisabled.fromJson(json['disabled'])
        : null;
    final edit =
        json['edit'] != null ? WorkspaceEdit.fromJson(json['edit']) : null;
    final command =
        json['command'] != null ? Command.fromJson(json['command']) : null;
    final data = json['data'];
    return CodeAction(
        title: title,
        kind: kind,
        diagnostics: diagnostics,
        isPreferred: isPreferred,
        disabled: disabled,
        edit: edit,
        command: command,
        data: data);
  }

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

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

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

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

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

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

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

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['title'] = title ?? (throw 'title is required but was not set');
    if (kind != null) {
      __result['kind'] = kind.toJson();
    }
    if (diagnostics != null) {
      __result['diagnostics'] =
          diagnostics.map((item) => item.toJson()).toList();
    }
    if (isPreferred != null) {
      __result['isPreferred'] = isPreferred;
    }
    if (disabled != null) {
      __result['disabled'] = disabled.toJson();
    }
    if (edit != null) {
      __result['edit'] = edit.toJson();
    }
    if (command != null) {
      __result['command'] = command.toJson();
    }
    if (data != null) {
      __result['data'] = data;
    }
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, title.hashCode);
    hash = JenkinsSmiHash.combine(hash, kind.hashCode);
    hash = JenkinsSmiHash.combine(hash, lspHashCode(diagnostics));
    hash = JenkinsSmiHash.combine(hash, isPreferred.hashCode);
    hash = JenkinsSmiHash.combine(hash, disabled.hashCode);
    hash = JenkinsSmiHash.combine(hash, edit.hashCode);
    hash = JenkinsSmiHash.combine(hash, command.hashCode);
    hash = JenkinsSmiHash.combine(hash, data.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  CodeActionClientCapabilities(
      {this.dynamicRegistration,
      this.codeActionLiteralSupport,
      this.isPreferredSupport,
      this.disabledSupport,
      this.dataSupport,
      this.resolveSupport,
      this.honorsChangeAnnotations});
  static CodeActionClientCapabilities fromJson(Map<String, dynamic> json) {
    final dynamicRegistration = json['dynamicRegistration'];
    final codeActionLiteralSupport = json['codeActionLiteralSupport'] != null
        ? CodeActionClientCapabilitiesCodeActionLiteralSupport.fromJson(
            json['codeActionLiteralSupport'])
        : null;
    final isPreferredSupport = json['isPreferredSupport'];
    final disabledSupport = json['disabledSupport'];
    final dataSupport = json['dataSupport'];
    final resolveSupport = json['resolveSupport'] != null
        ? CodeActionClientCapabilitiesResolveSupport.fromJson(
            json['resolveSupport'])
        : null;
    final honorsChangeAnnotations = json['honorsChangeAnnotations'];
    return CodeActionClientCapabilities(
        dynamicRegistration: dynamicRegistration,
        codeActionLiteralSupport: codeActionLiteralSupport,
        isPreferredSupport: isPreferredSupport,
        disabledSupport: disabledSupport,
        dataSupport: dataSupport,
        resolveSupport: resolveSupport,
        honorsChangeAnnotations: honorsChangeAnnotations);
  }

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

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

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

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

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

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

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

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

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode);
    hash = JenkinsSmiHash.combine(hash, codeActionLiteralSupport.hashCode);
    hash = JenkinsSmiHash.combine(hash, isPreferredSupport.hashCode);
    hash = JenkinsSmiHash.combine(hash, disabledSupport.hashCode);
    hash = JenkinsSmiHash.combine(hash, dataSupport.hashCode);
    hash = JenkinsSmiHash.combine(hash, resolveSupport.hashCode);
    hash = JenkinsSmiHash.combine(hash, honorsChangeAnnotations.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  CodeActionClientCapabilitiesCodeActionKind({@required this.valueSet}) {
    if (valueSet == null) {
      throw 'valueSet is required but was not provided';
    }
  }
  static CodeActionClientCapabilitiesCodeActionKind fromJson(
      Map<String, dynamic> json) {
    final valueSet = json['valueSet']
        ?.map((item) => item != null ? CodeActionKind.fromJson(item) : null)
        ?.cast<CodeActionKind>()
        ?.toList();
    return CodeActionClientCapabilitiesCodeActionKind(valueSet: valueSet);
  }

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['valueSet'] = valueSet?.map((item) => item.toJson())?.toList() ??
        (throw 'valueSet is required but was not set');
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(valueSet));
    return JenkinsSmiHash.finish(hash);
  }

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

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

  CodeActionClientCapabilitiesCodeActionLiteralSupport(
      {@required this.codeActionKind}) {
    if (codeActionKind == null) {
      throw 'codeActionKind is required but was not provided';
    }
  }
  static CodeActionClientCapabilitiesCodeActionLiteralSupport fromJson(
      Map<String, dynamic> json) {
    final codeActionKind = json['codeActionKind'] != null
        ? CodeActionClientCapabilitiesCodeActionKind.fromJson(
            json['codeActionKind'])
        : null;
    return CodeActionClientCapabilitiesCodeActionLiteralSupport(
        codeActionKind: codeActionKind);
  }

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['codeActionKind'] = codeActionKind?.toJson() ??
        (throw 'codeActionKind is required but was not set');
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, codeActionKind.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  CodeActionClientCapabilitiesResolveSupport({@required this.properties}) {
    if (properties == null) {
      throw 'properties is required but was not provided';
    }
  }
  static CodeActionClientCapabilitiesResolveSupport fromJson(
      Map<String, dynamic> json) {
    final properties =
        json['properties']?.map((item) => item)?.cast<String>()?.toList();
    return CodeActionClientCapabilitiesResolveSupport(properties: properties);
  }

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['properties'] =
        properties ?? (throw 'properties is required but was not set');
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(properties));
    return JenkinsSmiHash.finish(hash);
  }

  @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}) {
    if (diagnostics == null) {
      throw 'diagnostics is required but was not provided';
    }
  }
  static CodeActionContext fromJson(Map<String, dynamic> json) {
    final diagnostics = json['diagnostics']
        ?.map((item) => item != null ? Diagnostic.fromJson(item) : null)
        ?.cast<Diagnostic>()
        ?.toList();
    final only = json['only']
        ?.map((item) => item != null ? CodeActionKind.fromJson(item) : null)
        ?.cast<CodeActionKind>()
        ?.toList();
    return CodeActionContext(diagnostics: diagnostics, only: only);
  }

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

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['diagnostics'] =
        diagnostics?.map((item) => item.toJson())?.toList() ??
            (throw 'diagnostics is required but was not set');
    if (only != null) {
      __result['only'] = only.map((item) => item.toJson()).toList();
    }
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(diagnostics));
    hash = JenkinsSmiHash.combine(hash, lspHashCode(only));
    return JenkinsSmiHash.finish(hash);
  }

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

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

  CodeActionDisabled({@required this.reason}) {
    if (reason == null) {
      throw 'reason is required but was not provided';
    }
  }
  static CodeActionDisabled fromJson(Map<String, dynamic> json) {
    final reason = json['reason'];
    return CodeActionDisabled(reason: reason);
  }

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['reason'] = reason ?? (throw 'reason is required but was not set');
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('reason');
      try {
        if (!obj.containsKey('reason')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['reason'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, reason.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  final String _value;

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

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

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

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

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

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

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

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

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

  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

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

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

  CodeActionOptions(
      {this.codeActionKinds, this.resolveProvider, this.workDoneProgress});
  static CodeActionOptions fromJson(Map<String, dynamic> json) {
    if (CodeActionRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return CodeActionRegistrationOptions.fromJson(json);
    }
    final codeActionKinds = json['codeActionKinds']
        ?.map((item) => item != null ? CodeActionKind.fromJson(item) : null)
        ?.cast<CodeActionKind>()
        ?.toList();
    final resolveProvider = json['resolveProvider'];
    final workDoneProgress = json['workDoneProgress'];
    return CodeActionOptions(
        codeActionKinds: codeActionKinds,
        resolveProvider: resolveProvider,
        workDoneProgress: workDoneProgress);
  }

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

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    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, dynamic>) {
      reporter.push('codeActionKinds');
      try {
        if (obj['codeActionKinds'] != null &&
            !((obj['codeActionKinds'] is List &&
                (obj['codeActionKinds'].every(
                    (item) => CodeActionKind.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<CodeActionKind>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('resolveProvider');
      try {
        if (obj['resolveProvider'] != null &&
            !(obj['resolveProvider'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        if (obj['workDoneProgress'] != null &&
            !(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(codeActionKinds));
    hash = JenkinsSmiHash.combine(hash, resolveProvider.hashCode);
    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

/// Params for the CodeActionRequest
class CodeActionParams
    implements WorkDoneProgressParams, PartialResultParams, ToJsonable {
  static const jsonHandler =
      LspJsonHandler(CodeActionParams.canParse, CodeActionParams.fromJson);

  CodeActionParams(
      {@required this.textDocument,
      @required this.range,
      @required this.context,
      this.workDoneToken,
      this.partialResultToken}) {
    if (textDocument == null) {
      throw 'textDocument is required but was not provided';
    }
    if (range == null) {
      throw 'range is required but was not provided';
    }
    if (context == null) {
      throw 'context is required but was not provided';
    }
  }
  static CodeActionParams fromJson(Map<String, dynamic> json) {
    final textDocument = json['textDocument'] != null
        ? TextDocumentIdentifier.fromJson(json['textDocument'])
        : null;
    final range = json['range'] != null ? Range.fromJson(json['range']) : null;
    final context = json['context'] != null
        ? CodeActionContext.fromJson(json['context'])
        : null;
    final workDoneToken = json['workDoneToken'] is num
        ? Either2<num, String>.t1(json['workDoneToken'])
        : (json['workDoneToken'] is String
            ? Either2<num, String>.t2(json['workDoneToken'])
            : (json['workDoneToken'] == null
                ? null
                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
    final partialResultToken = json['partialResultToken'] is num
        ? Either2<num, String>.t1(json['partialResultToken'])
        : (json['partialResultToken'] is String
            ? Either2<num, String>.t2(json['partialResultToken'])
            : (json['partialResultToken'] == null
                ? null
                : (throw '''${json['partialResultToken']} was not one of (num, String)''')));
    return CodeActionParams(
        textDocument: textDocument,
        range: range,
        context: context,
        workDoneToken: workDoneToken,
        partialResultToken: partialResultToken);
  }

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

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

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

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

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['textDocument'] = textDocument?.toJson() ??
        (throw 'textDocument is required but was not set');
    __result['range'] =
        range?.toJson() ?? (throw 'range is required but was not set');
    __result['context'] =
        context?.toJson() ?? (throw 'context is required but was not set');
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    if (partialResultToken != null) {
      __result['partialResultToken'] = partialResultToken;
    }
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, textDocument.hashCode);
    hash = JenkinsSmiHash.combine(hash, range.hashCode);
    hash = JenkinsSmiHash.combine(hash, context.hashCode);
    hash = JenkinsSmiHash.combine(hash, workDoneToken.hashCode);
    hash = JenkinsSmiHash.combine(hash, partialResultToken.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  CodeActionRegistrationOptions(
      {this.documentSelector,
      this.codeActionKinds,
      this.resolveProvider,
      this.workDoneProgress});
  static CodeActionRegistrationOptions fromJson(Map<String, dynamic> json) {
    final documentSelector = json['documentSelector']
        ?.map((item) => item != null ? DocumentFilter.fromJson(item) : null)
        ?.cast<DocumentFilter>()
        ?.toList();
    final codeActionKinds = json['codeActionKinds']
        ?.map((item) => item != null ? CodeActionKind.fromJson(item) : null)
        ?.cast<CodeActionKind>()
        ?.toList();
    final resolveProvider = json['resolveProvider'];
    final workDoneProgress = json['workDoneProgress'];
    return CodeActionRegistrationOptions(
        documentSelector: documentSelector,
        codeActionKinds: codeActionKinds,
        resolveProvider: resolveProvider,
        workDoneProgress: workDoneProgress);
  }

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

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

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

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

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(documentSelector));
    hash = JenkinsSmiHash.combine(hash, lspHashCode(codeActionKinds));
    hash = JenkinsSmiHash.combine(hash, resolveProvider.hashCode);
    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  CodeDescription({@required this.href}) {
    if (href == null) {
      throw 'href is required but was not provided';
    }
  }
  static CodeDescription fromJson(Map<String, dynamic> json) {
    final href = json['href'];
    return CodeDescription(href: href);
  }

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['href'] = href ?? (throw 'href is required but was not set');
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('href');
      try {
        if (!obj.containsKey('href')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['href'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, href.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  CodeLens({@required this.range, this.command, this.data}) {
    if (range == null) {
      throw 'range is required but was not provided';
    }
  }
  static CodeLens fromJson(Map<String, dynamic> json) {
    final range = json['range'] != null ? Range.fromJson(json['range']) : null;
    final command =
        json['command'] != null ? Command.fromJson(json['command']) : null;
    final data = json['data'];
    return CodeLens(range: range, command: command, data: data);
  }

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

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

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['range'] =
        range?.toJson() ?? (throw 'range is required but was not set');
    if (command != null) {
      __result['command'] = command.toJson();
    }
    if (data != null) {
      __result['data'] = data;
    }
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, range.hashCode);
    hash = JenkinsSmiHash.combine(hash, command.hashCode);
    hash = JenkinsSmiHash.combine(hash, data.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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, dynamic> json) {
    final dynamicRegistration = json['dynamicRegistration'];
    return CodeLensClientCapabilities(dynamicRegistration: dynamicRegistration);
  }

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (dynamicRegistration != null) {
      __result['dynamicRegistration'] = dynamicRegistration;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('dynamicRegistration');
      try {
        if (obj['dynamicRegistration'] != null &&
            !(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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, dynamic> json) {
    if (CodeLensRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return CodeLensRegistrationOptions.fromJson(json);
    }
    final resolveProvider = json['resolveProvider'];
    final workDoneProgress = json['workDoneProgress'];
    return CodeLensOptions(
        resolveProvider: resolveProvider, workDoneProgress: workDoneProgress);
  }

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    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, dynamic>) {
      reporter.push('resolveProvider');
      try {
        if (obj['resolveProvider'] != null &&
            !(obj['resolveProvider'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        if (obj['workDoneProgress'] != null &&
            !(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, resolveProvider.hashCode);
    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  CodeLensParams(
      {@required this.textDocument,
      this.workDoneToken,
      this.partialResultToken}) {
    if (textDocument == null) {
      throw 'textDocument is required but was not provided';
    }
  }
  static CodeLensParams fromJson(Map<String, dynamic> json) {
    final textDocument = json['textDocument'] != null
        ? TextDocumentIdentifier.fromJson(json['textDocument'])
        : null;
    final workDoneToken = json['workDoneToken'] is num
        ? Either2<num, String>.t1(json['workDoneToken'])
        : (json['workDoneToken'] is String
            ? Either2<num, String>.t2(json['workDoneToken'])
            : (json['workDoneToken'] == null
                ? null
                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
    final partialResultToken = json['partialResultToken'] is num
        ? Either2<num, String>.t1(json['partialResultToken'])
        : (json['partialResultToken'] is String
            ? Either2<num, String>.t2(json['partialResultToken'])
            : (json['partialResultToken'] == null
                ? null
                : (throw '''${json['partialResultToken']} was not one of (num, String)''')));
    return CodeLensParams(
        textDocument: textDocument,
        workDoneToken: workDoneToken,
        partialResultToken: partialResultToken);
  }

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

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

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['textDocument'] = textDocument?.toJson() ??
        (throw 'textDocument is required but was not set');
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    if (partialResultToken != null) {
      __result['partialResultToken'] = partialResultToken;
    }
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, textDocument.hashCode);
    hash = JenkinsSmiHash.combine(hash, workDoneToken.hashCode);
    hash = JenkinsSmiHash.combine(hash, partialResultToken.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  CodeLensRegistrationOptions(
      {this.documentSelector, this.resolveProvider, this.workDoneProgress});
  static CodeLensRegistrationOptions fromJson(Map<String, dynamic> json) {
    final documentSelector = json['documentSelector']
        ?.map((item) => item != null ? DocumentFilter.fromJson(item) : null)
        ?.cast<DocumentFilter>()
        ?.toList();
    final resolveProvider = json['resolveProvider'];
    final workDoneProgress = json['workDoneProgress'];
    return CodeLensRegistrationOptions(
        documentSelector: documentSelector,
        resolveProvider: resolveProvider,
        workDoneProgress: workDoneProgress);
  }

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

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __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, dynamic>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['documentSelector'] != null &&
            !((obj['documentSelector'] is List &&
                (obj['documentSelector'].every(
                    (item) => DocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<DocumentFilter>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('resolveProvider');
      try {
        if (obj['resolveProvider'] != null &&
            !(obj['resolveProvider'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        if (obj['workDoneProgress'] != null &&
            !(obj['workDoneProgress'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type CodeLensRegistrationOptions');
      return false;
    }
  }

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(documentSelector));
    hash = JenkinsSmiHash.combine(hash, resolveProvider.hashCode);
    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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, dynamic> json) {
    final refreshSupport = json['refreshSupport'];
    return CodeLensWorkspaceClientCapabilities(refreshSupport: refreshSupport);
  }

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (refreshSupport != null) {
      __result['refreshSupport'] = refreshSupport;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('refreshSupport');
      try {
        if (obj['refreshSupport'] != null && !(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, refreshSupport.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  Color(
      {@required this.red,
      @required this.green,
      @required this.blue,
      @required this.alpha}) {
    if (red == null) {
      throw 'red is required but was not provided';
    }
    if (green == null) {
      throw 'green is required but was not provided';
    }
    if (blue == null) {
      throw 'blue is required but was not provided';
    }
    if (alpha == null) {
      throw 'alpha is required but was not provided';
    }
  }
  static Color fromJson(Map<String, dynamic> json) {
    final red = json['red'];
    final green = json['green'];
    final blue = json['blue'];
    final alpha = json['alpha'];
    return Color(red: red, green: green, blue: blue, alpha: alpha);
  }

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

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

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

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['red'] = red ?? (throw 'red is required but was not set');
    __result['green'] = green ?? (throw 'green is required but was not set');
    __result['blue'] = blue ?? (throw 'blue is required but was not set');
    __result['alpha'] = alpha ?? (throw 'alpha is required but was not set');
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, red.hashCode);
    hash = JenkinsSmiHash.combine(hash, green.hashCode);
    hash = JenkinsSmiHash.combine(hash, blue.hashCode);
    hash = JenkinsSmiHash.combine(hash, alpha.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  ColorInformation({@required this.range, @required this.color}) {
    if (range == null) {
      throw 'range is required but was not provided';
    }
    if (color == null) {
      throw 'color is required but was not provided';
    }
  }
  static ColorInformation fromJson(Map<String, dynamic> json) {
    final range = json['range'] != null ? Range.fromJson(json['range']) : null;
    final color = json['color'] != null ? Color.fromJson(json['color']) : null;
    return ColorInformation(range: range, color: color);
  }

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

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['range'] =
        range?.toJson() ?? (throw 'range is required but was not set');
    __result['color'] =
        color?.toJson() ?? (throw 'color is required but was not set');
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, range.hashCode);
    hash = JenkinsSmiHash.combine(hash, color.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  ColorPresentation(
      {@required this.label, this.textEdit, this.additionalTextEdits}) {
    if (label == null) {
      throw 'label is required but was not provided';
    }
  }
  static ColorPresentation fromJson(Map<String, dynamic> json) {
    final label = json['label'];
    final textEdit =
        json['textEdit'] != null ? TextEdit.fromJson(json['textEdit']) : null;
    final additionalTextEdits = json['additionalTextEdits']
        ?.map((item) => item != null ? TextEdit.fromJson(item) : null)
        ?.cast<TextEdit>()
        ?.toList();
    return ColorPresentation(
        label: label,
        textEdit: textEdit,
        additionalTextEdits: additionalTextEdits);
  }

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

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

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['label'] = label ?? (throw 'label is required but was not set');
    if (textEdit != null) {
      __result['textEdit'] = textEdit.toJson();
    }
    if (additionalTextEdits != null) {
      __result['additionalTextEdits'] =
          additionalTextEdits.map((item) => item.toJson()).toList();
    }
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, label.hashCode);
    hash = JenkinsSmiHash.combine(hash, textEdit.hashCode);
    hash = JenkinsSmiHash.combine(hash, lspHashCode(additionalTextEdits));
    return JenkinsSmiHash.finish(hash);
  }

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

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

  ColorPresentationParams(
      {@required this.textDocument,
      @required this.color,
      @required this.range,
      this.workDoneToken,
      this.partialResultToken}) {
    if (textDocument == null) {
      throw 'textDocument is required but was not provided';
    }
    if (color == null) {
      throw 'color is required but was not provided';
    }
    if (range == null) {
      throw 'range is required but was not provided';
    }
  }
  static ColorPresentationParams fromJson(Map<String, dynamic> json) {
    final textDocument = json['textDocument'] != null
        ? TextDocumentIdentifier.fromJson(json['textDocument'])
        : null;
    final color = json['color'] != null ? Color.fromJson(json['color']) : null;
    final range = json['range'] != null ? Range.fromJson(json['range']) : null;
    final workDoneToken = json['workDoneToken'] is num
        ? Either2<num, String>.t1(json['workDoneToken'])
        : (json['workDoneToken'] is String
            ? Either2<num, String>.t2(json['workDoneToken'])
            : (json['workDoneToken'] == null
                ? null
                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
    final partialResultToken = json['partialResultToken'] is num
        ? Either2<num, String>.t1(json['partialResultToken'])
        : (json['partialResultToken'] is String
            ? Either2<num, String>.t2(json['partialResultToken'])
            : (json['partialResultToken'] == null
                ? null
                : (throw '''${json['partialResultToken']} was not one of (num, String)''')));
    return ColorPresentationParams(
        textDocument: textDocument,
        color: color,
        range: range,
        workDoneToken: workDoneToken,
        partialResultToken: partialResultToken);
  }

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

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

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

  /// The text document.
  final TextDocumentIdentifier textDocument;

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['textDocument'] = textDocument?.toJson() ??
        (throw 'textDocument is required but was not set');
    __result['color'] =
        color?.toJson() ?? (throw 'color is required but was not set');
    __result['range'] =
        range?.toJson() ?? (throw 'range is required but was not set');
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    if (partialResultToken != null) {
      __result['partialResultToken'] = partialResultToken;
    }
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, textDocument.hashCode);
    hash = JenkinsSmiHash.combine(hash, color.hashCode);
    hash = JenkinsSmiHash.combine(hash, range.hashCode);
    hash = JenkinsSmiHash.combine(hash, workDoneToken.hashCode);
    hash = JenkinsSmiHash.combine(hash, partialResultToken.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  Command({@required this.title, @required this.command, this.arguments}) {
    if (title == null) {
      throw 'title is required but was not provided';
    }
    if (command == null) {
      throw 'command is required but was not provided';
    }
  }
  static Command fromJson(Map<String, dynamic> json) {
    final title = json['title'];
    final command = json['command'];
    final arguments =
        json['arguments']?.map((item) => item)?.cast<dynamic>()?.toList();
    return Command(title: title, command: command, arguments: arguments);
  }

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

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

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['title'] = title ?? (throw 'title is required but was not set');
    __result['command'] =
        command ?? (throw 'command is required but was not set');
    if (arguments != null) {
      __result['arguments'] = arguments;
    }
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, title.hashCode);
    hash = JenkinsSmiHash.combine(hash, command.hashCode);
    hash = JenkinsSmiHash.combine(hash, lspHashCode(arguments));
    return JenkinsSmiHash.finish(hash);
  }

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

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

  CompletionClientCapabilities(
      {this.dynamicRegistration,
      this.completionItem,
      this.completionItemKind,
      this.contextSupport});
  static CompletionClientCapabilities fromJson(Map<String, dynamic> json) {
    final dynamicRegistration = json['dynamicRegistration'];
    final completionItem = json['completionItem'] != null
        ? CompletionClientCapabilitiesCompletionItem.fromJson(
            json['completionItem'])
        : null;
    final completionItemKind = json['completionItemKind'] != null
        ? CompletionClientCapabilitiesCompletionItemKind.fromJson(
            json['completionItemKind'])
        : null;
    final contextSupport = json['contextSupport'];
    return CompletionClientCapabilities(
        dynamicRegistration: dynamicRegistration,
        completionItem: completionItem,
        completionItemKind: completionItemKind,
        contextSupport: contextSupport);
  }

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

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

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (dynamicRegistration != null) {
      __result['dynamicRegistration'] = dynamicRegistration;
    }
    if (completionItem != null) {
      __result['completionItem'] = completionItem.toJson();
    }
    if (completionItemKind != null) {
      __result['completionItemKind'] = completionItemKind.toJson();
    }
    if (contextSupport != null) {
      __result['contextSupport'] = contextSupport;
    }
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode);
    hash = JenkinsSmiHash.combine(hash, completionItem.hashCode);
    hash = JenkinsSmiHash.combine(hash, completionItemKind.hashCode);
    hash = JenkinsSmiHash.combine(hash, contextSupport.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  CompletionClientCapabilitiesCompletionItem(
      {this.snippetSupport,
      this.commitCharactersSupport,
      this.documentationFormat,
      this.deprecatedSupport,
      this.preselectSupport,
      this.tagSupport,
      this.insertReplaceSupport,
      this.resolveSupport,
      this.insertTextModeSupport});
  static CompletionClientCapabilitiesCompletionItem fromJson(
      Map<String, dynamic> json) {
    final snippetSupport = json['snippetSupport'];
    final commitCharactersSupport = json['commitCharactersSupport'];
    final documentationFormat = json['documentationFormat']
        ?.map((item) => item != null ? MarkupKind.fromJson(item) : null)
        ?.cast<MarkupKind>()
        ?.toList();
    final deprecatedSupport = json['deprecatedSupport'];
    final preselectSupport = json['preselectSupport'];
    final tagSupport = json['tagSupport'] != null
        ? CompletionClientCapabilitiesTagSupport.fromJson(json['tagSupport'])
        : null;
    final insertReplaceSupport = json['insertReplaceSupport'];
    final resolveSupport = json['resolveSupport'] != null
        ? CompletionClientCapabilitiesResolveSupport.fromJson(
            json['resolveSupport'])
        : null;
    final insertTextModeSupport = json['insertTextModeSupport'] != null
        ? CompletionClientCapabilitiesInsertTextModeSupport.fromJson(
            json['insertTextModeSupport'])
        : null;
    return CompletionClientCapabilitiesCompletionItem(
        snippetSupport: snippetSupport,
        commitCharactersSupport: commitCharactersSupport,
        documentationFormat: documentationFormat,
        deprecatedSupport: deprecatedSupport,
        preselectSupport: preselectSupport,
        tagSupport: tagSupport,
        insertReplaceSupport: insertReplaceSupport,
        resolveSupport: resolveSupport,
        insertTextModeSupport: insertTextModeSupport);
  }

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

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

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

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

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

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

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

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

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

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

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, snippetSupport.hashCode);
    hash = JenkinsSmiHash.combine(hash, commitCharactersSupport.hashCode);
    hash = JenkinsSmiHash.combine(hash, lspHashCode(documentationFormat));
    hash = JenkinsSmiHash.combine(hash, deprecatedSupport.hashCode);
    hash = JenkinsSmiHash.combine(hash, preselectSupport.hashCode);
    hash = JenkinsSmiHash.combine(hash, tagSupport.hashCode);
    hash = JenkinsSmiHash.combine(hash, insertReplaceSupport.hashCode);
    hash = JenkinsSmiHash.combine(hash, resolveSupport.hashCode);
    hash = JenkinsSmiHash.combine(hash, insertTextModeSupport.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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, dynamic> json) {
    final valueSet = json['valueSet']
        ?.map((item) => item != null ? CompletionItemKind.fromJson(item) : null)
        ?.cast<CompletionItemKind>()
        ?.toList();
    return CompletionClientCapabilitiesCompletionItemKind(valueSet: valueSet);
  }

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    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, dynamic>) {
      reporter.push('valueSet');
      try {
        if (obj['valueSet'] != null &&
            !((obj['valueSet'] is List &&
                (obj['valueSet'].every(
                    (item) => CompletionItemKind.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<CompletionItemKind>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type CompletionClientCapabilitiesCompletionItemKind');
      return false;
    }
  }

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(valueSet));
    return JenkinsSmiHash.finish(hash);
  }

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

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

  CompletionClientCapabilitiesInsertTextModeSupport({@required this.valueSet}) {
    if (valueSet == null) {
      throw 'valueSet is required but was not provided';
    }
  }
  static CompletionClientCapabilitiesInsertTextModeSupport fromJson(
      Map<String, dynamic> json) {
    final valueSet = json['valueSet']
        ?.map((item) => item != null ? InsertTextMode.fromJson(item) : null)
        ?.cast<InsertTextMode>()
        ?.toList();
    return CompletionClientCapabilitiesInsertTextModeSupport(
        valueSet: valueSet);
  }

  final List<InsertTextMode> valueSet;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['valueSet'] = valueSet?.map((item) => item.toJson())?.toList() ??
        (throw 'valueSet is required but was not set');
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(valueSet));
    return JenkinsSmiHash.finish(hash);
  }

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

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

  CompletionClientCapabilitiesResolveSupport({@required this.properties}) {
    if (properties == null) {
      throw 'properties is required but was not provided';
    }
  }
  static CompletionClientCapabilitiesResolveSupport fromJson(
      Map<String, dynamic> json) {
    final properties =
        json['properties']?.map((item) => item)?.cast<String>()?.toList();
    return CompletionClientCapabilitiesResolveSupport(properties: properties);
  }

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['properties'] =
        properties ?? (throw 'properties is required but was not set');
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(properties));
    return JenkinsSmiHash.finish(hash);
  }

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

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

  CompletionClientCapabilitiesTagSupport({@required this.valueSet}) {
    if (valueSet == null) {
      throw 'valueSet is required but was not provided';
    }
  }
  static CompletionClientCapabilitiesTagSupport fromJson(
      Map<String, dynamic> json) {
    final valueSet = json['valueSet']
        ?.map((item) => item != null ? CompletionItemTag.fromJson(item) : null)
        ?.cast<CompletionItemTag>()
        ?.toList();
    return CompletionClientCapabilitiesTagSupport(valueSet: valueSet);
  }

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['valueSet'] = valueSet?.map((item) => item.toJson())?.toList() ??
        (throw 'valueSet is required but was not set');
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(valueSet));
    return JenkinsSmiHash.finish(hash);
  }

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

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

  CompletionContext({@required this.triggerKind, this.triggerCharacter}) {
    if (triggerKind == null) {
      throw 'triggerKind is required but was not provided';
    }
  }
  static CompletionContext fromJson(Map<String, dynamic> json) {
    final triggerKind = json['triggerKind'] != null
        ? CompletionTriggerKind.fromJson(json['triggerKind'])
        : null;
    final triggerCharacter = json['triggerCharacter'];
    return CompletionContext(
        triggerKind: triggerKind, triggerCharacter: triggerCharacter);
  }

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

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['triggerKind'] = triggerKind?.toJson() ??
        (throw 'triggerKind is required but was not set');
    if (triggerCharacter != null) {
      __result['triggerCharacter'] = triggerCharacter;
    }
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, triggerKind.hashCode);
    hash = JenkinsSmiHash.combine(hash, triggerCharacter.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  CompletionItem(
      {@required this.label,
      this.kind,
      this.tags,
      this.detail,
      this.documentation,
      this.deprecated,
      this.preselect,
      this.sortText,
      this.filterText,
      this.insertText,
      this.insertTextFormat,
      this.insertTextMode,
      this.textEdit,
      this.additionalTextEdits,
      this.commitCharacters,
      this.command,
      this.data}) {
    if (label == null) {
      throw 'label is required but was not provided';
    }
  }
  static CompletionItem fromJson(Map<String, dynamic> json) {
    final label = json['label'];
    final kind =
        json['kind'] != null ? CompletionItemKind.fromJson(json['kind']) : null;
    final tags = json['tags']
        ?.map((item) => item != null ? CompletionItemTag.fromJson(item) : null)
        ?.cast<CompletionItemTag>()
        ?.toList();
    final detail = json['detail'];
    final documentation = json['documentation'] is String
        ? Either2<String, MarkupContent>.t1(json['documentation'])
        : (MarkupContent.canParse(json['documentation'], nullLspJsonReporter)
            ? Either2<String, MarkupContent>.t2(json['documentation'] != null
                ? MarkupContent.fromJson(json['documentation'])
                : null)
            : (json['documentation'] == null
                ? null
                : (throw '''${json['documentation']} was not one of (String, MarkupContent)''')));
    final deprecated = json['deprecated'];
    final preselect = json['preselect'];
    final sortText = json['sortText'];
    final filterText = json['filterText'];
    final insertText = json['insertText'];
    final insertTextFormat = json['insertTextFormat'] != null
        ? InsertTextFormat.fromJson(json['insertTextFormat'])
        : null;
    final insertTextMode = json['insertTextMode'] != null
        ? InsertTextMode.fromJson(json['insertTextMode'])
        : null;
    final textEdit = TextEdit.canParse(json['textEdit'], nullLspJsonReporter)
        ? Either2<TextEdit, InsertReplaceEdit>.t1(json['textEdit'] != null
            ? TextEdit.fromJson(json['textEdit'])
            : null)
        : (InsertReplaceEdit.canParse(json['textEdit'], nullLspJsonReporter)
            ? Either2<TextEdit, InsertReplaceEdit>.t2(json['textEdit'] != null
                ? InsertReplaceEdit.fromJson(json['textEdit'])
                : null)
            : (json['textEdit'] == null
                ? null
                : (throw '''${json['textEdit']} was not one of (TextEdit, InsertReplaceEdit)''')));
    final additionalTextEdits = json['additionalTextEdits']
        ?.map((item) => item != null ? TextEdit.fromJson(item) : null)
        ?.cast<TextEdit>()
        ?.toList();
    final commitCharacters =
        json['commitCharacters']?.map((item) => item)?.cast<String>()?.toList();
    final command =
        json['command'] != null ? Command.fromJson(json['command']) : null;
    final data = json['data'] != null
        ? CompletionItemResolutionInfo.fromJson(json['data'])
        : null;
    return CompletionItem(
        label: label,
        kind: kind,
        tags: tags,
        detail: detail,
        documentation: documentation,
        deprecated: deprecated,
        preselect: preselect,
        sortText: sortText,
        filterText: filterText,
        insertText: insertText,
        insertTextFormat: insertTextFormat,
        insertTextMode: insertTextMode,
        textEdit: textEdit,
        additionalTextEdits: additionalTextEdits,
        commitCharacters: commitCharacters,
        command: command,
        data: data);
  }

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

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

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

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

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

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

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

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

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

  /// The format of the insert text. The format applies to both the `insertText`
  /// property and the `newText` property of a provided `textEdit`. If omitted
  /// defaults to `InsertTextFormat.PlainText`.
  final InsertTextFormat insertTextFormat;

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

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

  /// The label of this completion item. By default also the text that is
  /// inserted when selecting this completion.
  final String label;

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

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

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

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['label'] = label ?? (throw 'label is required but was not set');
    if (kind != null) {
      __result['kind'] = kind.toJson();
    }
    if (tags != null) {
      __result['tags'] = tags.map((item) => item.toJson()).toList();
    }
    if (detail != null) {
      __result['detail'] = detail;
    }
    if (documentation != null) {
      __result['documentation'] = documentation;
    }
    if (deprecated != null) {
      __result['deprecated'] = deprecated;
    }
    if (preselect != null) {
      __result['preselect'] = preselect;
    }
    if (sortText != null) {
      __result['sortText'] = sortText;
    }
    if (filterText != null) {
      __result['filterText'] = filterText;
    }
    if (insertText != null) {
      __result['insertText'] = insertText;
    }
    if (insertTextFormat != null) {
      __result['insertTextFormat'] = insertTextFormat.toJson();
    }
    if (insertTextMode != null) {
      __result['insertTextMode'] = insertTextMode.toJson();
    }
    if (textEdit != null) {
      __result['textEdit'] = textEdit;
    }
    if (additionalTextEdits != null) {
      __result['additionalTextEdits'] =
          additionalTextEdits.map((item) => item.toJson()).toList();
    }
    if (commitCharacters != null) {
      __result['commitCharacters'] = commitCharacters;
    }
    if (command != null) {
      __result['command'] = command.toJson();
    }
    if (data != null) {
      __result['data'] = data.toJson();
    }
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, label.hashCode);
    hash = JenkinsSmiHash.combine(hash, kind.hashCode);
    hash = JenkinsSmiHash.combine(hash, lspHashCode(tags));
    hash = JenkinsSmiHash.combine(hash, detail.hashCode);
    hash = JenkinsSmiHash.combine(hash, documentation.hashCode);
    hash = JenkinsSmiHash.combine(hash, deprecated.hashCode);
    hash = JenkinsSmiHash.combine(hash, preselect.hashCode);
    hash = JenkinsSmiHash.combine(hash, sortText.hashCode);
    hash = JenkinsSmiHash.combine(hash, filterText.hashCode);
    hash = JenkinsSmiHash.combine(hash, insertText.hashCode);
    hash = JenkinsSmiHash.combine(hash, insertTextFormat.hashCode);
    hash = JenkinsSmiHash.combine(hash, insertTextMode.hashCode);
    hash = JenkinsSmiHash.combine(hash, textEdit.hashCode);
    hash = JenkinsSmiHash.combine(hash, lspHashCode(additionalTextEdits));
    hash = JenkinsSmiHash.combine(hash, lspHashCode(commitCharacters));
    hash = JenkinsSmiHash.combine(hash, command.hashCode);
    hash = JenkinsSmiHash.combine(hash, data.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  final num _value;

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

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

  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

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

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

  final num _value;

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

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

  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

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

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

  CompletionList({@required this.isIncomplete, @required this.items}) {
    if (isIncomplete == null) {
      throw 'isIncomplete is required but was not provided';
    }
    if (items == null) {
      throw 'items is required but was not provided';
    }
  }
  static CompletionList fromJson(Map<String, dynamic> json) {
    final isIncomplete = json['isIncomplete'];
    final items = json['items']
        ?.map((item) => item != null ? CompletionItem.fromJson(item) : null)
        ?.cast<CompletionItem>()
        ?.toList();
    return CompletionList(isIncomplete: isIncomplete, items: items);
  }

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

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['isIncomplete'] =
        isIncomplete ?? (throw 'isIncomplete is required but was not set');
    __result['items'] = items?.map((item) => item.toJson())?.toList() ??
        (throw 'items is required but was not set');
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, isIncomplete.hashCode);
    hash = JenkinsSmiHash.combine(hash, lspHashCode(items));
    return JenkinsSmiHash.finish(hash);
  }

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

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

  CompletionOptions(
      {this.triggerCharacters,
      this.allCommitCharacters,
      this.resolveProvider,
      this.workDoneProgress});
  static CompletionOptions fromJson(Map<String, dynamic> json) {
    if (CompletionRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return CompletionRegistrationOptions.fromJson(json);
    }
    final triggerCharacters = json['triggerCharacters']
        ?.map((item) => item)
        ?.cast<String>()
        ?.toList();
    final allCommitCharacters = json['allCommitCharacters']
        ?.map((item) => item)
        ?.cast<String>()
        ?.toList();
    final resolveProvider = json['resolveProvider'];
    final workDoneProgress = json['workDoneProgress'];
    return CompletionOptions(
        triggerCharacters: triggerCharacters,
        allCommitCharacters: allCommitCharacters,
        resolveProvider: resolveProvider,
        workDoneProgress: workDoneProgress);
  }

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

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

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (triggerCharacters != null) {
      __result['triggerCharacters'] = triggerCharacters;
    }
    if (allCommitCharacters != null) {
      __result['allCommitCharacters'] = allCommitCharacters;
    }
    if (resolveProvider != null) {
      __result['resolveProvider'] = resolveProvider;
    }
    if (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(triggerCharacters));
    hash = JenkinsSmiHash.combine(hash, lspHashCode(allCommitCharacters));
    hash = JenkinsSmiHash.combine(hash, resolveProvider.hashCode);
    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  CompletionParams(
      {this.context,
      @required this.textDocument,
      @required this.position,
      this.workDoneToken,
      this.partialResultToken}) {
    if (textDocument == null) {
      throw 'textDocument is required but was not provided';
    }
    if (position == null) {
      throw 'position is required but was not provided';
    }
  }
  static CompletionParams fromJson(Map<String, dynamic> json) {
    final context = json['context'] != null
        ? CompletionContext.fromJson(json['context'])
        : null;
    final textDocument = json['textDocument'] != null
        ? TextDocumentIdentifier.fromJson(json['textDocument'])
        : null;
    final position =
        json['position'] != null ? Position.fromJson(json['position']) : null;
    final workDoneToken = json['workDoneToken'] is num
        ? Either2<num, String>.t1(json['workDoneToken'])
        : (json['workDoneToken'] is String
            ? Either2<num, String>.t2(json['workDoneToken'])
            : (json['workDoneToken'] == null
                ? null
                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
    final partialResultToken = json['partialResultToken'] is num
        ? Either2<num, String>.t1(json['partialResultToken'])
        : (json['partialResultToken'] is String
            ? Either2<num, String>.t2(json['partialResultToken'])
            : (json['partialResultToken'] == null
                ? null
                : (throw '''${json['partialResultToken']} was not one of (num, String)''')));
    return CompletionParams(
        context: context,
        textDocument: textDocument,
        position: position,
        workDoneToken: workDoneToken,
        partialResultToken: partialResultToken);
  }

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

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

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

  /// The text document.
  final TextDocumentIdentifier textDocument;

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (context != null) {
      __result['context'] = context.toJson();
    }
    __result['textDocument'] = textDocument?.toJson() ??
        (throw 'textDocument is required but was not set');
    __result['position'] =
        position?.toJson() ?? (throw 'position is required but was not set');
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    if (partialResultToken != null) {
      __result['partialResultToken'] = partialResultToken;
    }
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, context.hashCode);
    hash = JenkinsSmiHash.combine(hash, textDocument.hashCode);
    hash = JenkinsSmiHash.combine(hash, position.hashCode);
    hash = JenkinsSmiHash.combine(hash, workDoneToken.hashCode);
    hash = JenkinsSmiHash.combine(hash, partialResultToken.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  CompletionRegistrationOptions(
      {this.documentSelector,
      this.triggerCharacters,
      this.allCommitCharacters,
      this.resolveProvider,
      this.workDoneProgress});
  static CompletionRegistrationOptions fromJson(Map<String, dynamic> json) {
    final documentSelector = json['documentSelector']
        ?.map((item) => item != null ? DocumentFilter.fromJson(item) : null)
        ?.cast<DocumentFilter>()
        ?.toList();
    final triggerCharacters = json['triggerCharacters']
        ?.map((item) => item)
        ?.cast<String>()
        ?.toList();
    final allCommitCharacters = json['allCommitCharacters']
        ?.map((item) => item)
        ?.cast<String>()
        ?.toList();
    final resolveProvider = json['resolveProvider'];
    final workDoneProgress = json['workDoneProgress'];
    return CompletionRegistrationOptions(
        documentSelector: documentSelector,
        triggerCharacters: triggerCharacters,
        allCommitCharacters: allCommitCharacters,
        resolveProvider: resolveProvider,
        workDoneProgress: workDoneProgress);
  }

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

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

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

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['documentSelector'] = documentSelector;
    if (triggerCharacters != null) {
      __result['triggerCharacters'] = triggerCharacters;
    }
    if (allCommitCharacters != null) {
      __result['allCommitCharacters'] = allCommitCharacters;
    }
    if (resolveProvider != null) {
      __result['resolveProvider'] = resolveProvider;
    }
    if (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(documentSelector));
    hash = JenkinsSmiHash.combine(hash, lspHashCode(triggerCharacters));
    hash = JenkinsSmiHash.combine(hash, lspHashCode(allCommitCharacters));
    hash = JenkinsSmiHash.combine(hash, resolveProvider.hashCode);
    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  final num _value;

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

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

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

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

  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

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

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

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

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

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    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, dynamic>) {
      reporter.push('scopeUri');
      try {
        if (obj['scopeUri'] != null && !(obj['scopeUri'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('section');
      try {
        if (obj['section'] != null && !(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, scopeUri.hashCode);
    hash = JenkinsSmiHash.combine(hash, section.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  ConfigurationParams({@required this.items}) {
    if (items == null) {
      throw 'items is required but was not provided';
    }
  }
  static ConfigurationParams fromJson(Map<String, dynamic> json) {
    final items = json['items']
        ?.map((item) => item != null ? ConfigurationItem.fromJson(item) : null)
        ?.cast<ConfigurationItem>()
        ?.toList();
    return ConfigurationParams(items: items);
  }

  final List<ConfigurationItem> items;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['items'] = items?.map((item) => item.toJson())?.toList() ??
        (throw 'items is required but was not set');
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(items));
    return JenkinsSmiHash.finish(hash);
  }

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

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

  CreateFile(
      {this.kind = 'create',
      @required this.uri,
      this.options,
      this.annotationId}) {
    if (kind != 'create') {
      throw 'kind may only be the literal \'create\'';
    }
    if (uri == null) {
      throw 'uri is required but was not provided';
    }
  }
  static CreateFile fromJson(Map<String, dynamic> json) {
    final kind = json['kind'];
    final uri = json['uri'];
    final options = json['options'] != null
        ? CreateFileOptions.fromJson(json['options'])
        : null;
    final annotationId = json['annotationId'];
    return CreateFile(
        kind: kind, uri: uri, options: options, annotationId: annotationId);
  }

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

  /// A create
  final String kind;

  /// Additional options
  final CreateFileOptions options;

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['kind'] = kind ?? (throw 'kind is required but was not set');
    __result['uri'] = uri ?? (throw 'uri is required but was not set');
    if (options != null) {
      __result['options'] = options.toJson();
    }
    if (annotationId != null) {
      __result['annotationId'] = annotationId;
    }
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, kind.hashCode);
    hash = JenkinsSmiHash.combine(hash, uri.hashCode);
    hash = JenkinsSmiHash.combine(hash, options.hashCode);
    hash = JenkinsSmiHash.combine(hash, annotationId.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  CreateFileOptions({this.overwrite, this.ignoreIfExists});
  static CreateFileOptions fromJson(Map<String, dynamic> json) {
    final overwrite = json['overwrite'];
    final ignoreIfExists = json['ignoreIfExists'];
    return CreateFileOptions(
        overwrite: overwrite, ignoreIfExists: ignoreIfExists);
  }

  /// Ignore if exists.
  final bool ignoreIfExists;

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (overwrite != null) {
      __result['overwrite'] = overwrite;
    }
    if (ignoreIfExists != null) {
      __result['ignoreIfExists'] = ignoreIfExists;
    }
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, overwrite.hashCode);
    hash = JenkinsSmiHash.combine(hash, ignoreIfExists.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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}) {
    if (files == null) {
      throw 'files is required but was not provided';
    }
  }
  static CreateFilesParams fromJson(Map<String, dynamic> json) {
    final files = json['files']
        ?.map((item) => item != null ? FileCreate.fromJson(item) : null)
        ?.cast<FileCreate>()
        ?.toList();
    return CreateFilesParams(files: files);
  }

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['files'] = files?.map((item) => item.toJson())?.toList() ??
        (throw 'files is required but was not set');
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(files));
    return JenkinsSmiHash.finish(hash);
  }

  @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, dynamic> json) {
    final dynamicRegistration = json['dynamicRegistration'];
    final linkSupport = json['linkSupport'];
    return DeclarationClientCapabilities(
        dynamicRegistration: dynamicRegistration, linkSupport: linkSupport);
  }

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

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    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, dynamic>) {
      reporter.push('dynamicRegistration');
      try {
        if (obj['dynamicRegistration'] != null &&
            !(obj['dynamicRegistration'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('linkSupport');
      try {
        if (obj['linkSupport'] != null && !(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode);
    hash = JenkinsSmiHash.combine(hash, linkSupport.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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, dynamic> json) {
    if (DeclarationRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DeclarationRegistrationOptions.fromJson(json);
    }
    final workDoneProgress = json['workDoneProgress'];
    return DeclarationOptions(workDoneProgress: workDoneProgress);
  }

  final bool workDoneProgress;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('workDoneProgress');
      try {
        if (obj['workDoneProgress'] != null &&
            !(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  DeclarationParams(
      {@required this.textDocument,
      @required this.position,
      this.workDoneToken,
      this.partialResultToken}) {
    if (textDocument == null) {
      throw 'textDocument is required but was not provided';
    }
    if (position == null) {
      throw 'position is required but was not provided';
    }
  }
  static DeclarationParams fromJson(Map<String, dynamic> json) {
    final textDocument = json['textDocument'] != null
        ? TextDocumentIdentifier.fromJson(json['textDocument'])
        : null;
    final position =
        json['position'] != null ? Position.fromJson(json['position']) : null;
    final workDoneToken = json['workDoneToken'] is num
        ? Either2<num, String>.t1(json['workDoneToken'])
        : (json['workDoneToken'] is String
            ? Either2<num, String>.t2(json['workDoneToken'])
            : (json['workDoneToken'] == null
                ? null
                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
    final partialResultToken = json['partialResultToken'] is num
        ? Either2<num, String>.t1(json['partialResultToken'])
        : (json['partialResultToken'] is String
            ? Either2<num, String>.t2(json['partialResultToken'])
            : (json['partialResultToken'] == null
                ? null
                : (throw '''${json['partialResultToken']} was not one of (num, String)''')));
    return DeclarationParams(
        textDocument: textDocument,
        position: position,
        workDoneToken: workDoneToken,
        partialResultToken: partialResultToken);
  }

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

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

  /// The text document.
  final TextDocumentIdentifier textDocument;

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['textDocument'] = textDocument?.toJson() ??
        (throw 'textDocument is required but was not set');
    __result['position'] =
        position?.toJson() ?? (throw 'position is required but was not set');
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    if (partialResultToken != null) {
      __result['partialResultToken'] = partialResultToken;
    }
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, textDocument.hashCode);
    hash = JenkinsSmiHash.combine(hash, position.hashCode);
    hash = JenkinsSmiHash.combine(hash, workDoneToken.hashCode);
    hash = JenkinsSmiHash.combine(hash, partialResultToken.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  DeclarationRegistrationOptions(
      {this.workDoneProgress, this.documentSelector, this.id});
  static DeclarationRegistrationOptions fromJson(Map<String, dynamic> json) {
    final workDoneProgress = json['workDoneProgress'];
    final documentSelector = json['documentSelector']
        ?.map((item) => item != null ? DocumentFilter.fromJson(item) : null)
        ?.cast<DocumentFilter>()
        ?.toList();
    final id = json['id'];
    return DeclarationRegistrationOptions(
        workDoneProgress: workDoneProgress,
        documentSelector: documentSelector,
        id: id);
  }

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

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    __result['documentSelector'] = documentSelector;
    if (id != null) {
      __result['id'] = id;
    }
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
    hash = JenkinsSmiHash.combine(hash, lspHashCode(documentSelector));
    hash = JenkinsSmiHash.combine(hash, id.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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, dynamic> json) {
    final dynamicRegistration = json['dynamicRegistration'];
    final linkSupport = json['linkSupport'];
    return DefinitionClientCapabilities(
        dynamicRegistration: dynamicRegistration, linkSupport: linkSupport);
  }

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

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    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, dynamic>) {
      reporter.push('dynamicRegistration');
      try {
        if (obj['dynamicRegistration'] != null &&
            !(obj['dynamicRegistration'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('linkSupport');
      try {
        if (obj['linkSupport'] != null && !(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode);
    hash = JenkinsSmiHash.combine(hash, linkSupport.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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, dynamic> json) {
    if (DefinitionRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DefinitionRegistrationOptions.fromJson(json);
    }
    final workDoneProgress = json['workDoneProgress'];
    return DefinitionOptions(workDoneProgress: workDoneProgress);
  }

  final bool workDoneProgress;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('workDoneProgress');
      try {
        if (obj['workDoneProgress'] != null &&
            !(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  DefinitionParams(
      {@required this.textDocument,
      @required this.position,
      this.workDoneToken,
      this.partialResultToken}) {
    if (textDocument == null) {
      throw 'textDocument is required but was not provided';
    }
    if (position == null) {
      throw 'position is required but was not provided';
    }
  }
  static DefinitionParams fromJson(Map<String, dynamic> json) {
    final textDocument = json['textDocument'] != null
        ? TextDocumentIdentifier.fromJson(json['textDocument'])
        : null;
    final position =
        json['position'] != null ? Position.fromJson(json['position']) : null;
    final workDoneToken = json['workDoneToken'] is num
        ? Either2<num, String>.t1(json['workDoneToken'])
        : (json['workDoneToken'] is String
            ? Either2<num, String>.t2(json['workDoneToken'])
            : (json['workDoneToken'] == null
                ? null
                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
    final partialResultToken = json['partialResultToken'] is num
        ? Either2<num, String>.t1(json['partialResultToken'])
        : (json['partialResultToken'] is String
            ? Either2<num, String>.t2(json['partialResultToken'])
            : (json['partialResultToken'] == null
                ? null
                : (throw '''${json['partialResultToken']} was not one of (num, String)''')));
    return DefinitionParams(
        textDocument: textDocument,
        position: position,
        workDoneToken: workDoneToken,
        partialResultToken: partialResultToken);
  }

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

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

  /// The text document.
  final TextDocumentIdentifier textDocument;

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['textDocument'] = textDocument?.toJson() ??
        (throw 'textDocument is required but was not set');
    __result['position'] =
        position?.toJson() ?? (throw 'position is required but was not set');
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    if (partialResultToken != null) {
      __result['partialResultToken'] = partialResultToken;
    }
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, textDocument.hashCode);
    hash = JenkinsSmiHash.combine(hash, position.hashCode);
    hash = JenkinsSmiHash.combine(hash, workDoneToken.hashCode);
    hash = JenkinsSmiHash.combine(hash, partialResultToken.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  DefinitionRegistrationOptions({this.documentSelector, this.workDoneProgress});
  static DefinitionRegistrationOptions fromJson(Map<String, dynamic> json) {
    final documentSelector = json['documentSelector']
        ?.map((item) => item != null ? DocumentFilter.fromJson(item) : null)
        ?.cast<DocumentFilter>()
        ?.toList();
    final workDoneProgress = json['workDoneProgress'];
    return DefinitionRegistrationOptions(
        documentSelector: documentSelector, workDoneProgress: workDoneProgress);
  }

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['documentSelector'] = documentSelector;
    if (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(documentSelector));
    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  DeleteFile(
      {this.kind = 'delete',
      @required this.uri,
      this.options,
      this.annotationId}) {
    if (kind != 'delete') {
      throw 'kind may only be the literal \'delete\'';
    }
    if (uri == null) {
      throw 'uri is required but was not provided';
    }
  }
  static DeleteFile fromJson(Map<String, dynamic> json) {
    final kind = json['kind'];
    final uri = json['uri'];
    final options = json['options'] != null
        ? DeleteFileOptions.fromJson(json['options'])
        : null;
    final annotationId = json['annotationId'];
    return DeleteFile(
        kind: kind, uri: uri, options: options, annotationId: annotationId);
  }

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

  /// A delete
  final String kind;

  /// Delete options.
  final DeleteFileOptions options;

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['kind'] = kind ?? (throw 'kind is required but was not set');
    __result['uri'] = uri ?? (throw 'uri is required but was not set');
    if (options != null) {
      __result['options'] = options.toJson();
    }
    if (annotationId != null) {
      __result['annotationId'] = annotationId;
    }
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, kind.hashCode);
    hash = JenkinsSmiHash.combine(hash, uri.hashCode);
    hash = JenkinsSmiHash.combine(hash, options.hashCode);
    hash = JenkinsSmiHash.combine(hash, annotationId.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  DeleteFileOptions({this.recursive, this.ignoreIfNotExists});
  static DeleteFileOptions fromJson(Map<String, dynamic> json) {
    final recursive = json['recursive'];
    final ignoreIfNotExists = json['ignoreIfNotExists'];
    return DeleteFileOptions(
        recursive: recursive, ignoreIfNotExists: ignoreIfNotExists);
  }

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

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (recursive != null) {
      __result['recursive'] = recursive;
    }
    if (ignoreIfNotExists != null) {
      __result['ignoreIfNotExists'] = ignoreIfNotExists;
    }
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, recursive.hashCode);
    hash = JenkinsSmiHash.combine(hash, ignoreIfNotExists.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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}) {
    if (files == null) {
      throw 'files is required but was not provided';
    }
  }
  static DeleteFilesParams fromJson(Map<String, dynamic> json) {
    final files = json['files']
        ?.map((item) => item != null ? FileDelete.fromJson(item) : null)
        ?.cast<FileDelete>()
        ?.toList();
    return DeleteFilesParams(files: files);
  }

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['files'] = files?.map((item) => item.toJson())?.toList() ??
        (throw 'files is required but was not set');
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(files));
    return JenkinsSmiHash.finish(hash);
  }

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

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

  Diagnostic(
      {@required this.range,
      this.severity,
      this.code,
      this.codeDescription,
      this.source,
      @required this.message,
      this.tags,
      this.relatedInformation,
      this.data}) {
    if (range == null) {
      throw 'range is required but was not provided';
    }
    if (message == null) {
      throw 'message is required but was not provided';
    }
  }
  static Diagnostic fromJson(Map<String, dynamic> json) {
    final range = json['range'] != null ? Range.fromJson(json['range']) : null;
    final severity = json['severity'] != null
        ? DiagnosticSeverity.fromJson(json['severity'])
        : null;
    final code = json['code'];
    final codeDescription = json['codeDescription'] != null
        ? CodeDescription.fromJson(json['codeDescription'])
        : null;
    final source = json['source'];
    final message = json['message'];
    final tags = json['tags']
        ?.map((item) => item != null ? DiagnosticTag.fromJson(item) : null)
        ?.cast<DiagnosticTag>()
        ?.toList();
    final relatedInformation = json['relatedInformation']
        ?.map((item) =>
            item != null ? DiagnosticRelatedInformation.fromJson(item) : null)
        ?.cast<DiagnosticRelatedInformation>()
        ?.toList();
    final data = json['data'];
    return Diagnostic(
        range: range,
        severity: severity,
        code: code,
        codeDescription: codeDescription,
        source: source,
        message: message,
        tags: tags,
        relatedInformation: relatedInformation,
        data: data);
  }

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

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

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

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

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

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

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

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

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['range'] =
        range?.toJson() ?? (throw 'range is required but was not set');
    if (severity != null) {
      __result['severity'] = severity.toJson();
    }
    if (code != null) {
      __result['code'] = code;
    }
    if (codeDescription != null) {
      __result['codeDescription'] = codeDescription.toJson();
    }
    if (source != null) {
      __result['source'] = source;
    }
    __result['message'] =
        message ?? (throw 'message is required but was not set');
    if (tags != null) {
      __result['tags'] = tags.map((item) => item.toJson()).toList();
    }
    if (relatedInformation != null) {
      __result['relatedInformation'] =
          relatedInformation.map((item) => item.toJson()).toList();
    }
    if (data != null) {
      __result['data'] = data;
    }
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, range.hashCode);
    hash = JenkinsSmiHash.combine(hash, severity.hashCode);
    hash = JenkinsSmiHash.combine(hash, code.hashCode);
    hash = JenkinsSmiHash.combine(hash, codeDescription.hashCode);
    hash = JenkinsSmiHash.combine(hash, source.hashCode);
    hash = JenkinsSmiHash.combine(hash, message.hashCode);
    hash = JenkinsSmiHash.combine(hash, lspHashCode(tags));
    hash = JenkinsSmiHash.combine(hash, lspHashCode(relatedInformation));
    hash = JenkinsSmiHash.combine(hash, data.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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}) {
    if (location == null) {
      throw 'location is required but was not provided';
    }
    if (message == null) {
      throw 'message is required but was not provided';
    }
  }
  static DiagnosticRelatedInformation fromJson(Map<String, dynamic> json) {
    final location =
        json['location'] != null ? Location.fromJson(json['location']) : null;
    final message = json['message'];
    return DiagnosticRelatedInformation(location: location, message: message);
  }

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

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['location'] =
        location?.toJson() ?? (throw 'location is required but was not set');
    __result['message'] =
        message ?? (throw 'message is required but was not set');
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('location');
      try {
        if (!obj.containsKey('location')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['location'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(Location.canParse(obj['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;
        }
        if (obj['message'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, location.hashCode);
    hash = JenkinsSmiHash.combine(hash, message.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  final num _value;

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

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

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

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

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

  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

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

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

  final num _value;

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

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

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

  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

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

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

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

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (dynamicRegistration != null) {
      __result['dynamicRegistration'] = dynamicRegistration;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('dynamicRegistration');
      try {
        if (obj['dynamicRegistration'] != null &&
            !(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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, dynamic> json) {
    final settings = json['settings'];
    return DidChangeConfigurationParams(settings: settings);
  }

  /// The actual changed settings
  final dynamic settings;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['settings'] = settings;
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('settings');
      try {
        if (!obj.containsKey('settings')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['settings'] != null && !(true)) {
          reporter.reportError('must be of type dynamic');
          return false;
        }
      } finally {
        reporter.pop();
      }
      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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, settings.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  DidChangeTextDocumentParams(
      {@required this.textDocument, @required this.contentChanges}) {
    if (textDocument == null) {
      throw 'textDocument is required but was not provided';
    }
    if (contentChanges == null) {
      throw 'contentChanges is required but was not provided';
    }
  }
  static DidChangeTextDocumentParams fromJson(Map<String, dynamic> json) {
    final textDocument = json['textDocument'] != null
        ? VersionedTextDocumentIdentifier.fromJson(json['textDocument'])
        : null;
    final contentChanges = json['contentChanges']
        ?.map((item) => TextDocumentContentChangeEvent1.canParse(
                item, nullLspJsonReporter)
            ? Either2<TextDocumentContentChangeEvent1, TextDocumentContentChangeEvent2>.t1(
                item != null
                    ? TextDocumentContentChangeEvent1.fromJson(item)
                    : null)
            : (TextDocumentContentChangeEvent2.canParse(item, nullLspJsonReporter)
                ? Either2<TextDocumentContentChangeEvent1,
                        TextDocumentContentChangeEvent2>.t2(
                    item != null
                        ? TextDocumentContentChangeEvent2.fromJson(item)
                        : null)
                : (throw '''${item} was not one of (TextDocumentContentChangeEvent1, TextDocumentContentChangeEvent2)''')))
        ?.cast<Either2<TextDocumentContentChangeEvent1, TextDocumentContentChangeEvent2>>()
        ?.toList();
    return DidChangeTextDocumentParams(
        textDocument: textDocument, contentChanges: contentChanges);
  }

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

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['textDocument'] = textDocument?.toJson() ??
        (throw 'textDocument is required but was not set');
    __result['contentChanges'] =
        contentChanges ?? (throw 'contentChanges is required but was not set');
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, textDocument.hashCode);
    hash = JenkinsSmiHash.combine(hash, lspHashCode(contentChanges));
    return JenkinsSmiHash.finish(hash);
  }

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

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

  DidChangeWatchedFilesClientCapabilities({this.dynamicRegistration});
  static DidChangeWatchedFilesClientCapabilities fromJson(
      Map<String, dynamic> json) {
    final dynamicRegistration = json['dynamicRegistration'];
    return DidChangeWatchedFilesClientCapabilities(
        dynamicRegistration: dynamicRegistration);
  }

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (dynamicRegistration != null) {
      __result['dynamicRegistration'] = dynamicRegistration;
    }
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  DidChangeWatchedFilesParams({@required this.changes}) {
    if (changes == null) {
      throw 'changes is required but was not provided';
    }
  }
  static DidChangeWatchedFilesParams fromJson(Map<String, dynamic> json) {
    final changes = json['changes']
        ?.map((item) => item != null ? FileEvent.fromJson(item) : null)
        ?.cast<FileEvent>()
        ?.toList();
    return DidChangeWatchedFilesParams(changes: changes);
  }

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['changes'] = changes?.map((item) => item.toJson())?.toList() ??
        (throw 'changes is required but was not set');
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(changes));
    return JenkinsSmiHash.finish(hash);
  }

  @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}) {
    if (watchers == null) {
      throw 'watchers is required but was not provided';
    }
  }
  static DidChangeWatchedFilesRegistrationOptions fromJson(
      Map<String, dynamic> json) {
    final watchers = json['watchers']
        ?.map((item) => item != null ? FileSystemWatcher.fromJson(item) : null)
        ?.cast<FileSystemWatcher>()
        ?.toList();
    return DidChangeWatchedFilesRegistrationOptions(watchers: watchers);
  }

  /// The watchers to register.
  final List<FileSystemWatcher> watchers;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['watchers'] = watchers?.map((item) => item.toJson())?.toList() ??
        (throw 'watchers is required but was not set');
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(watchers));
    return JenkinsSmiHash.finish(hash);
  }

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

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

  DidChangeWorkspaceFoldersParams({@required this.event}) {
    if (event == null) {
      throw 'event is required but was not provided';
    }
  }
  static DidChangeWorkspaceFoldersParams fromJson(Map<String, dynamic> json) {
    final event = json['event'] != null
        ? WorkspaceFoldersChangeEvent.fromJson(json['event'])
        : null;
    return DidChangeWorkspaceFoldersParams(event: event);
  }

  /// The actual workspace folder change event.
  final WorkspaceFoldersChangeEvent event;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['event'] =
        event?.toJson() ?? (throw 'event is required but was not set');
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('event');
      try {
        if (!obj.containsKey('event')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['event'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(WorkspaceFoldersChangeEvent.canParse(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, event.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  DidCloseTextDocumentParams({@required this.textDocument}) {
    if (textDocument == null) {
      throw 'textDocument is required but was not provided';
    }
  }
  static DidCloseTextDocumentParams fromJson(Map<String, dynamic> json) {
    final textDocument = json['textDocument'] != null
        ? TextDocumentIdentifier.fromJson(json['textDocument'])
        : null;
    return DidCloseTextDocumentParams(textDocument: textDocument);
  }

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['textDocument'] = textDocument?.toJson() ??
        (throw 'textDocument is required but was not set');
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['textDocument'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(TextDocumentIdentifier.canParse(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, textDocument.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  DidOpenTextDocumentParams({@required this.textDocument}) {
    if (textDocument == null) {
      throw 'textDocument is required but was not provided';
    }
  }
  static DidOpenTextDocumentParams fromJson(Map<String, dynamic> json) {
    final textDocument = json['textDocument'] != null
        ? TextDocumentItem.fromJson(json['textDocument'])
        : null;
    return DidOpenTextDocumentParams(textDocument: textDocument);
  }

  /// The document that was opened.
  final TextDocumentItem textDocument;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['textDocument'] = textDocument?.toJson() ??
        (throw 'textDocument is required but was not set');
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['textDocument'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(TextDocumentItem.canParse(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, textDocument.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  DidSaveTextDocumentParams({@required this.textDocument, this.text}) {
    if (textDocument == null) {
      throw 'textDocument is required but was not provided';
    }
  }
  static DidSaveTextDocumentParams fromJson(Map<String, dynamic> json) {
    final textDocument = json['textDocument'] != null
        ? TextDocumentIdentifier.fromJson(json['textDocument'])
        : null;
    final text = json['text'];
    return DidSaveTextDocumentParams(textDocument: textDocument, text: text);
  }

  /// Optional the content when saved. Depends on the includeText value when the
  /// save notification was requested.
  final String text;

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['textDocument'] = textDocument?.toJson() ??
        (throw 'textDocument is required but was not set');
    if (text != null) {
      __result['text'] = text;
    }
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, textDocument.hashCode);
    hash = JenkinsSmiHash.combine(hash, text.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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, dynamic> json) {
    final dynamicRegistration = json['dynamicRegistration'];
    return DocumentColorClientCapabilities(
        dynamicRegistration: dynamicRegistration);
  }

  /// Whether document color supports dynamic registration.
  final bool dynamicRegistration;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (dynamicRegistration != null) {
      __result['dynamicRegistration'] = dynamicRegistration;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('dynamicRegistration');
      try {
        if (obj['dynamicRegistration'] != null &&
            !(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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, dynamic> json) {
    if (DocumentColorRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentColorRegistrationOptions.fromJson(json);
    }
    final workDoneProgress = json['workDoneProgress'];
    return DocumentColorOptions(workDoneProgress: workDoneProgress);
  }

  final bool workDoneProgress;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('workDoneProgress');
      try {
        if (obj['workDoneProgress'] != null &&
            !(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  DocumentColorParams(
      {@required this.textDocument,
      this.workDoneToken,
      this.partialResultToken}) {
    if (textDocument == null) {
      throw 'textDocument is required but was not provided';
    }
  }
  static DocumentColorParams fromJson(Map<String, dynamic> json) {
    final textDocument = json['textDocument'] != null
        ? TextDocumentIdentifier.fromJson(json['textDocument'])
        : null;
    final workDoneToken = json['workDoneToken'] is num
        ? Either2<num, String>.t1(json['workDoneToken'])
        : (json['workDoneToken'] is String
            ? Either2<num, String>.t2(json['workDoneToken'])
            : (json['workDoneToken'] == null
                ? null
                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
    final partialResultToken = json['partialResultToken'] is num
        ? Either2<num, String>.t1(json['partialResultToken'])
        : (json['partialResultToken'] is String
            ? Either2<num, String>.t2(json['partialResultToken'])
            : (json['partialResultToken'] == null
                ? null
                : (throw '''${json['partialResultToken']} was not one of (num, String)''')));
    return DocumentColorParams(
        textDocument: textDocument,
        workDoneToken: workDoneToken,
        partialResultToken: partialResultToken);
  }

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

  /// The text document.
  final TextDocumentIdentifier textDocument;

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['textDocument'] = textDocument?.toJson() ??
        (throw 'textDocument is required but was not set');
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    if (partialResultToken != null) {
      __result['partialResultToken'] = partialResultToken;
    }
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, textDocument.hashCode);
    hash = JenkinsSmiHash.combine(hash, workDoneToken.hashCode);
    hash = JenkinsSmiHash.combine(hash, partialResultToken.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  DocumentColorRegistrationOptions(
      {this.documentSelector, this.id, this.workDoneProgress});
  static DocumentColorRegistrationOptions fromJson(Map<String, dynamic> json) {
    final documentSelector = json['documentSelector']
        ?.map((item) => item != null ? DocumentFilter.fromJson(item) : null)
        ?.cast<DocumentFilter>()
        ?.toList();
    final id = json['id'];
    final workDoneProgress = json['workDoneProgress'];
    return DocumentColorRegistrationOptions(
        documentSelector: documentSelector,
        id: id,
        workDoneProgress: workDoneProgress);
  }

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

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __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, dynamic>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['documentSelector'] != null &&
            !((obj['documentSelector'] is List &&
                (obj['documentSelector'].every(
                    (item) => DocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<DocumentFilter>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('id');
      try {
        if (obj['id'] != null && !(obj['id'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        if (obj['workDoneProgress'] != null &&
            !(obj['workDoneProgress'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DocumentColorRegistrationOptions');
      return false;
    }
  }

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(documentSelector));
    hash = JenkinsSmiHash.combine(hash, id.hashCode);
    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  DocumentFilter({this.language, this.scheme, this.pattern});
  static DocumentFilter fromJson(Map<String, dynamic> json) {
    final language = json['language'];
    final scheme = json['scheme'];
    final pattern = json['pattern'];
    return DocumentFilter(language: language, scheme: scheme, pattern: pattern);
  }

  /// A language id, like `typescript`.
  final String language;

  /// A glob pattern, like `*.{ts,js}`.
  ///
  /// Glob patterns can have the following syntax:
  /// - `*` to match one or more characters in a path segment
  /// - `?` to match on one character in a path segment
  /// - `**` to match any number of path segments, including none
  /// - `{}` to group conditions (e.g. `**​/*.{ts,js}` matches all TypeScript
  ///   and JavaScript files)
  /// - `[]` to declare a range of characters to match in a path segment
  ///   (e.g., `example.[0-9]` to match on `example.0`, `example.1`, …)
  /// - `[!...]` to negate a range of characters to match in a path segment
  ///   (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but
  ///   not `example.0`)
  final String pattern;

  /// A Uri [scheme](#Uri.scheme), like `file` or `untitled`.
  final String scheme;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (language != null) {
      __result['language'] = language;
    }
    if (scheme != null) {
      __result['scheme'] = scheme;
    }
    if (pattern != null) {
      __result['pattern'] = pattern;
    }
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, language.hashCode);
    hash = JenkinsSmiHash.combine(hash, scheme.hashCode);
    hash = JenkinsSmiHash.combine(hash, pattern.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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, dynamic> json) {
    final dynamicRegistration = json['dynamicRegistration'];
    return DocumentFormattingClientCapabilities(
        dynamicRegistration: dynamicRegistration);
  }

  /// Whether formatting supports dynamic registration.
  final bool dynamicRegistration;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (dynamicRegistration != null) {
      __result['dynamicRegistration'] = dynamicRegistration;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('dynamicRegistration');
      try {
        if (obj['dynamicRegistration'] != null &&
            !(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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, dynamic> json) {
    if (DocumentFormattingRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return DocumentFormattingRegistrationOptions.fromJson(json);
    }
    final workDoneProgress = json['workDoneProgress'];
    return DocumentFormattingOptions(workDoneProgress: workDoneProgress);
  }

  final bool workDoneProgress;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('workDoneProgress');
      try {
        if (obj['workDoneProgress'] != null &&
            !(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  DocumentFormattingParams(
      {@required this.textDocument,
      @required this.options,
      this.workDoneToken}) {
    if (textDocument == null) {
      throw 'textDocument is required but was not provided';
    }
    if (options == null) {
      throw 'options is required but was not provided';
    }
  }
  static DocumentFormattingParams fromJson(Map<String, dynamic> json) {
    final textDocument = json['textDocument'] != null
        ? TextDocumentIdentifier.fromJson(json['textDocument'])
        : null;
    final options = json['options'] != null
        ? FormattingOptions.fromJson(json['options'])
        : null;
    final workDoneToken = json['workDoneToken'] is num
        ? Either2<num, String>.t1(json['workDoneToken'])
        : (json['workDoneToken'] is String
            ? Either2<num, String>.t2(json['workDoneToken'])
            : (json['workDoneToken'] == null
                ? null
                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
    return DocumentFormattingParams(
        textDocument: textDocument,
        options: options,
        workDoneToken: workDoneToken);
  }

  /// The format options.
  final FormattingOptions options;

  /// The document to format.
  final TextDocumentIdentifier textDocument;

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['textDocument'] = textDocument?.toJson() ??
        (throw 'textDocument is required but was not set');
    __result['options'] =
        options?.toJson() ?? (throw 'options is required but was not set');
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, textDocument.hashCode);
    hash = JenkinsSmiHash.combine(hash, options.hashCode);
    hash = JenkinsSmiHash.combine(hash, workDoneToken.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  DocumentFormattingRegistrationOptions(
      {this.documentSelector, this.workDoneProgress});
  static DocumentFormattingRegistrationOptions fromJson(
      Map<String, dynamic> json) {
    final documentSelector = json['documentSelector']
        ?.map((item) => item != null ? DocumentFilter.fromJson(item) : null)
        ?.cast<DocumentFilter>()
        ?.toList();
    final workDoneProgress = json['workDoneProgress'];
    return DocumentFormattingRegistrationOptions(
        documentSelector: documentSelector, workDoneProgress: workDoneProgress);
  }

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['documentSelector'] = documentSelector;
    if (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(documentSelector));
    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

/// A document highlight is a range inside a text document which deserves
/// special attention. Usually a document highlight is visualized by changing
/// the background color of its range.
class DocumentHighlight implements ToJsonable {
  static const jsonHandler =
      LspJsonHandler(DocumentHighlight.canParse, DocumentHighlight.fromJson);

  DocumentHighlight({@required this.range, this.kind}) {
    if (range == null) {
      throw 'range is required but was not provided';
    }
  }
  static DocumentHighlight fromJson(Map<String, dynamic> json) {
    final range = json['range'] != null ? Range.fromJson(json['range']) : null;
    final kind = json['kind'] != null
        ? DocumentHighlightKind.fromJson(json['kind'])
        : null;
    return DocumentHighlight(range: range, kind: kind);
  }

  /// The highlight kind, default is DocumentHighlightKind.Text.
  final DocumentHighlightKind kind;

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['range'] =
        range?.toJson() ?? (throw 'range is required but was not set');
    if (kind != null) {
      __result['kind'] = kind.toJson();
    }
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, range.hashCode);
    hash = JenkinsSmiHash.combine(hash, kind.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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, dynamic> json) {
    final dynamicRegistration = json['dynamicRegistration'];
    return DocumentHighlightClientCapabilities(
        dynamicRegistration: dynamicRegistration);
  }

  /// Whether document highlight supports dynamic registration.
  final bool dynamicRegistration;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (dynamicRegistration != null) {
      __result['dynamicRegistration'] = dynamicRegistration;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('dynamicRegistration');
      try {
        if (obj['dynamicRegistration'] != null &&
            !(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  final num _value;

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

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

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

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

  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

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

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

  DocumentHighlightOptions({this.workDoneProgress});
  static DocumentHighlightOptions fromJson(Map<String, dynamic> json) {
    if (DocumentHighlightRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return DocumentHighlightRegistrationOptions.fromJson(json);
    }
    final workDoneProgress = json['workDoneProgress'];
    return DocumentHighlightOptions(workDoneProgress: workDoneProgress);
  }

  final bool workDoneProgress;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('workDoneProgress');
      try {
        if (obj['workDoneProgress'] != null &&
            !(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  DocumentHighlightParams(
      {@required this.textDocument,
      @required this.position,
      this.workDoneToken,
      this.partialResultToken}) {
    if (textDocument == null) {
      throw 'textDocument is required but was not provided';
    }
    if (position == null) {
      throw 'position is required but was not provided';
    }
  }
  static DocumentHighlightParams fromJson(Map<String, dynamic> json) {
    final textDocument = json['textDocument'] != null
        ? TextDocumentIdentifier.fromJson(json['textDocument'])
        : null;
    final position =
        json['position'] != null ? Position.fromJson(json['position']) : null;
    final workDoneToken = json['workDoneToken'] is num
        ? Either2<num, String>.t1(json['workDoneToken'])
        : (json['workDoneToken'] is String
            ? Either2<num, String>.t2(json['workDoneToken'])
            : (json['workDoneToken'] == null
                ? null
                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
    final partialResultToken = json['partialResultToken'] is num
        ? Either2<num, String>.t1(json['partialResultToken'])
        : (json['partialResultToken'] is String
            ? Either2<num, String>.t2(json['partialResultToken'])
            : (json['partialResultToken'] == null
                ? null
                : (throw '''${json['partialResultToken']} was not one of (num, String)''')));
    return DocumentHighlightParams(
        textDocument: textDocument,
        position: position,
        workDoneToken: workDoneToken,
        partialResultToken: partialResultToken);
  }

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

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

  /// The text document.
  final TextDocumentIdentifier textDocument;

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['textDocument'] = textDocument?.toJson() ??
        (throw 'textDocument is required but was not set');
    __result['position'] =
        position?.toJson() ?? (throw 'position is required but was not set');
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    if (partialResultToken != null) {
      __result['partialResultToken'] = partialResultToken;
    }
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, textDocument.hashCode);
    hash = JenkinsSmiHash.combine(hash, position.hashCode);
    hash = JenkinsSmiHash.combine(hash, workDoneToken.hashCode);
    hash = JenkinsSmiHash.combine(hash, partialResultToken.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  DocumentHighlightRegistrationOptions(
      {this.documentSelector, this.workDoneProgress});
  static DocumentHighlightRegistrationOptions fromJson(
      Map<String, dynamic> json) {
    final documentSelector = json['documentSelector']
        ?.map((item) => item != null ? DocumentFilter.fromJson(item) : null)
        ?.cast<DocumentFilter>()
        ?.toList();
    final workDoneProgress = json['workDoneProgress'];
    return DocumentHighlightRegistrationOptions(
        documentSelector: documentSelector, workDoneProgress: workDoneProgress);
  }

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['documentSelector'] = documentSelector;
    if (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(documentSelector));
    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

/// A document link is a range in a text document that links to an internal or
/// external resource, like another text document or a web site.
class DocumentLink implements ToJsonable {
  static const jsonHandler =
      LspJsonHandler(DocumentLink.canParse, DocumentLink.fromJson);

  DocumentLink({@required this.range, this.target, this.tooltip, this.data}) {
    if (range == null) {
      throw 'range is required but was not provided';
    }
  }
  static DocumentLink fromJson(Map<String, dynamic> json) {
    final range = json['range'] != null ? Range.fromJson(json['range']) : null;
    final target = json['target'];
    final tooltip = json['tooltip'];
    final data = json['data'];
    return DocumentLink(
        range: range, target: target, tooltip: tooltip, data: data);
  }

  /// A data entry field that is preserved on a document link between a
  /// DocumentLinkRequest and a DocumentLinkResolveRequest.
  final dynamic data;

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

  /// The uri this link points to. If missing a resolve request is sent later.
  final String target;

  /// The tooltip text when you hover over this link.
  ///
  /// If a tooltip is provided, is will be displayed in a string that includes
  /// instructions on how to trigger the link, such as `{0} (ctrl + click)`. The
  /// specific instructions vary depending on OS, user settings, and
  /// localization.
  ///  @since 3.15.0
  final String tooltip;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['range'] =
        range?.toJson() ?? (throw 'range is required but was not set');
    if (target != null) {
      __result['target'] = target;
    }
    if (tooltip != null) {
      __result['tooltip'] = tooltip;
    }
    if (data != null) {
      __result['data'] = data;
    }
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, range.hashCode);
    hash = JenkinsSmiHash.combine(hash, target.hashCode);
    hash = JenkinsSmiHash.combine(hash, tooltip.hashCode);
    hash = JenkinsSmiHash.combine(hash, data.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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, dynamic> json) {
    final dynamicRegistration = json['dynamicRegistration'];
    final tooltipSupport = json['tooltipSupport'];
    return DocumentLinkClientCapabilities(
        dynamicRegistration: dynamicRegistration,
        tooltipSupport: tooltipSupport);
  }

  /// Whether document link supports dynamic registration.
  final bool dynamicRegistration;

  /// Whether the client supports the `tooltip` property on `DocumentLink`.
  ///  @since 3.15.0
  final bool tooltipSupport;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    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, dynamic>) {
      reporter.push('dynamicRegistration');
      try {
        if (obj['dynamicRegistration'] != null &&
            !(obj['dynamicRegistration'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('tooltipSupport');
      try {
        if (obj['tooltipSupport'] != null && !(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode);
    hash = JenkinsSmiHash.combine(hash, tooltipSupport.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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, dynamic> json) {
    if (DocumentLinkRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentLinkRegistrationOptions.fromJson(json);
    }
    final resolveProvider = json['resolveProvider'];
    final workDoneProgress = json['workDoneProgress'];
    return DocumentLinkOptions(
        resolveProvider: resolveProvider, workDoneProgress: workDoneProgress);
  }

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    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, dynamic>) {
      reporter.push('resolveProvider');
      try {
        if (obj['resolveProvider'] != null &&
            !(obj['resolveProvider'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        if (obj['workDoneProgress'] != null &&
            !(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, resolveProvider.hashCode);
    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  DocumentLinkParams(
      {@required this.textDocument,
      this.workDoneToken,
      this.partialResultToken}) {
    if (textDocument == null) {
      throw 'textDocument is required but was not provided';
    }
  }
  static DocumentLinkParams fromJson(Map<String, dynamic> json) {
    final textDocument = json['textDocument'] != null
        ? TextDocumentIdentifier.fromJson(json['textDocument'])
        : null;
    final workDoneToken = json['workDoneToken'] is num
        ? Either2<num, String>.t1(json['workDoneToken'])
        : (json['workDoneToken'] is String
            ? Either2<num, String>.t2(json['workDoneToken'])
            : (json['workDoneToken'] == null
                ? null
                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
    final partialResultToken = json['partialResultToken'] is num
        ? Either2<num, String>.t1(json['partialResultToken'])
        : (json['partialResultToken'] is String
            ? Either2<num, String>.t2(json['partialResultToken'])
            : (json['partialResultToken'] == null
                ? null
                : (throw '''${json['partialResultToken']} was not one of (num, String)''')));
    return DocumentLinkParams(
        textDocument: textDocument,
        workDoneToken: workDoneToken,
        partialResultToken: partialResultToken);
  }

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

  /// The document to provide document links for.
  final TextDocumentIdentifier textDocument;

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['textDocument'] = textDocument?.toJson() ??
        (throw 'textDocument is required but was not set');
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    if (partialResultToken != null) {
      __result['partialResultToken'] = partialResultToken;
    }
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, textDocument.hashCode);
    hash = JenkinsSmiHash.combine(hash, workDoneToken.hashCode);
    hash = JenkinsSmiHash.combine(hash, partialResultToken.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  DocumentLinkRegistrationOptions(
      {this.documentSelector, this.resolveProvider, this.workDoneProgress});
  static DocumentLinkRegistrationOptions fromJson(Map<String, dynamic> json) {
    final documentSelector = json['documentSelector']
        ?.map((item) => item != null ? DocumentFilter.fromJson(item) : null)
        ?.cast<DocumentFilter>()
        ?.toList();
    final resolveProvider = json['resolveProvider'];
    final workDoneProgress = json['workDoneProgress'];
    return DocumentLinkRegistrationOptions(
        documentSelector: documentSelector,
        resolveProvider: resolveProvider,
        workDoneProgress: workDoneProgress);
  }

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

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __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, dynamic>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['documentSelector'] != null &&
            !((obj['documentSelector'] is List &&
                (obj['documentSelector'].every(
                    (item) => DocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<DocumentFilter>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('resolveProvider');
      try {
        if (obj['resolveProvider'] != null &&
            !(obj['resolveProvider'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        if (obj['workDoneProgress'] != null &&
            !(obj['workDoneProgress'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DocumentLinkRegistrationOptions');
      return false;
    }
  }

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(documentSelector));
    hash = JenkinsSmiHash.combine(hash, resolveProvider.hashCode);
    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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, dynamic> json) {
    final dynamicRegistration = json['dynamicRegistration'];
    return DocumentOnTypeFormattingClientCapabilities(
        dynamicRegistration: dynamicRegistration);
  }

  /// Whether on type formatting supports dynamic registration.
  final bool dynamicRegistration;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (dynamicRegistration != null) {
      __result['dynamicRegistration'] = dynamicRegistration;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('dynamicRegistration');
      try {
        if (obj['dynamicRegistration'] != null &&
            !(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  DocumentOnTypeFormattingOptions(
      {@required this.firstTriggerCharacter, this.moreTriggerCharacter}) {
    if (firstTriggerCharacter == null) {
      throw 'firstTriggerCharacter is required but was not provided';
    }
  }
  static DocumentOnTypeFormattingOptions fromJson(Map<String, dynamic> json) {
    if (DocumentOnTypeFormattingRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return DocumentOnTypeFormattingRegistrationOptions.fromJson(json);
    }
    final firstTriggerCharacter = json['firstTriggerCharacter'];
    final moreTriggerCharacter = json['moreTriggerCharacter']
        ?.map((item) => item)
        ?.cast<String>()
        ?.toList();
    return DocumentOnTypeFormattingOptions(
        firstTriggerCharacter: firstTriggerCharacter,
        moreTriggerCharacter: moreTriggerCharacter);
  }

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

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['firstTriggerCharacter'] = firstTriggerCharacter ??
        (throw 'firstTriggerCharacter is required but was not set');
    if (moreTriggerCharacter != null) {
      __result['moreTriggerCharacter'] = moreTriggerCharacter;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('firstTriggerCharacter');
      try {
        if (!obj.containsKey('firstTriggerCharacter')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['firstTriggerCharacter'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['firstTriggerCharacter'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('moreTriggerCharacter');
      try {
        if (obj['moreTriggerCharacter'] != null &&
            !((obj['moreTriggerCharacter'] is List &&
                (obj['moreTriggerCharacter']
                    .every((item) => item is String))))) {
          reporter.reportError('must be of type List<String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DocumentOnTypeFormattingOptions');
      return false;
    }
  }

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, firstTriggerCharacter.hashCode);
    hash = JenkinsSmiHash.combine(hash, lspHashCode(moreTriggerCharacter));
    return JenkinsSmiHash.finish(hash);
  }

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

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

  DocumentOnTypeFormattingParams(
      {@required this.ch,
      @required this.options,
      @required this.textDocument,
      @required this.position}) {
    if (ch == null) {
      throw 'ch is required but was not provided';
    }
    if (options == null) {
      throw 'options is required but was not provided';
    }
    if (textDocument == null) {
      throw 'textDocument is required but was not provided';
    }
    if (position == null) {
      throw 'position is required but was not provided';
    }
  }
  static DocumentOnTypeFormattingParams fromJson(Map<String, dynamic> json) {
    final ch = json['ch'];
    final options = json['options'] != null
        ? FormattingOptions.fromJson(json['options'])
        : null;
    final textDocument = json['textDocument'] != null
        ? TextDocumentIdentifier.fromJson(json['textDocument'])
        : null;
    final position =
        json['position'] != null ? Position.fromJson(json['position']) : null;
    return DocumentOnTypeFormattingParams(
        ch: ch,
        options: options,
        textDocument: textDocument,
        position: position);
  }

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

  /// The format options.
  final FormattingOptions options;

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

  /// The text document.
  final TextDocumentIdentifier textDocument;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['ch'] = ch ?? (throw 'ch is required but was not set');
    __result['options'] =
        options?.toJson() ?? (throw 'options is required but was not set');
    __result['textDocument'] = textDocument?.toJson() ??
        (throw 'textDocument is required but was not set');
    __result['position'] =
        position?.toJson() ?? (throw 'position is required but was not set');
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('ch');
      try {
        if (!obj.containsKey('ch')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['ch'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['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;
        }
        if (obj['options'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(FormattingOptions.canParse(obj['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;
        }
        if (obj['textDocument'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(TextDocumentIdentifier.canParse(obj['textDocument'], reporter))) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('position');
      try {
        if (!obj.containsKey('position')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['position'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(Position.canParse(obj['position'], reporter))) {
          reporter.reportError('must be of type Position');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DocumentOnTypeFormattingParams');
      return false;
    }
  }

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, ch.hashCode);
    hash = JenkinsSmiHash.combine(hash, options.hashCode);
    hash = JenkinsSmiHash.combine(hash, textDocument.hashCode);
    hash = JenkinsSmiHash.combine(hash, position.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  DocumentOnTypeFormattingRegistrationOptions(
      {this.documentSelector,
      @required this.firstTriggerCharacter,
      this.moreTriggerCharacter}) {
    if (firstTriggerCharacter == null) {
      throw 'firstTriggerCharacter is required but was not provided';
    }
  }
  static DocumentOnTypeFormattingRegistrationOptions fromJson(
      Map<String, dynamic> json) {
    final documentSelector = json['documentSelector']
        ?.map((item) => item != null ? DocumentFilter.fromJson(item) : null)
        ?.cast<DocumentFilter>()
        ?.toList();
    final firstTriggerCharacter = json['firstTriggerCharacter'];
    final moreTriggerCharacter = json['moreTriggerCharacter']
        ?.map((item) => item)
        ?.cast<String>()
        ?.toList();
    return DocumentOnTypeFormattingRegistrationOptions(
        documentSelector: documentSelector,
        firstTriggerCharacter: firstTriggerCharacter,
        moreTriggerCharacter: moreTriggerCharacter);
  }

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

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

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['documentSelector'] = documentSelector;
    __result['firstTriggerCharacter'] = firstTriggerCharacter ??
        (throw 'firstTriggerCharacter is required but was not set');
    if (moreTriggerCharacter != null) {
      __result['moreTriggerCharacter'] = moreTriggerCharacter;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['documentSelector'] != null &&
            !((obj['documentSelector'] is List &&
                (obj['documentSelector'].every(
                    (item) => DocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<DocumentFilter>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('firstTriggerCharacter');
      try {
        if (!obj.containsKey('firstTriggerCharacter')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['firstTriggerCharacter'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['firstTriggerCharacter'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('moreTriggerCharacter');
      try {
        if (obj['moreTriggerCharacter'] != null &&
            !((obj['moreTriggerCharacter'] is List &&
                (obj['moreTriggerCharacter']
                    .every((item) => item is String))))) {
          reporter.reportError('must be of type List<String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type DocumentOnTypeFormattingRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is DocumentOnTypeFormattingRegistrationOptions &&
        other.runtimeType == DocumentOnTypeFormattingRegistrationOptions) {
      return listEqual(documentSelector, other.documentSelector,
              (DocumentFilter a, DocumentFilter b) => a == b) &&
          firstTriggerCharacter == other.firstTriggerCharacter &&
          listEqual(moreTriggerCharacter, other.moreTriggerCharacter,
              (String a, String b) => a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(documentSelector));
    hash = JenkinsSmiHash.combine(hash, firstTriggerCharacter.hashCode);
    hash = JenkinsSmiHash.combine(hash, lspHashCode(moreTriggerCharacter));
    return JenkinsSmiHash.finish(hash);
  }

  @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, dynamic> json) {
    final dynamicRegistration = json['dynamicRegistration'];
    return DocumentRangeFormattingClientCapabilities(
        dynamicRegistration: dynamicRegistration);
  }

  /// Whether formatting supports dynamic registration.
  final bool dynamicRegistration;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (dynamicRegistration != null) {
      __result['dynamicRegistration'] = dynamicRegistration;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('dynamicRegistration');
      try {
        if (obj['dynamicRegistration'] != null &&
            !(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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, dynamic> json) {
    if (DocumentRangeFormattingRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return DocumentRangeFormattingRegistrationOptions.fromJson(json);
    }
    final workDoneProgress = json['workDoneProgress'];
    return DocumentRangeFormattingOptions(workDoneProgress: workDoneProgress);
  }

  final bool workDoneProgress;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('workDoneProgress');
      try {
        if (obj['workDoneProgress'] != null &&
            !(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  DocumentRangeFormattingParams(
      {@required this.textDocument,
      @required this.range,
      @required this.options,
      this.workDoneToken}) {
    if (textDocument == null) {
      throw 'textDocument is required but was not provided';
    }
    if (range == null) {
      throw 'range is required but was not provided';
    }
    if (options == null) {
      throw 'options is required but was not provided';
    }
  }
  static DocumentRangeFormattingParams fromJson(Map<String, dynamic> json) {
    final textDocument = json['textDocument'] != null
        ? TextDocumentIdentifier.fromJson(json['textDocument'])
        : null;
    final range = json['range'] != null ? Range.fromJson(json['range']) : null;
    final options = json['options'] != null
        ? FormattingOptions.fromJson(json['options'])
        : null;
    final workDoneToken = json['workDoneToken'] is num
        ? Either2<num, String>.t1(json['workDoneToken'])
        : (json['workDoneToken'] is String
            ? Either2<num, String>.t2(json['workDoneToken'])
            : (json['workDoneToken'] == null
                ? null
                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
    return DocumentRangeFormattingParams(
        textDocument: textDocument,
        range: range,
        options: options,
        workDoneToken: workDoneToken);
  }

  /// The format options
  final FormattingOptions options;

  /// The range to format
  final Range range;

  /// The document to format.
  final TextDocumentIdentifier textDocument;

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['textDocument'] = textDocument?.toJson() ??
        (throw 'textDocument is required but was not set');
    __result['range'] =
        range?.toJson() ?? (throw 'range is required but was not set');
    __result['options'] =
        options?.toJson() ?? (throw 'options is required but was not set');
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['textDocument'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(TextDocumentIdentifier.canParse(obj['textDocument'], reporter))) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('range');
      try {
        if (!obj.containsKey('range')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['range'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(Range.canParse(obj['range'], reporter))) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('options');
      try {
        if (!obj.containsKey('options')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['options'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(FormattingOptions.canParse(obj['options'], reporter))) {
          reporter.reportError('must be of type FormattingOptions');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        if (obj['workDoneToken'] != null &&
            !((obj['workDoneToken'] is num ||
                obj['workDoneToken'] is String))) {
          reporter.reportError('must be of type Either2<num, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DocumentRangeFormattingParams');
      return false;
    }
  }

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, textDocument.hashCode);
    hash = JenkinsSmiHash.combine(hash, range.hashCode);
    hash = JenkinsSmiHash.combine(hash, options.hashCode);
    hash = JenkinsSmiHash.combine(hash, workDoneToken.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  DocumentRangeFormattingRegistrationOptions(
      {this.documentSelector, this.workDoneProgress});
  static DocumentRangeFormattingRegistrationOptions fromJson(
      Map<String, dynamic> json) {
    final documentSelector = json['documentSelector']
        ?.map((item) => item != null ? DocumentFilter.fromJson(item) : null)
        ?.cast<DocumentFilter>()
        ?.toList();
    final workDoneProgress = json['workDoneProgress'];
    return DocumentRangeFormattingRegistrationOptions(
        documentSelector: documentSelector, workDoneProgress: workDoneProgress);
  }

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['documentSelector'] = documentSelector;
    if (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(documentSelector));
    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

/// Represents programming constructs like variables, classes, interfaces etc.
/// that appear in a document. Document symbols can be hierarchical and they
/// have two ranges: one that encloses its definition and one that points to its
/// most interesting range, e.g. the range of an identifier.
class DocumentSymbol implements ToJsonable {
  static const jsonHandler =
      LspJsonHandler(DocumentSymbol.canParse, DocumentSymbol.fromJson);

  DocumentSymbol(
      {@required this.name,
      this.detail,
      @required this.kind,
      this.tags,
      this.deprecated,
      @required this.range,
      @required this.selectionRange,
      this.children}) {
    if (name == null) {
      throw 'name is required but was not provided';
    }
    if (kind == null) {
      throw 'kind is required but was not provided';
    }
    if (range == null) {
      throw 'range is required but was not provided';
    }
    if (selectionRange == null) {
      throw 'selectionRange is required but was not provided';
    }
  }
  static DocumentSymbol fromJson(Map<String, dynamic> json) {
    final name = json['name'];
    final detail = json['detail'];
    final kind =
        json['kind'] != null ? SymbolKind.fromJson(json['kind']) : null;
    final tags = json['tags']
        ?.map((item) => item != null ? SymbolTag.fromJson(item) : null)
        ?.cast<SymbolTag>()
        ?.toList();
    final deprecated = json['deprecated'];
    final range = json['range'] != null ? Range.fromJson(json['range']) : null;
    final selectionRange = json['selectionRange'] != null
        ? Range.fromJson(json['selectionRange'])
        : null;
    final children = json['children']
        ?.map((item) => item != null ? DocumentSymbol.fromJson(item) : null)
        ?.cast<DocumentSymbol>()
        ?.toList();
    return DocumentSymbol(
        name: name,
        detail: detail,
        kind: kind,
        tags: tags,
        deprecated: deprecated,
        range: range,
        selectionRange: selectionRange,
        children: children);
  }

  /// Children of this symbol, e.g. properties of a class.
  final List<DocumentSymbol> children;

  /// Indicates if this symbol is deprecated.
  ///  @deprecated Use tags instead
  final bool deprecated;

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

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

  /// The name of this symbol. Will be displayed in the user interface and
  /// therefore must not be an empty string or a string only consisting of white
  /// spaces.
  final String name;

  /// The range enclosing this symbol not including leading/trailing whitespace
  /// but everything else like comments. This information is typically used to
  /// determine if the clients cursor is inside the symbol to reveal in the
  /// symbol in the UI.
  final Range range;

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

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['name'] = name ?? (throw 'name is required but was not set');
    if (detail != null) {
      __result['detail'] = detail;
    }
    __result['kind'] =
        kind?.toJson() ?? (throw 'kind is required but was not set');
    if (tags != null) {
      __result['tags'] = tags.map((item) => item.toJson()).toList();
    }
    if (deprecated != null) {
      __result['deprecated'] = deprecated;
    }
    __result['range'] =
        range?.toJson() ?? (throw 'range is required but was not set');
    __result['selectionRange'] = selectionRange?.toJson() ??
        (throw 'selectionRange is required but was not set');
    if (children != null) {
      __result['children'] = children.map((item) => item.toJson()).toList();
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('name');
      try {
        if (!obj.containsKey('name')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['name'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['name'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('detail');
      try {
        if (obj['detail'] != null && !(obj['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;
        }
        if (obj['kind'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(SymbolKind.canParse(obj['kind'], reporter))) {
          reporter.reportError('must be of type SymbolKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('tags');
      try {
        if (obj['tags'] != null &&
            !((obj['tags'] is List &&
                (obj['tags']
                    .every((item) => SymbolTag.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<SymbolTag>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('deprecated');
      try {
        if (obj['deprecated'] != null && !(obj['deprecated'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('range');
      try {
        if (!obj.containsKey('range')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['range'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(Range.canParse(obj['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;
        }
        if (obj['selectionRange'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(Range.canParse(obj['selectionRange'], reporter))) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('children');
      try {
        if (obj['children'] != null &&
            !((obj['children'] is List &&
                (obj['children'].every(
                    (item) => DocumentSymbol.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<DocumentSymbol>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DocumentSymbol');
      return false;
    }
  }

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, name.hashCode);
    hash = JenkinsSmiHash.combine(hash, detail.hashCode);
    hash = JenkinsSmiHash.combine(hash, kind.hashCode);
    hash = JenkinsSmiHash.combine(hash, lspHashCode(tags));
    hash = JenkinsSmiHash.combine(hash, deprecated.hashCode);
    hash = JenkinsSmiHash.combine(hash, range.hashCode);
    hash = JenkinsSmiHash.combine(hash, selectionRange.hashCode);
    hash = JenkinsSmiHash.combine(hash, lspHashCode(children));
    return JenkinsSmiHash.finish(hash);
  }

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

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

  DocumentSymbolClientCapabilities(
      {this.dynamicRegistration,
      this.symbolKind,
      this.hierarchicalDocumentSymbolSupport,
      this.tagSupport,
      this.labelSupport});
  static DocumentSymbolClientCapabilities fromJson(Map<String, dynamic> json) {
    final dynamicRegistration = json['dynamicRegistration'];
    final symbolKind = json['symbolKind'] != null
        ? DocumentSymbolClientCapabilitiesSymbolKind.fromJson(
            json['symbolKind'])
        : null;
    final hierarchicalDocumentSymbolSupport =
        json['hierarchicalDocumentSymbolSupport'];
    final tagSupport = json['tagSupport'] != null
        ? DocumentSymbolClientCapabilitiesTagSupport.fromJson(
            json['tagSupport'])
        : null;
    final labelSupport = json['labelSupport'];
    return DocumentSymbolClientCapabilities(
        dynamicRegistration: dynamicRegistration,
        symbolKind: symbolKind,
        hierarchicalDocumentSymbolSupport: hierarchicalDocumentSymbolSupport,
        tagSupport: tagSupport,
        labelSupport: labelSupport);
  }

  /// Whether document symbol supports dynamic registration.
  final bool dynamicRegistration;

  /// The client supports hierarchical document symbols.
  final bool hierarchicalDocumentSymbolSupport;

  /// The client supports an additional label presented in the UI when
  /// registering a document symbol provider.
  ///  @since 3.16.0
  final bool labelSupport;

  /// Specific capabilities for the `SymbolKind` in the
  /// `textDocument/documentSymbol` request.
  final DocumentSymbolClientCapabilitiesSymbolKind symbolKind;

  /// The client supports tags on `SymbolInformation`. Tags are supported on
  /// `DocumentSymbol` if `hierarchicalDocumentSymbolSupport` is set to true.
  /// Clients supporting tags have to handle unknown tags gracefully.
  ///  @since 3.16.0
  final DocumentSymbolClientCapabilitiesTagSupport tagSupport;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (dynamicRegistration != null) {
      __result['dynamicRegistration'] = dynamicRegistration;
    }
    if (symbolKind != null) {
      __result['symbolKind'] = symbolKind.toJson();
    }
    if (hierarchicalDocumentSymbolSupport != null) {
      __result['hierarchicalDocumentSymbolSupport'] =
          hierarchicalDocumentSymbolSupport;
    }
    if (tagSupport != null) {
      __result['tagSupport'] = tagSupport.toJson();
    }
    if (labelSupport != null) {
      __result['labelSupport'] = labelSupport;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('dynamicRegistration');
      try {
        if (obj['dynamicRegistration'] != null &&
            !(obj['dynamicRegistration'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('symbolKind');
      try {
        if (obj['symbolKind'] != null &&
            !(DocumentSymbolClientCapabilitiesSymbolKind.canParse(
                obj['symbolKind'], reporter))) {
          reporter.reportError(
              'must be of type DocumentSymbolClientCapabilitiesSymbolKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('hierarchicalDocumentSymbolSupport');
      try {
        if (obj['hierarchicalDocumentSymbolSupport'] != null &&
            !(obj['hierarchicalDocumentSymbolSupport'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('tagSupport');
      try {
        if (obj['tagSupport'] != null &&
            !(DocumentSymbolClientCapabilitiesTagSupport.canParse(
                obj['tagSupport'], reporter))) {
          reporter.reportError(
              'must be of type DocumentSymbolClientCapabilitiesTagSupport');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('labelSupport');
      try {
        if (obj['labelSupport'] != null && !(obj['labelSupport'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DocumentSymbolClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is DocumentSymbolClientCapabilities &&
        other.runtimeType == DocumentSymbolClientCapabilities) {
      return dynamicRegistration == other.dynamicRegistration &&
          symbolKind == other.symbolKind &&
          hierarchicalDocumentSymbolSupport ==
              other.hierarchicalDocumentSymbolSupport &&
          tagSupport == other.tagSupport &&
          labelSupport == other.labelSupport &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode);
    hash = JenkinsSmiHash.combine(hash, symbolKind.hashCode);
    hash = JenkinsSmiHash.combine(
        hash, hierarchicalDocumentSymbolSupport.hashCode);
    hash = JenkinsSmiHash.combine(hash, tagSupport.hashCode);
    hash = JenkinsSmiHash.combine(hash, labelSupport.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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, dynamic> json) {
    final valueSet = json['valueSet']
        ?.map((item) => item != null ? SymbolKind.fromJson(item) : null)
        ?.cast<SymbolKind>()
        ?.toList();
    return DocumentSymbolClientCapabilitiesSymbolKind(valueSet: valueSet);
  }

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    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, dynamic>) {
      reporter.push('valueSet');
      try {
        if (obj['valueSet'] != null &&
            !((obj['valueSet'] is List &&
                (obj['valueSet']
                    .every((item) => SymbolKind.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<SymbolKind>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type DocumentSymbolClientCapabilitiesSymbolKind');
      return false;
    }
  }

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(valueSet));
    return JenkinsSmiHash.finish(hash);
  }

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

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

  DocumentSymbolClientCapabilitiesTagSupport({@required this.valueSet}) {
    if (valueSet == null) {
      throw 'valueSet is required but was not provided';
    }
  }
  static DocumentSymbolClientCapabilitiesTagSupport fromJson(
      Map<String, dynamic> json) {
    final valueSet = json['valueSet']
        ?.map((item) => item != null ? SymbolTag.fromJson(item) : null)
        ?.cast<SymbolTag>()
        ?.toList();
    return DocumentSymbolClientCapabilitiesTagSupport(valueSet: valueSet);
  }

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['valueSet'] = valueSet?.map((item) => item.toJson())?.toList() ??
        (throw 'valueSet is required but was not set');
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(valueSet));
    return JenkinsSmiHash.finish(hash);
  }

  @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, dynamic> json) {
    if (DocumentSymbolRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentSymbolRegistrationOptions.fromJson(json);
    }
    final label = json['label'];
    final workDoneProgress = json['workDoneProgress'];
    return DocumentSymbolOptions(
        label: label, workDoneProgress: workDoneProgress);
  }

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    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, dynamic>) {
      reporter.push('label');
      try {
        if (obj['label'] != null && !(obj['label'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        if (obj['workDoneProgress'] != null &&
            !(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, label.hashCode);
    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  DocumentSymbolParams(
      {@required this.textDocument,
      this.workDoneToken,
      this.partialResultToken}) {
    if (textDocument == null) {
      throw 'textDocument is required but was not provided';
    }
  }
  static DocumentSymbolParams fromJson(Map<String, dynamic> json) {
    final textDocument = json['textDocument'] != null
        ? TextDocumentIdentifier.fromJson(json['textDocument'])
        : null;
    final workDoneToken = json['workDoneToken'] is num
        ? Either2<num, String>.t1(json['workDoneToken'])
        : (json['workDoneToken'] is String
            ? Either2<num, String>.t2(json['workDoneToken'])
            : (json['workDoneToken'] == null
                ? null
                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
    final partialResultToken = json['partialResultToken'] is num
        ? Either2<num, String>.t1(json['partialResultToken'])
        : (json['partialResultToken'] is String
            ? Either2<num, String>.t2(json['partialResultToken'])
            : (json['partialResultToken'] == null
                ? null
                : (throw '''${json['partialResultToken']} was not one of (num, String)''')));
    return DocumentSymbolParams(
        textDocument: textDocument,
        workDoneToken: workDoneToken,
        partialResultToken: partialResultToken);
  }

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

  /// The text document.
  final TextDocumentIdentifier textDocument;

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['textDocument'] = textDocument?.toJson() ??
        (throw 'textDocument is required but was not set');
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    if (partialResultToken != null) {
      __result['partialResultToken'] = partialResultToken;
    }
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, textDocument.hashCode);
    hash = JenkinsSmiHash.combine(hash, workDoneToken.hashCode);
    hash = JenkinsSmiHash.combine(hash, partialResultToken.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  DocumentSymbolRegistrationOptions(
      {this.documentSelector, this.label, this.workDoneProgress});
  static DocumentSymbolRegistrationOptions fromJson(Map<String, dynamic> json) {
    final documentSelector = json['documentSelector']
        ?.map((item) => item != null ? DocumentFilter.fromJson(item) : null)
        ?.cast<DocumentFilter>()
        ?.toList();
    final label = json['label'];
    final workDoneProgress = json['workDoneProgress'];
    return DocumentSymbolRegistrationOptions(
        documentSelector: documentSelector,
        label: label,
        workDoneProgress: workDoneProgress);
  }

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

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __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, dynamic>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['documentSelector'] != null &&
            !((obj['documentSelector'] is List &&
                (obj['documentSelector'].every(
                    (item) => DocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<DocumentFilter>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('label');
      try {
        if (obj['label'] != null && !(obj['label'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        if (obj['workDoneProgress'] != null &&
            !(obj['workDoneProgress'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type DocumentSymbolRegistrationOptions');
      return false;
    }
  }

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(documentSelector));
    hash = JenkinsSmiHash.combine(hash, label.hashCode);
    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  final num _value;

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

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

  /// This is the start range of JSON RPC reserved error codes. It doesn't
  /// denote a real error code. No LSP error codes should be defined between the
  /// start and end range. For backwards compatibility the
  /// `ServerNotInitialized` and the `UnknownErrorCode` are left in the range.
  ///  @since 3.16.0
  static const jsonrpcReservedErrorRangeStart = ErrorCodes(-32099);
  static const ServerNotInitialized = ErrorCodes(-32002);
  static const UnknownErrorCode = ErrorCodes(-32001);

  /// This is the start range of JSON RPC reserved error codes. It doesn't
  /// denote a real error code.
  static const jsonrpcReservedErrorRangeEnd = ErrorCodes(-32000);

  /// This is the start range of LSP reserved error codes. It doesn't denote a
  /// real error code.
  ///  @since 3.16.0
  static const lspReservedErrorRangeStart = ErrorCodes(-32899);
  static const ContentModified = ErrorCodes(-32801);
  static const RequestCancelled = ErrorCodes(-32800);

  /// This is the end range of LSP reserved error codes. It doesn't denote a
  /// real error code.
  ///  @since 3.16.0
  static const lspReservedErrorRangeEnd = ErrorCodes(-32800);

  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

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

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

  ExecuteCommandClientCapabilities({this.dynamicRegistration});
  static ExecuteCommandClientCapabilities fromJson(Map<String, dynamic> json) {
    final dynamicRegistration = json['dynamicRegistration'];
    return ExecuteCommandClientCapabilities(
        dynamicRegistration: dynamicRegistration);
  }

  /// Execute command supports dynamic registration.
  final bool dynamicRegistration;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (dynamicRegistration != null) {
      __result['dynamicRegistration'] = dynamicRegistration;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('dynamicRegistration');
      try {
        if (obj['dynamicRegistration'] != null &&
            !(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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}) {
    if (commands == null) {
      throw 'commands is required but was not provided';
    }
  }
  static ExecuteCommandOptions fromJson(Map<String, dynamic> json) {
    if (ExecuteCommandRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return ExecuteCommandRegistrationOptions.fromJson(json);
    }
    final commands =
        json['commands']?.map((item) => item)?.cast<String>()?.toList();
    final workDoneProgress = json['workDoneProgress'];
    return ExecuteCommandOptions(
        commands: commands, workDoneProgress: workDoneProgress);
  }

  /// The commands to be executed on the server
  final List<String> commands;
  final bool workDoneProgress;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['commands'] =
        commands ?? (throw 'commands is required but was not set');
    if (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('commands');
      try {
        if (!obj.containsKey('commands')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['commands'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!((obj['commands'] is List &&
            (obj['commands'].every((item) => item is String))))) {
          reporter.reportError('must be of type List<String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        if (obj['workDoneProgress'] != null &&
            !(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(commands));
    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  ExecuteCommandParams(
      {@required this.command, this.arguments, this.workDoneToken}) {
    if (command == null) {
      throw 'command is required but was not provided';
    }
  }
  static ExecuteCommandParams fromJson(Map<String, dynamic> json) {
    final command = json['command'];
    final arguments =
        json['arguments']?.map((item) => item)?.cast<dynamic>()?.toList();
    final workDoneToken = json['workDoneToken'] is num
        ? Either2<num, String>.t1(json['workDoneToken'])
        : (json['workDoneToken'] is String
            ? Either2<num, String>.t2(json['workDoneToken'])
            : (json['workDoneToken'] == null
                ? null
                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
    return ExecuteCommandParams(
        command: command, arguments: arguments, workDoneToken: workDoneToken);
  }

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

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

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['command'] =
        command ?? (throw 'command is required but was not set');
    if (arguments != null) {
      __result['arguments'] = arguments;
    }
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, command.hashCode);
    hash = JenkinsSmiHash.combine(hash, lspHashCode(arguments));
    hash = JenkinsSmiHash.combine(hash, workDoneToken.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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}) {
    if (commands == null) {
      throw 'commands is required but was not provided';
    }
  }
  static ExecuteCommandRegistrationOptions fromJson(Map<String, dynamic> json) {
    final commands =
        json['commands']?.map((item) => item)?.cast<String>()?.toList();
    final workDoneProgress = json['workDoneProgress'];
    return ExecuteCommandRegistrationOptions(
        commands: commands, workDoneProgress: workDoneProgress);
  }

  /// The commands to be executed on the server
  final List<String> commands;
  final bool workDoneProgress;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['commands'] =
        commands ?? (throw 'commands is required but was not set');
    if (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('commands');
      try {
        if (!obj.containsKey('commands')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['commands'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!((obj['commands'] is List &&
            (obj['commands'].every((item) => item is String))))) {
          reporter.reportError('must be of type List<String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        if (obj['workDoneProgress'] != null &&
            !(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(commands));
    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  final String _value;

  static bool canParse(Object obj, LspJsonReporter reporter) {
    switch (obj) {
      case 'abort':
      case 'transactional':
      case 'textOnlyTransactional':
      case 'undo':
        return true;
    }
    return false;
  }

  /// Applying the workspace change is simply aborted if one of the changes
  /// provided fails. All operations executed before the failing operation stay
  /// executed.
  static const Abort = FailureHandlingKind._('abort');

  /// All operations are executed transactional. That means they either all
  /// succeed or no changes at all are applied to the workspace.
  static const Transactional = FailureHandlingKind._('transactional');

  /// If the workspace edit contains only textual file changes they are executed
  /// transactional. If resource changes (create, rename or delete file) are
  /// part of the change the failure handling strategy is abort.
  static const TextOnlyTransactional =
      FailureHandlingKind._('textOnlyTransactional');

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

  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

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

/// The file event type.
class FileChangeType {
  const FileChangeType(this._value);
  const FileChangeType.fromJson(this._value);

  final num _value;

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

  /// The file got created.
  static const Created = FileChangeType(1);

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

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

  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

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

/// Represents information on a file/folder create.
///  @since 3.16.0
class FileCreate implements ToJsonable {
  static const jsonHandler =
      LspJsonHandler(FileCreate.canParse, FileCreate.fromJson);

  FileCreate({@required this.uri}) {
    if (uri == null) {
      throw 'uri is required but was not provided';
    }
  }
  static FileCreate fromJson(Map<String, dynamic> json) {
    final uri = json['uri'];
    return FileCreate(uri: uri);
  }

  /// A file:// URI for the location of the file/folder being created.
  final String uri;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['uri'] = uri ?? (throw 'uri is required but was not set');
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('uri');
      try {
        if (!obj.containsKey('uri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['uri'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, uri.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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}) {
    if (uri == null) {
      throw 'uri is required but was not provided';
    }
  }
  static FileDelete fromJson(Map<String, dynamic> json) {
    final uri = json['uri'];
    return FileDelete(uri: uri);
  }

  /// A file:// URI for the location of the file/folder being deleted.
  final String uri;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['uri'] = uri ?? (throw 'uri is required but was not set');
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('uri');
      try {
        if (!obj.containsKey('uri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['uri'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, uri.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

/// An event describing a file change.
class FileEvent implements ToJsonable {
  static const jsonHandler =
      LspJsonHandler(FileEvent.canParse, FileEvent.fromJson);

  FileEvent({@required this.uri, @required this.type}) {
    if (uri == null) {
      throw 'uri is required but was not provided';
    }
    if (type == null) {
      throw 'type is required but was not provided';
    }
  }
  static FileEvent fromJson(Map<String, dynamic> json) {
    final uri = json['uri'];
    final type = json['type'];
    return FileEvent(uri: uri, type: type);
  }

  /// The change type.
  final num type;

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['uri'] = uri ?? (throw 'uri is required but was not set');
    __result['type'] = type ?? (throw 'type is required but was not set');
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, uri.hashCode);
    hash = JenkinsSmiHash.combine(hash, type.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

/// A filter to describe in which file operation requests or notifications the
/// server is interested in.
///  @since 3.16.0
class FileOperationFilter implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
      FileOperationFilter.canParse, FileOperationFilter.fromJson);

  FileOperationFilter({this.scheme, @required this.pattern}) {
    if (pattern == null) {
      throw 'pattern is required but was not provided';
    }
  }
  static FileOperationFilter fromJson(Map<String, dynamic> json) {
    final scheme = json['scheme'];
    final pattern = json['pattern'] != null
        ? FileOperationPattern.fromJson(json['pattern'])
        : null;
    return FileOperationFilter(scheme: scheme, pattern: pattern);
  }

  /// The actual file operation pattern.
  final FileOperationPattern pattern;

  /// A Uri like `file` or `untitled`.
  final String scheme;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (scheme != null) {
      __result['scheme'] = scheme;
    }
    __result['pattern'] =
        pattern?.toJson() ?? (throw 'pattern is required but was not set');
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, scheme.hashCode);
    hash = JenkinsSmiHash.combine(hash, pattern.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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}) {
    if (glob == null) {
      throw 'glob is required but was not provided';
    }
  }
  static FileOperationPattern fromJson(Map<String, dynamic> json) {
    final glob = json['glob'];
    final matches = json['matches'] != null
        ? FileOperationPatternKind.fromJson(json['matches'])
        : null;
    final options = json['options'] != null
        ? FileOperationPatternOptions.fromJson(json['options'])
        : null;
    return FileOperationPattern(glob: glob, matches: matches, options: options);
  }

  /// The glob pattern to match. Glob patterns can have the following syntax:
  /// - `*` to match one or more characters in a path segment
  /// - `?` to match on one character in a path segment
  /// - `**` to match any number of path segments, including none
  /// - `{}` to group conditions (e.g. `**​/*.{ts,js}` matches all TypeScript
  ///   and JavaScript files)
  /// - `[]` to declare a range of characters to match in a path segment
  ///   (e.g., `example.[0-9]` to match on `example.0`, `example.1`, …)
  /// - `[!...]` to negate a range of characters to match in a path segment
  ///   (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but
  ///   not `example.0`)
  final String glob;

  /// Whether to match files or folders with this pattern.
  ///
  /// Matches both if undefined.
  final FileOperationPatternKind matches;

  /// Additional options used during matching.
  final FileOperationPatternOptions options;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['glob'] = glob ?? (throw 'glob is required but was not set');
    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, dynamic>) {
      reporter.push('glob');
      try {
        if (!obj.containsKey('glob')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['glob'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['glob'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('matches');
      try {
        if (obj['matches'] != null &&
            !(FileOperationPatternKind.canParse(obj['matches'], reporter))) {
          reporter.reportError('must be of type FileOperationPatternKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('options');
      try {
        if (obj['options'] != null &&
            !(FileOperationPatternOptions.canParse(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, glob.hashCode);
    hash = JenkinsSmiHash.combine(hash, matches.hashCode);
    hash = JenkinsSmiHash.combine(hash, options.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

/// A pattern kind describing if a glob pattern matches a file a folder or both.
///  @since 3.16.0
class FileOperationPatternKind {
  const FileOperationPatternKind(this._value);
  const FileOperationPatternKind.fromJson(this._value);

  final String _value;

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

  /// The pattern matches a file only.
  static const file = FileOperationPatternKind(r'file');

  /// The pattern matches a folder only.
  static const folder = FileOperationPatternKind(r'folder');

  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

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

/// Matching options for the file operation pattern.
///  @since 3.16.0
class FileOperationPatternOptions implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
      FileOperationPatternOptions.canParse,
      FileOperationPatternOptions.fromJson);

  FileOperationPatternOptions({this.ignoreCase});
  static FileOperationPatternOptions fromJson(Map<String, dynamic> json) {
    final ignoreCase = json['ignoreCase'];
    return FileOperationPatternOptions(ignoreCase: ignoreCase);
  }

  /// The pattern should be matched ignoring casing.
  final bool ignoreCase;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (ignoreCase != null) {
      __result['ignoreCase'] = ignoreCase;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('ignoreCase');
      try {
        if (obj['ignoreCase'] != null && !(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, ignoreCase.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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}) {
    if (filters == null) {
      throw 'filters is required but was not provided';
    }
  }
  static FileOperationRegistrationOptions fromJson(Map<String, dynamic> json) {
    final filters = json['filters']
        ?.map(
            (item) => item != null ? FileOperationFilter.fromJson(item) : null)
        ?.cast<FileOperationFilter>()
        ?.toList();
    return FileOperationRegistrationOptions(filters: filters);
  }

  /// The actual filters.
  final List<FileOperationFilter> filters;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['filters'] = filters?.map((item) => item.toJson())?.toList() ??
        (throw 'filters is required but was not set');
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('filters');
      try {
        if (!obj.containsKey('filters')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['filters'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!((obj['filters'] is List &&
            (obj['filters'].every(
                (item) => FileOperationFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<FileOperationFilter>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type FileOperationRegistrationOptions');
      return false;
    }
  }

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(filters));
    return JenkinsSmiHash.finish(hash);
  }

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

/// Represents information on a file/folder rename.
///  @since 3.16.0
class FileRename implements ToJsonable {
  static const jsonHandler =
      LspJsonHandler(FileRename.canParse, FileRename.fromJson);

  FileRename({@required this.oldUri, @required this.newUri}) {
    if (oldUri == null) {
      throw 'oldUri is required but was not provided';
    }
    if (newUri == null) {
      throw 'newUri is required but was not provided';
    }
  }
  static FileRename fromJson(Map<String, dynamic> json) {
    final oldUri = json['oldUri'];
    final newUri = json['newUri'];
    return FileRename(oldUri: oldUri, newUri: newUri);
  }

  /// A file:// URI for the new location of the file/folder being renamed.
  final String newUri;

  /// A file:// URI for the original location of the file/folder being renamed.
  final String oldUri;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['oldUri'] = oldUri ?? (throw 'oldUri is required but was not set');
    __result['newUri'] = newUri ?? (throw 'newUri is required but was not set');
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, oldUri.hashCode);
    hash = JenkinsSmiHash.combine(hash, newUri.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  FileSystemWatcher({@required this.globPattern, this.kind}) {
    if (globPattern == null) {
      throw 'globPattern is required but was not provided';
    }
  }
  static FileSystemWatcher fromJson(Map<String, dynamic> json) {
    final globPattern = json['globPattern'];
    final kind = json['kind'] != null ? WatchKind.fromJson(json['kind']) : null;
    return FileSystemWatcher(globPattern: globPattern, kind: kind);
  }

  /// The  glob pattern to watch.
  ///
  /// Glob patterns can have the following syntax:
  /// - `*` to match one or more characters in a path segment
  /// - `?` to match on one character in a path segment
  /// - `**` to match any number of path segments, including none
  /// - `{}` to group conditions (e.g. `**​/*.{ts,js}` matches all TypeScript
  ///   and JavaScript files)
  /// - `[]` to declare a range of characters to match in a path segment
  ///   (e.g., `example.[0-9]` to match on `example.0`, `example.1`, …)
  /// - `[!...]` to negate a range of characters to match in a path segment
  ///   (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but not
  ///   `example.0`)
  final String globPattern;

  /// The kind of events of interest. If omitted it defaults to WatchKind.Create
  /// | WatchKind.Change | WatchKind.Delete which is 7.
  final WatchKind kind;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['globPattern'] =
        globPattern ?? (throw 'globPattern is required but was not set');
    if (kind != null) {
      __result['kind'] = kind.toJson();
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('globPattern');
      try {
        if (!obj.containsKey('globPattern')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['globPattern'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['globPattern'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('kind');
      try {
        if (obj['kind'] != null &&
            !(WatchKind.canParse(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, globPattern.hashCode);
    hash = JenkinsSmiHash.combine(hash, kind.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

/// Represents a folding range. To be valid, start and end line must be bigger
/// than zero and smaller than the number of lines in the document. Clients are
/// free to ignore invalid ranges.
class FoldingRange implements ToJsonable {
  static const jsonHandler =
      LspJsonHandler(FoldingRange.canParse, FoldingRange.fromJson);

  FoldingRange(
      {@required this.startLine,
      this.startCharacter,
      @required this.endLine,
      this.endCharacter,
      this.kind}) {
    if (startLine == null) {
      throw 'startLine is required but was not provided';
    }
    if (endLine == null) {
      throw 'endLine is required but was not provided';
    }
  }
  static FoldingRange fromJson(Map<String, dynamic> json) {
    final startLine = json['startLine'];
    final startCharacter = json['startCharacter'];
    final endLine = json['endLine'];
    final endCharacter = json['endCharacter'];
    final kind =
        json['kind'] != null ? FoldingRangeKind.fromJson(json['kind']) : null;
    return FoldingRange(
        startLine: startLine,
        startCharacter: startCharacter,
        endLine: endLine,
        endCharacter: endCharacter,
        kind: kind);
  }

  /// The zero-based character offset before the folded range ends. If not
  /// defined, defaults to the length of the end line.
  final num 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 num 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 num 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 num startLine;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['startLine'] =
        startLine ?? (throw 'startLine is required but was not set');
    if (startCharacter != null) {
      __result['startCharacter'] = startCharacter;
    }
    __result['endLine'] =
        endLine ?? (throw 'endLine is required but was not set');
    if (endCharacter != null) {
      __result['endCharacter'] = endCharacter;
    }
    if (kind != null) {
      __result['kind'] = kind.toJson();
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('startLine');
      try {
        if (!obj.containsKey('startLine')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['startLine'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['startLine'] is num)) {
          reporter.reportError('must be of type num');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('startCharacter');
      try {
        if (obj['startCharacter'] != null && !(obj['startCharacter'] is num)) {
          reporter.reportError('must be of type num');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('endLine');
      try {
        if (!obj.containsKey('endLine')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['endLine'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['endLine'] is num)) {
          reporter.reportError('must be of type num');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('endCharacter');
      try {
        if (obj['endCharacter'] != null && !(obj['endCharacter'] is num)) {
          reporter.reportError('must be of type num');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('kind');
      try {
        if (obj['kind'] != null &&
            !(FoldingRangeKind.canParse(obj['kind'], reporter))) {
          reporter.reportError('must be of type FoldingRangeKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type FoldingRange');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is FoldingRange && other.runtimeType == FoldingRange) {
      return startLine == other.startLine &&
          startCharacter == other.startCharacter &&
          endLine == other.endLine &&
          endCharacter == other.endCharacter &&
          kind == other.kind &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, startLine.hashCode);
    hash = JenkinsSmiHash.combine(hash, startCharacter.hashCode);
    hash = JenkinsSmiHash.combine(hash, endLine.hashCode);
    hash = JenkinsSmiHash.combine(hash, endCharacter.hashCode);
    hash = JenkinsSmiHash.combine(hash, kind.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  FoldingRangeClientCapabilities(
      {this.dynamicRegistration, this.rangeLimit, this.lineFoldingOnly});
  static FoldingRangeClientCapabilities fromJson(Map<String, dynamic> json) {
    final dynamicRegistration = json['dynamicRegistration'];
    final rangeLimit = json['rangeLimit'];
    final lineFoldingOnly = json['lineFoldingOnly'];
    return FoldingRangeClientCapabilities(
        dynamicRegistration: dynamicRegistration,
        rangeLimit: rangeLimit,
        lineFoldingOnly: lineFoldingOnly);
  }

  /// Whether implementation supports dynamic registration for folding range
  /// providers. If this is set to `true` the client supports the new
  /// `FoldingRangeRegistrationOptions` return value for the corresponding
  /// server capability as well.
  final bool dynamicRegistration;

  /// If set, the client signals that it only supports folding complete lines.
  /// If set, client will ignore specified `startCharacter` and `endCharacter`
  /// properties in a FoldingRange.
  final bool lineFoldingOnly;

  /// The maximum number of folding ranges that the client prefers to receive
  /// per document. The value serves as a hint, servers are free to follow the
  /// limit.
  final num rangeLimit;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (dynamicRegistration != null) {
      __result['dynamicRegistration'] = dynamicRegistration;
    }
    if (rangeLimit != null) {
      __result['rangeLimit'] = rangeLimit;
    }
    if (lineFoldingOnly != null) {
      __result['lineFoldingOnly'] = lineFoldingOnly;
    }
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode);
    hash = JenkinsSmiHash.combine(hash, rangeLimit.hashCode);
    hash = JenkinsSmiHash.combine(hash, lineFoldingOnly.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

/// Enum of known range kinds
class FoldingRangeKind {
  const FoldingRangeKind(this._value);
  const FoldingRangeKind.fromJson(this._value);

  final String _value;

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

  /// Folding range for a comment
  static const Comment = FoldingRangeKind(r'comment');

  /// Folding range for a imports or includes
  static const Imports = FoldingRangeKind(r'imports');

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

  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

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

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

  FoldingRangeOptions({this.workDoneProgress});
  static FoldingRangeOptions fromJson(Map<String, dynamic> json) {
    if (FoldingRangeRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return FoldingRangeRegistrationOptions.fromJson(json);
    }
    final workDoneProgress = json['workDoneProgress'];
    return FoldingRangeOptions(workDoneProgress: workDoneProgress);
  }

  final bool workDoneProgress;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('workDoneProgress');
      try {
        if (obj['workDoneProgress'] != null &&
            !(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  FoldingRangeParams(
      {@required this.textDocument,
      this.workDoneToken,
      this.partialResultToken}) {
    if (textDocument == null) {
      throw 'textDocument is required but was not provided';
    }
  }
  static FoldingRangeParams fromJson(Map<String, dynamic> json) {
    final textDocument = json['textDocument'] != null
        ? TextDocumentIdentifier.fromJson(json['textDocument'])
        : null;
    final workDoneToken = json['workDoneToken'] is num
        ? Either2<num, String>.t1(json['workDoneToken'])
        : (json['workDoneToken'] is String
            ? Either2<num, String>.t2(json['workDoneToken'])
            : (json['workDoneToken'] == null
                ? null
                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
    final partialResultToken = json['partialResultToken'] is num
        ? Either2<num, String>.t1(json['partialResultToken'])
        : (json['partialResultToken'] is String
            ? Either2<num, String>.t2(json['partialResultToken'])
            : (json['partialResultToken'] == null
                ? null
                : (throw '''${json['partialResultToken']} was not one of (num, String)''')));
    return FoldingRangeParams(
        textDocument: textDocument,
        workDoneToken: workDoneToken,
        partialResultToken: partialResultToken);
  }

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

  /// The text document.
  final TextDocumentIdentifier textDocument;

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['textDocument'] = textDocument?.toJson() ??
        (throw 'textDocument is required but was not set');
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    if (partialResultToken != null) {
      __result['partialResultToken'] = partialResultToken;
    }
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, textDocument.hashCode);
    hash = JenkinsSmiHash.combine(hash, workDoneToken.hashCode);
    hash = JenkinsSmiHash.combine(hash, partialResultToken.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  FoldingRangeRegistrationOptions(
      {this.documentSelector, this.workDoneProgress, this.id});
  static FoldingRangeRegistrationOptions fromJson(Map<String, dynamic> json) {
    final documentSelector = json['documentSelector']
        ?.map((item) => item != null ? DocumentFilter.fromJson(item) : null)
        ?.cast<DocumentFilter>()
        ?.toList();
    final workDoneProgress = json['workDoneProgress'];
    final id = json['id'];
    return FoldingRangeRegistrationOptions(
        documentSelector: documentSelector,
        workDoneProgress: workDoneProgress,
        id: id);
  }

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

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['documentSelector'] = documentSelector;
    if (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    if (id != null) {
      __result['id'] = id;
    }
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(documentSelector));
    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
    hash = JenkinsSmiHash.combine(hash, id.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

/// Value-object describing what options formatting should use.
class FormattingOptions implements ToJsonable {
  static const jsonHandler =
      LspJsonHandler(FormattingOptions.canParse, FormattingOptions.fromJson);

  FormattingOptions(
      {@required this.tabSize,
      @required this.insertSpaces,
      this.trimTrailingWhitespace,
      this.insertFinalNewline,
      this.trimFinalNewlines}) {
    if (tabSize == null) {
      throw 'tabSize is required but was not provided';
    }
    if (insertSpaces == null) {
      throw 'insertSpaces is required but was not provided';
    }
  }
  static FormattingOptions fromJson(Map<String, dynamic> json) {
    final tabSize = json['tabSize'];
    final insertSpaces = json['insertSpaces'];
    final trimTrailingWhitespace = json['trimTrailingWhitespace'];
    final insertFinalNewline = json['insertFinalNewline'];
    final trimFinalNewlines = json['trimFinalNewlines'];
    return FormattingOptions(
        tabSize: tabSize,
        insertSpaces: insertSpaces,
        trimTrailingWhitespace: trimTrailingWhitespace,
        insertFinalNewline: insertFinalNewline,
        trimFinalNewlines: trimFinalNewlines);
  }

  /// Insert a newline character at the end of the file if one does not exist.
  ///  @since 3.15.0
  final bool insertFinalNewline;

  /// Prefer spaces over tabs.
  final bool insertSpaces;

  /// Size of a tab in spaces.
  final num tabSize;

  /// Trim all newlines after the final newline at the end of the file.
  ///  @since 3.15.0
  final bool trimFinalNewlines;

  /// Trim trailing whitespace on a line.
  ///  @since 3.15.0
  final bool trimTrailingWhitespace;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['tabSize'] =
        tabSize ?? (throw 'tabSize is required but was not set');
    __result['insertSpaces'] =
        insertSpaces ?? (throw 'insertSpaces is required but was not set');
    if (trimTrailingWhitespace != null) {
      __result['trimTrailingWhitespace'] = trimTrailingWhitespace;
    }
    if (insertFinalNewline != null) {
      __result['insertFinalNewline'] = insertFinalNewline;
    }
    if (trimFinalNewlines != null) {
      __result['trimFinalNewlines'] = trimFinalNewlines;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('tabSize');
      try {
        if (!obj.containsKey('tabSize')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['tabSize'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['tabSize'] is num)) {
          reporter.reportError('must be of type num');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('insertSpaces');
      try {
        if (!obj.containsKey('insertSpaces')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['insertSpaces'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['insertSpaces'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('trimTrailingWhitespace');
      try {
        if (obj['trimTrailingWhitespace'] != null &&
            !(obj['trimTrailingWhitespace'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('insertFinalNewline');
      try {
        if (obj['insertFinalNewline'] != null &&
            !(obj['insertFinalNewline'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('trimFinalNewlines');
      try {
        if (obj['trimFinalNewlines'] != null &&
            !(obj['trimFinalNewlines'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type FormattingOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is FormattingOptions && other.runtimeType == FormattingOptions) {
      return tabSize == other.tabSize &&
          insertSpaces == other.insertSpaces &&
          trimTrailingWhitespace == other.trimTrailingWhitespace &&
          insertFinalNewline == other.insertFinalNewline &&
          trimFinalNewlines == other.trimFinalNewlines &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, tabSize.hashCode);
    hash = JenkinsSmiHash.combine(hash, insertSpaces.hashCode);
    hash = JenkinsSmiHash.combine(hash, trimTrailingWhitespace.hashCode);
    hash = JenkinsSmiHash.combine(hash, insertFinalNewline.hashCode);
    hash = JenkinsSmiHash.combine(hash, trimFinalNewlines.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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}) {
    if (contents == null) {
      throw 'contents is required but was not provided';
    }
  }
  static Hover fromJson(Map<String, dynamic> json) {
    final contents = json['contents'] is String
        ? Either2<String, MarkupContent>.t1(json['contents'])
        : (MarkupContent.canParse(json['contents'], nullLspJsonReporter)
            ? Either2<String, MarkupContent>.t2(json['contents'] != null
                ? MarkupContent.fromJson(json['contents'])
                : null)
            : (throw '''${json['contents']} was not one of (String, MarkupContent)'''));
    final range = json['range'] != null ? Range.fromJson(json['range']) : null;
    return Hover(contents: contents, range: range);
  }

  /// The hover's content
  final Either2<String, MarkupContent> contents;

  /// An optional range is a range inside a text document that is used to
  /// visualize a hover, e.g. by changing the background color.
  final Range range;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['contents'] =
        contents ?? (throw 'contents is required but was not set');
    if (range != null) {
      __result['range'] = range.toJson();
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('contents');
      try {
        if (!obj.containsKey('contents')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['contents'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!((obj['contents'] is String ||
            MarkupContent.canParse(obj['contents'], reporter)))) {
          reporter
              .reportError('must be of type Either2<String, MarkupContent>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('range');
      try {
        if (obj['range'] != null && !(Range.canParse(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, contents.hashCode);
    hash = JenkinsSmiHash.combine(hash, range.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  HoverClientCapabilities({this.dynamicRegistration, this.contentFormat});
  static HoverClientCapabilities fromJson(Map<String, dynamic> json) {
    final dynamicRegistration = json['dynamicRegistration'];
    final contentFormat = json['contentFormat']
        ?.map((item) => item != null ? MarkupKind.fromJson(item) : null)
        ?.cast<MarkupKind>()
        ?.toList();
    return HoverClientCapabilities(
        dynamicRegistration: dynamicRegistration, contentFormat: contentFormat);
  }

  /// Client supports the follow content formats if the content property refers
  /// to a `literal of type MarkupContent`. The order describes the preferred
  /// format of the client.
  final List<MarkupKind> contentFormat;

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (dynamicRegistration != null) {
      __result['dynamicRegistration'] = dynamicRegistration;
    }
    if (contentFormat != null) {
      __result['contentFormat'] =
          contentFormat.map((item) => item.toJson()).toList();
    }
    return __result;
  }

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

  @override
  bool operator ==(Object other) {
    if (other is HoverClientCapabilities &&
        other.runtimeType == HoverClientCapabilities) {
      return dynamicRegistration == other.dynamicRegistration &&
          listEqual(contentFormat, other.contentFormat,
              (MarkupKind a, MarkupKind b) => a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode);
    hash = JenkinsSmiHash.combine(hash, lspHashCode(contentFormat));
    return JenkinsSmiHash.finish(hash);
  }

  @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, dynamic> json) {
    if (HoverRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return HoverRegistrationOptions.fromJson(json);
    }
    final workDoneProgress = json['workDoneProgress'];
    return HoverOptions(workDoneProgress: workDoneProgress);
  }

  final bool workDoneProgress;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('workDoneProgress');
      try {
        if (obj['workDoneProgress'] != null &&
            !(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  HoverParams(
      {@required this.textDocument,
      @required this.position,
      this.workDoneToken}) {
    if (textDocument == null) {
      throw 'textDocument is required but was not provided';
    }
    if (position == null) {
      throw 'position is required but was not provided';
    }
  }
  static HoverParams fromJson(Map<String, dynamic> json) {
    final textDocument = json['textDocument'] != null
        ? TextDocumentIdentifier.fromJson(json['textDocument'])
        : null;
    final position =
        json['position'] != null ? Position.fromJson(json['position']) : null;
    final workDoneToken = json['workDoneToken'] is num
        ? Either2<num, String>.t1(json['workDoneToken'])
        : (json['workDoneToken'] is String
            ? Either2<num, String>.t2(json['workDoneToken'])
            : (json['workDoneToken'] == null
                ? null
                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
    return HoverParams(
        textDocument: textDocument,
        position: position,
        workDoneToken: workDoneToken);
  }

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

  /// The text document.
  final TextDocumentIdentifier textDocument;

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['textDocument'] = textDocument?.toJson() ??
        (throw 'textDocument is required but was not set');
    __result['position'] =
        position?.toJson() ?? (throw 'position is required but was not set');
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, textDocument.hashCode);
    hash = JenkinsSmiHash.combine(hash, position.hashCode);
    hash = JenkinsSmiHash.combine(hash, workDoneToken.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  HoverRegistrationOptions({this.documentSelector, this.workDoneProgress});
  static HoverRegistrationOptions fromJson(Map<String, dynamic> json) {
    final documentSelector = json['documentSelector']
        ?.map((item) => item != null ? DocumentFilter.fromJson(item) : null)
        ?.cast<DocumentFilter>()
        ?.toList();
    final workDoneProgress = json['workDoneProgress'];
    return HoverRegistrationOptions(
        documentSelector: documentSelector, workDoneProgress: workDoneProgress);
  }

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['documentSelector'] = documentSelector;
    if (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(documentSelector));
    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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, dynamic> json) {
    final dynamicRegistration = json['dynamicRegistration'];
    final linkSupport = json['linkSupport'];
    return ImplementationClientCapabilities(
        dynamicRegistration: dynamicRegistration, linkSupport: linkSupport);
  }

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

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    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, dynamic>) {
      reporter.push('dynamicRegistration');
      try {
        if (obj['dynamicRegistration'] != null &&
            !(obj['dynamicRegistration'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('linkSupport');
      try {
        if (obj['linkSupport'] != null && !(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode);
    hash = JenkinsSmiHash.combine(hash, linkSupport.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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, dynamic> json) {
    if (ImplementationRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return ImplementationRegistrationOptions.fromJson(json);
    }
    final workDoneProgress = json['workDoneProgress'];
    return ImplementationOptions(workDoneProgress: workDoneProgress);
  }

  final bool workDoneProgress;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('workDoneProgress');
      try {
        if (obj['workDoneProgress'] != null &&
            !(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  ImplementationParams(
      {@required this.textDocument,
      @required this.position,
      this.workDoneToken,
      this.partialResultToken}) {
    if (textDocument == null) {
      throw 'textDocument is required but was not provided';
    }
    if (position == null) {
      throw 'position is required but was not provided';
    }
  }
  static ImplementationParams fromJson(Map<String, dynamic> json) {
    final textDocument = json['textDocument'] != null
        ? TextDocumentIdentifier.fromJson(json['textDocument'])
        : null;
    final position =
        json['position'] != null ? Position.fromJson(json['position']) : null;
    final workDoneToken = json['workDoneToken'] is num
        ? Either2<num, String>.t1(json['workDoneToken'])
        : (json['workDoneToken'] is String
            ? Either2<num, String>.t2(json['workDoneToken'])
            : (json['workDoneToken'] == null
                ? null
                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
    final partialResultToken = json['partialResultToken'] is num
        ? Either2<num, String>.t1(json['partialResultToken'])
        : (json['partialResultToken'] is String
            ? Either2<num, String>.t2(json['partialResultToken'])
            : (json['partialResultToken'] == null
                ? null
                : (throw '''${json['partialResultToken']} was not one of (num, String)''')));
    return ImplementationParams(
        textDocument: textDocument,
        position: position,
        workDoneToken: workDoneToken,
        partialResultToken: partialResultToken);
  }

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

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

  /// The text document.
  final TextDocumentIdentifier textDocument;

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['textDocument'] = textDocument?.toJson() ??
        (throw 'textDocument is required but was not set');
    __result['position'] =
        position?.toJson() ?? (throw 'position is required but was not set');
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    if (partialResultToken != null) {
      __result['partialResultToken'] = partialResultToken;
    }
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, textDocument.hashCode);
    hash = JenkinsSmiHash.combine(hash, position.hashCode);
    hash = JenkinsSmiHash.combine(hash, workDoneToken.hashCode);
    hash = JenkinsSmiHash.combine(hash, partialResultToken.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  ImplementationRegistrationOptions(
      {this.documentSelector, this.workDoneProgress, this.id});
  static ImplementationRegistrationOptions fromJson(Map<String, dynamic> json) {
    final documentSelector = json['documentSelector']
        ?.map((item) => item != null ? DocumentFilter.fromJson(item) : null)
        ?.cast<DocumentFilter>()
        ?.toList();
    final workDoneProgress = json['workDoneProgress'];
    final id = json['id'];
    return ImplementationRegistrationOptions(
        documentSelector: documentSelector,
        workDoneProgress: workDoneProgress,
        id: id);
  }

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

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['documentSelector'] = documentSelector;
    if (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    if (id != null) {
      __result['id'] = id;
    }
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(documentSelector));
    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
    hash = JenkinsSmiHash.combine(hash, id.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  InitializeParams(
      {this.processId,
      this.clientInfo,
      this.locale,
      this.rootPath,
      this.rootUri,
      this.initializationOptions,
      @required this.capabilities,
      this.trace,
      this.workspaceFolders,
      this.workDoneToken}) {
    if (capabilities == null) {
      throw 'capabilities is required but was not provided';
    }
  }
  static InitializeParams fromJson(Map<String, dynamic> json) {
    final processId = json['processId'];
    final clientInfo = json['clientInfo'] != null
        ? InitializeParamsClientInfo.fromJson(json['clientInfo'])
        : null;
    final locale = json['locale'];
    final rootPath = json['rootPath'];
    final rootUri = json['rootUri'];
    final initializationOptions = json['initializationOptions'];
    final capabilities = json['capabilities'] != null
        ? ClientCapabilities.fromJson(json['capabilities'])
        : null;
    final trace = const {null, 'off', 'message', 'verbose'}
            .contains(json['trace'])
        ? json['trace']
        : throw '''${json['trace']} was not one of (null, 'off', 'message', 'verbose')''';
    final workspaceFolders = json['workspaceFolders']
        ?.map((item) => item != null ? WorkspaceFolder.fromJson(item) : null)
        ?.cast<WorkspaceFolder>()
        ?.toList();
    final workDoneToken = json['workDoneToken'] is num
        ? Either2<num, String>.t1(json['workDoneToken'])
        : (json['workDoneToken'] is String
            ? Either2<num, String>.t2(json['workDoneToken'])
            : (json['workDoneToken'] == null
                ? null
                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
    return InitializeParams(
        processId: processId,
        clientInfo: clientInfo,
        locale: locale,
        rootPath: rootPath,
        rootUri: rootUri,
        initializationOptions: initializationOptions,
        capabilities: capabilities,
        trace: trace,
        workspaceFolders: workspaceFolders,
        workDoneToken: workDoneToken);
  }

  /// The capabilities provided by the client (editor or tool)
  final ClientCapabilities capabilities;

  /// Information about the client
  ///  @since 3.15.0
  final InitializeParamsClientInfo clientInfo;

  /// User provided initialization options.
  final dynamic 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 num processId;

  /// The rootPath of the workspace. Is null if no folder is open.
  ///  @deprecated in favour of `rootUri`.
  final String rootPath;

  /// The rootUri of the workspace. Is null if no folder is open. If both
  /// `rootPath` and `rootUri` are set `rootUri` wins.
  ///  @deprecated in favour of `workspaceFolders`
  final String rootUri;

  /// The initial trace setting. If omitted trace is disabled ('off').
  final String trace;

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

  /// The workspace folders configured in the client when the server starts.
  /// This property is only available if the client supports workspace folders.
  /// It can be `null` if the client supports workspace folders but none are
  /// configured.
  ///  @since 3.6.0
  final List<WorkspaceFolder> workspaceFolders;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['processId'] = processId;
    if (clientInfo != null) {
      __result['clientInfo'] = clientInfo.toJson();
    }
    if (locale != null) {
      __result['locale'] = locale;
    }
    if (rootPath != null) {
      __result['rootPath'] = rootPath;
    }
    __result['rootUri'] = rootUri;
    if (initializationOptions != null) {
      __result['initializationOptions'] = initializationOptions;
    }
    __result['capabilities'] = capabilities?.toJson() ??
        (throw 'capabilities is required but was not set');
    if (trace != null) {
      __result['trace'] = trace;
    }
    if (workspaceFolders != null) {
      __result['workspaceFolders'] =
          workspaceFolders.map((item) => item.toJson()).toList();
    }
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('processId');
      try {
        if (!obj.containsKey('processId')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['processId'] != null && !(obj['processId'] is num)) {
          reporter.reportError('must be of type num');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('clientInfo');
      try {
        if (obj['clientInfo'] != null &&
            !(InitializeParamsClientInfo.canParse(
                obj['clientInfo'], reporter))) {
          reporter.reportError('must be of type InitializeParamsClientInfo');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('locale');
      try {
        if (obj['locale'] != null && !(obj['locale'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('rootPath');
      try {
        if (obj['rootPath'] != null && !(obj['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;
        }
        if (obj['rootUri'] != null && !(obj['rootUri'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('initializationOptions');
      try {
        if (obj['initializationOptions'] != null && !(true)) {
          reporter.reportError('must be of type dynamic');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('capabilities');
      try {
        if (!obj.containsKey('capabilities')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['capabilities'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(ClientCapabilities.canParse(obj['capabilities'], reporter))) {
          reporter.reportError('must be of type ClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('trace');
      try {
        if (obj['trace'] != null &&
            !((obj['trace'] == 'off' ||
                obj['trace'] == 'message' ||
                obj['trace'] == 'verbose'))) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workspaceFolders');
      try {
        if (obj['workspaceFolders'] != null &&
            !((obj['workspaceFolders'] is List &&
                (obj['workspaceFolders'].every(
                    (item) => WorkspaceFolder.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<WorkspaceFolder>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        if (obj['workDoneToken'] != null &&
            !((obj['workDoneToken'] is num ||
                obj['workDoneToken'] is String))) {
          reporter.reportError('must be of type Either2<num, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type InitializeParams');
      return false;
    }
  }

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, processId.hashCode);
    hash = JenkinsSmiHash.combine(hash, clientInfo.hashCode);
    hash = JenkinsSmiHash.combine(hash, locale.hashCode);
    hash = JenkinsSmiHash.combine(hash, rootPath.hashCode);
    hash = JenkinsSmiHash.combine(hash, rootUri.hashCode);
    hash = JenkinsSmiHash.combine(hash, initializationOptions.hashCode);
    hash = JenkinsSmiHash.combine(hash, capabilities.hashCode);
    hash = JenkinsSmiHash.combine(hash, trace.hashCode);
    hash = JenkinsSmiHash.combine(hash, lspHashCode(workspaceFolders));
    hash = JenkinsSmiHash.combine(hash, workDoneToken.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  InitializeParamsClientInfo({@required this.name, this.version}) {
    if (name == null) {
      throw 'name is required but was not provided';
    }
  }
  static InitializeParamsClientInfo fromJson(Map<String, dynamic> json) {
    final name = json['name'];
    final version = json['version'];
    return InitializeParamsClientInfo(name: name, version: version);
  }

  /// The name of the client as defined by the client.
  final String name;

  /// The client's version as defined by the client.
  final String version;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['name'] = name ?? (throw 'name is required but was not set');
    if (version != null) {
      __result['version'] = version;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('name');
      try {
        if (!obj.containsKey('name')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['name'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['name'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('version');
      try {
        if (obj['version'] != null && !(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, name.hashCode);
    hash = JenkinsSmiHash.combine(hash, version.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  InitializeResult({@required this.capabilities, this.serverInfo}) {
    if (capabilities == null) {
      throw 'capabilities is required but was not provided';
    }
  }
  static InitializeResult fromJson(Map<String, dynamic> json) {
    final capabilities = json['capabilities'] != null
        ? ServerCapabilities.fromJson(json['capabilities'])
        : null;
    final serverInfo = json['serverInfo'] != null
        ? InitializeResultServerInfo.fromJson(json['serverInfo'])
        : null;
    return InitializeResult(capabilities: capabilities, serverInfo: serverInfo);
  }

  /// The capabilities the language server provides.
  final ServerCapabilities capabilities;

  /// Information about the server.
  ///  @since 3.15.0
  final InitializeResultServerInfo serverInfo;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['capabilities'] = capabilities?.toJson() ??
        (throw 'capabilities is required but was not set');
    if (serverInfo != null) {
      __result['serverInfo'] = serverInfo.toJson();
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('capabilities');
      try {
        if (!obj.containsKey('capabilities')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['capabilities'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(ServerCapabilities.canParse(obj['capabilities'], reporter))) {
          reporter.reportError('must be of type ServerCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('serverInfo');
      try {
        if (obj['serverInfo'] != null &&
            !(InitializeResultServerInfo.canParse(
                obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, capabilities.hashCode);
    hash = JenkinsSmiHash.combine(hash, serverInfo.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  InitializeResultServerInfo({@required this.name, this.version}) {
    if (name == null) {
      throw 'name is required but was not provided';
    }
  }
  static InitializeResultServerInfo fromJson(Map<String, dynamic> json) {
    final name = json['name'];
    final version = json['version'];
    return InitializeResultServerInfo(name: name, version: version);
  }

  /// The name of the server as defined by the server.
  final String name;

  /// The server's version as defined by the server.
  final String version;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['name'] = name ?? (throw 'name is required but was not set');
    if (version != null) {
      __result['version'] = version;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('name');
      try {
        if (!obj.containsKey('name')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['name'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['name'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('version');
      try {
        if (obj['version'] != null && !(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, name.hashCode);
    hash = JenkinsSmiHash.combine(hash, version.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  static InitializedParams fromJson(Map<String, dynamic> json) {
    return InitializedParams();
  }

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

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      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 {
    var hash = 0;
    return JenkinsSmiHash.finish(hash);
  }

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

/// A special text edit to provide an insert and a replace operation.
///  @since 3.16.0
class InsertReplaceEdit implements ToJsonable {
  static const jsonHandler =
      LspJsonHandler(InsertReplaceEdit.canParse, InsertReplaceEdit.fromJson);

  InsertReplaceEdit(
      {@required this.newText, @required this.insert, @required this.replace}) {
    if (newText == null) {
      throw 'newText is required but was not provided';
    }
    if (insert == null) {
      throw 'insert is required but was not provided';
    }
    if (replace == null) {
      throw 'replace is required but was not provided';
    }
  }
  static InsertReplaceEdit fromJson(Map<String, dynamic> json) {
    final newText = json['newText'];
    final insert =
        json['insert'] != null ? Range.fromJson(json['insert']) : null;
    final replace =
        json['replace'] != null ? Range.fromJson(json['replace']) : null;
    return InsertReplaceEdit(
        newText: newText, insert: insert, replace: replace);
  }

  /// The range if the insert is requested
  final Range insert;

  /// The string to be inserted.
  final String newText;

  /// The range if the replace is requested.
  final Range replace;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['newText'] =
        newText ?? (throw 'newText is required but was not set');
    __result['insert'] =
        insert?.toJson() ?? (throw 'insert is required but was not set');
    __result['replace'] =
        replace?.toJson() ?? (throw 'replace is required but was not set');
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('newText');
      try {
        if (!obj.containsKey('newText')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['newText'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['newText'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('insert');
      try {
        if (!obj.containsKey('insert')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['insert'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(Range.canParse(obj['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;
        }
        if (obj['replace'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(Range.canParse(obj['replace'], reporter))) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type InsertReplaceEdit');
      return false;
    }
  }

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, newText.hashCode);
    hash = JenkinsSmiHash.combine(hash, insert.hashCode);
    hash = JenkinsSmiHash.combine(hash, replace.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

/// Defines whether the insert text in a completion item should be interpreted
/// as plain text or a snippet.
class InsertTextFormat {
  const InsertTextFormat._(this._value);
  const InsertTextFormat.fromJson(this._value);

  final num _value;

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

  /// The primary text to be inserted is treated as a plain string.
  static const PlainText = InsertTextFormat._(1);

  /// The primary text to be inserted is treated as a snippet.
  ///
  /// A snippet can define tab stops and placeholders with `$1`, `$2` and
  /// `${3:foo}`. `$0` defines the final tab stop, it defaults to the end of the
  /// snippet. Placeholders with equal identifiers are linked, that is typing in
  /// one will update others too.
  static const Snippet = InsertTextFormat._(2);

  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

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

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

  final num _value;

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

  /// The insertion or replace strings is taken as it is. If the value is multi
  /// line the lines below the cursor will be inserted using the indentation
  /// defined in the string value. The client will not apply any kind of
  /// adjustments to the string.
  static const asIs = InsertTextMode(1);

  /// The editor adjusts leading whitespace of new lines so that they match the
  /// indentation up to the cursor of the line for which the item is accepted.
  ///
  /// Consider a line like this: <2tabs><cursor><3tabs>foo. Accepting a multi
  /// line completion item is indented using 2 tabs and all following lines
  /// inserted will be indented using 2 tabs as well.
  static const adjustIndentation = InsertTextMode(2);

  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

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

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

  LinkedEditingRangeClientCapabilities({this.dynamicRegistration});
  static LinkedEditingRangeClientCapabilities fromJson(
      Map<String, dynamic> json) {
    final dynamicRegistration = json['dynamicRegistration'];
    return LinkedEditingRangeClientCapabilities(
        dynamicRegistration: dynamicRegistration);
  }

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (dynamicRegistration != null) {
      __result['dynamicRegistration'] = dynamicRegistration;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('dynamicRegistration');
      try {
        if (obj['dynamicRegistration'] != null &&
            !(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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, dynamic> json) {
    if (LinkedEditingRangeRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return LinkedEditingRangeRegistrationOptions.fromJson(json);
    }
    final workDoneProgress = json['workDoneProgress'];
    return LinkedEditingRangeOptions(workDoneProgress: workDoneProgress);
  }

  final bool workDoneProgress;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('workDoneProgress');
      try {
        if (obj['workDoneProgress'] != null &&
            !(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  LinkedEditingRangeParams(
      {@required this.textDocument,
      @required this.position,
      this.workDoneToken}) {
    if (textDocument == null) {
      throw 'textDocument is required but was not provided';
    }
    if (position == null) {
      throw 'position is required but was not provided';
    }
  }
  static LinkedEditingRangeParams fromJson(Map<String, dynamic> json) {
    final textDocument = json['textDocument'] != null
        ? TextDocumentIdentifier.fromJson(json['textDocument'])
        : null;
    final position =
        json['position'] != null ? Position.fromJson(json['position']) : null;
    final workDoneToken = json['workDoneToken'] is num
        ? Either2<num, String>.t1(json['workDoneToken'])
        : (json['workDoneToken'] is String
            ? Either2<num, String>.t2(json['workDoneToken'])
            : (json['workDoneToken'] == null
                ? null
                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
    return LinkedEditingRangeParams(
        textDocument: textDocument,
        position: position,
        workDoneToken: workDoneToken);
  }

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

  /// The text document.
  final TextDocumentIdentifier textDocument;

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['textDocument'] = textDocument?.toJson() ??
        (throw 'textDocument is required but was not set');
    __result['position'] =
        position?.toJson() ?? (throw 'position is required but was not set');
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, textDocument.hashCode);
    hash = JenkinsSmiHash.combine(hash, position.hashCode);
    hash = JenkinsSmiHash.combine(hash, workDoneToken.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  LinkedEditingRangeRegistrationOptions(
      {this.documentSelector, this.workDoneProgress, this.id});
  static LinkedEditingRangeRegistrationOptions fromJson(
      Map<String, dynamic> json) {
    final documentSelector = json['documentSelector']
        ?.map((item) => item != null ? DocumentFilter.fromJson(item) : null)
        ?.cast<DocumentFilter>()
        ?.toList();
    final workDoneProgress = json['workDoneProgress'];
    final id = json['id'];
    return LinkedEditingRangeRegistrationOptions(
        documentSelector: documentSelector,
        workDoneProgress: workDoneProgress,
        id: id);
  }

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

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['documentSelector'] = documentSelector;
    if (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    if (id != null) {
      __result['id'] = id;
    }
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(documentSelector));
    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
    hash = JenkinsSmiHash.combine(hash, id.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  LinkedEditingRanges({@required this.ranges, this.wordPattern}) {
    if (ranges == null) {
      throw 'ranges is required but was not provided';
    }
  }
  static LinkedEditingRanges fromJson(Map<String, dynamic> json) {
    final ranges = json['ranges']
        ?.map((item) => item != null ? Range.fromJson(item) : null)
        ?.cast<Range>()
        ?.toList();
    final wordPattern = json['wordPattern'];
    return LinkedEditingRanges(ranges: ranges, wordPattern: wordPattern);
  }

  /// A list of ranges that can be renamed together. The ranges must have
  /// identical length and contain identical text content. The ranges cannot
  /// overlap.
  final List<Range> ranges;

  /// An optional word pattern (regular expression) that describes valid
  /// contents for the given ranges. If no pattern is provided, the client
  /// configuration's word pattern will be used.
  final String wordPattern;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['ranges'] = ranges?.map((item) => item.toJson())?.toList() ??
        (throw 'ranges is required but was not set');
    if (wordPattern != null) {
      __result['wordPattern'] = wordPattern;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('ranges');
      try {
        if (!obj.containsKey('ranges')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['ranges'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!((obj['ranges'] is List &&
            (obj['ranges'].every((item) => Range.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<Range>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('wordPattern');
      try {
        if (obj['wordPattern'] != null && !(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(ranges));
    hash = JenkinsSmiHash.combine(hash, wordPattern.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  Location({@required this.uri, @required this.range}) {
    if (uri == null) {
      throw 'uri is required but was not provided';
    }
    if (range == null) {
      throw 'range is required but was not provided';
    }
  }
  static Location fromJson(Map<String, dynamic> json) {
    final uri = json['uri'];
    final range = json['range'] != null ? Range.fromJson(json['range']) : null;
    return Location(uri: uri, range: range);
  }

  final Range range;
  final String uri;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['uri'] = uri ?? (throw 'uri is required but was not set');
    __result['range'] =
        range?.toJson() ?? (throw 'range is required but was not set');
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, uri.hashCode);
    hash = JenkinsSmiHash.combine(hash, range.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  LocationLink(
      {this.originSelectionRange,
      @required this.targetUri,
      @required this.targetRange,
      @required this.targetSelectionRange}) {
    if (targetUri == null) {
      throw 'targetUri is required but was not provided';
    }
    if (targetRange == null) {
      throw 'targetRange is required but was not provided';
    }
    if (targetSelectionRange == null) {
      throw 'targetSelectionRange is required but was not provided';
    }
  }
  static LocationLink fromJson(Map<String, dynamic> json) {
    final originSelectionRange = json['originSelectionRange'] != null
        ? Range.fromJson(json['originSelectionRange'])
        : null;
    final targetUri = json['targetUri'];
    final targetRange = json['targetRange'] != null
        ? Range.fromJson(json['targetRange'])
        : null;
    final targetSelectionRange = json['targetSelectionRange'] != null
        ? Range.fromJson(json['targetSelectionRange'])
        : null;
    return LocationLink(
        originSelectionRange: originSelectionRange,
        targetUri: targetUri,
        targetRange: targetRange,
        targetSelectionRange: targetSelectionRange);
  }

  /// Span of the origin of this link.
  ///
  /// Used as the underlined span for mouse interaction. Defaults to the word
  /// range at the mouse position.
  final Range originSelectionRange;

  /// The full target range of this link. If the target for example is a symbol
  /// then target range is the range enclosing this symbol not including
  /// leading/trailing whitespace but everything else like comments. This
  /// information is typically used to highlight the range in the editor.
  final Range targetRange;

  /// The range that should be selected and revealed when this link is being
  /// followed, e.g the name of a function. Must be contained by the the
  /// `targetRange`. See also `DocumentSymbol#range`
  final Range targetSelectionRange;

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (originSelectionRange != null) {
      __result['originSelectionRange'] = originSelectionRange.toJson();
    }
    __result['targetUri'] =
        targetUri ?? (throw 'targetUri is required but was not set');
    __result['targetRange'] = targetRange?.toJson() ??
        (throw 'targetRange is required but was not set');
    __result['targetSelectionRange'] = targetSelectionRange?.toJson() ??
        (throw 'targetSelectionRange is required but was not set');
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('originSelectionRange');
      try {
        if (obj['originSelectionRange'] != null &&
            !(Range.canParse(obj['originSelectionRange'], reporter))) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('targetUri');
      try {
        if (!obj.containsKey('targetUri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['targetUri'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['targetUri'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('targetRange');
      try {
        if (!obj.containsKey('targetRange')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['targetRange'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(Range.canParse(obj['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;
        }
        if (obj['targetSelectionRange'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(Range.canParse(obj['targetSelectionRange'], reporter))) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type LocationLink');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is LocationLink && other.runtimeType == LocationLink) {
      return originSelectionRange == other.originSelectionRange &&
          targetUri == other.targetUri &&
          targetRange == other.targetRange &&
          targetSelectionRange == other.targetSelectionRange &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, originSelectionRange.hashCode);
    hash = JenkinsSmiHash.combine(hash, targetUri.hashCode);
    hash = JenkinsSmiHash.combine(hash, targetRange.hashCode);
    hash = JenkinsSmiHash.combine(hash, targetSelectionRange.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  LogMessageParams({@required this.type, @required this.message}) {
    if (type == null) {
      throw 'type is required but was not provided';
    }
    if (message == null) {
      throw 'message is required but was not provided';
    }
  }
  static LogMessageParams fromJson(Map<String, dynamic> json) {
    final type =
        json['type'] != null ? MessageType.fromJson(json['type']) : null;
    final message = json['message'];
    return LogMessageParams(type: type, message: message);
  }

  /// The actual message
  final String message;

  /// The message type.
  final MessageType type;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['type'] =
        type?.toJson() ?? (throw 'type is required but was not set');
    __result['message'] =
        message ?? (throw 'message is required but was not set');
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, type.hashCode);
    hash = JenkinsSmiHash.combine(hash, message.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  LogTraceParams({@required this.message, this.verbose}) {
    if (message == null) {
      throw 'message is required but was not provided';
    }
  }
  static LogTraceParams fromJson(Map<String, dynamic> json) {
    final message = json['message'];
    final verbose = json['verbose'];
    return LogTraceParams(message: message, verbose: verbose);
  }

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

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

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['message'] =
        message ?? (throw 'message is required but was not set');
    if (verbose != null) {
      __result['verbose'] = verbose;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('message');
      try {
        if (!obj.containsKey('message')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['message'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['message'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('verbose');
      try {
        if (obj['verbose'] != null && !(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, message.hashCode);
    hash = JenkinsSmiHash.combine(hash, verbose.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

/// Client capabilities specific to the used markdown parser.
///  @since 3.16.0
class MarkdownClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
      MarkdownClientCapabilities.canParse, MarkdownClientCapabilities.fromJson);

  MarkdownClientCapabilities({@required this.parser, this.version}) {
    if (parser == null) {
      throw 'parser is required but was not provided';
    }
  }
  static MarkdownClientCapabilities fromJson(Map<String, dynamic> json) {
    final parser = json['parser'];
    final version = json['version'];
    return MarkdownClientCapabilities(parser: parser, version: version);
  }

  /// The name of the parser.
  final String parser;

  /// The version of the parser.
  final String version;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['parser'] = parser ?? (throw 'parser is required but was not set');
    if (version != null) {
      __result['version'] = version;
    }
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, parser.hashCode);
    hash = JenkinsSmiHash.combine(hash, version.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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}) {
    if (kind == null) {
      throw 'kind is required but was not provided';
    }
    if (value == null) {
      throw 'value is required but was not provided';
    }
  }
  static MarkupContent fromJson(Map<String, dynamic> json) {
    final kind =
        json['kind'] != null ? MarkupKind.fromJson(json['kind']) : null;
    final value = json['value'];
    return MarkupContent(kind: kind, value: value);
  }

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

  /// The content itself
  final String value;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['kind'] =
        kind?.toJson() ?? (throw 'kind is required but was not set');
    __result['value'] = value ?? (throw 'value is required but was not set');
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('kind');
      try {
        if (!obj.containsKey('kind')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['kind'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(MarkupKind.canParse(obj['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;
        }
        if (obj['value'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, kind.hashCode);
    hash = JenkinsSmiHash.combine(hash, value.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  final String _value;

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

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

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

  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

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

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

  Message({@required this.jsonrpc}) {
    if (jsonrpc == null) {
      throw 'jsonrpc is required but was not provided';
    }
  }
  static Message fromJson(Map<String, dynamic> json) {
    if (RequestMessage.canParse(json, nullLspJsonReporter)) {
      return RequestMessage.fromJson(json);
    }
    if (ResponseMessage.canParse(json, nullLspJsonReporter)) {
      return ResponseMessage.fromJson(json);
    }
    if (NotificationMessage.canParse(json, nullLspJsonReporter)) {
      return NotificationMessage.fromJson(json);
    }
    final jsonrpc = json['jsonrpc'];
    return Message(jsonrpc: jsonrpc);
  }

  final String jsonrpc;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['jsonrpc'] =
        jsonrpc ?? (throw 'jsonrpc is required but was not set');
    return __result;
  }

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

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

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, jsonrpc.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  MessageActionItem({@required this.title}) {
    if (title == null) {
      throw 'title is required but was not provided';
    }
  }
  static MessageActionItem fromJson(Map<String, dynamic> json) {
    final title = json['title'];
    return MessageActionItem(title: title);
  }

  /// A short title like 'Retry', 'Open Log' etc.
  final String title;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['title'] = title ?? (throw 'title is required but was not set');
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('title');
      try {
        if (!obj.containsKey('title')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['title'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, title.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

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

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

  final num _value;

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

  /// An error message.
  static const Error = MessageType(1);

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

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

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

  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

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

/// Valid LSP methods known at the time of code generation from the spec.
class Method {
  const Method(this._value);
  const Method.fromJson(this._value);

  final String _value;

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

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

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

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

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

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

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

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

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

  /// Constant for the 'window/showMessage' method.
  static const window_showMessage = Method(r'window/showMessage');

  /// Constant for the 'window/showMessageRequest' method.
  static const window_showMessageRequest = Method(r'window/showMessageRequest');

  /// Constant for the 'window/showDocument' method.
  static const window_showDocument = Method(r'window/showDocument');

  /// Constant for the 'window/logMessage' method.
  static const window_logMessage = Method(r'window/logMessage');

  /// Constant for the 'window/workDoneProgress/create' method.
  static const window_workDoneProgress_create =
      Method(r'window/workDoneProgress/create');

  /// Constant for the 'window/workDoneProgress/cancel' method.
  static const window_workDoneProgress_cancel =
      Method(r'window/workDoneProgress/cancel');

  /// Constant for the 'telemetry/event' method.
  static const telemetry_event = Method(r'telemetry/event');

  /// Constant for the 'client/registerCapability' method.
  static const client_registerCapability = Method(r'client/registerCapability');

  /// Constant for the 'client/unregisterCapability' method.
  static const client_unregisterCapability =
      Method(r'client/unregisterCapability');

  /// Constant for the 'workspace/workspaceFolders' method.
  static const workspace_workspaceFolders =
      Method(r'workspace/workspaceFolders');

  /// Constant for the 'workspace/didChangeWorkspaceFolders' method.
  static const workspace_didChangeWorkspaceFolders =
      Method(r'workspace/didChangeWorkspaceFolders');

  /// Constant for the 'workspace/didChangeConfiguration' method.
  static const workspace_didChangeConfiguration =
      Method(r'workspace/didChangeConfiguration');

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

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

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

  /// Constant for the 'workspace/executeCommand' method.
  static const workspace_executeCommand = Method(r'workspace/executeCommand');

  /// Constant for the 'workspace/applyEdit' method.
  static const workspace_applyEdit = Method(r'workspace/applyEdit');

  /// Constant for the 'workspace/willCreateFiles' method.
  static const workspace_willCreateFiles = Method(r'workspace/willCreateFiles');

  /// Constant for the 'workspace/didCreateFiles' method.
  static const workspace_didCreateFiles = Method(r'workspace/didCreateFiles');

  /// Constant for the 'workspace/willRenameFiles' method.
  static const workspace_willRenameFiles = Method(r'workspace/willRenameFiles');

  /// Constant for the 'workspace/didRenameFiles' method.
  static const workspace_didRenameFiles = Method(r'workspace/didRenameFiles');

  /// Constant for the 'workspace/willDeleteFiles' method.
  static const workspace_willDeleteFiles = Method(r'workspace/willDeleteFiles');

  /// Constant for the 'workspace/didDeleteFiles' method.
  static const workspace_didDeleteFiles = Method(r'workspace/didDeleteFiles');

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

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

  /// Constant for the 'textDocument/willSave' method.
  static const textDocument_willSave = Method(r'textDocument/willSave');

  /// Constant for the 'textDocument/willSaveWaitUntil' method.
  static const textDocument_willSaveWaitUntil =
      Method(r'textDocument/willSaveWaitUntil');

  /// Constant for the 'textDocument/didSave' method.
  static const textDocument_didSave = Method(r'textDocument/didSave');

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

  /// Constant for the 'textDocument/publishDiagnostics' method.
  static const textDocument_publishDiagnostics =
      Method(r'textDocument/publishDiagnostics');

  /// Constant for the 'textDocument/completion' method.
  static const textDocument_completion = Method(r'textDocument/completion');

  /// Constant for the 'completionItem/resolve' method.
  static const completionItem_resolve = Method(r'completionItem/resolve');

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

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

  /// Constant for the 'textDocument/declaration' method.
  static const textDocument_declaration = Method(r'textDocument/declaration');

  /// Constant for the 'textDocument/definition' method.
  static const textDocument_definition = Method(r'textDocument/definition');

  /// Constant for the 'textDocument/typeDefinition' method.
  static const textDocument_typeDefinition =
      Method(r'textDocument/typeDefinition');

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

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

  /// Constant for the 'textDocument/documentHighlight' method.
  static const textDocument_documentHighlight =
      Method(r'textDocument/documentHighlight');

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

  /// Constant for the 'textDocument/codeAction' method.
  static const textDocument_codeAction = Method(r'textDocument/codeAction');

  /// Constant for the 'codeAction/resolve' method.
  static const codeAction_resolve = Method(r'codeAction/resolve');

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

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

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

  /// Constant for the 'textDocument/documentLink' method.
  static const textDocument_documentLink = Method(r'textDocument/documentLink');

  /// Constant for the 'documentLink/resolve' method.
  static const documentLink_resolve = Method(r'documentLink/resolve');

  /// Constant for the 'textDocument/documentColor' method.
  static const textDocument_documentColor =
      Method(r'textDocument/documentColor');

  /// Constant for the 'textDocument/colorPresentation' method.
  static const textDocument_colorPresentation =
      Method(r'textDocument/colorPresentation');

  /// Constant for the 'textDocument/formatting' method.
  static const textDocument_formatting = Method(r'textDocument/formatting');

  /// Constant for the 'textDocument/rangeFormatting' method.
  static const textDocument_rangeFormatting =
      Method(r'textDocument/rangeFormatting');

  /// Constant for the 'textDocument/onTypeFormatting' method.
  static const textDocument_onTypeFormatting =
      Method(r'textDocument/onTypeFormatting');

  /// Constant for the 'textDocument/rename' method.
  static const textDocument_rename = Method(r'textDocument/rename');

  /// Constant for the 'textDocument/prepareRename' method.
  static const textDocument_prepareRename =
      Method(r'textDocument/prepareRename');

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

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

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

  /// Constant for the 'callHierarchy/incomingCalls' method.
  static const callHierarchy_incomingCalls =
      Method(r'callHierarchy/incomingCalls');

  /// Constant for the 'callHierarchy/outgoingCalls' method.
  static const callHierarchy_outgoingCalls =
      Method(r'callHierarchy/outgoingCalls');

  /// Constant for the 'textDocument/semanticTokens/full' method.
  static const textDocument_semanticTokens_full =
      Method(r'textDocument/semanticTokens/full');

  /// Constant for the 'textDocument/semanticTokens/full/delta' method.
  static const textDocument_semanticTokens_full_delta =
      Method(r'textDocument/semanticTokens/full/delta');

  /// Constant for the 'textDocument/semanticTokens/range' method.
  static const textDocument_semanticTokens_range =
      Method(r'textDocument/semanticTokens/range');

  /// Constant for the 'workspace/semanticTokens/refresh' method.
  static const workspace_semanticTokens_refresh =
      Method(r'workspace/semanticTokens/refresh');

  /// Constant for the 'textDocument/linkedEditingRange' method.
  static const textDocument_linkedEditingRange =
      Method(r'textDocument/linkedEditingRange');

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

  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  bool operator ==(Object o) => o is Method && o._value == _value;
}

/// Moniker definition to match LSIF 0.5 moniker definition.
class Moniker implements ToJsonable {
  static const jsonHandler = LspJsonHandler(Moniker.canParse, Moniker.fromJson);

  Moniker(
      {@required this.scheme,
      @required this.identifier,
      @required this.unique,
      this.kind}) {
    if (scheme == null) {
      throw 'scheme is required but was not provided';
    }
    if (identifier == null) {
      throw 'identifier is required but was not provided';
    }
    if (unique == null) {
      throw 'unique is required but was not provided';
    }
  }
  static Moniker fromJson(Map<String, dynamic> json) {
    final scheme = json['scheme'];
    final identifier = json['identifier'];
    final unique = json['unique'] != null
        ? UniquenessLevel.fromJson(json['unique'])
        : null;
    final kind =
        json['kind'] != null ? MonikerKind.fromJson(json['kind']) : null;
    return Moniker(
        scheme: scheme, identifier: identifier, unique: unique, kind: kind);
  }

  /// The identifier of the moniker. The value is opaque in LSIF however schema
  /// owners are allowed to define the structure if they want.
  final String identifier;

  /// The moniker kind if known.
  final MonikerKind kind;

  /// The scheme of the moniker. For example tsc or .Net
  final String scheme;

  /// The scope in which the moniker is unique
  final UniquenessLevel unique;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['scheme'] = scheme ?? (throw 'scheme is required but was not set');
    __result['identifier'] =
        identifier ?? (throw 'identifier is required but was not set');
    __result['unique'] =
        unique?.toJson() ?? (throw 'unique is required but was not set');
    if (kind != null) {
      __result['kind'] = kind.toJson();
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('scheme');
      try {
        if (!obj.containsKey('scheme')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['scheme'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['scheme'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('identifier');
      try {
        if (!obj.containsKey('identifier')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['identifier'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['identifier'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('unique');
      try {
        if (!obj.containsKey('unique')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['unique'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(UniquenessLevel.canParse(obj['unique'], reporter))) {
          reporter.reportError('must be of type UniquenessLevel');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('kind');
      try {
        if (obj['kind'] != null &&
            !(MonikerKind.canParse(obj['kind'], reporter))) {
          reporter.reportError('must be of type MonikerKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type Moniker');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is Moniker && other.runtimeType == Moniker) {
      return scheme == other.scheme &&
          identifier == other.identifier &&
          unique == other.unique &&
          kind == other.kind &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, scheme.hashCode);
    hash = JenkinsSmiHash.combine(hash, identifier.hashCode);
    hash = JenkinsSmiHash.combine(hash, unique.hashCode);
    hash = JenkinsSmiHash.combine(hash, kind.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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, dynamic> json) {
    final dynamicRegistration = json['dynamicRegistration'];
    return MonikerClientCapabilities(dynamicRegistration: dynamicRegistration);
  }

  /// Whether implementation supports dynamic registration. If this is set to
  /// `true` the client supports the new `(TextDocumentRegistrationOptions &
  /// StaticRegistrationOptions)` return value for the corresponding server
  /// capability as well.
  final bool dynamicRegistration;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (dynamicRegistration != null) {
      __result['dynamicRegistration'] = dynamicRegistration;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('dynamicRegistration');
      try {
        if (obj['dynamicRegistration'] != null &&
            !(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The moniker kind.
class MonikerKind {
  const MonikerKind(this._value);
  const MonikerKind.fromJson(this._value);

  final String _value;

  static bool canParse(Object obj, LspJsonReporter reporter) {
    return obj is String;
  }

  /// The moniker represent a symbol that is imported into a project
  static const import = MonikerKind(r'import');

  /// The moniker represents a symbol that is exported from a project
  static const export = MonikerKind(r'export');

  /// The moniker represents a symbol that is local to a project (e.g. a local
  /// variable of a function, a class not visible outside the project, ...)
  static const local = MonikerKind(r'local');

  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  bool operator ==(Object o) => o is MonikerKind && o._value == _value;
}

class MonikerOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler =
      LspJsonHandler(MonikerOptions.canParse, MonikerOptions.fromJson);

  MonikerOptions({this.workDoneProgress});
  static MonikerOptions fromJson(Map<String, dynamic> json) {
    if (MonikerRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return MonikerRegistrationOptions.fromJson(json);
    }
    final workDoneProgress = json['workDoneProgress'];
    return MonikerOptions(workDoneProgress: workDoneProgress);
  }

  final bool workDoneProgress;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('workDoneProgress');
      try {
        if (obj['workDoneProgress'] != null &&
            !(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class MonikerParams
    implements
        TextDocumentPositionParams,
        WorkDoneProgressParams,
        PartialResultParams,
        ToJsonable {
  static const jsonHandler =
      LspJsonHandler(MonikerParams.canParse, MonikerParams.fromJson);

  MonikerParams(
      {@required this.textDocument,
      @required this.position,
      this.workDoneToken,
      this.partialResultToken}) {
    if (textDocument == null) {
      throw 'textDocument is required but was not provided';
    }
    if (position == null) {
      throw 'position is required but was not provided';
    }
  }
  static MonikerParams fromJson(Map<String, dynamic> json) {
    final textDocument = json['textDocument'] != null
        ? TextDocumentIdentifier.fromJson(json['textDocument'])
        : null;
    final position =
        json['position'] != null ? Position.fromJson(json['position']) : null;
    final workDoneToken = json['workDoneToken'] is num
        ? Either2<num, String>.t1(json['workDoneToken'])
        : (json['workDoneToken'] is String
            ? Either2<num, String>.t2(json['workDoneToken'])
            : (json['workDoneToken'] == null
                ? null
                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
    final partialResultToken = json['partialResultToken'] is num
        ? Either2<num, String>.t1(json['partialResultToken'])
        : (json['partialResultToken'] is String
            ? Either2<num, String>.t2(json['partialResultToken'])
            : (json['partialResultToken'] == null
                ? null
                : (throw '''${json['partialResultToken']} was not one of (num, String)''')));
    return MonikerParams(
        textDocument: textDocument,
        position: position,
        workDoneToken: workDoneToken,
        partialResultToken: partialResultToken);
  }

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  final Either2<num, String> partialResultToken;

  /// The position inside the text document.
  final Position position;

  /// The text document.
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  final Either2<num, String> workDoneToken;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['textDocument'] = textDocument?.toJson() ??
        (throw 'textDocument is required but was not set');
    __result['position'] =
        position?.toJson() ?? (throw 'position is required but was not set');
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    if (partialResultToken != null) {
      __result['partialResultToken'] = partialResultToken;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['textDocument'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(TextDocumentIdentifier.canParse(obj['textDocument'], reporter))) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('position');
      try {
        if (!obj.containsKey('position')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['position'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(Position.canParse(obj['position'], reporter))) {
          reporter.reportError('must be of type Position');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        if (obj['workDoneToken'] != null &&
            !((obj['workDoneToken'] is num ||
                obj['workDoneToken'] is String))) {
          reporter.reportError('must be of type Either2<num, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('partialResultToken');
      try {
        if (obj['partialResultToken'] != null &&
            !((obj['partialResultToken'] is num ||
                obj['partialResultToken'] is String))) {
          reporter.reportError('must be of type Either2<num, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type MonikerParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is MonikerParams && other.runtimeType == MonikerParams) {
      return textDocument == other.textDocument &&
          position == other.position &&
          workDoneToken == other.workDoneToken &&
          partialResultToken == other.partialResultToken &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, textDocument.hashCode);
    hash = JenkinsSmiHash.combine(hash, position.hashCode);
    hash = JenkinsSmiHash.combine(hash, workDoneToken.hashCode);
    hash = JenkinsSmiHash.combine(hash, partialResultToken.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class MonikerRegistrationOptions
    implements TextDocumentRegistrationOptions, MonikerOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
      MonikerRegistrationOptions.canParse, MonikerRegistrationOptions.fromJson);

  MonikerRegistrationOptions({this.documentSelector, this.workDoneProgress});
  static MonikerRegistrationOptions fromJson(Map<String, dynamic> json) {
    final documentSelector = json['documentSelector']
        ?.map((item) => item != null ? DocumentFilter.fromJson(item) : null)
        ?.cast<DocumentFilter>()
        ?.toList();
    final workDoneProgress = json['workDoneProgress'];
    return MonikerRegistrationOptions(
        documentSelector: documentSelector, workDoneProgress: workDoneProgress);
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  final List<DocumentFilter> documentSelector;
  final bool workDoneProgress;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['documentSelector'] = documentSelector;
    if (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['documentSelector'] != null &&
            !((obj['documentSelector'] is List &&
                (obj['documentSelector'].every(
                    (item) => DocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<DocumentFilter>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        if (obj['workDoneProgress'] != null &&
            !(obj['workDoneProgress'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type MonikerRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is MonikerRegistrationOptions &&
        other.runtimeType == MonikerRegistrationOptions) {
      return listEqual(documentSelector, other.documentSelector,
              (DocumentFilter a, DocumentFilter b) => a == b) &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(documentSelector));
    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class NotificationMessage implements Message, IncomingMessage, ToJsonable {
  static const jsonHandler = LspJsonHandler(
      NotificationMessage.canParse, NotificationMessage.fromJson);

  NotificationMessage(
      {@required this.method, this.params, @required this.jsonrpc}) {
    if (method == null) {
      throw 'method is required but was not provided';
    }
    if (jsonrpc == null) {
      throw 'jsonrpc is required but was not provided';
    }
  }
  static NotificationMessage fromJson(Map<String, dynamic> json) {
    final method =
        json['method'] != null ? Method.fromJson(json['method']) : null;
    final params = json['params'];
    final jsonrpc = json['jsonrpc'];
    return NotificationMessage(
        method: method, params: params, jsonrpc: jsonrpc);
  }

  final String jsonrpc;

  /// The method to be invoked.
  final Method method;

  /// The notification's params.
  final dynamic params;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['method'] =
        method?.toJson() ?? (throw 'method is required but was not set');
    if (params != null) {
      __result['params'] = params;
    }
    __result['jsonrpc'] =
        jsonrpc ?? (throw 'jsonrpc is required but was not set');
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('method');
      try {
        if (!obj.containsKey('method')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['method'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(Method.canParse(obj['method'], reporter))) {
          reporter.reportError('must be of type Method');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('params');
      try {
        if (obj['params'] != null && !(true)) {
          reporter.reportError('must be of type dynamic');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('jsonrpc');
      try {
        if (!obj.containsKey('jsonrpc')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['jsonrpc'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['jsonrpc'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type NotificationMessage');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is NotificationMessage &&
        other.runtimeType == NotificationMessage) {
      return method == other.method &&
          params == other.params &&
          jsonrpc == other.jsonrpc &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, method.hashCode);
    hash = JenkinsSmiHash.combine(hash, params.hashCode);
    hash = JenkinsSmiHash.combine(hash, jsonrpc.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class OptionalVersionedTextDocumentIdentifier
    implements TextDocumentIdentifier, ToJsonable {
  static const jsonHandler = LspJsonHandler(
      OptionalVersionedTextDocumentIdentifier.canParse,
      OptionalVersionedTextDocumentIdentifier.fromJson);

  OptionalVersionedTextDocumentIdentifier({this.version, @required this.uri}) {
    if (uri == null) {
      throw 'uri is required but was not provided';
    }
  }
  static OptionalVersionedTextDocumentIdentifier fromJson(
      Map<String, dynamic> json) {
    final version = json['version'];
    final uri = json['uri'];
    return OptionalVersionedTextDocumentIdentifier(version: version, uri: uri);
  }

  /// The text document's URI.
  final String uri;

  /// The version number of this document. If an optional versioned text
  /// document identifier is sent from the server to the client and the file is
  /// not open in the editor (the server has not received an open notification
  /// before) the server can send `null` to indicate that the version is known
  /// and the content on disk is the master (as specified with document content
  /// ownership).
  ///
  /// The version number of a document will increase after each change,
  /// including undo/redo. The number doesn't need to be consecutive.
  final num version;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['version'] = version;
    __result['uri'] = uri ?? (throw 'uri is required but was not set');
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('version');
      try {
        if (!obj.containsKey('version')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['version'] != null && !(obj['version'] is num)) {
          reporter.reportError('must be of type num');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('uri');
      try {
        if (!obj.containsKey('uri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['uri'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['uri'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type OptionalVersionedTextDocumentIdentifier');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is OptionalVersionedTextDocumentIdentifier &&
        other.runtimeType == OptionalVersionedTextDocumentIdentifier) {
      return version == other.version && uri == other.uri && true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, version.hashCode);
    hash = JenkinsSmiHash.combine(hash, uri.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Represents a parameter of a callable-signature. A parameter can have a label
/// and a doc-comment.
class ParameterInformation implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
      ParameterInformation.canParse, ParameterInformation.fromJson);

  ParameterInformation({@required this.label, this.documentation}) {
    if (label == null) {
      throw 'label is required but was not provided';
    }
  }
  static ParameterInformation fromJson(Map<String, dynamic> json) {
    final label = json['label'];
    final documentation = json['documentation'] is String
        ? Either2<String, MarkupContent>.t1(json['documentation'])
        : (MarkupContent.canParse(json['documentation'], nullLspJsonReporter)
            ? Either2<String, MarkupContent>.t2(json['documentation'] != null
                ? MarkupContent.fromJson(json['documentation'])
                : null)
            : (json['documentation'] == null
                ? null
                : (throw '''${json['documentation']} was not one of (String, MarkupContent)''')));
    return ParameterInformation(label: label, documentation: documentation);
  }

  /// The human-readable doc-comment of this parameter. Will be shown in the UI
  /// but can be omitted.
  final Either2<String, MarkupContent> documentation;

  /// The label of this parameter information.
  ///
  /// Either a string or an inclusive start and exclusive end offsets within its
  /// containing signature label. (see SignatureInformation.label). The offsets
  /// are based on a UTF-16 string representation as `Position` and `Range`
  /// does.
  ///
  /// *Note*: a label of type string should be a substring of its containing
  /// signature label. Its intended use case is to highlight the parameter label
  /// part in the `SignatureInformation.label`.
  final String label;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['label'] = label ?? (throw 'label is required but was not set');
    if (documentation != null) {
      __result['documentation'] = documentation;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('label');
      try {
        if (!obj.containsKey('label')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['label'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['label'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('documentation');
      try {
        if (obj['documentation'] != null &&
            !((obj['documentation'] is String ||
                MarkupContent.canParse(obj['documentation'], reporter)))) {
          reporter
              .reportError('must be of type Either2<String, MarkupContent>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ParameterInformation');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is ParameterInformation &&
        other.runtimeType == ParameterInformation) {
      return label == other.label &&
          documentation == other.documentation &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, label.hashCode);
    hash = JenkinsSmiHash.combine(hash, documentation.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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, dynamic> json) {
    if (WorkspaceSymbolParams.canParse(json, nullLspJsonReporter)) {
      return WorkspaceSymbolParams.fromJson(json);
    }
    if (CompletionParams.canParse(json, nullLspJsonReporter)) {
      return CompletionParams.fromJson(json);
    }
    if (DeclarationParams.canParse(json, nullLspJsonReporter)) {
      return DeclarationParams.fromJson(json);
    }
    if (DefinitionParams.canParse(json, nullLspJsonReporter)) {
      return DefinitionParams.fromJson(json);
    }
    if (TypeDefinitionParams.canParse(json, nullLspJsonReporter)) {
      return TypeDefinitionParams.fromJson(json);
    }
    if (ImplementationParams.canParse(json, nullLspJsonReporter)) {
      return ImplementationParams.fromJson(json);
    }
    if (ReferenceParams.canParse(json, nullLspJsonReporter)) {
      return ReferenceParams.fromJson(json);
    }
    if (DocumentHighlightParams.canParse(json, nullLspJsonReporter)) {
      return DocumentHighlightParams.fromJson(json);
    }
    if (DocumentSymbolParams.canParse(json, nullLspJsonReporter)) {
      return DocumentSymbolParams.fromJson(json);
    }
    if (CodeActionParams.canParse(json, nullLspJsonReporter)) {
      return CodeActionParams.fromJson(json);
    }
    if (CodeLensParams.canParse(json, nullLspJsonReporter)) {
      return CodeLensParams.fromJson(json);
    }
    if (DocumentLinkParams.canParse(json, nullLspJsonReporter)) {
      return DocumentLinkParams.fromJson(json);
    }
    if (DocumentColorParams.canParse(json, nullLspJsonReporter)) {
      return DocumentColorParams.fromJson(json);
    }
    if (ColorPresentationParams.canParse(json, nullLspJsonReporter)) {
      return ColorPresentationParams.fromJson(json);
    }
    if (FoldingRangeParams.canParse(json, nullLspJsonReporter)) {
      return FoldingRangeParams.fromJson(json);
    }
    if (SelectionRangeParams.canParse(json, nullLspJsonReporter)) {
      return SelectionRangeParams.fromJson(json);
    }
    if (CallHierarchyIncomingCallsParams.canParse(json, nullLspJsonReporter)) {
      return CallHierarchyIncomingCallsParams.fromJson(json);
    }
    if (CallHierarchyOutgoingCallsParams.canParse(json, nullLspJsonReporter)) {
      return CallHierarchyOutgoingCallsParams.fromJson(json);
    }
    if (SemanticTokensParams.canParse(json, nullLspJsonReporter)) {
      return SemanticTokensParams.fromJson(json);
    }
    if (SemanticTokensDeltaParams.canParse(json, nullLspJsonReporter)) {
      return SemanticTokensDeltaParams.fromJson(json);
    }
    if (SemanticTokensRangeParams.canParse(json, nullLspJsonReporter)) {
      return SemanticTokensRangeParams.fromJson(json);
    }
    if (MonikerParams.canParse(json, nullLspJsonReporter)) {
      return MonikerParams.fromJson(json);
    }
    final partialResultToken = json['partialResultToken'] is num
        ? Either2<num, String>.t1(json['partialResultToken'])
        : (json['partialResultToken'] is String
            ? Either2<num, String>.t2(json['partialResultToken'])
            : (json['partialResultToken'] == null
                ? null
                : (throw '''${json['partialResultToken']} was not one of (num, 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<num, String> partialResultToken;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (partialResultToken != null) {
      __result['partialResultToken'] = partialResultToken;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('partialResultToken');
      try {
        if (obj['partialResultToken'] != null &&
            !((obj['partialResultToken'] is num ||
                obj['partialResultToken'] is String))) {
          reporter.reportError('must be of type Either2<num, 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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, partialResultToken.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class Position implements ToJsonable {
  static const jsonHandler =
      LspJsonHandler(Position.canParse, Position.fromJson);

  Position({@required this.line, @required this.character}) {
    if (line == null) {
      throw 'line is required but was not provided';
    }
    if (character == null) {
      throw 'character is required but was not provided';
    }
  }
  static Position fromJson(Map<String, dynamic> json) {
    final line = json['line'];
    final character = json['character'];
    return Position(line: line, character: character);
  }

  /// Character offset on a line in a document (zero-based). Assuming that the
  /// line is represented as a string, the `character` value represents the gap
  /// between the `character` and `character + 1`.
  ///
  /// If the character value is greater than the line length it defaults back to
  /// the line length.
  final num character;

  /// Line position in a document (zero-based).
  final num line;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['line'] = line ?? (throw 'line is required but was not set');
    __result['character'] =
        character ?? (throw 'character is required but was not set');
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('line');
      try {
        if (!obj.containsKey('line')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['line'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['line'] is num)) {
          reporter.reportError('must be of type num');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('character');
      try {
        if (!obj.containsKey('character')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['character'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['character'] is num)) {
          reporter.reportError('must be of type num');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type Position');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is Position && other.runtimeType == Position) {
      return line == other.line && character == other.character && true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, line.hashCode);
    hash = JenkinsSmiHash.combine(hash, character.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class PrepareRenameParams implements TextDocumentPositionParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
      PrepareRenameParams.canParse, PrepareRenameParams.fromJson);

  PrepareRenameParams({@required this.textDocument, @required this.position}) {
    if (textDocument == null) {
      throw 'textDocument is required but was not provided';
    }
    if (position == null) {
      throw 'position is required but was not provided';
    }
  }
  static PrepareRenameParams fromJson(Map<String, dynamic> json) {
    final textDocument = json['textDocument'] != null
        ? TextDocumentIdentifier.fromJson(json['textDocument'])
        : null;
    final position =
        json['position'] != null ? Position.fromJson(json['position']) : null;
    return PrepareRenameParams(textDocument: textDocument, position: position);
  }

  /// The position inside the text document.
  final Position position;

  /// The text document.
  final TextDocumentIdentifier textDocument;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['textDocument'] = textDocument?.toJson() ??
        (throw 'textDocument is required but was not set');
    __result['position'] =
        position?.toJson() ?? (throw 'position is required but was not set');
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['textDocument'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(TextDocumentIdentifier.canParse(obj['textDocument'], reporter))) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('position');
      try {
        if (!obj.containsKey('position')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['position'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(Position.canParse(obj['position'], reporter))) {
          reporter.reportError('must be of type Position');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type PrepareRenameParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is PrepareRenameParams &&
        other.runtimeType == PrepareRenameParams) {
      return textDocument == other.textDocument &&
          position == other.position &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, textDocument.hashCode);
    hash = JenkinsSmiHash.combine(hash, position.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class PrepareSupportDefaultBehavior {
  const PrepareSupportDefaultBehavior(this._value);
  const PrepareSupportDefaultBehavior.fromJson(this._value);

  final num _value;

  static bool canParse(Object obj, LspJsonReporter reporter) {
    return obj is num;
  }

  /// The client's default behavior is to select the identifier according the to
  /// language's syntax rule.
  static const Identifier = PrepareSupportDefaultBehavior(1);

  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  bool operator ==(Object o) =>
      o is PrepareSupportDefaultBehavior && o._value == _value;
}

class ProgressParams<T> implements ToJsonable {
  static const jsonHandler =
      LspJsonHandler(ProgressParams.canParse, ProgressParams.fromJson);

  ProgressParams({@required this.token, @required this.value}) {
    if (token == null) {
      throw 'token is required but was not provided';
    }
    if (value == null) {
      throw 'value is required but was not provided';
    }
  }
  static ProgressParams<T> fromJson<T>(Map<String, dynamic> json) {
    final token = json['token'] is num
        ? Either2<num, String>.t1(json['token'])
        : (json['token'] is String
            ? Either2<num, String>.t2(json['token'])
            : (throw '''${json['token']} was not one of (num, String)'''));
    final value = json['value'];
    return ProgressParams<T>(token: token, value: value);
  }

  /// The progress token provided by the client or server.
  final Either2<num, String> token;

  /// The progress data.
  final T value;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['token'] = token ?? (throw 'token is required but was not set');
    __result['value'] = value ?? (throw 'value is required but was not set');
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('token');
      try {
        if (!obj.containsKey('token')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['token'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!((obj['token'] is num || obj['token'] is String))) {
          reporter.reportError('must be of type Either2<num, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('value');
      try {
        if (!obj.containsKey('value')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['value'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(true /* T.canParse(obj['value']) */)) {
          reporter.reportError('must be of type T');
          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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, token.hashCode);
    hash = JenkinsSmiHash.combine(hash, value.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class PublishDiagnosticsClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
      PublishDiagnosticsClientCapabilities.canParse,
      PublishDiagnosticsClientCapabilities.fromJson);

  PublishDiagnosticsClientCapabilities(
      {this.relatedInformation,
      this.tagSupport,
      this.versionSupport,
      this.codeDescriptionSupport,
      this.dataSupport});
  static PublishDiagnosticsClientCapabilities fromJson(
      Map<String, dynamic> json) {
    final relatedInformation = json['relatedInformation'];
    final tagSupport = json['tagSupport'] != null
        ? PublishDiagnosticsClientCapabilitiesTagSupport.fromJson(
            json['tagSupport'])
        : null;
    final versionSupport = json['versionSupport'];
    final codeDescriptionSupport = json['codeDescriptionSupport'];
    final dataSupport = json['dataSupport'];
    return PublishDiagnosticsClientCapabilities(
        relatedInformation: relatedInformation,
        tagSupport: tagSupport,
        versionSupport: versionSupport,
        codeDescriptionSupport: codeDescriptionSupport,
        dataSupport: dataSupport);
  }

  /// Client supports a codeDescription property
  ///  @since 3.16.0
  final bool codeDescriptionSupport;

  /// Whether code action supports the `data` property which is preserved
  /// between a `textDocument/publishDiagnostics` and `textDocument/codeAction`
  /// request.
  ///  @since 3.16.0
  final bool dataSupport;

  /// Whether the clients accepts diagnostics with related information.
  final bool relatedInformation;

  /// Client supports the tag property to provide meta data about a diagnostic.
  /// Clients supporting tags have to handle unknown tags gracefully.
  ///  @since 3.15.0
  final PublishDiagnosticsClientCapabilitiesTagSupport tagSupport;

  /// Whether the client interprets the version property of the
  /// `textDocument/publishDiagnostics` notification's parameter.
  ///  @since 3.15.0
  final bool versionSupport;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (relatedInformation != null) {
      __result['relatedInformation'] = relatedInformation;
    }
    if (tagSupport != null) {
      __result['tagSupport'] = tagSupport.toJson();
    }
    if (versionSupport != null) {
      __result['versionSupport'] = versionSupport;
    }
    if (codeDescriptionSupport != null) {
      __result['codeDescriptionSupport'] = codeDescriptionSupport;
    }
    if (dataSupport != null) {
      __result['dataSupport'] = dataSupport;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('relatedInformation');
      try {
        if (obj['relatedInformation'] != null &&
            !(obj['relatedInformation'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('tagSupport');
      try {
        if (obj['tagSupport'] != null &&
            !(PublishDiagnosticsClientCapabilitiesTagSupport.canParse(
                obj['tagSupport'], reporter))) {
          reporter.reportError(
              'must be of type PublishDiagnosticsClientCapabilitiesTagSupport');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('versionSupport');
      try {
        if (obj['versionSupport'] != null && !(obj['versionSupport'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('codeDescriptionSupport');
      try {
        if (obj['codeDescriptionSupport'] != null &&
            !(obj['codeDescriptionSupport'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('dataSupport');
      try {
        if (obj['dataSupport'] != null && !(obj['dataSupport'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter
          .reportError('must be of type PublishDiagnosticsClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is PublishDiagnosticsClientCapabilities &&
        other.runtimeType == PublishDiagnosticsClientCapabilities) {
      return relatedInformation == other.relatedInformation &&
          tagSupport == other.tagSupport &&
          versionSupport == other.versionSupport &&
          codeDescriptionSupport == other.codeDescriptionSupport &&
          dataSupport == other.dataSupport &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, relatedInformation.hashCode);
    hash = JenkinsSmiHash.combine(hash, tagSupport.hashCode);
    hash = JenkinsSmiHash.combine(hash, versionSupport.hashCode);
    hash = JenkinsSmiHash.combine(hash, codeDescriptionSupport.hashCode);
    hash = JenkinsSmiHash.combine(hash, dataSupport.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class PublishDiagnosticsClientCapabilitiesTagSupport implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
      PublishDiagnosticsClientCapabilitiesTagSupport.canParse,
      PublishDiagnosticsClientCapabilitiesTagSupport.fromJson);

  PublishDiagnosticsClientCapabilitiesTagSupport({@required this.valueSet}) {
    if (valueSet == null) {
      throw 'valueSet is required but was not provided';
    }
  }
  static PublishDiagnosticsClientCapabilitiesTagSupport fromJson(
      Map<String, dynamic> json) {
    final valueSet = json['valueSet']
        ?.map((item) => item != null ? DiagnosticTag.fromJson(item) : null)
        ?.cast<DiagnosticTag>()
        ?.toList();
    return PublishDiagnosticsClientCapabilitiesTagSupport(valueSet: valueSet);
  }

  /// The tags supported by the client.
  final List<DiagnosticTag> valueSet;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['valueSet'] = valueSet?.map((item) => item.toJson())?.toList() ??
        (throw 'valueSet is required but was not set');
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('valueSet');
      try {
        if (!obj.containsKey('valueSet')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['valueSet'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!((obj['valueSet'] is List &&
            (obj['valueSet']
                .every((item) => DiagnosticTag.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<DiagnosticTag>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type PublishDiagnosticsClientCapabilitiesTagSupport');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is PublishDiagnosticsClientCapabilitiesTagSupport &&
        other.runtimeType == PublishDiagnosticsClientCapabilitiesTagSupport) {
      return listEqual(valueSet, other.valueSet,
              (DiagnosticTag a, DiagnosticTag b) => a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(valueSet));
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class PublishDiagnosticsParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
      PublishDiagnosticsParams.canParse, PublishDiagnosticsParams.fromJson);

  PublishDiagnosticsParams(
      {@required this.uri, this.version, @required this.diagnostics}) {
    if (uri == null) {
      throw 'uri is required but was not provided';
    }
    if (diagnostics == null) {
      throw 'diagnostics is required but was not provided';
    }
  }
  static PublishDiagnosticsParams fromJson(Map<String, dynamic> json) {
    final uri = json['uri'];
    final version = json['version'];
    final diagnostics = json['diagnostics']
        ?.map((item) => item != null ? Diagnostic.fromJson(item) : null)
        ?.cast<Diagnostic>()
        ?.toList();
    return PublishDiagnosticsParams(
        uri: uri, version: version, diagnostics: diagnostics);
  }

  /// An array of diagnostic information items.
  final List<Diagnostic> diagnostics;

  /// The URI for which diagnostic information is reported.
  final String uri;

  /// Optional the version number of the document the diagnostics are published
  /// for.
  ///  @since 3.15.0
  final num version;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['uri'] = uri ?? (throw 'uri is required but was not set');
    if (version != null) {
      __result['version'] = version;
    }
    __result['diagnostics'] =
        diagnostics?.map((item) => item.toJson())?.toList() ??
            (throw 'diagnostics is required but was not set');
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('uri');
      try {
        if (!obj.containsKey('uri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['uri'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['uri'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('version');
      try {
        if (obj['version'] != null && !(obj['version'] is num)) {
          reporter.reportError('must be of type num');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('diagnostics');
      try {
        if (!obj.containsKey('diagnostics')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['diagnostics'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!((obj['diagnostics'] is List &&
            (obj['diagnostics']
                .every((item) => Diagnostic.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<Diagnostic>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type PublishDiagnosticsParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is PublishDiagnosticsParams &&
        other.runtimeType == PublishDiagnosticsParams) {
      return uri == other.uri &&
          version == other.version &&
          listEqual(diagnostics, other.diagnostics,
              (Diagnostic a, Diagnostic b) => a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, uri.hashCode);
    hash = JenkinsSmiHash.combine(hash, version.hashCode);
    hash = JenkinsSmiHash.combine(hash, lspHashCode(diagnostics));
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class Range implements ToJsonable {
  static const jsonHandler = LspJsonHandler(Range.canParse, Range.fromJson);

  Range({@required this.start, @required this.end}) {
    if (start == null) {
      throw 'start is required but was not provided';
    }
    if (end == null) {
      throw 'end is required but was not provided';
    }
  }
  static Range fromJson(Map<String, dynamic> json) {
    final start =
        json['start'] != null ? Position.fromJson(json['start']) : null;
    final end = json['end'] != null ? Position.fromJson(json['end']) : null;
    return Range(start: start, end: end);
  }

  /// The range's end position.
  final Position end;

  /// The range's start position.
  final Position start;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['start'] =
        start?.toJson() ?? (throw 'start is required but was not set');
    __result['end'] =
        end?.toJson() ?? (throw 'end is required but was not set');
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('start');
      try {
        if (!obj.containsKey('start')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['start'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(Position.canParse(obj['start'], reporter))) {
          reporter.reportError('must be of type Position');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('end');
      try {
        if (!obj.containsKey('end')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['end'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(Position.canParse(obj['end'], reporter))) {
          reporter.reportError('must be of type Position');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type Range');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is Range && other.runtimeType == Range) {
      return start == other.start && end == other.end && true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, start.hashCode);
    hash = JenkinsSmiHash.combine(hash, end.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class RangeAndPlaceholder implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
      RangeAndPlaceholder.canParse, RangeAndPlaceholder.fromJson);

  RangeAndPlaceholder({@required this.range, @required this.placeholder}) {
    if (range == null) {
      throw 'range is required but was not provided';
    }
    if (placeholder == null) {
      throw 'placeholder is required but was not provided';
    }
  }
  static RangeAndPlaceholder fromJson(Map<String, dynamic> json) {
    final range = json['range'] != null ? Range.fromJson(json['range']) : null;
    final placeholder = json['placeholder'];
    return RangeAndPlaceholder(range: range, placeholder: placeholder);
  }

  final String placeholder;
  final Range range;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['range'] =
        range?.toJson() ?? (throw 'range is required but was not set');
    __result['placeholder'] =
        placeholder ?? (throw 'placeholder is required but was not set');
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('range');
      try {
        if (!obj.containsKey('range')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['range'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(Range.canParse(obj['range'], reporter))) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('placeholder');
      try {
        if (!obj.containsKey('placeholder')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['placeholder'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['placeholder'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type RangeAndPlaceholder');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is RangeAndPlaceholder &&
        other.runtimeType == RangeAndPlaceholder) {
      return range == other.range && placeholder == other.placeholder && true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, range.hashCode);
    hash = JenkinsSmiHash.combine(hash, placeholder.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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, dynamic> json) {
    final dynamicRegistration = json['dynamicRegistration'];
    return ReferenceClientCapabilities(
        dynamicRegistration: dynamicRegistration);
  }

  /// Whether references supports dynamic registration.
  final bool dynamicRegistration;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (dynamicRegistration != null) {
      __result['dynamicRegistration'] = dynamicRegistration;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('dynamicRegistration');
      try {
        if (obj['dynamicRegistration'] != null &&
            !(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class ReferenceContext implements ToJsonable {
  static const jsonHandler =
      LspJsonHandler(ReferenceContext.canParse, ReferenceContext.fromJson);

  ReferenceContext({@required this.includeDeclaration}) {
    if (includeDeclaration == null) {
      throw 'includeDeclaration is required but was not provided';
    }
  }
  static ReferenceContext fromJson(Map<String, dynamic> json) {
    final includeDeclaration = json['includeDeclaration'];
    return ReferenceContext(includeDeclaration: includeDeclaration);
  }

  /// Include the declaration of the current symbol.
  final bool includeDeclaration;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['includeDeclaration'] = includeDeclaration ??
        (throw 'includeDeclaration is required but was not set');
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('includeDeclaration');
      try {
        if (!obj.containsKey('includeDeclaration')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['includeDeclaration'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, includeDeclaration.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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, dynamic> json) {
    if (ReferenceRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return ReferenceRegistrationOptions.fromJson(json);
    }
    final workDoneProgress = json['workDoneProgress'];
    return ReferenceOptions(workDoneProgress: workDoneProgress);
  }

  final bool workDoneProgress;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('workDoneProgress');
      try {
        if (obj['workDoneProgress'] != null &&
            !(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class ReferenceParams
    implements
        TextDocumentPositionParams,
        WorkDoneProgressParams,
        PartialResultParams,
        ToJsonable {
  static const jsonHandler =
      LspJsonHandler(ReferenceParams.canParse, ReferenceParams.fromJson);

  ReferenceParams(
      {@required this.context,
      @required this.textDocument,
      @required this.position,
      this.workDoneToken,
      this.partialResultToken}) {
    if (context == null) {
      throw 'context is required but was not provided';
    }
    if (textDocument == null) {
      throw 'textDocument is required but was not provided';
    }
    if (position == null) {
      throw 'position is required but was not provided';
    }
  }
  static ReferenceParams fromJson(Map<String, dynamic> json) {
    final context = json['context'] != null
        ? ReferenceContext.fromJson(json['context'])
        : null;
    final textDocument = json['textDocument'] != null
        ? TextDocumentIdentifier.fromJson(json['textDocument'])
        : null;
    final position =
        json['position'] != null ? Position.fromJson(json['position']) : null;
    final workDoneToken = json['workDoneToken'] is num
        ? Either2<num, String>.t1(json['workDoneToken'])
        : (json['workDoneToken'] is String
            ? Either2<num, String>.t2(json['workDoneToken'])
            : (json['workDoneToken'] == null
                ? null
                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
    final partialResultToken = json['partialResultToken'] is num
        ? Either2<num, String>.t1(json['partialResultToken'])
        : (json['partialResultToken'] is String
            ? Either2<num, String>.t2(json['partialResultToken'])
            : (json['partialResultToken'] == null
                ? null
                : (throw '''${json['partialResultToken']} was not one of (num, String)''')));
    return ReferenceParams(
        context: context,
        textDocument: textDocument,
        position: position,
        workDoneToken: workDoneToken,
        partialResultToken: partialResultToken);
  }

  final ReferenceContext context;

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  final Either2<num, String> partialResultToken;

  /// The position inside the text document.
  final Position position;

  /// The text document.
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  final Either2<num, String> workDoneToken;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['context'] =
        context?.toJson() ?? (throw 'context is required but was not set');
    __result['textDocument'] = textDocument?.toJson() ??
        (throw 'textDocument is required but was not set');
    __result['position'] =
        position?.toJson() ?? (throw 'position is required but was not set');
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    if (partialResultToken != null) {
      __result['partialResultToken'] = partialResultToken;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('context');
      try {
        if (!obj.containsKey('context')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['context'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(ReferenceContext.canParse(obj['context'], reporter))) {
          reporter.reportError('must be of type ReferenceContext');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['textDocument'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(TextDocumentIdentifier.canParse(obj['textDocument'], reporter))) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('position');
      try {
        if (!obj.containsKey('position')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['position'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(Position.canParse(obj['position'], reporter))) {
          reporter.reportError('must be of type Position');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        if (obj['workDoneToken'] != null &&
            !((obj['workDoneToken'] is num ||
                obj['workDoneToken'] is String))) {
          reporter.reportError('must be of type Either2<num, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('partialResultToken');
      try {
        if (obj['partialResultToken'] != null &&
            !((obj['partialResultToken'] is num ||
                obj['partialResultToken'] is String))) {
          reporter.reportError('must be of type Either2<num, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ReferenceParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is ReferenceParams && other.runtimeType == ReferenceParams) {
      return context == other.context &&
          textDocument == other.textDocument &&
          position == other.position &&
          workDoneToken == other.workDoneToken &&
          partialResultToken == other.partialResultToken &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, context.hashCode);
    hash = JenkinsSmiHash.combine(hash, textDocument.hashCode);
    hash = JenkinsSmiHash.combine(hash, position.hashCode);
    hash = JenkinsSmiHash.combine(hash, workDoneToken.hashCode);
    hash = JenkinsSmiHash.combine(hash, partialResultToken.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class ReferenceRegistrationOptions
    implements TextDocumentRegistrationOptions, ReferenceOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
      ReferenceRegistrationOptions.canParse,
      ReferenceRegistrationOptions.fromJson);

  ReferenceRegistrationOptions({this.documentSelector, this.workDoneProgress});
  static ReferenceRegistrationOptions fromJson(Map<String, dynamic> json) {
    final documentSelector = json['documentSelector']
        ?.map((item) => item != null ? DocumentFilter.fromJson(item) : null)
        ?.cast<DocumentFilter>()
        ?.toList();
    final workDoneProgress = json['workDoneProgress'];
    return ReferenceRegistrationOptions(
        documentSelector: documentSelector, workDoneProgress: workDoneProgress);
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  final List<DocumentFilter> documentSelector;
  final bool workDoneProgress;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['documentSelector'] = documentSelector;
    if (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['documentSelector'] != null &&
            !((obj['documentSelector'] is List &&
                (obj['documentSelector'].every(
                    (item) => DocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<DocumentFilter>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        if (obj['workDoneProgress'] != null &&
            !(obj['workDoneProgress'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ReferenceRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is ReferenceRegistrationOptions &&
        other.runtimeType == ReferenceRegistrationOptions) {
      return listEqual(documentSelector, other.documentSelector,
              (DocumentFilter a, DocumentFilter b) => a == b) &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(documentSelector));
    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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}) {
    if (id == null) {
      throw 'id is required but was not provided';
    }
    if (method == null) {
      throw 'method is required but was not provided';
    }
  }
  static Registration fromJson(Map<String, dynamic> json) {
    final id = json['id'];
    final method = json['method'];
    final registerOptions = json['registerOptions'];
    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 dynamic registerOptions;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['id'] = id ?? (throw 'id is required but was not set');
    __result['method'] = method ?? (throw 'method is required but was not set');
    if (registerOptions != null) {
      __result['registerOptions'] = registerOptions;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('id');
      try {
        if (!obj.containsKey('id')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['id'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['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;
        }
        if (obj['method'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['method'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('registerOptions');
      try {
        if (obj['registerOptions'] != null && !(true)) {
          reporter.reportError('must be of type dynamic');
          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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, id.hashCode);
    hash = JenkinsSmiHash.combine(hash, method.hashCode);
    hash = JenkinsSmiHash.combine(hash, registerOptions.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class RegistrationParams implements ToJsonable {
  static const jsonHandler =
      LspJsonHandler(RegistrationParams.canParse, RegistrationParams.fromJson);

  RegistrationParams({@required this.registrations}) {
    if (registrations == null) {
      throw 'registrations is required but was not provided';
    }
  }
  static RegistrationParams fromJson(Map<String, dynamic> json) {
    final registrations = json['registrations']
        ?.map((item) => item != null ? Registration.fromJson(item) : null)
        ?.cast<Registration>()
        ?.toList();
    return RegistrationParams(registrations: registrations);
  }

  final List<Registration> registrations;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['registrations'] =
        registrations?.map((item) => item.toJson())?.toList() ??
            (throw 'registrations is required but was not set');
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('registrations');
      try {
        if (!obj.containsKey('registrations')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['registrations'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!((obj['registrations'] is List &&
            (obj['registrations']
                .every((item) => Registration.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<Registration>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type RegistrationParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is RegistrationParams &&
        other.runtimeType == RegistrationParams) {
      return listEqual(registrations, other.registrations,
              (Registration a, Registration b) => a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(registrations));
    return JenkinsSmiHash.finish(hash);
  }

  @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}) {
    if (engine == null) {
      throw 'engine is required but was not provided';
    }
  }
  static RegularExpressionsClientCapabilities fromJson(
      Map<String, dynamic> json) {
    final engine = json['engine'];
    final version = json['version'];
    return RegularExpressionsClientCapabilities(
        engine: engine, version: version);
  }

  /// The engine's name.
  final String engine;

  /// The engine's version.
  final String version;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['engine'] = engine ?? (throw 'engine is required but was not set');
    if (version != null) {
      __result['version'] = version;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('engine');
      try {
        if (!obj.containsKey('engine')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['engine'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['engine'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('version');
      try {
        if (obj['version'] != null && !(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, engine.hashCode);
    hash = JenkinsSmiHash.combine(hash, version.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class RenameClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
      RenameClientCapabilities.canParse, RenameClientCapabilities.fromJson);

  RenameClientCapabilities(
      {this.dynamicRegistration,
      this.prepareSupport,
      this.prepareSupportDefaultBehavior,
      this.honorsChangeAnnotations});
  static RenameClientCapabilities fromJson(Map<String, dynamic> json) {
    final dynamicRegistration = json['dynamicRegistration'];
    final prepareSupport = json['prepareSupport'];
    final prepareSupportDefaultBehavior =
        json['prepareSupportDefaultBehavior'] != null
            ? PrepareSupportDefaultBehavior.fromJson(
                json['prepareSupportDefaultBehavior'])
            : null;
    final honorsChangeAnnotations = json['honorsChangeAnnotations'];
    return RenameClientCapabilities(
        dynamicRegistration: dynamicRegistration,
        prepareSupport: prepareSupport,
        prepareSupportDefaultBehavior: prepareSupportDefaultBehavior,
        honorsChangeAnnotations: honorsChangeAnnotations);
  }

  /// Whether rename supports dynamic registration.
  final bool dynamicRegistration;

  /// Whether th client honors the change annotations in text edits and resource
  /// operations returned via the rename request's workspace edit by for example
  /// presenting the workspace edit in the user interface and asking for
  /// confirmation.
  ///  @since 3.16.0
  final bool honorsChangeAnnotations;

  /// Client supports testing for validity of rename operations before
  /// execution.
  ///  @since version 3.12.0
  final bool prepareSupport;

  /// Client supports the default behavior result (`{ defaultBehavior: boolean
  /// }`).
  ///
  /// The value indicates the default behavior used by the client.
  ///  @since version 3.16.0
  final PrepareSupportDefaultBehavior prepareSupportDefaultBehavior;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (dynamicRegistration != null) {
      __result['dynamicRegistration'] = dynamicRegistration;
    }
    if (prepareSupport != null) {
      __result['prepareSupport'] = prepareSupport;
    }
    if (prepareSupportDefaultBehavior != null) {
      __result['prepareSupportDefaultBehavior'] =
          prepareSupportDefaultBehavior.toJson();
    }
    if (honorsChangeAnnotations != null) {
      __result['honorsChangeAnnotations'] = honorsChangeAnnotations;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('dynamicRegistration');
      try {
        if (obj['dynamicRegistration'] != null &&
            !(obj['dynamicRegistration'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('prepareSupport');
      try {
        if (obj['prepareSupport'] != null && !(obj['prepareSupport'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('prepareSupportDefaultBehavior');
      try {
        if (obj['prepareSupportDefaultBehavior'] != null &&
            !(PrepareSupportDefaultBehavior.canParse(
                obj['prepareSupportDefaultBehavior'], reporter))) {
          reporter.reportError('must be of type PrepareSupportDefaultBehavior');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('honorsChangeAnnotations');
      try {
        if (obj['honorsChangeAnnotations'] != null &&
            !(obj['honorsChangeAnnotations'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type RenameClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is RenameClientCapabilities &&
        other.runtimeType == RenameClientCapabilities) {
      return dynamicRegistration == other.dynamicRegistration &&
          prepareSupport == other.prepareSupport &&
          prepareSupportDefaultBehavior ==
              other.prepareSupportDefaultBehavior &&
          honorsChangeAnnotations == other.honorsChangeAnnotations &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode);
    hash = JenkinsSmiHash.combine(hash, prepareSupport.hashCode);
    hash = JenkinsSmiHash.combine(hash, prepareSupportDefaultBehavior.hashCode);
    hash = JenkinsSmiHash.combine(hash, honorsChangeAnnotations.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Rename file operation
class RenameFile implements ToJsonable {
  static const jsonHandler =
      LspJsonHandler(RenameFile.canParse, RenameFile.fromJson);

  RenameFile(
      {this.kind = 'rename',
      @required this.oldUri,
      @required this.newUri,
      this.options,
      this.annotationId}) {
    if (kind != 'rename') {
      throw 'kind may only be the literal \'rename\'';
    }
    if (oldUri == null) {
      throw 'oldUri is required but was not provided';
    }
    if (newUri == null) {
      throw 'newUri is required but was not provided';
    }
  }
  static RenameFile fromJson(Map<String, dynamic> json) {
    final kind = json['kind'];
    final oldUri = json['oldUri'];
    final newUri = json['newUri'];
    final options = json['options'] != null
        ? RenameFileOptions.fromJson(json['options'])
        : null;
    final annotationId = json['annotationId'];
    return RenameFile(
        kind: kind,
        oldUri: oldUri,
        newUri: newUri,
        options: options,
        annotationId: annotationId);
  }

  /// An optional annotation identifer describing the operation.
  ///  @since 3.16.0
  final String annotationId;

  /// A rename
  final String kind;

  /// The new location.
  final String newUri;

  /// The old (existing) location.
  final String oldUri;

  /// Rename options.
  final RenameFileOptions options;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['kind'] = kind ?? (throw 'kind is required but was not set');
    __result['oldUri'] = oldUri ?? (throw 'oldUri is required but was not set');
    __result['newUri'] = newUri ?? (throw 'newUri is required but was not set');
    if (options != null) {
      __result['options'] = options.toJson();
    }
    if (annotationId != null) {
      __result['annotationId'] = annotationId;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('kind');
      try {
        if (!obj.containsKey('kind')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['kind'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['kind'] == 'rename')) {
          reporter.reportError('must be the literal \'rename\'');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('oldUri');
      try {
        if (!obj.containsKey('oldUri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['oldUri'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['oldUri'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('newUri');
      try {
        if (!obj.containsKey('newUri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['newUri'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['newUri'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('options');
      try {
        if (obj['options'] != null &&
            !(RenameFileOptions.canParse(obj['options'], reporter))) {
          reporter.reportError('must be of type RenameFileOptions');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('annotationId');
      try {
        if (obj['annotationId'] != null && !(obj['annotationId'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type RenameFile');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is RenameFile && other.runtimeType == RenameFile) {
      return kind == other.kind &&
          oldUri == other.oldUri &&
          newUri == other.newUri &&
          options == other.options &&
          annotationId == other.annotationId &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, kind.hashCode);
    hash = JenkinsSmiHash.combine(hash, oldUri.hashCode);
    hash = JenkinsSmiHash.combine(hash, newUri.hashCode);
    hash = JenkinsSmiHash.combine(hash, options.hashCode);
    hash = JenkinsSmiHash.combine(hash, annotationId.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Rename file options
class RenameFileOptions implements ToJsonable {
  static const jsonHandler =
      LspJsonHandler(RenameFileOptions.canParse, RenameFileOptions.fromJson);

  RenameFileOptions({this.overwrite, this.ignoreIfExists});
  static RenameFileOptions fromJson(Map<String, dynamic> json) {
    final overwrite = json['overwrite'];
    final ignoreIfExists = json['ignoreIfExists'];
    return RenameFileOptions(
        overwrite: overwrite, ignoreIfExists: ignoreIfExists);
  }

  /// Ignores if target exists.
  final bool ignoreIfExists;

  /// Overwrite target if existing. Overwrite wins over `ignoreIfExists`
  final bool overwrite;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (overwrite != null) {
      __result['overwrite'] = overwrite;
    }
    if (ignoreIfExists != null) {
      __result['ignoreIfExists'] = ignoreIfExists;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('overwrite');
      try {
        if (obj['overwrite'] != null && !(obj['overwrite'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('ignoreIfExists');
      try {
        if (obj['ignoreIfExists'] != null && !(obj['ignoreIfExists'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type RenameFileOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is RenameFileOptions && other.runtimeType == RenameFileOptions) {
      return overwrite == other.overwrite &&
          ignoreIfExists == other.ignoreIfExists &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, overwrite.hashCode);
    hash = JenkinsSmiHash.combine(hash, ignoreIfExists.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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}) {
    if (files == null) {
      throw 'files is required but was not provided';
    }
  }
  static RenameFilesParams fromJson(Map<String, dynamic> json) {
    final files = json['files']
        ?.map((item) => item != null ? FileRename.fromJson(item) : null)
        ?.cast<FileRename>()
        ?.toList();
    return RenameFilesParams(files: files);
  }

  /// An array of all files/folders renamed in this operation. When a folder is
  /// renamed, only the folder will be included, and not its children.
  final List<FileRename> files;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['files'] = files?.map((item) => item.toJson())?.toList() ??
        (throw 'files is required but was not set');
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('files');
      try {
        if (!obj.containsKey('files')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['files'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!((obj['files'] is List &&
            (obj['files']
                .every((item) => FileRename.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<FileRename>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type RenameFilesParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is RenameFilesParams && other.runtimeType == RenameFilesParams) {
      return listEqual(
              files, other.files, (FileRename a, FileRename b) => a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(files));
    return JenkinsSmiHash.finish(hash);
  }

  @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, dynamic> json) {
    if (RenameRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return RenameRegistrationOptions.fromJson(json);
    }
    final prepareProvider = json['prepareProvider'];
    final workDoneProgress = json['workDoneProgress'];
    return RenameOptions(
        prepareProvider: prepareProvider, workDoneProgress: workDoneProgress);
  }

  /// Renames should be checked and tested before being executed.
  final bool prepareProvider;
  final bool workDoneProgress;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    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, dynamic>) {
      reporter.push('prepareProvider');
      try {
        if (obj['prepareProvider'] != null &&
            !(obj['prepareProvider'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        if (obj['workDoneProgress'] != null &&
            !(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, prepareProvider.hashCode);
    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class RenameParams
    implements TextDocumentPositionParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler =
      LspJsonHandler(RenameParams.canParse, RenameParams.fromJson);

  RenameParams(
      {@required this.newName,
      @required this.textDocument,
      @required this.position,
      this.workDoneToken}) {
    if (newName == null) {
      throw 'newName is required but was not provided';
    }
    if (textDocument == null) {
      throw 'textDocument is required but was not provided';
    }
    if (position == null) {
      throw 'position is required but was not provided';
    }
  }
  static RenameParams fromJson(Map<String, dynamic> json) {
    final newName = json['newName'];
    final textDocument = json['textDocument'] != null
        ? TextDocumentIdentifier.fromJson(json['textDocument'])
        : null;
    final position =
        json['position'] != null ? Position.fromJson(json['position']) : null;
    final workDoneToken = json['workDoneToken'] is num
        ? Either2<num, String>.t1(json['workDoneToken'])
        : (json['workDoneToken'] is String
            ? Either2<num, String>.t2(json['workDoneToken'])
            : (json['workDoneToken'] == null
                ? null
                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
    return RenameParams(
        newName: newName,
        textDocument: textDocument,
        position: position,
        workDoneToken: workDoneToken);
  }

  /// The new name of the symbol. If the given name is not valid the request
  /// must return a [ResponseError] with an appropriate message set.
  final String newName;

  /// The position inside the text document.
  final Position position;

  /// The text document.
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  final Either2<num, String> workDoneToken;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['newName'] =
        newName ?? (throw 'newName is required but was not set');
    __result['textDocument'] = textDocument?.toJson() ??
        (throw 'textDocument is required but was not set');
    __result['position'] =
        position?.toJson() ?? (throw 'position is required but was not set');
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('newName');
      try {
        if (!obj.containsKey('newName')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['newName'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['newName'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['textDocument'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(TextDocumentIdentifier.canParse(obj['textDocument'], reporter))) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('position');
      try {
        if (!obj.containsKey('position')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['position'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(Position.canParse(obj['position'], reporter))) {
          reporter.reportError('must be of type Position');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        if (obj['workDoneToken'] != null &&
            !((obj['workDoneToken'] is num ||
                obj['workDoneToken'] is String))) {
          reporter.reportError('must be of type Either2<num, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type RenameParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is RenameParams && other.runtimeType == RenameParams) {
      return newName == other.newName &&
          textDocument == other.textDocument &&
          position == other.position &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, newName.hashCode);
    hash = JenkinsSmiHash.combine(hash, textDocument.hashCode);
    hash = JenkinsSmiHash.combine(hash, position.hashCode);
    hash = JenkinsSmiHash.combine(hash, workDoneToken.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class RenameRegistrationOptions
    implements TextDocumentRegistrationOptions, RenameOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
      RenameRegistrationOptions.canParse, RenameRegistrationOptions.fromJson);

  RenameRegistrationOptions(
      {this.documentSelector, this.prepareProvider, this.workDoneProgress});
  static RenameRegistrationOptions fromJson(Map<String, dynamic> json) {
    final documentSelector = json['documentSelector']
        ?.map((item) => item != null ? DocumentFilter.fromJson(item) : null)
        ?.cast<DocumentFilter>()
        ?.toList();
    final prepareProvider = json['prepareProvider'];
    final workDoneProgress = json['workDoneProgress'];
    return RenameRegistrationOptions(
        documentSelector: documentSelector,
        prepareProvider: prepareProvider,
        workDoneProgress: workDoneProgress);
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  final List<DocumentFilter> documentSelector;

  /// Renames should be checked and tested before being executed.
  final bool prepareProvider;
  final bool workDoneProgress;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __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, dynamic>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['documentSelector'] != null &&
            !((obj['documentSelector'] is List &&
                (obj['documentSelector'].every(
                    (item) => DocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<DocumentFilter>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('prepareProvider');
      try {
        if (obj['prepareProvider'] != null &&
            !(obj['prepareProvider'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        if (obj['workDoneProgress'] != null &&
            !(obj['workDoneProgress'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type RenameRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is RenameRegistrationOptions &&
        other.runtimeType == RenameRegistrationOptions) {
      return listEqual(documentSelector, other.documentSelector,
              (DocumentFilter a, DocumentFilter b) => a == b) &&
          prepareProvider == other.prepareProvider &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(documentSelector));
    hash = JenkinsSmiHash.combine(hash, prepareProvider.hashCode);
    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class RequestMessage implements Message, IncomingMessage, ToJsonable {
  static const jsonHandler =
      LspJsonHandler(RequestMessage.canParse, RequestMessage.fromJson);

  RequestMessage(
      {@required this.id,
      @required this.method,
      this.params,
      @required this.jsonrpc}) {
    if (id == null) {
      throw 'id is required but was not provided';
    }
    if (method == null) {
      throw 'method is required but was not provided';
    }
    if (jsonrpc == null) {
      throw 'jsonrpc is required but was not provided';
    }
  }
  static RequestMessage fromJson(Map<String, dynamic> json) {
    final id = json['id'] is num
        ? Either2<num, String>.t1(json['id'])
        : (json['id'] is String
            ? Either2<num, String>.t2(json['id'])
            : (throw '''${json['id']} was not one of (num, String)'''));
    final method =
        json['method'] != null ? Method.fromJson(json['method']) : null;
    final params = json['params'];
    final jsonrpc = json['jsonrpc'];
    return RequestMessage(
        id: id, method: method, params: params, jsonrpc: jsonrpc);
  }

  /// The request id.
  final Either2<num, String> id;
  final String jsonrpc;

  /// The method to be invoked.
  final Method method;

  /// The method's params.
  final dynamic params;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['id'] = id ?? (throw 'id is required but was not set');
    __result['method'] =
        method?.toJson() ?? (throw 'method is required but was not set');
    if (params != null) {
      __result['params'] = params;
    }
    __result['jsonrpc'] =
        jsonrpc ?? (throw 'jsonrpc is required but was not set');
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('id');
      try {
        if (!obj.containsKey('id')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['id'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!((obj['id'] is num || obj['id'] is String))) {
          reporter.reportError('must be of type Either2<num, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('method');
      try {
        if (!obj.containsKey('method')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['method'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(Method.canParse(obj['method'], reporter))) {
          reporter.reportError('must be of type Method');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('params');
      try {
        if (obj['params'] != null && !(true)) {
          reporter.reportError('must be of type dynamic');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('jsonrpc');
      try {
        if (!obj.containsKey('jsonrpc')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['jsonrpc'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['jsonrpc'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type RequestMessage');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is RequestMessage && other.runtimeType == RequestMessage) {
      return id == other.id &&
          method == other.method &&
          params == other.params &&
          jsonrpc == other.jsonrpc &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, id.hashCode);
    hash = JenkinsSmiHash.combine(hash, method.hashCode);
    hash = JenkinsSmiHash.combine(hash, params.hashCode);
    hash = JenkinsSmiHash.combine(hash, jsonrpc.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class ResourceOperationKind {
  const ResourceOperationKind._(this._value);
  const ResourceOperationKind.fromJson(this._value);

  final String _value;

  static bool canParse(Object obj, LspJsonReporter reporter) {
    switch (obj) {
      case 'create':
      case 'rename':
      case 'delete':
        return true;
    }
    return false;
  }

  /// Supports creating new files and folders.
  static const Create = ResourceOperationKind._('create');

  /// Supports renaming existing files and folders.
  static const Rename = ResourceOperationKind._('rename');

  /// Supports deleting existing files and folders.
  static const Delete = ResourceOperationKind._('delete');

  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  bool operator ==(Object o) =>
      o is ResourceOperationKind && o._value == _value;
}

class ResponseError implements ToJsonable {
  static const jsonHandler =
      LspJsonHandler(ResponseError.canParse, ResponseError.fromJson);

  ResponseError({@required this.code, @required this.message, this.data}) {
    if (code == null) {
      throw 'code is required but was not provided';
    }
    if (message == null) {
      throw 'message is required but was not provided';
    }
  }
  static ResponseError fromJson(Map<String, dynamic> json) {
    final code =
        json['code'] != null ? ErrorCodes.fromJson(json['code']) : null;
    final message = json['message'];
    final data = json['data'];
    return ResponseError(code: code, message: message, data: data);
  }

  /// A number indicating the error type that occurred.
  final ErrorCodes code;

  /// A string that contains additional information about the error. Can be
  /// omitted.
  final String data;

  /// A string providing a short description of the error.
  final String message;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['code'] =
        code?.toJson() ?? (throw 'code is required but was not set');
    __result['message'] =
        message ?? (throw 'message is required but was not set');
    if (data != null) {
      __result['data'] = data;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('code');
      try {
        if (!obj.containsKey('code')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['code'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(ErrorCodes.canParse(obj['code'], reporter))) {
          reporter.reportError('must be of type ErrorCodes');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('message');
      try {
        if (!obj.containsKey('message')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['message'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['message'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('data');
      try {
        if (obj['data'] != null && !(obj['data'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ResponseError');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is ResponseError && other.runtimeType == ResponseError) {
      return code == other.code &&
          message == other.message &&
          data == other.data &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, code.hashCode);
    hash = JenkinsSmiHash.combine(hash, message.hashCode);
    hash = JenkinsSmiHash.combine(hash, data.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class ResponseMessage implements Message, ToJsonable {
  static const jsonHandler =
      LspJsonHandler(ResponseMessage.canParse, ResponseMessage.fromJson);

  ResponseMessage({this.id, this.result, this.error, @required this.jsonrpc}) {
    if (jsonrpc == null) {
      throw 'jsonrpc is required but was not provided';
    }
  }
  static ResponseMessage fromJson(Map<String, dynamic> json) {
    final id = json['id'] is num
        ? Either2<num, String>.t1(json['id'])
        : (json['id'] is String
            ? Either2<num, String>.t2(json['id'])
            : (json['id'] == null
                ? null
                : (throw '''${json['id']} was not one of (num, String)''')));
    final result = json['result'];
    final error =
        json['error'] != null ? ResponseError.fromJson(json['error']) : null;
    final jsonrpc = json['jsonrpc'];
    return ResponseMessage(
        id: id, result: result, error: error, jsonrpc: jsonrpc);
  }

  /// The error object in case a request fails.
  final ResponseError error;

  /// The request id.
  final Either2<num, String> id;
  final String jsonrpc;

  /// The result of a request. This member is REQUIRED on success. This member
  /// MUST NOT exist if there was an error invoking the method.
  final dynamic result;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['id'] = id;
    __result['jsonrpc'] =
        jsonrpc ?? (throw 'jsonrpc is required but was not set');
    if (error != null && result != null) {
      throw 'result and error cannot both be set';
    } else if (error != null) {
      __result['error'] = error;
    } else {
      __result['result'] = result;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('id');
      try {
        if (!obj.containsKey('id')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['id'] != null && !((obj['id'] is num || obj['id'] is String))) {
          reporter.reportError('must be of type Either2<num, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('result');
      try {
        if (obj['result'] != null && !(true)) {
          reporter.reportError('must be of type dynamic');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('error');
      try {
        if (obj['error'] != null &&
            !(ResponseError.canParse(obj['error'], reporter))) {
          reporter.reportError('must be of type ResponseError');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('jsonrpc');
      try {
        if (!obj.containsKey('jsonrpc')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['jsonrpc'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['jsonrpc'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ResponseMessage');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is ResponseMessage && other.runtimeType == ResponseMessage) {
      return id == other.id &&
          result == other.result &&
          error == other.error &&
          jsonrpc == other.jsonrpc &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, id.hashCode);
    hash = JenkinsSmiHash.combine(hash, result.hashCode);
    hash = JenkinsSmiHash.combine(hash, error.hashCode);
    hash = JenkinsSmiHash.combine(hash, jsonrpc.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SaveOptions implements ToJsonable {
  static const jsonHandler =
      LspJsonHandler(SaveOptions.canParse, SaveOptions.fromJson);

  SaveOptions({this.includeText});
  static SaveOptions fromJson(Map<String, dynamic> json) {
    final includeText = json['includeText'];
    return SaveOptions(includeText: includeText);
  }

  /// The client is supposed to include the content on save.
  final bool includeText;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (includeText != null) {
      __result['includeText'] = includeText;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('includeText');
      try {
        if (obj['includeText'] != null && !(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, includeText.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SelectionRange implements ToJsonable {
  static const jsonHandler =
      LspJsonHandler(SelectionRange.canParse, SelectionRange.fromJson);

  SelectionRange({@required this.range, this.parent}) {
    if (range == null) {
      throw 'range is required but was not provided';
    }
  }
  static SelectionRange fromJson(Map<String, dynamic> json) {
    final range = json['range'] != null ? Range.fromJson(json['range']) : null;
    final parent =
        json['parent'] != null ? SelectionRange.fromJson(json['parent']) : null;
    return SelectionRange(range: range, parent: parent);
  }

  /// The parent selection range containing this range. Therefore `parent.range`
  /// must contain `this.range`.
  final SelectionRange parent;

  /// The range ([Range]) of this selection range.
  final Range range;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['range'] =
        range?.toJson() ?? (throw 'range is required but was not set');
    if (parent != null) {
      __result['parent'] = parent.toJson();
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('range');
      try {
        if (!obj.containsKey('range')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['range'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(Range.canParse(obj['range'], reporter))) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('parent');
      try {
        if (obj['parent'] != null &&
            !(SelectionRange.canParse(obj['parent'], reporter))) {
          reporter.reportError('must be of type SelectionRange');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SelectionRange');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SelectionRange && other.runtimeType == SelectionRange) {
      return range == other.range && parent == other.parent && true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, range.hashCode);
    hash = JenkinsSmiHash.combine(hash, parent.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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, dynamic> json) {
    final dynamicRegistration = json['dynamicRegistration'];
    return SelectionRangeClientCapabilities(
        dynamicRegistration: dynamicRegistration);
  }

  /// Whether implementation supports dynamic registration for selection range
  /// providers. If this is set to `true` the client supports the new
  /// `SelectionRangeRegistrationOptions` return value for the corresponding
  /// server capability as well.
  final bool dynamicRegistration;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (dynamicRegistration != null) {
      __result['dynamicRegistration'] = dynamicRegistration;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('dynamicRegistration');
      try {
        if (obj['dynamicRegistration'] != null &&
            !(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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, dynamic> json) {
    if (SelectionRangeRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return SelectionRangeRegistrationOptions.fromJson(json);
    }
    final workDoneProgress = json['workDoneProgress'];
    return SelectionRangeOptions(workDoneProgress: workDoneProgress);
  }

  final bool workDoneProgress;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('workDoneProgress');
      try {
        if (obj['workDoneProgress'] != null &&
            !(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SelectionRangeParams
    implements WorkDoneProgressParams, PartialResultParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
      SelectionRangeParams.canParse, SelectionRangeParams.fromJson);

  SelectionRangeParams(
      {@required this.textDocument,
      @required this.positions,
      this.workDoneToken,
      this.partialResultToken}) {
    if (textDocument == null) {
      throw 'textDocument is required but was not provided';
    }
    if (positions == null) {
      throw 'positions is required but was not provided';
    }
  }
  static SelectionRangeParams fromJson(Map<String, dynamic> json) {
    final textDocument = json['textDocument'] != null
        ? TextDocumentIdentifier.fromJson(json['textDocument'])
        : null;
    final positions = json['positions']
        ?.map((item) => item != null ? Position.fromJson(item) : null)
        ?.cast<Position>()
        ?.toList();
    final workDoneToken = json['workDoneToken'] is num
        ? Either2<num, String>.t1(json['workDoneToken'])
        : (json['workDoneToken'] is String
            ? Either2<num, String>.t2(json['workDoneToken'])
            : (json['workDoneToken'] == null
                ? null
                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
    final partialResultToken = json['partialResultToken'] is num
        ? Either2<num, String>.t1(json['partialResultToken'])
        : (json['partialResultToken'] is String
            ? Either2<num, String>.t2(json['partialResultToken'])
            : (json['partialResultToken'] == null
                ? null
                : (throw '''${json['partialResultToken']} was not one of (num, String)''')));
    return SelectionRangeParams(
        textDocument: textDocument,
        positions: positions,
        workDoneToken: workDoneToken,
        partialResultToken: partialResultToken);
  }

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  final Either2<num, String> partialResultToken;

  /// The positions inside the text document.
  final List<Position> positions;

  /// The text document.
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  final Either2<num, String> workDoneToken;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['textDocument'] = textDocument?.toJson() ??
        (throw 'textDocument is required but was not set');
    __result['positions'] = positions?.map((item) => item.toJson())?.toList() ??
        (throw 'positions is required but was not set');
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    if (partialResultToken != null) {
      __result['partialResultToken'] = partialResultToken;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['textDocument'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(TextDocumentIdentifier.canParse(obj['textDocument'], reporter))) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('positions');
      try {
        if (!obj.containsKey('positions')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['positions'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!((obj['positions'] is List &&
            (obj['positions']
                .every((item) => Position.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<Position>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        if (obj['workDoneToken'] != null &&
            !((obj['workDoneToken'] is num ||
                obj['workDoneToken'] is String))) {
          reporter.reportError('must be of type Either2<num, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('partialResultToken');
      try {
        if (obj['partialResultToken'] != null &&
            !((obj['partialResultToken'] is num ||
                obj['partialResultToken'] is String))) {
          reporter.reportError('must be of type Either2<num, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SelectionRangeParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SelectionRangeParams &&
        other.runtimeType == SelectionRangeParams) {
      return textDocument == other.textDocument &&
          listEqual(
              positions, other.positions, (Position a, Position b) => a == b) &&
          workDoneToken == other.workDoneToken &&
          partialResultToken == other.partialResultToken &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, textDocument.hashCode);
    hash = JenkinsSmiHash.combine(hash, lspHashCode(positions));
    hash = JenkinsSmiHash.combine(hash, workDoneToken.hashCode);
    hash = JenkinsSmiHash.combine(hash, partialResultToken.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SelectionRangeRegistrationOptions
    implements
        SelectionRangeOptions,
        TextDocumentRegistrationOptions,
        StaticRegistrationOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
      SelectionRangeRegistrationOptions.canParse,
      SelectionRangeRegistrationOptions.fromJson);

  SelectionRangeRegistrationOptions(
      {this.workDoneProgress, this.documentSelector, this.id});
  static SelectionRangeRegistrationOptions fromJson(Map<String, dynamic> json) {
    final workDoneProgress = json['workDoneProgress'];
    final documentSelector = json['documentSelector']
        ?.map((item) => item != null ? DocumentFilter.fromJson(item) : null)
        ?.cast<DocumentFilter>()
        ?.toList();
    final id = json['id'];
    return SelectionRangeRegistrationOptions(
        workDoneProgress: workDoneProgress,
        documentSelector: documentSelector,
        id: id);
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  final List<DocumentFilter> documentSelector;

  /// The id used to register the request. The id can be used to deregister the
  /// request again. See also Registration#id.
  final String id;
  final bool workDoneProgress;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    __result['documentSelector'] = documentSelector;
    if (id != null) {
      __result['id'] = id;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('workDoneProgress');
      try {
        if (obj['workDoneProgress'] != null &&
            !(obj['workDoneProgress'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['documentSelector'] != null &&
            !((obj['documentSelector'] is List &&
                (obj['documentSelector'].every(
                    (item) => DocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<DocumentFilter>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('id');
      try {
        if (obj['id'] != null && !(obj['id'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SelectionRangeRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SelectionRangeRegistrationOptions &&
        other.runtimeType == SelectionRangeRegistrationOptions) {
      return workDoneProgress == other.workDoneProgress &&
          listEqual(documentSelector, other.documentSelector,
              (DocumentFilter a, DocumentFilter b) => a == b) &&
          id == other.id &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
    hash = JenkinsSmiHash.combine(hash, lspHashCode(documentSelector));
    hash = JenkinsSmiHash.combine(hash, id.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SemanticTokenModifiers {
  const SemanticTokenModifiers(this._value);
  const SemanticTokenModifiers.fromJson(this._value);

  final String _value;

  static bool canParse(Object obj, LspJsonReporter reporter) {
    return obj is String;
  }

  static const declaration = SemanticTokenModifiers(r'declaration');
  static const definition = SemanticTokenModifiers(r'definition');
  static const readonly = SemanticTokenModifiers(r'readonly');
  static const static = SemanticTokenModifiers(r'static');
  static const deprecated = SemanticTokenModifiers(r'deprecated');
  static const abstract = SemanticTokenModifiers(r'abstract');
  static const async = SemanticTokenModifiers(r'async');
  static const modification = SemanticTokenModifiers(r'modification');
  static const documentation = SemanticTokenModifiers(r'documentation');
  static const defaultLibrary = SemanticTokenModifiers(r'defaultLibrary');

  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  bool operator ==(Object o) =>
      o is SemanticTokenModifiers && o._value == _value;
}

class SemanticTokenTypes {
  const SemanticTokenTypes(this._value);
  const SemanticTokenTypes.fromJson(this._value);

  final String _value;

  static bool canParse(Object obj, LspJsonReporter reporter) {
    return obj is String;
  }

  static const namespace = SemanticTokenTypes(r'namespace');

  /// Represents a generic type. Acts as a fallback for types which can't be
  /// mapped to a specific type like class or enum.
  static const type = SemanticTokenTypes(r'type');
  static const class_ = SemanticTokenTypes(r'class');
  static const enum_ = SemanticTokenTypes(r'enum');
  static const interface = SemanticTokenTypes(r'interface');
  static const struct = SemanticTokenTypes(r'struct');
  static const typeParameter = SemanticTokenTypes(r'typeParameter');
  static const parameter = SemanticTokenTypes(r'parameter');
  static const variable = SemanticTokenTypes(r'variable');
  static const property = SemanticTokenTypes(r'property');
  static const enumMember = SemanticTokenTypes(r'enumMember');
  static const event = SemanticTokenTypes(r'event');
  static const function = SemanticTokenTypes(r'function');
  static const method = SemanticTokenTypes(r'method');
  static const macro = SemanticTokenTypes(r'macro');
  static const keyword = SemanticTokenTypes(r'keyword');
  static const modifier = SemanticTokenTypes(r'modifier');
  static const comment = SemanticTokenTypes(r'comment');
  static const string = SemanticTokenTypes(r'string');
  static const number = SemanticTokenTypes(r'number');
  static const regexp = SemanticTokenTypes(r'regexp');
  static const operator = SemanticTokenTypes(r'operator');

  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  bool operator ==(Object o) => o is SemanticTokenTypes && o._value == _value;
}

class SemanticTokens implements ToJsonable {
  static const jsonHandler =
      LspJsonHandler(SemanticTokens.canParse, SemanticTokens.fromJson);

  SemanticTokens({this.resultId, @required this.data}) {
    if (data == null) {
      throw 'data is required but was not provided';
    }
  }
  static SemanticTokens fromJson(Map<String, dynamic> json) {
    final resultId = json['resultId'];
    final data = json['data']?.map((item) => item)?.cast<num>()?.toList();
    return SemanticTokens(resultId: resultId, data: data);
  }

  /// The actual tokens.
  final List<num> data;

  /// An optional result id. If provided and clients support delta updating the
  /// client will include the result id in the next semantic token request. A
  /// server can then instead of computing all semantic tokens again simply send
  /// a delta.
  final String resultId;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (resultId != null) {
      __result['resultId'] = resultId;
    }
    __result['data'] = data ?? (throw 'data is required but was not set');
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('resultId');
      try {
        if (obj['resultId'] != null && !(obj['resultId'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('data');
      try {
        if (!obj.containsKey('data')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['data'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!((obj['data'] is List &&
            (obj['data'].every((item) => item is num))))) {
          reporter.reportError('must be of type List<num>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SemanticTokens');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SemanticTokens && other.runtimeType == SemanticTokens) {
      return resultId == other.resultId &&
          listEqual(data, other.data, (num a, num b) => a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, resultId.hashCode);
    hash = JenkinsSmiHash.combine(hash, lspHashCode(data));
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SemanticTokensClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
      SemanticTokensClientCapabilities.canParse,
      SemanticTokensClientCapabilities.fromJson);

  SemanticTokensClientCapabilities(
      {this.dynamicRegistration,
      @required this.requests,
      @required this.tokenTypes,
      @required this.tokenModifiers,
      @required this.formats,
      this.overlappingTokenSupport,
      this.multilineTokenSupport}) {
    if (requests == null) {
      throw 'requests is required but was not provided';
    }
    if (tokenTypes == null) {
      throw 'tokenTypes is required but was not provided';
    }
    if (tokenModifiers == null) {
      throw 'tokenModifiers is required but was not provided';
    }
    if (formats == null) {
      throw 'formats is required but was not provided';
    }
  }
  static SemanticTokensClientCapabilities fromJson(Map<String, dynamic> json) {
    final dynamicRegistration = json['dynamicRegistration'];
    final requests = json['requests'] != null
        ? SemanticTokensClientCapabilitiesRequests.fromJson(json['requests'])
        : null;
    final tokenTypes =
        json['tokenTypes']?.map((item) => item)?.cast<String>()?.toList();
    final tokenModifiers =
        json['tokenModifiers']?.map((item) => item)?.cast<String>()?.toList();
    final formats = json['formats']
        ?.map((item) => item != null ? TokenFormat.fromJson(item) : null)
        ?.cast<TokenFormat>()
        ?.toList();
    final overlappingTokenSupport = json['overlappingTokenSupport'];
    final multilineTokenSupport = json['multilineTokenSupport'];
    return SemanticTokensClientCapabilities(
        dynamicRegistration: dynamicRegistration,
        requests: requests,
        tokenTypes: tokenTypes,
        tokenModifiers: tokenModifiers,
        formats: formats,
        overlappingTokenSupport: overlappingTokenSupport,
        multilineTokenSupport: multilineTokenSupport);
  }

  /// Whether implementation supports dynamic registration. If this is set to
  /// `true` the client supports the new `(TextDocumentRegistrationOptions &
  /// StaticRegistrationOptions)` return value for the corresponding server
  /// capability as well.
  final bool dynamicRegistration;

  /// The formats the clients supports.
  final List<TokenFormat> formats;

  /// Whether the client supports tokens that can span multiple lines.
  final bool multilineTokenSupport;

  /// Whether the client supports tokens that can overlap each other.
  final bool overlappingTokenSupport;

  /// Which requests the client supports and might send to the server depending
  /// on the server's capability. Please note that clients might not show
  /// semantic tokens or degrade some of the user experience if a range or full
  /// request is advertised by the client but not provided by the server. If for
  /// example the client capability `requests.full` and `request.range` are both
  /// set to true but the server only provides a range provider the client might
  /// not render a minimap correctly or might even decide to not show any
  /// semantic tokens at all.
  final SemanticTokensClientCapabilitiesRequests requests;

  /// The token modifiers that the client supports.
  final List<String> tokenModifiers;

  /// The token types that the client supports.
  final List<String> tokenTypes;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (dynamicRegistration != null) {
      __result['dynamicRegistration'] = dynamicRegistration;
    }
    __result['requests'] =
        requests?.toJson() ?? (throw 'requests is required but was not set');
    __result['tokenTypes'] =
        tokenTypes ?? (throw 'tokenTypes is required but was not set');
    __result['tokenModifiers'] =
        tokenModifiers ?? (throw 'tokenModifiers is required but was not set');
    __result['formats'] = formats?.map((item) => item.toJson())?.toList() ??
        (throw 'formats is required but was not set');
    if (overlappingTokenSupport != null) {
      __result['overlappingTokenSupport'] = overlappingTokenSupport;
    }
    if (multilineTokenSupport != null) {
      __result['multilineTokenSupport'] = multilineTokenSupport;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('dynamicRegistration');
      try {
        if (obj['dynamicRegistration'] != null &&
            !(obj['dynamicRegistration'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('requests');
      try {
        if (!obj.containsKey('requests')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['requests'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(SemanticTokensClientCapabilitiesRequests.canParse(
            obj['requests'], reporter))) {
          reporter.reportError(
              'must be of type SemanticTokensClientCapabilitiesRequests');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('tokenTypes');
      try {
        if (!obj.containsKey('tokenTypes')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['tokenTypes'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!((obj['tokenTypes'] is List &&
            (obj['tokenTypes'].every((item) => item is String))))) {
          reporter.reportError('must be of type List<String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('tokenModifiers');
      try {
        if (!obj.containsKey('tokenModifiers')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['tokenModifiers'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!((obj['tokenModifiers'] is List &&
            (obj['tokenModifiers'].every((item) => item is String))))) {
          reporter.reportError('must be of type List<String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('formats');
      try {
        if (!obj.containsKey('formats')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['formats'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!((obj['formats'] is List &&
            (obj['formats']
                .every((item) => TokenFormat.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<TokenFormat>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('overlappingTokenSupport');
      try {
        if (obj['overlappingTokenSupport'] != null &&
            !(obj['overlappingTokenSupport'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('multilineTokenSupport');
      try {
        if (obj['multilineTokenSupport'] != null &&
            !(obj['multilineTokenSupport'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SemanticTokensClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SemanticTokensClientCapabilities &&
        other.runtimeType == SemanticTokensClientCapabilities) {
      return dynamicRegistration == other.dynamicRegistration &&
          requests == other.requests &&
          listEqual(
              tokenTypes, other.tokenTypes, (String a, String b) => a == b) &&
          listEqual(tokenModifiers, other.tokenModifiers,
              (String a, String b) => a == b) &&
          listEqual(formats, other.formats,
              (TokenFormat a, TokenFormat b) => a == b) &&
          overlappingTokenSupport == other.overlappingTokenSupport &&
          multilineTokenSupport == other.multilineTokenSupport &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode);
    hash = JenkinsSmiHash.combine(hash, requests.hashCode);
    hash = JenkinsSmiHash.combine(hash, lspHashCode(tokenTypes));
    hash = JenkinsSmiHash.combine(hash, lspHashCode(tokenModifiers));
    hash = JenkinsSmiHash.combine(hash, lspHashCode(formats));
    hash = JenkinsSmiHash.combine(hash, overlappingTokenSupport.hashCode);
    hash = JenkinsSmiHash.combine(hash, multilineTokenSupport.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SemanticTokensClientCapabilitiesFull implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
      SemanticTokensClientCapabilitiesFull.canParse,
      SemanticTokensClientCapabilitiesFull.fromJson);

  SemanticTokensClientCapabilitiesFull({this.delta});
  static SemanticTokensClientCapabilitiesFull fromJson(
      Map<String, dynamic> json) {
    final delta = json['delta'];
    return SemanticTokensClientCapabilitiesFull(delta: delta);
  }

  /// The client will send the `textDocument/semanticTokens/full/delta` request
  /// if the server provides a corresponding handler.
  final bool delta;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (delta != null) {
      __result['delta'] = delta;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('delta');
      try {
        if (obj['delta'] != null && !(obj['delta'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter
          .reportError('must be of type SemanticTokensClientCapabilitiesFull');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SemanticTokensClientCapabilitiesFull &&
        other.runtimeType == SemanticTokensClientCapabilitiesFull) {
      return delta == other.delta && true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, delta.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SemanticTokensClientCapabilitiesRange implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
      SemanticTokensClientCapabilitiesRange.canParse,
      SemanticTokensClientCapabilitiesRange.fromJson);

  static SemanticTokensClientCapabilitiesRange fromJson(
      Map<String, dynamic> json) {
    return SemanticTokensClientCapabilitiesRange();
  }

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      return true;
    } else {
      reporter
          .reportError('must be of type SemanticTokensClientCapabilitiesRange');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SemanticTokensClientCapabilitiesRange &&
        other.runtimeType == SemanticTokensClientCapabilitiesRange) {
      return true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SemanticTokensClientCapabilitiesRequests implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
      SemanticTokensClientCapabilitiesRequests.canParse,
      SemanticTokensClientCapabilitiesRequests.fromJson);

  SemanticTokensClientCapabilitiesRequests({this.range, this.full});
  static SemanticTokensClientCapabilitiesRequests fromJson(
      Map<String, dynamic> json) {
    final range = json['range'] is bool
        ? Either2<bool, SemanticTokensClientCapabilitiesRange>.t1(json['range'])
        : (SemanticTokensClientCapabilitiesRange.canParse(
                json['range'], nullLspJsonReporter)
            ? Either2<bool, SemanticTokensClientCapabilitiesRange>.t2(
                json['range'] != null
                    ? SemanticTokensClientCapabilitiesRange.fromJson(
                        json['range'])
                    : null)
            : (json['range'] == null
                ? null
                : (throw '''${json['range']} was not one of (bool, SemanticTokensClientCapabilitiesRange)''')));
    final full = json['full'] is bool
        ? Either2<bool, SemanticTokensClientCapabilitiesFull>.t1(json['full'])
        : (SemanticTokensClientCapabilitiesFull.canParse(
                json['full'], nullLspJsonReporter)
            ? Either2<bool, SemanticTokensClientCapabilitiesFull>.t2(
                json['full'] != null
                    ? SemanticTokensClientCapabilitiesFull.fromJson(
                        json['full'])
                    : null)
            : (json['full'] == null
                ? null
                : (throw '''${json['full']} was not one of (bool, SemanticTokensClientCapabilitiesFull)''')));
    return SemanticTokensClientCapabilitiesRequests(range: range, full: full);
  }

  /// The client will send the `textDocument/semanticTokens/full` request if the
  /// server provides a corresponding handler.
  final Either2<bool, SemanticTokensClientCapabilitiesFull> full;

  /// The client will send the `textDocument/semanticTokens/range` request if
  /// the server provides a corresponding handler.
  final Either2<bool, SemanticTokensClientCapabilitiesRange> range;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (range != null) {
      __result['range'] = range;
    }
    if (full != null) {
      __result['full'] = full;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('range');
      try {
        if (obj['range'] != null &&
            !((obj['range'] is bool ||
                SemanticTokensClientCapabilitiesRange.canParse(
                    obj['range'], reporter)))) {
          reporter.reportError(
              'must be of type Either2<bool, SemanticTokensClientCapabilitiesRange>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('full');
      try {
        if (obj['full'] != null &&
            !((obj['full'] is bool ||
                SemanticTokensClientCapabilitiesFull.canParse(
                    obj['full'], reporter)))) {
          reporter.reportError(
              'must be of type Either2<bool, SemanticTokensClientCapabilitiesFull>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type SemanticTokensClientCapabilitiesRequests');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SemanticTokensClientCapabilitiesRequests &&
        other.runtimeType == SemanticTokensClientCapabilitiesRequests) {
      return range == other.range && full == other.full && true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, range.hashCode);
    hash = JenkinsSmiHash.combine(hash, full.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SemanticTokensDelta implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
      SemanticTokensDelta.canParse, SemanticTokensDelta.fromJson);

  SemanticTokensDelta({this.resultId, @required this.edits}) {
    if (edits == null) {
      throw 'edits is required but was not provided';
    }
  }
  static SemanticTokensDelta fromJson(Map<String, dynamic> json) {
    final resultId = json['resultId'];
    final edits = json['edits']
        ?.map((item) => item != null ? SemanticTokensEdit.fromJson(item) : null)
        ?.cast<SemanticTokensEdit>()
        ?.toList();
    return SemanticTokensDelta(resultId: resultId, edits: edits);
  }

  /// The semantic token edits to transform a previous result into a new result.
  final List<SemanticTokensEdit> edits;
  final String resultId;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (resultId != null) {
      __result['resultId'] = resultId;
    }
    __result['edits'] = edits?.map((item) => item.toJson())?.toList() ??
        (throw 'edits is required but was not set');
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('resultId');
      try {
        if (obj['resultId'] != null && !(obj['resultId'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('edits');
      try {
        if (!obj.containsKey('edits')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['edits'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!((obj['edits'] is List &&
            (obj['edits'].every(
                (item) => SemanticTokensEdit.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<SemanticTokensEdit>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SemanticTokensDelta');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SemanticTokensDelta &&
        other.runtimeType == SemanticTokensDelta) {
      return resultId == other.resultId &&
          listEqual(edits, other.edits,
              (SemanticTokensEdit a, SemanticTokensEdit b) => a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, resultId.hashCode);
    hash = JenkinsSmiHash.combine(hash, lspHashCode(edits));
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SemanticTokensDeltaParams
    implements WorkDoneProgressParams, PartialResultParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
      SemanticTokensDeltaParams.canParse, SemanticTokensDeltaParams.fromJson);

  SemanticTokensDeltaParams(
      {@required this.textDocument,
      @required this.previousResultId,
      this.workDoneToken,
      this.partialResultToken}) {
    if (textDocument == null) {
      throw 'textDocument is required but was not provided';
    }
    if (previousResultId == null) {
      throw 'previousResultId is required but was not provided';
    }
  }
  static SemanticTokensDeltaParams fromJson(Map<String, dynamic> json) {
    final textDocument = json['textDocument'] != null
        ? TextDocumentIdentifier.fromJson(json['textDocument'])
        : null;
    final previousResultId = json['previousResultId'];
    final workDoneToken = json['workDoneToken'] is num
        ? Either2<num, String>.t1(json['workDoneToken'])
        : (json['workDoneToken'] is String
            ? Either2<num, String>.t2(json['workDoneToken'])
            : (json['workDoneToken'] == null
                ? null
                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
    final partialResultToken = json['partialResultToken'] is num
        ? Either2<num, String>.t1(json['partialResultToken'])
        : (json['partialResultToken'] is String
            ? Either2<num, String>.t2(json['partialResultToken'])
            : (json['partialResultToken'] == null
                ? null
                : (throw '''${json['partialResultToken']} was not one of (num, String)''')));
    return SemanticTokensDeltaParams(
        textDocument: textDocument,
        previousResultId: previousResultId,
        workDoneToken: workDoneToken,
        partialResultToken: partialResultToken);
  }

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  final Either2<num, String> partialResultToken;

  /// The result id of a previous response. The result Id can either point to a
  /// full response or a delta response depending on what was received last.
  final String previousResultId;

  /// The text document.
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  final Either2<num, String> workDoneToken;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['textDocument'] = textDocument?.toJson() ??
        (throw 'textDocument is required but was not set');
    __result['previousResultId'] = previousResultId ??
        (throw 'previousResultId is required but was not set');
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    if (partialResultToken != null) {
      __result['partialResultToken'] = partialResultToken;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['textDocument'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(TextDocumentIdentifier.canParse(obj['textDocument'], reporter))) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('previousResultId');
      try {
        if (!obj.containsKey('previousResultId')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['previousResultId'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['previousResultId'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        if (obj['workDoneToken'] != null &&
            !((obj['workDoneToken'] is num ||
                obj['workDoneToken'] is String))) {
          reporter.reportError('must be of type Either2<num, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('partialResultToken');
      try {
        if (obj['partialResultToken'] != null &&
            !((obj['partialResultToken'] is num ||
                obj['partialResultToken'] is String))) {
          reporter.reportError('must be of type Either2<num, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SemanticTokensDeltaParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SemanticTokensDeltaParams &&
        other.runtimeType == SemanticTokensDeltaParams) {
      return textDocument == other.textDocument &&
          previousResultId == other.previousResultId &&
          workDoneToken == other.workDoneToken &&
          partialResultToken == other.partialResultToken &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, textDocument.hashCode);
    hash = JenkinsSmiHash.combine(hash, previousResultId.hashCode);
    hash = JenkinsSmiHash.combine(hash, workDoneToken.hashCode);
    hash = JenkinsSmiHash.combine(hash, partialResultToken.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SemanticTokensDeltaPartialResult implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
      SemanticTokensDeltaPartialResult.canParse,
      SemanticTokensDeltaPartialResult.fromJson);

  SemanticTokensDeltaPartialResult({@required this.edits}) {
    if (edits == null) {
      throw 'edits is required but was not provided';
    }
  }
  static SemanticTokensDeltaPartialResult fromJson(Map<String, dynamic> json) {
    final edits = json['edits']
        ?.map((item) => item != null ? SemanticTokensEdit.fromJson(item) : null)
        ?.cast<SemanticTokensEdit>()
        ?.toList();
    return SemanticTokensDeltaPartialResult(edits: edits);
  }

  final List<SemanticTokensEdit> edits;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['edits'] = edits?.map((item) => item.toJson())?.toList() ??
        (throw 'edits is required but was not set');
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('edits');
      try {
        if (!obj.containsKey('edits')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['edits'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!((obj['edits'] is List &&
            (obj['edits'].every(
                (item) => SemanticTokensEdit.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<SemanticTokensEdit>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SemanticTokensDeltaPartialResult');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SemanticTokensDeltaPartialResult &&
        other.runtimeType == SemanticTokensDeltaPartialResult) {
      return listEqual(edits, other.edits,
              (SemanticTokensEdit a, SemanticTokensEdit b) => a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(edits));
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SemanticTokensEdit implements ToJsonable {
  static const jsonHandler =
      LspJsonHandler(SemanticTokensEdit.canParse, SemanticTokensEdit.fromJson);

  SemanticTokensEdit(
      {@required this.start, @required this.deleteCount, this.data}) {
    if (start == null) {
      throw 'start is required but was not provided';
    }
    if (deleteCount == null) {
      throw 'deleteCount is required but was not provided';
    }
  }
  static SemanticTokensEdit fromJson(Map<String, dynamic> json) {
    final start = json['start'];
    final deleteCount = json['deleteCount'];
    final data = json['data']?.map((item) => item)?.cast<num>()?.toList();
    return SemanticTokensEdit(
        start: start, deleteCount: deleteCount, data: data);
  }

  /// The elements to insert.
  final List<num> data;

  /// The count of elements to remove.
  final num deleteCount;

  /// The start offset of the edit.
  final num start;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['start'] = start ?? (throw 'start is required but was not set');
    __result['deleteCount'] =
        deleteCount ?? (throw 'deleteCount is required but was not set');
    if (data != null) {
      __result['data'] = data;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('start');
      try {
        if (!obj.containsKey('start')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['start'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['start'] is num)) {
          reporter.reportError('must be of type num');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('deleteCount');
      try {
        if (!obj.containsKey('deleteCount')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['deleteCount'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['deleteCount'] is num)) {
          reporter.reportError('must be of type num');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('data');
      try {
        if (obj['data'] != null &&
            !((obj['data'] is List &&
                (obj['data'].every((item) => item is num))))) {
          reporter.reportError('must be of type List<num>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SemanticTokensEdit');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SemanticTokensEdit &&
        other.runtimeType == SemanticTokensEdit) {
      return start == other.start &&
          deleteCount == other.deleteCount &&
          listEqual(data, other.data, (num a, num b) => a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, start.hashCode);
    hash = JenkinsSmiHash.combine(hash, deleteCount.hashCode);
    hash = JenkinsSmiHash.combine(hash, lspHashCode(data));
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SemanticTokensLegend implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
      SemanticTokensLegend.canParse, SemanticTokensLegend.fromJson);

  SemanticTokensLegend(
      {@required this.tokenTypes, @required this.tokenModifiers}) {
    if (tokenTypes == null) {
      throw 'tokenTypes is required but was not provided';
    }
    if (tokenModifiers == null) {
      throw 'tokenModifiers is required but was not provided';
    }
  }
  static SemanticTokensLegend fromJson(Map<String, dynamic> json) {
    final tokenTypes =
        json['tokenTypes']?.map((item) => item)?.cast<String>()?.toList();
    final tokenModifiers =
        json['tokenModifiers']?.map((item) => item)?.cast<String>()?.toList();
    return SemanticTokensLegend(
        tokenTypes: tokenTypes, tokenModifiers: tokenModifiers);
  }

  /// The token modifiers a server uses.
  final List<String> tokenModifiers;

  /// The token types a server uses.
  final List<String> tokenTypes;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['tokenTypes'] =
        tokenTypes ?? (throw 'tokenTypes is required but was not set');
    __result['tokenModifiers'] =
        tokenModifiers ?? (throw 'tokenModifiers is required but was not set');
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('tokenTypes');
      try {
        if (!obj.containsKey('tokenTypes')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['tokenTypes'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!((obj['tokenTypes'] is List &&
            (obj['tokenTypes'].every((item) => item is String))))) {
          reporter.reportError('must be of type List<String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('tokenModifiers');
      try {
        if (!obj.containsKey('tokenModifiers')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['tokenModifiers'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!((obj['tokenModifiers'] is List &&
            (obj['tokenModifiers'].every((item) => item is String))))) {
          reporter.reportError('must be of type List<String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SemanticTokensLegend');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SemanticTokensLegend &&
        other.runtimeType == SemanticTokensLegend) {
      return listEqual(
              tokenTypes, other.tokenTypes, (String a, String b) => a == b) &&
          listEqual(tokenModifiers, other.tokenModifiers,
              (String a, String b) => a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(tokenTypes));
    hash = JenkinsSmiHash.combine(hash, lspHashCode(tokenModifiers));
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SemanticTokensOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
      SemanticTokensOptions.canParse, SemanticTokensOptions.fromJson);

  SemanticTokensOptions(
      {@required this.legend, this.range, this.full, this.workDoneProgress}) {
    if (legend == null) {
      throw 'legend is required but was not provided';
    }
  }
  static SemanticTokensOptions fromJson(Map<String, dynamic> json) {
    if (SemanticTokensRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return SemanticTokensRegistrationOptions.fromJson(json);
    }
    final legend = json['legend'] != null
        ? SemanticTokensLegend.fromJson(json['legend'])
        : null;
    final range = json['range'] is bool
        ? Either2<bool, SemanticTokensOptionsRange>.t1(json['range'])
        : (SemanticTokensOptionsRange.canParse(
                json['range'], nullLspJsonReporter)
            ? Either2<bool, SemanticTokensOptionsRange>.t2(json['range'] != null
                ? SemanticTokensOptionsRange.fromJson(json['range'])
                : null)
            : (json['range'] == null
                ? null
                : (throw '''${json['range']} was not one of (bool, SemanticTokensOptionsRange)''')));
    final full = json['full'] is bool
        ? Either2<bool, SemanticTokensOptionsFull>.t1(json['full'])
        : (SemanticTokensOptionsFull.canParse(json['full'], nullLspJsonReporter)
            ? Either2<bool, SemanticTokensOptionsFull>.t2(json['full'] != null
                ? SemanticTokensOptionsFull.fromJson(json['full'])
                : null)
            : (json['full'] == null
                ? null
                : (throw '''${json['full']} was not one of (bool, SemanticTokensOptionsFull)''')));
    final workDoneProgress = json['workDoneProgress'];
    return SemanticTokensOptions(
        legend: legend,
        range: range,
        full: full,
        workDoneProgress: workDoneProgress);
  }

  /// Server supports providing semantic tokens for a full document.
  final Either2<bool, SemanticTokensOptionsFull> full;

  /// The legend used by the server
  final SemanticTokensLegend legend;

  /// Server supports providing semantic tokens for a specific range of a
  /// document.
  final Either2<bool, SemanticTokensOptionsRange> range;
  final bool workDoneProgress;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['legend'] =
        legend?.toJson() ?? (throw 'legend is required but was not set');
    if (range != null) {
      __result['range'] = range;
    }
    if (full != null) {
      __result['full'] = full;
    }
    if (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('legend');
      try {
        if (!obj.containsKey('legend')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['legend'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(SemanticTokensLegend.canParse(obj['legend'], reporter))) {
          reporter.reportError('must be of type SemanticTokensLegend');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('range');
      try {
        if (obj['range'] != null &&
            !((obj['range'] is bool ||
                SemanticTokensOptionsRange.canParse(obj['range'], reporter)))) {
          reporter.reportError(
              'must be of type Either2<bool, SemanticTokensOptionsRange>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('full');
      try {
        if (obj['full'] != null &&
            !((obj['full'] is bool ||
                SemanticTokensOptionsFull.canParse(obj['full'], reporter)))) {
          reporter.reportError(
              'must be of type Either2<bool, SemanticTokensOptionsFull>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        if (obj['workDoneProgress'] != null &&
            !(obj['workDoneProgress'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SemanticTokensOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SemanticTokensOptions &&
        other.runtimeType == SemanticTokensOptions) {
      return legend == other.legend &&
          range == other.range &&
          full == other.full &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, legend.hashCode);
    hash = JenkinsSmiHash.combine(hash, range.hashCode);
    hash = JenkinsSmiHash.combine(hash, full.hashCode);
    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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, dynamic> json) {
    final delta = json['delta'];
    return SemanticTokensOptionsFull(delta: delta);
  }

  /// The server supports deltas for full documents.
  final bool delta;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (delta != null) {
      __result['delta'] = delta;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('delta');
      try {
        if (obj['delta'] != null && !(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, delta.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SemanticTokensOptionsRange implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
      SemanticTokensOptionsRange.canParse, SemanticTokensOptionsRange.fromJson);

  static SemanticTokensOptionsRange fromJson(Map<String, dynamic> json) {
    return SemanticTokensOptionsRange();
  }

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      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 {
    var hash = 0;
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SemanticTokensParams
    implements WorkDoneProgressParams, PartialResultParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
      SemanticTokensParams.canParse, SemanticTokensParams.fromJson);

  SemanticTokensParams(
      {@required this.textDocument,
      this.workDoneToken,
      this.partialResultToken}) {
    if (textDocument == null) {
      throw 'textDocument is required but was not provided';
    }
  }
  static SemanticTokensParams fromJson(Map<String, dynamic> json) {
    final textDocument = json['textDocument'] != null
        ? TextDocumentIdentifier.fromJson(json['textDocument'])
        : null;
    final workDoneToken = json['workDoneToken'] is num
        ? Either2<num, String>.t1(json['workDoneToken'])
        : (json['workDoneToken'] is String
            ? Either2<num, String>.t2(json['workDoneToken'])
            : (json['workDoneToken'] == null
                ? null
                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
    final partialResultToken = json['partialResultToken'] is num
        ? Either2<num, String>.t1(json['partialResultToken'])
        : (json['partialResultToken'] is String
            ? Either2<num, String>.t2(json['partialResultToken'])
            : (json['partialResultToken'] == null
                ? null
                : (throw '''${json['partialResultToken']} was not one of (num, String)''')));
    return SemanticTokensParams(
        textDocument: textDocument,
        workDoneToken: workDoneToken,
        partialResultToken: partialResultToken);
  }

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  final Either2<num, String> partialResultToken;

  /// The text document.
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  final Either2<num, String> workDoneToken;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['textDocument'] = textDocument?.toJson() ??
        (throw 'textDocument is required but was not set');
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    if (partialResultToken != null) {
      __result['partialResultToken'] = partialResultToken;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['textDocument'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(TextDocumentIdentifier.canParse(obj['textDocument'], reporter))) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        if (obj['workDoneToken'] != null &&
            !((obj['workDoneToken'] is num ||
                obj['workDoneToken'] is String))) {
          reporter.reportError('must be of type Either2<num, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('partialResultToken');
      try {
        if (obj['partialResultToken'] != null &&
            !((obj['partialResultToken'] is num ||
                obj['partialResultToken'] is String))) {
          reporter.reportError('must be of type Either2<num, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SemanticTokensParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SemanticTokensParams &&
        other.runtimeType == SemanticTokensParams) {
      return textDocument == other.textDocument &&
          workDoneToken == other.workDoneToken &&
          partialResultToken == other.partialResultToken &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, textDocument.hashCode);
    hash = JenkinsSmiHash.combine(hash, workDoneToken.hashCode);
    hash = JenkinsSmiHash.combine(hash, partialResultToken.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SemanticTokensPartialResult implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
      SemanticTokensPartialResult.canParse,
      SemanticTokensPartialResult.fromJson);

  SemanticTokensPartialResult({@required this.data}) {
    if (data == null) {
      throw 'data is required but was not provided';
    }
  }
  static SemanticTokensPartialResult fromJson(Map<String, dynamic> json) {
    final data = json['data']?.map((item) => item)?.cast<num>()?.toList();
    return SemanticTokensPartialResult(data: data);
  }

  final List<num> data;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['data'] = data ?? (throw 'data is required but was not set');
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('data');
      try {
        if (!obj.containsKey('data')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['data'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!((obj['data'] is List &&
            (obj['data'].every((item) => item is num))))) {
          reporter.reportError('must be of type List<num>');
          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, (num a, num b) => a == b) && true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(data));
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SemanticTokensRangeParams
    implements WorkDoneProgressParams, PartialResultParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
      SemanticTokensRangeParams.canParse, SemanticTokensRangeParams.fromJson);

  SemanticTokensRangeParams(
      {@required this.textDocument,
      @required this.range,
      this.workDoneToken,
      this.partialResultToken}) {
    if (textDocument == null) {
      throw 'textDocument is required but was not provided';
    }
    if (range == null) {
      throw 'range is required but was not provided';
    }
  }
  static SemanticTokensRangeParams fromJson(Map<String, dynamic> json) {
    final textDocument = json['textDocument'] != null
        ? TextDocumentIdentifier.fromJson(json['textDocument'])
        : null;
    final range = json['range'] != null ? Range.fromJson(json['range']) : null;
    final workDoneToken = json['workDoneToken'] is num
        ? Either2<num, String>.t1(json['workDoneToken'])
        : (json['workDoneToken'] is String
            ? Either2<num, String>.t2(json['workDoneToken'])
            : (json['workDoneToken'] == null
                ? null
                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
    final partialResultToken = json['partialResultToken'] is num
        ? Either2<num, String>.t1(json['partialResultToken'])
        : (json['partialResultToken'] is String
            ? Either2<num, String>.t2(json['partialResultToken'])
            : (json['partialResultToken'] == null
                ? null
                : (throw '''${json['partialResultToken']} was not one of (num, String)''')));
    return SemanticTokensRangeParams(
        textDocument: textDocument,
        range: range,
        workDoneToken: workDoneToken,
        partialResultToken: partialResultToken);
  }

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  final Either2<num, String> partialResultToken;

  /// The range the semantic tokens are requested for.
  final Range range;

  /// The text document.
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  final Either2<num, String> workDoneToken;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['textDocument'] = textDocument?.toJson() ??
        (throw 'textDocument is required but was not set');
    __result['range'] =
        range?.toJson() ?? (throw 'range is required but was not set');
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    if (partialResultToken != null) {
      __result['partialResultToken'] = partialResultToken;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['textDocument'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(TextDocumentIdentifier.canParse(obj['textDocument'], reporter))) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('range');
      try {
        if (!obj.containsKey('range')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['range'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(Range.canParse(obj['range'], reporter))) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        if (obj['workDoneToken'] != null &&
            !((obj['workDoneToken'] is num ||
                obj['workDoneToken'] is String))) {
          reporter.reportError('must be of type Either2<num, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('partialResultToken');
      try {
        if (obj['partialResultToken'] != null &&
            !((obj['partialResultToken'] is num ||
                obj['partialResultToken'] is String))) {
          reporter.reportError('must be of type Either2<num, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SemanticTokensRangeParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SemanticTokensRangeParams &&
        other.runtimeType == SemanticTokensRangeParams) {
      return textDocument == other.textDocument &&
          range == other.range &&
          workDoneToken == other.workDoneToken &&
          partialResultToken == other.partialResultToken &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, textDocument.hashCode);
    hash = JenkinsSmiHash.combine(hash, range.hashCode);
    hash = JenkinsSmiHash.combine(hash, workDoneToken.hashCode);
    hash = JenkinsSmiHash.combine(hash, partialResultToken.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SemanticTokensRegistrationOptions
    implements
        TextDocumentRegistrationOptions,
        SemanticTokensOptions,
        StaticRegistrationOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
      SemanticTokensRegistrationOptions.canParse,
      SemanticTokensRegistrationOptions.fromJson);

  SemanticTokensRegistrationOptions(
      {this.documentSelector,
      @required this.legend,
      this.range,
      this.full,
      this.workDoneProgress,
      this.id}) {
    if (legend == null) {
      throw 'legend is required but was not provided';
    }
  }
  static SemanticTokensRegistrationOptions fromJson(Map<String, dynamic> json) {
    final documentSelector = json['documentSelector']
        ?.map((item) => item != null ? DocumentFilter.fromJson(item) : null)
        ?.cast<DocumentFilter>()
        ?.toList();
    final legend = json['legend'] != null
        ? SemanticTokensLegend.fromJson(json['legend'])
        : null;
    final range = json['range'] is bool
        ? Either2<bool, SemanticTokensOptionsRange>.t1(json['range'])
        : (SemanticTokensOptionsRange.canParse(
                json['range'], nullLspJsonReporter)
            ? Either2<bool, SemanticTokensOptionsRange>.t2(json['range'] != null
                ? SemanticTokensOptionsRange.fromJson(json['range'])
                : null)
            : (json['range'] == null
                ? null
                : (throw '''${json['range']} was not one of (bool, SemanticTokensOptionsRange)''')));
    final full = json['full'] is bool
        ? Either2<bool, SemanticTokensOptionsFull>.t1(json['full'])
        : (SemanticTokensOptionsFull.canParse(json['full'], nullLspJsonReporter)
            ? Either2<bool, SemanticTokensOptionsFull>.t2(json['full'] != null
                ? SemanticTokensOptionsFull.fromJson(json['full'])
                : null)
            : (json['full'] == null
                ? null
                : (throw '''${json['full']} was not one of (bool, SemanticTokensOptionsFull)''')));
    final workDoneProgress = json['workDoneProgress'];
    final id = json['id'];
    return SemanticTokensRegistrationOptions(
        documentSelector: documentSelector,
        legend: legend,
        range: range,
        full: full,
        workDoneProgress: workDoneProgress,
        id: id);
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  final List<DocumentFilter> documentSelector;

  /// Server supports providing semantic tokens for a full document.
  final Either2<bool, SemanticTokensOptionsFull> full;

  /// The id used to register the request. The id can be used to deregister the
  /// request again. See also Registration#id.
  final String id;

  /// The legend used by the server
  final SemanticTokensLegend legend;

  /// Server supports providing semantic tokens for a specific range of a
  /// document.
  final Either2<bool, SemanticTokensOptionsRange> range;
  final bool workDoneProgress;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['documentSelector'] = documentSelector;
    __result['legend'] =
        legend?.toJson() ?? (throw 'legend is required but was not set');
    if (range != null) {
      __result['range'] = range;
    }
    if (full != null) {
      __result['full'] = full;
    }
    if (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    if (id != null) {
      __result['id'] = id;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['documentSelector'] != null &&
            !((obj['documentSelector'] is List &&
                (obj['documentSelector'].every(
                    (item) => DocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<DocumentFilter>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('legend');
      try {
        if (!obj.containsKey('legend')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['legend'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(SemanticTokensLegend.canParse(obj['legend'], reporter))) {
          reporter.reportError('must be of type SemanticTokensLegend');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('range');
      try {
        if (obj['range'] != null &&
            !((obj['range'] is bool ||
                SemanticTokensOptionsRange.canParse(obj['range'], reporter)))) {
          reporter.reportError(
              'must be of type Either2<bool, SemanticTokensOptionsRange>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('full');
      try {
        if (obj['full'] != null &&
            !((obj['full'] is bool ||
                SemanticTokensOptionsFull.canParse(obj['full'], reporter)))) {
          reporter.reportError(
              'must be of type Either2<bool, SemanticTokensOptionsFull>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        if (obj['workDoneProgress'] != null &&
            !(obj['workDoneProgress'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('id');
      try {
        if (obj['id'] != null && !(obj['id'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SemanticTokensRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SemanticTokensRegistrationOptions &&
        other.runtimeType == SemanticTokensRegistrationOptions) {
      return listEqual(documentSelector, other.documentSelector,
              (DocumentFilter a, DocumentFilter b) => a == b) &&
          legend == other.legend &&
          range == other.range &&
          full == other.full &&
          workDoneProgress == other.workDoneProgress &&
          id == other.id &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(documentSelector));
    hash = JenkinsSmiHash.combine(hash, legend.hashCode);
    hash = JenkinsSmiHash.combine(hash, range.hashCode);
    hash = JenkinsSmiHash.combine(hash, full.hashCode);
    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
    hash = JenkinsSmiHash.combine(hash, id.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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, dynamic> json) {
    final refreshSupport = json['refreshSupport'];
    return SemanticTokensWorkspaceClientCapabilities(
        refreshSupport: refreshSupport);
  }

  /// Whether the client implementation supports a refresh request sent from the
  /// server to the client.
  ///
  /// Note that this event is global and will force the client to refresh all
  /// semantic tokens currently shown. It should be used with absolute care and
  /// is useful for situation where a server for example detect a project wide
  /// change that requires such a calculation.
  final bool refreshSupport;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (refreshSupport != null) {
      __result['refreshSupport'] = refreshSupport;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('refreshSupport');
      try {
        if (obj['refreshSupport'] != null && !(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, refreshSupport.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class ServerCapabilities implements ToJsonable {
  static const jsonHandler =
      LspJsonHandler(ServerCapabilities.canParse, ServerCapabilities.fromJson);

  ServerCapabilities(
      {this.textDocumentSync,
      this.completionProvider,
      this.hoverProvider,
      this.signatureHelpProvider,
      this.declarationProvider,
      this.definitionProvider,
      this.typeDefinitionProvider,
      this.implementationProvider,
      this.referencesProvider,
      this.documentHighlightProvider,
      this.documentSymbolProvider,
      this.codeActionProvider,
      this.codeLensProvider,
      this.documentLinkProvider,
      this.colorProvider,
      this.documentFormattingProvider,
      this.documentRangeFormattingProvider,
      this.documentOnTypeFormattingProvider,
      this.renameProvider,
      this.foldingRangeProvider,
      this.executeCommandProvider,
      this.selectionRangeProvider,
      this.linkedEditingRangeProvider,
      this.callHierarchyProvider,
      this.semanticTokensProvider,
      this.monikerProvider,
      this.workspaceSymbolProvider,
      this.workspace,
      this.experimental});
  static ServerCapabilities fromJson(Map<String, dynamic> json) {
    final textDocumentSync = TextDocumentSyncOptions.canParse(
            json['textDocumentSync'], nullLspJsonReporter)
        ? Either2<TextDocumentSyncOptions, TextDocumentSyncKind>.t1(
            json['textDocumentSync'] != null
                ? TextDocumentSyncOptions.fromJson(json['textDocumentSync'])
                : null)
        : (TextDocumentSyncKind.canParse(
                json['textDocumentSync'], nullLspJsonReporter)
            ? Either2<TextDocumentSyncOptions, TextDocumentSyncKind>.t2(
                json['textDocumentSync'] != null
                    ? TextDocumentSyncKind.fromJson(json['textDocumentSync'])
                    : null)
            : (json['textDocumentSync'] == null
                ? null
                : (throw '''${json['textDocumentSync']} was not one of (TextDocumentSyncOptions, TextDocumentSyncKind)''')));
    final completionProvider = json['completionProvider'] != null
        ? CompletionOptions.fromJson(json['completionProvider'])
        : null;
    final hoverProvider = json['hoverProvider'] is bool
        ? Either2<bool, HoverOptions>.t1(json['hoverProvider'])
        : (HoverOptions.canParse(json['hoverProvider'], nullLspJsonReporter)
            ? Either2<bool, HoverOptions>.t2(json['hoverProvider'] != null
                ? HoverOptions.fromJson(json['hoverProvider'])
                : null)
            : (json['hoverProvider'] == null
                ? null
                : (throw '''${json['hoverProvider']} was not one of (bool, HoverOptions)''')));
    final signatureHelpProvider = json['signatureHelpProvider'] != null
        ? SignatureHelpOptions.fromJson(json['signatureHelpProvider'])
        : null;
    final declarationProvider = json['declarationProvider'] is bool
        ? Either3<bool, DeclarationOptions, DeclarationRegistrationOptions>.t1(
            json['declarationProvider'])
        : (DeclarationOptions.canParse(
                json['declarationProvider'], nullLspJsonReporter)
            ? Either3<bool, DeclarationOptions, DeclarationRegistrationOptions>.t2(
                json['declarationProvider'] != null
                    ? DeclarationOptions.fromJson(json['declarationProvider'])
                    : null)
            : (DeclarationRegistrationOptions.canParse(
                    json['declarationProvider'], nullLspJsonReporter)
                ? Either3<bool, DeclarationOptions, DeclarationRegistrationOptions>.t3(
                    json['declarationProvider'] != null
                        ? DeclarationRegistrationOptions.fromJson(
                            json['declarationProvider'])
                        : null)
                : (json['declarationProvider'] == null
                    ? null
                    : (throw '''${json['declarationProvider']} was not one of (bool, DeclarationOptions, DeclarationRegistrationOptions)'''))));
    final definitionProvider = json['definitionProvider'] is bool
        ? Either2<bool, DefinitionOptions>.t1(json['definitionProvider'])
        : (DefinitionOptions.canParse(
                json['definitionProvider'], nullLspJsonReporter)
            ? Either2<bool, DefinitionOptions>.t2(
                json['definitionProvider'] != null
                    ? DefinitionOptions.fromJson(json['definitionProvider'])
                    : null)
            : (json['definitionProvider'] == null
                ? null
                : (throw '''${json['definitionProvider']} was not one of (bool, DefinitionOptions)''')));
    final typeDefinitionProvider = json['typeDefinitionProvider'] is bool
        ? Either3<bool, TypeDefinitionOptions, TypeDefinitionRegistrationOptions>.t1(
            json['typeDefinitionProvider'])
        : (TypeDefinitionOptions.canParse(
                json['typeDefinitionProvider'], nullLspJsonReporter)
            ? Either3<bool, TypeDefinitionOptions, TypeDefinitionRegistrationOptions>.t2(json['typeDefinitionProvider'] != null
                ? TypeDefinitionOptions.fromJson(json['typeDefinitionProvider'])
                : null)
            : (TypeDefinitionRegistrationOptions.canParse(
                    json['typeDefinitionProvider'], nullLspJsonReporter)
                ? Either3<bool, TypeDefinitionOptions, TypeDefinitionRegistrationOptions>.t3(
                    json['typeDefinitionProvider'] != null
                        ? TypeDefinitionRegistrationOptions.fromJson(
                            json['typeDefinitionProvider'])
                        : null)
                : (json['typeDefinitionProvider'] == null
                    ? null
                    : (throw '''${json['typeDefinitionProvider']} was not one of (bool, TypeDefinitionOptions, TypeDefinitionRegistrationOptions)'''))));
    final implementationProvider = json['implementationProvider'] is bool
        ? Either3<bool, ImplementationOptions, ImplementationRegistrationOptions>.t1(
            json['implementationProvider'])
        : (ImplementationOptions.canParse(
                json['implementationProvider'], nullLspJsonReporter)
            ? Either3<bool, ImplementationOptions, ImplementationRegistrationOptions>.t2(json['implementationProvider'] != null
                ? ImplementationOptions.fromJson(json['implementationProvider'])
                : null)
            : (ImplementationRegistrationOptions.canParse(
                    json['implementationProvider'], nullLspJsonReporter)
                ? Either3<bool, ImplementationOptions, ImplementationRegistrationOptions>.t3(
                    json['implementationProvider'] != null
                        ? ImplementationRegistrationOptions.fromJson(
                            json['implementationProvider'])
                        : null)
                : (json['implementationProvider'] == null
                    ? null
                    : (throw '''${json['implementationProvider']} was not one of (bool, ImplementationOptions, ImplementationRegistrationOptions)'''))));
    final referencesProvider = json['referencesProvider'] is bool
        ? Either2<bool, ReferenceOptions>.t1(json['referencesProvider'])
        : (ReferenceOptions.canParse(
                json['referencesProvider'], nullLspJsonReporter)
            ? Either2<bool, ReferenceOptions>.t2(
                json['referencesProvider'] != null
                    ? ReferenceOptions.fromJson(json['referencesProvider'])
                    : null)
            : (json['referencesProvider'] == null
                ? null
                : (throw '''${json['referencesProvider']} was not one of (bool, ReferenceOptions)''')));
    final documentHighlightProvider = json['documentHighlightProvider'] is bool
        ? Either2<bool, DocumentHighlightOptions>.t1(
            json['documentHighlightProvider'])
        : (DocumentHighlightOptions.canParse(
                json['documentHighlightProvider'], nullLspJsonReporter)
            ? Either2<bool, DocumentHighlightOptions>.t2(
                json['documentHighlightProvider'] != null
                    ? DocumentHighlightOptions.fromJson(
                        json['documentHighlightProvider'])
                    : null)
            : (json['documentHighlightProvider'] == null
                ? null
                : (throw '''${json['documentHighlightProvider']} was not one of (bool, DocumentHighlightOptions)''')));
    final documentSymbolProvider = json['documentSymbolProvider'] is bool
        ? Either2<bool, DocumentSymbolOptions>.t1(
            json['documentSymbolProvider'])
        : (DocumentSymbolOptions.canParse(
                json['documentSymbolProvider'], nullLspJsonReporter)
            ? Either2<bool, DocumentSymbolOptions>.t2(
                json['documentSymbolProvider'] != null
                    ? DocumentSymbolOptions.fromJson(
                        json['documentSymbolProvider'])
                    : null)
            : (json['documentSymbolProvider'] == null
                ? null
                : (throw '''${json['documentSymbolProvider']} was not one of (bool, DocumentSymbolOptions)''')));
    final codeActionProvider = json['codeActionProvider'] is bool
        ? Either2<bool, CodeActionOptions>.t1(json['codeActionProvider'])
        : (CodeActionOptions.canParse(
                json['codeActionProvider'], nullLspJsonReporter)
            ? Either2<bool, CodeActionOptions>.t2(
                json['codeActionProvider'] != null
                    ? CodeActionOptions.fromJson(json['codeActionProvider'])
                    : null)
            : (json['codeActionProvider'] == null
                ? null
                : (throw '''${json['codeActionProvider']} was not one of (bool, CodeActionOptions)''')));
    final codeLensProvider = json['codeLensProvider'] != null
        ? CodeLensOptions.fromJson(json['codeLensProvider'])
        : null;
    final documentLinkProvider = json['documentLinkProvider'] != null
        ? DocumentLinkOptions.fromJson(json['documentLinkProvider'])
        : null;
    final colorProvider = json['colorProvider'] is bool
        ? Either3<bool, DocumentColorOptions, DocumentColorRegistrationOptions>.t1(
            json['colorProvider'])
        : (DocumentColorOptions.canParse(
                json['colorProvider'], nullLspJsonReporter)
            ? Either3<bool, DocumentColorOptions, DocumentColorRegistrationOptions>.t2(
                json['colorProvider'] != null
                    ? DocumentColorOptions.fromJson(json['colorProvider'])
                    : null)
            : (DocumentColorRegistrationOptions.canParse(
                    json['colorProvider'], nullLspJsonReporter)
                ? Either3<bool, DocumentColorOptions, DocumentColorRegistrationOptions>.t3(
                    json['colorProvider'] != null
                        ? DocumentColorRegistrationOptions.fromJson(
                            json['colorProvider'])
                        : null)
                : (json['colorProvider'] == null
                    ? null
                    : (throw '''${json['colorProvider']} was not one of (bool, DocumentColorOptions, DocumentColorRegistrationOptions)'''))));
    final documentFormattingProvider = json['documentFormattingProvider']
            is bool
        ? Either2<bool, DocumentFormattingOptions>.t1(
            json['documentFormattingProvider'])
        : (DocumentFormattingOptions.canParse(
                json['documentFormattingProvider'], nullLspJsonReporter)
            ? Either2<bool, DocumentFormattingOptions>.t2(
                json['documentFormattingProvider'] != null
                    ? DocumentFormattingOptions.fromJson(
                        json['documentFormattingProvider'])
                    : null)
            : (json['documentFormattingProvider'] == null
                ? null
                : (throw '''${json['documentFormattingProvider']} was not one of (bool, DocumentFormattingOptions)''')));
    final documentRangeFormattingProvider = json[
            'documentRangeFormattingProvider'] is bool
        ? Either2<bool, DocumentRangeFormattingOptions>.t1(
            json['documentRangeFormattingProvider'])
        : (DocumentRangeFormattingOptions.canParse(
                json['documentRangeFormattingProvider'], nullLspJsonReporter)
            ? Either2<bool, DocumentRangeFormattingOptions>.t2(
                json['documentRangeFormattingProvider'] != null
                    ? DocumentRangeFormattingOptions.fromJson(
                        json['documentRangeFormattingProvider'])
                    : null)
            : (json['documentRangeFormattingProvider'] == null
                ? null
                : (throw '''${json['documentRangeFormattingProvider']} was not one of (bool, DocumentRangeFormattingOptions)''')));
    final documentOnTypeFormattingProvider =
        json['documentOnTypeFormattingProvider'] != null
            ? DocumentOnTypeFormattingOptions.fromJson(
                json['documentOnTypeFormattingProvider'])
            : null;
    final renameProvider = json['renameProvider'] is bool
        ? Either2<bool, RenameOptions>.t1(json['renameProvider'])
        : (RenameOptions.canParse(json['renameProvider'], nullLspJsonReporter)
            ? Either2<bool, RenameOptions>.t2(json['renameProvider'] != null
                ? RenameOptions.fromJson(json['renameProvider'])
                : null)
            : (json['renameProvider'] == null
                ? null
                : (throw '''${json['renameProvider']} was not one of (bool, RenameOptions)''')));
    final foldingRangeProvider = json['foldingRangeProvider'] is bool
        ? Either3<bool, FoldingRangeOptions, FoldingRangeRegistrationOptions>.t1(
            json['foldingRangeProvider'])
        : (FoldingRangeOptions.canParse(
                json['foldingRangeProvider'], nullLspJsonReporter)
            ? Either3<bool, FoldingRangeOptions, FoldingRangeRegistrationOptions>.t2(
                json['foldingRangeProvider'] != null
                    ? FoldingRangeOptions.fromJson(json['foldingRangeProvider'])
                    : null)
            : (FoldingRangeRegistrationOptions.canParse(
                    json['foldingRangeProvider'], nullLspJsonReporter)
                ? Either3<bool, FoldingRangeOptions, FoldingRangeRegistrationOptions>.t3(
                    json['foldingRangeProvider'] != null
                        ? FoldingRangeRegistrationOptions.fromJson(
                            json['foldingRangeProvider'])
                        : null)
                : (json['foldingRangeProvider'] == null
                    ? null
                    : (throw '''${json['foldingRangeProvider']} was not one of (bool, FoldingRangeOptions, FoldingRangeRegistrationOptions)'''))));
    final executeCommandProvider = json['executeCommandProvider'] != null
        ? ExecuteCommandOptions.fromJson(json['executeCommandProvider'])
        : null;
    final selectionRangeProvider = json['selectionRangeProvider'] is bool
        ? Either3<bool, SelectionRangeOptions, SelectionRangeRegistrationOptions>.t1(
            json['selectionRangeProvider'])
        : (SelectionRangeOptions.canParse(
                json['selectionRangeProvider'], nullLspJsonReporter)
            ? Either3<bool, SelectionRangeOptions, SelectionRangeRegistrationOptions>.t2(json['selectionRangeProvider'] != null
                ? SelectionRangeOptions.fromJson(json['selectionRangeProvider'])
                : null)
            : (SelectionRangeRegistrationOptions.canParse(
                    json['selectionRangeProvider'], nullLspJsonReporter)
                ? Either3<bool, SelectionRangeOptions, SelectionRangeRegistrationOptions>.t3(
                    json['selectionRangeProvider'] != null
                        ? SelectionRangeRegistrationOptions.fromJson(
                            json['selectionRangeProvider'])
                        : null)
                : (json['selectionRangeProvider'] == null
                    ? null
                    : (throw '''${json['selectionRangeProvider']} was not one of (bool, SelectionRangeOptions, SelectionRangeRegistrationOptions)'''))));
    final linkedEditingRangeProvider = json['linkedEditingRangeProvider']
            is bool
        ? Either3<bool, LinkedEditingRangeOptions, LinkedEditingRangeRegistrationOptions>.t1(
            json['linkedEditingRangeProvider'])
        : (LinkedEditingRangeOptions.canParse(json['linkedEditingRangeProvider'], nullLspJsonReporter)
            ? Either3<bool, LinkedEditingRangeOptions, LinkedEditingRangeRegistrationOptions>.t2(
                json['linkedEditingRangeProvider'] != null
                    ? LinkedEditingRangeOptions.fromJson(
                        json['linkedEditingRangeProvider'])
                    : null)
            : (LinkedEditingRangeRegistrationOptions.canParse(json['linkedEditingRangeProvider'], nullLspJsonReporter)
                ? Either3<bool, LinkedEditingRangeOptions, LinkedEditingRangeRegistrationOptions>.t3(
                    json['linkedEditingRangeProvider'] != null
                        ? LinkedEditingRangeRegistrationOptions.fromJson(
                            json['linkedEditingRangeProvider'])
                        : null)
                : (json['linkedEditingRangeProvider'] == null
                    ? null
                    : (throw '''${json['linkedEditingRangeProvider']} was not one of (bool, LinkedEditingRangeOptions, LinkedEditingRangeRegistrationOptions)'''))));
    final callHierarchyProvider = json['callHierarchyProvider'] is bool
        ? Either3<bool, CallHierarchyOptions, CallHierarchyRegistrationOptions>.t1(
            json['callHierarchyProvider'])
        : (CallHierarchyOptions.canParse(
                json['callHierarchyProvider'], nullLspJsonReporter)
            ? Either3<bool, CallHierarchyOptions, CallHierarchyRegistrationOptions>.t2(json['callHierarchyProvider'] != null
                ? CallHierarchyOptions.fromJson(json['callHierarchyProvider'])
                : null)
            : (CallHierarchyRegistrationOptions.canParse(
                    json['callHierarchyProvider'], nullLspJsonReporter)
                ? Either3<bool, CallHierarchyOptions, CallHierarchyRegistrationOptions>.t3(
                    json['callHierarchyProvider'] != null
                        ? CallHierarchyRegistrationOptions.fromJson(
                            json['callHierarchyProvider'])
                        : null)
                : (json['callHierarchyProvider'] == null
                    ? null
                    : (throw '''${json['callHierarchyProvider']} was not one of (bool, CallHierarchyOptions, CallHierarchyRegistrationOptions)'''))));
    final semanticTokensProvider = SemanticTokensOptions.canParse(
            json['semanticTokensProvider'], nullLspJsonReporter)
        ? Either2<SemanticTokensOptions, SemanticTokensRegistrationOptions>.t1(
            json['semanticTokensProvider'] != null
                ? SemanticTokensOptions.fromJson(json['semanticTokensProvider'])
                : null)
        : (SemanticTokensRegistrationOptions.canParse(
                json['semanticTokensProvider'], nullLspJsonReporter)
            ? Either2<SemanticTokensOptions, SemanticTokensRegistrationOptions>.t2(
                json['semanticTokensProvider'] != null
                    ? SemanticTokensRegistrationOptions.fromJson(
                        json['semanticTokensProvider'])
                    : null)
            : (json['semanticTokensProvider'] == null
                ? null
                : (throw '''${json['semanticTokensProvider']} was not one of (SemanticTokensOptions, SemanticTokensRegistrationOptions)''')));
    final monikerProvider = json['monikerProvider'] is bool
        ? Either3<bool, MonikerOptions, MonikerRegistrationOptions>.t1(
            json['monikerProvider'])
        : (MonikerOptions.canParse(json['monikerProvider'], nullLspJsonReporter)
            ? Either3<bool, MonikerOptions, MonikerRegistrationOptions>.t2(
                json['monikerProvider'] != null
                    ? MonikerOptions.fromJson(json['monikerProvider'])
                    : null)
            : (MonikerRegistrationOptions.canParse(
                    json['monikerProvider'], nullLspJsonReporter)
                ? Either3<bool, MonikerOptions, MonikerRegistrationOptions>.t3(
                    json['monikerProvider'] != null
                        ? MonikerRegistrationOptions.fromJson(
                            json['monikerProvider'])
                        : null)
                : (json['monikerProvider'] == null
                    ? null
                    : (throw '''${json['monikerProvider']} was not one of (bool, MonikerOptions, MonikerRegistrationOptions)'''))));
    final workspaceSymbolProvider = json['workspaceSymbolProvider'] is bool
        ? Either2<bool, WorkspaceSymbolOptions>.t1(
            json['workspaceSymbolProvider'])
        : (WorkspaceSymbolOptions.canParse(
                json['workspaceSymbolProvider'], nullLspJsonReporter)
            ? Either2<bool, WorkspaceSymbolOptions>.t2(
                json['workspaceSymbolProvider'] != null
                    ? WorkspaceSymbolOptions.fromJson(
                        json['workspaceSymbolProvider'])
                    : null)
            : (json['workspaceSymbolProvider'] == null
                ? null
                : (throw '''${json['workspaceSymbolProvider']} was not one of (bool, WorkspaceSymbolOptions)''')));
    final workspace = json['workspace'] != null
        ? ServerCapabilitiesWorkspace.fromJson(json['workspace'])
        : null;
    final experimental = json['experimental'];
    return ServerCapabilities(
        textDocumentSync: textDocumentSync,
        completionProvider: completionProvider,
        hoverProvider: hoverProvider,
        signatureHelpProvider: signatureHelpProvider,
        declarationProvider: declarationProvider,
        definitionProvider: definitionProvider,
        typeDefinitionProvider: typeDefinitionProvider,
        implementationProvider: implementationProvider,
        referencesProvider: referencesProvider,
        documentHighlightProvider: documentHighlightProvider,
        documentSymbolProvider: documentSymbolProvider,
        codeActionProvider: codeActionProvider,
        codeLensProvider: codeLensProvider,
        documentLinkProvider: documentLinkProvider,
        colorProvider: colorProvider,
        documentFormattingProvider: documentFormattingProvider,
        documentRangeFormattingProvider: documentRangeFormattingProvider,
        documentOnTypeFormattingProvider: documentOnTypeFormattingProvider,
        renameProvider: renameProvider,
        foldingRangeProvider: foldingRangeProvider,
        executeCommandProvider: executeCommandProvider,
        selectionRangeProvider: selectionRangeProvider,
        linkedEditingRangeProvider: linkedEditingRangeProvider,
        callHierarchyProvider: callHierarchyProvider,
        semanticTokensProvider: semanticTokensProvider,
        monikerProvider: monikerProvider,
        workspaceSymbolProvider: workspaceSymbolProvider,
        workspace: workspace,
        experimental: experimental);
  }

  /// The server provides call hierarchy support.
  ///  @since 3.16.0
  final Either3<bool, CallHierarchyOptions, CallHierarchyRegistrationOptions>
      callHierarchyProvider;

  /// The server provides code actions. The `CodeActionOptions` return type is
  /// only valid if the client signals code action literal support via the
  /// property `textDocument.codeAction.codeActionLiteralSupport`.
  final Either2<bool, CodeActionOptions> codeActionProvider;

  /// The server provides code lens.
  final CodeLensOptions codeLensProvider;

  /// The server provides color provider support.
  ///  @since 3.6.0
  final Either3<bool, DocumentColorOptions, DocumentColorRegistrationOptions>
      colorProvider;

  /// The server provides completion support.
  final CompletionOptions completionProvider;

  /// The server provides go to declaration support.
  ///  @since 3.14.0
  final Either3<bool, DeclarationOptions, DeclarationRegistrationOptions>
      declarationProvider;

  /// The server provides goto definition support.
  final Either2<bool, DefinitionOptions> definitionProvider;

  /// The server provides document formatting.
  final Either2<bool, DocumentFormattingOptions> documentFormattingProvider;

  /// The server provides document highlight support.
  final Either2<bool, DocumentHighlightOptions> documentHighlightProvider;

  /// The server provides document link support.
  final DocumentLinkOptions documentLinkProvider;

  /// The server provides document formatting on typing.
  final DocumentOnTypeFormattingOptions documentOnTypeFormattingProvider;

  /// The server provides document range formatting.
  final Either2<bool, DocumentRangeFormattingOptions>
      documentRangeFormattingProvider;

  /// The server provides document symbol support.
  final Either2<bool, DocumentSymbolOptions> documentSymbolProvider;

  /// The server provides execute command support.
  final ExecuteCommandOptions executeCommandProvider;

  /// Experimental server capabilities.
  final dynamic experimental;

  /// The server provides folding provider support.
  ///  @since 3.10.0
  final Either3<bool, FoldingRangeOptions, FoldingRangeRegistrationOptions>
      foldingRangeProvider;

  /// The server provides hover support.
  final Either2<bool, HoverOptions> hoverProvider;

  /// The server provides goto implementation support.
  ///  @since 3.6.0
  final Either3<bool, ImplementationOptions, ImplementationRegistrationOptions>
      implementationProvider;

  /// The server provides linked editing range support.
  ///  @since 3.16.0
  final Either3<bool, LinkedEditingRangeOptions,
      LinkedEditingRangeRegistrationOptions> linkedEditingRangeProvider;

  /// Whether server provides moniker support.
  ///  @since 3.16.0
  final Either3<bool, MonikerOptions, MonikerRegistrationOptions>
      monikerProvider;

  /// The server provides find references support.
  final Either2<bool, ReferenceOptions> referencesProvider;

  /// The server provides rename support. RenameOptions may only be specified if
  /// the client states that it supports `prepareSupport` in its initial
  /// `initialize` request.
  final Either2<bool, RenameOptions> renameProvider;

  /// The server provides selection range support.
  ///  @since 3.15.0
  final Either3<bool, SelectionRangeOptions, SelectionRangeRegistrationOptions>
      selectionRangeProvider;

  /// The server provides semantic tokens support.
  ///  @since 3.16.0
  final Either2<SemanticTokensOptions, SemanticTokensRegistrationOptions>
      semanticTokensProvider;

  /// The server provides signature help support.
  final SignatureHelpOptions signatureHelpProvider;

  /// Defines how text documents are synced. Is either a detailed structure
  /// defining each notification or for backwards compatibility the
  /// TextDocumentSyncKind number. If omitted it defaults to
  /// `TextDocumentSyncKind.None`.
  final Either2<TextDocumentSyncOptions, TextDocumentSyncKind> textDocumentSync;

  /// The server provides goto type definition support.
  ///  @since 3.6.0
  final Either3<bool, TypeDefinitionOptions, TypeDefinitionRegistrationOptions>
      typeDefinitionProvider;

  /// Workspace specific server capabilities
  final ServerCapabilitiesWorkspace workspace;

  /// The server provides workspace symbol support.
  final Either2<bool, WorkspaceSymbolOptions> workspaceSymbolProvider;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (textDocumentSync != null) {
      __result['textDocumentSync'] = textDocumentSync;
    }
    if (completionProvider != null) {
      __result['completionProvider'] = completionProvider.toJson();
    }
    if (hoverProvider != null) {
      __result['hoverProvider'] = hoverProvider;
    }
    if (signatureHelpProvider != null) {
      __result['signatureHelpProvider'] = signatureHelpProvider.toJson();
    }
    if (declarationProvider != null) {
      __result['declarationProvider'] = declarationProvider;
    }
    if (definitionProvider != null) {
      __result['definitionProvider'] = definitionProvider;
    }
    if (typeDefinitionProvider != null) {
      __result['typeDefinitionProvider'] = typeDefinitionProvider;
    }
    if (implementationProvider != null) {
      __result['implementationProvider'] = implementationProvider;
    }
    if (referencesProvider != null) {
      __result['referencesProvider'] = referencesProvider;
    }
    if (documentHighlightProvider != null) {
      __result['documentHighlightProvider'] = documentHighlightProvider;
    }
    if (documentSymbolProvider != null) {
      __result['documentSymbolProvider'] = documentSymbolProvider;
    }
    if (codeActionProvider != null) {
      __result['codeActionProvider'] = codeActionProvider;
    }
    if (codeLensProvider != null) {
      __result['codeLensProvider'] = codeLensProvider.toJson();
    }
    if (documentLinkProvider != null) {
      __result['documentLinkProvider'] = documentLinkProvider.toJson();
    }
    if (colorProvider != null) {
      __result['colorProvider'] = colorProvider;
    }
    if (documentFormattingProvider != null) {
      __result['documentFormattingProvider'] = documentFormattingProvider;
    }
    if (documentRangeFormattingProvider != null) {
      __result['documentRangeFormattingProvider'] =
          documentRangeFormattingProvider;
    }
    if (documentOnTypeFormattingProvider != null) {
      __result['documentOnTypeFormattingProvider'] =
          documentOnTypeFormattingProvider.toJson();
    }
    if (renameProvider != null) {
      __result['renameProvider'] = renameProvider;
    }
    if (foldingRangeProvider != null) {
      __result['foldingRangeProvider'] = foldingRangeProvider;
    }
    if (executeCommandProvider != null) {
      __result['executeCommandProvider'] = executeCommandProvider.toJson();
    }
    if (selectionRangeProvider != null) {
      __result['selectionRangeProvider'] = selectionRangeProvider;
    }
    if (linkedEditingRangeProvider != null) {
      __result['linkedEditingRangeProvider'] = linkedEditingRangeProvider;
    }
    if (callHierarchyProvider != null) {
      __result['callHierarchyProvider'] = callHierarchyProvider;
    }
    if (semanticTokensProvider != null) {
      __result['semanticTokensProvider'] = semanticTokensProvider;
    }
    if (monikerProvider != null) {
      __result['monikerProvider'] = monikerProvider;
    }
    if (workspaceSymbolProvider != null) {
      __result['workspaceSymbolProvider'] = workspaceSymbolProvider;
    }
    if (workspace != null) {
      __result['workspace'] = workspace.toJson();
    }
    if (experimental != null) {
      __result['experimental'] = experimental;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('textDocumentSync');
      try {
        if (obj['textDocumentSync'] != null &&
            !((TextDocumentSyncOptions.canParse(
                    obj['textDocumentSync'], reporter) ||
                TextDocumentSyncKind.canParse(
                    obj['textDocumentSync'], reporter)))) {
          reporter.reportError(
              'must be of type Either2<TextDocumentSyncOptions, TextDocumentSyncKind>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('completionProvider');
      try {
        if (obj['completionProvider'] != null &&
            !(CompletionOptions.canParse(
                obj['completionProvider'], reporter))) {
          reporter.reportError('must be of type CompletionOptions');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('hoverProvider');
      try {
        if (obj['hoverProvider'] != null &&
            !((obj['hoverProvider'] is bool ||
                HoverOptions.canParse(obj['hoverProvider'], reporter)))) {
          reporter.reportError('must be of type Either2<bool, HoverOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('signatureHelpProvider');
      try {
        if (obj['signatureHelpProvider'] != null &&
            !(SignatureHelpOptions.canParse(
                obj['signatureHelpProvider'], reporter))) {
          reporter.reportError('must be of type SignatureHelpOptions');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('declarationProvider');
      try {
        if (obj['declarationProvider'] != null &&
            !((obj['declarationProvider'] is bool ||
                DeclarationOptions.canParse(
                    obj['declarationProvider'], reporter) ||
                DeclarationRegistrationOptions.canParse(
                    obj['declarationProvider'], reporter)))) {
          reporter.reportError(
              'must be of type Either3<bool, DeclarationOptions, DeclarationRegistrationOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('definitionProvider');
      try {
        if (obj['definitionProvider'] != null &&
            !((obj['definitionProvider'] is bool ||
                DefinitionOptions.canParse(
                    obj['definitionProvider'], reporter)))) {
          reporter
              .reportError('must be of type Either2<bool, DefinitionOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('typeDefinitionProvider');
      try {
        if (obj['typeDefinitionProvider'] != null &&
            !((obj['typeDefinitionProvider'] is bool ||
                TypeDefinitionOptions.canParse(
                    obj['typeDefinitionProvider'], reporter) ||
                TypeDefinitionRegistrationOptions.canParse(
                    obj['typeDefinitionProvider'], reporter)))) {
          reporter.reportError(
              'must be of type Either3<bool, TypeDefinitionOptions, TypeDefinitionRegistrationOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('implementationProvider');
      try {
        if (obj['implementationProvider'] != null &&
            !((obj['implementationProvider'] is bool ||
                ImplementationOptions.canParse(
                    obj['implementationProvider'], reporter) ||
                ImplementationRegistrationOptions.canParse(
                    obj['implementationProvider'], reporter)))) {
          reporter.reportError(
              'must be of type Either3<bool, ImplementationOptions, ImplementationRegistrationOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('referencesProvider');
      try {
        if (obj['referencesProvider'] != null &&
            !((obj['referencesProvider'] is bool ||
                ReferenceOptions.canParse(
                    obj['referencesProvider'], reporter)))) {
          reporter
              .reportError('must be of type Either2<bool, ReferenceOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('documentHighlightProvider');
      try {
        if (obj['documentHighlightProvider'] != null &&
            !((obj['documentHighlightProvider'] is bool ||
                DocumentHighlightOptions.canParse(
                    obj['documentHighlightProvider'], reporter)))) {
          reporter.reportError(
              'must be of type Either2<bool, DocumentHighlightOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('documentSymbolProvider');
      try {
        if (obj['documentSymbolProvider'] != null &&
            !((obj['documentSymbolProvider'] is bool ||
                DocumentSymbolOptions.canParse(
                    obj['documentSymbolProvider'], reporter)))) {
          reporter.reportError(
              'must be of type Either2<bool, DocumentSymbolOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('codeActionProvider');
      try {
        if (obj['codeActionProvider'] != null &&
            !((obj['codeActionProvider'] is bool ||
                CodeActionOptions.canParse(
                    obj['codeActionProvider'], reporter)))) {
          reporter
              .reportError('must be of type Either2<bool, CodeActionOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('codeLensProvider');
      try {
        if (obj['codeLensProvider'] != null &&
            !(CodeLensOptions.canParse(obj['codeLensProvider'], reporter))) {
          reporter.reportError('must be of type CodeLensOptions');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('documentLinkProvider');
      try {
        if (obj['documentLinkProvider'] != null &&
            !(DocumentLinkOptions.canParse(
                obj['documentLinkProvider'], reporter))) {
          reporter.reportError('must be of type DocumentLinkOptions');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('colorProvider');
      try {
        if (obj['colorProvider'] != null &&
            !((obj['colorProvider'] is bool ||
                DocumentColorOptions.canParse(obj['colorProvider'], reporter) ||
                DocumentColorRegistrationOptions.canParse(
                    obj['colorProvider'], reporter)))) {
          reporter.reportError(
              'must be of type Either3<bool, DocumentColorOptions, DocumentColorRegistrationOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('documentFormattingProvider');
      try {
        if (obj['documentFormattingProvider'] != null &&
            !((obj['documentFormattingProvider'] is bool ||
                DocumentFormattingOptions.canParse(
                    obj['documentFormattingProvider'], reporter)))) {
          reporter.reportError(
              'must be of type Either2<bool, DocumentFormattingOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('documentRangeFormattingProvider');
      try {
        if (obj['documentRangeFormattingProvider'] != null &&
            !((obj['documentRangeFormattingProvider'] is bool ||
                DocumentRangeFormattingOptions.canParse(
                    obj['documentRangeFormattingProvider'], reporter)))) {
          reporter.reportError(
              'must be of type Either2<bool, DocumentRangeFormattingOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('documentOnTypeFormattingProvider');
      try {
        if (obj['documentOnTypeFormattingProvider'] != null &&
            !(DocumentOnTypeFormattingOptions.canParse(
                obj['documentOnTypeFormattingProvider'], reporter))) {
          reporter
              .reportError('must be of type DocumentOnTypeFormattingOptions');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('renameProvider');
      try {
        if (obj['renameProvider'] != null &&
            !((obj['renameProvider'] is bool ||
                RenameOptions.canParse(obj['renameProvider'], reporter)))) {
          reporter.reportError('must be of type Either2<bool, RenameOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('foldingRangeProvider');
      try {
        if (obj['foldingRangeProvider'] != null &&
            !((obj['foldingRangeProvider'] is bool ||
                FoldingRangeOptions.canParse(
                    obj['foldingRangeProvider'], reporter) ||
                FoldingRangeRegistrationOptions.canParse(
                    obj['foldingRangeProvider'], reporter)))) {
          reporter.reportError(
              'must be of type Either3<bool, FoldingRangeOptions, FoldingRangeRegistrationOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('executeCommandProvider');
      try {
        if (obj['executeCommandProvider'] != null &&
            !(ExecuteCommandOptions.canParse(
                obj['executeCommandProvider'], reporter))) {
          reporter.reportError('must be of type ExecuteCommandOptions');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('selectionRangeProvider');
      try {
        if (obj['selectionRangeProvider'] != null &&
            !((obj['selectionRangeProvider'] is bool ||
                SelectionRangeOptions.canParse(
                    obj['selectionRangeProvider'], reporter) ||
                SelectionRangeRegistrationOptions.canParse(
                    obj['selectionRangeProvider'], reporter)))) {
          reporter.reportError(
              'must be of type Either3<bool, SelectionRangeOptions, SelectionRangeRegistrationOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('linkedEditingRangeProvider');
      try {
        if (obj['linkedEditingRangeProvider'] != null &&
            !((obj['linkedEditingRangeProvider'] is bool ||
                LinkedEditingRangeOptions.canParse(
                    obj['linkedEditingRangeProvider'], reporter) ||
                LinkedEditingRangeRegistrationOptions.canParse(
                    obj['linkedEditingRangeProvider'], reporter)))) {
          reporter.reportError(
              'must be of type Either3<bool, LinkedEditingRangeOptions, LinkedEditingRangeRegistrationOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('callHierarchyProvider');
      try {
        if (obj['callHierarchyProvider'] != null &&
            !((obj['callHierarchyProvider'] is bool ||
                CallHierarchyOptions.canParse(
                    obj['callHierarchyProvider'], reporter) ||
                CallHierarchyRegistrationOptions.canParse(
                    obj['callHierarchyProvider'], reporter)))) {
          reporter.reportError(
              'must be of type Either3<bool, CallHierarchyOptions, CallHierarchyRegistrationOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('semanticTokensProvider');
      try {
        if (obj['semanticTokensProvider'] != null &&
            !((SemanticTokensOptions.canParse(
                    obj['semanticTokensProvider'], reporter) ||
                SemanticTokensRegistrationOptions.canParse(
                    obj['semanticTokensProvider'], reporter)))) {
          reporter.reportError(
              'must be of type Either2<SemanticTokensOptions, SemanticTokensRegistrationOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('monikerProvider');
      try {
        if (obj['monikerProvider'] != null &&
            !((obj['monikerProvider'] is bool ||
                MonikerOptions.canParse(obj['monikerProvider'], reporter) ||
                MonikerRegistrationOptions.canParse(
                    obj['monikerProvider'], reporter)))) {
          reporter.reportError(
              'must be of type Either3<bool, MonikerOptions, MonikerRegistrationOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workspaceSymbolProvider');
      try {
        if (obj['workspaceSymbolProvider'] != null &&
            !((obj['workspaceSymbolProvider'] is bool ||
                WorkspaceSymbolOptions.canParse(
                    obj['workspaceSymbolProvider'], reporter)))) {
          reporter.reportError(
              'must be of type Either2<bool, WorkspaceSymbolOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workspace');
      try {
        if (obj['workspace'] != null &&
            !(ServerCapabilitiesWorkspace.canParse(
                obj['workspace'], reporter))) {
          reporter.reportError('must be of type ServerCapabilitiesWorkspace');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('experimental');
      try {
        if (obj['experimental'] != null && !(true)) {
          reporter.reportError('must be of type dynamic');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ServerCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is ServerCapabilities &&
        other.runtimeType == ServerCapabilities) {
      return textDocumentSync == other.textDocumentSync &&
          completionProvider == other.completionProvider &&
          hoverProvider == other.hoverProvider &&
          signatureHelpProvider == other.signatureHelpProvider &&
          declarationProvider == other.declarationProvider &&
          definitionProvider == other.definitionProvider &&
          typeDefinitionProvider == other.typeDefinitionProvider &&
          implementationProvider == other.implementationProvider &&
          referencesProvider == other.referencesProvider &&
          documentHighlightProvider == other.documentHighlightProvider &&
          documentSymbolProvider == other.documentSymbolProvider &&
          codeActionProvider == other.codeActionProvider &&
          codeLensProvider == other.codeLensProvider &&
          documentLinkProvider == other.documentLinkProvider &&
          colorProvider == other.colorProvider &&
          documentFormattingProvider == other.documentFormattingProvider &&
          documentRangeFormattingProvider ==
              other.documentRangeFormattingProvider &&
          documentOnTypeFormattingProvider ==
              other.documentOnTypeFormattingProvider &&
          renameProvider == other.renameProvider &&
          foldingRangeProvider == other.foldingRangeProvider &&
          executeCommandProvider == other.executeCommandProvider &&
          selectionRangeProvider == other.selectionRangeProvider &&
          linkedEditingRangeProvider == other.linkedEditingRangeProvider &&
          callHierarchyProvider == other.callHierarchyProvider &&
          semanticTokensProvider == other.semanticTokensProvider &&
          monikerProvider == other.monikerProvider &&
          workspaceSymbolProvider == other.workspaceSymbolProvider &&
          workspace == other.workspace &&
          experimental == other.experimental &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, textDocumentSync.hashCode);
    hash = JenkinsSmiHash.combine(hash, completionProvider.hashCode);
    hash = JenkinsSmiHash.combine(hash, hoverProvider.hashCode);
    hash = JenkinsSmiHash.combine(hash, signatureHelpProvider.hashCode);
    hash = JenkinsSmiHash.combine(hash, declarationProvider.hashCode);
    hash = JenkinsSmiHash.combine(hash, definitionProvider.hashCode);
    hash = JenkinsSmiHash.combine(hash, typeDefinitionProvider.hashCode);
    hash = JenkinsSmiHash.combine(hash, implementationProvider.hashCode);
    hash = JenkinsSmiHash.combine(hash, referencesProvider.hashCode);
    hash = JenkinsSmiHash.combine(hash, documentHighlightProvider.hashCode);
    hash = JenkinsSmiHash.combine(hash, documentSymbolProvider.hashCode);
    hash = JenkinsSmiHash.combine(hash, codeActionProvider.hashCode);
    hash = JenkinsSmiHash.combine(hash, codeLensProvider.hashCode);
    hash = JenkinsSmiHash.combine(hash, documentLinkProvider.hashCode);
    hash = JenkinsSmiHash.combine(hash, colorProvider.hashCode);
    hash = JenkinsSmiHash.combine(hash, documentFormattingProvider.hashCode);
    hash =
        JenkinsSmiHash.combine(hash, documentRangeFormattingProvider.hashCode);
    hash =
        JenkinsSmiHash.combine(hash, documentOnTypeFormattingProvider.hashCode);
    hash = JenkinsSmiHash.combine(hash, renameProvider.hashCode);
    hash = JenkinsSmiHash.combine(hash, foldingRangeProvider.hashCode);
    hash = JenkinsSmiHash.combine(hash, executeCommandProvider.hashCode);
    hash = JenkinsSmiHash.combine(hash, selectionRangeProvider.hashCode);
    hash = JenkinsSmiHash.combine(hash, linkedEditingRangeProvider.hashCode);
    hash = JenkinsSmiHash.combine(hash, callHierarchyProvider.hashCode);
    hash = JenkinsSmiHash.combine(hash, semanticTokensProvider.hashCode);
    hash = JenkinsSmiHash.combine(hash, monikerProvider.hashCode);
    hash = JenkinsSmiHash.combine(hash, workspaceSymbolProvider.hashCode);
    hash = JenkinsSmiHash.combine(hash, workspace.hashCode);
    hash = JenkinsSmiHash.combine(hash, experimental.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class ServerCapabilitiesFileOperations implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
      ServerCapabilitiesFileOperations.canParse,
      ServerCapabilitiesFileOperations.fromJson);

  ServerCapabilitiesFileOperations(
      {this.didCreate,
      this.willCreate,
      this.didRename,
      this.willRename,
      this.didDelete,
      this.willDelete});
  static ServerCapabilitiesFileOperations fromJson(Map<String, dynamic> json) {
    final didCreate = json['didCreate'] != null
        ? FileOperationRegistrationOptions.fromJson(json['didCreate'])
        : null;
    final willCreate = json['willCreate'] != null
        ? FileOperationRegistrationOptions.fromJson(json['willCreate'])
        : null;
    final didRename = json['didRename'] != null
        ? FileOperationRegistrationOptions.fromJson(json['didRename'])
        : null;
    final willRename = json['willRename'] != null
        ? FileOperationRegistrationOptions.fromJson(json['willRename'])
        : null;
    final didDelete = json['didDelete'] != null
        ? FileOperationRegistrationOptions.fromJson(json['didDelete'])
        : null;
    final willDelete = json['willDelete'] != null
        ? FileOperationRegistrationOptions.fromJson(json['willDelete'])
        : null;
    return ServerCapabilitiesFileOperations(
        didCreate: didCreate,
        willCreate: willCreate,
        didRename: didRename,
        willRename: willRename,
        didDelete: didDelete,
        willDelete: willDelete);
  }

  /// The server is interested in receiving didCreateFiles notifications.
  final FileOperationRegistrationOptions didCreate;

  /// The server is interested in receiving didDeleteFiles file notifications.
  final FileOperationRegistrationOptions didDelete;

  /// The server is interested in receiving didRenameFiles notifications.
  final FileOperationRegistrationOptions didRename;

  /// The server is interested in receiving willCreateFiles requests.
  final FileOperationRegistrationOptions willCreate;

  /// The server is interested in receiving willDeleteFiles file requests.
  final FileOperationRegistrationOptions willDelete;

  /// The server is interested in receiving willRenameFiles requests.
  final FileOperationRegistrationOptions willRename;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (didCreate != null) {
      __result['didCreate'] = didCreate.toJson();
    }
    if (willCreate != null) {
      __result['willCreate'] = willCreate.toJson();
    }
    if (didRename != null) {
      __result['didRename'] = didRename.toJson();
    }
    if (willRename != null) {
      __result['willRename'] = willRename.toJson();
    }
    if (didDelete != null) {
      __result['didDelete'] = didDelete.toJson();
    }
    if (willDelete != null) {
      __result['willDelete'] = willDelete.toJson();
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('didCreate');
      try {
        if (obj['didCreate'] != null &&
            !(FileOperationRegistrationOptions.canParse(
                obj['didCreate'], reporter))) {
          reporter
              .reportError('must be of type FileOperationRegistrationOptions');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('willCreate');
      try {
        if (obj['willCreate'] != null &&
            !(FileOperationRegistrationOptions.canParse(
                obj['willCreate'], reporter))) {
          reporter
              .reportError('must be of type FileOperationRegistrationOptions');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('didRename');
      try {
        if (obj['didRename'] != null &&
            !(FileOperationRegistrationOptions.canParse(
                obj['didRename'], reporter))) {
          reporter
              .reportError('must be of type FileOperationRegistrationOptions');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('willRename');
      try {
        if (obj['willRename'] != null &&
            !(FileOperationRegistrationOptions.canParse(
                obj['willRename'], reporter))) {
          reporter
              .reportError('must be of type FileOperationRegistrationOptions');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('didDelete');
      try {
        if (obj['didDelete'] != null &&
            !(FileOperationRegistrationOptions.canParse(
                obj['didDelete'], reporter))) {
          reporter
              .reportError('must be of type FileOperationRegistrationOptions');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('willDelete');
      try {
        if (obj['willDelete'] != null &&
            !(FileOperationRegistrationOptions.canParse(
                obj['willDelete'], reporter))) {
          reporter
              .reportError('must be of type FileOperationRegistrationOptions');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ServerCapabilitiesFileOperations');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is ServerCapabilitiesFileOperations &&
        other.runtimeType == ServerCapabilitiesFileOperations) {
      return didCreate == other.didCreate &&
          willCreate == other.willCreate &&
          didRename == other.didRename &&
          willRename == other.willRename &&
          didDelete == other.didDelete &&
          willDelete == other.willDelete &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, didCreate.hashCode);
    hash = JenkinsSmiHash.combine(hash, willCreate.hashCode);
    hash = JenkinsSmiHash.combine(hash, didRename.hashCode);
    hash = JenkinsSmiHash.combine(hash, willRename.hashCode);
    hash = JenkinsSmiHash.combine(hash, didDelete.hashCode);
    hash = JenkinsSmiHash.combine(hash, willDelete.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class ServerCapabilitiesWorkspace implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
      ServerCapabilitiesWorkspace.canParse,
      ServerCapabilitiesWorkspace.fromJson);

  ServerCapabilitiesWorkspace({this.workspaceFolders, this.fileOperations});
  static ServerCapabilitiesWorkspace fromJson(Map<String, dynamic> json) {
    final workspaceFolders = json['workspaceFolders'] != null
        ? WorkspaceFoldersServerCapabilities.fromJson(json['workspaceFolders'])
        : null;
    final fileOperations = json['fileOperations'] != null
        ? ServerCapabilitiesFileOperations.fromJson(json['fileOperations'])
        : null;
    return ServerCapabilitiesWorkspace(
        workspaceFolders: workspaceFolders, fileOperations: fileOperations);
  }

  /// The server is interested in file notifications/requests.
  ///  @since 3.16.0
  final ServerCapabilitiesFileOperations fileOperations;

  /// The server supports workspace folder.
  ///  @since 3.6.0
  final WorkspaceFoldersServerCapabilities workspaceFolders;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (workspaceFolders != null) {
      __result['workspaceFolders'] = workspaceFolders.toJson();
    }
    if (fileOperations != null) {
      __result['fileOperations'] = fileOperations.toJson();
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('workspaceFolders');
      try {
        if (obj['workspaceFolders'] != null &&
            !(WorkspaceFoldersServerCapabilities.canParse(
                obj['workspaceFolders'], reporter))) {
          reporter.reportError(
              'must be of type WorkspaceFoldersServerCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('fileOperations');
      try {
        if (obj['fileOperations'] != null &&
            !(ServerCapabilitiesFileOperations.canParse(
                obj['fileOperations'], reporter))) {
          reporter
              .reportError('must be of type ServerCapabilitiesFileOperations');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ServerCapabilitiesWorkspace');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is ServerCapabilitiesWorkspace &&
        other.runtimeType == ServerCapabilitiesWorkspace) {
      return workspaceFolders == other.workspaceFolders &&
          fileOperations == other.fileOperations &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, workspaceFolders.hashCode);
    hash = JenkinsSmiHash.combine(hash, fileOperations.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SetTraceParams implements ToJsonable {
  static const jsonHandler =
      LspJsonHandler(SetTraceParams.canParse, SetTraceParams.fromJson);

  SetTraceParams({@required this.value}) {
    if (value == null) {
      throw 'value is required but was not provided';
    }
  }
  static SetTraceParams fromJson(Map<String, dynamic> json) {
    final value = const {'off', 'message', 'verbose'}.contains(json['value'])
        ? json['value']
        : throw '''${json['value']} was not one of ('off', 'message', 'verbose')''';
    return SetTraceParams(value: value);
  }

  /// The new value that should be assigned to the trace setting.
  final String value;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['value'] = value ?? (throw 'value is required but was not set');
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('value');
      try {
        if (!obj.containsKey('value')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['value'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!((obj['value'] == 'off' ||
            obj['value'] == 'message' ||
            obj['value'] == 'verbose'))) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SetTraceParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SetTraceParams && other.runtimeType == SetTraceParams) {
      return value == other.value && true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, value.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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}) {
    if (support == null) {
      throw 'support is required but was not provided';
    }
  }
  static ShowDocumentClientCapabilities fromJson(Map<String, dynamic> json) {
    final support = json['support'];
    return ShowDocumentClientCapabilities(support: support);
  }

  /// The client has support for the show document request.
  final bool support;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['support'] =
        support ?? (throw 'support is required but was not set');
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('support');
      try {
        if (!obj.containsKey('support')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['support'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, support.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Params to show a document.
///  @since 3.16.0
class ShowDocumentParams implements ToJsonable {
  static const jsonHandler =
      LspJsonHandler(ShowDocumentParams.canParse, ShowDocumentParams.fromJson);

  ShowDocumentParams(
      {@required this.uri, this.external, this.takeFocus, this.selection}) {
    if (uri == null) {
      throw 'uri is required but was not provided';
    }
  }
  static ShowDocumentParams fromJson(Map<String, dynamic> json) {
    final uri = json['uri'];
    final external = json['external'];
    final takeFocus = json['takeFocus'];
    final selection =
        json['selection'] != null ? Range.fromJson(json['selection']) : null;
    return ShowDocumentParams(
        uri: uri,
        external: external,
        takeFocus: takeFocus,
        selection: selection);
  }

  /// Indicates to show the resource in an external program. To show for example
  /// `https://code.visualstudio.com/` in the default WEB browser set `external`
  /// to `true`.
  final bool external;

  /// An optional selection range if the document is a text document. Clients
  /// might ignore the property if an external program is started or the file is
  /// not a text file.
  final Range selection;

  /// An optional property to indicate whether the editor showing the document
  /// should take focus or not. Clients might ignore this property if an
  /// external program is started.
  final bool takeFocus;

  /// The document uri to show.
  final String uri;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['uri'] = uri ?? (throw 'uri is required but was not set');
    if (external != null) {
      __result['external'] = external;
    }
    if (takeFocus != null) {
      __result['takeFocus'] = takeFocus;
    }
    if (selection != null) {
      __result['selection'] = selection.toJson();
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('uri');
      try {
        if (!obj.containsKey('uri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['uri'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['uri'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('external');
      try {
        if (obj['external'] != null && !(obj['external'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('takeFocus');
      try {
        if (obj['takeFocus'] != null && !(obj['takeFocus'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('selection');
      try {
        if (obj['selection'] != null &&
            !(Range.canParse(obj['selection'], reporter))) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ShowDocumentParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is ShowDocumentParams &&
        other.runtimeType == ShowDocumentParams) {
      return uri == other.uri &&
          external == other.external &&
          takeFocus == other.takeFocus &&
          selection == other.selection &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, uri.hashCode);
    hash = JenkinsSmiHash.combine(hash, external.hashCode);
    hash = JenkinsSmiHash.combine(hash, takeFocus.hashCode);
    hash = JenkinsSmiHash.combine(hash, selection.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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}) {
    if (success == null) {
      throw 'success is required but was not provided';
    }
  }
  static ShowDocumentResult fromJson(Map<String, dynamic> json) {
    final success = json['success'];
    return ShowDocumentResult(success: success);
  }

  /// A boolean indicating if the show was successful.
  final bool success;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['success'] =
        success ?? (throw 'success is required but was not set');
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('success');
      try {
        if (!obj.containsKey('success')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['success'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, success.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class ShowMessageParams implements ToJsonable {
  static const jsonHandler =
      LspJsonHandler(ShowMessageParams.canParse, ShowMessageParams.fromJson);

  ShowMessageParams({@required this.type, @required this.message}) {
    if (type == null) {
      throw 'type is required but was not provided';
    }
    if (message == null) {
      throw 'message is required but was not provided';
    }
  }
  static ShowMessageParams fromJson(Map<String, dynamic> json) {
    final type =
        json['type'] != null ? MessageType.fromJson(json['type']) : null;
    final message = json['message'];
    return ShowMessageParams(type: type, message: message);
  }

  /// The actual message.
  final String message;

  /// The message type.
  final MessageType type;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['type'] =
        type?.toJson() ?? (throw 'type is required but was not set');
    __result['message'] =
        message ?? (throw 'message is required but was not set');
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('type');
      try {
        if (!obj.containsKey('type')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['type'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(MessageType.canParse(obj['type'], reporter))) {
          reporter.reportError('must be of type MessageType');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('message');
      try {
        if (!obj.containsKey('message')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['message'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['message'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ShowMessageParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is ShowMessageParams && other.runtimeType == ShowMessageParams) {
      return type == other.type && message == other.message && true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, type.hashCode);
    hash = JenkinsSmiHash.combine(hash, message.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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, dynamic> json) {
    final messageActionItem = json['messageActionItem'] != null
        ? ShowMessageRequestClientCapabilitiesMessageActionItem.fromJson(
            json['messageActionItem'])
        : null;
    return ShowMessageRequestClientCapabilities(
        messageActionItem: messageActionItem);
  }

  /// Capabilities specific to the `MessageActionItem` type.
  final ShowMessageRequestClientCapabilitiesMessageActionItem messageActionItem;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (messageActionItem != null) {
      __result['messageActionItem'] = messageActionItem.toJson();
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('messageActionItem');
      try {
        if (obj['messageActionItem'] != null &&
            !(ShowMessageRequestClientCapabilitiesMessageActionItem.canParse(
                obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, messageActionItem.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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, dynamic> json) {
    final additionalPropertiesSupport = json['additionalPropertiesSupport'];
    return ShowMessageRequestClientCapabilitiesMessageActionItem(
        additionalPropertiesSupport: additionalPropertiesSupport);
  }

  /// Whether the client supports additional attributes which are preserved and
  /// sent back to the server in the request's response.
  final bool additionalPropertiesSupport;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (additionalPropertiesSupport != null) {
      __result['additionalPropertiesSupport'] = additionalPropertiesSupport;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('additionalPropertiesSupport');
      try {
        if (obj['additionalPropertiesSupport'] != null &&
            !(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, additionalPropertiesSupport.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class ShowMessageRequestParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
      ShowMessageRequestParams.canParse, ShowMessageRequestParams.fromJson);

  ShowMessageRequestParams(
      {@required this.type, @required this.message, this.actions}) {
    if (type == null) {
      throw 'type is required but was not provided';
    }
    if (message == null) {
      throw 'message is required but was not provided';
    }
  }
  static ShowMessageRequestParams fromJson(Map<String, dynamic> json) {
    final type =
        json['type'] != null ? MessageType.fromJson(json['type']) : null;
    final message = json['message'];
    final actions = json['actions']
        ?.map((item) => item != null ? MessageActionItem.fromJson(item) : null)
        ?.cast<MessageActionItem>()
        ?.toList();
    return ShowMessageRequestParams(
        type: type, message: message, actions: actions);
  }

  /// The message action items to present.
  final List<MessageActionItem> actions;

  /// The actual message
  final String message;

  /// The message type.
  final MessageType type;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['type'] =
        type?.toJson() ?? (throw 'type is required but was not set');
    __result['message'] =
        message ?? (throw 'message is required but was not set');
    if (actions != null) {
      __result['actions'] = actions.map((item) => item.toJson()).toList();
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('type');
      try {
        if (!obj.containsKey('type')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['type'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(MessageType.canParse(obj['type'], reporter))) {
          reporter.reportError('must be of type MessageType');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('message');
      try {
        if (!obj.containsKey('message')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['message'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['message'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('actions');
      try {
        if (obj['actions'] != null &&
            !((obj['actions'] is List &&
                (obj['actions'].every(
                    (item) => MessageActionItem.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<MessageActionItem>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type ShowMessageRequestParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is ShowMessageRequestParams &&
        other.runtimeType == ShowMessageRequestParams) {
      return type == other.type &&
          message == other.message &&
          listEqual(actions, other.actions,
              (MessageActionItem a, MessageActionItem b) => a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, type.hashCode);
    hash = JenkinsSmiHash.combine(hash, message.hashCode);
    hash = JenkinsSmiHash.combine(hash, lspHashCode(actions));
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Signature help represents the signature of something callable. There can be
/// multiple signature but only one active and only one active parameter.
class SignatureHelp implements ToJsonable {
  static const jsonHandler =
      LspJsonHandler(SignatureHelp.canParse, SignatureHelp.fromJson);

  SignatureHelp(
      {@required this.signatures, this.activeSignature, this.activeParameter}) {
    if (signatures == null) {
      throw 'signatures is required but was not provided';
    }
  }
  static SignatureHelp fromJson(Map<String, dynamic> json) {
    final signatures = json['signatures']
        ?.map(
            (item) => item != null ? SignatureInformation.fromJson(item) : null)
        ?.cast<SignatureInformation>()
        ?.toList();
    final activeSignature = json['activeSignature'];
    final activeParameter = json['activeParameter'];
    return SignatureHelp(
        signatures: signatures,
        activeSignature: activeSignature,
        activeParameter: activeParameter);
  }

  /// The active parameter of the active signature. If omitted or the value lies
  /// outside the range of `signatures[activeSignature].parameters` defaults to
  /// 0 if the active signature has parameters. If the active signature has no
  /// parameters it is ignored. In future version of the protocol this property
  /// might become mandatory to better express the active parameter if the
  /// active signature does have any.
  final num 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 num activeSignature;

  /// One or more signatures. If no signatures are available the signature help
  /// request should return `null`.
  final List<SignatureInformation> signatures;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['signatures'] =
        signatures?.map((item) => item.toJson())?.toList() ??
            (throw 'signatures is required but was not set');
    if (activeSignature != null) {
      __result['activeSignature'] = activeSignature;
    }
    if (activeParameter != null) {
      __result['activeParameter'] = activeParameter;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('signatures');
      try {
        if (!obj.containsKey('signatures')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['signatures'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!((obj['signatures'] is List &&
            (obj['signatures'].every(
                (item) => SignatureInformation.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<SignatureInformation>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('activeSignature');
      try {
        if (obj['activeSignature'] != null &&
            !(obj['activeSignature'] is num)) {
          reporter.reportError('must be of type num');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('activeParameter');
      try {
        if (obj['activeParameter'] != null &&
            !(obj['activeParameter'] is num)) {
          reporter.reportError('must be of type num');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SignatureHelp');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SignatureHelp && other.runtimeType == SignatureHelp) {
      return listEqual(signatures, other.signatures,
              (SignatureInformation a, SignatureInformation b) => a == b) &&
          activeSignature == other.activeSignature &&
          activeParameter == other.activeParameter &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(signatures));
    hash = JenkinsSmiHash.combine(hash, activeSignature.hashCode);
    hash = JenkinsSmiHash.combine(hash, activeParameter.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SignatureHelpClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
      SignatureHelpClientCapabilities.canParse,
      SignatureHelpClientCapabilities.fromJson);

  SignatureHelpClientCapabilities(
      {this.dynamicRegistration,
      this.signatureInformation,
      this.contextSupport});
  static SignatureHelpClientCapabilities fromJson(Map<String, dynamic> json) {
    final dynamicRegistration = json['dynamicRegistration'];
    final signatureInformation = json['signatureInformation'] != null
        ? SignatureHelpClientCapabilitiesSignatureInformation.fromJson(
            json['signatureInformation'])
        : null;
    final contextSupport = json['contextSupport'];
    return SignatureHelpClientCapabilities(
        dynamicRegistration: dynamicRegistration,
        signatureInformation: signatureInformation,
        contextSupport: contextSupport);
  }

  /// The client supports to send additional context information for a
  /// `textDocument/signatureHelp` request. A client that opts into
  /// contextSupport will also support the `retriggerCharacters` on
  /// `SignatureHelpOptions`.
  ///  @since 3.15.0
  final bool contextSupport;

  /// Whether signature help supports dynamic registration.
  final bool dynamicRegistration;

  /// The client supports the following `SignatureInformation` specific
  /// properties.
  final SignatureHelpClientCapabilitiesSignatureInformation
      signatureInformation;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (dynamicRegistration != null) {
      __result['dynamicRegistration'] = dynamicRegistration;
    }
    if (signatureInformation != null) {
      __result['signatureInformation'] = signatureInformation.toJson();
    }
    if (contextSupport != null) {
      __result['contextSupport'] = contextSupport;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('dynamicRegistration');
      try {
        if (obj['dynamicRegistration'] != null &&
            !(obj['dynamicRegistration'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('signatureInformation');
      try {
        if (obj['signatureInformation'] != null &&
            !(SignatureHelpClientCapabilitiesSignatureInformation.canParse(
                obj['signatureInformation'], reporter))) {
          reporter.reportError(
              'must be of type SignatureHelpClientCapabilitiesSignatureInformation');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('contextSupport');
      try {
        if (obj['contextSupport'] != null && !(obj['contextSupport'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SignatureHelpClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SignatureHelpClientCapabilities &&
        other.runtimeType == SignatureHelpClientCapabilities) {
      return dynamicRegistration == other.dynamicRegistration &&
          signatureInformation == other.signatureInformation &&
          contextSupport == other.contextSupport &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode);
    hash = JenkinsSmiHash.combine(hash, signatureInformation.hashCode);
    hash = JenkinsSmiHash.combine(hash, contextSupport.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SignatureHelpClientCapabilitiesParameterInformation
    implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
      SignatureHelpClientCapabilitiesParameterInformation.canParse,
      SignatureHelpClientCapabilitiesParameterInformation.fromJson);

  SignatureHelpClientCapabilitiesParameterInformation(
      {this.labelOffsetSupport});
  static SignatureHelpClientCapabilitiesParameterInformation fromJson(
      Map<String, dynamic> json) {
    final labelOffsetSupport = json['labelOffsetSupport'];
    return SignatureHelpClientCapabilitiesParameterInformation(
        labelOffsetSupport: labelOffsetSupport);
  }

  /// The client supports processing label offsets instead of a simple label
  /// string.
  ///  @since 3.14.0
  final bool labelOffsetSupport;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (labelOffsetSupport != null) {
      __result['labelOffsetSupport'] = labelOffsetSupport;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('labelOffsetSupport');
      try {
        if (obj['labelOffsetSupport'] != null &&
            !(obj['labelOffsetSupport'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type SignatureHelpClientCapabilitiesParameterInformation');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SignatureHelpClientCapabilitiesParameterInformation &&
        other.runtimeType ==
            SignatureHelpClientCapabilitiesParameterInformation) {
      return labelOffsetSupport == other.labelOffsetSupport && true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, labelOffsetSupport.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SignatureHelpClientCapabilitiesSignatureInformation
    implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
      SignatureHelpClientCapabilitiesSignatureInformation.canParse,
      SignatureHelpClientCapabilitiesSignatureInformation.fromJson);

  SignatureHelpClientCapabilitiesSignatureInformation(
      {this.documentationFormat,
      this.parameterInformation,
      this.activeParameterSupport});
  static SignatureHelpClientCapabilitiesSignatureInformation fromJson(
      Map<String, dynamic> json) {
    final documentationFormat = json['documentationFormat']
        ?.map((item) => item != null ? MarkupKind.fromJson(item) : null)
        ?.cast<MarkupKind>()
        ?.toList();
    final parameterInformation = json['parameterInformation'] != null
        ? SignatureHelpClientCapabilitiesParameterInformation.fromJson(
            json['parameterInformation'])
        : null;
    final activeParameterSupport = json['activeParameterSupport'];
    return SignatureHelpClientCapabilitiesSignatureInformation(
        documentationFormat: documentationFormat,
        parameterInformation: parameterInformation,
        activeParameterSupport: activeParameterSupport);
  }

  /// The client supports the `activeParameter` property on
  /// `SignatureInformation` literal.
  ///  @since 3.16.0
  final bool activeParameterSupport;

  /// Client supports the follow content formats for the documentation property.
  /// The order describes the preferred format of the client.
  final List<MarkupKind> documentationFormat;

  /// Client capabilities specific to parameter information.
  final SignatureHelpClientCapabilitiesParameterInformation
      parameterInformation;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (documentationFormat != null) {
      __result['documentationFormat'] =
          documentationFormat.map((item) => item.toJson()).toList();
    }
    if (parameterInformation != null) {
      __result['parameterInformation'] = parameterInformation.toJson();
    }
    if (activeParameterSupport != null) {
      __result['activeParameterSupport'] = activeParameterSupport;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('documentationFormat');
      try {
        if (obj['documentationFormat'] != null &&
            !((obj['documentationFormat'] is List &&
                (obj['documentationFormat']
                    .every((item) => MarkupKind.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<MarkupKind>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('parameterInformation');
      try {
        if (obj['parameterInformation'] != null &&
            !(SignatureHelpClientCapabilitiesParameterInformation.canParse(
                obj['parameterInformation'], reporter))) {
          reporter.reportError(
              'must be of type SignatureHelpClientCapabilitiesParameterInformation');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('activeParameterSupport');
      try {
        if (obj['activeParameterSupport'] != null &&
            !(obj['activeParameterSupport'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type SignatureHelpClientCapabilitiesSignatureInformation');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SignatureHelpClientCapabilitiesSignatureInformation &&
        other.runtimeType ==
            SignatureHelpClientCapabilitiesSignatureInformation) {
      return listEqual(documentationFormat, other.documentationFormat,
              (MarkupKind a, MarkupKind b) => a == b) &&
          parameterInformation == other.parameterInformation &&
          activeParameterSupport == other.activeParameterSupport &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(documentationFormat));
    hash = JenkinsSmiHash.combine(hash, parameterInformation.hashCode);
    hash = JenkinsSmiHash.combine(hash, activeParameterSupport.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Additional information about the context in which a signature help request
/// was triggered.
///  @since 3.15.0
class SignatureHelpContext implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
      SignatureHelpContext.canParse, SignatureHelpContext.fromJson);

  SignatureHelpContext(
      {@required this.triggerKind,
      this.triggerCharacter,
      @required this.isRetrigger,
      this.activeSignatureHelp}) {
    if (triggerKind == null) {
      throw 'triggerKind is required but was not provided';
    }
    if (isRetrigger == null) {
      throw 'isRetrigger is required but was not provided';
    }
  }
  static SignatureHelpContext fromJson(Map<String, dynamic> json) {
    final triggerKind = json['triggerKind'] != null
        ? SignatureHelpTriggerKind.fromJson(json['triggerKind'])
        : null;
    final triggerCharacter = json['triggerCharacter'];
    final isRetrigger = json['isRetrigger'];
    final activeSignatureHelp = json['activeSignatureHelp'] != null
        ? SignatureHelp.fromJson(json['activeSignatureHelp'])
        : null;
    return SignatureHelpContext(
        triggerKind: triggerKind,
        triggerCharacter: triggerCharacter,
        isRetrigger: isRetrigger,
        activeSignatureHelp: activeSignatureHelp);
  }

  /// The currently active `SignatureHelp`.
  ///
  /// The `activeSignatureHelp` has its `SignatureHelp.activeSignature` field
  /// updated based on the user navigating through available signatures.
  final SignatureHelp activeSignatureHelp;

  /// `true` if signature help was already showing when it was triggered.
  ///
  /// Retriggers occur when the signature help is already active and can be
  /// caused by actions such as typing a trigger character, a cursor move, or
  /// document content changes.
  final bool isRetrigger;

  /// Character that caused signature help to be triggered.
  ///
  /// This is undefined when triggerKind !==
  /// SignatureHelpTriggerKind.TriggerCharacter
  final String triggerCharacter;

  /// Action that caused signature help to be triggered.
  final SignatureHelpTriggerKind triggerKind;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['triggerKind'] = triggerKind?.toJson() ??
        (throw 'triggerKind is required but was not set');
    if (triggerCharacter != null) {
      __result['triggerCharacter'] = triggerCharacter;
    }
    __result['isRetrigger'] =
        isRetrigger ?? (throw 'isRetrigger is required but was not set');
    if (activeSignatureHelp != null) {
      __result['activeSignatureHelp'] = activeSignatureHelp.toJson();
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('triggerKind');
      try {
        if (!obj.containsKey('triggerKind')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['triggerKind'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(SignatureHelpTriggerKind.canParse(
            obj['triggerKind'], reporter))) {
          reporter.reportError('must be of type SignatureHelpTriggerKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('triggerCharacter');
      try {
        if (obj['triggerCharacter'] != null &&
            !(obj['triggerCharacter'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('isRetrigger');
      try {
        if (!obj.containsKey('isRetrigger')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['isRetrigger'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['isRetrigger'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('activeSignatureHelp');
      try {
        if (obj['activeSignatureHelp'] != null &&
            !(SignatureHelp.canParse(obj['activeSignatureHelp'], reporter))) {
          reporter.reportError('must be of type SignatureHelp');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SignatureHelpContext');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SignatureHelpContext &&
        other.runtimeType == SignatureHelpContext) {
      return triggerKind == other.triggerKind &&
          triggerCharacter == other.triggerCharacter &&
          isRetrigger == other.isRetrigger &&
          activeSignatureHelp == other.activeSignatureHelp &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, triggerKind.hashCode);
    hash = JenkinsSmiHash.combine(hash, triggerCharacter.hashCode);
    hash = JenkinsSmiHash.combine(hash, isRetrigger.hashCode);
    hash = JenkinsSmiHash.combine(hash, activeSignatureHelp.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SignatureHelpOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
      SignatureHelpOptions.canParse, SignatureHelpOptions.fromJson);

  SignatureHelpOptions(
      {this.triggerCharacters,
      this.retriggerCharacters,
      this.workDoneProgress});
  static SignatureHelpOptions fromJson(Map<String, dynamic> json) {
    if (SignatureHelpRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return SignatureHelpRegistrationOptions.fromJson(json);
    }
    final triggerCharacters = json['triggerCharacters']
        ?.map((item) => item)
        ?.cast<String>()
        ?.toList();
    final retriggerCharacters = json['retriggerCharacters']
        ?.map((item) => item)
        ?.cast<String>()
        ?.toList();
    final workDoneProgress = json['workDoneProgress'];
    return SignatureHelpOptions(
        triggerCharacters: triggerCharacters,
        retriggerCharacters: retriggerCharacters,
        workDoneProgress: workDoneProgress);
  }

  /// List of characters that re-trigger signature help.
  ///
  /// These trigger characters are only active when signature help is already
  /// showing. All trigger characters are also counted as re-trigger characters.
  ///  @since 3.15.0
  final List<String> retriggerCharacters;

  /// The characters that trigger signature help automatically.
  final List<String> triggerCharacters;
  final bool workDoneProgress;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (triggerCharacters != null) {
      __result['triggerCharacters'] = triggerCharacters;
    }
    if (retriggerCharacters != null) {
      __result['retriggerCharacters'] = retriggerCharacters;
    }
    if (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('triggerCharacters');
      try {
        if (obj['triggerCharacters'] != null &&
            !((obj['triggerCharacters'] is List &&
                (obj['triggerCharacters'].every((item) => item is String))))) {
          reporter.reportError('must be of type List<String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('retriggerCharacters');
      try {
        if (obj['retriggerCharacters'] != null &&
            !((obj['retriggerCharacters'] is List &&
                (obj['retriggerCharacters']
                    .every((item) => item is String))))) {
          reporter.reportError('must be of type List<String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        if (obj['workDoneProgress'] != null &&
            !(obj['workDoneProgress'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SignatureHelpOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SignatureHelpOptions &&
        other.runtimeType == SignatureHelpOptions) {
      return listEqual(triggerCharacters, other.triggerCharacters,
              (String a, String b) => a == b) &&
          listEqual(retriggerCharacters, other.retriggerCharacters,
              (String a, String b) => a == b) &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(triggerCharacters));
    hash = JenkinsSmiHash.combine(hash, lspHashCode(retriggerCharacters));
    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SignatureHelpParams
    implements TextDocumentPositionParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
      SignatureHelpParams.canParse, SignatureHelpParams.fromJson);

  SignatureHelpParams(
      {this.context,
      @required this.textDocument,
      @required this.position,
      this.workDoneToken}) {
    if (textDocument == null) {
      throw 'textDocument is required but was not provided';
    }
    if (position == null) {
      throw 'position is required but was not provided';
    }
  }
  static SignatureHelpParams fromJson(Map<String, dynamic> json) {
    final context = json['context'] != null
        ? SignatureHelpContext.fromJson(json['context'])
        : null;
    final textDocument = json['textDocument'] != null
        ? TextDocumentIdentifier.fromJson(json['textDocument'])
        : null;
    final position =
        json['position'] != null ? Position.fromJson(json['position']) : null;
    final workDoneToken = json['workDoneToken'] is num
        ? Either2<num, String>.t1(json['workDoneToken'])
        : (json['workDoneToken'] is String
            ? Either2<num, String>.t2(json['workDoneToken'])
            : (json['workDoneToken'] == null
                ? null
                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
    return SignatureHelpParams(
        context: context,
        textDocument: textDocument,
        position: position,
        workDoneToken: workDoneToken);
  }

  /// The signature help context. This is only available if the client specifies
  /// to send this using the client capability
  /// `textDocument.signatureHelp.contextSupport === true`
  ///  @since 3.15.0
  final SignatureHelpContext context;

  /// The position inside the text document.
  final Position position;

  /// The text document.
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  final Either2<num, String> workDoneToken;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (context != null) {
      __result['context'] = context.toJson();
    }
    __result['textDocument'] = textDocument?.toJson() ??
        (throw 'textDocument is required but was not set');
    __result['position'] =
        position?.toJson() ?? (throw 'position is required but was not set');
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('context');
      try {
        if (obj['context'] != null &&
            !(SignatureHelpContext.canParse(obj['context'], reporter))) {
          reporter.reportError('must be of type SignatureHelpContext');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['textDocument'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(TextDocumentIdentifier.canParse(obj['textDocument'], reporter))) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('position');
      try {
        if (!obj.containsKey('position')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['position'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(Position.canParse(obj['position'], reporter))) {
          reporter.reportError('must be of type Position');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        if (obj['workDoneToken'] != null &&
            !((obj['workDoneToken'] is num ||
                obj['workDoneToken'] is String))) {
          reporter.reportError('must be of type Either2<num, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SignatureHelpParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SignatureHelpParams &&
        other.runtimeType == SignatureHelpParams) {
      return context == other.context &&
          textDocument == other.textDocument &&
          position == other.position &&
          workDoneToken == other.workDoneToken &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, context.hashCode);
    hash = JenkinsSmiHash.combine(hash, textDocument.hashCode);
    hash = JenkinsSmiHash.combine(hash, position.hashCode);
    hash = JenkinsSmiHash.combine(hash, workDoneToken.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SignatureHelpRegistrationOptions
    implements
        TextDocumentRegistrationOptions,
        SignatureHelpOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
      SignatureHelpRegistrationOptions.canParse,
      SignatureHelpRegistrationOptions.fromJson);

  SignatureHelpRegistrationOptions(
      {this.documentSelector,
      this.triggerCharacters,
      this.retriggerCharacters,
      this.workDoneProgress});
  static SignatureHelpRegistrationOptions fromJson(Map<String, dynamic> json) {
    final documentSelector = json['documentSelector']
        ?.map((item) => item != null ? DocumentFilter.fromJson(item) : null)
        ?.cast<DocumentFilter>()
        ?.toList();
    final triggerCharacters = json['triggerCharacters']
        ?.map((item) => item)
        ?.cast<String>()
        ?.toList();
    final retriggerCharacters = json['retriggerCharacters']
        ?.map((item) => item)
        ?.cast<String>()
        ?.toList();
    final workDoneProgress = json['workDoneProgress'];
    return SignatureHelpRegistrationOptions(
        documentSelector: documentSelector,
        triggerCharacters: triggerCharacters,
        retriggerCharacters: retriggerCharacters,
        workDoneProgress: workDoneProgress);
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  final List<DocumentFilter> documentSelector;

  /// List of characters that re-trigger signature help.
  ///
  /// These trigger characters are only active when signature help is already
  /// showing. All trigger characters are also counted as re-trigger characters.
  ///  @since 3.15.0
  final List<String> retriggerCharacters;

  /// The characters that trigger signature help automatically.
  final List<String> triggerCharacters;
  final bool workDoneProgress;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['documentSelector'] = documentSelector;
    if (triggerCharacters != null) {
      __result['triggerCharacters'] = triggerCharacters;
    }
    if (retriggerCharacters != null) {
      __result['retriggerCharacters'] = retriggerCharacters;
    }
    if (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['documentSelector'] != null &&
            !((obj['documentSelector'] is List &&
                (obj['documentSelector'].every(
                    (item) => DocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<DocumentFilter>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('triggerCharacters');
      try {
        if (obj['triggerCharacters'] != null &&
            !((obj['triggerCharacters'] is List &&
                (obj['triggerCharacters'].every((item) => item is String))))) {
          reporter.reportError('must be of type List<String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('retriggerCharacters');
      try {
        if (obj['retriggerCharacters'] != null &&
            !((obj['retriggerCharacters'] is List &&
                (obj['retriggerCharacters']
                    .every((item) => item is String))))) {
          reporter.reportError('must be of type List<String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        if (obj['workDoneProgress'] != null &&
            !(obj['workDoneProgress'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SignatureHelpRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SignatureHelpRegistrationOptions &&
        other.runtimeType == SignatureHelpRegistrationOptions) {
      return listEqual(documentSelector, other.documentSelector,
              (DocumentFilter a, DocumentFilter b) => a == b) &&
          listEqual(triggerCharacters, other.triggerCharacters,
              (String a, String b) => a == b) &&
          listEqual(retriggerCharacters, other.retriggerCharacters,
              (String a, String b) => a == b) &&
          workDoneProgress == other.workDoneProgress &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(documentSelector));
    hash = JenkinsSmiHash.combine(hash, lspHashCode(triggerCharacters));
    hash = JenkinsSmiHash.combine(hash, lspHashCode(retriggerCharacters));
    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// How a signature help was triggered.
///  @since 3.15.0
class SignatureHelpTriggerKind {
  const SignatureHelpTriggerKind(this._value);
  const SignatureHelpTriggerKind.fromJson(this._value);

  final num _value;

  static bool canParse(Object obj, LspJsonReporter reporter) {
    return obj is num;
  }

  /// Signature help was invoked manually by the user or by a command.
  static const Invoked = SignatureHelpTriggerKind(1);

  /// Signature help was triggered by a trigger character.
  static const TriggerCharacter = SignatureHelpTriggerKind(2);

  /// Signature help was triggered by the cursor moving or by the document
  /// content changing.
  static const ContentChange = SignatureHelpTriggerKind(3);

  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  bool operator ==(Object o) =>
      o is SignatureHelpTriggerKind && o._value == _value;
}

/// Represents the signature of something callable. A signature can have a
/// label, like a function-name, a doc-comment, and a set of parameters.
class SignatureInformation implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
      SignatureInformation.canParse, SignatureInformation.fromJson);

  SignatureInformation(
      {@required this.label,
      this.documentation,
      this.parameters,
      this.activeParameter}) {
    if (label == null) {
      throw 'label is required but was not provided';
    }
  }
  static SignatureInformation fromJson(Map<String, dynamic> json) {
    final label = json['label'];
    final documentation = json['documentation'] is String
        ? Either2<String, MarkupContent>.t1(json['documentation'])
        : (MarkupContent.canParse(json['documentation'], nullLspJsonReporter)
            ? Either2<String, MarkupContent>.t2(json['documentation'] != null
                ? MarkupContent.fromJson(json['documentation'])
                : null)
            : (json['documentation'] == null
                ? null
                : (throw '''${json['documentation']} was not one of (String, MarkupContent)''')));
    final parameters = json['parameters']
        ?.map(
            (item) => item != null ? ParameterInformation.fromJson(item) : null)
        ?.cast<ParameterInformation>()
        ?.toList();
    final activeParameter = json['activeParameter'];
    return SignatureInformation(
        label: label,
        documentation: documentation,
        parameters: parameters,
        activeParameter: activeParameter);
  }

  /// The index of the active parameter.
  ///
  /// If provided, this is used in place of `SignatureHelp.activeParameter`.
  ///  @since 3.16.0
  final num activeParameter;

  /// The human-readable doc-comment of this signature. Will be shown in the UI
  /// but can be omitted.
  final Either2<String, MarkupContent> documentation;

  /// The label of this signature. Will be shown in the UI.
  final String label;

  /// The parameters of this signature.
  final List<ParameterInformation> parameters;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['label'] = label ?? (throw 'label is required but was not set');
    if (documentation != null) {
      __result['documentation'] = documentation;
    }
    if (parameters != null) {
      __result['parameters'] = parameters.map((item) => item.toJson()).toList();
    }
    if (activeParameter != null) {
      __result['activeParameter'] = activeParameter;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('label');
      try {
        if (!obj.containsKey('label')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['label'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['label'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('documentation');
      try {
        if (obj['documentation'] != null &&
            !((obj['documentation'] is String ||
                MarkupContent.canParse(obj['documentation'], reporter)))) {
          reporter
              .reportError('must be of type Either2<String, MarkupContent>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('parameters');
      try {
        if (obj['parameters'] != null &&
            !((obj['parameters'] is List &&
                (obj['parameters'].every((item) =>
                    ParameterInformation.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<ParameterInformation>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('activeParameter');
      try {
        if (obj['activeParameter'] != null &&
            !(obj['activeParameter'] is num)) {
          reporter.reportError('must be of type num');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SignatureInformation');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SignatureInformation &&
        other.runtimeType == SignatureInformation) {
      return label == other.label &&
          documentation == other.documentation &&
          listEqual(parameters, other.parameters,
              (ParameterInformation a, ParameterInformation b) => a == b) &&
          activeParameter == other.activeParameter &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, label.hashCode);
    hash = JenkinsSmiHash.combine(hash, documentation.hashCode);
    hash = JenkinsSmiHash.combine(hash, lspHashCode(parameters));
    hash = JenkinsSmiHash.combine(hash, activeParameter.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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, dynamic> json) {
    if (DeclarationRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DeclarationRegistrationOptions.fromJson(json);
    }
    if (TypeDefinitionRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return TypeDefinitionRegistrationOptions.fromJson(json);
    }
    if (ImplementationRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return ImplementationRegistrationOptions.fromJson(json);
    }
    if (DocumentColorRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentColorRegistrationOptions.fromJson(json);
    }
    if (FoldingRangeRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return FoldingRangeRegistrationOptions.fromJson(json);
    }
    if (SelectionRangeRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return SelectionRangeRegistrationOptions.fromJson(json);
    }
    if (CallHierarchyRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return CallHierarchyRegistrationOptions.fromJson(json);
    }
    if (SemanticTokensRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return SemanticTokensRegistrationOptions.fromJson(json);
    }
    if (LinkedEditingRangeRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return LinkedEditingRangeRegistrationOptions.fromJson(json);
    }
    final id = json['id'];
    return StaticRegistrationOptions(id: id);
  }

  /// The id used to register the request. The id can be used to deregister the
  /// request again. See also Registration#id.
  final String id;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (id != null) {
      __result['id'] = id;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('id');
      try {
        if (obj['id'] != null && !(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, id.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Represents information about programming constructs like variables, classes,
/// interfaces etc.
class SymbolInformation implements ToJsonable {
  static const jsonHandler =
      LspJsonHandler(SymbolInformation.canParse, SymbolInformation.fromJson);

  SymbolInformation(
      {@required this.name,
      @required this.kind,
      this.tags,
      this.deprecated,
      @required this.location,
      this.containerName}) {
    if (name == null) {
      throw 'name is required but was not provided';
    }
    if (kind == null) {
      throw 'kind is required but was not provided';
    }
    if (location == null) {
      throw 'location is required but was not provided';
    }
  }
  static SymbolInformation fromJson(Map<String, dynamic> json) {
    final name = json['name'];
    final kind =
        json['kind'] != null ? SymbolKind.fromJson(json['kind']) : null;
    final tags = json['tags']
        ?.map((item) => item != null ? SymbolTag.fromJson(item) : null)
        ?.cast<SymbolTag>()
        ?.toList();
    final deprecated = json['deprecated'];
    final location =
        json['location'] != null ? Location.fromJson(json['location']) : null;
    final containerName = json['containerName'];
    return SymbolInformation(
        name: name,
        kind: kind,
        tags: tags,
        deprecated: deprecated,
        location: location,
        containerName: containerName);
  }

  /// The name of the symbol containing this symbol. This information is for
  /// user interface purposes (e.g. to render a qualifier in the user interface
  /// if necessary). It can't be used to re-infer a hierarchy for the document
  /// symbols.
  final String containerName;

  /// Indicates if this symbol is deprecated.
  ///  @deprecated Use tags instead
  final bool deprecated;

  /// The kind of this symbol.
  final SymbolKind kind;

  /// The location of this symbol. The location's range is used by a tool to
  /// reveal the location in the editor. If the symbol is selected in the tool
  /// the range's start information is used to position the cursor. So the range
  /// usually spans more then the actual symbol's name and does normally include
  /// things like visibility modifiers.
  ///
  /// The range doesn't have to denote a node range in the sense of a abstract
  /// syntax tree. It can therefore not be used to re-construct a hierarchy of
  /// the symbols.
  final Location location;

  /// The name of this symbol.
  final String name;

  /// Tags for this completion item.
  ///  @since 3.16.0
  final List<SymbolTag> tags;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['name'] = name ?? (throw 'name is required but was not set');
    __result['kind'] =
        kind?.toJson() ?? (throw 'kind is required but was not set');
    if (tags != null) {
      __result['tags'] = tags.map((item) => item.toJson()).toList();
    }
    if (deprecated != null) {
      __result['deprecated'] = deprecated;
    }
    __result['location'] =
        location?.toJson() ?? (throw 'location is required but was not set');
    if (containerName != null) {
      __result['containerName'] = containerName;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('name');
      try {
        if (!obj.containsKey('name')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['name'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['name'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('kind');
      try {
        if (!obj.containsKey('kind')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['kind'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(SymbolKind.canParse(obj['kind'], reporter))) {
          reporter.reportError('must be of type SymbolKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('tags');
      try {
        if (obj['tags'] != null &&
            !((obj['tags'] is List &&
                (obj['tags']
                    .every((item) => SymbolTag.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<SymbolTag>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('deprecated');
      try {
        if (obj['deprecated'] != null && !(obj['deprecated'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('location');
      try {
        if (!obj.containsKey('location')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['location'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(Location.canParse(obj['location'], reporter))) {
          reporter.reportError('must be of type Location');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('containerName');
      try {
        if (obj['containerName'] != null && !(obj['containerName'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type SymbolInformation');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is SymbolInformation && other.runtimeType == SymbolInformation) {
      return name == other.name &&
          kind == other.kind &&
          listEqual(tags, other.tags, (SymbolTag a, SymbolTag b) => a == b) &&
          deprecated == other.deprecated &&
          location == other.location &&
          containerName == other.containerName &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, name.hashCode);
    hash = JenkinsSmiHash.combine(hash, kind.hashCode);
    hash = JenkinsSmiHash.combine(hash, lspHashCode(tags));
    hash = JenkinsSmiHash.combine(hash, deprecated.hashCode);
    hash = JenkinsSmiHash.combine(hash, location.hashCode);
    hash = JenkinsSmiHash.combine(hash, containerName.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A symbol kind.
class SymbolKind {
  const SymbolKind(this._value);
  const SymbolKind.fromJson(this._value);

  final num _value;

  static bool canParse(Object obj, LspJsonReporter reporter) {
    return obj is num;
  }

  static const File = SymbolKind(1);
  static const Module = SymbolKind(2);
  static const Namespace = SymbolKind(3);
  static const Package = SymbolKind(4);
  static const Class = SymbolKind(5);
  static const Method = SymbolKind(6);
  static const Property = SymbolKind(7);
  static const Field = SymbolKind(8);
  static const Constructor = SymbolKind(9);
  static const Enum = SymbolKind(10);
  static const Interface = SymbolKind(11);
  static const Function = SymbolKind(12);
  static const Variable = SymbolKind(13);
  static const Constant = SymbolKind(14);
  static const Str = SymbolKind(15);
  static const Number = SymbolKind(16);
  static const Boolean = SymbolKind(17);
  static const Array = SymbolKind(18);
  static const Obj = SymbolKind(19);
  static const Key = SymbolKind(20);
  static const Null = SymbolKind(21);
  static const EnumMember = SymbolKind(22);
  static const Struct = SymbolKind(23);
  static const Event = SymbolKind(24);
  static const Operator = SymbolKind(25);
  static const TypeParameter = SymbolKind(26);

  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  bool operator ==(Object o) => o is SymbolKind && o._value == _value;
}

/// Symbol tags are extra annotations that tweak the rendering of a symbol.
///  @since 3.16
class SymbolTag {
  const SymbolTag(this._value);
  const SymbolTag.fromJson(this._value);

  final num _value;

  static bool canParse(Object obj, LspJsonReporter reporter) {
    return obj is num;
  }

  /// Render a symbol as obsolete, usually using a strike-out.
  static const Deprecated = SymbolTag(1);

  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  bool operator ==(Object o) => o is SymbolTag && o._value == _value;
}

/// Describe options to be used when registering for text document change
/// events.
class TextDocumentChangeRegistrationOptions
    implements TextDocumentRegistrationOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
      TextDocumentChangeRegistrationOptions.canParse,
      TextDocumentChangeRegistrationOptions.fromJson);

  TextDocumentChangeRegistrationOptions(
      {@required this.syncKind, this.documentSelector}) {
    if (syncKind == null) {
      throw 'syncKind is required but was not provided';
    }
  }
  static TextDocumentChangeRegistrationOptions fromJson(
      Map<String, dynamic> json) {
    final syncKind = json['syncKind'] != null
        ? TextDocumentSyncKind.fromJson(json['syncKind'])
        : null;
    final documentSelector = json['documentSelector']
        ?.map((item) => item != null ? DocumentFilter.fromJson(item) : null)
        ?.cast<DocumentFilter>()
        ?.toList();
    return TextDocumentChangeRegistrationOptions(
        syncKind: syncKind, documentSelector: documentSelector);
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  final List<DocumentFilter> documentSelector;

  /// How documents are synced to the server. See TextDocumentSyncKind.Full and
  /// TextDocumentSyncKind.Incremental.
  final TextDocumentSyncKind syncKind;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['syncKind'] =
        syncKind?.toJson() ?? (throw 'syncKind is required but was not set');
    __result['documentSelector'] = documentSelector;
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('syncKind');
      try {
        if (!obj.containsKey('syncKind')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['syncKind'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(TextDocumentSyncKind.canParse(obj['syncKind'], reporter))) {
          reporter.reportError('must be of type TextDocumentSyncKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['documentSelector'] != null &&
            !((obj['documentSelector'] is List &&
                (obj['documentSelector'].every(
                    (item) => DocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<DocumentFilter>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter
          .reportError('must be of type TextDocumentChangeRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is TextDocumentChangeRegistrationOptions &&
        other.runtimeType == TextDocumentChangeRegistrationOptions) {
      return syncKind == other.syncKind &&
          listEqual(documentSelector, other.documentSelector,
              (DocumentFilter a, DocumentFilter b) => a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, syncKind.hashCode);
    hash = JenkinsSmiHash.combine(hash, lspHashCode(documentSelector));
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Text document specific client capabilities.
class TextDocumentClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
      TextDocumentClientCapabilities.canParse,
      TextDocumentClientCapabilities.fromJson);

  TextDocumentClientCapabilities(
      {this.synchronization,
      this.completion,
      this.hover,
      this.signatureHelp,
      this.declaration,
      this.definition,
      this.typeDefinition,
      this.implementation,
      this.references,
      this.documentHighlight,
      this.documentSymbol,
      this.codeAction,
      this.codeLens,
      this.documentLink,
      this.colorProvider,
      this.formatting,
      this.rangeFormatting,
      this.onTypeFormatting,
      this.rename,
      this.publishDiagnostics,
      this.foldingRange,
      this.selectionRange,
      this.linkedEditingRange,
      this.callHierarchy,
      this.semanticTokens,
      this.moniker});
  static TextDocumentClientCapabilities fromJson(Map<String, dynamic> json) {
    final synchronization = json['synchronization'] != null
        ? TextDocumentSyncClientCapabilities.fromJson(json['synchronization'])
        : null;
    final completion = json['completion'] != null
        ? CompletionClientCapabilities.fromJson(json['completion'])
        : null;
    final hover = json['hover'] != null
        ? HoverClientCapabilities.fromJson(json['hover'])
        : null;
    final signatureHelp = json['signatureHelp'] != null
        ? SignatureHelpClientCapabilities.fromJson(json['signatureHelp'])
        : null;
    final declaration = json['declaration'] != null
        ? DeclarationClientCapabilities.fromJson(json['declaration'])
        : null;
    final definition = json['definition'] != null
        ? DefinitionClientCapabilities.fromJson(json['definition'])
        : null;
    final typeDefinition = json['typeDefinition'] != null
        ? TypeDefinitionClientCapabilities.fromJson(json['typeDefinition'])
        : null;
    final implementation = json['implementation'] != null
        ? ImplementationClientCapabilities.fromJson(json['implementation'])
        : null;
    final references = json['references'] != null
        ? ReferenceClientCapabilities.fromJson(json['references'])
        : null;
    final documentHighlight = json['documentHighlight'] != null
        ? DocumentHighlightClientCapabilities.fromJson(
            json['documentHighlight'])
        : null;
    final documentSymbol = json['documentSymbol'] != null
        ? DocumentSymbolClientCapabilities.fromJson(json['documentSymbol'])
        : null;
    final codeAction = json['codeAction'] != null
        ? CodeActionClientCapabilities.fromJson(json['codeAction'])
        : null;
    final codeLens = json['codeLens'] != null
        ? CodeLensClientCapabilities.fromJson(json['codeLens'])
        : null;
    final documentLink = json['documentLink'] != null
        ? DocumentLinkClientCapabilities.fromJson(json['documentLink'])
        : null;
    final colorProvider = json['colorProvider'] != null
        ? DocumentColorClientCapabilities.fromJson(json['colorProvider'])
        : null;
    final formatting = json['formatting'] != null
        ? DocumentFormattingClientCapabilities.fromJson(json['formatting'])
        : null;
    final rangeFormatting = json['rangeFormatting'] != null
        ? DocumentRangeFormattingClientCapabilities.fromJson(
            json['rangeFormatting'])
        : null;
    final onTypeFormatting = json['onTypeFormatting'] != null
        ? DocumentOnTypeFormattingClientCapabilities.fromJson(
            json['onTypeFormatting'])
        : null;
    final rename = json['rename'] != null
        ? RenameClientCapabilities.fromJson(json['rename'])
        : null;
    final publishDiagnostics = json['publishDiagnostics'] != null
        ? PublishDiagnosticsClientCapabilities.fromJson(
            json['publishDiagnostics'])
        : null;
    final foldingRange = json['foldingRange'] != null
        ? FoldingRangeClientCapabilities.fromJson(json['foldingRange'])
        : null;
    final selectionRange = json['selectionRange'] != null
        ? SelectionRangeClientCapabilities.fromJson(json['selectionRange'])
        : null;
    final linkedEditingRange = json['linkedEditingRange'] != null
        ? LinkedEditingRangeClientCapabilities.fromJson(
            json['linkedEditingRange'])
        : null;
    final callHierarchy = json['callHierarchy'] != null
        ? CallHierarchyClientCapabilities.fromJson(json['callHierarchy'])
        : null;
    final semanticTokens = json['semanticTokens'] != null
        ? SemanticTokensClientCapabilities.fromJson(json['semanticTokens'])
        : null;
    final moniker = json['moniker'] != null
        ? MonikerClientCapabilities.fromJson(json['moniker'])
        : null;
    return TextDocumentClientCapabilities(
        synchronization: synchronization,
        completion: completion,
        hover: hover,
        signatureHelp: signatureHelp,
        declaration: declaration,
        definition: definition,
        typeDefinition: typeDefinition,
        implementation: implementation,
        references: references,
        documentHighlight: documentHighlight,
        documentSymbol: documentSymbol,
        codeAction: codeAction,
        codeLens: codeLens,
        documentLink: documentLink,
        colorProvider: colorProvider,
        formatting: formatting,
        rangeFormatting: rangeFormatting,
        onTypeFormatting: onTypeFormatting,
        rename: rename,
        publishDiagnostics: publishDiagnostics,
        foldingRange: foldingRange,
        selectionRange: selectionRange,
        linkedEditingRange: linkedEditingRange,
        callHierarchy: callHierarchy,
        semanticTokens: semanticTokens,
        moniker: moniker);
  }

  /// Capabilities specific to the various call hierarchy requests.
  ///  @since 3.16.0
  final CallHierarchyClientCapabilities callHierarchy;

  /// Capabilities specific to the `textDocument/codeAction` request.
  final CodeActionClientCapabilities codeAction;

  /// Capabilities specific to the `textDocument/codeLens` request.
  final CodeLensClientCapabilities codeLens;

  /// Capabilities specific to the `textDocument/documentColor` and the
  /// `textDocument/colorPresentation` request.
  ///  @since 3.6.0
  final DocumentColorClientCapabilities colorProvider;

  /// Capabilities specific to the `textDocument/completion` request.
  final CompletionClientCapabilities completion;

  /// Capabilities specific to the `textDocument/declaration` request.
  ///  @since 3.14.0
  final DeclarationClientCapabilities declaration;

  /// Capabilities specific to the `textDocument/definition` request.
  final DefinitionClientCapabilities definition;

  /// Capabilities specific to the `textDocument/documentHighlight` request.
  final DocumentHighlightClientCapabilities documentHighlight;

  /// Capabilities specific to the `textDocument/documentLink` request.
  final DocumentLinkClientCapabilities documentLink;

  /// Capabilities specific to the `textDocument/documentSymbol` request.
  final DocumentSymbolClientCapabilities documentSymbol;

  /// Capabilities specific to the `textDocument/foldingRange` request.
  ///  @since 3.10.0
  final FoldingRangeClientCapabilities foldingRange;

  /// Capabilities specific to the `textDocument/formatting` request.
  final DocumentFormattingClientCapabilities formatting;

  /// Capabilities specific to the `textDocument/hover` request.
  final HoverClientCapabilities hover;

  /// Capabilities specific to the `textDocument/implementation` request.
  ///  @since 3.6.0
  final ImplementationClientCapabilities implementation;

  /// Capabilities specific to the `textDocument/linkedEditingRange` request.
  ///  @since 3.16.0
  final LinkedEditingRangeClientCapabilities linkedEditingRange;

  /// Capabilities specific to the `textDocument/moniker` request.
  ///  @since 3.16.0
  final MonikerClientCapabilities moniker;

  /// request. Capabilities specific to the `textDocument/onTypeFormatting`
  /// request.
  final DocumentOnTypeFormattingClientCapabilities onTypeFormatting;

  /// Capabilities specific to the `textDocument/publishDiagnostics`
  /// notification.
  final PublishDiagnosticsClientCapabilities publishDiagnostics;

  /// Capabilities specific to the `textDocument/rangeFormatting` request.
  final DocumentRangeFormattingClientCapabilities rangeFormatting;

  /// Capabilities specific to the `textDocument/references` request.
  final ReferenceClientCapabilities references;

  /// Capabilities specific to the `textDocument/rename` request.
  final RenameClientCapabilities rename;

  /// Capabilities specific to the `textDocument/selectionRange` request.
  ///  @since 3.15.0
  final SelectionRangeClientCapabilities selectionRange;

  /// Capabilities specific to the various semantic token requests.
  ///  @since 3.16.0
  final SemanticTokensClientCapabilities semanticTokens;

  /// Capabilities specific to the `textDocument/signatureHelp` request.
  final SignatureHelpClientCapabilities signatureHelp;
  final TextDocumentSyncClientCapabilities synchronization;

  /// Capabilities specific to the `textDocument/typeDefinition` request.
  ///  @since 3.6.0
  final TypeDefinitionClientCapabilities typeDefinition;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (synchronization != null) {
      __result['synchronization'] = synchronization.toJson();
    }
    if (completion != null) {
      __result['completion'] = completion.toJson();
    }
    if (hover != null) {
      __result['hover'] = hover.toJson();
    }
    if (signatureHelp != null) {
      __result['signatureHelp'] = signatureHelp.toJson();
    }
    if (declaration != null) {
      __result['declaration'] = declaration.toJson();
    }
    if (definition != null) {
      __result['definition'] = definition.toJson();
    }
    if (typeDefinition != null) {
      __result['typeDefinition'] = typeDefinition.toJson();
    }
    if (implementation != null) {
      __result['implementation'] = implementation.toJson();
    }
    if (references != null) {
      __result['references'] = references.toJson();
    }
    if (documentHighlight != null) {
      __result['documentHighlight'] = documentHighlight.toJson();
    }
    if (documentSymbol != null) {
      __result['documentSymbol'] = documentSymbol.toJson();
    }
    if (codeAction != null) {
      __result['codeAction'] = codeAction.toJson();
    }
    if (codeLens != null) {
      __result['codeLens'] = codeLens.toJson();
    }
    if (documentLink != null) {
      __result['documentLink'] = documentLink.toJson();
    }
    if (colorProvider != null) {
      __result['colorProvider'] = colorProvider.toJson();
    }
    if (formatting != null) {
      __result['formatting'] = formatting.toJson();
    }
    if (rangeFormatting != null) {
      __result['rangeFormatting'] = rangeFormatting.toJson();
    }
    if (onTypeFormatting != null) {
      __result['onTypeFormatting'] = onTypeFormatting.toJson();
    }
    if (rename != null) {
      __result['rename'] = rename.toJson();
    }
    if (publishDiagnostics != null) {
      __result['publishDiagnostics'] = publishDiagnostics.toJson();
    }
    if (foldingRange != null) {
      __result['foldingRange'] = foldingRange.toJson();
    }
    if (selectionRange != null) {
      __result['selectionRange'] = selectionRange.toJson();
    }
    if (linkedEditingRange != null) {
      __result['linkedEditingRange'] = linkedEditingRange.toJson();
    }
    if (callHierarchy != null) {
      __result['callHierarchy'] = callHierarchy.toJson();
    }
    if (semanticTokens != null) {
      __result['semanticTokens'] = semanticTokens.toJson();
    }
    if (moniker != null) {
      __result['moniker'] = moniker.toJson();
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('synchronization');
      try {
        if (obj['synchronization'] != null &&
            !(TextDocumentSyncClientCapabilities.canParse(
                obj['synchronization'], reporter))) {
          reporter.reportError(
              'must be of type TextDocumentSyncClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('completion');
      try {
        if (obj['completion'] != null &&
            !(CompletionClientCapabilities.canParse(
                obj['completion'], reporter))) {
          reporter.reportError('must be of type CompletionClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('hover');
      try {
        if (obj['hover'] != null &&
            !(HoverClientCapabilities.canParse(obj['hover'], reporter))) {
          reporter.reportError('must be of type HoverClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('signatureHelp');
      try {
        if (obj['signatureHelp'] != null &&
            !(SignatureHelpClientCapabilities.canParse(
                obj['signatureHelp'], reporter))) {
          reporter
              .reportError('must be of type SignatureHelpClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('declaration');
      try {
        if (obj['declaration'] != null &&
            !(DeclarationClientCapabilities.canParse(
                obj['declaration'], reporter))) {
          reporter.reportError('must be of type DeclarationClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('definition');
      try {
        if (obj['definition'] != null &&
            !(DefinitionClientCapabilities.canParse(
                obj['definition'], reporter))) {
          reporter.reportError('must be of type DefinitionClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('typeDefinition');
      try {
        if (obj['typeDefinition'] != null &&
            !(TypeDefinitionClientCapabilities.canParse(
                obj['typeDefinition'], reporter))) {
          reporter
              .reportError('must be of type TypeDefinitionClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('implementation');
      try {
        if (obj['implementation'] != null &&
            !(ImplementationClientCapabilities.canParse(
                obj['implementation'], reporter))) {
          reporter
              .reportError('must be of type ImplementationClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('references');
      try {
        if (obj['references'] != null &&
            !(ReferenceClientCapabilities.canParse(
                obj['references'], reporter))) {
          reporter.reportError('must be of type ReferenceClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('documentHighlight');
      try {
        if (obj['documentHighlight'] != null &&
            !(DocumentHighlightClientCapabilities.canParse(
                obj['documentHighlight'], reporter))) {
          reporter.reportError(
              'must be of type DocumentHighlightClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('documentSymbol');
      try {
        if (obj['documentSymbol'] != null &&
            !(DocumentSymbolClientCapabilities.canParse(
                obj['documentSymbol'], reporter))) {
          reporter
              .reportError('must be of type DocumentSymbolClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('codeAction');
      try {
        if (obj['codeAction'] != null &&
            !(CodeActionClientCapabilities.canParse(
                obj['codeAction'], reporter))) {
          reporter.reportError('must be of type CodeActionClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('codeLens');
      try {
        if (obj['codeLens'] != null &&
            !(CodeLensClientCapabilities.canParse(obj['codeLens'], reporter))) {
          reporter.reportError('must be of type CodeLensClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('documentLink');
      try {
        if (obj['documentLink'] != null &&
            !(DocumentLinkClientCapabilities.canParse(
                obj['documentLink'], reporter))) {
          reporter
              .reportError('must be of type DocumentLinkClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('colorProvider');
      try {
        if (obj['colorProvider'] != null &&
            !(DocumentColorClientCapabilities.canParse(
                obj['colorProvider'], reporter))) {
          reporter
              .reportError('must be of type DocumentColorClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('formatting');
      try {
        if (obj['formatting'] != null &&
            !(DocumentFormattingClientCapabilities.canParse(
                obj['formatting'], reporter))) {
          reporter.reportError(
              'must be of type DocumentFormattingClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('rangeFormatting');
      try {
        if (obj['rangeFormatting'] != null &&
            !(DocumentRangeFormattingClientCapabilities.canParse(
                obj['rangeFormatting'], reporter))) {
          reporter.reportError(
              'must be of type DocumentRangeFormattingClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('onTypeFormatting');
      try {
        if (obj['onTypeFormatting'] != null &&
            !(DocumentOnTypeFormattingClientCapabilities.canParse(
                obj['onTypeFormatting'], reporter))) {
          reporter.reportError(
              'must be of type DocumentOnTypeFormattingClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('rename');
      try {
        if (obj['rename'] != null &&
            !(RenameClientCapabilities.canParse(obj['rename'], reporter))) {
          reporter.reportError('must be of type RenameClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('publishDiagnostics');
      try {
        if (obj['publishDiagnostics'] != null &&
            !(PublishDiagnosticsClientCapabilities.canParse(
                obj['publishDiagnostics'], reporter))) {
          reporter.reportError(
              'must be of type PublishDiagnosticsClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('foldingRange');
      try {
        if (obj['foldingRange'] != null &&
            !(FoldingRangeClientCapabilities.canParse(
                obj['foldingRange'], reporter))) {
          reporter
              .reportError('must be of type FoldingRangeClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('selectionRange');
      try {
        if (obj['selectionRange'] != null &&
            !(SelectionRangeClientCapabilities.canParse(
                obj['selectionRange'], reporter))) {
          reporter
              .reportError('must be of type SelectionRangeClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('linkedEditingRange');
      try {
        if (obj['linkedEditingRange'] != null &&
            !(LinkedEditingRangeClientCapabilities.canParse(
                obj['linkedEditingRange'], reporter))) {
          reporter.reportError(
              'must be of type LinkedEditingRangeClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('callHierarchy');
      try {
        if (obj['callHierarchy'] != null &&
            !(CallHierarchyClientCapabilities.canParse(
                obj['callHierarchy'], reporter))) {
          reporter
              .reportError('must be of type CallHierarchyClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('semanticTokens');
      try {
        if (obj['semanticTokens'] != null &&
            !(SemanticTokensClientCapabilities.canParse(
                obj['semanticTokens'], reporter))) {
          reporter
              .reportError('must be of type SemanticTokensClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('moniker');
      try {
        if (obj['moniker'] != null &&
            !(MonikerClientCapabilities.canParse(obj['moniker'], reporter))) {
          reporter.reportError('must be of type MonikerClientCapabilities');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TextDocumentClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is TextDocumentClientCapabilities &&
        other.runtimeType == TextDocumentClientCapabilities) {
      return synchronization == other.synchronization &&
          completion == other.completion &&
          hover == other.hover &&
          signatureHelp == other.signatureHelp &&
          declaration == other.declaration &&
          definition == other.definition &&
          typeDefinition == other.typeDefinition &&
          implementation == other.implementation &&
          references == other.references &&
          documentHighlight == other.documentHighlight &&
          documentSymbol == other.documentSymbol &&
          codeAction == other.codeAction &&
          codeLens == other.codeLens &&
          documentLink == other.documentLink &&
          colorProvider == other.colorProvider &&
          formatting == other.formatting &&
          rangeFormatting == other.rangeFormatting &&
          onTypeFormatting == other.onTypeFormatting &&
          rename == other.rename &&
          publishDiagnostics == other.publishDiagnostics &&
          foldingRange == other.foldingRange &&
          selectionRange == other.selectionRange &&
          linkedEditingRange == other.linkedEditingRange &&
          callHierarchy == other.callHierarchy &&
          semanticTokens == other.semanticTokens &&
          moniker == other.moniker &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, synchronization.hashCode);
    hash = JenkinsSmiHash.combine(hash, completion.hashCode);
    hash = JenkinsSmiHash.combine(hash, hover.hashCode);
    hash = JenkinsSmiHash.combine(hash, signatureHelp.hashCode);
    hash = JenkinsSmiHash.combine(hash, declaration.hashCode);
    hash = JenkinsSmiHash.combine(hash, definition.hashCode);
    hash = JenkinsSmiHash.combine(hash, typeDefinition.hashCode);
    hash = JenkinsSmiHash.combine(hash, implementation.hashCode);
    hash = JenkinsSmiHash.combine(hash, references.hashCode);
    hash = JenkinsSmiHash.combine(hash, documentHighlight.hashCode);
    hash = JenkinsSmiHash.combine(hash, documentSymbol.hashCode);
    hash = JenkinsSmiHash.combine(hash, codeAction.hashCode);
    hash = JenkinsSmiHash.combine(hash, codeLens.hashCode);
    hash = JenkinsSmiHash.combine(hash, documentLink.hashCode);
    hash = JenkinsSmiHash.combine(hash, colorProvider.hashCode);
    hash = JenkinsSmiHash.combine(hash, formatting.hashCode);
    hash = JenkinsSmiHash.combine(hash, rangeFormatting.hashCode);
    hash = JenkinsSmiHash.combine(hash, onTypeFormatting.hashCode);
    hash = JenkinsSmiHash.combine(hash, rename.hashCode);
    hash = JenkinsSmiHash.combine(hash, publishDiagnostics.hashCode);
    hash = JenkinsSmiHash.combine(hash, foldingRange.hashCode);
    hash = JenkinsSmiHash.combine(hash, selectionRange.hashCode);
    hash = JenkinsSmiHash.combine(hash, linkedEditingRange.hashCode);
    hash = JenkinsSmiHash.combine(hash, callHierarchy.hashCode);
    hash = JenkinsSmiHash.combine(hash, semanticTokens.hashCode);
    hash = JenkinsSmiHash.combine(hash, moniker.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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}) {
    if (range == null) {
      throw 'range is required but was not provided';
    }
    if (text == null) {
      throw 'text is required but was not provided';
    }
  }
  static TextDocumentContentChangeEvent1 fromJson(Map<String, dynamic> json) {
    final range = json['range'] != null ? Range.fromJson(json['range']) : null;
    final rangeLength = json['rangeLength'];
    final text = json['text'];
    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 num rangeLength;

  /// The new text for the provided range.
  final String text;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['range'] =
        range?.toJson() ?? (throw 'range is required but was not set');
    if (rangeLength != null) {
      __result['rangeLength'] = rangeLength;
    }
    __result['text'] = text ?? (throw 'text is required but was not set');
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('range');
      try {
        if (!obj.containsKey('range')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['range'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(Range.canParse(obj['range'], reporter))) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('rangeLength');
      try {
        if (obj['rangeLength'] != null && !(obj['rangeLength'] is num)) {
          reporter.reportError('must be of type num');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('text');
      try {
        if (!obj.containsKey('text')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['text'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, range.hashCode);
    hash = JenkinsSmiHash.combine(hash, rangeLength.hashCode);
    hash = JenkinsSmiHash.combine(hash, text.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class TextDocumentContentChangeEvent2 implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
      TextDocumentContentChangeEvent2.canParse,
      TextDocumentContentChangeEvent2.fromJson);

  TextDocumentContentChangeEvent2({@required this.text}) {
    if (text == null) {
      throw 'text is required but was not provided';
    }
  }
  static TextDocumentContentChangeEvent2 fromJson(Map<String, dynamic> json) {
    final text = json['text'];
    return TextDocumentContentChangeEvent2(text: text);
  }

  /// The new text of the whole document.
  final String text;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['text'] = text ?? (throw 'text is required but was not set');
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('text');
      try {
        if (!obj.containsKey('text')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['text'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, text.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class TextDocumentEdit implements ToJsonable {
  static const jsonHandler =
      LspJsonHandler(TextDocumentEdit.canParse, TextDocumentEdit.fromJson);

  TextDocumentEdit({@required this.textDocument, @required this.edits}) {
    if (textDocument == null) {
      throw 'textDocument is required but was not provided';
    }
    if (edits == null) {
      throw 'edits is required but was not provided';
    }
  }
  static TextDocumentEdit fromJson(Map<String, dynamic> json) {
    final textDocument = json['textDocument'] != null
        ? OptionalVersionedTextDocumentIdentifier.fromJson(json['textDocument'])
        : null;
    final edits = json['edits']
        ?.map((item) => TextEdit.canParse(item, nullLspJsonReporter)
            ? Either2<TextEdit, AnnotatedTextEdit>.t1(
                item != null ? TextEdit.fromJson(item) : null)
            : (AnnotatedTextEdit.canParse(item, nullLspJsonReporter)
                ? Either2<TextEdit, AnnotatedTextEdit>.t2(
                    item != null ? AnnotatedTextEdit.fromJson(item) : null)
                : (throw '''${item} was not one of (TextEdit, AnnotatedTextEdit)''')))
        ?.cast<Either2<TextEdit, AnnotatedTextEdit>>()
        ?.toList();
    return TextDocumentEdit(textDocument: textDocument, edits: edits);
  }

  /// The edits to be applied.
  ///  @since 3.16.0 - support for AnnotatedTextEdit. This is guarded by the
  /// client capability `workspace.workspaceEdit.changeAnnotationSupport`
  final List<Either2<TextEdit, AnnotatedTextEdit>> edits;

  /// The text document to change.
  final OptionalVersionedTextDocumentIdentifier textDocument;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['textDocument'] = textDocument?.toJson() ??
        (throw 'textDocument is required but was not set');
    __result['edits'] = edits ?? (throw 'edits is required but was not set');
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['textDocument'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(OptionalVersionedTextDocumentIdentifier.canParse(
            obj['textDocument'], reporter))) {
          reporter.reportError(
              'must be of type OptionalVersionedTextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('edits');
      try {
        if (!obj.containsKey('edits')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['edits'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!((obj['edits'] is List &&
            (obj['edits'].every((item) => (TextEdit.canParse(item, reporter) ||
                AnnotatedTextEdit.canParse(item, reporter))))))) {
          reporter.reportError(
              'must be of type List<Either2<TextEdit, AnnotatedTextEdit>>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TextDocumentEdit');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is TextDocumentEdit && other.runtimeType == TextDocumentEdit) {
      return textDocument == other.textDocument &&
          listEqual(
              edits,
              other.edits,
              (Either2<TextEdit, AnnotatedTextEdit> a,
                      Either2<TextEdit, AnnotatedTextEdit> b) =>
                  a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, textDocument.hashCode);
    hash = JenkinsSmiHash.combine(hash, lspHashCode(edits));
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class TextDocumentIdentifier implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
      TextDocumentIdentifier.canParse, TextDocumentIdentifier.fromJson);

  TextDocumentIdentifier({@required this.uri}) {
    if (uri == null) {
      throw 'uri is required but was not provided';
    }
  }
  static TextDocumentIdentifier fromJson(Map<String, dynamic> json) {
    if (VersionedTextDocumentIdentifier.canParse(json, nullLspJsonReporter)) {
      return VersionedTextDocumentIdentifier.fromJson(json);
    }
    if (OptionalVersionedTextDocumentIdentifier.canParse(
        json, nullLspJsonReporter)) {
      return OptionalVersionedTextDocumentIdentifier.fromJson(json);
    }
    final uri = json['uri'];
    return TextDocumentIdentifier(uri: uri);
  }

  /// The text document's URI.
  final String uri;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['uri'] = uri ?? (throw 'uri is required but was not set');
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('uri');
      try {
        if (!obj.containsKey('uri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['uri'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, uri.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class TextDocumentItem implements ToJsonable {
  static const jsonHandler =
      LspJsonHandler(TextDocumentItem.canParse, TextDocumentItem.fromJson);

  TextDocumentItem(
      {@required this.uri,
      @required this.languageId,
      @required this.version,
      @required this.text}) {
    if (uri == null) {
      throw 'uri is required but was not provided';
    }
    if (languageId == null) {
      throw 'languageId is required but was not provided';
    }
    if (version == null) {
      throw 'version is required but was not provided';
    }
    if (text == null) {
      throw 'text is required but was not provided';
    }
  }
  static TextDocumentItem fromJson(Map<String, dynamic> json) {
    final uri = json['uri'];
    final languageId = json['languageId'];
    final version = json['version'];
    final text = json['text'];
    return TextDocumentItem(
        uri: uri, languageId: languageId, version: version, text: text);
  }

  /// The text document's language identifier.
  final String languageId;

  /// The content of the opened text document.
  final String text;

  /// The text document's URI.
  final String uri;

  /// The version number of this document (it will increase after each change,
  /// including undo/redo).
  final num version;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['uri'] = uri ?? (throw 'uri is required but was not set');
    __result['languageId'] =
        languageId ?? (throw 'languageId is required but was not set');
    __result['version'] =
        version ?? (throw 'version is required but was not set');
    __result['text'] = text ?? (throw 'text is required but was not set');
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('uri');
      try {
        if (!obj.containsKey('uri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['uri'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['uri'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('languageId');
      try {
        if (!obj.containsKey('languageId')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['languageId'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['languageId'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('version');
      try {
        if (!obj.containsKey('version')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['version'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['version'] is num)) {
          reporter.reportError('must be of type num');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('text');
      try {
        if (!obj.containsKey('text')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['text'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['text'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TextDocumentItem');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is TextDocumentItem && other.runtimeType == TextDocumentItem) {
      return uri == other.uri &&
          languageId == other.languageId &&
          version == other.version &&
          text == other.text &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, uri.hashCode);
    hash = JenkinsSmiHash.combine(hash, languageId.hashCode);
    hash = JenkinsSmiHash.combine(hash, version.hashCode);
    hash = JenkinsSmiHash.combine(hash, text.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class TextDocumentPositionParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
      TextDocumentPositionParams.canParse, TextDocumentPositionParams.fromJson);

  TextDocumentPositionParams(
      {@required this.textDocument, @required this.position}) {
    if (textDocument == null) {
      throw 'textDocument is required but was not provided';
    }
    if (position == null) {
      throw 'position is required but was not provided';
    }
  }
  static TextDocumentPositionParams fromJson(Map<String, dynamic> json) {
    if (CompletionParams.canParse(json, nullLspJsonReporter)) {
      return CompletionParams.fromJson(json);
    }
    if (HoverParams.canParse(json, nullLspJsonReporter)) {
      return HoverParams.fromJson(json);
    }
    if (SignatureHelpParams.canParse(json, nullLspJsonReporter)) {
      return SignatureHelpParams.fromJson(json);
    }
    if (DeclarationParams.canParse(json, nullLspJsonReporter)) {
      return DeclarationParams.fromJson(json);
    }
    if (DefinitionParams.canParse(json, nullLspJsonReporter)) {
      return DefinitionParams.fromJson(json);
    }
    if (TypeDefinitionParams.canParse(json, nullLspJsonReporter)) {
      return TypeDefinitionParams.fromJson(json);
    }
    if (ImplementationParams.canParse(json, nullLspJsonReporter)) {
      return ImplementationParams.fromJson(json);
    }
    if (ReferenceParams.canParse(json, nullLspJsonReporter)) {
      return ReferenceParams.fromJson(json);
    }
    if (DocumentHighlightParams.canParse(json, nullLspJsonReporter)) {
      return DocumentHighlightParams.fromJson(json);
    }
    if (DocumentOnTypeFormattingParams.canParse(json, nullLspJsonReporter)) {
      return DocumentOnTypeFormattingParams.fromJson(json);
    }
    if (RenameParams.canParse(json, nullLspJsonReporter)) {
      return RenameParams.fromJson(json);
    }
    if (PrepareRenameParams.canParse(json, nullLspJsonReporter)) {
      return PrepareRenameParams.fromJson(json);
    }
    if (CallHierarchyPrepareParams.canParse(json, nullLspJsonReporter)) {
      return CallHierarchyPrepareParams.fromJson(json);
    }
    if (LinkedEditingRangeParams.canParse(json, nullLspJsonReporter)) {
      return LinkedEditingRangeParams.fromJson(json);
    }
    if (MonikerParams.canParse(json, nullLspJsonReporter)) {
      return MonikerParams.fromJson(json);
    }
    final textDocument = json['textDocument'] != null
        ? TextDocumentIdentifier.fromJson(json['textDocument'])
        : null;
    final position =
        json['position'] != null ? Position.fromJson(json['position']) : null;
    return TextDocumentPositionParams(
        textDocument: textDocument, position: position);
  }

  /// The position inside the text document.
  final Position position;

  /// The text document.
  final TextDocumentIdentifier textDocument;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['textDocument'] = textDocument?.toJson() ??
        (throw 'textDocument is required but was not set');
    __result['position'] =
        position?.toJson() ?? (throw 'position is required but was not set');
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['textDocument'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(TextDocumentIdentifier.canParse(obj['textDocument'], reporter))) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('position');
      try {
        if (!obj.containsKey('position')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['position'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(Position.canParse(obj['position'], reporter))) {
          reporter.reportError('must be of type Position');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TextDocumentPositionParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is TextDocumentPositionParams &&
        other.runtimeType == TextDocumentPositionParams) {
      return textDocument == other.textDocument &&
          position == other.position &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, textDocument.hashCode);
    hash = JenkinsSmiHash.combine(hash, position.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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, dynamic> json) {
    if (TextDocumentChangeRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return TextDocumentChangeRegistrationOptions.fromJson(json);
    }
    if (TextDocumentSaveRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return TextDocumentSaveRegistrationOptions.fromJson(json);
    }
    if (CompletionRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return CompletionRegistrationOptions.fromJson(json);
    }
    if (HoverRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return HoverRegistrationOptions.fromJson(json);
    }
    if (SignatureHelpRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return SignatureHelpRegistrationOptions.fromJson(json);
    }
    if (DeclarationRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DeclarationRegistrationOptions.fromJson(json);
    }
    if (DefinitionRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DefinitionRegistrationOptions.fromJson(json);
    }
    if (TypeDefinitionRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return TypeDefinitionRegistrationOptions.fromJson(json);
    }
    if (ImplementationRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return ImplementationRegistrationOptions.fromJson(json);
    }
    if (ReferenceRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return ReferenceRegistrationOptions.fromJson(json);
    }
    if (DocumentHighlightRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return DocumentHighlightRegistrationOptions.fromJson(json);
    }
    if (DocumentSymbolRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentSymbolRegistrationOptions.fromJson(json);
    }
    if (CodeActionRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return CodeActionRegistrationOptions.fromJson(json);
    }
    if (CodeLensRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return CodeLensRegistrationOptions.fromJson(json);
    }
    if (DocumentLinkRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentLinkRegistrationOptions.fromJson(json);
    }
    if (DocumentColorRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentColorRegistrationOptions.fromJson(json);
    }
    if (DocumentFormattingRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return DocumentFormattingRegistrationOptions.fromJson(json);
    }
    if (DocumentRangeFormattingRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return DocumentRangeFormattingRegistrationOptions.fromJson(json);
    }
    if (DocumentOnTypeFormattingRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return DocumentOnTypeFormattingRegistrationOptions.fromJson(json);
    }
    if (RenameRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return RenameRegistrationOptions.fromJson(json);
    }
    if (FoldingRangeRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return FoldingRangeRegistrationOptions.fromJson(json);
    }
    if (SelectionRangeRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return SelectionRangeRegistrationOptions.fromJson(json);
    }
    if (CallHierarchyRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return CallHierarchyRegistrationOptions.fromJson(json);
    }
    if (SemanticTokensRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return SemanticTokensRegistrationOptions.fromJson(json);
    }
    if (LinkedEditingRangeRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return LinkedEditingRangeRegistrationOptions.fromJson(json);
    }
    if (MonikerRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return MonikerRegistrationOptions.fromJson(json);
    }
    final documentSelector = json['documentSelector']
        ?.map((item) => item != null ? DocumentFilter.fromJson(item) : null)
        ?.cast<DocumentFilter>()
        ?.toList();
    return TextDocumentRegistrationOptions(documentSelector: documentSelector);
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  final List<DocumentFilter> documentSelector;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['documentSelector'] = documentSelector;
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['documentSelector'] != null &&
            !((obj['documentSelector'] is List &&
                (obj['documentSelector'].every(
                    (item) => DocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<DocumentFilter>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TextDocumentRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is TextDocumentRegistrationOptions &&
        other.runtimeType == TextDocumentRegistrationOptions) {
      return listEqual(documentSelector, other.documentSelector,
              (DocumentFilter a, DocumentFilter b) => a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(documentSelector));
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Represents reasons why a text document is saved.
class TextDocumentSaveReason {
  const TextDocumentSaveReason(this._value);
  const TextDocumentSaveReason.fromJson(this._value);

  final num _value;

  static bool canParse(Object obj, LspJsonReporter reporter) {
    return obj is num;
  }

  /// Manually triggered, e.g. by the user pressing save, by starting debugging,
  /// or by an API call.
  static const Manual = TextDocumentSaveReason(1);

  /// Automatic after a delay.
  static const AfterDelay = TextDocumentSaveReason(2);

  /// When the editor lost focus.
  static const FocusOut = TextDocumentSaveReason(3);

  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  bool operator ==(Object o) =>
      o is TextDocumentSaveReason && o._value == _value;
}

class TextDocumentSaveRegistrationOptions
    implements TextDocumentRegistrationOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
      TextDocumentSaveRegistrationOptions.canParse,
      TextDocumentSaveRegistrationOptions.fromJson);

  TextDocumentSaveRegistrationOptions(
      {this.includeText, this.documentSelector});
  static TextDocumentSaveRegistrationOptions fromJson(
      Map<String, dynamic> json) {
    final includeText = json['includeText'];
    final documentSelector = json['documentSelector']
        ?.map((item) => item != null ? DocumentFilter.fromJson(item) : null)
        ?.cast<DocumentFilter>()
        ?.toList();
    return TextDocumentSaveRegistrationOptions(
        includeText: includeText, documentSelector: documentSelector);
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  final List<DocumentFilter> documentSelector;

  /// The client is supposed to include the content on save.
  final bool includeText;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (includeText != null) {
      __result['includeText'] = includeText;
    }
    __result['documentSelector'] = documentSelector;
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('includeText');
      try {
        if (obj['includeText'] != null && !(obj['includeText'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['documentSelector'] != null &&
            !((obj['documentSelector'] is List &&
                (obj['documentSelector'].every(
                    (item) => DocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<DocumentFilter>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter
          .reportError('must be of type TextDocumentSaveRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is TextDocumentSaveRegistrationOptions &&
        other.runtimeType == TextDocumentSaveRegistrationOptions) {
      return includeText == other.includeText &&
          listEqual(documentSelector, other.documentSelector,
              (DocumentFilter a, DocumentFilter b) => a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, includeText.hashCode);
    hash = JenkinsSmiHash.combine(hash, lspHashCode(documentSelector));
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class TextDocumentSyncClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
      TextDocumentSyncClientCapabilities.canParse,
      TextDocumentSyncClientCapabilities.fromJson);

  TextDocumentSyncClientCapabilities(
      {this.dynamicRegistration,
      this.willSave,
      this.willSaveWaitUntil,
      this.didSave});
  static TextDocumentSyncClientCapabilities fromJson(
      Map<String, dynamic> json) {
    final dynamicRegistration = json['dynamicRegistration'];
    final willSave = json['willSave'];
    final willSaveWaitUntil = json['willSaveWaitUntil'];
    final didSave = json['didSave'];
    return TextDocumentSyncClientCapabilities(
        dynamicRegistration: dynamicRegistration,
        willSave: willSave,
        willSaveWaitUntil: willSaveWaitUntil,
        didSave: didSave);
  }

  /// The client supports did save notifications.
  final bool didSave;

  /// Whether text document synchronization supports dynamic registration.
  final bool dynamicRegistration;

  /// The client supports sending will save notifications.
  final bool willSave;

  /// The client supports sending a will save request and waits for a response
  /// providing text edits which will be applied to the document before it is
  /// saved.
  final bool willSaveWaitUntil;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (dynamicRegistration != null) {
      __result['dynamicRegistration'] = dynamicRegistration;
    }
    if (willSave != null) {
      __result['willSave'] = willSave;
    }
    if (willSaveWaitUntil != null) {
      __result['willSaveWaitUntil'] = willSaveWaitUntil;
    }
    if (didSave != null) {
      __result['didSave'] = didSave;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('dynamicRegistration');
      try {
        if (obj['dynamicRegistration'] != null &&
            !(obj['dynamicRegistration'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('willSave');
      try {
        if (obj['willSave'] != null && !(obj['willSave'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('willSaveWaitUntil');
      try {
        if (obj['willSaveWaitUntil'] != null &&
            !(obj['willSaveWaitUntil'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('didSave');
      try {
        if (obj['didSave'] != null && !(obj['didSave'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter
          .reportError('must be of type TextDocumentSyncClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is TextDocumentSyncClientCapabilities &&
        other.runtimeType == TextDocumentSyncClientCapabilities) {
      return dynamicRegistration == other.dynamicRegistration &&
          willSave == other.willSave &&
          willSaveWaitUntil == other.willSaveWaitUntil &&
          didSave == other.didSave &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode);
    hash = JenkinsSmiHash.combine(hash, willSave.hashCode);
    hash = JenkinsSmiHash.combine(hash, willSaveWaitUntil.hashCode);
    hash = JenkinsSmiHash.combine(hash, didSave.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Defines how the host (editor) should sync document changes to the language
/// server.
class TextDocumentSyncKind {
  const TextDocumentSyncKind(this._value);
  const TextDocumentSyncKind.fromJson(this._value);

  final num _value;

  static bool canParse(Object obj, LspJsonReporter reporter) {
    return obj is num;
  }

  /// Documents should not be synced at all.
  static const None = TextDocumentSyncKind(0);

  /// Documents are synced by always sending the full content of the document.
  static const Full = TextDocumentSyncKind(1);

  /// Documents are synced by sending the full content on open. After that only
  /// incremental updates to the document are send.
  static const Incremental = TextDocumentSyncKind(2);

  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  bool operator ==(Object o) => o is TextDocumentSyncKind && o._value == _value;
}

class TextDocumentSyncOptions implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
      TextDocumentSyncOptions.canParse, TextDocumentSyncOptions.fromJson);

  TextDocumentSyncOptions(
      {this.openClose,
      this.change,
      this.willSave,
      this.willSaveWaitUntil,
      this.save});
  static TextDocumentSyncOptions fromJson(Map<String, dynamic> json) {
    final openClose = json['openClose'];
    final change = json['change'] != null
        ? TextDocumentSyncKind.fromJson(json['change'])
        : null;
    final willSave = json['willSave'];
    final willSaveWaitUntil = json['willSaveWaitUntil'];
    final save = json['save'] is bool
        ? Either2<bool, SaveOptions>.t1(json['save'])
        : (SaveOptions.canParse(json['save'], nullLspJsonReporter)
            ? Either2<bool, SaveOptions>.t2(json['save'] != null
                ? SaveOptions.fromJson(json['save'])
                : null)
            : (json['save'] == null
                ? null
                : (throw '''${json['save']} was not one of (bool, SaveOptions)''')));
    return TextDocumentSyncOptions(
        openClose: openClose,
        change: change,
        willSave: willSave,
        willSaveWaitUntil: willSaveWaitUntil,
        save: save);
  }

  /// Change notifications are sent to the server. See
  /// TextDocumentSyncKind.None, TextDocumentSyncKind.Full and
  /// TextDocumentSyncKind.Incremental. If omitted it defaults to
  /// TextDocumentSyncKind.None.
  final TextDocumentSyncKind change;

  /// Open and close notifications are sent to the server. If omitted open close
  /// notification should not be sent.
  final bool openClose;

  /// If present save notifications are sent to the server. If omitted the
  /// notification should not be sent.
  final Either2<bool, SaveOptions> save;

  /// If present will save notifications are sent to the server. If omitted the
  /// notification should not be sent.
  final bool willSave;

  /// If present will save wait until requests are sent to the server. If
  /// omitted the request should not be sent.
  final bool willSaveWaitUntil;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (openClose != null) {
      __result['openClose'] = openClose;
    }
    if (change != null) {
      __result['change'] = change.toJson();
    }
    if (willSave != null) {
      __result['willSave'] = willSave;
    }
    if (willSaveWaitUntil != null) {
      __result['willSaveWaitUntil'] = willSaveWaitUntil;
    }
    if (save != null) {
      __result['save'] = save;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('openClose');
      try {
        if (obj['openClose'] != null && !(obj['openClose'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('change');
      try {
        if (obj['change'] != null &&
            !(TextDocumentSyncKind.canParse(obj['change'], reporter))) {
          reporter.reportError('must be of type TextDocumentSyncKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('willSave');
      try {
        if (obj['willSave'] != null && !(obj['willSave'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('willSaveWaitUntil');
      try {
        if (obj['willSaveWaitUntil'] != null &&
            !(obj['willSaveWaitUntil'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('save');
      try {
        if (obj['save'] != null &&
            !((obj['save'] is bool ||
                SaveOptions.canParse(obj['save'], reporter)))) {
          reporter.reportError('must be of type Either2<bool, SaveOptions>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TextDocumentSyncOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is TextDocumentSyncOptions &&
        other.runtimeType == TextDocumentSyncOptions) {
      return openClose == other.openClose &&
          change == other.change &&
          willSave == other.willSave &&
          willSaveWaitUntil == other.willSaveWaitUntil &&
          save == other.save &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, openClose.hashCode);
    hash = JenkinsSmiHash.combine(hash, change.hashCode);
    hash = JenkinsSmiHash.combine(hash, willSave.hashCode);
    hash = JenkinsSmiHash.combine(hash, willSaveWaitUntil.hashCode);
    hash = JenkinsSmiHash.combine(hash, save.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class TextEdit implements ToJsonable {
  static const jsonHandler =
      LspJsonHandler(TextEdit.canParse, TextEdit.fromJson);

  TextEdit({@required this.range, @required this.newText}) {
    if (range == null) {
      throw 'range is required but was not provided';
    }
    if (newText == null) {
      throw 'newText is required but was not provided';
    }
  }
  static TextEdit fromJson(Map<String, dynamic> json) {
    if (AnnotatedTextEdit.canParse(json, nullLspJsonReporter)) {
      return AnnotatedTextEdit.fromJson(json);
    }
    final range = json['range'] != null ? Range.fromJson(json['range']) : null;
    final newText = json['newText'];
    return TextEdit(range: range, newText: newText);
  }

  /// The string to be inserted. For delete operations use an empty string.
  final String newText;

  /// The range of the text document to be manipulated. To insert text into a
  /// document create a range where start === end.
  final Range range;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['range'] =
        range?.toJson() ?? (throw 'range is required but was not set');
    __result['newText'] =
        newText ?? (throw 'newText is required but was not set');
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('range');
      try {
        if (!obj.containsKey('range')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['range'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(Range.canParse(obj['range'], reporter))) {
          reporter.reportError('must be of type Range');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('newText');
      try {
        if (!obj.containsKey('newText')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['newText'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['newText'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TextEdit');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is TextEdit && other.runtimeType == TextEdit) {
      return range == other.range && newText == other.newText && true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, range.hashCode);
    hash = JenkinsSmiHash.combine(hash, newText.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class TokenFormat {
  const TokenFormat(this._value);
  const TokenFormat.fromJson(this._value);

  final String _value;

  static bool canParse(Object obj, LspJsonReporter reporter) {
    return obj is String;
  }

  static const Relative = TokenFormat(r'relative');

  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  bool operator ==(Object o) => o is TokenFormat && o._value == _value;
}

class TypeDefinitionClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
      TypeDefinitionClientCapabilities.canParse,
      TypeDefinitionClientCapabilities.fromJson);

  TypeDefinitionClientCapabilities(
      {this.dynamicRegistration, this.linkSupport});
  static TypeDefinitionClientCapabilities fromJson(Map<String, dynamic> json) {
    final dynamicRegistration = json['dynamicRegistration'];
    final linkSupport = json['linkSupport'];
    return TypeDefinitionClientCapabilities(
        dynamicRegistration: dynamicRegistration, linkSupport: linkSupport);
  }

  /// Whether implementation supports dynamic registration. If this is set to
  /// `true` the client supports the new `TypeDefinitionRegistrationOptions`
  /// return value for the corresponding server capability as well.
  final bool dynamicRegistration;

  /// The client supports additional metadata in the form of definition links.
  ///  @since 3.14.0
  final bool linkSupport;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    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, dynamic>) {
      reporter.push('dynamicRegistration');
      try {
        if (obj['dynamicRegistration'] != null &&
            !(obj['dynamicRegistration'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('linkSupport');
      try {
        if (obj['linkSupport'] != null && !(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode);
    hash = JenkinsSmiHash.combine(hash, linkSupport.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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, dynamic> json) {
    if (TypeDefinitionRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return TypeDefinitionRegistrationOptions.fromJson(json);
    }
    final workDoneProgress = json['workDoneProgress'];
    return TypeDefinitionOptions(workDoneProgress: workDoneProgress);
  }

  final bool workDoneProgress;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('workDoneProgress');
      try {
        if (obj['workDoneProgress'] != null &&
            !(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class TypeDefinitionParams
    implements
        TextDocumentPositionParams,
        WorkDoneProgressParams,
        PartialResultParams,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
      TypeDefinitionParams.canParse, TypeDefinitionParams.fromJson);

  TypeDefinitionParams(
      {@required this.textDocument,
      @required this.position,
      this.workDoneToken,
      this.partialResultToken}) {
    if (textDocument == null) {
      throw 'textDocument is required but was not provided';
    }
    if (position == null) {
      throw 'position is required but was not provided';
    }
  }
  static TypeDefinitionParams fromJson(Map<String, dynamic> json) {
    final textDocument = json['textDocument'] != null
        ? TextDocumentIdentifier.fromJson(json['textDocument'])
        : null;
    final position =
        json['position'] != null ? Position.fromJson(json['position']) : null;
    final workDoneToken = json['workDoneToken'] is num
        ? Either2<num, String>.t1(json['workDoneToken'])
        : (json['workDoneToken'] is String
            ? Either2<num, String>.t2(json['workDoneToken'])
            : (json['workDoneToken'] == null
                ? null
                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
    final partialResultToken = json['partialResultToken'] is num
        ? Either2<num, String>.t1(json['partialResultToken'])
        : (json['partialResultToken'] is String
            ? Either2<num, String>.t2(json['partialResultToken'])
            : (json['partialResultToken'] == null
                ? null
                : (throw '''${json['partialResultToken']} was not one of (num, String)''')));
    return TypeDefinitionParams(
        textDocument: textDocument,
        position: position,
        workDoneToken: workDoneToken,
        partialResultToken: partialResultToken);
  }

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  final Either2<num, String> partialResultToken;

  /// The position inside the text document.
  final Position position;

  /// The text document.
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  final Either2<num, String> workDoneToken;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['textDocument'] = textDocument?.toJson() ??
        (throw 'textDocument is required but was not set');
    __result['position'] =
        position?.toJson() ?? (throw 'position is required but was not set');
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    if (partialResultToken != null) {
      __result['partialResultToken'] = partialResultToken;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['textDocument'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(TextDocumentIdentifier.canParse(obj['textDocument'], reporter))) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('position');
      try {
        if (!obj.containsKey('position')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['position'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(Position.canParse(obj['position'], reporter))) {
          reporter.reportError('must be of type Position');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        if (obj['workDoneToken'] != null &&
            !((obj['workDoneToken'] is num ||
                obj['workDoneToken'] is String))) {
          reporter.reportError('must be of type Either2<num, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('partialResultToken');
      try {
        if (obj['partialResultToken'] != null &&
            !((obj['partialResultToken'] is num ||
                obj['partialResultToken'] is String))) {
          reporter.reportError('must be of type Either2<num, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TypeDefinitionParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is TypeDefinitionParams &&
        other.runtimeType == TypeDefinitionParams) {
      return textDocument == other.textDocument &&
          position == other.position &&
          workDoneToken == other.workDoneToken &&
          partialResultToken == other.partialResultToken &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, textDocument.hashCode);
    hash = JenkinsSmiHash.combine(hash, position.hashCode);
    hash = JenkinsSmiHash.combine(hash, workDoneToken.hashCode);
    hash = JenkinsSmiHash.combine(hash, partialResultToken.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class TypeDefinitionRegistrationOptions
    implements
        TextDocumentRegistrationOptions,
        TypeDefinitionOptions,
        StaticRegistrationOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
      TypeDefinitionRegistrationOptions.canParse,
      TypeDefinitionRegistrationOptions.fromJson);

  TypeDefinitionRegistrationOptions(
      {this.documentSelector, this.workDoneProgress, this.id});
  static TypeDefinitionRegistrationOptions fromJson(Map<String, dynamic> json) {
    final documentSelector = json['documentSelector']
        ?.map((item) => item != null ? DocumentFilter.fromJson(item) : null)
        ?.cast<DocumentFilter>()
        ?.toList();
    final workDoneProgress = json['workDoneProgress'];
    final id = json['id'];
    return TypeDefinitionRegistrationOptions(
        documentSelector: documentSelector,
        workDoneProgress: workDoneProgress,
        id: id);
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  final List<DocumentFilter> documentSelector;

  /// The id used to register the request. The id can be used to deregister the
  /// request again. See also Registration#id.
  final String id;
  final bool workDoneProgress;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['documentSelector'] = documentSelector;
    if (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    if (id != null) {
      __result['id'] = id;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('documentSelector');
      try {
        if (!obj.containsKey('documentSelector')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['documentSelector'] != null &&
            !((obj['documentSelector'] is List &&
                (obj['documentSelector'].every(
                    (item) => DocumentFilter.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<DocumentFilter>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneProgress');
      try {
        if (obj['workDoneProgress'] != null &&
            !(obj['workDoneProgress'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('id');
      try {
        if (obj['id'] != null && !(obj['id'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type TypeDefinitionRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is TypeDefinitionRegistrationOptions &&
        other.runtimeType == TypeDefinitionRegistrationOptions) {
      return listEqual(documentSelector, other.documentSelector,
              (DocumentFilter a, DocumentFilter b) => a == b) &&
          workDoneProgress == other.workDoneProgress &&
          id == other.id &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(documentSelector));
    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
    hash = JenkinsSmiHash.combine(hash, id.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Moniker uniqueness level to define scope of the moniker.
class UniquenessLevel {
  const UniquenessLevel(this._value);
  const UniquenessLevel.fromJson(this._value);

  final String _value;

  static bool canParse(Object obj, LspJsonReporter reporter) {
    return obj is String;
  }

  /// The moniker is only unique inside a document
  static const document = UniquenessLevel(r'document');

  /// The moniker is unique inside a project for which a dump got created
  static const project = UniquenessLevel(r'project');

  /// The moniker is unique inside the group to which a project belongs
  static const group = UniquenessLevel(r'group');

  /// The moniker is unique inside the moniker scheme.
  static const scheme = UniquenessLevel(r'scheme');

  /// The moniker is globally unique
  static const global = UniquenessLevel(r'global');

  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  bool operator ==(Object o) => o is UniquenessLevel && o._value == _value;
}

/// General parameters to unregister a capability.
class Unregistration implements ToJsonable {
  static const jsonHandler =
      LspJsonHandler(Unregistration.canParse, Unregistration.fromJson);

  Unregistration({@required this.id, @required this.method}) {
    if (id == null) {
      throw 'id is required but was not provided';
    }
    if (method == null) {
      throw 'method is required but was not provided';
    }
  }
  static Unregistration fromJson(Map<String, dynamic> json) {
    final id = json['id'];
    final method = json['method'];
    return Unregistration(id: id, method: method);
  }

  /// The id used to unregister the request or notification. Usually an id
  /// provided during the register request.
  final String id;

  /// The method / capability to unregister for.
  final String method;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['id'] = id ?? (throw 'id is required but was not set');
    __result['method'] = method ?? (throw 'method is required but was not set');
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('id');
      try {
        if (!obj.containsKey('id')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['id'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['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;
        }
        if (obj['method'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, id.hashCode);
    hash = JenkinsSmiHash.combine(hash, method.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class UnregistrationParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
      UnregistrationParams.canParse, UnregistrationParams.fromJson);

  UnregistrationParams({@required this.unregisterations}) {
    if (unregisterations == null) {
      throw 'unregisterations is required but was not provided';
    }
  }
  static UnregistrationParams fromJson(Map<String, dynamic> json) {
    final unregisterations = json['unregisterations']
        ?.map((item) => item != null ? Unregistration.fromJson(item) : null)
        ?.cast<Unregistration>()
        ?.toList();
    return UnregistrationParams(unregisterations: unregisterations);
  }

  /// This should correctly be named `unregistrations`. However changing this //
  /// is a breaking change and needs to wait until we deliver a 4.x version //
  /// of the specification.
  final List<Unregistration> unregisterations;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['unregisterations'] =
        unregisterations?.map((item) => item.toJson())?.toList() ??
            (throw 'unregisterations is required but was not set');
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('unregisterations');
      try {
        if (!obj.containsKey('unregisterations')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['unregisterations'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!((obj['unregisterations'] is List &&
            (obj['unregisterations']
                .every((item) => Unregistration.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<Unregistration>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type UnregistrationParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is UnregistrationParams &&
        other.runtimeType == UnregistrationParams) {
      return listEqual(unregisterations, other.unregisterations,
              (Unregistration a, Unregistration b) => a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(unregisterations));
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class VersionedTextDocumentIdentifier
    implements TextDocumentIdentifier, ToJsonable {
  static const jsonHandler = LspJsonHandler(
      VersionedTextDocumentIdentifier.canParse,
      VersionedTextDocumentIdentifier.fromJson);

  VersionedTextDocumentIdentifier(
      {@required this.version, @required this.uri}) {
    if (version == null) {
      throw 'version is required but was not provided';
    }
    if (uri == null) {
      throw 'uri is required but was not provided';
    }
  }
  static VersionedTextDocumentIdentifier fromJson(Map<String, dynamic> json) {
    final version = json['version'];
    final uri = json['uri'];
    return VersionedTextDocumentIdentifier(version: version, uri: uri);
  }

  /// The text document's URI.
  final String uri;

  /// The version number of this document.
  ///
  /// The version number of a document will increase after each change,
  /// including undo/redo. The number doesn't need to be consecutive.
  final num version;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['version'] =
        version ?? (throw 'version is required but was not set');
    __result['uri'] = uri ?? (throw 'uri is required but was not set');
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('version');
      try {
        if (!obj.containsKey('version')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['version'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['version'] is num)) {
          reporter.reportError('must be of type num');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('uri');
      try {
        if (!obj.containsKey('uri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['uri'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['uri'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type VersionedTextDocumentIdentifier');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is VersionedTextDocumentIdentifier &&
        other.runtimeType == VersionedTextDocumentIdentifier) {
      return version == other.version && uri == other.uri && true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, version.hashCode);
    hash = JenkinsSmiHash.combine(hash, uri.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WatchKind {
  const WatchKind(this._value);
  const WatchKind.fromJson(this._value);

  final num _value;

  static bool canParse(Object obj, LspJsonReporter reporter) {
    return obj is num;
  }

  /// Interested in create events.
  static const Create = WatchKind(1);

  /// Interested in change events
  static const Change = WatchKind(2);

  /// Interested in delete events
  static const Delete = WatchKind(4);

  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  bool operator ==(Object o) => o is WatchKind && o._value == _value;
}

/// The parameters send in a will save text document notification.
class WillSaveTextDocumentParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
      WillSaveTextDocumentParams.canParse, WillSaveTextDocumentParams.fromJson);

  WillSaveTextDocumentParams(
      {@required this.textDocument, @required this.reason}) {
    if (textDocument == null) {
      throw 'textDocument is required but was not provided';
    }
    if (reason == null) {
      throw 'reason is required but was not provided';
    }
  }
  static WillSaveTextDocumentParams fromJson(Map<String, dynamic> json) {
    final textDocument = json['textDocument'] != null
        ? TextDocumentIdentifier.fromJson(json['textDocument'])
        : null;
    final reason = json['reason'] != null
        ? TextDocumentSaveReason.fromJson(json['reason'])
        : null;
    return WillSaveTextDocumentParams(
        textDocument: textDocument, reason: reason);
  }

  /// The 'TextDocumentSaveReason'.
  final TextDocumentSaveReason reason;

  /// The document that will be saved.
  final TextDocumentIdentifier textDocument;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['textDocument'] = textDocument?.toJson() ??
        (throw 'textDocument is required but was not set');
    __result['reason'] =
        reason?.toJson() ?? (throw 'reason is required but was not set');
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('textDocument');
      try {
        if (!obj.containsKey('textDocument')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['textDocument'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(TextDocumentIdentifier.canParse(obj['textDocument'], reporter))) {
          reporter.reportError('must be of type TextDocumentIdentifier');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('reason');
      try {
        if (!obj.containsKey('reason')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['reason'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(TextDocumentSaveReason.canParse(obj['reason'], reporter))) {
          reporter.reportError('must be of type TextDocumentSaveReason');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type WillSaveTextDocumentParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is WillSaveTextDocumentParams &&
        other.runtimeType == WillSaveTextDocumentParams) {
      return textDocument == other.textDocument &&
          reason == other.reason &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, textDocument.hashCode);
    hash = JenkinsSmiHash.combine(hash, reason.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WorkDoneProgressBegin implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
      WorkDoneProgressBegin.canParse, WorkDoneProgressBegin.fromJson);

  WorkDoneProgressBegin(
      {this.kind = 'begin',
      @required this.title,
      this.cancellable,
      this.message,
      this.percentage}) {
    if (kind != 'begin') {
      throw 'kind may only be the literal \'begin\'';
    }
    if (title == null) {
      throw 'title is required but was not provided';
    }
  }
  static WorkDoneProgressBegin fromJson(Map<String, dynamic> json) {
    final kind = json['kind'];
    final title = json['title'];
    final cancellable = json['cancellable'];
    final message = json['message'];
    final percentage = json['percentage'];
    return WorkDoneProgressBegin(
        kind: kind,
        title: title,
        cancellable: cancellable,
        message: message,
        percentage: percentage);
  }

  /// Controls if a cancel button should show to allow the user to cancel the
  /// long running operation. Clients that don't support cancellation are
  /// allowed to ignore the setting.
  final bool cancellable;
  final String kind;

  /// Optional, more detailed associated progress message. Contains
  /// complementary information to the `title`.
  ///
  /// Examples: "3/25 files", "project/src/module2", "node_modules/some_dep". If
  /// unset, the previous progress message (if any) is still valid.
  final String message;

  /// Optional progress percentage to display (value 100 is considered 100%). If
  /// not provided infinite progress is assumed and clients are allowed to
  /// ignore the `percentage` value in subsequent in report notifications.
  ///
  /// The value should be steadily rising. Clients are free to ignore values
  /// that are not following this rule. The value range is [0, 100]
  final num percentage;

  /// Mandatory title of the progress operation. Used to briefly inform about
  /// the kind of operation being performed.
  ///
  /// Examples: "Indexing" or "Linking dependencies".
  final String title;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['kind'] = kind ?? (throw 'kind is required but was not set');
    __result['title'] = title ?? (throw 'title is required but was not set');
    if (cancellable != null) {
      __result['cancellable'] = cancellable;
    }
    if (message != null) {
      __result['message'] = message;
    }
    if (percentage != null) {
      __result['percentage'] = percentage;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('kind');
      try {
        if (!obj.containsKey('kind')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['kind'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['kind'] == 'begin')) {
          reporter.reportError('must be the literal \'begin\'');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('title');
      try {
        if (!obj.containsKey('title')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['title'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['title'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('cancellable');
      try {
        if (obj['cancellable'] != null && !(obj['cancellable'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('message');
      try {
        if (obj['message'] != null && !(obj['message'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('percentage');
      try {
        if (obj['percentage'] != null && !(obj['percentage'] is num)) {
          reporter.reportError('must be of type num');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type WorkDoneProgressBegin');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is WorkDoneProgressBegin &&
        other.runtimeType == WorkDoneProgressBegin) {
      return kind == other.kind &&
          title == other.title &&
          cancellable == other.cancellable &&
          message == other.message &&
          percentage == other.percentage &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, kind.hashCode);
    hash = JenkinsSmiHash.combine(hash, title.hashCode);
    hash = JenkinsSmiHash.combine(hash, cancellable.hashCode);
    hash = JenkinsSmiHash.combine(hash, message.hashCode);
    hash = JenkinsSmiHash.combine(hash, percentage.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WorkDoneProgressCancelParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
      WorkDoneProgressCancelParams.canParse,
      WorkDoneProgressCancelParams.fromJson);

  WorkDoneProgressCancelParams({@required this.token}) {
    if (token == null) {
      throw 'token is required but was not provided';
    }
  }
  static WorkDoneProgressCancelParams fromJson(Map<String, dynamic> json) {
    final token = json['token'] is num
        ? Either2<num, String>.t1(json['token'])
        : (json['token'] is String
            ? Either2<num, String>.t2(json['token'])
            : (throw '''${json['token']} was not one of (num, String)'''));
    return WorkDoneProgressCancelParams(token: token);
  }

  /// The token to be used to report progress.
  final Either2<num, String> token;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['token'] = token ?? (throw 'token is required but was not set');
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('token');
      try {
        if (!obj.containsKey('token')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['token'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!((obj['token'] is num || obj['token'] is String))) {
          reporter.reportError('must be of type Either2<num, 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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, token.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WorkDoneProgressCreateParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
      WorkDoneProgressCreateParams.canParse,
      WorkDoneProgressCreateParams.fromJson);

  WorkDoneProgressCreateParams({@required this.token}) {
    if (token == null) {
      throw 'token is required but was not provided';
    }
  }
  static WorkDoneProgressCreateParams fromJson(Map<String, dynamic> json) {
    final token = json['token'] is num
        ? Either2<num, String>.t1(json['token'])
        : (json['token'] is String
            ? Either2<num, String>.t2(json['token'])
            : (throw '''${json['token']} was not one of (num, String)'''));
    return WorkDoneProgressCreateParams(token: token);
  }

  /// The token to be used to report progress.
  final Either2<num, String> token;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['token'] = token ?? (throw 'token is required but was not set');
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('token');
      try {
        if (!obj.containsKey('token')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['token'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!((obj['token'] is num || obj['token'] is String))) {
          reporter.reportError('must be of type Either2<num, 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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, token.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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, dynamic> json) {
    final kind = json['kind'];
    final message = json['message'];
    return WorkDoneProgressEnd(kind: kind, message: message);
  }

  final String kind;

  /// Optional, a final message indicating to for example indicate the outcome
  /// of the operation.
  final String message;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['kind'] = kind ?? (throw 'kind is required but was not set');
    if (message != null) {
      __result['message'] = message;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('kind');
      try {
        if (!obj.containsKey('kind')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['kind'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['kind'] == 'end')) {
          reporter.reportError('must be the literal \'end\'');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('message');
      try {
        if (obj['message'] != null && !(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, kind.hashCode);
    hash = JenkinsSmiHash.combine(hash, message.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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, dynamic> json) {
    if (WorkspaceSymbolOptions.canParse(json, nullLspJsonReporter)) {
      return WorkspaceSymbolOptions.fromJson(json);
    }
    if (ExecuteCommandOptions.canParse(json, nullLspJsonReporter)) {
      return ExecuteCommandOptions.fromJson(json);
    }
    if (CompletionOptions.canParse(json, nullLspJsonReporter)) {
      return CompletionOptions.fromJson(json);
    }
    if (HoverOptions.canParse(json, nullLspJsonReporter)) {
      return HoverOptions.fromJson(json);
    }
    if (SignatureHelpOptions.canParse(json, nullLspJsonReporter)) {
      return SignatureHelpOptions.fromJson(json);
    }
    if (DeclarationOptions.canParse(json, nullLspJsonReporter)) {
      return DeclarationOptions.fromJson(json);
    }
    if (DefinitionOptions.canParse(json, nullLspJsonReporter)) {
      return DefinitionOptions.fromJson(json);
    }
    if (TypeDefinitionOptions.canParse(json, nullLspJsonReporter)) {
      return TypeDefinitionOptions.fromJson(json);
    }
    if (ImplementationOptions.canParse(json, nullLspJsonReporter)) {
      return ImplementationOptions.fromJson(json);
    }
    if (ReferenceOptions.canParse(json, nullLspJsonReporter)) {
      return ReferenceOptions.fromJson(json);
    }
    if (DocumentHighlightOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentHighlightOptions.fromJson(json);
    }
    if (DocumentSymbolOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentSymbolOptions.fromJson(json);
    }
    if (CodeActionOptions.canParse(json, nullLspJsonReporter)) {
      return CodeActionOptions.fromJson(json);
    }
    if (CodeLensOptions.canParse(json, nullLspJsonReporter)) {
      return CodeLensOptions.fromJson(json);
    }
    if (DocumentLinkOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentLinkOptions.fromJson(json);
    }
    if (DocumentColorOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentColorOptions.fromJson(json);
    }
    if (DocumentFormattingOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentFormattingOptions.fromJson(json);
    }
    if (DocumentRangeFormattingOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentRangeFormattingOptions.fromJson(json);
    }
    if (RenameOptions.canParse(json, nullLspJsonReporter)) {
      return RenameOptions.fromJson(json);
    }
    if (FoldingRangeOptions.canParse(json, nullLspJsonReporter)) {
      return FoldingRangeOptions.fromJson(json);
    }
    if (SelectionRangeOptions.canParse(json, nullLspJsonReporter)) {
      return SelectionRangeOptions.fromJson(json);
    }
    if (CallHierarchyOptions.canParse(json, nullLspJsonReporter)) {
      return CallHierarchyOptions.fromJson(json);
    }
    if (SemanticTokensOptions.canParse(json, nullLspJsonReporter)) {
      return SemanticTokensOptions.fromJson(json);
    }
    if (LinkedEditingRangeOptions.canParse(json, nullLspJsonReporter)) {
      return LinkedEditingRangeOptions.fromJson(json);
    }
    if (MonikerOptions.canParse(json, nullLspJsonReporter)) {
      return MonikerOptions.fromJson(json);
    }
    final workDoneProgress = json['workDoneProgress'];
    return WorkDoneProgressOptions(workDoneProgress: workDoneProgress);
  }

  final bool workDoneProgress;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('workDoneProgress');
      try {
        if (obj['workDoneProgress'] != null &&
            !(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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, dynamic> json) {
    if (InitializeParams.canParse(json, nullLspJsonReporter)) {
      return InitializeParams.fromJson(json);
    }
    if (WorkspaceSymbolParams.canParse(json, nullLspJsonReporter)) {
      return WorkspaceSymbolParams.fromJson(json);
    }
    if (ExecuteCommandParams.canParse(json, nullLspJsonReporter)) {
      return ExecuteCommandParams.fromJson(json);
    }
    if (CompletionParams.canParse(json, nullLspJsonReporter)) {
      return CompletionParams.fromJson(json);
    }
    if (HoverParams.canParse(json, nullLspJsonReporter)) {
      return HoverParams.fromJson(json);
    }
    if (SignatureHelpParams.canParse(json, nullLspJsonReporter)) {
      return SignatureHelpParams.fromJson(json);
    }
    if (DeclarationParams.canParse(json, nullLspJsonReporter)) {
      return DeclarationParams.fromJson(json);
    }
    if (DefinitionParams.canParse(json, nullLspJsonReporter)) {
      return DefinitionParams.fromJson(json);
    }
    if (TypeDefinitionParams.canParse(json, nullLspJsonReporter)) {
      return TypeDefinitionParams.fromJson(json);
    }
    if (ImplementationParams.canParse(json, nullLspJsonReporter)) {
      return ImplementationParams.fromJson(json);
    }
    if (ReferenceParams.canParse(json, nullLspJsonReporter)) {
      return ReferenceParams.fromJson(json);
    }
    if (DocumentHighlightParams.canParse(json, nullLspJsonReporter)) {
      return DocumentHighlightParams.fromJson(json);
    }
    if (DocumentSymbolParams.canParse(json, nullLspJsonReporter)) {
      return DocumentSymbolParams.fromJson(json);
    }
    if (CodeActionParams.canParse(json, nullLspJsonReporter)) {
      return CodeActionParams.fromJson(json);
    }
    if (CodeLensParams.canParse(json, nullLspJsonReporter)) {
      return CodeLensParams.fromJson(json);
    }
    if (DocumentLinkParams.canParse(json, nullLspJsonReporter)) {
      return DocumentLinkParams.fromJson(json);
    }
    if (DocumentColorParams.canParse(json, nullLspJsonReporter)) {
      return DocumentColorParams.fromJson(json);
    }
    if (ColorPresentationParams.canParse(json, nullLspJsonReporter)) {
      return ColorPresentationParams.fromJson(json);
    }
    if (DocumentFormattingParams.canParse(json, nullLspJsonReporter)) {
      return DocumentFormattingParams.fromJson(json);
    }
    if (DocumentRangeFormattingParams.canParse(json, nullLspJsonReporter)) {
      return DocumentRangeFormattingParams.fromJson(json);
    }
    if (RenameParams.canParse(json, nullLspJsonReporter)) {
      return RenameParams.fromJson(json);
    }
    if (FoldingRangeParams.canParse(json, nullLspJsonReporter)) {
      return FoldingRangeParams.fromJson(json);
    }
    if (SelectionRangeParams.canParse(json, nullLspJsonReporter)) {
      return SelectionRangeParams.fromJson(json);
    }
    if (CallHierarchyPrepareParams.canParse(json, nullLspJsonReporter)) {
      return CallHierarchyPrepareParams.fromJson(json);
    }
    if (CallHierarchyIncomingCallsParams.canParse(json, nullLspJsonReporter)) {
      return CallHierarchyIncomingCallsParams.fromJson(json);
    }
    if (CallHierarchyOutgoingCallsParams.canParse(json, nullLspJsonReporter)) {
      return CallHierarchyOutgoingCallsParams.fromJson(json);
    }
    if (SemanticTokensParams.canParse(json, nullLspJsonReporter)) {
      return SemanticTokensParams.fromJson(json);
    }
    if (SemanticTokensDeltaParams.canParse(json, nullLspJsonReporter)) {
      return SemanticTokensDeltaParams.fromJson(json);
    }
    if (SemanticTokensRangeParams.canParse(json, nullLspJsonReporter)) {
      return SemanticTokensRangeParams.fromJson(json);
    }
    if (LinkedEditingRangeParams.canParse(json, nullLspJsonReporter)) {
      return LinkedEditingRangeParams.fromJson(json);
    }
    if (MonikerParams.canParse(json, nullLspJsonReporter)) {
      return MonikerParams.fromJson(json);
    }
    final workDoneToken = json['workDoneToken'] is num
        ? Either2<num, String>.t1(json['workDoneToken'])
        : (json['workDoneToken'] is String
            ? Either2<num, String>.t2(json['workDoneToken'])
            : (json['workDoneToken'] == null
                ? null
                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
    return WorkDoneProgressParams(workDoneToken: workDoneToken);
  }

  /// An optional token that a server can use to report work done progress.
  final Either2<num, String> workDoneToken;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('workDoneToken');
      try {
        if (obj['workDoneToken'] != null &&
            !((obj['workDoneToken'] is num ||
                obj['workDoneToken'] is String))) {
          reporter.reportError('must be of type Either2<num, 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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, workDoneToken.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WorkDoneProgressReport implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
      WorkDoneProgressReport.canParse, WorkDoneProgressReport.fromJson);

  WorkDoneProgressReport(
      {this.kind = 'report', this.cancellable, this.message, this.percentage}) {
    if (kind != 'report') {
      throw 'kind may only be the literal \'report\'';
    }
  }
  static WorkDoneProgressReport fromJson(Map<String, dynamic> json) {
    final kind = json['kind'];
    final cancellable = json['cancellable'];
    final message = json['message'];
    final percentage = json['percentage'];
    return WorkDoneProgressReport(
        kind: kind,
        cancellable: cancellable,
        message: message,
        percentage: percentage);
  }

  /// Controls enablement state of a cancel button. This property is only valid
  ///
  /// if a cancel button got requested in the `WorkDoneProgressStart` payload.
  ///
  /// Clients that don't support cancellation or don't support control the
  /// button's enablement state are allowed to ignore the setting.
  final bool cancellable;
  final String kind;

  /// Optional, more detailed associated progress message. Contains
  /// complementary information to the `title`.
  ///
  /// Examples: "3/25 files", "project/src/module2", "node_modules/some_dep". If
  /// unset, the previous progress message (if any) is still valid.
  final String message;

  /// Optional progress percentage to display (value 100 is considered 100%). If
  /// not provided infinite progress is assumed and clients are allowed to
  /// ignore the `percentage` value in subsequent in report notifications.
  ///
  /// The value should be steadily rising. Clients are free to ignore values
  /// that are not following this rule. The value range is [0, 100]
  final num percentage;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['kind'] = kind ?? (throw 'kind is required but was not set');
    if (cancellable != null) {
      __result['cancellable'] = cancellable;
    }
    if (message != null) {
      __result['message'] = message;
    }
    if (percentage != null) {
      __result['percentage'] = percentage;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('kind');
      try {
        if (!obj.containsKey('kind')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['kind'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['kind'] == 'report')) {
          reporter.reportError('must be the literal \'report\'');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('cancellable');
      try {
        if (obj['cancellable'] != null && !(obj['cancellable'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('message');
      try {
        if (obj['message'] != null && !(obj['message'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('percentage');
      try {
        if (obj['percentage'] != null && !(obj['percentage'] is num)) {
          reporter.reportError('must be of type num');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type WorkDoneProgressReport');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is WorkDoneProgressReport &&
        other.runtimeType == WorkDoneProgressReport) {
      return kind == other.kind &&
          cancellable == other.cancellable &&
          message == other.message &&
          percentage == other.percentage &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, kind.hashCode);
    hash = JenkinsSmiHash.combine(hash, cancellable.hashCode);
    hash = JenkinsSmiHash.combine(hash, message.hashCode);
    hash = JenkinsSmiHash.combine(hash, percentage.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WorkspaceEdit implements ToJsonable {
  static const jsonHandler =
      LspJsonHandler(WorkspaceEdit.canParse, WorkspaceEdit.fromJson);

  WorkspaceEdit({this.changes, this.documentChanges, this.changeAnnotations});
  static WorkspaceEdit fromJson(Map<String, dynamic> json) {
    final changes = json['changes']
        ?.map((key, value) => MapEntry(
            key,
            value
                ?.map((item) => item != null ? TextEdit.fromJson(item) : null)
                ?.cast<TextEdit>()
                ?.toList()))
        ?.cast<String, List<TextEdit>>();
    final documentChanges = (json['documentChanges'] is List && (json['documentChanges'].every((item) => TextDocumentEdit.canParse(item, nullLspJsonReporter))))
        ? Either2<List<TextDocumentEdit>, List<Either4<TextDocumentEdit, CreateFile, RenameFile, DeleteFile>>>.t1(
            json['documentChanges']
                ?.map((item) =>
                    item != null ? TextDocumentEdit.fromJson(item) : null)
                ?.cast<TextDocumentEdit>()
                ?.toList())
        : ((json['documentChanges'] is List && (json['documentChanges'].every((item) => (TextDocumentEdit.canParse(item, nullLspJsonReporter) || CreateFile.canParse(item, nullLspJsonReporter) || RenameFile.canParse(item, nullLspJsonReporter) || DeleteFile.canParse(item, nullLspJsonReporter)))))
            ? Either2<List<TextDocumentEdit>, List<Either4<TextDocumentEdit, CreateFile, RenameFile, DeleteFile>>>.t2(json['documentChanges']
                ?.map((item) => TextDocumentEdit.canParse(item, nullLspJsonReporter)
                    ? Either4<TextDocumentEdit, CreateFile, RenameFile, DeleteFile>.t1(
                        item != null ? TextDocumentEdit.fromJson(item) : null)
                    : (CreateFile.canParse(item, nullLspJsonReporter)
                        ? Either4<TextDocumentEdit, CreateFile, RenameFile, DeleteFile>.t2(item != null ? CreateFile.fromJson(item) : null)
                        : (RenameFile.canParse(item, nullLspJsonReporter) ? Either4<TextDocumentEdit, CreateFile, RenameFile, DeleteFile>.t3(item != null ? RenameFile.fromJson(item) : null) : (DeleteFile.canParse(item, nullLspJsonReporter) ? Either4<TextDocumentEdit, CreateFile, RenameFile, DeleteFile>.t4(item != null ? DeleteFile.fromJson(item) : null) : (item == null ? null : (throw '''${item} was not one of (TextDocumentEdit, CreateFile, RenameFile, DeleteFile)'''))))))
                ?.cast<Either4<TextDocumentEdit, CreateFile, RenameFile, DeleteFile>>()
                ?.toList())
            : (json['documentChanges'] == null ? null : (throw '''${json['documentChanges']} was not one of (List<TextDocumentEdit>, List<Either4<TextDocumentEdit, CreateFile, RenameFile, DeleteFile>>)''')));
    final changeAnnotations = json['changeAnnotations']
        ?.map((key, value) => MapEntry(
            key, value != null ? ChangeAnnotation.fromJson(value) : null))
        ?.cast<String, ChangeAnnotation>();
    return WorkspaceEdit(
        changes: changes,
        documentChanges: documentChanges,
        changeAnnotations: changeAnnotations);
  }

  /// A map of change annotations that can be referenced in `AnnotatedTextEdit`s
  /// or create, rename and delete file / folder operations.
  ///
  /// Whether clients honor this property depends on the client capability
  /// `workspace.changeAnnotationSupport`.
  ///  @since 3.16.0
  final Map<String, ChangeAnnotation> changeAnnotations;

  /// Holds changes to existing resources.
  final Map<String, List<TextEdit>> changes;

  /// Depending on the client capability
  /// `workspace.workspaceEdit.resourceOperations` document changes are either
  /// an array of `TextDocumentEdit`s to express changes to n different text
  /// documents where each text document edit addresses a specific version of a
  /// text document. Or it can contain above `TextDocumentEdit`s mixed with
  /// create, rename and delete file / folder operations.
  ///
  /// Whether a client supports versioned document edits is expressed via
  /// `workspace.workspaceEdit.documentChanges` client capability.
  ///
  /// If a client neither supports `documentChanges` nor
  /// `workspace.workspaceEdit.resourceOperations` then only plain `TextEdit`s
  /// using the `changes` property are supported.
  final Either2<List<TextDocumentEdit>,
          List<Either4<TextDocumentEdit, CreateFile, RenameFile, DeleteFile>>>
      documentChanges;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (changes != null) {
      __result['changes'] = changes;
    }
    if (documentChanges != null) {
      __result['documentChanges'] = documentChanges;
    }
    if (changeAnnotations != null) {
      __result['changeAnnotations'] = changeAnnotations;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('changes');
      try {
        if (obj['changes'] != null &&
            !((obj['changes'] is Map &&
                (obj['changes'].keys.every((item) =>
                    item is String &&
                    obj['changes'].values.every((item) => (item is List &&
                        (item.every((item) =>
                            TextEdit.canParse(item, reporter)))))))))) {
          reporter.reportError('must be of type Map<String, List<TextEdit>>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('documentChanges');
      try {
        if (obj['documentChanges'] != null &&
            !(((obj['documentChanges'] is List &&
                    (obj['documentChanges'].every((item) =>
                        TextDocumentEdit.canParse(item, reporter)))) ||
                (obj['documentChanges'] is List &&
                    (obj['documentChanges'].every((item) =>
                        (TextDocumentEdit.canParse(item, reporter) ||
                            CreateFile.canParse(item, reporter) ||
                            RenameFile.canParse(item, reporter) ||
                            DeleteFile.canParse(item, reporter)))))))) {
          reporter.reportError(
              'must be of type Either2<List<TextDocumentEdit>, List<Either4<TextDocumentEdit, CreateFile, RenameFile, DeleteFile>>>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('changeAnnotations');
      try {
        if (obj['changeAnnotations'] != null &&
            !((obj['changeAnnotations'] is Map &&
                (obj['changeAnnotations'].keys.every((item) =>
                    item is String &&
                    obj['changeAnnotations'].values.every((item) =>
                        ChangeAnnotation.canParse(item, reporter))))))) {
          reporter.reportError('must be of type Map<String, ChangeAnnotation>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type WorkspaceEdit');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is WorkspaceEdit && other.runtimeType == WorkspaceEdit) {
      return mapEqual(
              changes,
              other.changes,
              (List<TextEdit> a, List<TextEdit> b) =>
                  listEqual(a, b, (TextEdit a, TextEdit b) => a == b)) &&
          documentChanges == other.documentChanges &&
          mapEqual(changeAnnotations, other.changeAnnotations,
              (ChangeAnnotation a, ChangeAnnotation b) => a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(changes));
    hash = JenkinsSmiHash.combine(hash, documentChanges.hashCode);
    hash = JenkinsSmiHash.combine(hash, lspHashCode(changeAnnotations));
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WorkspaceEditClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
      WorkspaceEditClientCapabilities.canParse,
      WorkspaceEditClientCapabilities.fromJson);

  WorkspaceEditClientCapabilities(
      {this.documentChanges,
      this.resourceOperations,
      this.failureHandling,
      this.normalizesLineEndings,
      this.changeAnnotationSupport});
  static WorkspaceEditClientCapabilities fromJson(Map<String, dynamic> json) {
    final documentChanges = json['documentChanges'];
    final resourceOperations = json['resourceOperations']
        ?.map((item) =>
            item != null ? ResourceOperationKind.fromJson(item) : null)
        ?.cast<ResourceOperationKind>()
        ?.toList();
    final failureHandling = json['failureHandling'] != null
        ? FailureHandlingKind.fromJson(json['failureHandling'])
        : null;
    final normalizesLineEndings = json['normalizesLineEndings'];
    final changeAnnotationSupport = json['changeAnnotationSupport'] != null
        ? WorkspaceEditClientCapabilitiesChangeAnnotationSupport.fromJson(
            json['changeAnnotationSupport'])
        : null;
    return WorkspaceEditClientCapabilities(
        documentChanges: documentChanges,
        resourceOperations: resourceOperations,
        failureHandling: failureHandling,
        normalizesLineEndings: normalizesLineEndings,
        changeAnnotationSupport: changeAnnotationSupport);
  }

  /// Whether the client in general supports change annotations on text edits,
  /// create file, rename file and delete file changes.
  ///  @since 3.16.0
  final WorkspaceEditClientCapabilitiesChangeAnnotationSupport
      changeAnnotationSupport;

  /// The client supports versioned document changes in `WorkspaceEdit`s
  final bool documentChanges;

  /// The failure handling strategy of a client if applying the workspace edit
  /// fails.
  ///  @since 3.13.0
  final FailureHandlingKind failureHandling;

  /// Whether the client normalizes line endings to the client specific setting.
  /// If set to `true` the client will normalize line ending characters in a
  /// workspace edit to the client specific new line character(s).
  ///  @since 3.16.0
  final bool normalizesLineEndings;

  /// The resource operations the client supports. Clients should at least
  /// support 'create', 'rename' and 'delete' files and folders.
  ///  @since 3.13.0
  final List<ResourceOperationKind> resourceOperations;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (documentChanges != null) {
      __result['documentChanges'] = documentChanges;
    }
    if (resourceOperations != null) {
      __result['resourceOperations'] =
          resourceOperations.map((item) => item.toJson()).toList();
    }
    if (failureHandling != null) {
      __result['failureHandling'] = failureHandling.toJson();
    }
    if (normalizesLineEndings != null) {
      __result['normalizesLineEndings'] = normalizesLineEndings;
    }
    if (changeAnnotationSupport != null) {
      __result['changeAnnotationSupport'] = changeAnnotationSupport.toJson();
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('documentChanges');
      try {
        if (obj['documentChanges'] != null &&
            !(obj['documentChanges'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('resourceOperations');
      try {
        if (obj['resourceOperations'] != null &&
            !((obj['resourceOperations'] is List &&
                (obj['resourceOperations'].every((item) =>
                    ResourceOperationKind.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<ResourceOperationKind>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('failureHandling');
      try {
        if (obj['failureHandling'] != null &&
            !(FailureHandlingKind.canParse(obj['failureHandling'], reporter))) {
          reporter.reportError('must be of type FailureHandlingKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('normalizesLineEndings');
      try {
        if (obj['normalizesLineEndings'] != null &&
            !(obj['normalizesLineEndings'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('changeAnnotationSupport');
      try {
        if (obj['changeAnnotationSupport'] != null &&
            !(WorkspaceEditClientCapabilitiesChangeAnnotationSupport.canParse(
                obj['changeAnnotationSupport'], reporter))) {
          reporter.reportError(
              'must be of type WorkspaceEditClientCapabilitiesChangeAnnotationSupport');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type WorkspaceEditClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is WorkspaceEditClientCapabilities &&
        other.runtimeType == WorkspaceEditClientCapabilities) {
      return documentChanges == other.documentChanges &&
          listEqual(resourceOperations, other.resourceOperations,
              (ResourceOperationKind a, ResourceOperationKind b) => a == b) &&
          failureHandling == other.failureHandling &&
          normalizesLineEndings == other.normalizesLineEndings &&
          changeAnnotationSupport == other.changeAnnotationSupport &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, documentChanges.hashCode);
    hash = JenkinsSmiHash.combine(hash, lspHashCode(resourceOperations));
    hash = JenkinsSmiHash.combine(hash, failureHandling.hashCode);
    hash = JenkinsSmiHash.combine(hash, normalizesLineEndings.hashCode);
    hash = JenkinsSmiHash.combine(hash, changeAnnotationSupport.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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, dynamic> json) {
    final groupsOnLabel = json['groupsOnLabel'];
    return WorkspaceEditClientCapabilitiesChangeAnnotationSupport(
        groupsOnLabel: groupsOnLabel);
  }

  /// Whether the client groups edits with equal labels into tree nodes, for
  /// instance all edits labelled with "Changes in Strings" would be a tree
  /// node.
  final bool groupsOnLabel;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (groupsOnLabel != null) {
      __result['groupsOnLabel'] = groupsOnLabel;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('groupsOnLabel');
      try {
        if (obj['groupsOnLabel'] != null && !(obj['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 {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, groupsOnLabel.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WorkspaceFolder implements ToJsonable {
  static const jsonHandler =
      LspJsonHandler(WorkspaceFolder.canParse, WorkspaceFolder.fromJson);

  WorkspaceFolder({@required this.uri, @required this.name}) {
    if (uri == null) {
      throw 'uri is required but was not provided';
    }
    if (name == null) {
      throw 'name is required but was not provided';
    }
  }
  static WorkspaceFolder fromJson(Map<String, dynamic> json) {
    final uri = json['uri'];
    final name = json['name'];
    return WorkspaceFolder(uri: uri, name: name);
  }

  /// The name of the workspace folder. Used to refer to this workspace folder
  /// in the user interface.
  final String name;

  /// The associated URI for this workspace folder.
  final String uri;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['uri'] = uri ?? (throw 'uri is required but was not set');
    __result['name'] = name ?? (throw 'name is required but was not set');
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('uri');
      try {
        if (!obj.containsKey('uri')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['uri'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['uri'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('name');
      try {
        if (!obj.containsKey('name')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['name'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['name'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type WorkspaceFolder');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is WorkspaceFolder && other.runtimeType == WorkspaceFolder) {
      return uri == other.uri && name == other.name && true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, uri.hashCode);
    hash = JenkinsSmiHash.combine(hash, name.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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}) {
    if (added == null) {
      throw 'added is required but was not provided';
    }
    if (removed == null) {
      throw 'removed is required but was not provided';
    }
  }
  static WorkspaceFoldersChangeEvent fromJson(Map<String, dynamic> json) {
    final added = json['added']
        ?.map((item) => item != null ? WorkspaceFolder.fromJson(item) : null)
        ?.cast<WorkspaceFolder>()
        ?.toList();
    final removed = json['removed']
        ?.map((item) => item != null ? WorkspaceFolder.fromJson(item) : null)
        ?.cast<WorkspaceFolder>()
        ?.toList();
    return WorkspaceFoldersChangeEvent(added: added, removed: removed);
  }

  /// The array of added workspace folders
  final List<WorkspaceFolder> added;

  /// The array of the removed workspace folders
  final List<WorkspaceFolder> removed;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['added'] = added?.map((item) => item.toJson())?.toList() ??
        (throw 'added is required but was not set');
    __result['removed'] = removed?.map((item) => item.toJson())?.toList() ??
        (throw 'removed is required but was not set');
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('added');
      try {
        if (!obj.containsKey('added')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['added'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!((obj['added'] is List &&
            (obj['added']
                .every((item) => WorkspaceFolder.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<WorkspaceFolder>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('removed');
      try {
        if (!obj.containsKey('removed')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['removed'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!((obj['removed'] is List &&
            (obj['removed']
                .every((item) => WorkspaceFolder.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<WorkspaceFolder>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type WorkspaceFoldersChangeEvent');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is WorkspaceFoldersChangeEvent &&
        other.runtimeType == WorkspaceFoldersChangeEvent) {
      return listEqual(added, other.added,
              (WorkspaceFolder a, WorkspaceFolder b) => a == b) &&
          listEqual(removed, other.removed,
              (WorkspaceFolder a, WorkspaceFolder b) => a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(added));
    hash = JenkinsSmiHash.combine(hash, lspHashCode(removed));
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WorkspaceFoldersServerCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
      WorkspaceFoldersServerCapabilities.canParse,
      WorkspaceFoldersServerCapabilities.fromJson);

  WorkspaceFoldersServerCapabilities(
      {this.supported, this.changeNotifications});
  static WorkspaceFoldersServerCapabilities fromJson(
      Map<String, dynamic> json) {
    final supported = json['supported'];
    final changeNotifications = json['changeNotifications'] is String
        ? Either2<String, bool>.t1(json['changeNotifications'])
        : (json['changeNotifications'] is bool
            ? Either2<String, bool>.t2(json['changeNotifications'])
            : (json['changeNotifications'] == null
                ? null
                : (throw '''${json['changeNotifications']} was not one of (String, bool)''')));
    return WorkspaceFoldersServerCapabilities(
        supported: supported, changeNotifications: changeNotifications);
  }

  /// Whether the server wants to receive workspace folder change notifications.
  ///
  /// If a string is provided, the string is treated as an ID under which the
  /// notification is registered on the client side. The ID can be used to
  /// unregister for these events using the `client/unregisterCapability`
  /// request.
  final Either2<String, bool> changeNotifications;

  /// The server has support for workspace folders
  final bool supported;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (supported != null) {
      __result['supported'] = supported;
    }
    if (changeNotifications != null) {
      __result['changeNotifications'] = changeNotifications;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('supported');
      try {
        if (obj['supported'] != null && !(obj['supported'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('changeNotifications');
      try {
        if (obj['changeNotifications'] != null &&
            !((obj['changeNotifications'] is String ||
                obj['changeNotifications'] is bool))) {
          reporter.reportError('must be of type Either2<String, bool>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter
          .reportError('must be of type WorkspaceFoldersServerCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is WorkspaceFoldersServerCapabilities &&
        other.runtimeType == WorkspaceFoldersServerCapabilities) {
      return supported == other.supported &&
          changeNotifications == other.changeNotifications &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, supported.hashCode);
    hash = JenkinsSmiHash.combine(hash, changeNotifications.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WorkspaceSymbolClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
      WorkspaceSymbolClientCapabilities.canParse,
      WorkspaceSymbolClientCapabilities.fromJson);

  WorkspaceSymbolClientCapabilities(
      {this.dynamicRegistration, this.symbolKind, this.tagSupport});
  static WorkspaceSymbolClientCapabilities fromJson(Map<String, dynamic> json) {
    final dynamicRegistration = json['dynamicRegistration'];
    final symbolKind = json['symbolKind'] != null
        ? WorkspaceSymbolClientCapabilitiesSymbolKind.fromJson(
            json['symbolKind'])
        : null;
    final tagSupport = json['tagSupport'] != null
        ? WorkspaceSymbolClientCapabilitiesTagSupport.fromJson(
            json['tagSupport'])
        : null;
    return WorkspaceSymbolClientCapabilities(
        dynamicRegistration: dynamicRegistration,
        symbolKind: symbolKind,
        tagSupport: tagSupport);
  }

  /// Symbol request supports dynamic registration.
  final bool dynamicRegistration;

  /// Specific capabilities for the `SymbolKind` in the `workspace/symbol`
  /// request.
  final WorkspaceSymbolClientCapabilitiesSymbolKind symbolKind;

  /// The client supports tags on `SymbolInformation`. Clients supporting tags
  /// have to handle unknown tags gracefully.
  ///  @since 3.16.0
  final WorkspaceSymbolClientCapabilitiesTagSupport tagSupport;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (dynamicRegistration != null) {
      __result['dynamicRegistration'] = dynamicRegistration;
    }
    if (symbolKind != null) {
      __result['symbolKind'] = symbolKind.toJson();
    }
    if (tagSupport != null) {
      __result['tagSupport'] = tagSupport.toJson();
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('dynamicRegistration');
      try {
        if (obj['dynamicRegistration'] != null &&
            !(obj['dynamicRegistration'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('symbolKind');
      try {
        if (obj['symbolKind'] != null &&
            !(WorkspaceSymbolClientCapabilitiesSymbolKind.canParse(
                obj['symbolKind'], reporter))) {
          reporter.reportError(
              'must be of type WorkspaceSymbolClientCapabilitiesSymbolKind');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('tagSupport');
      try {
        if (obj['tagSupport'] != null &&
            !(WorkspaceSymbolClientCapabilitiesTagSupport.canParse(
                obj['tagSupport'], reporter))) {
          reporter.reportError(
              'must be of type WorkspaceSymbolClientCapabilitiesTagSupport');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type WorkspaceSymbolClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is WorkspaceSymbolClientCapabilities &&
        other.runtimeType == WorkspaceSymbolClientCapabilities) {
      return dynamicRegistration == other.dynamicRegistration &&
          symbolKind == other.symbolKind &&
          tagSupport == other.tagSupport &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode);
    hash = JenkinsSmiHash.combine(hash, symbolKind.hashCode);
    hash = JenkinsSmiHash.combine(hash, tagSupport.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @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, dynamic> json) {
    final valueSet = json['valueSet']
        ?.map((item) => item != null ? SymbolKind.fromJson(item) : null)
        ?.cast<SymbolKind>()
        ?.toList();
    return WorkspaceSymbolClientCapabilitiesSymbolKind(valueSet: valueSet);
  }

  /// The symbol kind values the client supports. When this property exists the
  /// client also guarantees that it will handle values outside its set
  /// gracefully and falls back to a default value when unknown.
  ///
  /// If this property is not present the client only supports the symbol kinds
  /// from `File` to `Array` as defined in the initial version of the protocol.
  final List<SymbolKind> valueSet;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    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, dynamic>) {
      reporter.push('valueSet');
      try {
        if (obj['valueSet'] != null &&
            !((obj['valueSet'] is List &&
                (obj['valueSet']
                    .every((item) => SymbolKind.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<SymbolKind>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type WorkspaceSymbolClientCapabilitiesSymbolKind');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is WorkspaceSymbolClientCapabilitiesSymbolKind &&
        other.runtimeType == WorkspaceSymbolClientCapabilitiesSymbolKind) {
      return listEqual(valueSet, other.valueSet,
              (SymbolKind a, SymbolKind b) => a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(valueSet));
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WorkspaceSymbolClientCapabilitiesTagSupport implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
      WorkspaceSymbolClientCapabilitiesTagSupport.canParse,
      WorkspaceSymbolClientCapabilitiesTagSupport.fromJson);

  WorkspaceSymbolClientCapabilitiesTagSupport({@required this.valueSet}) {
    if (valueSet == null) {
      throw 'valueSet is required but was not provided';
    }
  }
  static WorkspaceSymbolClientCapabilitiesTagSupport fromJson(
      Map<String, dynamic> json) {
    final valueSet = json['valueSet']
        ?.map((item) => item != null ? SymbolTag.fromJson(item) : null)
        ?.cast<SymbolTag>()
        ?.toList();
    return WorkspaceSymbolClientCapabilitiesTagSupport(valueSet: valueSet);
  }

  /// The tags supported by the client.
  final List<SymbolTag> valueSet;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['valueSet'] = valueSet?.map((item) => item.toJson())?.toList() ??
        (throw 'valueSet is required but was not set');
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('valueSet');
      try {
        if (!obj.containsKey('valueSet')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['valueSet'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!((obj['valueSet'] is List &&
            (obj['valueSet']
                .every((item) => SymbolTag.canParse(item, reporter)))))) {
          reporter.reportError('must be of type List<SymbolTag>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError(
          'must be of type WorkspaceSymbolClientCapabilitiesTagSupport');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is WorkspaceSymbolClientCapabilitiesTagSupport &&
        other.runtimeType == WorkspaceSymbolClientCapabilitiesTagSupport) {
      return listEqual(
              valueSet, other.valueSet, (SymbolTag a, SymbolTag b) => a == b) &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, lspHashCode(valueSet));
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WorkspaceSymbolOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
      WorkspaceSymbolOptions.canParse, WorkspaceSymbolOptions.fromJson);

  WorkspaceSymbolOptions({this.workDoneProgress});
  static WorkspaceSymbolOptions fromJson(Map<String, dynamic> json) {
    if (WorkspaceSymbolRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return WorkspaceSymbolRegistrationOptions.fromJson(json);
    }
    final workDoneProgress = json['workDoneProgress'];
    return WorkspaceSymbolOptions(workDoneProgress: workDoneProgress);
  }

  final bool workDoneProgress;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('workDoneProgress');
      try {
        if (obj['workDoneProgress'] != null &&
            !(obj['workDoneProgress'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type WorkspaceSymbolOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is WorkspaceSymbolOptions &&
        other.runtimeType == WorkspaceSymbolOptions) {
      return workDoneProgress == other.workDoneProgress && true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The parameters of a Workspace Symbol Request.
class WorkspaceSymbolParams
    implements WorkDoneProgressParams, PartialResultParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
      WorkspaceSymbolParams.canParse, WorkspaceSymbolParams.fromJson);

  WorkspaceSymbolParams(
      {@required this.query, this.workDoneToken, this.partialResultToken}) {
    if (query == null) {
      throw 'query is required but was not provided';
    }
  }
  static WorkspaceSymbolParams fromJson(Map<String, dynamic> json) {
    final query = json['query'];
    final workDoneToken = json['workDoneToken'] is num
        ? Either2<num, String>.t1(json['workDoneToken'])
        : (json['workDoneToken'] is String
            ? Either2<num, String>.t2(json['workDoneToken'])
            : (json['workDoneToken'] == null
                ? null
                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
    final partialResultToken = json['partialResultToken'] is num
        ? Either2<num, String>.t1(json['partialResultToken'])
        : (json['partialResultToken'] is String
            ? Either2<num, String>.t2(json['partialResultToken'])
            : (json['partialResultToken'] == null
                ? null
                : (throw '''${json['partialResultToken']} was not one of (num, String)''')));
    return WorkspaceSymbolParams(
        query: query,
        workDoneToken: workDoneToken,
        partialResultToken: partialResultToken);
  }

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  final Either2<num, String> partialResultToken;

  /// A query string to filter symbols by. Clients may send an empty string here
  /// to request all symbols.
  final String query;

  /// An optional token that a server can use to report work done progress.
  final Either2<num, String> workDoneToken;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    __result['query'] = query ?? (throw 'query is required but was not set');
    if (workDoneToken != null) {
      __result['workDoneToken'] = workDoneToken;
    }
    if (partialResultToken != null) {
      __result['partialResultToken'] = partialResultToken;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('query');
      try {
        if (!obj.containsKey('query')) {
          reporter.reportError('must not be undefined');
          return false;
        }
        if (obj['query'] == null) {
          reporter.reportError('must not be null');
          return false;
        }
        if (!(obj['query'] is String)) {
          reporter.reportError('must be of type String');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('workDoneToken');
      try {
        if (obj['workDoneToken'] != null &&
            !((obj['workDoneToken'] is num ||
                obj['workDoneToken'] is String))) {
          reporter.reportError('must be of type Either2<num, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      reporter.push('partialResultToken');
      try {
        if (obj['partialResultToken'] != null &&
            !((obj['partialResultToken'] is num ||
                obj['partialResultToken'] is String))) {
          reporter.reportError('must be of type Either2<num, String>');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter.reportError('must be of type WorkspaceSymbolParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is WorkspaceSymbolParams &&
        other.runtimeType == WorkspaceSymbolParams) {
      return query == other.query &&
          workDoneToken == other.workDoneToken &&
          partialResultToken == other.partialResultToken &&
          true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, query.hashCode);
    hash = JenkinsSmiHash.combine(hash, workDoneToken.hashCode);
    hash = JenkinsSmiHash.combine(hash, partialResultToken.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WorkspaceSymbolRegistrationOptions
    implements WorkspaceSymbolOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
      WorkspaceSymbolRegistrationOptions.canParse,
      WorkspaceSymbolRegistrationOptions.fromJson);

  WorkspaceSymbolRegistrationOptions({this.workDoneProgress});
  static WorkspaceSymbolRegistrationOptions fromJson(
      Map<String, dynamic> json) {
    final workDoneProgress = json['workDoneProgress'];
    return WorkspaceSymbolRegistrationOptions(
        workDoneProgress: workDoneProgress);
  }

  final bool workDoneProgress;

  Map<String, dynamic> toJson() {
    var __result = <String, dynamic>{};
    if (workDoneProgress != null) {
      __result['workDoneProgress'] = workDoneProgress;
    }
    return __result;
  }

  static bool canParse(Object obj, LspJsonReporter reporter) {
    if (obj is Map<String, dynamic>) {
      reporter.push('workDoneProgress');
      try {
        if (obj['workDoneProgress'] != null &&
            !(obj['workDoneProgress'] is bool)) {
          reporter.reportError('must be of type bool');
          return false;
        }
      } finally {
        reporter.pop();
      }
      return true;
    } else {
      reporter
          .reportError('must be of type WorkspaceSymbolRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is WorkspaceSymbolRegistrationOptions &&
        other.runtimeType == WorkspaceSymbolRegistrationOptions) {
      return workDoneProgress == other.workDoneProgress && true;
    }
    return false;
  }

  @override
  int get hashCode {
    var hash = 0;
    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  String toString() => jsonEncoder.convert(toJson());
}
