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

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

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

const jsonEncoder = JsonEncoder.withIndent('    ');

/// Result for a request to resolve the incoming calls for a given
/// `CallHierarchyItem`.
///
/// @since 3.16.0
typedef CallHierarchyIncomingCallsResult = List<CallHierarchyIncomingCall>?;

/// Result for a request to resolve the outgoing calls for a given
/// `CallHierarchyItem`.
///
/// @since 3.16.0
typedef CallHierarchyOutgoingCallsResult = List<CallHierarchyOutgoingCall>?;

/// An identifier to refer to a change annotation stored with a workspace edit.
typedef ChangeAnnotationIdentifier = String;

/// The declaration of a symbol representation as one or many locations.
typedef Declaration = Either2<List<Location>, Location>;

/// Information about where a symbol is declared.
///
/// Provides additional metadata over normal location declarations, including
/// the range of the declaring symbol.
///
/// Servers should prefer returning `DeclarationLink` over `Declaration` if
/// supported by the client.
typedef DeclarationLink = LocationLink;

/// The definition of a symbol represented as one or many locations. For most
/// programming languages there is only one location at which a symbol is
/// defined.
///
/// Servers should prefer returning `DefinitionLink` over `Definition` if
/// supported by the client.
typedef Definition = Either2<List<Location>, Location>;

/// Information about where a symbol is defined.
///
/// Provides additional metadata over normal location definitions, including the
/// range of the defining symbol
typedef DefinitionLink = LocationLink;

/// The result of a document diagnostic pull request. A report can either be a
/// full report containing all diagnostics for the requested document or an
/// unchanged report indicating that nothing has changed in terms of diagnostics
/// in comparison to the last pull request.
///
/// @since 3.17.0
typedef DocumentDiagnosticReport = Either2<RelatedFullDocumentDiagnosticReport,
    RelatedUnchangedDocumentDiagnosticReport>;

/// A document filter describes a top level text document or a notebook cell
/// document.
///
/// @since 3.17.0 - proposed support for NotebookCellTextDocumentFilter.
typedef DocumentFilter
    = Either2<NotebookCellTextDocumentFilter, TextDocumentFilter>;

/// A document selector is the combination of one or many document filters.
///
/// @sample `let sel:DocumentSelector = [{ language: 'typescript' }, { language:
/// 'json', pattern: '**∕tsconfig.json' }]`;
///
/// The use of a string as a document filter is deprecated @since 3.16.0.
typedef DocumentSelector = List<Either2<TextDocumentFilterWithScheme, String>>;

/// The glob pattern. Either a string pattern or a relative pattern.
///
/// @since 3.17.0
typedef GlobPattern = Either2<LspPattern, RelativePattern>;

/// Inline value information can be provided by different means:
/// - directly as a text value (class InlineValueText).
/// - as a name to use for a variable lookup (class InlineValueVariableLookup)
/// - as an evaluatable expression (class InlineValueEvaluatableExpression) The
/// InlineValue types combines all inline value types into one type.
///
/// @since 3.17.0
typedef InlineValue = Either3<InlineValueEvaluatableExpression, InlineValueText,
    InlineValueVariableLookup>;

/// LSP arrays.
/// @since 3.17.0
typedef LSPArray = List<LSPAny>;

/// The glob pattern to watch relative to the base path. 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`)
///
/// @since 3.17.0
typedef LspPattern = String;

/// A tagging type for string properties that are actually URIs
///
/// @since 3.16.0
typedef LspUri = String;

/// A notebook document filter denotes a notebook document by different
/// properties. The properties will be match against the notebook's URI (same as
/// with documents)
///
/// @since 3.17.0
typedef NotebookDocumentFilter = Either3<NotebookDocumentFilter1,
    NotebookDocumentFilter2, NotebookDocumentFilter3>;
typedef PrepareRenameResult
    = Either3<PlaceholderAndRange, PrepareRenameResult2, Range>;
typedef ProgressToken = Either2<int, String>;

/// Result for a request to provide commands for the given text document and
/// range.
typedef TextDocumentCodeActionResult = List<Either2<CodeAction, Command>>?;

/// Result for a request to provide code lens for the given text document.
typedef TextDocumentCodeLensResult = List<CodeLens>?;

/// Result for request to request completion at a given text document position.
/// The request's parameter is of type TextDocumentPosition the response is of
/// type [CompletionItem[]](#CompletionItem) or CompletionList or a Thenable
/// that resolves to such.
///
/// The request can delay the computation of the `detail` and `documentation`
/// properties to the `completionItem/resolve` request. However, properties that
/// are needed for the initial sorting and filtering, like `sortText`,
/// `filterText`, `insertText`, and `textEdit`, must not be changed during
/// resolve.
typedef TextDocumentCompletionResult
    = Either2<CompletionList, List<CompletionItem>>?;

/// An event describing a change to a text document. If only a text is provided
/// it is considered to be the full content of the document.
typedef TextDocumentContentChangeEvent
    = Either2<TextDocumentContentChangeEvent1, TextDocumentContentChangeEvent2>;

/// Result for a request to resolve the type definition locations of a symbol at
/// a given text document position. The request's parameter is of type
/// TextDocumentPositionParams the response is of type Declaration or a typed
/// array of DeclarationLink or a Thenable that resolves to such.
typedef TextDocumentDeclarationResult
    = Either2<Declaration, List<DeclarationLink>>?;

/// Result for a request to resolve the definition location of a symbol at a
/// given text document position. The request's parameter is of type
/// TextDocumentPosition the response is of either type Definition or a typed
/// array of DefinitionLink or a Thenable that resolves to such.
typedef TextDocumentDefinitionResult
    = Either2<Definition, List<DefinitionLink>>?;

/// Result for request to resolve a DocumentHighlight for a given text document
/// position. The request's parameter is of type TextDocumentPosition the
/// request response is of type [DocumentHighlight[]] (#DocumentHighlight) or a
/// Thenable that resolves to such.
typedef TextDocumentDocumentHighlightResult = List<DocumentHighlight>?;

/// Result for a request to provide document links
typedef TextDocumentDocumentLinkResult = List<DocumentLink>?;

/// Result for a request to list all symbols found in a given text document. The
/// request's parameter is of type TextDocumentIdentifier the response is of
/// type [SymbolInformation[]](#SymbolInformation) or a Thenable that resolves
/// to such.
typedef TextDocumentDocumentSymbolResult
    = Either2<List<DocumentSymbol>, List<SymbolInformation>>?;

/// A document filter denotes a document by different properties like the
/// language, the scheme of its resource, or a glob-pattern that is applied to
/// the path.
///
/// Glob patterns can have the following syntax:
/// - `*` to match one or more characters in a path segment
/// - `?` to match on one character in a path segment
/// - `**` to match any number of path segments, including none
/// - `{}` to group sub patterns into an OR expression. (e.g. `**​/*.{ts,js}`
/// matches all TypeScript and JavaScript files)
/// - `[]` to declare a range of characters to match in a path segment (e.g.,
/// `example.[0-9]` to match on `example.0`, `example.1`, …)
/// - `[!...]` to negate a range of characters to match in a path segment (e.g.,
/// `example.[!0-9]` to match on `example.a`, `example.b`, but not `example.0`)
///
/// @sample A language filter that applies to typescript files on disk: `{
/// language: 'typescript', scheme: 'file' }`
/// @sample A language filter that applies to all package.json paths: `{
/// language: 'json', pattern: '**package.json' }`
///
/// @since 3.17.0
typedef TextDocumentFilter = Either3<TextDocumentFilter1,
    TextDocumentFilterWithScheme, TextDocumentFilter3>;

/// Result for a request to provide folding ranges in a document. The request's
/// parameter is of type FoldingRangeParams, the response is of type
/// FoldingRangeList or a Thenable that resolves to such.
typedef TextDocumentFoldingRangeResult = List<FoldingRange>?;

/// Result for a request to to format a whole document.
typedef TextDocumentFormattingResult = List<TextEdit>?;

/// Result for request to request hover information at a given text document
/// position. The request's parameter is of type TextDocumentPosition the
/// response is of type Hover or a Thenable that resolves to such.
typedef TextDocumentHoverResult = Hover?;

/// Result for a request to resolve the implementation locations of a symbol at
/// a given text document position. The request's parameter is of type
/// TextDocumentPositionParams the response is of type Definition or a Thenable
/// that resolves to such.
typedef TextDocumentImplementationResult
    = Either2<Definition, List<DefinitionLink>>?;

/// Result for a request to provide inlay hints in a document. The request's
/// parameter is of type InlayHintsParams, the response is of type
/// [InlayHint[]](#InlayHint[]) or a Thenable that resolves to such.
///
/// @since 3.17.0
typedef TextDocumentInlayHintResult = List<InlayHint>?;

/// Result for a request to provide inline values in a document. The request's
/// parameter is of type InlineValueParams, the response is of type
/// [InlineValue[]](#InlineValue[]) or a Thenable that resolves to such.
///
/// @since 3.17.0
typedef TextDocumentInlineValueResult = List<InlineValue>?;

/// Result for a request to provide ranges that can be edited together.
///
/// @since 3.16.0
typedef TextDocumentLinkedEditingRangeResult = LinkedEditingRanges?;

/// Result for a request to get the moniker of a symbol at a given text document
/// position. The request parameter is of type TextDocumentPositionParams. The
/// response is of type [Moniker[]](#Moniker[]) or `null`.
typedef TextDocumentMonikerResult = List<Moniker>?;

/// Result for a request to format a document on type.
typedef TextDocumentOnTypeFormattingResult = List<TextEdit>?;

/// Result for a request to result a `CallHierarchyItem` in a document at a
/// given position. Can be used as an input to an incoming or outgoing call
/// hierarchy.
///
/// @since 3.16.0
typedef TextDocumentPrepareCallHierarchyResult = List<CallHierarchyItem>?;

/// Result for a request to test and perform the setup necessary for a rename.
///
/// @since 3.16 - support for default behavior
typedef TextDocumentPrepareRenameResult = PrepareRenameResult?;

/// Result for a request to result a `TypeHierarchyItem` in a document at a
/// given position. Can be used as an input to a subtypes or supertypes type
/// hierarchy.
///
/// @since 3.17.0
typedef TextDocumentPrepareTypeHierarchyResult = List<TypeHierarchyItem>?;

/// Result for a request to to format a range in a document.
typedef TextDocumentRangeFormattingResult = List<TextEdit>?;

/// Result for a request to resolve project-wide references for the symbol
/// denoted by the given text document position. The request's parameter is of
/// type ReferenceParams the response is of type [Location[]](#Location) or a
/// Thenable that resolves to such.
typedef TextDocumentReferencesResult = List<Location>?;

/// Result for a request to rename a symbol.
typedef TextDocumentRenameResult = WorkspaceEdit?;

/// Result for a request to provide selection ranges in a document. The
/// request's parameter is of type SelectionRangeParams, the response is of type
/// [SelectionRange[]](#SelectionRange[]) or a Thenable that resolves to such.
typedef TextDocumentSelectionRangeResult = List<SelectionRange>?;

/// Result for @since 3.16.0
typedef TextDocumentSemanticTokensFullDeltaResult
    = Either2<SemanticTokens, SemanticTokensDelta>?;

/// Result for @since 3.16.0
typedef TextDocumentSemanticTokensFullResult = SemanticTokens?;

/// Result for @since 3.16.0
typedef TextDocumentSemanticTokensRangeResult = SemanticTokens?;
typedef TextDocumentSignatureHelpResult = SignatureHelp?;

/// Result for a request to resolve the type definition locations of a symbol at
/// a given text document position. The request's parameter is of type
/// TextDocumentPositioParams the response is of type Definition or a Thenable
/// that resolves to such.
typedef TextDocumentTypeDefinitionResult
    = Either2<Definition, List<DefinitionLink>>?;

/// Result for a document will save request is sent from the client to the
/// server before the document is actually saved. The request can return an
/// array of TextEdits which will be applied to the text document before it is
/// saved. Please note that clients might drop results if computing the text
/// edits took too long or if a server constantly fails on this request. This is
/// done to keep the save fast and reliable.
typedef TextDocumentWillSaveWaitUntilResult = List<TextEdit>?;

/// Result for a request to resolve the subtypes for a given
/// `TypeHierarchyItem`.
///
/// @since 3.17.0
typedef TypeHierarchySubtypesResult = List<TypeHierarchyItem>?;

/// Result for a request to resolve the supertypes for a given
/// `TypeHierarchyItem`.
///
/// @since 3.17.0
typedef TypeHierarchySupertypesResult = List<TypeHierarchyItem>?;

/// Result for the show message request is sent from the server to the client to
/// show a message and a set of options actions to the user.
typedef WindowShowMessageRequestResult = MessageActionItem?;

/// A workspace diagnostic document report.
///
/// @since 3.17.0
typedef WorkspaceDocumentDiagnosticReport = Either2<
    WorkspaceFullDocumentDiagnosticReport,
    WorkspaceUnchangedDocumentDiagnosticReport>;

/// Result for a request send from the client to the server to execute a
/// command. The request might return a workspace edit which the client will
/// apply to the workspace.
typedef WorkspaceExecuteCommandResult = LSPAny?;

/// Result for a request to list project-wide symbols matching the query string
/// given by the WorkspaceSymbolParams. The response is of type
/// [SymbolInformation[]](#SymbolInformation) or a Thenable that resolves to
/// such.
///
/// @since 3.17.0 - support for WorkspaceSymbol in the returned data. Clients
///  need to advertise support for WorkspaceSymbols via the client capability
///  `workspace.symbol.resolveSupport`.
typedef WorkspaceSymbolResult
    = Either2<List<SymbolInformation>, List<WorkspaceSymbol>>?;

/// Result for the will create files request is sent from the client to the
/// server before files are actually created as long as the creation is
/// triggered from within the client.
///
/// @since 3.16.0
typedef WorkspaceWillCreateFilesResult = WorkspaceEdit?;

/// Result for the did delete files notification is sent from the client to the
/// server when files were deleted from within the client.
///
/// @since 3.16.0
typedef WorkspaceWillDeleteFilesResult = WorkspaceEdit?;

/// Result for the will rename files request is sent from the client to the
/// server before files are actually renamed as long as the rename is triggered
/// from within the client.
///
/// @since 3.16.0
typedef WorkspaceWillRenameFilesResult = WorkspaceEdit?;

/// Result for the `workspace/workspaceFolders` is sent from the server to the
/// client to fetch the open workspace folders.
typedef WorkspaceWorkspaceFoldersResult = List<WorkspaceFolder>?;

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

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

  /// The actual identifier of the change annotation
  final ChangeAnnotationIdentifier annotationId;

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseString(obj, reporter, 'annotationId',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'newText',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseRange(obj, reporter, 'range',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type AnnotatedTextEdit');
      return false;
    }
  }

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

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

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

/// The parameters passed via a apply workspace edit request.
class ApplyWorkspaceEditParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ApplyWorkspaceEditParams.canParse,
    ApplyWorkspaceEditParams.fromJson,
  );

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

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseWorkspaceEdit(obj, reporter, 'edit',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseString(obj, reporter, 'label',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type ApplyWorkspaceEditParams');
      return false;
    }
  }

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

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

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

/// The result returned from the apply workspace edit request.
///
/// @since 3.17 renamed from ApplyWorkspaceEditResponse
class ApplyWorkspaceEditResult implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ApplyWorkspaceEditResult.canParse,
    ApplyWorkspaceEditResult.fromJson,
  );

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

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

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseBool(obj, reporter, 'applied',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseInt(obj, reporter, 'failedChange',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseString(obj, reporter, 'failureReason',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type ApplyWorkspaceEditResult');
      return false;
    }
  }

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

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

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

/// A base for all symbol information.
class BaseSymbolInformation implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    BaseSymbolInformation.canParse,
    BaseSymbolInformation.fromJson,
  );

  BaseSymbolInformation({
    this.containerName,
    required this.kind,
    required this.name,
    this.tags,
  });
  static BaseSymbolInformation fromJson(Map<String, Object?> json) {
    if (SymbolInformation.canParse(json, nullLspJsonReporter)) {
      return SymbolInformation.fromJson(json);
    }
    if (WorkspaceSymbol.canParse(json, nullLspJsonReporter)) {
      return WorkspaceSymbol.fromJson(json);
    }
    final containerNameJson = json['containerName'];
    final containerName = containerNameJson as String?;
    final kindJson = json['kind'];
    final kind = SymbolKind.fromJson(kindJson as int);
    final nameJson = json['name'];
    final name = nameJson as String;
    final tagsJson = json['tags'];
    final tags = (tagsJson as List<Object?>?)
        ?.map((item) => SymbolTag.fromJson(item as int))
        .toList();
    return BaseSymbolInformation(
      containerName: containerName,
      kind: kind,
      name: name,
      tags: tags,
    );
  }

  /// The name of the symbol containing this symbol. This information is for
  /// user interface purposes (e.g. to render a qualifier in the user interface
  /// if necessary). It can't be used to re-infer a hierarchy for the document
  /// symbols.
  final String? containerName;

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

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

  /// Tags for this symbol.
  ///
  /// @since 3.16.0
  final List<SymbolTag>? tags;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseString(obj, reporter, 'containerName',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseSymbolKind(obj, reporter, 'kind',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'name',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseListSymbolTag(obj, reporter, 'tags',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type BaseSymbolInformation');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is BaseSymbolInformation &&
        other.runtimeType == BaseSymbolInformation &&
        containerName == other.containerName &&
        kind == other.kind &&
        name == other.name &&
        listEqual(tags, other.tags, (SymbolTag a, SymbolTag b) => a == b);
  }

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

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

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

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

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

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

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

  @override
  bool operator ==(Object other) {
    return other is CallHierarchyClientCapabilities &&
        other.runtimeType == CallHierarchyClientCapabilities &&
        dynamicRegistration == other.dynamicRegistration;
  }

  @override
  int get hashCode => dynamicRegistration.hashCode;

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

/// Represents an incoming call, e.g. a caller of a method or constructor.
///
/// @since 3.16.0
class CallHierarchyIncomingCall implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CallHierarchyIncomingCall.canParse,
    CallHierarchyIncomingCall.fromJson,
  );

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

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseCallHierarchyItem(obj, reporter, 'from',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseListRange(obj, reporter, 'fromRanges',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type CallHierarchyIncomingCall');
      return false;
    }
  }

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

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

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

/// The parameter of a `callHierarchy/incomingCalls` request.
///
/// @since 3.16.0
class CallHierarchyIncomingCallsParams
    implements PartialResultParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CallHierarchyIncomingCallsParams.canParse,
    CallHierarchyIncomingCallsParams.fromJson,
  );

  CallHierarchyIncomingCallsParams({
    required this.item,
    this.partialResultToken,
    this.workDoneToken,
  });
  static CallHierarchyIncomingCallsParams fromJson(Map<String, Object?> json) {
    final itemJson = json['item'];
    final item = CallHierarchyItem.fromJson(itemJson as Map<String, Object?>);
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : _eitherIntString(partialResultTokenJson);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken =
        workDoneTokenJson == null ? null : _eitherIntString(workDoneTokenJson);
    return CallHierarchyIncomingCallsParams(
      item: item,
      partialResultToken: partialResultToken,
      workDoneToken: workDoneToken,
    );
  }

  final CallHierarchyItem item;

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final ProgressToken? partialResultToken;

  /// An optional token that a server can use to report work done progress.
  @override
  final ProgressToken? workDoneToken;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseCallHierarchyItem(obj, reporter, 'item',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseIntString(obj, reporter, 'partialResultToken',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseIntString(obj, reporter, 'workDoneToken',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type CallHierarchyIncomingCallsParams');
      return false;
    }
  }

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

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

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

/// Represents programming constructs like functions or constructors in the
/// context of call hierarchy.
///
/// @since 3.16.0
class CallHierarchyItem implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CallHierarchyItem.canParse,
    CallHierarchyItem.fromJson,
  );

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

  /// A data entry field that is preserved between a call hierarchy prepare and
  /// incoming calls or outgoing calls requests.
  final LSPAny 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`.
  final Range selectionRange;

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseString(obj, reporter, 'detail',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseSymbolKind(obj, reporter, 'kind',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'name',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseRange(obj, reporter, 'range',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseRange(obj, reporter, 'selectionRange',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseListSymbolTag(obj, reporter, 'tags',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseString(obj, reporter, 'uri',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type CallHierarchyItem');
      return false;
    }
  }

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

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

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

/// Call hierarchy options used during static registration.
///
/// @since 3.16.0
class CallHierarchyOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CallHierarchyOptions.canParse,
    CallHierarchyOptions.fromJson,
  );

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

  @override
  final bool? workDoneProgress;

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

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

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

  @override
  int get hashCode => workDoneProgress.hashCode;

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

/// Represents an outgoing call, e.g. calling a getter from a method or a method
/// from a constructor etc.
///
/// @since 3.16.0
class CallHierarchyOutgoingCall implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CallHierarchyOutgoingCall.canParse,
    CallHierarchyOutgoingCall.fromJson,
  );

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

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListRange(obj, reporter, 'fromRanges',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseCallHierarchyItem(obj, reporter, 'to',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type CallHierarchyOutgoingCall');
      return false;
    }
  }

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

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

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

/// The parameter of a `callHierarchy/outgoingCalls` request.
///
/// @since 3.16.0
class CallHierarchyOutgoingCallsParams
    implements PartialResultParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CallHierarchyOutgoingCallsParams.canParse,
    CallHierarchyOutgoingCallsParams.fromJson,
  );

  CallHierarchyOutgoingCallsParams({
    required this.item,
    this.partialResultToken,
    this.workDoneToken,
  });
  static CallHierarchyOutgoingCallsParams fromJson(Map<String, Object?> json) {
    final itemJson = json['item'];
    final item = CallHierarchyItem.fromJson(itemJson as Map<String, Object?>);
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : _eitherIntString(partialResultTokenJson);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken =
        workDoneTokenJson == null ? null : _eitherIntString(workDoneTokenJson);
    return CallHierarchyOutgoingCallsParams(
      item: item,
      partialResultToken: partialResultToken,
      workDoneToken: workDoneToken,
    );
  }

  final CallHierarchyItem item;

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final ProgressToken? partialResultToken;

  /// An optional token that a server can use to report work done progress.
  @override
  final ProgressToken? workDoneToken;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseCallHierarchyItem(obj, reporter, 'item',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseIntString(obj, reporter, 'partialResultToken',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseIntString(obj, reporter, 'workDoneToken',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type CallHierarchyOutgoingCallsParams');
      return false;
    }
  }

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

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

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

/// The parameter of a `textDocument/prepareCallHierarchy` request.
///
/// @since 3.16.0
class CallHierarchyPrepareParams
    implements TextDocumentPositionParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CallHierarchyPrepareParams.canParse,
    CallHierarchyPrepareParams.fromJson,
  );

  CallHierarchyPrepareParams({
    required this.position,
    required this.textDocument,
    this.workDoneToken,
  });
  static CallHierarchyPrepareParams fromJson(Map<String, Object?> json) {
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken =
        workDoneTokenJson == null ? null : _eitherIntString(workDoneTokenJson);
    return CallHierarchyPrepareParams(
      position: position,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

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

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

  /// An optional token that a server can use to report work done progress.
  @override
  final ProgressToken? workDoneToken;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParsePosition(obj, reporter, 'position',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseIntString(obj, reporter, 'workDoneToken',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type CallHierarchyPrepareParams');
      return false;
    }
  }

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

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

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

/// Call hierarchy options used during static or dynamic registration.
///
/// @since 3.16.0
class CallHierarchyRegistrationOptions
    implements
        CallHierarchyOptions,
        StaticRegistrationOptions,
        TextDocumentRegistrationOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CallHierarchyRegistrationOptions.canParse,
    CallHierarchyRegistrationOptions.fromJson,
  );

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

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListTextDocumentFilterWithScheme(
          obj, reporter, 'documentSelector',
          allowsUndefined: false, allowsNull: true)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'id',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'workDoneProgress',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type CallHierarchyRegistrationOptions');
      return false;
    }
  }

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

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

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

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

  CancelParams({
    required this.id,
  });
  static CancelParams fromJson(Map<String, Object?> json) {
    final idJson = json['id'];
    final id = _eitherIntString(idJson);
    return CancelParams(
      id: id,
    );
  }

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseIntString(obj, reporter, 'id',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type CancelParams');
      return false;
    }
  }

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

  @override
  int get hashCode => id.hashCode;

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

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

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

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

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseString(obj, reporter, 'description',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'label',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'needsConfirmation',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type ChangeAnnotation');
      return false;
    }
  }

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

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

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

/// Defines the capabilities provided by the client.
class ClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ClientCapabilities.canParse,
    ClientCapabilities.fromJson,
  );

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

  /// Experimental client capabilities.
  final LSPAny experimental;

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

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

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

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseGeneralClientCapabilities(obj, reporter, 'general',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseNotebookDocumentClientCapabilities(
          obj, reporter, 'notebookDocument',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseTextDocumentClientCapabilities(
          obj, reporter, 'textDocument',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseWindowClientCapabilities(obj, reporter, 'window',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseWorkspaceClientCapabilities(obj, reporter, 'workspace',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type ClientCapabilities');
      return false;
    }
  }

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

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

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

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

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

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

  /// A data entry field that is preserved on a code action between a
  /// `textDocument/codeAction` and a `codeAction/resolve` request.
  ///
  /// @since 3.16.0
  final LSPAny 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](https://code.visualstudio.com/docs/editor/editingevolved#_code-action)
  ///     code action menus.
  ///
  ///   - Disabled actions are shown as faded out in the code action menu when
  /// the user requests a more specific type
  ///     of code action, such as refactorings.
  ///
  ///   - If the user has a
  /// [keybinding](https://code.visualstudio.com/docs/editor/refactoring#_keybindings-for-code-actions)
  ///     that auto applies a code action and only disabled code actions are
  /// returned, the client should show the user an
  ///     error message with `reason` in the editor.
  ///
  /// @since 3.16.0
  final CodeActionDisabled? disabled;

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

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

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseCommand(obj, reporter, 'command',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseListDiagnostic(obj, reporter, 'diagnostics',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseCodeActionDisabled(obj, reporter, 'disabled',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseWorkspaceEdit(obj, reporter, 'edit',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'isPreferred',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseCodeActionKind(obj, reporter, 'kind',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseString(obj, reporter, 'title',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type CodeAction');
      return false;
    }
  }

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

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

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

/// The Client Capabilities of a CodeActionRequest.
class CodeActionClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CodeActionClientCapabilities.canParse,
    CodeActionClientCapabilities.fromJson,
  );

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

  /// The client support code action literals of type `CodeAction` as a valid
  /// response of the `textDocument/codeAction` request. If the property is not
  /// set the request can only return `Command` literals.
  ///
  /// @since 3.8.0
  final CodeActionClientCapabilitiesCodeActionLiteralSupport?
      codeActionLiteralSupport;

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

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

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

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

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseCodeActionClientCapabilitiesCodeActionLiteralSupport(
          obj, reporter, 'codeActionLiteralSupport',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'dataSupport',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'disabledSupport',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'dynamicRegistration',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'honorsChangeAnnotations',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'isPreferredSupport',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseCodeActionClientCapabilitiesResolveSupport(
          obj, reporter, 'resolveSupport',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type CodeActionClientCapabilities');
      return false;
    }
  }

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

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

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

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

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseCodeActionLiteralSupportCodeActionKind(
          obj, reporter, 'codeActionKind',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError(
          'must be of type CodeActionClientCapabilitiesCodeActionLiteralSupport');
      return false;
    }
  }

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

  @override
  int get hashCode => codeActionKind.hashCode;

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

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

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseListString(obj, reporter, 'properties',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError(
          'must be of type CodeActionClientCapabilitiesResolveSupport');
      return false;
    }
  }

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

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

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

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

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

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

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListDiagnostic(obj, reporter, 'diagnostics',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseListCodeActionKind(obj, reporter, 'only',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseCodeActionTriggerKind(obj, reporter, 'triggerKind',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type CodeActionContext');
      return false;
    }
  }

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

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

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

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

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseString(obj, reporter, 'reason',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type CodeActionDisabled');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is CodeActionDisabled &&
        other.runtimeType == CodeActionDisabled &&
        reason == other.reason;
  }

  @override
  int get hashCode => reason.hashCode;

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

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

  final String _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) => 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 auto-fix source actions: `source.fixAll`.
  ///
  /// Fix all actions automatically fix errors that have a clear fix that do not
  /// require user input. They should not suppress errors or perform unsafe
  /// fixes such as generating new types or classes.
  ///
  /// @since 3.15.0
  static const SourceFixAll = CodeActionKind('source.fixAll');

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

  @override
  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

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

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

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseListCodeActionKind(obj, reporter, 'valueSet',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError(
          'must be of type CodeActionLiteralSupportCodeActionKind');
      return false;
    }
  }

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

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

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

/// Provider options for a CodeActionRequest.
class CodeActionOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CodeActionOptions.canParse,
    CodeActionOptions.fromJson,
  );

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

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListCodeActionKind(obj, reporter, 'codeActionKinds',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'resolveProvider',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'workDoneProgress',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type CodeActionOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is CodeActionOptions &&
        other.runtimeType == CodeActionOptions &&
        listEqual(codeActionKinds, other.codeActionKinds,
            (CodeActionKind a, CodeActionKind b) => a == b) &&
        resolveProvider == other.resolveProvider &&
        workDoneProgress == other.workDoneProgress;
  }

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

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

/// The parameters of a CodeActionRequest.
class CodeActionParams
    implements PartialResultParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CodeActionParams.canParse,
    CodeActionParams.fromJson,
  );

  CodeActionParams({
    required this.context,
    this.partialResultToken,
    required this.range,
    required this.textDocument,
    this.workDoneToken,
  });
  static CodeActionParams fromJson(Map<String, Object?> json) {
    final contextJson = json['context'];
    final context =
        CodeActionContext.fromJson(contextJson as Map<String, Object?>);
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : _eitherIntString(partialResultTokenJson);
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken =
        workDoneTokenJson == null ? null : _eitherIntString(workDoneTokenJson);
    return CodeActionParams(
      context: context,
      partialResultToken: partialResultToken,
      range: range,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

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

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final ProgressToken? partialResultToken;

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

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

  /// An optional token that a server can use to report work done progress.
  @override
  final ProgressToken? workDoneToken;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseCodeActionContext(obj, reporter, 'context',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseIntString(obj, reporter, 'partialResultToken',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseRange(obj, reporter, 'range',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseIntString(obj, reporter, 'workDoneToken',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type CodeActionParams');
      return false;
    }
  }

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

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

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

/// Registration options for a CodeActionRequest.
class CodeActionRegistrationOptions
    implements CodeActionOptions, TextDocumentRegistrationOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CodeActionRegistrationOptions.canParse,
    CodeActionRegistrationOptions.fromJson,
  );

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

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

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListCodeActionKind(obj, reporter, 'codeActionKinds',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseListTextDocumentFilterWithScheme(
          obj, reporter, 'documentSelector',
          allowsUndefined: false, allowsNull: true)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'resolveProvider',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'workDoneProgress',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type CodeActionRegistrationOptions');
      return false;
    }
  }

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

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

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

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

  final int _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is int;

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

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

  @override
  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

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

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

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseString(obj, reporter, 'href',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type CodeDescription');
      return false;
    }
  }

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

  @override
  int get hashCode => href.hashCode;

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

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

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

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

  /// A data entry field that is preserved on a code lens item between a
  /// CodeLensRequest and a CodeLensResolveRequest
  final LSPAny data;

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseCommand(obj, reporter, 'command',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseRange(obj, reporter, 'range',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type CodeLens');
      return false;
    }
  }

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

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

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

/// The client capabilities  of a CodeLensRequest.
class CodeLensClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CodeLensClientCapabilities.canParse,
    CodeLensClientCapabilities.fromJson,
  );

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

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

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

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

  @override
  bool operator ==(Object other) {
    return other is CodeLensClientCapabilities &&
        other.runtimeType == CodeLensClientCapabilities &&
        dynamicRegistration == other.dynamicRegistration;
  }

  @override
  int get hashCode => dynamicRegistration.hashCode;

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

/// Code Lens provider options of a CodeLensRequest.
class CodeLensOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CodeLensOptions.canParse,
    CodeLensOptions.fromJson,
  );

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseBool(obj, reporter, 'resolveProvider',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'workDoneProgress',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type CodeLensOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is CodeLensOptions &&
        other.runtimeType == CodeLensOptions &&
        resolveProvider == other.resolveProvider &&
        workDoneProgress == other.workDoneProgress;
  }

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

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

/// The parameters of a CodeLensRequest.
class CodeLensParams
    implements PartialResultParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CodeLensParams.canParse,
    CodeLensParams.fromJson,
  );

  CodeLensParams({
    this.partialResultToken,
    required this.textDocument,
    this.workDoneToken,
  });
  static CodeLensParams fromJson(Map<String, Object?> json) {
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : _eitherIntString(partialResultTokenJson);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken =
        workDoneTokenJson == null ? null : _eitherIntString(workDoneTokenJson);
    return CodeLensParams(
      partialResultToken: partialResultToken,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final ProgressToken? partialResultToken;

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

  /// An optional token that a server can use to report work done progress.
  @override
  final ProgressToken? workDoneToken;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseIntString(obj, reporter, 'partialResultToken',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseIntString(obj, reporter, 'workDoneToken',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type CodeLensParams');
      return false;
    }
  }

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

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

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

/// Registration options for a CodeLensRequest.
class CodeLensRegistrationOptions
    implements CodeLensOptions, TextDocumentRegistrationOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CodeLensRegistrationOptions.canParse,
    CodeLensRegistrationOptions.fromJson,
  );

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

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListTextDocumentFilterWithScheme(
          obj, reporter, 'documentSelector',
          allowsUndefined: false, allowsNull: true)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'resolveProvider',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'workDoneProgress',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type CodeLensRegistrationOptions');
      return false;
    }
  }

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

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

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

/// @since 3.16.0
class CodeLensWorkspaceClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CodeLensWorkspaceClientCapabilities.canParse,
    CodeLensWorkspaceClientCapabilities.fromJson,
  );

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

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

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

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

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

  @override
  int get hashCode => refreshSupport.hashCode;

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

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

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

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

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

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseNum(obj, reporter, 'alpha',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseNum(obj, reporter, 'blue',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseNum(obj, reporter, 'green',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseNum(obj, reporter, 'red',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type Color');
      return false;
    }
  }

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

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

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

/// Represents a color range from a document.
class ColorInformation implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ColorInformation.canParse,
    ColorInformation.fromJson,
  );

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

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseColor(obj, reporter, 'color',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseRange(obj, reporter, 'range',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type ColorInformation');
      return false;
    }
  }

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

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

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

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

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

  /// An optional array of additional text edits that are applied when selecting
  /// this color presentation. Edits must not overlap with the main edit 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 which is applied to a document when selecting this presentation
  /// for the color.  When `falsy` the label is used.
  final TextEdit? textEdit;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListTextEdit(obj, reporter, 'additionalTextEdits',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'label',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseTextEdit(obj, reporter, 'textEdit',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type ColorPresentation');
      return false;
    }
  }

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

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

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

/// Parameters for a ColorPresentationRequest.
class ColorPresentationParams
    implements PartialResultParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ColorPresentationParams.canParse,
    ColorPresentationParams.fromJson,
  );

  ColorPresentationParams({
    required this.color,
    this.partialResultToken,
    required this.range,
    required this.textDocument,
    this.workDoneToken,
  });
  static ColorPresentationParams fromJson(Map<String, Object?> json) {
    final colorJson = json['color'];
    final color = Color.fromJson(colorJson as Map<String, Object?>);
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : _eitherIntString(partialResultTokenJson);
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken =
        workDoneTokenJson == null ? null : _eitherIntString(workDoneTokenJson);
    return ColorPresentationParams(
      color: color,
      partialResultToken: partialResultToken,
      range: range,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

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

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final ProgressToken? partialResultToken;

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

  /// The text document.
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final ProgressToken? workDoneToken;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseColor(obj, reporter, 'color',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseIntString(obj, reporter, 'partialResultToken',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseRange(obj, reporter, 'range',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseIntString(obj, reporter, 'workDoneToken',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type ColorPresentationParams');
      return false;
    }
  }

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

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

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

/// Represents a reference to a command. Provides a title which will be used to
/// represent a command in the UI and, optionally,
/// an array of arguments which will be passed to the command handler function
/// when invoked.
class Command implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    Command.canParse,
    Command.fromJson,
  );

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

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

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListObjectNullable(obj, reporter, 'arguments',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'command',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseString(obj, reporter, 'title',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type Command');
      return false;
    }
  }

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

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

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

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

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

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

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

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

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

  /// Defines how the client handles whitespace and indentation when accepting a
  /// completion item that uses multi line text in either `insertText` or
  /// `textEdit`.
  ///
  /// @since 3.17.0
  final InsertTextMode? insertTextMode;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseCompletionClientCapabilitiesCompletionItem(
          obj, reporter, 'completionItem',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseCompletionClientCapabilitiesCompletionItemKind(
          obj, reporter, 'completionItemKind',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseCompletionClientCapabilitiesCompletionList(
          obj, reporter, 'completionList',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'contextSupport',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'dynamicRegistration',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseInsertTextMode(obj, reporter, 'insertTextMode',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type CompletionClientCapabilities');
      return false;
    }
  }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseBool(obj, reporter, 'commitCharactersSupport',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'deprecatedSupport',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseListMarkupKind(obj, reporter, 'documentationFormat',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'insertReplaceSupport',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseCompletionItemInsertTextModeSupport(
          obj, reporter, 'insertTextModeSupport',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'labelDetailsSupport',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'preselectSupport',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseCompletionItemResolveSupport(
          obj, reporter, 'resolveSupport',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'snippetSupport',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseCompletionItemTagSupport(obj, reporter, 'tagSupport',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError(
          'must be of type CompletionClientCapabilitiesCompletionItem');
      return false;
    }
  }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseString(obj, reporter, 'triggerCharacter',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseCompletionTriggerKind(obj, reporter, 'triggerKind',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type CompletionContext');
      return false;
    }
  }

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

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

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

/// A completion item represents a text snippet that is proposed to complete
/// text that is being typed.
class CompletionItem implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CompletionItem.canParse,
    CompletionItem.fromJson,
  );

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

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

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

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

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

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

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

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

  /// A string that should be used when filtering a set of completion items.
  /// When `falsy` the label is used.
  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`.
  ///
  /// Please note that the insertTextFormat doesn't apply to
  /// `additionalTextEdits`.
  final InsertTextFormat? insertTextFormat;

  /// How whitespace and indentation is handled during completion item
  /// insertion. If not provided the clients 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.
  final CompletionItemKind? kind;

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

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

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

  /// A string that should be used when comparing this item with other items.
  /// When `falsy` the label is used.
  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.
  ///
  /// 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<InsertReplaceEdit, TextEdit>? textEdit;

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListTextEdit(obj, reporter, 'additionalTextEdits',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseCommand(obj, reporter, 'command',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseListString(obj, reporter, 'commitCharacters',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseCompletionItemResolutionInfo(obj, reporter, 'data',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'deprecated',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'detail',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseMarkupContentString(obj, reporter, 'documentation',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'filterText',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'insertText',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseInsertTextFormat(obj, reporter, 'insertTextFormat',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseInsertTextMode(obj, reporter, 'insertTextMode',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseCompletionItemKind(obj, reporter, 'kind',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'label',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseCompletionItemLabelDetails(obj, reporter, 'labelDetails',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'preselect',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'sortText',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseListCompletionItemTag(obj, reporter, 'tags',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseInsertReplaceEditTextEdit(obj, reporter, 'textEdit',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseString(obj, reporter, 'textEditText',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type CompletionItem');
      return false;
    }
  }

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

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

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

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

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

  final Range insert;
  final Range replace;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseRange(obj, reporter, 'insert',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseRange(obj, reporter, 'replace',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type CompletionItemEditRange');
      return false;
    }
  }

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

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

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

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

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

  final List<InsertTextMode> valueSet;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseListInsertTextMode(obj, reporter, 'valueSet',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter
          .reportError('must be of type CompletionItemInsertTextModeSupport');
      return false;
    }
  }

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

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

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

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

  final int _value;

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

  @override
  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

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

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

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

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseString(obj, reporter, 'description',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseString(obj, reporter, 'detail',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type CompletionItemLabelDetails');
      return false;
    }
  }

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

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

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

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

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseListString(obj, reporter, 'properties',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type CompletionItemResolveSupport');
      return false;
    }
  }

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

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

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

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

  final int _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is int;

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

  @override
  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

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

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

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseListCompletionItemTag(obj, reporter, 'valueSet',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type CompletionItemTagSupport');
      return false;
    }
  }

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

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

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

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

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

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

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseBool(obj, reporter, 'isIncomplete',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseCompletionListItemDefaults(obj, reporter, 'itemDefaults',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseListCompletionItem(obj, reporter, 'items',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type CompletionList');
      return false;
    }
  }

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

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

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

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

  CompletionListItemDefaults({
    this.commitCharacters,
    this.data,
    this.editRange,
    this.insertTextFormat,
    this.insertTextMode,
  });
  static CompletionListItemDefaults fromJson(Map<String, Object?> json) {
    final commitCharactersJson = json['commitCharacters'];
    final commitCharacters = (commitCharactersJson as List<Object?>?)
        ?.map((item) => item as String)
        .toList();
    final dataJson = json['data'];
    final data = dataJson;
    final editRangeJson = json['editRange'];
    final editRange = editRangeJson == null
        ? null
        : _eitherCompletionItemEditRangeRange(editRangeJson);
    final insertTextFormatJson = json['insertTextFormat'];
    final insertTextFormat = insertTextFormatJson != null
        ? InsertTextFormat.fromJson(insertTextFormatJson as int)
        : null;
    final insertTextModeJson = json['insertTextMode'];
    final insertTextMode = insertTextModeJson != null
        ? InsertTextMode.fromJson(insertTextModeJson as int)
        : null;
    return CompletionListItemDefaults(
      commitCharacters: commitCharacters,
      data: data,
      editRange: editRange,
      insertTextFormat: insertTextFormat,
      insertTextMode: insertTextMode,
    );
  }

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

  /// A default data value.
  ///
  /// @since 3.17.0
  final LSPAny data;

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

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListString(obj, reporter, 'commitCharacters',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseCompletionItemEditRangeRange(obj, reporter, 'editRange',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseInsertTextFormat(obj, reporter, 'insertTextFormat',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseInsertTextMode(obj, reporter, 'insertTextMode',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type CompletionListItemDefaults');
      return false;
    }
  }

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

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

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

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

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

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

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

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListString(obj, reporter, 'allCommitCharacters',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseCompletionOptionsCompletionItem(
          obj, reporter, 'completionItem',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'resolveProvider',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseListString(obj, reporter, 'triggerCharacters',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'workDoneProgress',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type CompletionOptions');
      return false;
    }
  }

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

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

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

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

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

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

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

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

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

  @override
  int get hashCode => labelDetailsSupport.hashCode;

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

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

  CompletionParams({
    this.context,
    this.partialResultToken,
    required this.position,
    required this.textDocument,
    this.workDoneToken,
  });
  static CompletionParams fromJson(Map<String, Object?> json) {
    final contextJson = json['context'];
    final context = contextJson != null
        ? CompletionContext.fromJson(contextJson as Map<String, Object?>)
        : null;
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : _eitherIntString(partialResultTokenJson);
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken =
        workDoneTokenJson == null ? null : _eitherIntString(workDoneTokenJson);
    return CompletionParams(
      context: context,
      partialResultToken: partialResultToken,
      position: position,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

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

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final ProgressToken? partialResultToken;

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

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

  /// An optional token that a server can use to report work done progress.
  @override
  final ProgressToken? workDoneToken;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseCompletionContext(obj, reporter, 'context',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseIntString(obj, reporter, 'partialResultToken',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParsePosition(obj, reporter, 'position',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseIntString(obj, reporter, 'workDoneToken',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type CompletionParams');
      return false;
    }
  }

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

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

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

/// Registration options for a CompletionRequest.
class CompletionRegistrationOptions
    implements CompletionOptions, TextDocumentRegistrationOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CompletionRegistrationOptions.canParse,
    CompletionRegistrationOptions.fromJson,
  );

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

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

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

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

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListString(obj, reporter, 'allCommitCharacters',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseCompletionOptionsCompletionItem(
          obj, reporter, 'completionItem',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseListTextDocumentFilterWithScheme(
          obj, reporter, 'documentSelector',
          allowsUndefined: false, allowsNull: true)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'resolveProvider',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseListString(obj, reporter, 'triggerCharacters',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'workDoneProgress',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type CompletionRegistrationOptions');
      return false;
    }
  }

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

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

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

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

  final int _value;

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

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

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

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

  @override
  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

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

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

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

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseString(obj, reporter, 'scopeUri',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseString(obj, reporter, 'section',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type ConfigurationItem');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ConfigurationItem &&
        other.runtimeType == ConfigurationItem &&
        scopeUri == other.scopeUri &&
        section == other.section;
  }

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

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

/// The parameters of a configuration request.
class ConfigurationParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ConfigurationParams.canParse,
    ConfigurationParams.fromJson,
  );

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

  final List<ConfigurationItem> items;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseListConfigurationItem(obj, reporter, 'items',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type ConfigurationParams');
      return false;
    }
  }

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

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

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

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

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

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

  /// A create
  @override
  final String kind;

  /// Additional options
  final CreateFileOptions? options;

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseString(obj, reporter, 'annotationId',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseLiteral(obj, reporter, 'kind',
          allowsUndefined: false, allowsNull: false, literal: 'create')) {
        return false;
      }
      if (!_canParseCreateFileOptions(obj, reporter, 'options',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseString(obj, reporter, 'uri',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type CreateFile');
      return false;
    }
  }

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

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

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

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

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

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseBool(obj, reporter, 'ignoreIfExists',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'overwrite',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type CreateFileOptions');
      return false;
    }
  }

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

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

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

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

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseListFileCreate(obj, reporter, 'files',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type CreateFilesParams');
      return false;
    }
  }

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

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

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

/// @since 3.14.0
class DeclarationClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DeclarationClientCapabilities.canParse,
    DeclarationClientCapabilities.fromJson,
  );

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

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseBool(obj, reporter, 'dynamicRegistration',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'linkSupport',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type DeclarationClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DeclarationClientCapabilities &&
        other.runtimeType == DeclarationClientCapabilities &&
        dynamicRegistration == other.dynamicRegistration &&
        linkSupport == other.linkSupport;
  }

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

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

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

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

  @override
  final bool? workDoneProgress;

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

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

  @override
  bool operator ==(Object other) {
    return other is DeclarationOptions &&
        other.runtimeType == DeclarationOptions &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => workDoneProgress.hashCode;

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

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

  DeclarationParams({
    this.partialResultToken,
    required this.position,
    required this.textDocument,
    this.workDoneToken,
  });
  static DeclarationParams fromJson(Map<String, Object?> json) {
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : _eitherIntString(partialResultTokenJson);
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken =
        workDoneTokenJson == null ? null : _eitherIntString(workDoneTokenJson);
    return DeclarationParams(
      partialResultToken: partialResultToken,
      position: position,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final ProgressToken? partialResultToken;

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

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

  /// An optional token that a server can use to report work done progress.
  @override
  final ProgressToken? workDoneToken;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseIntString(obj, reporter, 'partialResultToken',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParsePosition(obj, reporter, 'position',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseIntString(obj, reporter, 'workDoneToken',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type DeclarationParams');
      return false;
    }
  }

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

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

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

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

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

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListTextDocumentFilterWithScheme(
          obj, reporter, 'documentSelector',
          allowsUndefined: false, allowsNull: true)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'id',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'workDoneProgress',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type DeclarationRegistrationOptions');
      return false;
    }
  }

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

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

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

/// Client Capabilities for a DefinitionRequest.
class DefinitionClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DefinitionClientCapabilities.canParse,
    DefinitionClientCapabilities.fromJson,
  );

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

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseBool(obj, reporter, 'dynamicRegistration',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'linkSupport',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type DefinitionClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DefinitionClientCapabilities &&
        other.runtimeType == DefinitionClientCapabilities &&
        dynamicRegistration == other.dynamicRegistration &&
        linkSupport == other.linkSupport;
  }

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

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

/// Server Capabilities for a DefinitionRequest.
class DefinitionOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DefinitionOptions.canParse,
    DefinitionOptions.fromJson,
  );

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

  @override
  final bool? workDoneProgress;

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

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

  @override
  bool operator ==(Object other) {
    return other is DefinitionOptions &&
        other.runtimeType == DefinitionOptions &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => workDoneProgress.hashCode;

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

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

  DefinitionParams({
    this.partialResultToken,
    required this.position,
    required this.textDocument,
    this.workDoneToken,
  });
  static DefinitionParams fromJson(Map<String, Object?> json) {
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : _eitherIntString(partialResultTokenJson);
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken =
        workDoneTokenJson == null ? null : _eitherIntString(workDoneTokenJson);
    return DefinitionParams(
      partialResultToken: partialResultToken,
      position: position,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final ProgressToken? partialResultToken;

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

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

  /// An optional token that a server can use to report work done progress.
  @override
  final ProgressToken? workDoneToken;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseIntString(obj, reporter, 'partialResultToken',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParsePosition(obj, reporter, 'position',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseIntString(obj, reporter, 'workDoneToken',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type DefinitionParams');
      return false;
    }
  }

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

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

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

/// Registration options for a DefinitionRequest.
class DefinitionRegistrationOptions
    implements DefinitionOptions, TextDocumentRegistrationOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DefinitionRegistrationOptions.canParse,
    DefinitionRegistrationOptions.fromJson,
  );

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListTextDocumentFilterWithScheme(
          obj, reporter, 'documentSelector',
          allowsUndefined: false, allowsNull: true)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'workDoneProgress',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type DefinitionRegistrationOptions');
      return false;
    }
  }

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

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

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

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

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

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

  /// A delete
  @override
  final String kind;

  /// Delete options.
  final DeleteFileOptions? options;

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseString(obj, reporter, 'annotationId',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseLiteral(obj, reporter, 'kind',
          allowsUndefined: false, allowsNull: false, literal: 'delete')) {
        return false;
      }
      if (!_canParseDeleteFileOptions(obj, reporter, 'options',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseString(obj, reporter, 'uri',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type DeleteFile');
      return false;
    }
  }

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

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

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

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

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

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseBool(obj, reporter, 'ignoreIfNotExists',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'recursive',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type DeleteFileOptions');
      return false;
    }
  }

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

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

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

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

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseListFileDelete(obj, reporter, 'files',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type DeleteFilesParams');
      return false;
    }
  }

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

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

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

/// Represents a diagnostic, such as a compiler error or warning. Diagnostic
/// objects are only valid in the scope of a resource.
class Diagnostic implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    Diagnostic.canParse,
    Diagnostic.fromJson,
  );

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

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

  /// An optional property to describe the error code. Requires the code field
  /// (above) to be present/not null.
  ///
  /// @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 LSPAny data;

  /// The diagnostic's message. It usually appears in the user interface
  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'. It usually appears in the user interface.
  final String? source;

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseString(obj, reporter, 'code',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseCodeDescription(obj, reporter, 'codeDescription',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'message',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseRange(obj, reporter, 'range',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseListDiagnosticRelatedInformation(
          obj, reporter, 'relatedInformation',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseDiagnosticSeverity(obj, reporter, 'severity',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'source',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseListDiagnosticTag(obj, reporter, 'tags',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type Diagnostic');
      return false;
    }
  }

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

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

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

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

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

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseBool(obj, reporter, 'dynamicRegistration',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'relatedDocumentSupport',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type DiagnosticClientCapabilities');
      return false;
    }
  }

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

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

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

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

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

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

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseString(obj, reporter, 'identifier',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'interFileDependencies',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'workDoneProgress',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'workspaceDiagnostics',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type DiagnosticOptions');
      return false;
    }
  }

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

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

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

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

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

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

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

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

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListTextDocumentFilterWithScheme(
          obj, reporter, 'documentSelector',
          allowsUndefined: false, allowsNull: true)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'id',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'identifier',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'interFileDependencies',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'workDoneProgress',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'workspaceDiagnostics',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type DiagnosticRegistrationOptions');
      return false;
    }
  }

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

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

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

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

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

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseLocation(obj, reporter, 'location',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseString(obj, reporter, 'message',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type DiagnosticRelatedInformation');
      return false;
    }
  }

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

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

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

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

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

  final bool retriggerRequest;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseBool(obj, reporter, 'retriggerRequest',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type DiagnosticServerCancellationData');
      return false;
    }
  }

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

  @override
  int get hashCode => retriggerRequest.hashCode;

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

/// The diagnostic's severity.
class DiagnosticSeverity implements ToJsonable {
  const DiagnosticSeverity(this._value);
  const DiagnosticSeverity.fromJson(this._value);

  final int _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is int;

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

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

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

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

  @override
  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

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

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

  final int _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is int;

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

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

  @override
  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

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

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

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

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

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

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

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

  @override
  int get hashCode => refreshSupport.hashCode;

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

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

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

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

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

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

  @override
  bool operator ==(Object other) {
    return other is DidChangeConfigurationClientCapabilities &&
        other.runtimeType == DidChangeConfigurationClientCapabilities &&
        dynamicRegistration == other.dynamicRegistration;
  }

  @override
  int get hashCode => dynamicRegistration.hashCode;

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

/// The parameters of a change configuration notification.
class DidChangeConfigurationParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DidChangeConfigurationParams.canParse,
    DidChangeConfigurationParams.fromJson,
  );

  DidChangeConfigurationParams({
    this.settings,
  });
  static DidChangeConfigurationParams fromJson(Map<String, Object?> json) {
    final settingsJson = json['settings'];
    final settings = settingsJson;
    return DidChangeConfigurationParams(
      settings: settings,
    );
  }

  /// The actual changed settings
  final LSPAny settings;

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

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

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

  @override
  int get hashCode => settings.hashCode;

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

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

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

  /// The actual changes to the notebook document.
  ///
  /// The changes describe single state changes to the notebook document. So if
  /// there are two changes c1 (at array index 0) and c2 (at array index 1) for
  /// a notebook in state S then c1 moves the notebook 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 notebook using change events use the following
  /// approach:
  /// - start with the same initial content
  /// - apply the 'notebookDocument/didChange' notifications in the order you
  /// receive them.
  /// - apply the `NotebookChangeEvent`s in a single notification in the order
  ///   you receive them.
  final NotebookDocumentChangeEvent change;

  /// The notebook document that did change. The version number points to the
  /// version after all provided changes have been applied. If only the text
  /// document content of a cell changes the notebook version doesn't
  /// necessarily have to change.
  final VersionedNotebookDocumentIdentifier notebookDocument;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseNotebookDocumentChangeEvent(obj, reporter, 'change',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseVersionedNotebookDocumentIdentifier(
          obj, reporter, 'notebookDocument',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type DidChangeNotebookDocumentParams');
      return false;
    }
  }

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

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

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

/// The change text document notification's parameters.
class DidChangeTextDocumentParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DidChangeTextDocumentParams.canParse,
    DidChangeTextDocumentParams.fromJson,
  );

  DidChangeTextDocumentParams({
    required this.contentChanges,
    required this.textDocument,
  });
  static DidChangeTextDocumentParams fromJson(Map<String, Object?> json) {
    final contentChangesJson = json['contentChanges'];
    final contentChanges = (contentChangesJson as List<Object?>)
        .map((item) =>
            _eitherTextDocumentContentChangeEvent1TextDocumentContentChangeEvent2(
                item))
        .toList();
    final textDocumentJson = json['textDocument'];
    final textDocument = VersionedTextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    return DidChangeTextDocumentParams(
      contentChanges: contentChanges,
      textDocument: textDocument,
    );
  }

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListTextDocumentContentChangeEvent1TextDocumentContentChangeEvent2(
          obj, reporter, 'contentChanges',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseVersionedTextDocumentIdentifier(
          obj, reporter, 'textDocument',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type DidChangeTextDocumentParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DidChangeTextDocumentParams &&
        other.runtimeType == DidChangeTextDocumentParams &&
        listEqual(
            contentChanges,
            other.contentChanges,
            (TextDocumentContentChangeEvent a,
                    TextDocumentContentChangeEvent b) =>
                a == b) &&
        textDocument == other.textDocument;
  }

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

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

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

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

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

  /// Whether the client has support for {@link  RelativePattern relative
  /// pattern}
  /// or not.
  ///
  /// @since 3.17.0
  final bool? relativePatternSupport;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseBool(obj, reporter, 'dynamicRegistration',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'relativePatternSupport',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError(
          'must be of type DidChangeWatchedFilesClientCapabilities');
      return false;
    }
  }

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

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

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

/// The watched files change notification's parameters.
class DidChangeWatchedFilesParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DidChangeWatchedFilesParams.canParse,
    DidChangeWatchedFilesParams.fromJson,
  );

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseListFileEvent(obj, reporter, 'changes',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type DidChangeWatchedFilesParams');
      return false;
    }
  }

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

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

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

/// Describe options to be used when registered for text document change events.
class DidChangeWatchedFilesRegistrationOptions implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DidChangeWatchedFilesRegistrationOptions.canParse,
    DidChangeWatchedFilesRegistrationOptions.fromJson,
  );

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseListFileSystemWatcher(obj, reporter, 'watchers',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError(
          'must be of type DidChangeWatchedFilesRegistrationOptions');
      return false;
    }
  }

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

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

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

/// The parameters of a `workspace/didChangeWorkspaceFolders` notification.
class DidChangeWorkspaceFoldersParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DidChangeWorkspaceFoldersParams.canParse,
    DidChangeWorkspaceFoldersParams.fromJson,
  );

  DidChangeWorkspaceFoldersParams({
    required this.event,
  });
  static DidChangeWorkspaceFoldersParams fromJson(Map<String, Object?> json) {
    final eventJson = json['event'];
    final event =
        WorkspaceFoldersChangeEvent.fromJson(eventJson as Map<String, Object?>);
    return DidChangeWorkspaceFoldersParams(
      event: event,
    );
  }

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseWorkspaceFoldersChangeEvent(obj, reporter, 'event',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type DidChangeWorkspaceFoldersParams');
      return false;
    }
  }

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

  @override
  int get hashCode => event.hashCode;

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

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

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

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListTextDocumentIdentifier(
          obj, reporter, 'cellTextDocuments',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseNotebookDocumentIdentifier(
          obj, reporter, 'notebookDocument',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type DidCloseNotebookDocumentParams');
      return false;
    }
  }

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

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

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

/// The parameters sent in a close text document notification
class DidCloseTextDocumentParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DidCloseTextDocumentParams.canParse,
    DidCloseTextDocumentParams.fromJson,
  );

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type DidCloseTextDocumentParams');
      return false;
    }
  }

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

  @override
  int get hashCode => textDocument.hashCode;

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

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

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

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListTextDocumentItem(obj, reporter, 'cellTextDocuments',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseNotebookDocument(obj, reporter, 'notebookDocument',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type DidOpenNotebookDocumentParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DidOpenNotebookDocumentParams &&
        other.runtimeType == DidOpenNotebookDocumentParams &&
        listEqual(cellTextDocuments, other.cellTextDocuments,
            (TextDocumentItem a, TextDocumentItem b) => a == b) &&
        notebookDocument == other.notebookDocument;
  }

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

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

/// The parameters sent in an open text document notification
class DidOpenTextDocumentParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DidOpenTextDocumentParams.canParse,
    DidOpenTextDocumentParams.fromJson,
  );

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseTextDocumentItem(obj, reporter, 'textDocument',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type DidOpenTextDocumentParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DidOpenTextDocumentParams &&
        other.runtimeType == DidOpenTextDocumentParams &&
        textDocument == other.textDocument;
  }

  @override
  int get hashCode => textDocument.hashCode;

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

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

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseNotebookDocumentIdentifier(
          obj, reporter, 'notebookDocument',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type DidSaveNotebookDocumentParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DidSaveNotebookDocumentParams &&
        other.runtimeType == DidSaveNotebookDocumentParams &&
        notebookDocument == other.notebookDocument;
  }

  @override
  int get hashCode => notebookDocument.hashCode;

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

/// The parameters sent in a save text document notification
class DidSaveTextDocumentParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DidSaveTextDocumentParams.canParse,
    DidSaveTextDocumentParams.fromJson,
  );

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

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseString(obj, reporter, 'text',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type DidSaveTextDocumentParams');
      return false;
    }
  }

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

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

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

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

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

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

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

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

  @override
  bool operator ==(Object other) {
    return other is DocumentColorClientCapabilities &&
        other.runtimeType == DocumentColorClientCapabilities &&
        dynamicRegistration == other.dynamicRegistration;
  }

  @override
  int get hashCode => dynamicRegistration.hashCode;

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

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

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

  @override
  final bool? workDoneProgress;

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

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

  @override
  bool operator ==(Object other) {
    return other is DocumentColorOptions &&
        other.runtimeType == DocumentColorOptions &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => workDoneProgress.hashCode;

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

/// Parameters for a DocumentColorRequest.
class DocumentColorParams
    implements PartialResultParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentColorParams.canParse,
    DocumentColorParams.fromJson,
  );

  DocumentColorParams({
    this.partialResultToken,
    required this.textDocument,
    this.workDoneToken,
  });
  static DocumentColorParams fromJson(Map<String, Object?> json) {
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : _eitherIntString(partialResultTokenJson);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken =
        workDoneTokenJson == null ? null : _eitherIntString(workDoneTokenJson);
    return DocumentColorParams(
      partialResultToken: partialResultToken,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final ProgressToken? partialResultToken;

  /// The text document.
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final ProgressToken? workDoneToken;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseIntString(obj, reporter, 'partialResultToken',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseIntString(obj, reporter, 'workDoneToken',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type DocumentColorParams');
      return false;
    }
  }

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

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

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

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

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

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListTextDocumentFilterWithScheme(
          obj, reporter, 'documentSelector',
          allowsUndefined: false, allowsNull: true)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'id',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'workDoneProgress',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type DocumentColorRegistrationOptions');
      return false;
    }
  }

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

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

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

/// Parameters of the document diagnostic request.
///
/// @since 3.17.0
class DocumentDiagnosticParams
    implements PartialResultParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentDiagnosticParams.canParse,
    DocumentDiagnosticParams.fromJson,
  );

  DocumentDiagnosticParams({
    this.identifier,
    this.partialResultToken,
    this.previousResultId,
    required this.textDocument,
    this.workDoneToken,
  });
  static DocumentDiagnosticParams fromJson(Map<String, Object?> json) {
    final identifierJson = json['identifier'];
    final identifier = identifierJson as String?;
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : _eitherIntString(partialResultTokenJson);
    final previousResultIdJson = json['previousResultId'];
    final previousResultId = previousResultIdJson as String?;
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken =
        workDoneTokenJson == null ? null : _eitherIntString(workDoneTokenJson);
    return DocumentDiagnosticParams(
      identifier: identifier,
      partialResultToken: partialResultToken,
      previousResultId: previousResultId,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// The additional identifier  provided during registration.
  final String? identifier;

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final ProgressToken? partialResultToken;

  /// The result id of a previous response if provided.
  final String? previousResultId;

  /// The text document.
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final ProgressToken? workDoneToken;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseString(obj, reporter, 'identifier',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseIntString(obj, reporter, 'partialResultToken',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'previousResultId',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseIntString(obj, reporter, 'workDoneToken',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type DocumentDiagnosticParams');
      return false;
    }
  }

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

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

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

/// A partial result for a document diagnostic report.
///
/// @since 3.17.0
class DocumentDiagnosticReportPartialResult implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentDiagnosticReportPartialResult.canParse,
    DocumentDiagnosticReportPartialResult.fromJson,
  );

  DocumentDiagnosticReportPartialResult({
    required this.relatedDocuments,
  });
  static DocumentDiagnosticReportPartialResult fromJson(
      Map<String, Object?> json) {
    final relatedDocumentsJson = json['relatedDocuments'];
    final relatedDocuments = (relatedDocumentsJson as Map<Object, Object?>).map(
        (key, value) => MapEntry(
            key as String,
            _eitherFullDocumentDiagnosticReportUnchangedDocumentDiagnosticReport(
                value)));
    return DocumentDiagnosticReportPartialResult(
      relatedDocuments: relatedDocuments,
    );
  }

  final Map<
      DocumentUri,
      Either2<FullDocumentDiagnosticReport,
          UnchangedDocumentDiagnosticReport>> relatedDocuments;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseMapStringFullDocumentDiagnosticReportUnchangedDocumentDiagnosticReport(
          obj, reporter, 'relatedDocuments',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter
          .reportError('must be of type DocumentDiagnosticReportPartialResult');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DocumentDiagnosticReportPartialResult &&
        other.runtimeType == DocumentDiagnosticReportPartialResult &&
        mapEqual(
            relatedDocuments,
            other.relatedDocuments,
            (Either2<FullDocumentDiagnosticReport,
                            UnchangedDocumentDiagnosticReport>
                        a,
                    Either2<FullDocumentDiagnosticReport,
                            UnchangedDocumentDiagnosticReport>
                        b) =>
                a == b);
  }

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

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

/// Client capabilities of a DocumentFormattingRequest.
class DocumentFormattingClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentFormattingClientCapabilities.canParse,
    DocumentFormattingClientCapabilities.fromJson,
  );

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

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

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

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

  @override
  bool operator ==(Object other) {
    return other is DocumentFormattingClientCapabilities &&
        other.runtimeType == DocumentFormattingClientCapabilities &&
        dynamicRegistration == other.dynamicRegistration;
  }

  @override
  int get hashCode => dynamicRegistration.hashCode;

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

/// Provider options for a DocumentFormattingRequest.
class DocumentFormattingOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentFormattingOptions.canParse,
    DocumentFormattingOptions.fromJson,
  );

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

  @override
  final bool? workDoneProgress;

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

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

  @override
  bool operator ==(Object other) {
    return other is DocumentFormattingOptions &&
        other.runtimeType == DocumentFormattingOptions &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => workDoneProgress.hashCode;

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

/// The parameters of a DocumentFormattingRequest.
class DocumentFormattingParams implements WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentFormattingParams.canParse,
    DocumentFormattingParams.fromJson,
  );

  DocumentFormattingParams({
    required this.options,
    required this.textDocument,
    this.workDoneToken,
  });
  static DocumentFormattingParams fromJson(Map<String, Object?> json) {
    final optionsJson = json['options'];
    final options =
        FormattingOptions.fromJson(optionsJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken =
        workDoneTokenJson == null ? null : _eitherIntString(workDoneTokenJson);
    return DocumentFormattingParams(
      options: options,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// The format options.
  final FormattingOptions options;

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

  /// An optional token that a server can use to report work done progress.
  @override
  final ProgressToken? workDoneToken;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseFormattingOptions(obj, reporter, 'options',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseIntString(obj, reporter, 'workDoneToken',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type DocumentFormattingParams');
      return false;
    }
  }

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

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

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

/// Registration options for a DocumentFormattingRequest.
class DocumentFormattingRegistrationOptions
    implements
        DocumentFormattingOptions,
        TextDocumentRegistrationOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentFormattingRegistrationOptions.canParse,
    DocumentFormattingRegistrationOptions.fromJson,
  );

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListTextDocumentFilterWithScheme(
          obj, reporter, 'documentSelector',
          allowsUndefined: false, allowsNull: true)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'workDoneProgress',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter
          .reportError('must be of type DocumentFormattingRegistrationOptions');
      return false;
    }
  }

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

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

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

/// A document highlight is a range inside a text document which deserves
/// special attention. Usually a document highlight is visualized by changing
/// the background color of its range.
class DocumentHighlight implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentHighlight.canParse,
    DocumentHighlight.fromJson,
  );

  DocumentHighlight({
    this.kind,
    required this.range,
  });
  static DocumentHighlight fromJson(Map<String, Object?> json) {
    final kindJson = json['kind'];
    final kind = kindJson != null
        ? DocumentHighlightKind.fromJson(kindJson as int)
        : null;
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    return DocumentHighlight(
      kind: kind,
      range: range,
    );
  }

  /// The highlight kind, default is text.
  final DocumentHighlightKind? kind;

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseDocumentHighlightKind(obj, reporter, 'kind',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseRange(obj, reporter, 'range',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type DocumentHighlight');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DocumentHighlight &&
        other.runtimeType == DocumentHighlight &&
        kind == other.kind &&
        range == other.range;
  }

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

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

/// Client Capabilities for a DocumentHighlightRequest.
class DocumentHighlightClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentHighlightClientCapabilities.canParse,
    DocumentHighlightClientCapabilities.fromJson,
  );

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

  /// Whether document highlight supports dynamic registration.
  final bool? dynamicRegistration;

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

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

  @override
  bool operator ==(Object other) {
    return other is DocumentHighlightClientCapabilities &&
        other.runtimeType == DocumentHighlightClientCapabilities &&
        dynamicRegistration == other.dynamicRegistration;
  }

  @override
  int get hashCode => dynamicRegistration.hashCode;

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

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

  final int _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is int;

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

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

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

  @override
  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

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

/// Provider options for a DocumentHighlightRequest.
class DocumentHighlightOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentHighlightOptions.canParse,
    DocumentHighlightOptions.fromJson,
  );

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

  @override
  final bool? workDoneProgress;

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

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

  @override
  bool operator ==(Object other) {
    return other is DocumentHighlightOptions &&
        other.runtimeType == DocumentHighlightOptions &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => workDoneProgress.hashCode;

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

/// Parameters for a DocumentHighlightRequest.
class DocumentHighlightParams
    implements
        PartialResultParams,
        TextDocumentPositionParams,
        WorkDoneProgressParams,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentHighlightParams.canParse,
    DocumentHighlightParams.fromJson,
  );

  DocumentHighlightParams({
    this.partialResultToken,
    required this.position,
    required this.textDocument,
    this.workDoneToken,
  });
  static DocumentHighlightParams fromJson(Map<String, Object?> json) {
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : _eitherIntString(partialResultTokenJson);
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken =
        workDoneTokenJson == null ? null : _eitherIntString(workDoneTokenJson);
    return DocumentHighlightParams(
      partialResultToken: partialResultToken,
      position: position,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final ProgressToken? partialResultToken;

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

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

  /// An optional token that a server can use to report work done progress.
  @override
  final ProgressToken? workDoneToken;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseIntString(obj, reporter, 'partialResultToken',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParsePosition(obj, reporter, 'position',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseIntString(obj, reporter, 'workDoneToken',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type DocumentHighlightParams');
      return false;
    }
  }

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

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

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

/// Registration options for a DocumentHighlightRequest.
class DocumentHighlightRegistrationOptions
    implements
        DocumentHighlightOptions,
        TextDocumentRegistrationOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentHighlightRegistrationOptions.canParse,
    DocumentHighlightRegistrationOptions.fromJson,
  );

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListTextDocumentFilterWithScheme(
          obj, reporter, 'documentSelector',
          allowsUndefined: false, allowsNull: true)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'workDoneProgress',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter
          .reportError('must be of type DocumentHighlightRegistrationOptions');
      return false;
    }
  }

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

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

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

/// A document link is a range in a text document that links to an internal or
/// external resource, like another text document or a web site.
class DocumentLink implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentLink.canParse,
    DocumentLink.fromJson,
  );

  DocumentLink({
    this.data,
    required this.range,
    this.target,
    this.tooltip,
  });
  static DocumentLink fromJson(Map<String, Object?> json) {
    final dataJson = json['data'];
    final data = dataJson;
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    final targetJson = json['target'];
    final target = targetJson as String?;
    final tooltipJson = json['tooltip'];
    final tooltip = tooltipJson as String?;
    return DocumentLink(
      data: data,
      range: range,
      target: target,
      tooltip: tooltip,
    );
  }

  /// A data entry field that is preserved on a document link between a
  /// DocumentLinkRequest and a DocumentLinkResolveRequest.
  final LSPAny data;

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

  /// The uri this link points to. If missing a resolve request is sent later.
  final String? target;

  /// The tooltip text when you hover over this link.
  ///
  /// If a tooltip is provided, is will be displayed in a string that includes
  /// instructions on how to trigger the link, such as `{0} (ctrl + click)`. The
  /// specific instructions vary depending on OS,
  /// user settings, and localization.
  ///
  /// @since 3.15.0
  final String? tooltip;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseRange(obj, reporter, 'range',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'target',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseString(obj, reporter, 'tooltip',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type DocumentLink');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DocumentLink &&
        other.runtimeType == DocumentLink &&
        data == other.data &&
        range == other.range &&
        target == other.target &&
        tooltip == other.tooltip;
  }

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

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

/// The client capabilities of a DocumentLinkRequest.
class DocumentLinkClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentLinkClientCapabilities.canParse,
    DocumentLinkClientCapabilities.fromJson,
  );

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

  /// Whether document link supports dynamic registration.
  final bool? dynamicRegistration;

  /// Whether the client supports the `tooltip` property on `DocumentLink`.
  ///
  /// @since 3.15.0
  final bool? tooltipSupport;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseBool(obj, reporter, 'dynamicRegistration',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'tooltipSupport',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type DocumentLinkClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DocumentLinkClientCapabilities &&
        other.runtimeType == DocumentLinkClientCapabilities &&
        dynamicRegistration == other.dynamicRegistration &&
        tooltipSupport == other.tooltipSupport;
  }

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

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

/// Provider options for a DocumentLinkRequest.
class DocumentLinkOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentLinkOptions.canParse,
    DocumentLinkOptions.fromJson,
  );

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseBool(obj, reporter, 'resolveProvider',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'workDoneProgress',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type DocumentLinkOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DocumentLinkOptions &&
        other.runtimeType == DocumentLinkOptions &&
        resolveProvider == other.resolveProvider &&
        workDoneProgress == other.workDoneProgress;
  }

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

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

/// The parameters of a DocumentLinkRequest.
class DocumentLinkParams
    implements PartialResultParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentLinkParams.canParse,
    DocumentLinkParams.fromJson,
  );

  DocumentLinkParams({
    this.partialResultToken,
    required this.textDocument,
    this.workDoneToken,
  });
  static DocumentLinkParams fromJson(Map<String, Object?> json) {
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : _eitherIntString(partialResultTokenJson);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken =
        workDoneTokenJson == null ? null : _eitherIntString(workDoneTokenJson);
    return DocumentLinkParams(
      partialResultToken: partialResultToken,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final ProgressToken? partialResultToken;

  /// The document to provide document links for.
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final ProgressToken? workDoneToken;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseIntString(obj, reporter, 'partialResultToken',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseIntString(obj, reporter, 'workDoneToken',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type DocumentLinkParams');
      return false;
    }
  }

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

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

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

/// Registration options for a DocumentLinkRequest.
class DocumentLinkRegistrationOptions
    implements
        DocumentLinkOptions,
        TextDocumentRegistrationOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentLinkRegistrationOptions.canParse,
    DocumentLinkRegistrationOptions.fromJson,
  );

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

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListTextDocumentFilterWithScheme(
          obj, reporter, 'documentSelector',
          allowsUndefined: false, allowsNull: true)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'resolveProvider',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'workDoneProgress',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type DocumentLinkRegistrationOptions');
      return false;
    }
  }

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

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

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

/// Client capabilities of a DocumentOnTypeFormattingRequest.
class DocumentOnTypeFormattingClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentOnTypeFormattingClientCapabilities.canParse,
    DocumentOnTypeFormattingClientCapabilities.fromJson,
  );

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

  /// Whether on type formatting supports dynamic registration.
  final bool? dynamicRegistration;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseBool(obj, reporter, 'dynamicRegistration',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError(
          'must be of type DocumentOnTypeFormattingClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DocumentOnTypeFormattingClientCapabilities &&
        other.runtimeType == DocumentOnTypeFormattingClientCapabilities &&
        dynamicRegistration == other.dynamicRegistration;
  }

  @override
  int get hashCode => dynamicRegistration.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Provider options for a DocumentOnTypeFormattingRequest.
class DocumentOnTypeFormattingOptions implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentOnTypeFormattingOptions.canParse,
    DocumentOnTypeFormattingOptions.fromJson,
  );

  DocumentOnTypeFormattingOptions({
    required this.firstTriggerCharacter,
    this.moreTriggerCharacter,
  });
  static DocumentOnTypeFormattingOptions fromJson(Map<String, Object?> json) {
    if (DocumentOnTypeFormattingRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return DocumentOnTypeFormattingRegistrationOptions.fromJson(json);
    }
    final firstTriggerCharacterJson = json['firstTriggerCharacter'];
    final firstTriggerCharacter = firstTriggerCharacterJson as String;
    final moreTriggerCharacterJson = json['moreTriggerCharacter'];
    final moreTriggerCharacter = (moreTriggerCharacterJson as List<Object?>?)
        ?.map((item) => item as String)
        .toList();
    return DocumentOnTypeFormattingOptions(
      firstTriggerCharacter: firstTriggerCharacter,
      moreTriggerCharacter: moreTriggerCharacter,
    );
  }

  /// A character on which formatting should be triggered, like `{`.
  final String firstTriggerCharacter;

  /// More trigger characters.
  final List<String>? moreTriggerCharacter;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['firstTriggerCharacter'] = firstTriggerCharacter;
    if (moreTriggerCharacter != null) {
      result['moreTriggerCharacter'] = moreTriggerCharacter;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseString(obj, reporter, 'firstTriggerCharacter',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseListString(obj, reporter, 'moreTriggerCharacter',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type DocumentOnTypeFormattingOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DocumentOnTypeFormattingOptions &&
        other.runtimeType == DocumentOnTypeFormattingOptions &&
        firstTriggerCharacter == other.firstTriggerCharacter &&
        listEqual(moreTriggerCharacter, other.moreTriggerCharacter,
            (String a, String b) => a == b);
  }

  @override
  int get hashCode => Object.hash(
        firstTriggerCharacter,
        lspHashCode(moreTriggerCharacter),
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The parameters of a DocumentOnTypeFormattingRequest.
class DocumentOnTypeFormattingParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentOnTypeFormattingParams.canParse,
    DocumentOnTypeFormattingParams.fromJson,
  );

  DocumentOnTypeFormattingParams({
    required this.ch,
    required this.options,
    required this.position,
    required this.textDocument,
  });
  static DocumentOnTypeFormattingParams fromJson(Map<String, Object?> json) {
    final chJson = json['ch'];
    final ch = chJson as String;
    final optionsJson = json['options'];
    final options =
        FormattingOptions.fromJson(optionsJson as Map<String, Object?>);
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    return DocumentOnTypeFormattingParams(
      ch: ch,
      options: options,
      position: position,
      textDocument: textDocument,
    );
  }

  /// The character that has been typed that triggered the formatting on type
  /// request. That is not necessarily the last character that got inserted into
  /// the document since the client could auto insert characters as well (e.g.
  /// like automatic brace completion).
  final String ch;

  /// The formatting options.
  final FormattingOptions options;

  /// The position around which the on type formatting should happen. This is
  /// not necessarily the exact position where the character denoted by the
  /// property `ch` got typed.
  final Position position;

  /// The document to format.
  final TextDocumentIdentifier textDocument;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['ch'] = ch;
    result['options'] = options.toJson();
    result['position'] = position.toJson();
    result['textDocument'] = textDocument.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseString(obj, reporter, 'ch',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseFormattingOptions(obj, reporter, 'options',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParsePosition(obj, reporter, 'position',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type DocumentOnTypeFormattingParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DocumentOnTypeFormattingParams &&
        other.runtimeType == DocumentOnTypeFormattingParams &&
        ch == other.ch &&
        options == other.options &&
        position == other.position &&
        textDocument == other.textDocument;
  }

  @override
  int get hashCode => Object.hash(
        ch,
        options,
        position,
        textDocument,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Registration options for a DocumentOnTypeFormattingRequest.
class DocumentOnTypeFormattingRegistrationOptions
    implements
        DocumentOnTypeFormattingOptions,
        TextDocumentRegistrationOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentOnTypeFormattingRegistrationOptions.canParse,
    DocumentOnTypeFormattingRegistrationOptions.fromJson,
  );

  DocumentOnTypeFormattingRegistrationOptions({
    this.documentSelector,
    required this.firstTriggerCharacter,
    this.moreTriggerCharacter,
  });
  static DocumentOnTypeFormattingRegistrationOptions fromJson(
      Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final firstTriggerCharacterJson = json['firstTriggerCharacter'];
    final firstTriggerCharacter = firstTriggerCharacterJson as String;
    final moreTriggerCharacterJson = json['moreTriggerCharacter'];
    final moreTriggerCharacter = (moreTriggerCharacterJson as List<Object?>?)
        ?.map((item) => item as String)
        .toList();
    return DocumentOnTypeFormattingRegistrationOptions(
      documentSelector: documentSelector,
      firstTriggerCharacter: firstTriggerCharacter,
      moreTriggerCharacter: moreTriggerCharacter,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;

  /// A character on which formatting should be triggered, like `{`.
  @override
  final String firstTriggerCharacter;

  /// More trigger characters.
  @override
  final List<String>? moreTriggerCharacter;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    result['firstTriggerCharacter'] = firstTriggerCharacter;
    if (moreTriggerCharacter != null) {
      result['moreTriggerCharacter'] = moreTriggerCharacter;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListTextDocumentFilterWithScheme(
          obj, reporter, 'documentSelector',
          allowsUndefined: false, allowsNull: true)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'firstTriggerCharacter',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseListString(obj, reporter, 'moreTriggerCharacter',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError(
          'must be of type DocumentOnTypeFormattingRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DocumentOnTypeFormattingRegistrationOptions &&
        other.runtimeType == DocumentOnTypeFormattingRegistrationOptions &&
        listEqual(
            documentSelector,
            other.documentSelector,
            (TextDocumentFilterWithScheme a, TextDocumentFilterWithScheme b) =>
                a == b) &&
        firstTriggerCharacter == other.firstTriggerCharacter &&
        listEqual(moreTriggerCharacter, other.moreTriggerCharacter,
            (String a, String b) => a == b);
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        firstTriggerCharacter,
        lspHashCode(moreTriggerCharacter),
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Client capabilities of a DocumentRangeFormattingRequest.
class DocumentRangeFormattingClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentRangeFormattingClientCapabilities.canParse,
    DocumentRangeFormattingClientCapabilities.fromJson,
  );

  DocumentRangeFormattingClientCapabilities({
    this.dynamicRegistration,
  });
  static DocumentRangeFormattingClientCapabilities fromJson(
      Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    return DocumentRangeFormattingClientCapabilities(
      dynamicRegistration: dynamicRegistration,
    );
  }

  /// Whether range formatting supports dynamic registration.
  final bool? dynamicRegistration;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseBool(obj, reporter, 'dynamicRegistration',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError(
          'must be of type DocumentRangeFormattingClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DocumentRangeFormattingClientCapabilities &&
        other.runtimeType == DocumentRangeFormattingClientCapabilities &&
        dynamicRegistration == other.dynamicRegistration;
  }

  @override
  int get hashCode => dynamicRegistration.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Provider options for a DocumentRangeFormattingRequest.
class DocumentRangeFormattingOptions
    implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentRangeFormattingOptions.canParse,
    DocumentRangeFormattingOptions.fromJson,
  );

  DocumentRangeFormattingOptions({
    this.workDoneProgress,
  });
  static DocumentRangeFormattingOptions fromJson(Map<String, Object?> json) {
    if (DocumentRangeFormattingRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return DocumentRangeFormattingRegistrationOptions.fromJson(json);
    }
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return DocumentRangeFormattingOptions(
      workDoneProgress: workDoneProgress,
    );
  }

  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseBool(obj, reporter, 'workDoneProgress',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type DocumentRangeFormattingOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DocumentRangeFormattingOptions &&
        other.runtimeType == DocumentRangeFormattingOptions &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => workDoneProgress.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The parameters of a DocumentRangeFormattingRequest.
class DocumentRangeFormattingParams
    implements WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentRangeFormattingParams.canParse,
    DocumentRangeFormattingParams.fromJson,
  );

  DocumentRangeFormattingParams({
    required this.options,
    required this.range,
    required this.textDocument,
    this.workDoneToken,
  });
  static DocumentRangeFormattingParams fromJson(Map<String, Object?> json) {
    final optionsJson = json['options'];
    final options =
        FormattingOptions.fromJson(optionsJson as Map<String, Object?>);
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken =
        workDoneTokenJson == null ? null : _eitherIntString(workDoneTokenJson);
    return DocumentRangeFormattingParams(
      options: options,
      range: range,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// The format options
  final FormattingOptions options;

  /// The range to format
  final Range range;

  /// The document to format.
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final ProgressToken? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['options'] = options.toJson();
    result['range'] = range.toJson();
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseFormattingOptions(obj, reporter, 'options',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseRange(obj, reporter, 'range',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseIntString(obj, reporter, 'workDoneToken',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type DocumentRangeFormattingParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DocumentRangeFormattingParams &&
        other.runtimeType == DocumentRangeFormattingParams &&
        options == other.options &&
        range == other.range &&
        textDocument == other.textDocument &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        options,
        range,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Registration options for a DocumentRangeFormattingRequest.
class DocumentRangeFormattingRegistrationOptions
    implements
        DocumentRangeFormattingOptions,
        TextDocumentRegistrationOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentRangeFormattingRegistrationOptions.canParse,
    DocumentRangeFormattingRegistrationOptions.fromJson,
  );

  DocumentRangeFormattingRegistrationOptions({
    this.documentSelector,
    this.workDoneProgress,
  });
  static DocumentRangeFormattingRegistrationOptions fromJson(
      Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return DocumentRangeFormattingRegistrationOptions(
      documentSelector: documentSelector,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListTextDocumentFilterWithScheme(
          obj, reporter, 'documentSelector',
          allowsUndefined: false, allowsNull: true)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'workDoneProgress',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError(
          'must be of type DocumentRangeFormattingRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DocumentRangeFormattingRegistrationOptions &&
        other.runtimeType == DocumentRangeFormattingRegistrationOptions &&
        listEqual(
            documentSelector,
            other.documentSelector,
            (TextDocumentFilterWithScheme a, TextDocumentFilterWithScheme b) =>
                a == b) &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Represents programming constructs like variables, classes, interfaces etc.
/// that appear in a document. Document symbols can be hierarchical and they
/// have two ranges: one that encloses its definition and one that points to its
/// most interesting range, e.g. the range of an identifier.
class DocumentSymbol implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentSymbol.canParse,
    DocumentSymbol.fromJson,
  );

  DocumentSymbol({
    this.children,
    this.deprecated,
    this.detail,
    required this.kind,
    required this.name,
    required this.range,
    required this.selectionRange,
    this.tags,
  });
  static DocumentSymbol fromJson(Map<String, Object?> json) {
    final childrenJson = json['children'];
    final children = (childrenJson as List<Object?>?)
        ?.map((item) => DocumentSymbol.fromJson(item as Map<String, Object?>))
        .toList();
    final deprecatedJson = json['deprecated'];
    final deprecated = deprecatedJson as bool?;
    final detailJson = json['detail'];
    final detail = detailJson as String?;
    final kindJson = json['kind'];
    final kind = SymbolKind.fromJson(kindJson as int);
    final nameJson = json['name'];
    final name = nameJson as String;
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    final selectionRangeJson = json['selectionRange'];
    final selectionRange =
        Range.fromJson(selectionRangeJson as Map<String, Object?>);
    final tagsJson = json['tags'];
    final tags = (tagsJson as List<Object?>?)
        ?.map((item) => SymbolTag.fromJson(item as int))
        .toList();
    return DocumentSymbol(
      children: children,
      deprecated: deprecated,
      detail: detail,
      kind: kind,
      name: name,
      range: range,
      selectionRange: selectionRange,
      tags: tags,
    );
  }

  /// Children of this symbol, e.g. properties of a class.
  final List<DocumentSymbol>? children;

  /// Indicates if this symbol is deprecated.
  ///
  /// @deprecated Use tags instead
  final bool? deprecated;

  /// More detail for this symbol, e.g the signature of a function.
  final String? detail;

  /// The kind of this symbol.
  final SymbolKind kind;

  /// The name of this symbol. Will be displayed in the user interface and
  /// therefore must not be an empty string or a string only consisting of white
  /// spaces.
  final String name;

  /// The range enclosing this symbol not including leading/trailing whitespace
  /// but everything else like comments. This information is typically used to
  /// determine if the clients cursor is inside the symbol to reveal in the
  /// symbol in the UI.
  final Range range;

  /// The range that should be selected and revealed when this symbol is being
  /// picked, e.g the name of a function. Must be contained by the `range`.
  final Range selectionRange;

  /// Tags for this document symbol.
  ///
  /// @since 3.16.0
  final List<SymbolTag>? tags;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (children != null) {
      result['children'] = children?.map((item) => item.toJson()).toList();
    }
    if (deprecated != null) {
      result['deprecated'] = deprecated;
    }
    if (detail != null) {
      result['detail'] = detail;
    }
    result['kind'] = kind.toJson();
    result['name'] = name;
    result['range'] = range.toJson();
    result['selectionRange'] = selectionRange.toJson();
    if (tags != null) {
      result['tags'] = tags?.map((item) => item.toJson()).toList();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListDocumentSymbol(obj, reporter, 'children',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'deprecated',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'detail',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseSymbolKind(obj, reporter, 'kind',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'name',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseRange(obj, reporter, 'range',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseRange(obj, reporter, 'selectionRange',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseListSymbolTag(obj, reporter, 'tags',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type DocumentSymbol');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DocumentSymbol &&
        other.runtimeType == DocumentSymbol &&
        listEqual(children, other.children,
            (DocumentSymbol a, DocumentSymbol b) => a == b) &&
        deprecated == other.deprecated &&
        detail == other.detail &&
        kind == other.kind &&
        name == other.name &&
        range == other.range &&
        selectionRange == other.selectionRange &&
        listEqual(tags, other.tags, (SymbolTag a, SymbolTag b) => a == b);
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(children),
        deprecated,
        detail,
        kind,
        name,
        range,
        selectionRange,
        lspHashCode(tags),
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Client Capabilities for a DocumentSymbolRequest.
class DocumentSymbolClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentSymbolClientCapabilities.canParse,
    DocumentSymbolClientCapabilities.fromJson,
  );

  DocumentSymbolClientCapabilities({
    this.dynamicRegistration,
    this.hierarchicalDocumentSymbolSupport,
    this.labelSupport,
    this.symbolKind,
    this.tagSupport,
  });
  static DocumentSymbolClientCapabilities fromJson(Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    final hierarchicalDocumentSymbolSupportJson =
        json['hierarchicalDocumentSymbolSupport'];
    final hierarchicalDocumentSymbolSupport =
        hierarchicalDocumentSymbolSupportJson as bool?;
    final labelSupportJson = json['labelSupport'];
    final labelSupport = labelSupportJson as bool?;
    final symbolKindJson = json['symbolKind'];
    final symbolKind = symbolKindJson != null
        ? DocumentSymbolClientCapabilitiesSymbolKind.fromJson(
            symbolKindJson as Map<String, Object?>)
        : null;
    final tagSupportJson = json['tagSupport'];
    final tagSupport = tagSupportJson != null
        ? DocumentSymbolClientCapabilitiesTagSupport.fromJson(
            tagSupportJson as Map<String, Object?>)
        : null;
    return DocumentSymbolClientCapabilities(
      dynamicRegistration: dynamicRegistration,
      hierarchicalDocumentSymbolSupport: hierarchicalDocumentSymbolSupport,
      labelSupport: labelSupport,
      symbolKind: symbolKind,
      tagSupport: tagSupport,
    );
  }

  /// Whether document symbol supports dynamic registration.
  final bool? dynamicRegistration;

  /// The client supports hierarchical document symbols.
  final bool? hierarchicalDocumentSymbolSupport;

  /// The client supports an additional label presented in the UI when
  /// registering a document symbol provider.
  ///
  /// @since 3.16.0
  final bool? labelSupport;

  /// Specific capabilities for the `SymbolKind` in the
  /// `textDocument/documentSymbol` request.
  final DocumentSymbolClientCapabilitiesSymbolKind? symbolKind;

  /// The client supports tags on `SymbolInformation`. Tags are supported on
  /// `DocumentSymbol` if `hierarchicalDocumentSymbolSupport` is set to true.
  /// Clients supporting tags have to handle unknown tags gracefully.
  ///
  /// @since 3.16.0
  final DocumentSymbolClientCapabilitiesTagSupport? tagSupport;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    if (hierarchicalDocumentSymbolSupport != null) {
      result['hierarchicalDocumentSymbolSupport'] =
          hierarchicalDocumentSymbolSupport;
    }
    if (labelSupport != null) {
      result['labelSupport'] = labelSupport;
    }
    if (symbolKind != null) {
      result['symbolKind'] = symbolKind?.toJson();
    }
    if (tagSupport != null) {
      result['tagSupport'] = tagSupport?.toJson();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseBool(obj, reporter, 'dynamicRegistration',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'hierarchicalDocumentSymbolSupport',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'labelSupport',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseDocumentSymbolClientCapabilitiesSymbolKind(
          obj, reporter, 'symbolKind',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseDocumentSymbolClientCapabilitiesTagSupport(
          obj, reporter, 'tagSupport',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type DocumentSymbolClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DocumentSymbolClientCapabilities &&
        other.runtimeType == DocumentSymbolClientCapabilities &&
        dynamicRegistration == other.dynamicRegistration &&
        hierarchicalDocumentSymbolSupport ==
            other.hierarchicalDocumentSymbolSupport &&
        labelSupport == other.labelSupport &&
        symbolKind == other.symbolKind &&
        tagSupport == other.tagSupport;
  }

  @override
  int get hashCode => Object.hash(
        dynamicRegistration,
        hierarchicalDocumentSymbolSupport,
        labelSupport,
        symbolKind,
        tagSupport,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class DocumentSymbolClientCapabilitiesSymbolKind implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentSymbolClientCapabilitiesSymbolKind.canParse,
    DocumentSymbolClientCapabilitiesSymbolKind.fromJson,
  );

  DocumentSymbolClientCapabilitiesSymbolKind({
    this.valueSet,
  });
  static DocumentSymbolClientCapabilitiesSymbolKind fromJson(
      Map<String, Object?> json) {
    final valueSetJson = json['valueSet'];
    final valueSet = (valueSetJson as List<Object?>?)
        ?.map((item) => SymbolKind.fromJson(item as int))
        .toList();
    return DocumentSymbolClientCapabilitiesSymbolKind(
      valueSet: valueSet,
    );
  }

  /// The symbol kind values the client supports. When this property exists the
  /// client also guarantees that it will handle values outside its set
  /// gracefully and falls back to a default value when unknown.
  ///
  /// If this property is not present the client only supports the symbol kinds
  /// from `File` to `Array` as defined in the initial version of the protocol.
  final List<SymbolKind>? valueSet;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (valueSet != null) {
      result['valueSet'] = valueSet?.map((item) => item.toJson()).toList();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseListSymbolKind(obj, reporter, 'valueSet',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError(
          'must be of type DocumentSymbolClientCapabilitiesSymbolKind');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DocumentSymbolClientCapabilitiesSymbolKind &&
        other.runtimeType == DocumentSymbolClientCapabilitiesSymbolKind &&
        listEqual(
            valueSet, other.valueSet, (SymbolKind a, SymbolKind b) => a == b);
  }

  @override
  int get hashCode => lspHashCode(valueSet);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class DocumentSymbolClientCapabilitiesTagSupport implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentSymbolClientCapabilitiesTagSupport.canParse,
    DocumentSymbolClientCapabilitiesTagSupport.fromJson,
  );

  DocumentSymbolClientCapabilitiesTagSupport({
    required this.valueSet,
  });
  static DocumentSymbolClientCapabilitiesTagSupport fromJson(
      Map<String, Object?> json) {
    final valueSetJson = json['valueSet'];
    final valueSet = (valueSetJson as List<Object?>)
        .map((item) => SymbolTag.fromJson(item as int))
        .toList();
    return DocumentSymbolClientCapabilitiesTagSupport(
      valueSet: valueSet,
    );
  }

  /// The tags supported by the client.
  final List<SymbolTag> valueSet;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['valueSet'] = valueSet.map((item) => item.toJson()).toList();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseListSymbolTag(obj, reporter, 'valueSet',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError(
          'must be of type DocumentSymbolClientCapabilitiesTagSupport');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DocumentSymbolClientCapabilitiesTagSupport &&
        other.runtimeType == DocumentSymbolClientCapabilitiesTagSupport &&
        listEqual(
            valueSet, other.valueSet, (SymbolTag a, SymbolTag b) => a == b);
  }

  @override
  int get hashCode => lspHashCode(valueSet);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Provider options for a DocumentSymbolRequest.
class DocumentSymbolOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentSymbolOptions.canParse,
    DocumentSymbolOptions.fromJson,
  );

  DocumentSymbolOptions({
    this.label,
    this.workDoneProgress,
  });
  static DocumentSymbolOptions fromJson(Map<String, Object?> json) {
    if (DocumentSymbolRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentSymbolRegistrationOptions.fromJson(json);
    }
    final labelJson = json['label'];
    final label = labelJson as String?;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return DocumentSymbolOptions(
      label: label,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A human-readable string that is shown when multiple outlines trees are
  /// shown for the same document.
  ///
  /// @since 3.16.0
  final String? label;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (label != null) {
      result['label'] = label;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseString(obj, reporter, 'label',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'workDoneProgress',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type DocumentSymbolOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DocumentSymbolOptions &&
        other.runtimeType == DocumentSymbolOptions &&
        label == other.label &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        label,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Parameters for a DocumentSymbolRequest.
class DocumentSymbolParams
    implements PartialResultParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentSymbolParams.canParse,
    DocumentSymbolParams.fromJson,
  );

  DocumentSymbolParams({
    this.partialResultToken,
    required this.textDocument,
    this.workDoneToken,
  });
  static DocumentSymbolParams fromJson(Map<String, Object?> json) {
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : _eitherIntString(partialResultTokenJson);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken =
        workDoneTokenJson == null ? null : _eitherIntString(workDoneTokenJson);
    return DocumentSymbolParams(
      partialResultToken: partialResultToken,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final ProgressToken? partialResultToken;

  /// The text document.
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final ProgressToken? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseIntString(obj, reporter, 'partialResultToken',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseIntString(obj, reporter, 'workDoneToken',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type DocumentSymbolParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DocumentSymbolParams &&
        other.runtimeType == DocumentSymbolParams &&
        partialResultToken == other.partialResultToken &&
        textDocument == other.textDocument &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        partialResultToken,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Registration options for a DocumentSymbolRequest.
class DocumentSymbolRegistrationOptions
    implements
        DocumentSymbolOptions,
        TextDocumentRegistrationOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentSymbolRegistrationOptions.canParse,
    DocumentSymbolRegistrationOptions.fromJson,
  );

  DocumentSymbolRegistrationOptions({
    this.documentSelector,
    this.label,
    this.workDoneProgress,
  });
  static DocumentSymbolRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final labelJson = json['label'];
    final label = labelJson as String?;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return DocumentSymbolRegistrationOptions(
      documentSelector: documentSelector,
      label: label,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;

  /// A human-readable string that is shown when multiple outlines trees are
  /// shown for the same document.
  ///
  /// @since 3.16.0
  @override
  final String? label;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (label != null) {
      result['label'] = label;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListTextDocumentFilterWithScheme(
          obj, reporter, 'documentSelector',
          allowsUndefined: false, allowsNull: true)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'label',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'workDoneProgress',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type DocumentSymbolRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is DocumentSymbolRegistrationOptions &&
        other.runtimeType == DocumentSymbolRegistrationOptions &&
        listEqual(
            documentSelector,
            other.documentSelector,
            (TextDocumentFilterWithScheme a, TextDocumentFilterWithScheme b) =>
                a == b) &&
        label == other.label &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        label,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Predefined error codes.
class ErrorCodes implements ToJsonable {
  const ErrorCodes(this._value);
  const ErrorCodes.fromJson(this._value);

  final int _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is int;

  /// The server detected that the content of a document got modified outside
  /// normal conditions. A server should NOT send this error code if it detects
  /// a content change in it unprocessed messages. The result even computed on
  /// an older state might still be useful for the client.
  ///
  /// If a client decides that a result is not of any use anymore the client
  /// should cancel the request.
  static const ContentModified = ErrorCodes(-32801);
  static const InternalError = ErrorCodes(-32603);
  static const InvalidParams = ErrorCodes(-32602);
  static const InvalidRequest = ErrorCodes(-32600);

  /// This is the end range of JSON RPC reserved error codes. It doesn't denote
  /// a real error code.
  ///
  /// @since 3.16.0
  static const jsonrpcReservedErrorRangeEnd = ErrorCodes(-32000);

  /// This is the start range of JSON RPC reserved error codes. It doesn't
  /// denote a real error code. No application error codes should be defined
  /// between the start and end range. For backwards compatibility the
  /// `ServerNotInitialized` and the `UnknownErrorCode` are left in the range.
  ///
  /// @since 3.16.0
  static const jsonrpcReservedErrorRangeStart = ErrorCodes(-32099);

  /// This is the end range of LSP reserved error codes. It doesn't denote a
  /// real error code.
  ///
  /// @since 3.16.0
  static const lspReservedErrorRangeEnd = ErrorCodes(-32800);

  /// This is the start range of LSP reserved error codes. It doesn't denote a
  /// real error code.
  ///
  /// @since 3.16.0
  static const lspReservedErrorRangeStart = ErrorCodes(-32899);
  static const MethodNotFound = ErrorCodes(-32601);
  static const ParseError = ErrorCodes(-32700);

  /// The client has canceled a request and a server as detected the cancel.
  static const RequestCancelled = ErrorCodes(-32800);

  /// A request failed but it was syntactically correct, e.g the method name was
  /// known and the parameters were valid. The error message should contain
  /// human readable information about why the request failed.
  ///
  /// @since 3.17.0
  static const RequestFailed = ErrorCodes(-32803);

  /// The server cancelled the request. This error code should only be used for
  /// requests that explicitly support being server cancellable.
  ///
  /// @since 3.17.0
  static const ServerCancelled = ErrorCodes(-32802);

  /// Error code indicating that a server received a notification or request
  /// before the server has received the `initialize` request.
  static const ServerNotInitialized = ErrorCodes(-32002);
  static const UnknownErrorCode = ErrorCodes(-32001);

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is ErrorCodes && other._value == _value;
}

/// The client capabilities of a ExecuteCommandRequest.
class ExecuteCommandClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ExecuteCommandClientCapabilities.canParse,
    ExecuteCommandClientCapabilities.fromJson,
  );

  ExecuteCommandClientCapabilities({
    this.dynamicRegistration,
  });
  static ExecuteCommandClientCapabilities fromJson(Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    return ExecuteCommandClientCapabilities(
      dynamicRegistration: dynamicRegistration,
    );
  }

  /// Execute command supports dynamic registration.
  final bool? dynamicRegistration;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseBool(obj, reporter, 'dynamicRegistration',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type ExecuteCommandClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ExecuteCommandClientCapabilities &&
        other.runtimeType == ExecuteCommandClientCapabilities &&
        dynamicRegistration == other.dynamicRegistration;
  }

  @override
  int get hashCode => dynamicRegistration.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The server capabilities of a ExecuteCommandRequest.
class ExecuteCommandOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ExecuteCommandOptions.canParse,
    ExecuteCommandOptions.fromJson,
  );

  ExecuteCommandOptions({
    required this.commands,
    this.workDoneProgress,
  });
  static ExecuteCommandOptions fromJson(Map<String, Object?> json) {
    if (ExecuteCommandRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return ExecuteCommandRegistrationOptions.fromJson(json);
    }
    final commandsJson = json['commands'];
    final commands =
        (commandsJson as List<Object?>).map((item) => item as String).toList();
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return ExecuteCommandOptions(
      commands: commands,
      workDoneProgress: workDoneProgress,
    );
  }

  /// The commands to be executed on the server
  final List<String> commands;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['commands'] = commands;
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListString(obj, reporter, 'commands',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'workDoneProgress',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type ExecuteCommandOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ExecuteCommandOptions &&
        other.runtimeType == ExecuteCommandOptions &&
        listEqual(commands, other.commands, (String a, String b) => a == b) &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(commands),
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The parameters of a ExecuteCommandRequest.
class ExecuteCommandParams implements WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ExecuteCommandParams.canParse,
    ExecuteCommandParams.fromJson,
  );

  ExecuteCommandParams({
    this.arguments,
    required this.command,
    this.workDoneToken,
  });
  static ExecuteCommandParams fromJson(Map<String, Object?> json) {
    final argumentsJson = json['arguments'];
    final arguments =
        (argumentsJson as List<Object?>?)?.map((item) => item).toList();
    final commandJson = json['command'];
    final command = commandJson as String;
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken =
        workDoneTokenJson == null ? null : _eitherIntString(workDoneTokenJson);
    return ExecuteCommandParams(
      arguments: arguments,
      command: command,
      workDoneToken: workDoneToken,
    );
  }

  /// Arguments that the command should be invoked with.
  final List<LSPAny>? arguments;

  /// The identifier of the actual command handler.
  final String command;

  /// An optional token that a server can use to report work done progress.
  @override
  final ProgressToken? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (arguments != null) {
      result['arguments'] = arguments;
    }
    result['command'] = command;
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListObjectNullable(obj, reporter, 'arguments',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'command',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseIntString(obj, reporter, 'workDoneToken',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type ExecuteCommandParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ExecuteCommandParams &&
        other.runtimeType == ExecuteCommandParams &&
        listEqual(arguments, other.arguments, (LSPAny a, LSPAny b) => a == b) &&
        command == other.command &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(arguments),
        command,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Registration options for a ExecuteCommandRequest.
class ExecuteCommandRegistrationOptions
    implements ExecuteCommandOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ExecuteCommandRegistrationOptions.canParse,
    ExecuteCommandRegistrationOptions.fromJson,
  );

  ExecuteCommandRegistrationOptions({
    required this.commands,
    this.workDoneProgress,
  });
  static ExecuteCommandRegistrationOptions fromJson(Map<String, Object?> json) {
    final commandsJson = json['commands'];
    final commands =
        (commandsJson as List<Object?>).map((item) => item as String).toList();
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return ExecuteCommandRegistrationOptions(
      commands: commands,
      workDoneProgress: workDoneProgress,
    );
  }

  /// The commands to be executed on the server
  @override
  final List<String> commands;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['commands'] = commands;
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListString(obj, reporter, 'commands',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'workDoneProgress',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type ExecuteCommandRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ExecuteCommandRegistrationOptions &&
        other.runtimeType == ExecuteCommandRegistrationOptions &&
        listEqual(commands, other.commands, (String a, String b) => a == b) &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(commands),
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class ExecutionSummary implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ExecutionSummary.canParse,
    ExecutionSummary.fromJson,
  );

  ExecutionSummary({
    required this.executionOrder,
    this.success,
  });
  static ExecutionSummary fromJson(Map<String, Object?> json) {
    final executionOrderJson = json['executionOrder'];
    final executionOrder = executionOrderJson as int;
    final successJson = json['success'];
    final success = successJson as bool?;
    return ExecutionSummary(
      executionOrder: executionOrder,
      success: success,
    );
  }

  /// A strict monotonically increasing value indicating the execution order of
  /// a cell inside a notebook.
  final int executionOrder;

  /// Whether the execution was successful or not if known by the client.
  final bool? success;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['executionOrder'] = executionOrder;
    if (success != null) {
      result['success'] = success;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseInt(obj, reporter, 'executionOrder',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'success',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type ExecutionSummary');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ExecutionSummary &&
        other.runtimeType == ExecutionSummary &&
        executionOrder == other.executionOrder &&
        success == other.success;
  }

  @override
  int get hashCode => Object.hash(
        executionOrder,
        success,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class FailureHandlingKind implements ToJsonable {
  const FailureHandlingKind._(this._value);
  const FailureHandlingKind.fromJson(this._value);

  final String _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    switch (obj) {
      case 'abort':
      case 'textOnlyTransactional':
      case 'transactional':
      case 'undo':
        return true;
    }
    return false;
  }

  /// Applying the workspace change is simply aborted if one of the changes
  /// provided fails. All operations executed before the failing operation stay
  /// executed.
  static const Abort = FailureHandlingKind._('abort');

  /// If the workspace edit contains only textual file changes they are executed
  /// transactional. If resource changes (create, rename or delete file) are
  /// part of the change the failure handling strategy is abort.
  static const TextOnlyTransactional =
      FailureHandlingKind._('textOnlyTransactional');

  /// All operations are executed transactional. That means they either all
  /// succeed or no changes at all are applied to the workspace.
  static const Transactional = FailureHandlingKind._('transactional');

  /// The client tries to undo the operations already executed. But there is no
  /// guarantee that this is succeeding.
  static const Undo = FailureHandlingKind._('undo');

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is FailureHandlingKind && other._value == _value;
}

/// The file event type
class FileChangeType implements ToJsonable {
  const FileChangeType(this._value);
  const FileChangeType.fromJson(this._value);

  final int _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is int;

  /// The file got changed.
  static const Changed = FileChangeType(2);

  /// The file got created.
  static const Created = FileChangeType(1);

  /// The file got deleted.
  static const Deleted = FileChangeType(3);

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is FileChangeType && other._value == _value;
}

/// Represents information on a file/folder create.
///
/// @since 3.16.0
class FileCreate implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FileCreate.canParse,
    FileCreate.fromJson,
  );

  FileCreate({
    required this.uri,
  });
  static FileCreate fromJson(Map<String, Object?> json) {
    final uriJson = json['uri'];
    final uri = uriJson as String;
    return FileCreate(
      uri: uri,
    );
  }

  /// A file:// URI for the location of the file/folder being created.
  final String uri;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['uri'] = uri;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseString(obj, reporter, 'uri',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type FileCreate');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is FileCreate &&
        other.runtimeType == FileCreate &&
        uri == other.uri;
  }

  @override
  int get hashCode => uri.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Represents information on a file/folder delete.
///
/// @since 3.16.0
class FileDelete implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FileDelete.canParse,
    FileDelete.fromJson,
  );

  FileDelete({
    required this.uri,
  });
  static FileDelete fromJson(Map<String, Object?> json) {
    final uriJson = json['uri'];
    final uri = uriJson as String;
    return FileDelete(
      uri: uri,
    );
  }

  /// A file:// URI for the location of the file/folder being deleted.
  final String uri;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['uri'] = uri;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseString(obj, reporter, 'uri',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type FileDelete');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is FileDelete &&
        other.runtimeType == FileDelete &&
        uri == other.uri;
  }

  @override
  int get hashCode => uri.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// An event describing a file change.
class FileEvent implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FileEvent.canParse,
    FileEvent.fromJson,
  );

  FileEvent({
    required this.type,
    required this.uri,
  });
  static FileEvent fromJson(Map<String, Object?> json) {
    final typeJson = json['type'];
    final type = FileChangeType.fromJson(typeJson as int);
    final uriJson = json['uri'];
    final uri = uriJson as String;
    return FileEvent(
      type: type,
      uri: uri,
    );
  }

  /// The change type.
  final FileChangeType type;

  /// The file's uri.
  final DocumentUri uri;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['type'] = type.toJson();
    result['uri'] = uri;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseFileChangeType(obj, reporter, 'type',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseString(obj, reporter, 'uri',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type FileEvent');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is FileEvent &&
        other.runtimeType == FileEvent &&
        type == other.type &&
        uri == other.uri;
  }

  @override
  int get hashCode => Object.hash(
        type,
        uri,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Capabilities relating to events from file operations by the user in the
/// client.
///
/// These events do not come from the file system, they come from user
/// operations like renaming a file in the UI.
///
/// @since 3.16.0
class FileOperationClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FileOperationClientCapabilities.canParse,
    FileOperationClientCapabilities.fromJson,
  );

  FileOperationClientCapabilities({
    this.didCreate,
    this.didDelete,
    this.didRename,
    this.dynamicRegistration,
    this.willCreate,
    this.willDelete,
    this.willRename,
  });
  static FileOperationClientCapabilities fromJson(Map<String, Object?> json) {
    final didCreateJson = json['didCreate'];
    final didCreate = didCreateJson as bool?;
    final didDeleteJson = json['didDelete'];
    final didDelete = didDeleteJson as bool?;
    final didRenameJson = json['didRename'];
    final didRename = didRenameJson as bool?;
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    final willCreateJson = json['willCreate'];
    final willCreate = willCreateJson as bool?;
    final willDeleteJson = json['willDelete'];
    final willDelete = willDeleteJson as bool?;
    final willRenameJson = json['willRename'];
    final willRename = willRenameJson as bool?;
    return FileOperationClientCapabilities(
      didCreate: didCreate,
      didDelete: didDelete,
      didRename: didRename,
      dynamicRegistration: dynamicRegistration,
      willCreate: willCreate,
      willDelete: willDelete,
      willRename: willRename,
    );
  }

  /// The client has support for sending didCreateFiles notifications.
  final bool? didCreate;

  /// The client has support for sending didDeleteFiles notifications.
  final bool? didDelete;

  /// The client has support for sending didRenameFiles notifications.
  final bool? didRename;

  /// Whether the client supports dynamic registration for file
  /// requests/notifications.
  final bool? dynamicRegistration;

  /// The client has support for sending willCreateFiles requests.
  final bool? willCreate;

  /// The client has support for sending willDeleteFiles requests.
  final bool? willDelete;

  /// The client has support for sending willRenameFiles requests.
  final bool? willRename;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (didCreate != null) {
      result['didCreate'] = didCreate;
    }
    if (didDelete != null) {
      result['didDelete'] = didDelete;
    }
    if (didRename != null) {
      result['didRename'] = didRename;
    }
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    if (willCreate != null) {
      result['willCreate'] = willCreate;
    }
    if (willDelete != null) {
      result['willDelete'] = willDelete;
    }
    if (willRename != null) {
      result['willRename'] = willRename;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseBool(obj, reporter, 'didCreate',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'didDelete',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'didRename',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'dynamicRegistration',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'willCreate',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'willDelete',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'willRename',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type FileOperationClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is FileOperationClientCapabilities &&
        other.runtimeType == FileOperationClientCapabilities &&
        didCreate == other.didCreate &&
        didDelete == other.didDelete &&
        didRename == other.didRename &&
        dynamicRegistration == other.dynamicRegistration &&
        willCreate == other.willCreate &&
        willDelete == other.willDelete &&
        willRename == other.willRename;
  }

  @override
  int get hashCode => Object.hash(
        didCreate,
        didDelete,
        didRename,
        dynamicRegistration,
        willCreate,
        willDelete,
        willRename,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A filter to describe in which file operation requests or notifications the
/// server is interested in receiving.
///
/// @since 3.16.0
class FileOperationFilter implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FileOperationFilter.canParse,
    FileOperationFilter.fromJson,
  );

  FileOperationFilter({
    required this.pattern,
    this.scheme,
  });
  static FileOperationFilter fromJson(Map<String, Object?> json) {
    final patternJson = json['pattern'];
    final pattern =
        FileOperationPattern.fromJson(patternJson as Map<String, Object?>);
    final schemeJson = json['scheme'];
    final scheme = schemeJson as String?;
    return FileOperationFilter(
      pattern: pattern,
      scheme: scheme,
    );
  }

  /// The actual file operation pattern.
  final FileOperationPattern pattern;

  /// A Uri scheme like `file` or `untitled`.
  final String? scheme;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['pattern'] = pattern.toJson();
    if (scheme != null) {
      result['scheme'] = scheme;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseFileOperationPattern(obj, reporter, 'pattern',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseString(obj, reporter, 'scheme',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type FileOperationFilter');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is FileOperationFilter &&
        other.runtimeType == FileOperationFilter &&
        pattern == other.pattern &&
        scheme == other.scheme;
  }

  @override
  int get hashCode => Object.hash(
        pattern,
        scheme,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Options for notifications/requests for user operations on files.
///
/// @since 3.16.0
class FileOperationOptions implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FileOperationOptions.canParse,
    FileOperationOptions.fromJson,
  );

  FileOperationOptions({
    this.didCreate,
    this.didDelete,
    this.didRename,
    this.willCreate,
    this.willDelete,
    this.willRename,
  });
  static FileOperationOptions fromJson(Map<String, Object?> json) {
    final didCreateJson = json['didCreate'];
    final didCreate = didCreateJson != null
        ? FileOperationRegistrationOptions.fromJson(
            didCreateJson as Map<String, Object?>)
        : null;
    final didDeleteJson = json['didDelete'];
    final didDelete = didDeleteJson != null
        ? FileOperationRegistrationOptions.fromJson(
            didDeleteJson as Map<String, Object?>)
        : null;
    final didRenameJson = json['didRename'];
    final didRename = didRenameJson != null
        ? FileOperationRegistrationOptions.fromJson(
            didRenameJson as Map<String, Object?>)
        : null;
    final willCreateJson = json['willCreate'];
    final willCreate = willCreateJson != null
        ? FileOperationRegistrationOptions.fromJson(
            willCreateJson as Map<String, Object?>)
        : null;
    final willDeleteJson = json['willDelete'];
    final willDelete = willDeleteJson != null
        ? FileOperationRegistrationOptions.fromJson(
            willDeleteJson as Map<String, Object?>)
        : null;
    final willRenameJson = json['willRename'];
    final willRename = willRenameJson != null
        ? FileOperationRegistrationOptions.fromJson(
            willRenameJson as Map<String, Object?>)
        : null;
    return FileOperationOptions(
      didCreate: didCreate,
      didDelete: didDelete,
      didRename: didRename,
      willCreate: willCreate,
      willDelete: willDelete,
      willRename: willRename,
    );
  }

  /// The server is interested in receiving didCreateFiles notifications.
  final FileOperationRegistrationOptions? didCreate;

  /// The server is interested in receiving didDeleteFiles file notifications.
  final FileOperationRegistrationOptions? didDelete;

  /// The server is interested in receiving didRenameFiles notifications.
  final FileOperationRegistrationOptions? didRename;

  /// The server is interested in receiving willCreateFiles requests.
  final FileOperationRegistrationOptions? willCreate;

  /// The server is interested in receiving willDeleteFiles file requests.
  final FileOperationRegistrationOptions? willDelete;

  /// The server is interested in receiving willRenameFiles requests.
  final FileOperationRegistrationOptions? willRename;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (didCreate != null) {
      result['didCreate'] = didCreate?.toJson();
    }
    if (didDelete != null) {
      result['didDelete'] = didDelete?.toJson();
    }
    if (didRename != null) {
      result['didRename'] = didRename?.toJson();
    }
    if (willCreate != null) {
      result['willCreate'] = willCreate?.toJson();
    }
    if (willDelete != null) {
      result['willDelete'] = willDelete?.toJson();
    }
    if (willRename != null) {
      result['willRename'] = willRename?.toJson();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseFileOperationRegistrationOptions(obj, reporter, 'didCreate',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseFileOperationRegistrationOptions(obj, reporter, 'didDelete',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseFileOperationRegistrationOptions(obj, reporter, 'didRename',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseFileOperationRegistrationOptions(
          obj, reporter, 'willCreate',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseFileOperationRegistrationOptions(
          obj, reporter, 'willDelete',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseFileOperationRegistrationOptions(
          obj, reporter, 'willRename',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type FileOperationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is FileOperationOptions &&
        other.runtimeType == FileOperationOptions &&
        didCreate == other.didCreate &&
        didDelete == other.didDelete &&
        didRename == other.didRename &&
        willCreate == other.willCreate &&
        willDelete == other.willDelete &&
        willRename == other.willRename;
  }

  @override
  int get hashCode => Object.hash(
        didCreate,
        didDelete,
        didRename,
        willCreate,
        willDelete,
        willRename,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A pattern to describe in which file operation requests or notifications the
/// server is interested in receiving.
///
/// @since 3.16.0
class FileOperationPattern implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FileOperationPattern.canParse,
    FileOperationPattern.fromJson,
  );

  FileOperationPattern({
    required this.glob,
    this.matches,
    this.options,
  });
  static FileOperationPattern fromJson(Map<String, Object?> json) {
    final globJson = json['glob'];
    final glob = globJson as String;
    final matchesJson = json['matches'];
    final matches = matchesJson != null
        ? FileOperationPatternKind.fromJson(matchesJson as String)
        : null;
    final optionsJson = json['options'];
    final options = optionsJson != null
        ? FileOperationPatternOptions.fromJson(
            optionsJson as Map<String, Object?>)
        : null;
    return FileOperationPattern(
      glob: glob,
      matches: matches,
      options: options,
    );
  }

  /// The glob pattern to match. Glob patterns can have the following syntax:
  /// - `*` to match one or more characters in a path segment
  /// - `?` to match on one character in a path segment
  /// - `**` to match any number of path segments, including none
  /// - `{}` to group sub patterns into an OR expression. (e.g. `**​/*.{ts,js}`
  /// matches all TypeScript and JavaScript files)
  /// - `[]` to declare a range of characters to match in a path segment (e.g.,
  /// `example.[0-9]` to match on `example.0`, `example.1`, …)
  /// - `[!...]` to negate a range of characters to match in a path segment
  /// (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but not
  /// `example.0`)
  final String glob;

  /// Whether to match files or folders with this pattern.
  ///
  /// Matches both if undefined.
  final FileOperationPatternKind? matches;

  /// Additional options used during matching.
  final FileOperationPatternOptions? options;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['glob'] = glob;
    if (matches != null) {
      result['matches'] = matches?.toJson();
    }
    if (options != null) {
      result['options'] = options?.toJson();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseString(obj, reporter, 'glob',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseFileOperationPatternKind(obj, reporter, 'matches',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseFileOperationPatternOptions(obj, reporter, 'options',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type FileOperationPattern');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is FileOperationPattern &&
        other.runtimeType == FileOperationPattern &&
        glob == other.glob &&
        matches == other.matches &&
        options == other.options;
  }

  @override
  int get hashCode => Object.hash(
        glob,
        matches,
        options,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A pattern kind describing if a glob pattern matches a file a folder or both.
///
/// @since 3.16.0
class FileOperationPatternKind implements ToJsonable {
  const FileOperationPatternKind(this._value);
  const FileOperationPatternKind.fromJson(this._value);

  final String _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is String;

  /// The pattern matches a file only.
  static const file = FileOperationPatternKind('file');

  /// The pattern matches a folder only.
  static const folder = FileOperationPatternKind('folder');

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is FileOperationPatternKind && other._value == _value;
}

/// Matching options for the file operation pattern.
///
/// @since 3.16.0
class FileOperationPatternOptions implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FileOperationPatternOptions.canParse,
    FileOperationPatternOptions.fromJson,
  );

  FileOperationPatternOptions({
    this.ignoreCase,
  });
  static FileOperationPatternOptions fromJson(Map<String, Object?> json) {
    final ignoreCaseJson = json['ignoreCase'];
    final ignoreCase = ignoreCaseJson as bool?;
    return FileOperationPatternOptions(
      ignoreCase: ignoreCase,
    );
  }

  /// The pattern should be matched ignoring casing.
  final bool? ignoreCase;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (ignoreCase != null) {
      result['ignoreCase'] = ignoreCase;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseBool(obj, reporter, 'ignoreCase',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type FileOperationPatternOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is FileOperationPatternOptions &&
        other.runtimeType == FileOperationPatternOptions &&
        ignoreCase == other.ignoreCase;
  }

  @override
  int get hashCode => ignoreCase.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The options to register for file operations.
///
/// @since 3.16.0
class FileOperationRegistrationOptions implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FileOperationRegistrationOptions.canParse,
    FileOperationRegistrationOptions.fromJson,
  );

  FileOperationRegistrationOptions({
    required this.filters,
  });
  static FileOperationRegistrationOptions fromJson(Map<String, Object?> json) {
    final filtersJson = json['filters'];
    final filters = (filtersJson as List<Object?>)
        .map((item) =>
            FileOperationFilter.fromJson(item as Map<String, Object?>))
        .toList();
    return FileOperationRegistrationOptions(
      filters: filters,
    );
  }

  /// The actual filters.
  final List<FileOperationFilter> filters;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['filters'] = filters.map((item) => item.toJson()).toList();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseListFileOperationFilter(obj, reporter, 'filters',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type FileOperationRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is FileOperationRegistrationOptions &&
        other.runtimeType == FileOperationRegistrationOptions &&
        listEqual(filters, other.filters,
            (FileOperationFilter a, FileOperationFilter b) => a == b);
  }

  @override
  int get hashCode => lspHashCode(filters);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Represents information on a file/folder rename.
///
/// @since 3.16.0
class FileRename implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FileRename.canParse,
    FileRename.fromJson,
  );

  FileRename({
    required this.newUri,
    required this.oldUri,
  });
  static FileRename fromJson(Map<String, Object?> json) {
    final newUriJson = json['newUri'];
    final newUri = newUriJson as String;
    final oldUriJson = json['oldUri'];
    final oldUri = oldUriJson as String;
    return FileRename(
      newUri: newUri,
      oldUri: oldUri,
    );
  }

  /// A file:// URI for the new location of the file/folder being renamed.
  final String newUri;

  /// A file:// URI for the original location of the file/folder being renamed.
  final String oldUri;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['newUri'] = newUri;
    result['oldUri'] = oldUri;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseString(obj, reporter, 'newUri',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseString(obj, reporter, 'oldUri',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type FileRename');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is FileRename &&
        other.runtimeType == FileRename &&
        newUri == other.newUri &&
        oldUri == other.oldUri;
  }

  @override
  int get hashCode => Object.hash(
        newUri,
        oldUri,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class FileSystemWatcher implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FileSystemWatcher.canParse,
    FileSystemWatcher.fromJson,
  );

  FileSystemWatcher({
    required this.globPattern,
    this.kind,
  });
  static FileSystemWatcher fromJson(Map<String, Object?> json) {
    final globPatternJson = json['globPattern'];
    final globPattern = _eitherStringRelativePattern(globPatternJson);
    final kindJson = json['kind'];
    final kind = kindJson != null ? WatchKind.fromJson(kindJson as int) : null;
    return FileSystemWatcher(
      globPattern: globPattern,
      kind: kind,
    );
  }

  /// The glob pattern to watch. See {@link GlobPattern glob pattern} for more
  /// detail.
  ///
  /// @since 3.17.0 support for relative patterns.
  final GlobPattern globPattern;

  /// The kind of events of interest. If omitted it defaults to WatchKind.Create
  /// | WatchKind.Change | WatchKind.Delete which is 7.
  final WatchKind? kind;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['globPattern'] = globPattern;
    if (kind != null) {
      result['kind'] = kind?.toJson();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseStringRelativePattern(obj, reporter, 'globPattern',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseWatchKind(obj, reporter, 'kind',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type FileSystemWatcher');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is FileSystemWatcher &&
        other.runtimeType == FileSystemWatcher &&
        globPattern == other.globPattern &&
        kind == other.kind;
  }

  @override
  int get hashCode => Object.hash(
        globPattern,
        kind,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Represents a folding range. To be valid, start and end line must be bigger
/// than zero and smaller than the number of lines in the document. Clients are
/// free to ignore invalid ranges.
class FoldingRange implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FoldingRange.canParse,
    FoldingRange.fromJson,
  );

  FoldingRange({
    this.collapsedText,
    this.endCharacter,
    required this.endLine,
    this.kind,
    this.startCharacter,
    required this.startLine,
  });
  static FoldingRange fromJson(Map<String, Object?> json) {
    final collapsedTextJson = json['collapsedText'];
    final collapsedText = collapsedTextJson as String?;
    final endCharacterJson = json['endCharacter'];
    final endCharacter = endCharacterJson as int?;
    final endLineJson = json['endLine'];
    final endLine = endLineJson as int;
    final kindJson = json['kind'];
    final kind =
        kindJson != null ? FoldingRangeKind.fromJson(kindJson as String) : null;
    final startCharacterJson = json['startCharacter'];
    final startCharacter = startCharacterJson as int?;
    final startLineJson = json['startLine'];
    final startLine = startLineJson as int;
    return FoldingRange(
      collapsedText: collapsedText,
      endCharacter: endCharacter,
      endLine: endLine,
      kind: kind,
      startCharacter: startCharacter,
      startLine: startLine,
    );
  }

  /// The text that the client should show when the specified range is
  /// collapsed. If not defined or not supported by the client, a default will
  /// be chosen by the client.
  ///
  /// @since 3.17.0
  final String? collapsedText;

  /// The zero-based character offset before the folded range ends. If not
  /// defined, defaults to the length of the end line.
  final int? endCharacter;

  /// The zero-based end line of the range to fold. The folded area ends with
  /// the line's last character. To be valid, the end must be zero or larger and
  /// smaller than the number of lines in the document.
  final int endLine;

  /// Describes the kind of the folding range such as `comment' or 'region'. The
  /// kind is used to categorize folding ranges and used by commands like 'Fold
  /// all comments'. See FoldingRangeKind for an enumeration of standardized
  /// kinds.
  final FoldingRangeKind? kind;

  /// The zero-based character offset from where the folded range starts. If not
  /// defined, defaults to the length of the start line.
  final int? startCharacter;

  /// The zero-based start line of the range to fold. The folded area starts
  /// after the line's last character. To be valid, the end must be zero or
  /// larger and smaller than the number of lines in the document.
  final int startLine;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (collapsedText != null) {
      result['collapsedText'] = collapsedText;
    }
    if (endCharacter != null) {
      result['endCharacter'] = endCharacter;
    }
    result['endLine'] = endLine;
    if (kind != null) {
      result['kind'] = kind?.toJson();
    }
    if (startCharacter != null) {
      result['startCharacter'] = startCharacter;
    }
    result['startLine'] = startLine;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseString(obj, reporter, 'collapsedText',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseInt(obj, reporter, 'endCharacter',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseInt(obj, reporter, 'endLine',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseFoldingRangeKind(obj, reporter, 'kind',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseInt(obj, reporter, 'startCharacter',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseInt(obj, reporter, 'startLine',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type FoldingRange');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is FoldingRange &&
        other.runtimeType == FoldingRange &&
        collapsedText == other.collapsedText &&
        endCharacter == other.endCharacter &&
        endLine == other.endLine &&
        kind == other.kind &&
        startCharacter == other.startCharacter &&
        startLine == other.startLine;
  }

  @override
  int get hashCode => Object.hash(
        collapsedText,
        endCharacter,
        endLine,
        kind,
        startCharacter,
        startLine,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class FoldingRangeClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FoldingRangeClientCapabilities.canParse,
    FoldingRangeClientCapabilities.fromJson,
  );

  FoldingRangeClientCapabilities({
    this.dynamicRegistration,
    this.foldingRange,
    this.foldingRangeKind,
    this.lineFoldingOnly,
    this.rangeLimit,
  });
  static FoldingRangeClientCapabilities fromJson(Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    final foldingRangeJson = json['foldingRange'];
    final foldingRange = foldingRangeJson != null
        ? FoldingRangeClientCapabilitiesFoldingRange.fromJson(
            foldingRangeJson as Map<String, Object?>)
        : null;
    final foldingRangeKindJson = json['foldingRangeKind'];
    final foldingRangeKind = foldingRangeKindJson != null
        ? FoldingRangeClientCapabilitiesFoldingRangeKind.fromJson(
            foldingRangeKindJson as Map<String, Object?>)
        : null;
    final lineFoldingOnlyJson = json['lineFoldingOnly'];
    final lineFoldingOnly = lineFoldingOnlyJson as bool?;
    final rangeLimitJson = json['rangeLimit'];
    final rangeLimit = rangeLimitJson as int?;
    return FoldingRangeClientCapabilities(
      dynamicRegistration: dynamicRegistration,
      foldingRange: foldingRange,
      foldingRangeKind: foldingRangeKind,
      lineFoldingOnly: lineFoldingOnly,
      rangeLimit: rangeLimit,
    );
  }

  /// Whether implementation supports dynamic registration for folding range
  /// providers. If this is set to `true` the client supports the new
  /// `FoldingRangeRegistrationOptions` return value for the corresponding
  /// server capability as well.
  final bool? dynamicRegistration;

  /// Specific options for the folding range.
  ///
  /// @since 3.17.0
  final FoldingRangeClientCapabilitiesFoldingRange? foldingRange;

  /// Specific options for the folding range kind.
  ///
  /// @since 3.17.0
  final FoldingRangeClientCapabilitiesFoldingRangeKind? foldingRangeKind;

  /// If set, the client signals that it only supports folding complete lines.
  /// If set, client will ignore specified `startCharacter` and `endCharacter`
  /// properties in a FoldingRange.
  final bool? lineFoldingOnly;

  /// The maximum number of folding ranges that the client prefers to receive
  /// per document. The value serves as a hint, servers are free to follow the
  /// limit.
  final int? rangeLimit;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    if (foldingRange != null) {
      result['foldingRange'] = foldingRange?.toJson();
    }
    if (foldingRangeKind != null) {
      result['foldingRangeKind'] = foldingRangeKind?.toJson();
    }
    if (lineFoldingOnly != null) {
      result['lineFoldingOnly'] = lineFoldingOnly;
    }
    if (rangeLimit != null) {
      result['rangeLimit'] = rangeLimit;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseBool(obj, reporter, 'dynamicRegistration',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseFoldingRangeClientCapabilitiesFoldingRange(
          obj, reporter, 'foldingRange',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseFoldingRangeClientCapabilitiesFoldingRangeKind(
          obj, reporter, 'foldingRangeKind',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'lineFoldingOnly',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseInt(obj, reporter, 'rangeLimit',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type FoldingRangeClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is FoldingRangeClientCapabilities &&
        other.runtimeType == FoldingRangeClientCapabilities &&
        dynamicRegistration == other.dynamicRegistration &&
        foldingRange == other.foldingRange &&
        foldingRangeKind == other.foldingRangeKind &&
        lineFoldingOnly == other.lineFoldingOnly &&
        rangeLimit == other.rangeLimit;
  }

  @override
  int get hashCode => Object.hash(
        dynamicRegistration,
        foldingRange,
        foldingRangeKind,
        lineFoldingOnly,
        rangeLimit,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class FoldingRangeClientCapabilitiesFoldingRange implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FoldingRangeClientCapabilitiesFoldingRange.canParse,
    FoldingRangeClientCapabilitiesFoldingRange.fromJson,
  );

  FoldingRangeClientCapabilitiesFoldingRange({
    this.collapsedText,
  });
  static FoldingRangeClientCapabilitiesFoldingRange fromJson(
      Map<String, Object?> json) {
    final collapsedTextJson = json['collapsedText'];
    final collapsedText = collapsedTextJson as bool?;
    return FoldingRangeClientCapabilitiesFoldingRange(
      collapsedText: collapsedText,
    );
  }

  /// If set, the client signals that it supports setting collapsedText on
  /// folding ranges to display custom labels instead of the default text.
  ///
  /// @since 3.17.0
  final bool? collapsedText;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (collapsedText != null) {
      result['collapsedText'] = collapsedText;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseBool(obj, reporter, 'collapsedText',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError(
          'must be of type FoldingRangeClientCapabilitiesFoldingRange');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is FoldingRangeClientCapabilitiesFoldingRange &&
        other.runtimeType == FoldingRangeClientCapabilitiesFoldingRange &&
        collapsedText == other.collapsedText;
  }

  @override
  int get hashCode => collapsedText.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class FoldingRangeClientCapabilitiesFoldingRangeKind implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FoldingRangeClientCapabilitiesFoldingRangeKind.canParse,
    FoldingRangeClientCapabilitiesFoldingRangeKind.fromJson,
  );

  FoldingRangeClientCapabilitiesFoldingRangeKind({
    this.valueSet,
  });
  static FoldingRangeClientCapabilitiesFoldingRangeKind fromJson(
      Map<String, Object?> json) {
    final valueSetJson = json['valueSet'];
    final valueSet = (valueSetJson as List<Object?>?)
        ?.map((item) => FoldingRangeKind.fromJson(item as String))
        .toList();
    return FoldingRangeClientCapabilitiesFoldingRangeKind(
      valueSet: valueSet,
    );
  }

  /// The folding range kind values the client supports. When this property
  /// exists the client also guarantees that it will handle values outside its
  /// set gracefully and falls back to a default value when unknown.
  final List<FoldingRangeKind>? valueSet;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (valueSet != null) {
      result['valueSet'] = valueSet?.map((item) => item.toJson()).toList();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseListFoldingRangeKind(obj, reporter, 'valueSet',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError(
          'must be of type FoldingRangeClientCapabilitiesFoldingRangeKind');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is FoldingRangeClientCapabilitiesFoldingRangeKind &&
        other.runtimeType == FoldingRangeClientCapabilitiesFoldingRangeKind &&
        listEqual(valueSet, other.valueSet,
            (FoldingRangeKind a, FoldingRangeKind b) => a == b);
  }

  @override
  int get hashCode => lspHashCode(valueSet);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A set of predefined range kinds.
class FoldingRangeKind implements ToJsonable {
  const FoldingRangeKind(this._value);
  const FoldingRangeKind.fromJson(this._value);

  final String _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is String;

  /// Folding range for a comment
  static const Comment = FoldingRangeKind('comment');

  /// Folding range for an import or include
  static const Imports = FoldingRangeKind('imports');

  /// Folding range for a region (e.g. `#region`)
  static const Region = FoldingRangeKind('region');

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is FoldingRangeKind && other._value == _value;
}

class FoldingRangeOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FoldingRangeOptions.canParse,
    FoldingRangeOptions.fromJson,
  );

  FoldingRangeOptions({
    this.workDoneProgress,
  });
  static FoldingRangeOptions fromJson(Map<String, Object?> json) {
    if (FoldingRangeRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return FoldingRangeRegistrationOptions.fromJson(json);
    }
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return FoldingRangeOptions(
      workDoneProgress: workDoneProgress,
    );
  }

  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseBool(obj, reporter, 'workDoneProgress',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type FoldingRangeOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is FoldingRangeOptions &&
        other.runtimeType == FoldingRangeOptions &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => workDoneProgress.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Parameters for a FoldingRangeRequest.
class FoldingRangeParams
    implements PartialResultParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FoldingRangeParams.canParse,
    FoldingRangeParams.fromJson,
  );

  FoldingRangeParams({
    this.partialResultToken,
    required this.textDocument,
    this.workDoneToken,
  });
  static FoldingRangeParams fromJson(Map<String, Object?> json) {
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : _eitherIntString(partialResultTokenJson);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken =
        workDoneTokenJson == null ? null : _eitherIntString(workDoneTokenJson);
    return FoldingRangeParams(
      partialResultToken: partialResultToken,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final ProgressToken? partialResultToken;

  /// The text document.
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final ProgressToken? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseIntString(obj, reporter, 'partialResultToken',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseIntString(obj, reporter, 'workDoneToken',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type FoldingRangeParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is FoldingRangeParams &&
        other.runtimeType == FoldingRangeParams &&
        partialResultToken == other.partialResultToken &&
        textDocument == other.textDocument &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        partialResultToken,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class FoldingRangeRegistrationOptions
    implements
        FoldingRangeOptions,
        StaticRegistrationOptions,
        TextDocumentRegistrationOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FoldingRangeRegistrationOptions.canParse,
    FoldingRangeRegistrationOptions.fromJson,
  );

  FoldingRangeRegistrationOptions({
    this.documentSelector,
    this.id,
    this.workDoneProgress,
  });
  static FoldingRangeRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final idJson = json['id'];
    final id = idJson as String?;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return FoldingRangeRegistrationOptions(
      documentSelector: documentSelector,
      id: id,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;

  /// The id used to register the request. The id can be used to deregister the
  /// request again. See also Registration#id.
  @override
  final String? id;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (id != null) {
      result['id'] = id;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListTextDocumentFilterWithScheme(
          obj, reporter, 'documentSelector',
          allowsUndefined: false, allowsNull: true)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'id',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'workDoneProgress',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type FoldingRangeRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is FoldingRangeRegistrationOptions &&
        other.runtimeType == FoldingRangeRegistrationOptions &&
        listEqual(
            documentSelector,
            other.documentSelector,
            (TextDocumentFilterWithScheme a, TextDocumentFilterWithScheme b) =>
                a == b) &&
        id == other.id &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        id,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Value-object describing what options formatting should use.
class FormattingOptions implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FormattingOptions.canParse,
    FormattingOptions.fromJson,
  );

  FormattingOptions({
    this.insertFinalNewline,
    required this.insertSpaces,
    required this.tabSize,
    this.trimFinalNewlines,
    this.trimTrailingWhitespace,
  });
  static FormattingOptions fromJson(Map<String, Object?> json) {
    final insertFinalNewlineJson = json['insertFinalNewline'];
    final insertFinalNewline = insertFinalNewlineJson as bool?;
    final insertSpacesJson = json['insertSpaces'];
    final insertSpaces = insertSpacesJson as bool;
    final tabSizeJson = json['tabSize'];
    final tabSize = tabSizeJson as int;
    final trimFinalNewlinesJson = json['trimFinalNewlines'];
    final trimFinalNewlines = trimFinalNewlinesJson as bool?;
    final trimTrailingWhitespaceJson = json['trimTrailingWhitespace'];
    final trimTrailingWhitespace = trimTrailingWhitespaceJson as bool?;
    return FormattingOptions(
      insertFinalNewline: insertFinalNewline,
      insertSpaces: insertSpaces,
      tabSize: tabSize,
      trimFinalNewlines: trimFinalNewlines,
      trimTrailingWhitespace: trimTrailingWhitespace,
    );
  }

  /// Insert a newline character at the end of the file if one does not exist.
  ///
  /// @since 3.15.0
  final bool? insertFinalNewline;

  /// Prefer spaces over tabs.
  final bool insertSpaces;

  /// Size of a tab in spaces.
  final int tabSize;

  /// Trim all newlines after the final newline at the end of the file.
  ///
  /// @since 3.15.0
  final bool? trimFinalNewlines;

  /// Trim trailing whitespace on a line.
  ///
  /// @since 3.15.0
  final bool? trimTrailingWhitespace;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (insertFinalNewline != null) {
      result['insertFinalNewline'] = insertFinalNewline;
    }
    result['insertSpaces'] = insertSpaces;
    result['tabSize'] = tabSize;
    if (trimFinalNewlines != null) {
      result['trimFinalNewlines'] = trimFinalNewlines;
    }
    if (trimTrailingWhitespace != null) {
      result['trimTrailingWhitespace'] = trimTrailingWhitespace;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseBool(obj, reporter, 'insertFinalNewline',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'insertSpaces',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseInt(obj, reporter, 'tabSize',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'trimFinalNewlines',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'trimTrailingWhitespace',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type FormattingOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is FormattingOptions &&
        other.runtimeType == FormattingOptions &&
        insertFinalNewline == other.insertFinalNewline &&
        insertSpaces == other.insertSpaces &&
        tabSize == other.tabSize &&
        trimFinalNewlines == other.trimFinalNewlines &&
        trimTrailingWhitespace == other.trimTrailingWhitespace;
  }

  @override
  int get hashCode => Object.hash(
        insertFinalNewline,
        insertSpaces,
        tabSize,
        trimFinalNewlines,
        trimTrailingWhitespace,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A diagnostic report with a full set of problems.
///
/// @since 3.17.0
class FullDocumentDiagnosticReport implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    FullDocumentDiagnosticReport.canParse,
    FullDocumentDiagnosticReport.fromJson,
  );

  FullDocumentDiagnosticReport({
    required this.items,
    this.kind = 'full',
    this.resultId,
  }) {
    if (kind != 'full') {
      throw 'kind may only be the literal \'full\'';
    }
  }
  static FullDocumentDiagnosticReport fromJson(Map<String, Object?> json) {
    if (WorkspaceFullDocumentDiagnosticReport.canParse(
        json, nullLspJsonReporter)) {
      return WorkspaceFullDocumentDiagnosticReport.fromJson(json);
    }
    if (RelatedFullDocumentDiagnosticReport.canParse(
        json, nullLspJsonReporter)) {
      return RelatedFullDocumentDiagnosticReport.fromJson(json);
    }
    final itemsJson = json['items'];
    final items = (itemsJson as List<Object?>)
        .map((item) => Diagnostic.fromJson(item as Map<String, Object?>))
        .toList();
    final kindJson = json['kind'];
    final kind = kindJson as String;
    final resultIdJson = json['resultId'];
    final resultId = resultIdJson as String?;
    return FullDocumentDiagnosticReport(
      items: items,
      kind: kind,
      resultId: resultId,
    );
  }

  /// The actual items.
  final List<Diagnostic> items;

  /// A full document diagnostic report.
  final String kind;

  /// An optional result id. If provided it will be sent on the next diagnostic
  /// request for the same document.
  final String? resultId;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['items'] = items.map((item) => item.toJson()).toList();
    result['kind'] = kind;
    if (resultId != null) {
      result['resultId'] = resultId;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListDiagnostic(obj, reporter, 'items',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseLiteral(obj, reporter, 'kind',
          allowsUndefined: false, allowsNull: false, literal: 'full')) {
        return false;
      }
      return _canParseString(obj, reporter, 'resultId',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type FullDocumentDiagnosticReport');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is FullDocumentDiagnosticReport &&
        other.runtimeType == FullDocumentDiagnosticReport &&
        listEqual(items, other.items, (Diagnostic a, Diagnostic b) => a == b) &&
        kind == other.kind &&
        resultId == other.resultId;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(items),
        kind,
        resultId,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// General client capabilities.
///
/// @since 3.16.0
class GeneralClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    GeneralClientCapabilities.canParse,
    GeneralClientCapabilities.fromJson,
  );

  GeneralClientCapabilities({
    this.markdown,
    this.positionEncodings,
    this.regularExpressions,
    this.staleRequestSupport,
  });
  static GeneralClientCapabilities fromJson(Map<String, Object?> json) {
    final markdownJson = json['markdown'];
    final markdown = markdownJson != null
        ? MarkdownClientCapabilities.fromJson(
            markdownJson as Map<String, Object?>)
        : null;
    final positionEncodingsJson = json['positionEncodings'];
    final positionEncodings = (positionEncodingsJson as List<Object?>?)
        ?.map((item) => PositionEncodingKind.fromJson(item as String))
        .toList();
    final regularExpressionsJson = json['regularExpressions'];
    final regularExpressions = regularExpressionsJson != null
        ? RegularExpressionsClientCapabilities.fromJson(
            regularExpressionsJson as Map<String, Object?>)
        : null;
    final staleRequestSupportJson = json['staleRequestSupport'];
    final staleRequestSupport = staleRequestSupportJson != null
        ? GeneralClientCapabilitiesStaleRequestSupport.fromJson(
            staleRequestSupportJson as Map<String, Object?>)
        : null;
    return GeneralClientCapabilities(
      markdown: markdown,
      positionEncodings: positionEncodings,
      regularExpressions: regularExpressions,
      staleRequestSupport: staleRequestSupport,
    );
  }

  /// Client capabilities specific to the client's markdown parser.
  ///
  /// @since 3.16.0
  final MarkdownClientCapabilities? markdown;

  /// The position encodings supported by the client. Client and server have to
  /// agree on the same position encoding to ensure that offsets (e.g. character
  /// position in a line) are interpreted the same on both sides.
  ///
  /// To keep the protocol backwards compatible the following applies: if the
  /// value 'utf-16' is missing from the array of position encodings servers can
  /// assume that the client supports UTF-16. UTF-16 is therefore a mandatory
  /// encoding.
  ///
  /// If omitted it defaults to ['utf-16'].
  ///
  /// Implementation considerations: since the conversion from one encoding into
  /// another requires the content of the file / line the conversion is best
  /// done where the file is read which is usually on the server side.
  ///
  /// @since 3.17.0
  final List<PositionEncodingKind>? positionEncodings;

  /// Client capabilities specific to regular expressions.
  ///
  /// @since 3.16.0
  final RegularExpressionsClientCapabilities? regularExpressions;

  /// Client capability that signals how the client handles stale requests (e.g.
  /// a request for which the client will not process the response anymore since
  /// the information is outdated).
  ///
  /// @since 3.17.0
  final GeneralClientCapabilitiesStaleRequestSupport? staleRequestSupport;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (markdown != null) {
      result['markdown'] = markdown?.toJson();
    }
    if (positionEncodings != null) {
      result['positionEncodings'] =
          positionEncodings?.map((item) => item.toJson()).toList();
    }
    if (regularExpressions != null) {
      result['regularExpressions'] = regularExpressions?.toJson();
    }
    if (staleRequestSupport != null) {
      result['staleRequestSupport'] = staleRequestSupport?.toJson();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseMarkdownClientCapabilities(obj, reporter, 'markdown',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseListPositionEncodingKind(obj, reporter, 'positionEncodings',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseRegularExpressionsClientCapabilities(
          obj, reporter, 'regularExpressions',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseGeneralClientCapabilitiesStaleRequestSupport(
          obj, reporter, 'staleRequestSupport',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type GeneralClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is GeneralClientCapabilities &&
        other.runtimeType == GeneralClientCapabilities &&
        markdown == other.markdown &&
        listEqual(positionEncodings, other.positionEncodings,
            (PositionEncodingKind a, PositionEncodingKind b) => a == b) &&
        regularExpressions == other.regularExpressions &&
        staleRequestSupport == other.staleRequestSupport;
  }

  @override
  int get hashCode => Object.hash(
        markdown,
        lspHashCode(positionEncodings),
        regularExpressions,
        staleRequestSupport,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class GeneralClientCapabilitiesStaleRequestSupport implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    GeneralClientCapabilitiesStaleRequestSupport.canParse,
    GeneralClientCapabilitiesStaleRequestSupport.fromJson,
  );

  GeneralClientCapabilitiesStaleRequestSupport({
    required this.cancel,
    required this.retryOnContentModified,
  });
  static GeneralClientCapabilitiesStaleRequestSupport fromJson(
      Map<String, Object?> json) {
    final cancelJson = json['cancel'];
    final cancel = cancelJson as bool;
    final retryOnContentModifiedJson = json['retryOnContentModified'];
    final retryOnContentModified = (retryOnContentModifiedJson as List<Object?>)
        .map((item) => item as String)
        .toList();
    return GeneralClientCapabilitiesStaleRequestSupport(
      cancel: cancel,
      retryOnContentModified: retryOnContentModified,
    );
  }

  /// The client will actively cancel the request.
  final bool cancel;

  /// The list of requests for which the client will retry the request if it
  /// receives a response with error code `ContentModified`
  final List<String> retryOnContentModified;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['cancel'] = cancel;
    result['retryOnContentModified'] = retryOnContentModified;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseBool(obj, reporter, 'cancel',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseListString(obj, reporter, 'retryOnContentModified',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError(
          'must be of type GeneralClientCapabilitiesStaleRequestSupport');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is GeneralClientCapabilitiesStaleRequestSupport &&
        other.runtimeType == GeneralClientCapabilitiesStaleRequestSupport &&
        cancel == other.cancel &&
        listEqual(retryOnContentModified, other.retryOnContentModified,
            (String a, String b) => a == b);
  }

  @override
  int get hashCode => Object.hash(
        cancel,
        lspHashCode(retryOnContentModified),
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The result of a hover request.
class Hover implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    Hover.canParse,
    Hover.fromJson,
  );

  Hover({
    required this.contents,
    this.range,
  });
  static Hover fromJson(Map<String, Object?> json) {
    final contentsJson = json['contents'];
    final contents = _eitherMarkupContentString(contentsJson);
    final rangeJson = json['range'];
    final range = rangeJson != null
        ? Range.fromJson(rangeJson as Map<String, Object?>)
        : null;
    return Hover(
      contents: contents,
      range: range,
    );
  }

  /// The hover's content
  final Either2<MarkupContent, String> contents;

  /// An optional range inside the text document that is used to visualize the
  /// hover, e.g. by changing the background color.
  final Range? range;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['contents'] = contents;
    if (range != null) {
      result['range'] = range?.toJson();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseMarkupContentString(obj, reporter, 'contents',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseRange(obj, reporter, 'range',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type Hover');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is Hover &&
        other.runtimeType == Hover &&
        contents == other.contents &&
        range == other.range;
  }

  @override
  int get hashCode => Object.hash(
        contents,
        range,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class HoverClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    HoverClientCapabilities.canParse,
    HoverClientCapabilities.fromJson,
  );

  HoverClientCapabilities({
    this.contentFormat,
    this.dynamicRegistration,
  });
  static HoverClientCapabilities fromJson(Map<String, Object?> json) {
    final contentFormatJson = json['contentFormat'];
    final contentFormat = (contentFormatJson as List<Object?>?)
        ?.map((item) => MarkupKind.fromJson(item as String))
        .toList();
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    return HoverClientCapabilities(
      contentFormat: contentFormat,
      dynamicRegistration: dynamicRegistration,
    );
  }

  /// Client supports the following content formats for the content property.
  /// The order describes the preferred format of the client.
  final List<MarkupKind>? contentFormat;

  /// Whether hover supports dynamic registration.
  final bool? dynamicRegistration;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (contentFormat != null) {
      result['contentFormat'] =
          contentFormat?.map((item) => item.toJson()).toList();
    }
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListMarkupKind(obj, reporter, 'contentFormat',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'dynamicRegistration',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type HoverClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is HoverClientCapabilities &&
        other.runtimeType == HoverClientCapabilities &&
        listEqual(contentFormat, other.contentFormat,
            (MarkupKind a, MarkupKind b) => a == b) &&
        dynamicRegistration == other.dynamicRegistration;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(contentFormat),
        dynamicRegistration,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Hover options.
class HoverOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    HoverOptions.canParse,
    HoverOptions.fromJson,
  );

  HoverOptions({
    this.workDoneProgress,
  });
  static HoverOptions fromJson(Map<String, Object?> json) {
    if (HoverRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return HoverRegistrationOptions.fromJson(json);
    }
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return HoverOptions(
      workDoneProgress: workDoneProgress,
    );
  }

  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseBool(obj, reporter, 'workDoneProgress',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type HoverOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is HoverOptions &&
        other.runtimeType == HoverOptions &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => workDoneProgress.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Parameters for a HoverRequest.
class HoverParams
    implements TextDocumentPositionParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    HoverParams.canParse,
    HoverParams.fromJson,
  );

  HoverParams({
    required this.position,
    required this.textDocument,
    this.workDoneToken,
  });
  static HoverParams fromJson(Map<String, Object?> json) {
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken =
        workDoneTokenJson == null ? null : _eitherIntString(workDoneTokenJson);
    return HoverParams(
      position: position,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// The position inside the text document.
  @override
  final Position position;

  /// The text document.
  @override
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final ProgressToken? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['position'] = position.toJson();
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParsePosition(obj, reporter, 'position',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseIntString(obj, reporter, 'workDoneToken',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type HoverParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is HoverParams &&
        other.runtimeType == HoverParams &&
        position == other.position &&
        textDocument == other.textDocument &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        position,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Registration options for a HoverRequest.
class HoverRegistrationOptions
    implements HoverOptions, TextDocumentRegistrationOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    HoverRegistrationOptions.canParse,
    HoverRegistrationOptions.fromJson,
  );

  HoverRegistrationOptions({
    this.documentSelector,
    this.workDoneProgress,
  });
  static HoverRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return HoverRegistrationOptions(
      documentSelector: documentSelector,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListTextDocumentFilterWithScheme(
          obj, reporter, 'documentSelector',
          allowsUndefined: false, allowsNull: true)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'workDoneProgress',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type HoverRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is HoverRegistrationOptions &&
        other.runtimeType == HoverRegistrationOptions &&
        listEqual(
            documentSelector,
            other.documentSelector,
            (TextDocumentFilterWithScheme a, TextDocumentFilterWithScheme b) =>
                a == b) &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// @since 3.6.0
class ImplementationClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ImplementationClientCapabilities.canParse,
    ImplementationClientCapabilities.fromJson,
  );

  ImplementationClientCapabilities({
    this.dynamicRegistration,
    this.linkSupport,
  });
  static ImplementationClientCapabilities fromJson(Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    final linkSupportJson = json['linkSupport'];
    final linkSupport = linkSupportJson as bool?;
    return ImplementationClientCapabilities(
      dynamicRegistration: dynamicRegistration,
      linkSupport: linkSupport,
    );
  }

  /// Whether implementation supports dynamic registration. If this is set to
  /// `true` the client supports the new `ImplementationRegistrationOptions`
  /// return value for the corresponding server capability as well.
  final bool? dynamicRegistration;

  /// The client supports additional metadata in the form of definition links.
  ///
  /// @since 3.14.0
  final bool? linkSupport;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    if (linkSupport != null) {
      result['linkSupport'] = linkSupport;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseBool(obj, reporter, 'dynamicRegistration',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'linkSupport',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type ImplementationClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ImplementationClientCapabilities &&
        other.runtimeType == ImplementationClientCapabilities &&
        dynamicRegistration == other.dynamicRegistration &&
        linkSupport == other.linkSupport;
  }

  @override
  int get hashCode => Object.hash(
        dynamicRegistration,
        linkSupport,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class ImplementationOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ImplementationOptions.canParse,
    ImplementationOptions.fromJson,
  );

  ImplementationOptions({
    this.workDoneProgress,
  });
  static ImplementationOptions fromJson(Map<String, Object?> json) {
    if (ImplementationRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return ImplementationRegistrationOptions.fromJson(json);
    }
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return ImplementationOptions(
      workDoneProgress: workDoneProgress,
    );
  }

  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseBool(obj, reporter, 'workDoneProgress',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type ImplementationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ImplementationOptions &&
        other.runtimeType == ImplementationOptions &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => workDoneProgress.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class ImplementationParams
    implements
        PartialResultParams,
        TextDocumentPositionParams,
        WorkDoneProgressParams,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ImplementationParams.canParse,
    ImplementationParams.fromJson,
  );

  ImplementationParams({
    this.partialResultToken,
    required this.position,
    required this.textDocument,
    this.workDoneToken,
  });
  static ImplementationParams fromJson(Map<String, Object?> json) {
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : _eitherIntString(partialResultTokenJson);
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken =
        workDoneTokenJson == null ? null : _eitherIntString(workDoneTokenJson);
    return ImplementationParams(
      partialResultToken: partialResultToken,
      position: position,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final ProgressToken? partialResultToken;

  /// The position inside the text document.
  @override
  final Position position;

  /// The text document.
  @override
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final ProgressToken? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    result['position'] = position.toJson();
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseIntString(obj, reporter, 'partialResultToken',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParsePosition(obj, reporter, 'position',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseIntString(obj, reporter, 'workDoneToken',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type ImplementationParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ImplementationParams &&
        other.runtimeType == ImplementationParams &&
        partialResultToken == other.partialResultToken &&
        position == other.position &&
        textDocument == other.textDocument &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        partialResultToken,
        position,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class ImplementationRegistrationOptions
    implements
        ImplementationOptions,
        StaticRegistrationOptions,
        TextDocumentRegistrationOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ImplementationRegistrationOptions.canParse,
    ImplementationRegistrationOptions.fromJson,
  );

  ImplementationRegistrationOptions({
    this.documentSelector,
    this.id,
    this.workDoneProgress,
  });
  static ImplementationRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final idJson = json['id'];
    final id = idJson as String?;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return ImplementationRegistrationOptions(
      documentSelector: documentSelector,
      id: id,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;

  /// The id used to register the request. The id can be used to deregister the
  /// request again. See also Registration#id.
  @override
  final String? id;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (id != null) {
      result['id'] = id;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListTextDocumentFilterWithScheme(
          obj, reporter, 'documentSelector',
          allowsUndefined: false, allowsNull: true)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'id',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'workDoneProgress',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type ImplementationRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ImplementationRegistrationOptions &&
        other.runtimeType == ImplementationRegistrationOptions &&
        listEqual(
            documentSelector,
            other.documentSelector,
            (TextDocumentFilterWithScheme a, TextDocumentFilterWithScheme b) =>
                a == b) &&
        id == other.id &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        id,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The initialize parameters
class InitializeParams implements WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InitializeParams.canParse,
    InitializeParams.fromJson,
  );

  InitializeParams({
    required this.capabilities,
    this.clientInfo,
    this.initializationOptions,
    this.locale,
    this.processId,
    this.rootPath,
    this.rootUri,
    this.trace,
    this.workDoneToken,
    this.workspaceFolders,
  });
  static InitializeParams fromJson(Map<String, Object?> json) {
    final capabilitiesJson = json['capabilities'];
    final capabilities =
        ClientCapabilities.fromJson(capabilitiesJson as Map<String, Object?>);
    final clientInfoJson = json['clientInfo'];
    final clientInfo = clientInfoJson != null
        ? InitializeParamsClientInfo.fromJson(
            clientInfoJson as Map<String, Object?>)
        : null;
    final initializationOptionsJson = json['initializationOptions'];
    final initializationOptions = initializationOptionsJson;
    final localeJson = json['locale'];
    final locale = localeJson as String?;
    final processIdJson = json['processId'];
    final processId = processIdJson as int?;
    final rootPathJson = json['rootPath'];
    final rootPath = rootPathJson as String?;
    final rootUriJson = json['rootUri'];
    final rootUri = rootUriJson as String?;
    final traceJson = json['trace'];
    final trace = const {null, 'off', 'messages', 'compact', 'verbose'}
            .contains(traceJson)
        ? traceJson as String?
        : throw "$traceJson was not one of (null, 'off', 'messages', 'compact', 'verbose')";
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken =
        workDoneTokenJson == null ? null : _eitherIntString(workDoneTokenJson);
    final workspaceFoldersJson = json['workspaceFolders'];
    final workspaceFolders = (workspaceFoldersJson as List<Object?>?)
        ?.map((item) => WorkspaceFolder.fromJson(item as Map<String, Object?>))
        .toList();
    return InitializeParams(
      capabilities: capabilities,
      clientInfo: clientInfo,
      initializationOptions: initializationOptions,
      locale: locale,
      processId: processId,
      rootPath: rootPath,
      rootUri: rootUri,
      trace: trace,
      workDoneToken: workDoneToken,
      workspaceFolders: workspaceFolders,
    );
  }

  /// The capabilities provided by the client (editor or tool)
  final ClientCapabilities capabilities;

  /// Information about the client
  ///
  /// @since 3.15.0
  final InitializeParamsClientInfo? clientInfo;

  /// User provided initialization options.
  final LSPAny 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.
  final int? processId;

  /// The rootPath of the workspace. Is null if no folder is open.
  ///
  /// @deprecated in favour of rootUri.
  final String? rootPath;

  /// The rootUri of the workspace. Is null if no folder is open. If both
  /// `rootPath` and `rootUri` are set `rootUri` wins.
  ///
  /// @deprecated in favour of workspaceFolders.
  final DocumentUri? rootUri;

  /// The initial trace setting. If omitted trace is disabled ('off').
  final String? trace;

  /// An optional token that a server can use to report work done progress.
  @override
  final ProgressToken? workDoneToken;

  /// The workspace folders configured in the client when the server starts.
  ///
  /// This property is only available if the client supports workspace folders.
  /// It can be `null` if the client supports workspace folders but none are
  /// configured.
  ///
  /// @since 3.6.0
  final List<WorkspaceFolder>? workspaceFolders;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['capabilities'] = capabilities.toJson();
    if (clientInfo != null) {
      result['clientInfo'] = clientInfo?.toJson();
    }
    if (initializationOptions != null) {
      result['initializationOptions'] = initializationOptions;
    }
    if (locale != null) {
      result['locale'] = locale;
    }
    result['processId'] = processId;
    if (rootPath != null) {
      result['rootPath'] = rootPath;
    }
    result['rootUri'] = rootUri;
    if (trace != null) {
      result['trace'] = trace;
    }
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    if (workspaceFolders != null) {
      result['workspaceFolders'] =
          workspaceFolders?.map((item) => item.toJson()).toList();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseClientCapabilities(obj, reporter, 'capabilities',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseInitializeParamsClientInfo(obj, reporter, 'clientInfo',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'locale',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseInt(obj, reporter, 'processId',
          allowsUndefined: false, allowsNull: true)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'rootPath',
          allowsUndefined: true, allowsNull: true)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'rootUri',
          allowsUndefined: false, allowsNull: true)) {
        return false;
      }
      if (!_canParseLiteralUnion(obj, reporter, 'trace',
          allowsUndefined: true,
          allowsNull: false,
          literals: {'off', 'messages', 'compact', 'verbose'})) {
        return false;
      }
      if (!_canParseIntString(obj, reporter, 'workDoneToken',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseListWorkspaceFolder(obj, reporter, 'workspaceFolders',
          allowsUndefined: true, allowsNull: true);
    } else {
      reporter.reportError('must be of type InitializeParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is InitializeParams &&
        other.runtimeType == InitializeParams &&
        capabilities == other.capabilities &&
        clientInfo == other.clientInfo &&
        initializationOptions == other.initializationOptions &&
        locale == other.locale &&
        processId == other.processId &&
        rootPath == other.rootPath &&
        rootUri == other.rootUri &&
        trace == other.trace &&
        workDoneToken == other.workDoneToken &&
        listEqual(workspaceFolders, other.workspaceFolders,
            (WorkspaceFolder a, WorkspaceFolder b) => a == b);
  }

  @override
  int get hashCode => Object.hash(
        capabilities,
        clientInfo,
        initializationOptions,
        locale,
        processId,
        rootPath,
        rootUri,
        trace,
        workDoneToken,
        lspHashCode(workspaceFolders),
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class InitializeParamsClientInfo implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InitializeParamsClientInfo.canParse,
    InitializeParamsClientInfo.fromJson,
  );

  InitializeParamsClientInfo({
    required this.name,
    this.version,
  });
  static InitializeParamsClientInfo fromJson(Map<String, Object?> json) {
    final nameJson = json['name'];
    final name = nameJson as String;
    final versionJson = json['version'];
    final version = versionJson as String?;
    return InitializeParamsClientInfo(
      name: name,
      version: version,
    );
  }

  /// The name of the client as defined by the client.
  final String name;

  /// The client's version as defined by the client.
  final String? version;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['name'] = name;
    if (version != null) {
      result['version'] = version;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseString(obj, reporter, 'name',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseString(obj, reporter, 'version',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type InitializeParamsClientInfo');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is InitializeParamsClientInfo &&
        other.runtimeType == InitializeParamsClientInfo &&
        name == other.name &&
        version == other.version;
  }

  @override
  int get hashCode => Object.hash(
        name,
        version,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The result returned from an initialize request.
class InitializeResult implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InitializeResult.canParse,
    InitializeResult.fromJson,
  );

  InitializeResult({
    required this.capabilities,
    this.serverInfo,
  });
  static InitializeResult fromJson(Map<String, Object?> json) {
    final capabilitiesJson = json['capabilities'];
    final capabilities =
        ServerCapabilities.fromJson(capabilitiesJson as Map<String, Object?>);
    final serverInfoJson = json['serverInfo'];
    final serverInfo = serverInfoJson != null
        ? InitializeResultServerInfo.fromJson(
            serverInfoJson as Map<String, Object?>)
        : null;
    return InitializeResult(
      capabilities: capabilities,
      serverInfo: serverInfo,
    );
  }

  /// The capabilities the language server provides.
  final ServerCapabilities capabilities;

  /// Information about the server.
  ///
  /// @since 3.15.0
  final InitializeResultServerInfo? serverInfo;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['capabilities'] = capabilities.toJson();
    if (serverInfo != null) {
      result['serverInfo'] = serverInfo?.toJson();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseServerCapabilities(obj, reporter, 'capabilities',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseInitializeResultServerInfo(obj, reporter, 'serverInfo',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type InitializeResult');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is InitializeResult &&
        other.runtimeType == InitializeResult &&
        capabilities == other.capabilities &&
        serverInfo == other.serverInfo;
  }

  @override
  int get hashCode => Object.hash(
        capabilities,
        serverInfo,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class InitializeResultServerInfo implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InitializeResultServerInfo.canParse,
    InitializeResultServerInfo.fromJson,
  );

  InitializeResultServerInfo({
    required this.name,
    this.version,
  });
  static InitializeResultServerInfo fromJson(Map<String, Object?> json) {
    final nameJson = json['name'];
    final name = nameJson as String;
    final versionJson = json['version'];
    final version = versionJson as String?;
    return InitializeResultServerInfo(
      name: name,
      version: version,
    );
  }

  /// The name of the server as defined by the server.
  final String name;

  /// The server's version as defined by the server.
  final String? version;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['name'] = name;
    if (version != null) {
      result['version'] = version;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseString(obj, reporter, 'name',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseString(obj, reporter, 'version',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type InitializeResultServerInfo');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is InitializeResultServerInfo &&
        other.runtimeType == InitializeResultServerInfo &&
        name == other.name &&
        version == other.version;
  }

  @override
  int get hashCode => Object.hash(
        name,
        version,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class InitializedParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InitializedParams.canParse,
    InitializedParams.fromJson,
  );

  static InitializedParams fromJson(Map<String, Object?> json) {
    return InitializedParams();
  }

  @override
  Map<String, Object?> toJson() => {};

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return true;
    } else {
      reporter.reportError('must be of type InitializedParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is InitializedParams && other.runtimeType == InitializedParams;
  }

  @override
  int get hashCode => 42;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Inlay hint information.
///
/// @since 3.17.0
class InlayHint implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InlayHint.canParse,
    InlayHint.fromJson,
  );

  InlayHint({
    this.data,
    this.kind,
    required this.label,
    this.paddingLeft,
    this.paddingRight,
    required this.position,
    this.textEdits,
    this.tooltip,
  });
  static InlayHint fromJson(Map<String, Object?> json) {
    final dataJson = json['data'];
    final data = dataJson;
    final kindJson = json['kind'];
    final kind =
        kindJson != null ? InlayHintKind.fromJson(kindJson as int) : null;
    final labelJson = json['label'];
    final label = _eitherListInlayHintLabelPartString(labelJson);
    final paddingLeftJson = json['paddingLeft'];
    final paddingLeft = paddingLeftJson as bool?;
    final paddingRightJson = json['paddingRight'];
    final paddingRight = paddingRightJson as bool?;
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson as Map<String, Object?>);
    final textEditsJson = json['textEdits'];
    final textEdits = (textEditsJson as List<Object?>?)
        ?.map((item) => TextEdit.fromJson(item as Map<String, Object?>))
        .toList();
    final tooltipJson = json['tooltip'];
    final tooltip =
        tooltipJson == null ? null : _eitherMarkupContentString(tooltipJson);
    return InlayHint(
      data: data,
      kind: kind,
      label: label,
      paddingLeft: paddingLeft,
      paddingRight: paddingRight,
      position: position,
      textEdits: textEdits,
      tooltip: tooltip,
    );
  }

  /// A data entry field that is preserved on an inlay hint between a
  /// `textDocument/inlayHint` and a `inlayHint/resolve` request.
  final LSPAny data;

  /// The kind of this hint. Can be omitted in which case the client should fall
  /// back to a reasonable default.
  final InlayHintKind? kind;

  /// The label of this hint. A human readable string or an array of
  /// InlayHintLabelPart label parts.
  ///
  /// *Note* that neither the string nor the label part can be empty.
  final Either2<List<InlayHintLabelPart>, String> label;

  /// Render padding before the hint.
  ///
  /// Note: Padding should use the editor's background color, not the background
  /// color of the hint itself. That means padding can be used to visually
  /// align/separate an inlay hint.
  final bool? paddingLeft;

  /// Render padding after the hint.
  ///
  /// Note: Padding should use the editor's background color, not the background
  /// color of the hint itself. That means padding can be used to visually
  /// align/separate an inlay hint.
  final bool? paddingRight;

  /// The position of this hint.
  final Position position;

  /// Optional text edits that are performed when accepting this inlay hint.
  ///
  /// *Note* that edits are expected to change the document so that the inlay
  /// hint (or its nearest variant) is now part of the document and the inlay
  /// hint itself is now obsolete.
  final List<TextEdit>? textEdits;

  /// The tooltip text when you hover over this item.
  final Either2<MarkupContent, String>? tooltip;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (data != null) {
      result['data'] = data;
    }
    if (kind != null) {
      result['kind'] = kind?.toJson();
    }
    result['label'] = label;
    if (paddingLeft != null) {
      result['paddingLeft'] = paddingLeft;
    }
    if (paddingRight != null) {
      result['paddingRight'] = paddingRight;
    }
    result['position'] = position.toJson();
    if (textEdits != null) {
      result['textEdits'] = textEdits?.map((item) => item.toJson()).toList();
    }
    if (tooltip != null) {
      result['tooltip'] = tooltip;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseInlayHintKind(obj, reporter, 'kind',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseListInlayHintLabelPartString(obj, reporter, 'label',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'paddingLeft',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'paddingRight',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParsePosition(obj, reporter, 'position',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseListTextEdit(obj, reporter, 'textEdits',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseMarkupContentString(obj, reporter, 'tooltip',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type InlayHint');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is InlayHint &&
        other.runtimeType == InlayHint &&
        data == other.data &&
        kind == other.kind &&
        label == other.label &&
        paddingLeft == other.paddingLeft &&
        paddingRight == other.paddingRight &&
        position == other.position &&
        listEqual(
            textEdits, other.textEdits, (TextEdit a, TextEdit b) => a == b) &&
        tooltip == other.tooltip;
  }

  @override
  int get hashCode => Object.hash(
        data,
        kind,
        label,
        paddingLeft,
        paddingRight,
        position,
        lspHashCode(textEdits),
        tooltip,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Inlay hint client capabilities.
///
/// @since 3.17.0
class InlayHintClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InlayHintClientCapabilities.canParse,
    InlayHintClientCapabilities.fromJson,
  );

  InlayHintClientCapabilities({
    this.dynamicRegistration,
    this.resolveSupport,
  });
  static InlayHintClientCapabilities fromJson(Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    final resolveSupportJson = json['resolveSupport'];
    final resolveSupport = resolveSupportJson != null
        ? InlayHintClientCapabilitiesResolveSupport.fromJson(
            resolveSupportJson as Map<String, Object?>)
        : null;
    return InlayHintClientCapabilities(
      dynamicRegistration: dynamicRegistration,
      resolveSupport: resolveSupport,
    );
  }

  /// Whether inlay hints support dynamic registration.
  final bool? dynamicRegistration;

  /// Indicates which properties a client can resolve lazily on an inlay hint.
  final InlayHintClientCapabilitiesResolveSupport? resolveSupport;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    if (resolveSupport != null) {
      result['resolveSupport'] = resolveSupport?.toJson();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseBool(obj, reporter, 'dynamicRegistration',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseInlayHintClientCapabilitiesResolveSupport(
          obj, reporter, 'resolveSupport',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type InlayHintClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is InlayHintClientCapabilities &&
        other.runtimeType == InlayHintClientCapabilities &&
        dynamicRegistration == other.dynamicRegistration &&
        resolveSupport == other.resolveSupport;
  }

  @override
  int get hashCode => Object.hash(
        dynamicRegistration,
        resolveSupport,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class InlayHintClientCapabilitiesResolveSupport implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InlayHintClientCapabilitiesResolveSupport.canParse,
    InlayHintClientCapabilitiesResolveSupport.fromJson,
  );

  InlayHintClientCapabilitiesResolveSupport({
    required this.properties,
  });
  static InlayHintClientCapabilitiesResolveSupport fromJson(
      Map<String, Object?> json) {
    final propertiesJson = json['properties'];
    final properties = (propertiesJson as List<Object?>)
        .map((item) => item as String)
        .toList();
    return InlayHintClientCapabilitiesResolveSupport(
      properties: properties,
    );
  }

  /// The properties that a client can resolve lazily.
  final List<String> properties;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['properties'] = properties;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseListString(obj, reporter, 'properties',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError(
          'must be of type InlayHintClientCapabilitiesResolveSupport');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is InlayHintClientCapabilitiesResolveSupport &&
        other.runtimeType == InlayHintClientCapabilitiesResolveSupport &&
        listEqual(properties, other.properties, (String a, String b) => a == b);
  }

  @override
  int get hashCode => lspHashCode(properties);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Inlay hint kinds.
///
/// @since 3.17.0
class InlayHintKind implements ToJsonable {
  const InlayHintKind(this._value);
  const InlayHintKind.fromJson(this._value);

  final int _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is int;

  /// An inlay hint that is for a parameter.
  static const Parameter = InlayHintKind(2);

  /// An inlay hint that for a type annotation.
  static const Type = InlayHintKind(1);

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is InlayHintKind && other._value == _value;
}

/// An inlay hint label part allows for interactive and composite labels of
/// inlay hints.
///
/// @since 3.17.0
class InlayHintLabelPart implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InlayHintLabelPart.canParse,
    InlayHintLabelPart.fromJson,
  );

  InlayHintLabelPart({
    this.command,
    this.location,
    this.tooltip,
    required this.value,
  });
  static InlayHintLabelPart fromJson(Map<String, Object?> json) {
    final commandJson = json['command'];
    final command = commandJson != null
        ? Command.fromJson(commandJson as Map<String, Object?>)
        : null;
    final locationJson = json['location'];
    final location = locationJson != null
        ? Location.fromJson(locationJson as Map<String, Object?>)
        : null;
    final tooltipJson = json['tooltip'];
    final tooltip =
        tooltipJson == null ? null : _eitherMarkupContentString(tooltipJson);
    final valueJson = json['value'];
    final value = valueJson as String;
    return InlayHintLabelPart(
      command: command,
      location: location,
      tooltip: tooltip,
      value: value,
    );
  }

  /// An optional command for this label part.
  ///
  /// Depending on the client capability `inlayHint.resolveSupport` clients
  /// might resolve this property late using the resolve request.
  final Command? command;

  /// An optional source code location that represents this label part.
  ///
  /// The editor will use this location for the hover and for code navigation
  /// features: This part will become a clickable link that resolves to the
  /// definition of the symbol at the given location (not necessarily the
  /// location itself), it shows the hover that shows at the given location,
  /// and it shows a context menu with further code navigation commands.
  ///
  /// Depending on the client capability `inlayHint.resolveSupport` clients
  /// might resolve this property late using the resolve request.
  final Location? location;

  /// The tooltip text when you hover over this label part. Depending on the
  /// client capability `inlayHint.resolveSupport` clients might resolve this
  /// property late using the resolve request.
  final Either2<MarkupContent, String>? tooltip;

  /// The value of this label part.
  final String value;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (command != null) {
      result['command'] = command?.toJson();
    }
    if (location != null) {
      result['location'] = location?.toJson();
    }
    if (tooltip != null) {
      result['tooltip'] = tooltip;
    }
    result['value'] = value;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseCommand(obj, reporter, 'command',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseLocation(obj, reporter, 'location',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseMarkupContentString(obj, reporter, 'tooltip',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseString(obj, reporter, 'value',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type InlayHintLabelPart');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is InlayHintLabelPart &&
        other.runtimeType == InlayHintLabelPart &&
        command == other.command &&
        location == other.location &&
        tooltip == other.tooltip &&
        value == other.value;
  }

  @override
  int get hashCode => Object.hash(
        command,
        location,
        tooltip,
        value,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Inlay hint options used during static registration.
///
/// @since 3.17.0
class InlayHintOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InlayHintOptions.canParse,
    InlayHintOptions.fromJson,
  );

  InlayHintOptions({
    this.resolveProvider,
    this.workDoneProgress,
  });
  static InlayHintOptions fromJson(Map<String, Object?> json) {
    if (InlayHintRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return InlayHintRegistrationOptions.fromJson(json);
    }
    final resolveProviderJson = json['resolveProvider'];
    final resolveProvider = resolveProviderJson as bool?;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return InlayHintOptions(
      resolveProvider: resolveProvider,
      workDoneProgress: workDoneProgress,
    );
  }

  /// The server provides support to resolve additional information for an inlay
  /// hint item.
  final bool? resolveProvider;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (resolveProvider != null) {
      result['resolveProvider'] = resolveProvider;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseBool(obj, reporter, 'resolveProvider',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'workDoneProgress',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type InlayHintOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is InlayHintOptions &&
        other.runtimeType == InlayHintOptions &&
        resolveProvider == other.resolveProvider &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        resolveProvider,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A parameter literal used in inlay hint requests.
///
/// @since 3.17.0
class InlayHintParams implements WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InlayHintParams.canParse,
    InlayHintParams.fromJson,
  );

  InlayHintParams({
    required this.range,
    required this.textDocument,
    this.workDoneToken,
  });
  static InlayHintParams fromJson(Map<String, Object?> json) {
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken =
        workDoneTokenJson == null ? null : _eitherIntString(workDoneTokenJson);
    return InlayHintParams(
      range: range,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// The document range for which inlay hints should be computed.
  final Range range;

  /// The text document.
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final ProgressToken? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['range'] = range.toJson();
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseRange(obj, reporter, 'range',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseIntString(obj, reporter, 'workDoneToken',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type InlayHintParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is InlayHintParams &&
        other.runtimeType == InlayHintParams &&
        range == other.range &&
        textDocument == other.textDocument &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        range,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Inlay hint options used during static or dynamic registration.
///
/// @since 3.17.0
class InlayHintRegistrationOptions
    implements
        InlayHintOptions,
        StaticRegistrationOptions,
        TextDocumentRegistrationOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InlayHintRegistrationOptions.canParse,
    InlayHintRegistrationOptions.fromJson,
  );

  InlayHintRegistrationOptions({
    this.documentSelector,
    this.id,
    this.resolveProvider,
    this.workDoneProgress,
  });
  static InlayHintRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final idJson = json['id'];
    final id = idJson as String?;
    final resolveProviderJson = json['resolveProvider'];
    final resolveProvider = resolveProviderJson as bool?;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return InlayHintRegistrationOptions(
      documentSelector: documentSelector,
      id: id,
      resolveProvider: resolveProvider,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;

  /// The id used to register the request. The id can be used to deregister the
  /// request again. See also Registration#id.
  @override
  final String? id;

  /// The server provides support to resolve additional information for an inlay
  /// hint item.
  @override
  final bool? resolveProvider;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (id != null) {
      result['id'] = id;
    }
    if (resolveProvider != null) {
      result['resolveProvider'] = resolveProvider;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListTextDocumentFilterWithScheme(
          obj, reporter, 'documentSelector',
          allowsUndefined: false, allowsNull: true)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'id',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'resolveProvider',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'workDoneProgress',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type InlayHintRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is InlayHintRegistrationOptions &&
        other.runtimeType == InlayHintRegistrationOptions &&
        listEqual(
            documentSelector,
            other.documentSelector,
            (TextDocumentFilterWithScheme a, TextDocumentFilterWithScheme b) =>
                a == b) &&
        id == other.id &&
        resolveProvider == other.resolveProvider &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        id,
        resolveProvider,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Client workspace capabilities specific to inlay hints.
///
/// @since 3.17.0
class InlayHintWorkspaceClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InlayHintWorkspaceClientCapabilities.canParse,
    InlayHintWorkspaceClientCapabilities.fromJson,
  );

  InlayHintWorkspaceClientCapabilities({
    this.refreshSupport,
  });
  static InlayHintWorkspaceClientCapabilities fromJson(
      Map<String, Object?> json) {
    final refreshSupportJson = json['refreshSupport'];
    final refreshSupport = refreshSupportJson as bool?;
    return InlayHintWorkspaceClientCapabilities(
      refreshSupport: refreshSupport,
    );
  }

  /// Whether the client implementation supports a refresh request sent from the
  /// server to the client.
  ///
  /// Note that this event is global and will force the client to refresh all
  /// inlay hints currently shown. It should be used with absolute care and is
  /// useful for situation where a server for example detects a project wide
  /// change that requires such a calculation.
  final bool? refreshSupport;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (refreshSupport != null) {
      result['refreshSupport'] = refreshSupport;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseBool(obj, reporter, 'refreshSupport',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter
          .reportError('must be of type InlayHintWorkspaceClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is InlayHintWorkspaceClientCapabilities &&
        other.runtimeType == InlayHintWorkspaceClientCapabilities &&
        refreshSupport == other.refreshSupport;
  }

  @override
  int get hashCode => refreshSupport.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Client capabilities specific to inline values.
///
/// @since 3.17.0
class InlineValueClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InlineValueClientCapabilities.canParse,
    InlineValueClientCapabilities.fromJson,
  );

  InlineValueClientCapabilities({
    this.dynamicRegistration,
  });
  static InlineValueClientCapabilities fromJson(Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    return InlineValueClientCapabilities(
      dynamicRegistration: dynamicRegistration,
    );
  }

  /// Whether implementation supports dynamic registration for inline value
  /// providers.
  final bool? dynamicRegistration;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseBool(obj, reporter, 'dynamicRegistration',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type InlineValueClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is InlineValueClientCapabilities &&
        other.runtimeType == InlineValueClientCapabilities &&
        dynamicRegistration == other.dynamicRegistration;
  }

  @override
  int get hashCode => dynamicRegistration.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// @since 3.17.0
class InlineValueContext implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InlineValueContext.canParse,
    InlineValueContext.fromJson,
  );

  InlineValueContext({
    required this.frameId,
    required this.stoppedLocation,
  });
  static InlineValueContext fromJson(Map<String, Object?> json) {
    final frameIdJson = json['frameId'];
    final frameId = frameIdJson as int;
    final stoppedLocationJson = json['stoppedLocation'];
    final stoppedLocation =
        Range.fromJson(stoppedLocationJson as Map<String, Object?>);
    return InlineValueContext(
      frameId: frameId,
      stoppedLocation: stoppedLocation,
    );
  }

  /// The stack frame (as a DAP Id) where the execution has stopped.
  final int frameId;

  /// The document range where execution has stopped. Typically the end position
  /// of the range denotes the line where the inline values are shown.
  final Range stoppedLocation;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['frameId'] = frameId;
    result['stoppedLocation'] = stoppedLocation.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseInt(obj, reporter, 'frameId',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseRange(obj, reporter, 'stoppedLocation',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type InlineValueContext');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is InlineValueContext &&
        other.runtimeType == InlineValueContext &&
        frameId == other.frameId &&
        stoppedLocation == other.stoppedLocation;
  }

  @override
  int get hashCode => Object.hash(
        frameId,
        stoppedLocation,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Provide an inline value through an expression evaluation. If only a range is
/// specified, the expression will be extracted from the underlying document. An
/// optional expression can be used to override the extracted expression.
///
/// @since 3.17.0
class InlineValueEvaluatableExpression implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InlineValueEvaluatableExpression.canParse,
    InlineValueEvaluatableExpression.fromJson,
  );

  InlineValueEvaluatableExpression({
    this.expression,
    required this.range,
  });
  static InlineValueEvaluatableExpression fromJson(Map<String, Object?> json) {
    final expressionJson = json['expression'];
    final expression = expressionJson as String?;
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    return InlineValueEvaluatableExpression(
      expression: expression,
      range: range,
    );
  }

  /// If specified the expression overrides the extracted expression.
  final String? expression;

  /// The document range for which the inline value applies. The range is used
  /// to extract the evaluatable expression from the underlying document.
  final Range range;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (expression != null) {
      result['expression'] = expression;
    }
    result['range'] = range.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseString(obj, reporter, 'expression',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseRange(obj, reporter, 'range',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type InlineValueEvaluatableExpression');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is InlineValueEvaluatableExpression &&
        other.runtimeType == InlineValueEvaluatableExpression &&
        expression == other.expression &&
        range == other.range;
  }

  @override
  int get hashCode => Object.hash(
        expression,
        range,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Inline value options used during static registration.
///
/// @since 3.17.0
class InlineValueOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InlineValueOptions.canParse,
    InlineValueOptions.fromJson,
  );

  InlineValueOptions({
    this.workDoneProgress,
  });
  static InlineValueOptions fromJson(Map<String, Object?> json) {
    if (InlineValueRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return InlineValueRegistrationOptions.fromJson(json);
    }
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return InlineValueOptions(
      workDoneProgress: workDoneProgress,
    );
  }

  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseBool(obj, reporter, 'workDoneProgress',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type InlineValueOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is InlineValueOptions &&
        other.runtimeType == InlineValueOptions &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => workDoneProgress.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A parameter literal used in inline value requests.
///
/// @since 3.17.0
class InlineValueParams implements WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InlineValueParams.canParse,
    InlineValueParams.fromJson,
  );

  InlineValueParams({
    required this.context,
    required this.range,
    required this.textDocument,
    this.workDoneToken,
  });
  static InlineValueParams fromJson(Map<String, Object?> json) {
    final contextJson = json['context'];
    final context =
        InlineValueContext.fromJson(contextJson as Map<String, Object?>);
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken =
        workDoneTokenJson == null ? null : _eitherIntString(workDoneTokenJson);
    return InlineValueParams(
      context: context,
      range: range,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// Additional information about the context in which inline values were
  /// requested.
  final InlineValueContext context;

  /// The document range for which inline values should be computed.
  final Range range;

  /// The text document.
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final ProgressToken? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['context'] = context.toJson();
    result['range'] = range.toJson();
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseInlineValueContext(obj, reporter, 'context',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseRange(obj, reporter, 'range',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseIntString(obj, reporter, 'workDoneToken',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type InlineValueParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is InlineValueParams &&
        other.runtimeType == InlineValueParams &&
        context == other.context &&
        range == other.range &&
        textDocument == other.textDocument &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        context,
        range,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Inline value options used during static or dynamic registration.
///
/// @since 3.17.0
class InlineValueRegistrationOptions
    implements
        InlineValueOptions,
        StaticRegistrationOptions,
        TextDocumentRegistrationOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InlineValueRegistrationOptions.canParse,
    InlineValueRegistrationOptions.fromJson,
  );

  InlineValueRegistrationOptions({
    this.documentSelector,
    this.id,
    this.workDoneProgress,
  });
  static InlineValueRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final idJson = json['id'];
    final id = idJson as String?;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return InlineValueRegistrationOptions(
      documentSelector: documentSelector,
      id: id,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;

  /// The id used to register the request. The id can be used to deregister the
  /// request again. See also Registration#id.
  @override
  final String? id;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (id != null) {
      result['id'] = id;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListTextDocumentFilterWithScheme(
          obj, reporter, 'documentSelector',
          allowsUndefined: false, allowsNull: true)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'id',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'workDoneProgress',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type InlineValueRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is InlineValueRegistrationOptions &&
        other.runtimeType == InlineValueRegistrationOptions &&
        listEqual(
            documentSelector,
            other.documentSelector,
            (TextDocumentFilterWithScheme a, TextDocumentFilterWithScheme b) =>
                a == b) &&
        id == other.id &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        id,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Provide inline value as text.
///
/// @since 3.17.0
class InlineValueText implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InlineValueText.canParse,
    InlineValueText.fromJson,
  );

  InlineValueText({
    required this.range,
    required this.text,
  });
  static InlineValueText fromJson(Map<String, Object?> json) {
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    final textJson = json['text'];
    final text = textJson as String;
    return InlineValueText(
      range: range,
      text: text,
    );
  }

  /// The document range for which the inline value applies.
  final Range range;

  /// The text of the inline value.
  final String text;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['range'] = range.toJson();
    result['text'] = text;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseRange(obj, reporter, 'range',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseString(obj, reporter, 'text',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type InlineValueText');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is InlineValueText &&
        other.runtimeType == InlineValueText &&
        range == other.range &&
        text == other.text;
  }

  @override
  int get hashCode => Object.hash(
        range,
        text,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Provide inline value through a variable lookup. If only a range is
/// specified, the variable name will be extracted from the underlying document.
/// An optional variable name can be used to override the extracted name.
///
/// @since 3.17.0
class InlineValueVariableLookup implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InlineValueVariableLookup.canParse,
    InlineValueVariableLookup.fromJson,
  );

  InlineValueVariableLookup({
    required this.caseSensitiveLookup,
    required this.range,
    this.variableName,
  });
  static InlineValueVariableLookup fromJson(Map<String, Object?> json) {
    final caseSensitiveLookupJson = json['caseSensitiveLookup'];
    final caseSensitiveLookup = caseSensitiveLookupJson as bool;
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    final variableNameJson = json['variableName'];
    final variableName = variableNameJson as String?;
    return InlineValueVariableLookup(
      caseSensitiveLookup: caseSensitiveLookup,
      range: range,
      variableName: variableName,
    );
  }

  /// How to perform the lookup.
  final bool caseSensitiveLookup;

  /// The document range for which the inline value applies. The range is used
  /// to extract the variable name from the underlying document.
  final Range range;

  /// If specified the name of the variable to look up.
  final String? variableName;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['caseSensitiveLookup'] = caseSensitiveLookup;
    result['range'] = range.toJson();
    if (variableName != null) {
      result['variableName'] = variableName;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseBool(obj, reporter, 'caseSensitiveLookup',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseRange(obj, reporter, 'range',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseString(obj, reporter, 'variableName',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type InlineValueVariableLookup');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is InlineValueVariableLookup &&
        other.runtimeType == InlineValueVariableLookup &&
        caseSensitiveLookup == other.caseSensitiveLookup &&
        range == other.range &&
        variableName == other.variableName;
  }

  @override
  int get hashCode => Object.hash(
        caseSensitiveLookup,
        range,
        variableName,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Client workspace capabilities specific to inline values.
///
/// @since 3.17.0
class InlineValueWorkspaceClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InlineValueWorkspaceClientCapabilities.canParse,
    InlineValueWorkspaceClientCapabilities.fromJson,
  );

  InlineValueWorkspaceClientCapabilities({
    this.refreshSupport,
  });
  static InlineValueWorkspaceClientCapabilities fromJson(
      Map<String, Object?> json) {
    final refreshSupportJson = json['refreshSupport'];
    final refreshSupport = refreshSupportJson as bool?;
    return InlineValueWorkspaceClientCapabilities(
      refreshSupport: refreshSupport,
    );
  }

  /// Whether the client implementation supports a refresh request sent from the
  /// server to the client.
  ///
  /// Note that this event is global and will force the client to refresh all
  /// inline values currently shown. It should be used with absolute care and is
  /// useful for situation where a server for example detects a project wide
  /// change that requires such a calculation.
  final bool? refreshSupport;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (refreshSupport != null) {
      result['refreshSupport'] = refreshSupport;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseBool(obj, reporter, 'refreshSupport',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError(
          'must be of type InlineValueWorkspaceClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is InlineValueWorkspaceClientCapabilities &&
        other.runtimeType == InlineValueWorkspaceClientCapabilities &&
        refreshSupport == other.refreshSupport;
  }

  @override
  int get hashCode => refreshSupport.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A special text edit to provide an insert and a replace operation.
///
/// @since 3.16.0
class InsertReplaceEdit implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    InsertReplaceEdit.canParse,
    InsertReplaceEdit.fromJson,
  );

  InsertReplaceEdit({
    required this.insert,
    required this.newText,
    required this.replace,
  });
  static InsertReplaceEdit fromJson(Map<String, Object?> json) {
    final insertJson = json['insert'];
    final insert = Range.fromJson(insertJson as Map<String, Object?>);
    final newTextJson = json['newText'];
    final newText = newTextJson as String;
    final replaceJson = json['replace'];
    final replace = Range.fromJson(replaceJson as Map<String, Object?>);
    return InsertReplaceEdit(
      insert: insert,
      newText: newText,
      replace: replace,
    );
  }

  /// The range if the insert is requested
  final Range insert;

  /// The string to be inserted.
  final String newText;

  /// The range if the replace is requested.
  final Range replace;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['insert'] = insert.toJson();
    result['newText'] = newText;
    result['replace'] = replace.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseRange(obj, reporter, 'insert',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'newText',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseRange(obj, reporter, 'replace',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type InsertReplaceEdit');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is InsertReplaceEdit &&
        other.runtimeType == InsertReplaceEdit &&
        insert == other.insert &&
        newText == other.newText &&
        replace == other.replace;
  }

  @override
  int get hashCode => Object.hash(
        insert,
        newText,
        replace,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Defines whether the insert text in a completion item should be interpreted
/// as plain text or a snippet.
class InsertTextFormat implements ToJsonable {
  const InsertTextFormat._(this._value);
  const InsertTextFormat.fromJson(this._value);

  final int _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    switch (obj) {
      case 1:
      case 2:
        return true;
    }
    return false;
  }

  /// The primary text to be inserted is treated as a plain string.
  static const PlainText = InsertTextFormat._(1);

  /// The primary text to be inserted is treated as a snippet.
  ///
  /// A snippet can define tab stops and placeholders with `$1`, `$2` and
  /// `${3:foo}`. `$0` defines the final tab stop, it defaults to the end of the
  /// snippet. Placeholders with equal identifiers are linked,
  /// that is typing in one will update others too.
  ///
  /// See also:
  /// https://microsoft.github.io/language-server-protocol/specifications/specification-current/#snippet_syntax
  static const Snippet = InsertTextFormat._(2);

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is InsertTextFormat && other._value == _value;
}

/// How whitespace and indentation is handled during completion item insertion.
///
/// @since 3.16.0
class InsertTextMode implements ToJsonable {
  const InsertTextMode(this._value);
  const InsertTextMode.fromJson(this._value);

  final int _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is int;

  /// The editor adjusts leading whitespace of new lines so that they match the
  /// indentation up to the cursor of the line for which the item is accepted.
  ///
  /// Consider a line like this: <2tabs><cursor><3tabs>foo. Accepting a multi
  /// line completion item is indented using 2 tabs and all following lines
  /// inserted will be indented using 2 tabs as well.
  static const adjustIndentation = InsertTextMode(2);

  /// The insertion or replace strings is taken as it is. If the value is multi
  /// line the lines below the cursor will be inserted using the indentation
  /// defined in the string value. The client will not apply any kind of
  /// adjustments to the string.
  static const asIs = InsertTextMode(1);

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is InsertTextMode && other._value == _value;
}

/// Client capabilities for the linked editing range request.
///
/// @since 3.16.0
class LinkedEditingRangeClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    LinkedEditingRangeClientCapabilities.canParse,
    LinkedEditingRangeClientCapabilities.fromJson,
  );

  LinkedEditingRangeClientCapabilities({
    this.dynamicRegistration,
  });
  static LinkedEditingRangeClientCapabilities fromJson(
      Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    return LinkedEditingRangeClientCapabilities(
      dynamicRegistration: dynamicRegistration,
    );
  }

  /// Whether implementation supports dynamic registration. If this is set to
  /// `true` the client supports the new `(TextDocumentRegistrationOptions &
  /// StaticRegistrationOptions)` return value for the corresponding server
  /// capability as well.
  final bool? dynamicRegistration;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseBool(obj, reporter, 'dynamicRegistration',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter
          .reportError('must be of type LinkedEditingRangeClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is LinkedEditingRangeClientCapabilities &&
        other.runtimeType == LinkedEditingRangeClientCapabilities &&
        dynamicRegistration == other.dynamicRegistration;
  }

  @override
  int get hashCode => dynamicRegistration.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class LinkedEditingRangeOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    LinkedEditingRangeOptions.canParse,
    LinkedEditingRangeOptions.fromJson,
  );

  LinkedEditingRangeOptions({
    this.workDoneProgress,
  });
  static LinkedEditingRangeOptions fromJson(Map<String, Object?> json) {
    if (LinkedEditingRangeRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return LinkedEditingRangeRegistrationOptions.fromJson(json);
    }
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return LinkedEditingRangeOptions(
      workDoneProgress: workDoneProgress,
    );
  }

  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseBool(obj, reporter, 'workDoneProgress',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type LinkedEditingRangeOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is LinkedEditingRangeOptions &&
        other.runtimeType == LinkedEditingRangeOptions &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => workDoneProgress.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class LinkedEditingRangeParams
    implements TextDocumentPositionParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    LinkedEditingRangeParams.canParse,
    LinkedEditingRangeParams.fromJson,
  );

  LinkedEditingRangeParams({
    required this.position,
    required this.textDocument,
    this.workDoneToken,
  });
  static LinkedEditingRangeParams fromJson(Map<String, Object?> json) {
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken =
        workDoneTokenJson == null ? null : _eitherIntString(workDoneTokenJson);
    return LinkedEditingRangeParams(
      position: position,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// The position inside the text document.
  @override
  final Position position;

  /// The text document.
  @override
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final ProgressToken? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['position'] = position.toJson();
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParsePosition(obj, reporter, 'position',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseIntString(obj, reporter, 'workDoneToken',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type LinkedEditingRangeParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is LinkedEditingRangeParams &&
        other.runtimeType == LinkedEditingRangeParams &&
        position == other.position &&
        textDocument == other.textDocument &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        position,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class LinkedEditingRangeRegistrationOptions
    implements
        LinkedEditingRangeOptions,
        StaticRegistrationOptions,
        TextDocumentRegistrationOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    LinkedEditingRangeRegistrationOptions.canParse,
    LinkedEditingRangeRegistrationOptions.fromJson,
  );

  LinkedEditingRangeRegistrationOptions({
    this.documentSelector,
    this.id,
    this.workDoneProgress,
  });
  static LinkedEditingRangeRegistrationOptions fromJson(
      Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final idJson = json['id'];
    final id = idJson as String?;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return LinkedEditingRangeRegistrationOptions(
      documentSelector: documentSelector,
      id: id,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;

  /// The id used to register the request. The id can be used to deregister the
  /// request again. See also Registration#id.
  @override
  final String? id;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (id != null) {
      result['id'] = id;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListTextDocumentFilterWithScheme(
          obj, reporter, 'documentSelector',
          allowsUndefined: false, allowsNull: true)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'id',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'workDoneProgress',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter
          .reportError('must be of type LinkedEditingRangeRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is LinkedEditingRangeRegistrationOptions &&
        other.runtimeType == LinkedEditingRangeRegistrationOptions &&
        listEqual(
            documentSelector,
            other.documentSelector,
            (TextDocumentFilterWithScheme a, TextDocumentFilterWithScheme b) =>
                a == b) &&
        id == other.id &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        id,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The result of a linked editing range request.
///
/// @since 3.16.0
class LinkedEditingRanges implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    LinkedEditingRanges.canParse,
    LinkedEditingRanges.fromJson,
  );

  LinkedEditingRanges({
    required this.ranges,
    this.wordPattern,
  });
  static LinkedEditingRanges fromJson(Map<String, Object?> json) {
    final rangesJson = json['ranges'];
    final ranges = (rangesJson as List<Object?>)
        .map((item) => Range.fromJson(item as Map<String, Object?>))
        .toList();
    final wordPatternJson = json['wordPattern'];
    final wordPattern = wordPatternJson as String?;
    return LinkedEditingRanges(
      ranges: ranges,
      wordPattern: wordPattern,
    );
  }

  /// A list of ranges that can be edited together. The ranges must have
  /// identical length and contain identical text content. The ranges cannot
  /// overlap.
  final List<Range> ranges;

  /// An optional word pattern (regular expression) that describes valid
  /// contents for the given ranges. If no pattern is provided, the client
  /// configuration's word pattern will be used.
  final String? wordPattern;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['ranges'] = ranges.map((item) => item.toJson()).toList();
    if (wordPattern != null) {
      result['wordPattern'] = wordPattern;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListRange(obj, reporter, 'ranges',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseString(obj, reporter, 'wordPattern',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type LinkedEditingRanges');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is LinkedEditingRanges &&
        other.runtimeType == LinkedEditingRanges &&
        listEqual(ranges, other.ranges, (Range a, Range b) => a == b) &&
        wordPattern == other.wordPattern;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(ranges),
        wordPattern,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Represents a location inside a resource, such as a line inside a text file.
class Location implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    Location.canParse,
    Location.fromJson,
  );

  Location({
    required this.range,
    required this.uri,
  });
  static Location fromJson(Map<String, Object?> json) {
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    final uriJson = json['uri'];
    final uri = uriJson as String;
    return Location(
      range: range,
      uri: uri,
    );
  }

  final Range range;
  final DocumentUri uri;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['range'] = range.toJson();
    result['uri'] = uri;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseRange(obj, reporter, 'range',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseString(obj, reporter, 'uri',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type Location');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is Location &&
        other.runtimeType == Location &&
        range == other.range &&
        uri == other.uri;
  }

  @override
  int get hashCode => Object.hash(
        range,
        uri,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Represents the connection of two locations. Provides additional metadata
/// over normal locations,
/// including an origin range.
class LocationLink implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    LocationLink.canParse,
    LocationLink.fromJson,
  );

  LocationLink({
    this.originSelectionRange,
    required this.targetRange,
    required this.targetSelectionRange,
    required this.targetUri,
  });
  static LocationLink fromJson(Map<String, Object?> json) {
    final originSelectionRangeJson = json['originSelectionRange'];
    final originSelectionRange = originSelectionRangeJson != null
        ? Range.fromJson(originSelectionRangeJson as Map<String, Object?>)
        : null;
    final targetRangeJson = json['targetRange'];
    final targetRange = Range.fromJson(targetRangeJson as Map<String, Object?>);
    final targetSelectionRangeJson = json['targetSelectionRange'];
    final targetSelectionRange =
        Range.fromJson(targetSelectionRangeJson as Map<String, Object?>);
    final targetUriJson = json['targetUri'];
    final targetUri = targetUriJson as String;
    return LocationLink(
      originSelectionRange: originSelectionRange,
      targetRange: targetRange,
      targetSelectionRange: targetSelectionRange,
      targetUri: targetUri,
    );
  }

  /// Span of the origin of this link.
  ///
  /// Used as the underlined span for mouse interaction. Defaults to the word
  /// range at the definition position.
  final Range? originSelectionRange;

  /// The full target range of this link. If the target for example is a symbol
  /// then target range is the range enclosing this symbol not including
  /// leading/trailing whitespace but everything else like comments. This
  /// information is typically used to highlight the range in the editor.
  final Range targetRange;

  /// The range that should be selected and revealed when this link is being
  /// followed, e.g the name of a function. Must be contained by the
  /// `targetRange`. See also `DocumentSymbol#range`
  final Range targetSelectionRange;

  /// The target resource identifier of this link.
  final DocumentUri targetUri;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (originSelectionRange != null) {
      result['originSelectionRange'] = originSelectionRange?.toJson();
    }
    result['targetRange'] = targetRange.toJson();
    result['targetSelectionRange'] = targetSelectionRange.toJson();
    result['targetUri'] = targetUri;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseRange(obj, reporter, 'originSelectionRange',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseRange(obj, reporter, 'targetRange',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseRange(obj, reporter, 'targetSelectionRange',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseString(obj, reporter, 'targetUri',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type LocationLink');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is LocationLink &&
        other.runtimeType == LocationLink &&
        originSelectionRange == other.originSelectionRange &&
        targetRange == other.targetRange &&
        targetSelectionRange == other.targetSelectionRange &&
        targetUri == other.targetUri;
  }

  @override
  int get hashCode => Object.hash(
        originSelectionRange,
        targetRange,
        targetSelectionRange,
        targetUri,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The log message parameters.
class LogMessageParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    LogMessageParams.canParse,
    LogMessageParams.fromJson,
  );

  LogMessageParams({
    required this.message,
    required this.type,
  });
  static LogMessageParams fromJson(Map<String, Object?> json) {
    final messageJson = json['message'];
    final message = messageJson as String;
    final typeJson = json['type'];
    final type = MessageType.fromJson(typeJson as int);
    return LogMessageParams(
      message: message,
      type: type,
    );
  }

  /// The actual message.
  final String message;

  /// The message type. See {@link MessageType}
  final MessageType type;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['message'] = message;
    result['type'] = type.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseString(obj, reporter, 'message',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseMessageType(obj, reporter, 'type',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type LogMessageParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is LogMessageParams &&
        other.runtimeType == LogMessageParams &&
        message == other.message &&
        type == other.type;
  }

  @override
  int get hashCode => Object.hash(
        message,
        type,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class LogTraceParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    LogTraceParams.canParse,
    LogTraceParams.fromJson,
  );

  LogTraceParams({
    required this.message,
    this.verbose,
  });
  static LogTraceParams fromJson(Map<String, Object?> json) {
    final messageJson = json['message'];
    final message = messageJson as String;
    final verboseJson = json['verbose'];
    final verbose = verboseJson as String?;
    return LogTraceParams(
      message: message,
      verbose: verbose,
    );
  }

  final String message;
  final String? verbose;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['message'] = message;
    if (verbose != null) {
      result['verbose'] = verbose;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseString(obj, reporter, 'message',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseString(obj, reporter, 'verbose',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type LogTraceParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is LogTraceParams &&
        other.runtimeType == LogTraceParams &&
        message == other.message &&
        verbose == other.verbose;
  }

  @override
  int get hashCode => Object.hash(
        message,
        verbose,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Client capabilities specific to the used markdown parser.
///
/// @since 3.16.0
class MarkdownClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    MarkdownClientCapabilities.canParse,
    MarkdownClientCapabilities.fromJson,
  );

  MarkdownClientCapabilities({
    this.allowedTags,
    required this.parser,
    this.version,
  });
  static MarkdownClientCapabilities fromJson(Map<String, Object?> json) {
    final allowedTagsJson = json['allowedTags'];
    final allowedTags = (allowedTagsJson as List<Object?>?)
        ?.map((item) => item as String)
        .toList();
    final parserJson = json['parser'];
    final parser = parserJson as String;
    final versionJson = json['version'];
    final version = versionJson as String?;
    return MarkdownClientCapabilities(
      allowedTags: allowedTags,
      parser: parser,
      version: version,
    );
  }

  /// A list of HTML tags that the client allows / supports in Markdown.
  ///
  /// @since 3.17.0
  final List<String>? allowedTags;

  /// The name of the parser.
  final String parser;

  /// The version of the parser.
  final String? version;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (allowedTags != null) {
      result['allowedTags'] = allowedTags;
    }
    result['parser'] = parser;
    if (version != null) {
      result['version'] = version;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListString(obj, reporter, 'allowedTags',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'parser',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseString(obj, reporter, 'version',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type MarkdownClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is MarkdownClientCapabilities &&
        other.runtimeType == MarkdownClientCapabilities &&
        listEqual(
            allowedTags, other.allowedTags, (String a, String b) => a == b) &&
        parser == other.parser &&
        version == other.version;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(allowedTags),
        parser,
        version,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A `MarkupContent` literal represents a string value which content is
/// interpreted base on its kind flag. Currently the protocol supports
/// `plaintext` and `markdown` as markup kinds.
///
/// If the kind is `markdown` then the value can contain fenced code blocks like
/// in GitHub issues. See
/// https://help.github.com/articles/creating-and-highlighting-code-blocks/#syntax-highlighting
///
/// Here is an example how such a string can be constructed using JavaScript /
/// TypeScript:
/// ```ts let markdown: MarkdownContent = {
///  kind: MarkupKind.Markdown,
///  value: [
///    '# Header',
///    'Some text',
///    '```typescript',
///    'someCode();',
///    '```'
///  ].join('\n')
/// };
/// ```
///
/// *Please Note* that clients might sanitize the return markdown. A client
/// could decide to remove HTML from the markdown to avoid script execution.
class MarkupContent implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    MarkupContent.canParse,
    MarkupContent.fromJson,
  );

  MarkupContent({
    required this.kind,
    required this.value,
  });
  static MarkupContent fromJson(Map<String, Object?> json) {
    final kindJson = json['kind'];
    final kind = MarkupKind.fromJson(kindJson as String);
    final valueJson = json['value'];
    final value = valueJson as String;
    return MarkupContent(
      kind: kind,
      value: value,
    );
  }

  /// The type of the Markup
  final MarkupKind kind;

  /// The content itself
  final String value;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['kind'] = kind.toJson();
    result['value'] = value;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseMarkupKind(obj, reporter, 'kind',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseString(obj, reporter, 'value',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type MarkupContent');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is MarkupContent &&
        other.runtimeType == MarkupContent &&
        kind == other.kind &&
        value == other.value;
  }

  @override
  int get hashCode => Object.hash(
        kind,
        value,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Describes the content type that a client supports in various result literals
/// like `Hover`, `ParameterInfo` or `CompletionItem`.
///
/// Please note that `MarkupKinds` must not start with a `$`. This kinds are
/// reserved for internal usage.
class MarkupKind implements ToJsonable {
  const MarkupKind._(this._value);
  const MarkupKind.fromJson(this._value);

  final String _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    switch (obj) {
      case 'markdown':
      case 'plaintext':
        return true;
    }
    return false;
  }

  /// Markdown is supported as a content format
  static const Markdown = MarkupKind._('markdown');

  /// Plain text is supported as a content format
  static const PlainText = MarkupKind._('plaintext');

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is MarkupKind && other._value == _value;
}

class MessageActionItem implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    MessageActionItem.canParse,
    MessageActionItem.fromJson,
  );

  MessageActionItem({
    required this.title,
  });
  static MessageActionItem fromJson(Map<String, Object?> json) {
    final titleJson = json['title'];
    final title = titleJson as String;
    return MessageActionItem(
      title: title,
    );
  }

  /// A short title like 'Retry', 'Open Log' etc.
  final String title;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['title'] = title;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseString(obj, reporter, 'title',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type MessageActionItem');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is MessageActionItem &&
        other.runtimeType == MessageActionItem &&
        title == other.title;
  }

  @override
  int get hashCode => title.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The message type
class MessageType implements ToJsonable {
  const MessageType(this._value);
  const MessageType.fromJson(this._value);

  final int _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is int;

  /// An error message.
  static const Error = MessageType(1);

  /// An information message.
  static const Info = MessageType(3);

  /// A log message.
  static const Log = MessageType(4);

  /// A warning message.
  static const Warning = MessageType(2);

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is MessageType && other._value == _value;
}

/// All standard LSP Methods read from the JSON spec.
class Method implements ToJsonable {
  const Method(this._value);
  const Method.fromJson(this._value);

  final String _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is String;

  /// Constant for the 'callHierarchy/incomingCalls' method.
  static const callHierarchy_incomingCalls =
      Method('callHierarchy/incomingCalls');

  /// Constant for the 'callHierarchy/outgoingCalls' method.
  static const callHierarchy_outgoingCalls =
      Method('callHierarchy/outgoingCalls');

  /// Constant for the '$/cancelRequest' method.
  static const cancelRequest = Method(r'$/cancelRequest');

  /// Constant for the 'client/registerCapability' method.
  static const client_registerCapability = Method('client/registerCapability');

  /// Constant for the 'client/unregisterCapability' method.
  static const client_unregisterCapability =
      Method('client/unregisterCapability');

  /// Constant for the 'codeAction/resolve' method.
  static const codeAction_resolve = Method('codeAction/resolve');

  /// Constant for the 'codeLens/resolve' method.
  static const codeLens_resolve = Method('codeLens/resolve');

  /// Constant for the 'completionItem/resolve' method.
  static const completionItem_resolve = Method('completionItem/resolve');

  /// Constant for the 'documentLink/resolve' method.
  static const documentLink_resolve = Method('documentLink/resolve');

  /// Constant for the 'exit' method.
  static const exit = Method('exit');

  /// Constant for the 'initialize' method.
  static const initialize = Method('initialize');

  /// Constant for the 'initialized' method.
  static const initialized = Method('initialized');

  /// Constant for the 'inlayHint/resolve' method.
  static const inlayHint_resolve = Method('inlayHint/resolve');

  /// Constant for the '$/logTrace' method.
  static const logTrace = Method(r'$/logTrace');

  /// Constant for the 'notebookDocument/didChange' method.
  static const notebookDocument_didChange =
      Method('notebookDocument/didChange');

  /// Constant for the 'notebookDocument/didClose' method.
  static const notebookDocument_didClose = Method('notebookDocument/didClose');

  /// Constant for the 'notebookDocument/didOpen' method.
  static const notebookDocument_didOpen = Method('notebookDocument/didOpen');

  /// Constant for the 'notebookDocument/didSave' method.
  static const notebookDocument_didSave = Method('notebookDocument/didSave');

  /// Constant for the '$/progress' method.
  static const progress = Method(r'$/progress');

  /// Constant for the '$/setTrace' method.
  static const setTrace = Method(r'$/setTrace');

  /// Constant for the 'shutdown' method.
  static const shutdown = Method('shutdown');

  /// Constant for the 'telemetry/event' method.
  static const telemetry_event = Method('telemetry/event');

  /// Constant for the 'textDocument/codeAction' method.
  static const textDocument_codeAction = Method('textDocument/codeAction');

  /// Constant for the 'textDocument/codeLens' method.
  static const textDocument_codeLens = Method('textDocument/codeLens');

  /// Constant for the 'textDocument/colorPresentation' method.
  static const textDocument_colorPresentation =
      Method('textDocument/colorPresentation');

  /// Constant for the 'textDocument/completion' method.
  static const textDocument_completion = Method('textDocument/completion');

  /// Constant for the 'textDocument/declaration' method.
  static const textDocument_declaration = Method('textDocument/declaration');

  /// Constant for the 'textDocument/definition' method.
  static const textDocument_definition = Method('textDocument/definition');

  /// Constant for the 'textDocument/diagnostic' method.
  static const textDocument_diagnostic = Method('textDocument/diagnostic');

  /// Constant for the 'textDocument/didChange' method.
  static const textDocument_didChange = Method('textDocument/didChange');

  /// Constant for the 'textDocument/didClose' method.
  static const textDocument_didClose = Method('textDocument/didClose');

  /// Constant for the 'textDocument/didOpen' method.
  static const textDocument_didOpen = Method('textDocument/didOpen');

  /// Constant for the 'textDocument/didSave' method.
  static const textDocument_didSave = Method('textDocument/didSave');

  /// Constant for the 'textDocument/documentColor' method.
  static const textDocument_documentColor =
      Method('textDocument/documentColor');

  /// Constant for the 'textDocument/documentHighlight' method.
  static const textDocument_documentHighlight =
      Method('textDocument/documentHighlight');

  /// Constant for the 'textDocument/documentLink' method.
  static const textDocument_documentLink = Method('textDocument/documentLink');

  /// Constant for the 'textDocument/documentSymbol' method.
  static const textDocument_documentSymbol =
      Method('textDocument/documentSymbol');

  /// Constant for the 'textDocument/foldingRange' method.
  static const textDocument_foldingRange = Method('textDocument/foldingRange');

  /// Constant for the 'textDocument/formatting' method.
  static const textDocument_formatting = Method('textDocument/formatting');

  /// Constant for the 'textDocument/hover' method.
  static const textDocument_hover = Method('textDocument/hover');

  /// Constant for the 'textDocument/implementation' method.
  static const textDocument_implementation =
      Method('textDocument/implementation');

  /// Constant for the 'textDocument/inlayHint' method.
  static const textDocument_inlayHint = Method('textDocument/inlayHint');

  /// Constant for the 'textDocument/inlineValue' method.
  static const textDocument_inlineValue = Method('textDocument/inlineValue');

  /// Constant for the 'textDocument/linkedEditingRange' method.
  static const textDocument_linkedEditingRange =
      Method('textDocument/linkedEditingRange');

  /// Constant for the 'textDocument/moniker' method.
  static const textDocument_moniker = Method('textDocument/moniker');

  /// Constant for the 'textDocument/onTypeFormatting' method.
  static const textDocument_onTypeFormatting =
      Method('textDocument/onTypeFormatting');

  /// Constant for the 'textDocument/prepareCallHierarchy' method.
  static const textDocument_prepareCallHierarchy =
      Method('textDocument/prepareCallHierarchy');

  /// Constant for the 'textDocument/prepareRename' method.
  static const textDocument_prepareRename =
      Method('textDocument/prepareRename');

  /// Constant for the 'textDocument/prepareTypeHierarchy' method.
  static const textDocument_prepareTypeHierarchy =
      Method('textDocument/prepareTypeHierarchy');

  /// Constant for the 'textDocument/publishDiagnostics' method.
  static const textDocument_publishDiagnostics =
      Method('textDocument/publishDiagnostics');

  /// Constant for the 'textDocument/rangeFormatting' method.
  static const textDocument_rangeFormatting =
      Method('textDocument/rangeFormatting');

  /// Constant for the 'textDocument/references' method.
  static const textDocument_references = Method('textDocument/references');

  /// Constant for the 'textDocument/rename' method.
  static const textDocument_rename = Method('textDocument/rename');

  /// Constant for the 'textDocument/selectionRange' method.
  static const textDocument_selectionRange =
      Method('textDocument/selectionRange');

  /// Constant for the 'textDocument/semanticTokens/full' method.
  static const textDocument_semanticTokens_full =
      Method('textDocument/semanticTokens/full');

  /// Constant for the 'textDocument/semanticTokens/full/delta' method.
  static const textDocument_semanticTokens_full_delta =
      Method('textDocument/semanticTokens/full/delta');

  /// Constant for the 'textDocument/semanticTokens/range' method.
  static const textDocument_semanticTokens_range =
      Method('textDocument/semanticTokens/range');

  /// Constant for the 'textDocument/signatureHelp' method.
  static const textDocument_signatureHelp =
      Method('textDocument/signatureHelp');

  /// Constant for the 'textDocument/typeDefinition' method.
  static const textDocument_typeDefinition =
      Method('textDocument/typeDefinition');

  /// Constant for the 'textDocument/willSave' method.
  static const textDocument_willSave = Method('textDocument/willSave');

  /// Constant for the 'textDocument/willSaveWaitUntil' method.
  static const textDocument_willSaveWaitUntil =
      Method('textDocument/willSaveWaitUntil');

  /// Constant for the 'typeHierarchy/subtypes' method.
  static const typeHierarchy_subtypes = Method('typeHierarchy/subtypes');

  /// Constant for the 'typeHierarchy/supertypes' method.
  static const typeHierarchy_supertypes = Method('typeHierarchy/supertypes');

  /// Constant for the 'window/logMessage' method.
  static const window_logMessage = Method('window/logMessage');

  /// Constant for the 'window/showDocument' method.
  static const window_showDocument = Method('window/showDocument');

  /// Constant for the 'window/showMessage' method.
  static const window_showMessage = Method('window/showMessage');

  /// Constant for the 'window/showMessageRequest' method.
  static const window_showMessageRequest = Method('window/showMessageRequest');

  /// Constant for the 'window/workDoneProgress/cancel' method.
  static const window_workDoneProgress_cancel =
      Method('window/workDoneProgress/cancel');

  /// Constant for the 'window/workDoneProgress/create' method.
  static const window_workDoneProgress_create =
      Method('window/workDoneProgress/create');

  /// Constant for the 'workspace/applyEdit' method.
  static const workspace_applyEdit = Method('workspace/applyEdit');

  /// Constant for the 'workspace/codeLens/refresh' method.
  static const workspace_codeLens_refresh =
      Method('workspace/codeLens/refresh');

  /// Constant for the 'workspace/configuration' method.
  static const workspace_configuration = Method('workspace/configuration');

  /// Constant for the 'workspace/diagnostic' method.
  static const workspace_diagnostic = Method('workspace/diagnostic');

  /// Constant for the 'workspace/diagnostic/refresh' method.
  static const workspace_diagnostic_refresh =
      Method('workspace/diagnostic/refresh');

  /// Constant for the 'workspace/didChangeConfiguration' method.
  static const workspace_didChangeConfiguration =
      Method('workspace/didChangeConfiguration');

  /// Constant for the 'workspace/didChangeWatchedFiles' method.
  static const workspace_didChangeWatchedFiles =
      Method('workspace/didChangeWatchedFiles');

  /// Constant for the 'workspace/didChangeWorkspaceFolders' method.
  static const workspace_didChangeWorkspaceFolders =
      Method('workspace/didChangeWorkspaceFolders');

  /// Constant for the 'workspace/didCreateFiles' method.
  static const workspace_didCreateFiles = Method('workspace/didCreateFiles');

  /// Constant for the 'workspace/didDeleteFiles' method.
  static const workspace_didDeleteFiles = Method('workspace/didDeleteFiles');

  /// Constant for the 'workspace/didRenameFiles' method.
  static const workspace_didRenameFiles = Method('workspace/didRenameFiles');

  /// Constant for the 'workspace/executeCommand' method.
  static const workspace_executeCommand = Method('workspace/executeCommand');

  /// Constant for the 'workspace/inlayHint/refresh' method.
  static const workspace_inlayHint_refresh =
      Method('workspace/inlayHint/refresh');

  /// Constant for the 'workspace/inlineValue/refresh' method.
  static const workspace_inlineValue_refresh =
      Method('workspace/inlineValue/refresh');

  /// Constant for the 'workspace/semanticTokens/refresh' method.
  static const workspace_semanticTokens_refresh =
      Method('workspace/semanticTokens/refresh');

  /// Constant for the 'workspace/symbol' method.
  static const workspace_symbol = Method('workspace/symbol');

  /// Constant for the 'workspace/willCreateFiles' method.
  static const workspace_willCreateFiles = Method('workspace/willCreateFiles');

  /// Constant for the 'workspace/willDeleteFiles' method.
  static const workspace_willDeleteFiles = Method('workspace/willDeleteFiles');

  /// Constant for the 'workspace/willRenameFiles' method.
  static const workspace_willRenameFiles = Method('workspace/willRenameFiles');

  /// Constant for the 'workspace/workspaceFolders' method.
  static const workspace_workspaceFolders =
      Method('workspace/workspaceFolders');

  /// Constant for the 'workspaceSymbol/resolve' method.
  static const workspaceSymbol_resolve = Method('workspaceSymbol/resolve');

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) => other is Method && other._value == _value;
}

/// Moniker definition to match LSIF 0.5 moniker definition.
///
/// @since 3.16.0
class Moniker implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    Moniker.canParse,
    Moniker.fromJson,
  );

  Moniker({
    required this.identifier,
    this.kind,
    required this.scheme,
    required this.unique,
  });
  static Moniker fromJson(Map<String, Object?> json) {
    final identifierJson = json['identifier'];
    final identifier = identifierJson as String;
    final kindJson = json['kind'];
    final kind =
        kindJson != null ? MonikerKind.fromJson(kindJson as String) : null;
    final schemeJson = json['scheme'];
    final scheme = schemeJson as String;
    final uniqueJson = json['unique'];
    final unique = UniquenessLevel.fromJson(uniqueJson as String);
    return Moniker(
      identifier: identifier,
      kind: kind,
      scheme: scheme,
      unique: unique,
    );
  }

  /// The identifier of the moniker. The value is opaque in LSIF however schema
  /// owners are allowed to define the structure if they want.
  final String identifier;

  /// The moniker kind if known.
  final MonikerKind? kind;

  /// The scheme of the moniker. For example tsc or .Net
  final String scheme;

  /// The scope in which the moniker is unique
  final UniquenessLevel unique;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['identifier'] = identifier;
    if (kind != null) {
      result['kind'] = kind?.toJson();
    }
    result['scheme'] = scheme;
    result['unique'] = unique.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseString(obj, reporter, 'identifier',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseMonikerKind(obj, reporter, 'kind',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'scheme',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseUniquenessLevel(obj, reporter, 'unique',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type Moniker');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is Moniker &&
        other.runtimeType == Moniker &&
        identifier == other.identifier &&
        kind == other.kind &&
        scheme == other.scheme &&
        unique == other.unique;
  }

  @override
  int get hashCode => Object.hash(
        identifier,
        kind,
        scheme,
        unique,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Client capabilities specific to the moniker request.
///
/// @since 3.16.0
class MonikerClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    MonikerClientCapabilities.canParse,
    MonikerClientCapabilities.fromJson,
  );

  MonikerClientCapabilities({
    this.dynamicRegistration,
  });
  static MonikerClientCapabilities fromJson(Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    return MonikerClientCapabilities(
      dynamicRegistration: dynamicRegistration,
    );
  }

  /// Whether moniker supports dynamic registration. If this is set to `true`
  /// the client supports the new `MonikerRegistrationOptions` return value for
  /// the corresponding server capability as well.
  final bool? dynamicRegistration;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseBool(obj, reporter, 'dynamicRegistration',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type MonikerClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is MonikerClientCapabilities &&
        other.runtimeType == MonikerClientCapabilities &&
        dynamicRegistration == other.dynamicRegistration;
  }

  @override
  int get hashCode => dynamicRegistration.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The moniker kind.
///
/// @since 3.16.0
class MonikerKind implements ToJsonable {
  const MonikerKind(this._value);
  const MonikerKind.fromJson(this._value);

  final String _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is String;

  /// The moniker represents a symbol that is exported from a project
  static const export = MonikerKind('export');

  /// The moniker represent a symbol that is imported into a project
  static const import = MonikerKind('import');

  /// The moniker represents a symbol that is local to a project (e.g. a local
  /// variable of a function, a class not visible outside the project, ...)
  static const local = MonikerKind('local');

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is MonikerKind && other._value == _value;
}

class MonikerOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    MonikerOptions.canParse,
    MonikerOptions.fromJson,
  );

  MonikerOptions({
    this.workDoneProgress,
  });
  static MonikerOptions fromJson(Map<String, Object?> json) {
    if (MonikerRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return MonikerRegistrationOptions.fromJson(json);
    }
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return MonikerOptions(
      workDoneProgress: workDoneProgress,
    );
  }

  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseBool(obj, reporter, 'workDoneProgress',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type MonikerOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is MonikerOptions &&
        other.runtimeType == MonikerOptions &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => workDoneProgress.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class MonikerParams
    implements
        PartialResultParams,
        TextDocumentPositionParams,
        WorkDoneProgressParams,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    MonikerParams.canParse,
    MonikerParams.fromJson,
  );

  MonikerParams({
    this.partialResultToken,
    required this.position,
    required this.textDocument,
    this.workDoneToken,
  });
  static MonikerParams fromJson(Map<String, Object?> json) {
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : _eitherIntString(partialResultTokenJson);
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken =
        workDoneTokenJson == null ? null : _eitherIntString(workDoneTokenJson);
    return MonikerParams(
      partialResultToken: partialResultToken,
      position: position,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final ProgressToken? partialResultToken;

  /// The position inside the text document.
  @override
  final Position position;

  /// The text document.
  @override
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final ProgressToken? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    result['position'] = position.toJson();
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseIntString(obj, reporter, 'partialResultToken',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParsePosition(obj, reporter, 'position',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseIntString(obj, reporter, 'workDoneToken',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type MonikerParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is MonikerParams &&
        other.runtimeType == MonikerParams &&
        partialResultToken == other.partialResultToken &&
        position == other.position &&
        textDocument == other.textDocument &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        partialResultToken,
        position,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class MonikerRegistrationOptions
    implements MonikerOptions, TextDocumentRegistrationOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    MonikerRegistrationOptions.canParse,
    MonikerRegistrationOptions.fromJson,
  );

  MonikerRegistrationOptions({
    this.documentSelector,
    this.workDoneProgress,
  });
  static MonikerRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return MonikerRegistrationOptions(
      documentSelector: documentSelector,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListTextDocumentFilterWithScheme(
          obj, reporter, 'documentSelector',
          allowsUndefined: false, allowsNull: true)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'workDoneProgress',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type MonikerRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is MonikerRegistrationOptions &&
        other.runtimeType == MonikerRegistrationOptions &&
        listEqual(
            documentSelector,
            other.documentSelector,
            (TextDocumentFilterWithScheme a, TextDocumentFilterWithScheme b) =>
                a == b) &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A notebook cell.
///
/// A cell's document URI must be unique across ALL notebook cells and can
/// therefore be used to uniquely identify a notebook cell or the cell's text
/// document.
///
/// @since 3.17.0
class NotebookCell implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookCell.canParse,
    NotebookCell.fromJson,
  );

  NotebookCell({
    required this.document,
    this.executionSummary,
    required this.kind,
    this.metadata,
  });
  static NotebookCell fromJson(Map<String, Object?> json) {
    final documentJson = json['document'];
    final document = documentJson as String;
    final executionSummaryJson = json['executionSummary'];
    final executionSummary = executionSummaryJson != null
        ? ExecutionSummary.fromJson(
            executionSummaryJson as Map<String, Object?>)
        : null;
    final kindJson = json['kind'];
    final kind = NotebookCellKind.fromJson(kindJson as int);
    final metadataJson = json['metadata'];
    final metadata = metadataJson;
    return NotebookCell(
      document: document,
      executionSummary: executionSummary,
      kind: kind,
      metadata: metadata,
    );
  }

  /// The URI of the cell's text document content.
  final DocumentUri document;

  /// Additional execution summary information if supported by the client.
  final ExecutionSummary? executionSummary;

  /// The cell's kind
  final NotebookCellKind kind;

  /// Additional metadata stored with the cell.
  ///
  /// Note: should always be an object literal (e.g. LSPObject)
  final LSPObject? metadata;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['document'] = document;
    if (executionSummary != null) {
      result['executionSummary'] = executionSummary?.toJson();
    }
    result['kind'] = kind.toJson();
    if (metadata != null) {
      result['metadata'] = metadata;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseString(obj, reporter, 'document',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseExecutionSummary(obj, reporter, 'executionSummary',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseNotebookCellKind(obj, reporter, 'kind',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseObject(obj, reporter, 'metadata',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type NotebookCell');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is NotebookCell &&
        other.runtimeType == NotebookCell &&
        document == other.document &&
        executionSummary == other.executionSummary &&
        kind == other.kind &&
        metadata == other.metadata;
  }

  @override
  int get hashCode => Object.hash(
        document,
        executionSummary,
        kind,
        metadata,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A change describing how to move a `NotebookCell` array from state S to S'.
///
/// @since 3.17.0
class NotebookCellArrayChange implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookCellArrayChange.canParse,
    NotebookCellArrayChange.fromJson,
  );

  NotebookCellArrayChange({
    this.cells,
    required this.deleteCount,
    required this.start,
  });
  static NotebookCellArrayChange fromJson(Map<String, Object?> json) {
    final cellsJson = json['cells'];
    final cells = (cellsJson as List<Object?>?)
        ?.map((item) => NotebookCell.fromJson(item as Map<String, Object?>))
        .toList();
    final deleteCountJson = json['deleteCount'];
    final deleteCount = deleteCountJson as int;
    final startJson = json['start'];
    final start = startJson as int;
    return NotebookCellArrayChange(
      cells: cells,
      deleteCount: deleteCount,
      start: start,
    );
  }

  /// The new cells, if any
  final List<NotebookCell>? cells;

  /// The deleted cells
  final int deleteCount;

  /// The start oftest of the cell that changed.
  final int start;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (cells != null) {
      result['cells'] = cells?.map((item) => item.toJson()).toList();
    }
    result['deleteCount'] = deleteCount;
    result['start'] = start;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListNotebookCell(obj, reporter, 'cells',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseInt(obj, reporter, 'deleteCount',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseInt(obj, reporter, 'start',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type NotebookCellArrayChange');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is NotebookCellArrayChange &&
        other.runtimeType == NotebookCellArrayChange &&
        listEqual(
            cells, other.cells, (NotebookCell a, NotebookCell b) => a == b) &&
        deleteCount == other.deleteCount &&
        start == other.start;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(cells),
        deleteCount,
        start,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A notebook cell kind.
///
/// @since 3.17.0
class NotebookCellKind implements ToJsonable {
  const NotebookCellKind(this._value);
  const NotebookCellKind.fromJson(this._value);

  final int _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is int;

  /// A code-cell is source code.
  static const Code = NotebookCellKind(2);

  /// A markup-cell is formatted source that is used for display.
  static const Markup = NotebookCellKind(1);

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is NotebookCellKind && other._value == _value;
}

/// A notebook cell text document filter denotes a cell text document by
/// different properties.
///
/// @since 3.17.0
class NotebookCellTextDocumentFilter implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookCellTextDocumentFilter.canParse,
    NotebookCellTextDocumentFilter.fromJson,
  );

  NotebookCellTextDocumentFilter({
    this.language,
    required this.notebook,
  });
  static NotebookCellTextDocumentFilter fromJson(Map<String, Object?> json) {
    final languageJson = json['language'];
    final language = languageJson as String?;
    final notebookJson = json['notebook'];
    final notebook =
        _eitherNotebookDocumentFilter1NotebookDocumentFilter2NotebookDocumentFilter3String(
            notebookJson);
    return NotebookCellTextDocumentFilter(
      language: language,
      notebook: notebook,
    );
  }

  /// A language id like `python`.
  ///
  /// Will be matched against the language id of the notebook cell document. '*'
  /// matches every language.
  final String? language;

  /// A filter that matches against the notebook containing the notebook cell.
  /// If a string value is provided it matches against the notebook type. '*'
  /// matches every notebook.
  final Either2<NotebookDocumentFilter, String> notebook;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (language != null) {
      result['language'] = language;
    }
    result['notebook'] = notebook;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseString(obj, reporter, 'language',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseNotebookDocumentFilter1NotebookDocumentFilter2NotebookDocumentFilter3String(
          obj, reporter, 'notebook',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type NotebookCellTextDocumentFilter');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is NotebookCellTextDocumentFilter &&
        other.runtimeType == NotebookCellTextDocumentFilter &&
        language == other.language &&
        notebook == other.notebook;
  }

  @override
  int get hashCode => Object.hash(
        language,
        notebook,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A notebook document.
///
/// @since 3.17.0
class NotebookDocument implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookDocument.canParse,
    NotebookDocument.fromJson,
  );

  NotebookDocument({
    required this.cells,
    this.metadata,
    required this.notebookType,
    required this.uri,
    required this.version,
  });
  static NotebookDocument fromJson(Map<String, Object?> json) {
    final cellsJson = json['cells'];
    final cells = (cellsJson as List<Object?>)
        .map((item) => NotebookCell.fromJson(item as Map<String, Object?>))
        .toList();
    final metadataJson = json['metadata'];
    final metadata = metadataJson;
    final notebookTypeJson = json['notebookType'];
    final notebookType = notebookTypeJson as String;
    final uriJson = json['uri'];
    final uri = uriJson as String;
    final versionJson = json['version'];
    final version = versionJson as int;
    return NotebookDocument(
      cells: cells,
      metadata: metadata,
      notebookType: notebookType,
      uri: uri,
      version: version,
    );
  }

  /// The cells of a notebook.
  final List<NotebookCell> cells;

  /// Additional metadata stored with the notebook document.
  ///
  /// Note: should always be an object literal (e.g. LSPObject)
  final LSPObject? metadata;

  /// The type of the notebook.
  final String notebookType;

  /// The notebook document's uri.
  final LspUri uri;

  /// The version number of this document (it will increase after each change,
  /// including undo/redo).
  final int version;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['cells'] = cells.map((item) => item.toJson()).toList();
    if (metadata != null) {
      result['metadata'] = metadata;
    }
    result['notebookType'] = notebookType;
    result['uri'] = uri;
    result['version'] = version;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListNotebookCell(obj, reporter, 'cells',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseObject(obj, reporter, 'metadata',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'notebookType',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'uri',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseInt(obj, reporter, 'version',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type NotebookDocument');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is NotebookDocument &&
        other.runtimeType == NotebookDocument &&
        listEqual(
            cells, other.cells, (NotebookCell a, NotebookCell b) => a == b) &&
        metadata == other.metadata &&
        notebookType == other.notebookType &&
        uri == other.uri &&
        version == other.version;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(cells),
        metadata,
        notebookType,
        uri,
        version,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A change event for a notebook document.
///
/// @since 3.17.0
class NotebookDocumentChangeEvent implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookDocumentChangeEvent.canParse,
    NotebookDocumentChangeEvent.fromJson,
  );

  NotebookDocumentChangeEvent({
    this.cells,
    this.metadata,
  });
  static NotebookDocumentChangeEvent fromJson(Map<String, Object?> json) {
    final cellsJson = json['cells'];
    final cells = cellsJson != null
        ? NotebookDocumentChangeEventCells.fromJson(
            cellsJson as Map<String, Object?>)
        : null;
    final metadataJson = json['metadata'];
    final metadata = metadataJson;
    return NotebookDocumentChangeEvent(
      cells: cells,
      metadata: metadata,
    );
  }

  /// Changes to cells
  final NotebookDocumentChangeEventCells? cells;

  /// The changed meta data if any.
  ///
  /// Note: should always be an object literal (e.g. LSPObject)
  final LSPObject? metadata;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (cells != null) {
      result['cells'] = cells?.toJson();
    }
    if (metadata != null) {
      result['metadata'] = metadata;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseNotebookDocumentChangeEventCells(obj, reporter, 'cells',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseObject(obj, reporter, 'metadata',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type NotebookDocumentChangeEvent');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is NotebookDocumentChangeEvent &&
        other.runtimeType == NotebookDocumentChangeEvent &&
        cells == other.cells &&
        metadata == other.metadata;
  }

  @override
  int get hashCode => Object.hash(
        cells,
        metadata,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class NotebookDocumentChangeEventCells implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookDocumentChangeEventCells.canParse,
    NotebookDocumentChangeEventCells.fromJson,
  );

  NotebookDocumentChangeEventCells({
    this.data,
    this.structure,
    this.textContent,
  });
  static NotebookDocumentChangeEventCells fromJson(Map<String, Object?> json) {
    final dataJson = json['data'];
    final data = (dataJson as List<Object?>?)
        ?.map((item) => NotebookCell.fromJson(item as Map<String, Object?>))
        .toList();
    final structureJson = json['structure'];
    final structure = structureJson != null
        ? NotebookDocumentChangeEventCellsStructure.fromJson(
            structureJson as Map<String, Object?>)
        : null;
    final textContentJson = json['textContent'];
    final textContent = (textContentJson as List<Object?>?)
        ?.map((item) => NotebookDocumentChangeEventCellsTextContent.fromJson(
            item as Map<String, Object?>))
        .toList();
    return NotebookDocumentChangeEventCells(
      data: data,
      structure: structure,
      textContent: textContent,
    );
  }

  /// Changes to notebook cells properties like its kind, execution summary or
  /// metadata.
  final List<NotebookCell>? data;

  /// Changes to the cell structure to add or remove cells.
  final NotebookDocumentChangeEventCellsStructure? structure;

  /// Changes to the text content of notebook cells.
  final List<NotebookDocumentChangeEventCellsTextContent>? textContent;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (data != null) {
      result['data'] = data?.map((item) => item.toJson()).toList();
    }
    if (structure != null) {
      result['structure'] = structure?.toJson();
    }
    if (textContent != null) {
      result['textContent'] =
          textContent?.map((item) => item.toJson()).toList();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListNotebookCell(obj, reporter, 'data',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseNotebookDocumentChangeEventCellsStructure(
          obj, reporter, 'structure',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseListNotebookDocumentChangeEventCellsTextContent(
          obj, reporter, 'textContent',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type NotebookDocumentChangeEventCells');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is NotebookDocumentChangeEventCells &&
        other.runtimeType == NotebookDocumentChangeEventCells &&
        listEqual(
            data, other.data, (NotebookCell a, NotebookCell b) => a == b) &&
        structure == other.structure &&
        listEqual(
            textContent,
            other.textContent,
            (NotebookDocumentChangeEventCellsTextContent a,
                    NotebookDocumentChangeEventCellsTextContent b) =>
                a == b);
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(data),
        structure,
        lspHashCode(textContent),
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class NotebookDocumentChangeEventCellsStructure implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookDocumentChangeEventCellsStructure.canParse,
    NotebookDocumentChangeEventCellsStructure.fromJson,
  );

  NotebookDocumentChangeEventCellsStructure({
    required this.array,
    this.didClose,
    this.didOpen,
  });
  static NotebookDocumentChangeEventCellsStructure fromJson(
      Map<String, Object?> json) {
    final arrayJson = json['array'];
    final array =
        NotebookCellArrayChange.fromJson(arrayJson as Map<String, Object?>);
    final didCloseJson = json['didClose'];
    final didClose = (didCloseJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentIdentifier.fromJson(item as Map<String, Object?>))
        .toList();
    final didOpenJson = json['didOpen'];
    final didOpen = (didOpenJson as List<Object?>?)
        ?.map((item) => TextDocumentItem.fromJson(item as Map<String, Object?>))
        .toList();
    return NotebookDocumentChangeEventCellsStructure(
      array: array,
      didClose: didClose,
      didOpen: didOpen,
    );
  }

  /// The change to the cell array.
  final NotebookCellArrayChange array;

  /// Additional closed cell text documents.
  final List<TextDocumentIdentifier>? didClose;

  /// Additional opened cell text documents.
  final List<TextDocumentItem>? didOpen;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['array'] = array.toJson();
    if (didClose != null) {
      result['didClose'] = didClose?.map((item) => item.toJson()).toList();
    }
    if (didOpen != null) {
      result['didOpen'] = didOpen?.map((item) => item.toJson()).toList();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseNotebookCellArrayChange(obj, reporter, 'array',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseListTextDocumentIdentifier(obj, reporter, 'didClose',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseListTextDocumentItem(obj, reporter, 'didOpen',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError(
          'must be of type NotebookDocumentChangeEventCellsStructure');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is NotebookDocumentChangeEventCellsStructure &&
        other.runtimeType == NotebookDocumentChangeEventCellsStructure &&
        array == other.array &&
        listEqual(didClose, other.didClose,
            (TextDocumentIdentifier a, TextDocumentIdentifier b) => a == b) &&
        listEqual(didOpen, other.didOpen,
            (TextDocumentItem a, TextDocumentItem b) => a == b);
  }

  @override
  int get hashCode => Object.hash(
        array,
        lspHashCode(didClose),
        lspHashCode(didOpen),
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class NotebookDocumentChangeEventCellsTextContent implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookDocumentChangeEventCellsTextContent.canParse,
    NotebookDocumentChangeEventCellsTextContent.fromJson,
  );

  NotebookDocumentChangeEventCellsTextContent({
    required this.changes,
    required this.document,
  });
  static NotebookDocumentChangeEventCellsTextContent fromJson(
      Map<String, Object?> json) {
    final changesJson = json['changes'];
    final changes = (changesJson as List<Object?>)
        .map((item) =>
            _eitherTextDocumentContentChangeEvent1TextDocumentContentChangeEvent2(
                item))
        .toList();
    final documentJson = json['document'];
    final document = VersionedTextDocumentIdentifier.fromJson(
        documentJson as Map<String, Object?>);
    return NotebookDocumentChangeEventCellsTextContent(
      changes: changes,
      document: document,
    );
  }

  final List<TextDocumentContentChangeEvent> changes;
  final VersionedTextDocumentIdentifier document;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['changes'] = changes;
    result['document'] = document.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListTextDocumentContentChangeEvent1TextDocumentContentChangeEvent2(
          obj, reporter, 'changes',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseVersionedTextDocumentIdentifier(obj, reporter, 'document',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError(
          'must be of type NotebookDocumentChangeEventCellsTextContent');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is NotebookDocumentChangeEventCellsTextContent &&
        other.runtimeType == NotebookDocumentChangeEventCellsTextContent &&
        listEqual(
            changes,
            other.changes,
            (TextDocumentContentChangeEvent a,
                    TextDocumentContentChangeEvent b) =>
                a == b) &&
        document == other.document;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(changes),
        document,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Capabilities specific to the notebook document support.
///
/// @since 3.17.0
class NotebookDocumentClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookDocumentClientCapabilities.canParse,
    NotebookDocumentClientCapabilities.fromJson,
  );

  NotebookDocumentClientCapabilities({
    required this.synchronization,
  });
  static NotebookDocumentClientCapabilities fromJson(
      Map<String, Object?> json) {
    final synchronizationJson = json['synchronization'];
    final synchronization = NotebookDocumentSyncClientCapabilities.fromJson(
        synchronizationJson as Map<String, Object?>);
    return NotebookDocumentClientCapabilities(
      synchronization: synchronization,
    );
  }

  /// Capabilities specific to notebook document synchronization
  ///
  /// @since 3.17.0
  final NotebookDocumentSyncClientCapabilities synchronization;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['synchronization'] = synchronization.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseNotebookDocumentSyncClientCapabilities(
          obj, reporter, 'synchronization',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter
          .reportError('must be of type NotebookDocumentClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is NotebookDocumentClientCapabilities &&
        other.runtimeType == NotebookDocumentClientCapabilities &&
        synchronization == other.synchronization;
  }

  @override
  int get hashCode => synchronization.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class NotebookDocumentFilter1 implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookDocumentFilter1.canParse,
    NotebookDocumentFilter1.fromJson,
  );

  NotebookDocumentFilter1({
    required this.notebookType,
    this.pattern,
    this.scheme,
  });
  static NotebookDocumentFilter1 fromJson(Map<String, Object?> json) {
    final notebookTypeJson = json['notebookType'];
    final notebookType = notebookTypeJson as String;
    final patternJson = json['pattern'];
    final pattern = patternJson as String?;
    final schemeJson = json['scheme'];
    final scheme = schemeJson as String?;
    return NotebookDocumentFilter1(
      notebookType: notebookType,
      pattern: pattern,
      scheme: scheme,
    );
  }

  /// The type of the enclosing notebook. */
  final String notebookType;

  /// A glob pattern. */
  final String? pattern;

  /// A Uri scheme, like `file` or `untitled`. */
  final String? scheme;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['notebookType'] = notebookType;
    if (pattern != null) {
      result['pattern'] = pattern;
    }
    if (scheme != null) {
      result['scheme'] = scheme;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseString(obj, reporter, 'notebookType',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'pattern',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseString(obj, reporter, 'scheme',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type NotebookDocumentFilter1');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is NotebookDocumentFilter1 &&
        other.runtimeType == NotebookDocumentFilter1 &&
        notebookType == other.notebookType &&
        pattern == other.pattern &&
        scheme == other.scheme;
  }

  @override
  int get hashCode => Object.hash(
        notebookType,
        pattern,
        scheme,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class NotebookDocumentFilter2 implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookDocumentFilter2.canParse,
    NotebookDocumentFilter2.fromJson,
  );

  NotebookDocumentFilter2({
    this.notebookType,
    this.pattern,
    required this.scheme,
  });
  static NotebookDocumentFilter2 fromJson(Map<String, Object?> json) {
    final notebookTypeJson = json['notebookType'];
    final notebookType = notebookTypeJson as String?;
    final patternJson = json['pattern'];
    final pattern = patternJson as String?;
    final schemeJson = json['scheme'];
    final scheme = schemeJson as String;
    return NotebookDocumentFilter2(
      notebookType: notebookType,
      pattern: pattern,
      scheme: scheme,
    );
  }

  /// The type of the enclosing notebook. */
  final String? notebookType;

  /// A glob pattern. */
  final String? pattern;

  /// A Uri scheme, like `file` or `untitled`.*/
  final String scheme;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (notebookType != null) {
      result['notebookType'] = notebookType;
    }
    if (pattern != null) {
      result['pattern'] = pattern;
    }
    result['scheme'] = scheme;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseString(obj, reporter, 'notebookType',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'pattern',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseString(obj, reporter, 'scheme',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type NotebookDocumentFilter2');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is NotebookDocumentFilter2 &&
        other.runtimeType == NotebookDocumentFilter2 &&
        notebookType == other.notebookType &&
        pattern == other.pattern &&
        scheme == other.scheme;
  }

  @override
  int get hashCode => Object.hash(
        notebookType,
        pattern,
        scheme,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class NotebookDocumentFilter3 implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookDocumentFilter3.canParse,
    NotebookDocumentFilter3.fromJson,
  );

  NotebookDocumentFilter3({
    this.notebookType,
    required this.pattern,
    this.scheme,
  });
  static NotebookDocumentFilter3 fromJson(Map<String, Object?> json) {
    final notebookTypeJson = json['notebookType'];
    final notebookType = notebookTypeJson as String?;
    final patternJson = json['pattern'];
    final pattern = patternJson as String;
    final schemeJson = json['scheme'];
    final scheme = schemeJson as String?;
    return NotebookDocumentFilter3(
      notebookType: notebookType,
      pattern: pattern,
      scheme: scheme,
    );
  }

  /// The type of the enclosing notebook. */
  final String? notebookType;

  /// A glob pattern. */
  final String pattern;

  /// A Uri scheme, like `file` or `untitled`. */
  final String? scheme;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (notebookType != null) {
      result['notebookType'] = notebookType;
    }
    result['pattern'] = pattern;
    if (scheme != null) {
      result['scheme'] = scheme;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseString(obj, reporter, 'notebookType',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'pattern',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseString(obj, reporter, 'scheme',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type NotebookDocumentFilter3');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is NotebookDocumentFilter3 &&
        other.runtimeType == NotebookDocumentFilter3 &&
        notebookType == other.notebookType &&
        pattern == other.pattern &&
        scheme == other.scheme;
  }

  @override
  int get hashCode => Object.hash(
        notebookType,
        pattern,
        scheme,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A literal to identify a notebook document in the client.
///
/// @since 3.17.0
class NotebookDocumentIdentifier implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookDocumentIdentifier.canParse,
    NotebookDocumentIdentifier.fromJson,
  );

  NotebookDocumentIdentifier({
    required this.uri,
  });
  static NotebookDocumentIdentifier fromJson(Map<String, Object?> json) {
    final uriJson = json['uri'];
    final uri = uriJson as String;
    return NotebookDocumentIdentifier(
      uri: uri,
    );
  }

  /// The notebook document's uri.
  final LspUri uri;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['uri'] = uri;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseString(obj, reporter, 'uri',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type NotebookDocumentIdentifier');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is NotebookDocumentIdentifier &&
        other.runtimeType == NotebookDocumentIdentifier &&
        uri == other.uri;
  }

  @override
  int get hashCode => uri.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Notebook specific client capabilities.
///
/// @since 3.17.0
class NotebookDocumentSyncClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookDocumentSyncClientCapabilities.canParse,
    NotebookDocumentSyncClientCapabilities.fromJson,
  );

  NotebookDocumentSyncClientCapabilities({
    this.dynamicRegistration,
    this.executionSummarySupport,
  });
  static NotebookDocumentSyncClientCapabilities fromJson(
      Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    final executionSummarySupportJson = json['executionSummarySupport'];
    final executionSummarySupport = executionSummarySupportJson as bool?;
    return NotebookDocumentSyncClientCapabilities(
      dynamicRegistration: dynamicRegistration,
      executionSummarySupport: executionSummarySupport,
    );
  }

  /// Whether implementation supports dynamic registration. If this is set to
  /// `true` the client supports the new `(TextDocumentRegistrationOptions &
  /// StaticRegistrationOptions)` return value for the corresponding server
  /// capability as well.
  final bool? dynamicRegistration;

  /// The client supports sending execution summary data per cell.
  final bool? executionSummarySupport;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    if (executionSummarySupport != null) {
      result['executionSummarySupport'] = executionSummarySupport;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseBool(obj, reporter, 'dynamicRegistration',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'executionSummarySupport',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError(
          'must be of type NotebookDocumentSyncClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is NotebookDocumentSyncClientCapabilities &&
        other.runtimeType == NotebookDocumentSyncClientCapabilities &&
        dynamicRegistration == other.dynamicRegistration &&
        executionSummarySupport == other.executionSummarySupport;
  }

  @override
  int get hashCode => Object.hash(
        dynamicRegistration,
        executionSummarySupport,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Options specific to a notebook plus its cells to be synced to the server.
///
/// If a selector provides a notebook document filter but no cell selector all
/// cells of a matching notebook document will be synced.
///
/// If a selector provides no notebook document filter but only a cell selector
/// all notebook document that contain at least one matching cell will be
/// synced.
///
/// @since 3.17.0
class NotebookDocumentSyncOptions implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookDocumentSyncOptions.canParse,
    NotebookDocumentSyncOptions.fromJson,
  );

  NotebookDocumentSyncOptions({
    required this.notebookSelector,
    this.save,
  });
  static NotebookDocumentSyncOptions fromJson(Map<String, Object?> json) {
    if (NotebookDocumentSyncRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return NotebookDocumentSyncRegistrationOptions.fromJson(json);
    }
    final notebookSelectorJson = json['notebookSelector'];
    final notebookSelector = (notebookSelectorJson as List<Object?>)
        .map((item) =>
            _eitherNotebookDocumentSyncOptionsNotebookSelectorNotebookDocumentSyncOptionsNotebookSelector2(
                item))
        .toList();
    final saveJson = json['save'];
    final save = saveJson as bool?;
    return NotebookDocumentSyncOptions(
      notebookSelector: notebookSelector,
      save: save,
    );
  }

  /// The notebooks to be synced
  final List<
      Either2<NotebookDocumentSyncOptionsNotebookSelector,
          NotebookDocumentSyncOptionsNotebookSelector2>> notebookSelector;

  /// Whether save notification should be forwarded to the server. Will only be
  /// honored if mode === `notebook`.
  final bool? save;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['notebookSelector'] = notebookSelector;
    if (save != null) {
      result['save'] = save;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListNotebookDocumentSyncOptionsNotebookSelectorNotebookDocumentSyncOptionsNotebookSelector2(
          obj, reporter, 'notebookSelector',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'save',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type NotebookDocumentSyncOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is NotebookDocumentSyncOptions &&
        other.runtimeType == NotebookDocumentSyncOptions &&
        listEqual(
            notebookSelector,
            other.notebookSelector,
            (Either2<NotebookDocumentSyncOptionsNotebookSelector,
                            NotebookDocumentSyncOptionsNotebookSelector2>
                        a,
                    Either2<NotebookDocumentSyncOptionsNotebookSelector,
                            NotebookDocumentSyncOptionsNotebookSelector2>
                        b) =>
                a == b) &&
        save == other.save;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(notebookSelector),
        save,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class NotebookDocumentSyncOptionsNotebookSelector implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookDocumentSyncOptionsNotebookSelector.canParse,
    NotebookDocumentSyncOptionsNotebookSelector.fromJson,
  );

  NotebookDocumentSyncOptionsNotebookSelector({
    this.cells,
    required this.notebook,
  });
  static NotebookDocumentSyncOptionsNotebookSelector fromJson(
      Map<String, Object?> json) {
    final cellsJson = json['cells'];
    final cells = (cellsJson as List<Object?>?)
        ?.map((item) =>
            NotebookDocumentSyncOptionsNotebookSelectorCells.fromJson(
                item as Map<String, Object?>))
        .toList();
    final notebookJson = json['notebook'];
    final notebook =
        _eitherNotebookDocumentFilter1NotebookDocumentFilter2NotebookDocumentFilter3String(
            notebookJson);
    return NotebookDocumentSyncOptionsNotebookSelector(
      cells: cells,
      notebook: notebook,
    );
  }

  /// The cells of the matching notebook to be synced.
  final List<NotebookDocumentSyncOptionsNotebookSelectorCells>? cells;

  /// The notebook to be synced If a string value is provided it matches against
  /// the notebook type. '*' matches every notebook.
  final Either2<NotebookDocumentFilter, String> notebook;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (cells != null) {
      result['cells'] = cells?.map((item) => item.toJson()).toList();
    }
    result['notebook'] = notebook;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListNotebookDocumentSyncOptionsNotebookSelectorCells(
          obj, reporter, 'cells',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseNotebookDocumentFilter1NotebookDocumentFilter2NotebookDocumentFilter3String(
          obj, reporter, 'notebook',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError(
          'must be of type NotebookDocumentSyncOptionsNotebookSelector');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is NotebookDocumentSyncOptionsNotebookSelector &&
        other.runtimeType == NotebookDocumentSyncOptionsNotebookSelector &&
        listEqual(
            cells,
            other.cells,
            (NotebookDocumentSyncOptionsNotebookSelectorCells a,
                    NotebookDocumentSyncOptionsNotebookSelectorCells b) =>
                a == b) &&
        notebook == other.notebook;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(cells),
        notebook,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class NotebookDocumentSyncOptionsNotebookSelector2 implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookDocumentSyncOptionsNotebookSelector2.canParse,
    NotebookDocumentSyncOptionsNotebookSelector2.fromJson,
  );

  NotebookDocumentSyncOptionsNotebookSelector2({
    required this.cells,
    this.notebook,
  });
  static NotebookDocumentSyncOptionsNotebookSelector2 fromJson(
      Map<String, Object?> json) {
    final cellsJson = json['cells'];
    final cells = (cellsJson as List<Object?>)
        .map((item) =>
            NotebookDocumentSyncOptionsNotebookSelector2Cells.fromJson(
                item as Map<String, Object?>))
        .toList();
    final notebookJson = json['notebook'];
    final notebook = notebookJson == null
        ? null
        : _eitherNotebookDocumentFilter1NotebookDocumentFilter2NotebookDocumentFilter3String(
            notebookJson);
    return NotebookDocumentSyncOptionsNotebookSelector2(
      cells: cells,
      notebook: notebook,
    );
  }

  /// The cells of the matching notebook to be synced.
  final List<NotebookDocumentSyncOptionsNotebookSelector2Cells> cells;

  /// The notebook to be synced If a string value is provided it matches against
  /// the notebook type. '*' matches every notebook.
  final Either2<NotebookDocumentFilter, String>? notebook;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['cells'] = cells.map((item) => item.toJson()).toList();
    if (notebook != null) {
      result['notebook'] = notebook;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListNotebookDocumentSyncOptionsNotebookSelector2Cells(
          obj, reporter, 'cells',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseNotebookDocumentFilter1NotebookDocumentFilter2NotebookDocumentFilter3String(
          obj, reporter, 'notebook',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError(
          'must be of type NotebookDocumentSyncOptionsNotebookSelector2');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is NotebookDocumentSyncOptionsNotebookSelector2 &&
        other.runtimeType == NotebookDocumentSyncOptionsNotebookSelector2 &&
        listEqual(
            cells,
            other.cells,
            (NotebookDocumentSyncOptionsNotebookSelector2Cells a,
                    NotebookDocumentSyncOptionsNotebookSelector2Cells b) =>
                a == b) &&
        notebook == other.notebook;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(cells),
        notebook,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class NotebookDocumentSyncOptionsNotebookSelector2Cells implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookDocumentSyncOptionsNotebookSelector2Cells.canParse,
    NotebookDocumentSyncOptionsNotebookSelector2Cells.fromJson,
  );

  NotebookDocumentSyncOptionsNotebookSelector2Cells({
    required this.language,
  });
  static NotebookDocumentSyncOptionsNotebookSelector2Cells fromJson(
      Map<String, Object?> json) {
    final languageJson = json['language'];
    final language = languageJson as String;
    return NotebookDocumentSyncOptionsNotebookSelector2Cells(
      language: language,
    );
  }

  final String language;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['language'] = language;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseString(obj, reporter, 'language',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError(
          'must be of type NotebookDocumentSyncOptionsNotebookSelector2Cells');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is NotebookDocumentSyncOptionsNotebookSelector2Cells &&
        other.runtimeType ==
            NotebookDocumentSyncOptionsNotebookSelector2Cells &&
        language == other.language;
  }

  @override
  int get hashCode => language.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class NotebookDocumentSyncOptionsNotebookSelectorCells implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookDocumentSyncOptionsNotebookSelectorCells.canParse,
    NotebookDocumentSyncOptionsNotebookSelectorCells.fromJson,
  );

  NotebookDocumentSyncOptionsNotebookSelectorCells({
    required this.language,
  });
  static NotebookDocumentSyncOptionsNotebookSelectorCells fromJson(
      Map<String, Object?> json) {
    final languageJson = json['language'];
    final language = languageJson as String;
    return NotebookDocumentSyncOptionsNotebookSelectorCells(
      language: language,
    );
  }

  final String language;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['language'] = language;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseString(obj, reporter, 'language',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError(
          'must be of type NotebookDocumentSyncOptionsNotebookSelectorCells');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is NotebookDocumentSyncOptionsNotebookSelectorCells &&
        other.runtimeType == NotebookDocumentSyncOptionsNotebookSelectorCells &&
        language == other.language;
  }

  @override
  int get hashCode => language.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Registration options specific to a notebook.
///
/// @since 3.17.0
class NotebookDocumentSyncRegistrationOptions
    implements
        NotebookDocumentSyncOptions,
        StaticRegistrationOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    NotebookDocumentSyncRegistrationOptions.canParse,
    NotebookDocumentSyncRegistrationOptions.fromJson,
  );

  NotebookDocumentSyncRegistrationOptions({
    this.id,
    required this.notebookSelector,
    this.save,
  });
  static NotebookDocumentSyncRegistrationOptions fromJson(
      Map<String, Object?> json) {
    final idJson = json['id'];
    final id = idJson as String?;
    final notebookSelectorJson = json['notebookSelector'];
    final notebookSelector = (notebookSelectorJson as List<Object?>)
        .map((item) =>
            _eitherNotebookDocumentSyncOptionsNotebookSelectorNotebookDocumentSyncOptionsNotebookSelector2(
                item))
        .toList();
    final saveJson = json['save'];
    final save = saveJson as bool?;
    return NotebookDocumentSyncRegistrationOptions(
      id: id,
      notebookSelector: notebookSelector,
      save: save,
    );
  }

  /// The id used to register the request. The id can be used to deregister the
  /// request again. See also Registration#id.
  @override
  final String? id;

  /// The notebooks to be synced
  @override
  final List<
      Either2<NotebookDocumentSyncOptionsNotebookSelector,
          NotebookDocumentSyncOptionsNotebookSelector2>> notebookSelector;

  /// Whether save notification should be forwarded to the server. Will only be
  /// honored if mode === `notebook`.
  @override
  final bool? save;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (id != null) {
      result['id'] = id;
    }
    result['notebookSelector'] = notebookSelector;
    if (save != null) {
      result['save'] = save;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseString(obj, reporter, 'id',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseListNotebookDocumentSyncOptionsNotebookSelectorNotebookDocumentSyncOptionsNotebookSelector2(
          obj, reporter, 'notebookSelector',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'save',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError(
          'must be of type NotebookDocumentSyncRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is NotebookDocumentSyncRegistrationOptions &&
        other.runtimeType == NotebookDocumentSyncRegistrationOptions &&
        id == other.id &&
        listEqual(
            notebookSelector,
            other.notebookSelector,
            (Either2<NotebookDocumentSyncOptionsNotebookSelector,
                            NotebookDocumentSyncOptionsNotebookSelector2>
                        a,
                    Either2<NotebookDocumentSyncOptionsNotebookSelector,
                            NotebookDocumentSyncOptionsNotebookSelector2>
                        b) =>
                a == b) &&
        save == other.save;
  }

  @override
  int get hashCode => Object.hash(
        id,
        lspHashCode(notebookSelector),
        save,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A text document identifier to optionally denote a specific version of a text
/// document.
class OptionalVersionedTextDocumentIdentifier
    implements TextDocumentIdentifier, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    OptionalVersionedTextDocumentIdentifier.canParse,
    OptionalVersionedTextDocumentIdentifier.fromJson,
  );

  OptionalVersionedTextDocumentIdentifier({
    required this.uri,
    this.version,
  });
  static OptionalVersionedTextDocumentIdentifier fromJson(
      Map<String, Object?> json) {
    final uriJson = json['uri'];
    final uri = uriJson as String;
    final versionJson = json['version'];
    final version = versionJson as int?;
    return OptionalVersionedTextDocumentIdentifier(
      uri: uri,
      version: version,
    );
  }

  /// The text document's uri.
  @override
  final DocumentUri uri;

  /// The version number of this document. If a 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 unknown and the
  /// content on disk is the truth (as specified with document content
  /// ownership).
  final int? version;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['uri'] = uri;
    result['version'] = version;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseString(obj, reporter, 'uri',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseInt(obj, reporter, 'version',
          allowsUndefined: false, allowsNull: true);
    } else {
      reporter.reportError(
          'must be of type OptionalVersionedTextDocumentIdentifier');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is OptionalVersionedTextDocumentIdentifier &&
        other.runtimeType == OptionalVersionedTextDocumentIdentifier &&
        uri == other.uri &&
        version == other.version;
  }

  @override
  int get hashCode => Object.hash(
        uri,
        version,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Represents a parameter of a callable-signature. A parameter can have a label
/// and a doc-comment.
class ParameterInformation implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ParameterInformation.canParse,
    ParameterInformation.fromJson,
  );

  ParameterInformation({
    this.documentation,
    required this.label,
  });
  static ParameterInformation fromJson(Map<String, Object?> json) {
    final documentationJson = json['documentation'];
    final documentation = documentationJson == null
        ? null
        : _eitherMarkupContentString(documentationJson);
    final labelJson = json['label'];
    final label = labelJson as String;
    return ParameterInformation(
      documentation: documentation,
      label: label,
    );
  }

  /// The human-readable doc-comment of this parameter. Will be shown in the UI
  /// but can be omitted.
  final Either2<MarkupContent, String>? documentation;

  /// The label of this parameter information.
  ///
  /// Either a string or an inclusive start and exclusive end offsets within its
  /// containing signature label. (see SignatureInformation.label). The offsets
  /// are based on a UTF-16 string representation as `Position` and `Range`
  /// does.
  ///
  /// *Note*: a label of type string should be a substring of its containing
  /// signature label. Its intended use case is to highlight the parameter label
  /// part in the `SignatureInformation.label`.
  final String label;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (documentation != null) {
      result['documentation'] = documentation;
    }
    result['label'] = label;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseMarkupContentString(obj, reporter, 'documentation',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseString(obj, reporter, 'label',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type ParameterInformation');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ParameterInformation &&
        other.runtimeType == ParameterInformation &&
        documentation == other.documentation &&
        label == other.label;
  }

  @override
  int get hashCode => Object.hash(
        documentation,
        label,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class PartialResultParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    PartialResultParams.canParse,
    PartialResultParams.fromJson,
  );

  PartialResultParams({
    this.partialResultToken,
  });
  static PartialResultParams fromJson(Map<String, Object?> json) {
    if (CodeActionParams.canParse(json, nullLspJsonReporter)) {
      return CodeActionParams.fromJson(json);
    }
    if (ColorPresentationParams.canParse(json, nullLspJsonReporter)) {
      return ColorPresentationParams.fromJson(json);
    }
    if (SelectionRangeParams.canParse(json, nullLspJsonReporter)) {
      return SelectionRangeParams.fromJson(json);
    }
    if (SemanticTokensDeltaParams.canParse(json, nullLspJsonReporter)) {
      return SemanticTokensDeltaParams.fromJson(json);
    }
    if (SemanticTokensRangeParams.canParse(json, nullLspJsonReporter)) {
      return SemanticTokensRangeParams.fromJson(json);
    }
    if (DocumentDiagnosticParams.canParse(json, nullLspJsonReporter)) {
      return DocumentDiagnosticParams.fromJson(json);
    }
    if (WorkspaceDiagnosticParams.canParse(json, nullLspJsonReporter)) {
      return WorkspaceDiagnosticParams.fromJson(json);
    }
    if (CallHierarchyIncomingCallsParams.canParse(json, nullLspJsonReporter)) {
      return CallHierarchyIncomingCallsParams.fromJson(json);
    }
    if (CallHierarchyOutgoingCallsParams.canParse(json, nullLspJsonReporter)) {
      return CallHierarchyOutgoingCallsParams.fromJson(json);
    }
    if (CodeLensParams.canParse(json, nullLspJsonReporter)) {
      return CodeLensParams.fromJson(json);
    }
    if (DocumentColorParams.canParse(json, nullLspJsonReporter)) {
      return DocumentColorParams.fromJson(json);
    }
    if (DocumentLinkParams.canParse(json, nullLspJsonReporter)) {
      return DocumentLinkParams.fromJson(json);
    }
    if (DocumentSymbolParams.canParse(json, nullLspJsonReporter)) {
      return DocumentSymbolParams.fromJson(json);
    }
    if (FoldingRangeParams.canParse(json, nullLspJsonReporter)) {
      return FoldingRangeParams.fromJson(json);
    }
    if (ReferenceParams.canParse(json, nullLspJsonReporter)) {
      return ReferenceParams.fromJson(json);
    }
    if (SemanticTokensParams.canParse(json, nullLspJsonReporter)) {
      return SemanticTokensParams.fromJson(json);
    }
    if (TypeHierarchySubtypesParams.canParse(json, nullLspJsonReporter)) {
      return TypeHierarchySubtypesParams.fromJson(json);
    }
    if (TypeHierarchySupertypesParams.canParse(json, nullLspJsonReporter)) {
      return TypeHierarchySupertypesParams.fromJson(json);
    }
    if (WorkspaceSymbolParams.canParse(json, nullLspJsonReporter)) {
      return WorkspaceSymbolParams.fromJson(json);
    }
    if (CompletionParams.canParse(json, nullLspJsonReporter)) {
      return CompletionParams.fromJson(json);
    }
    if (DeclarationParams.canParse(json, nullLspJsonReporter)) {
      return DeclarationParams.fromJson(json);
    }
    if (DefinitionParams.canParse(json, nullLspJsonReporter)) {
      return DefinitionParams.fromJson(json);
    }
    if (DocumentHighlightParams.canParse(json, nullLspJsonReporter)) {
      return DocumentHighlightParams.fromJson(json);
    }
    if (ImplementationParams.canParse(json, nullLspJsonReporter)) {
      return ImplementationParams.fromJson(json);
    }
    if (MonikerParams.canParse(json, nullLspJsonReporter)) {
      return MonikerParams.fromJson(json);
    }
    if (TypeDefinitionParams.canParse(json, nullLspJsonReporter)) {
      return TypeDefinitionParams.fromJson(json);
    }
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : _eitherIntString(partialResultTokenJson);
    return PartialResultParams(
      partialResultToken: partialResultToken,
    );
  }

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  final ProgressToken? partialResultToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseIntString(obj, reporter, 'partialResultToken',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type PartialResultParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is PartialResultParams &&
        other.runtimeType == PartialResultParams &&
        partialResultToken == other.partialResultToken;
  }

  @override
  int get hashCode => partialResultToken.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class PlaceholderAndRange implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    PlaceholderAndRange.canParse,
    PlaceholderAndRange.fromJson,
  );

  PlaceholderAndRange({
    required this.placeholder,
    required this.range,
  });
  static PlaceholderAndRange fromJson(Map<String, Object?> json) {
    final placeholderJson = json['placeholder'];
    final placeholder = placeholderJson as String;
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    return PlaceholderAndRange(
      placeholder: placeholder,
      range: range,
    );
  }

  final String placeholder;
  final Range range;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['placeholder'] = placeholder;
    result['range'] = range.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseString(obj, reporter, 'placeholder',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseRange(obj, reporter, 'range',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type PlaceholderAndRange');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is PlaceholderAndRange &&
        other.runtimeType == PlaceholderAndRange &&
        placeholder == other.placeholder &&
        range == other.range;
  }

  @override
  int get hashCode => Object.hash(
        placeholder,
        range,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Position in a text document expressed as zero-based line and character
/// offset. Prior to 3.17 the offsets were always based on a UTF-16 string
/// representation. So a string of the form `a𐐀b` the character offset of the
/// character `a` is 0, the character offset of `𐐀` is 1 and the character
/// offset of b is 3 since `𐐀` is represented using two code units in UTF-16.
/// Since 3.17 clients and servers can agree on a different string encoding
/// representation (e.g. UTF-8). The client announces it's supported encoding
/// via the client capability `general.positionEncodings`. The value is an array
/// of position encodings the client supports, with decreasing preference (e.g.
/// the encoding at index `0` is the most preferred one). To stay backwards
/// compatible the only mandatory encoding is UTF-16 represented via the string
/// `utf-16`. The server can pick one of the encodings offered by the client and
/// signals that encoding back to the client via the initialize result's
/// property `capabilities.positionEncoding`. If the string value `utf-16` is
/// missing from the client's capability `general.positionEncodings` servers can
/// safely assume that the client supports UTF-16. If the server omits the
/// position encoding in its initialize result the encoding defaults to the
/// string value `utf-16`. Implementation considerations: since the conversion
/// from one encoding into another requires the content of the file / line the
/// conversion is best done where the file is read which is usually on the
/// server side.
///
/// Positions are line end character agnostic. So you can not specify a position
/// that denotes `\r|\n` or `\n|` where `|` represents the character offset.
///
/// @since 3.17.0 - support for negotiated position encoding.
class Position implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    Position.canParse,
    Position.fromJson,
  );

  Position({
    required this.character,
    required this.line,
  });
  static Position fromJson(Map<String, Object?> json) {
    final characterJson = json['character'];
    final character = characterJson as int;
    final lineJson = json['line'];
    final line = lineJson as int;
    return Position(
      character: character,
      line: line,
    );
  }

  /// Character offset on a line in a document (zero-based).
  ///
  /// The meaning of this offset is determined by the negotiated
  /// `PositionEncodingKind`.
  ///
  /// If the character value is greater than the line length it defaults back to
  /// the line length.
  final int character;

  /// Line position in a document (zero-based).
  ///
  /// If a line number is greater than the number of lines in a document, it
  /// defaults back to the number of lines in the document. If a line number is
  /// negative, it defaults to 0.
  final int line;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['character'] = character;
    result['line'] = line;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseInt(obj, reporter, 'character',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseInt(obj, reporter, 'line',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type Position');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is Position &&
        other.runtimeType == Position &&
        character == other.character &&
        line == other.line;
  }

  @override
  int get hashCode => Object.hash(
        character,
        line,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A set of predefined position encoding kinds.
///
/// @since 3.17.0
class PositionEncodingKind implements ToJsonable {
  const PositionEncodingKind(this._value);
  const PositionEncodingKind.fromJson(this._value);

  final String _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is String;

  /// Character offsets count UTF-16 code units.
  ///
  /// This is the default and must always be supported by servers
  static const UTF16 = PositionEncodingKind('utf-16');

  /// Character offsets count UTF-32 code units.
  ///
  /// Implementation note: these are the same as Unicode code points,
  /// so this `PositionEncodingKind` may also be used for an encoding-agnostic
  /// representation of character offsets.
  static const UTF32 = PositionEncodingKind('utf-32');

  /// Character offsets count UTF-8 code units.
  static const UTF8 = PositionEncodingKind('utf-8');

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is PositionEncodingKind && other._value == _value;
}

class PrepareRenameParams
    implements TextDocumentPositionParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    PrepareRenameParams.canParse,
    PrepareRenameParams.fromJson,
  );

  PrepareRenameParams({
    required this.position,
    required this.textDocument,
    this.workDoneToken,
  });
  static PrepareRenameParams fromJson(Map<String, Object?> json) {
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken =
        workDoneTokenJson == null ? null : _eitherIntString(workDoneTokenJson);
    return PrepareRenameParams(
      position: position,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// The position inside the text document.
  @override
  final Position position;

  /// The text document.
  @override
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final ProgressToken? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['position'] = position.toJson();
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParsePosition(obj, reporter, 'position',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseIntString(obj, reporter, 'workDoneToken',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type PrepareRenameParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is PrepareRenameParams &&
        other.runtimeType == PrepareRenameParams &&
        position == other.position &&
        textDocument == other.textDocument &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        position,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class PrepareRenameResult2 implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    PrepareRenameResult2.canParse,
    PrepareRenameResult2.fromJson,
  );

  PrepareRenameResult2({
    required this.defaultBehavior,
  });
  static PrepareRenameResult2 fromJson(Map<String, Object?> json) {
    final defaultBehaviorJson = json['defaultBehavior'];
    final defaultBehavior = defaultBehaviorJson as bool;
    return PrepareRenameResult2(
      defaultBehavior: defaultBehavior,
    );
  }

  final bool defaultBehavior;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['defaultBehavior'] = defaultBehavior;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseBool(obj, reporter, 'defaultBehavior',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type PrepareRenameResult2');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is PrepareRenameResult2 &&
        other.runtimeType == PrepareRenameResult2 &&
        defaultBehavior == other.defaultBehavior;
  }

  @override
  int get hashCode => defaultBehavior.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class PrepareSupportDefaultBehavior implements ToJsonable {
  const PrepareSupportDefaultBehavior(this._value);
  const PrepareSupportDefaultBehavior.fromJson(this._value);

  final int _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is int;

  /// The client's default behavior is to select the identifier according the to
  /// language's syntax rule.
  static const Identifier = PrepareSupportDefaultBehavior(1);

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is PrepareSupportDefaultBehavior && other._value == _value;
}

/// A previous result id in a workspace pull request.
///
/// @since 3.17.0
class PreviousResultId implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    PreviousResultId.canParse,
    PreviousResultId.fromJson,
  );

  PreviousResultId({
    required this.uri,
    required this.value,
  });
  static PreviousResultId fromJson(Map<String, Object?> json) {
    final uriJson = json['uri'];
    final uri = uriJson as String;
    final valueJson = json['value'];
    final value = valueJson as String;
    return PreviousResultId(
      uri: uri,
      value: value,
    );
  }

  /// The URI for which the client knowns a result id.
  final DocumentUri uri;

  /// The value of the previous result id.
  final String value;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['uri'] = uri;
    result['value'] = value;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseString(obj, reporter, 'uri',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseString(obj, reporter, 'value',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type PreviousResultId');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is PreviousResultId &&
        other.runtimeType == PreviousResultId &&
        uri == other.uri &&
        value == other.value;
  }

  @override
  int get hashCode => Object.hash(
        uri,
        value,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class ProgressParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ProgressParams.canParse,
    ProgressParams.fromJson,
  );

  ProgressParams({
    required this.token,
    this.value,
  });
  static ProgressParams fromJson(Map<String, Object?> json) {
    final tokenJson = json['token'];
    final token = _eitherIntString(tokenJson);
    final valueJson = json['value'];
    final value = valueJson;
    return ProgressParams(
      token: token,
      value: value,
    );
  }

  /// The progress token provided by the client or server.
  final ProgressToken token;

  /// The progress data.
  final LSPAny value;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['token'] = token;
    result['value'] = value;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseIntString(obj, reporter, 'token',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type ProgressParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ProgressParams &&
        other.runtimeType == ProgressParams &&
        token == other.token &&
        value == other.value;
  }

  @override
  int get hashCode => Object.hash(
        token,
        value,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The publish diagnostic client capabilities.
class PublishDiagnosticsClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    PublishDiagnosticsClientCapabilities.canParse,
    PublishDiagnosticsClientCapabilities.fromJson,
  );

  PublishDiagnosticsClientCapabilities({
    this.codeDescriptionSupport,
    this.dataSupport,
    this.relatedInformation,
    this.tagSupport,
    this.versionSupport,
  });
  static PublishDiagnosticsClientCapabilities fromJson(
      Map<String, Object?> json) {
    final codeDescriptionSupportJson = json['codeDescriptionSupport'];
    final codeDescriptionSupport = codeDescriptionSupportJson as bool?;
    final dataSupportJson = json['dataSupport'];
    final dataSupport = dataSupportJson as bool?;
    final relatedInformationJson = json['relatedInformation'];
    final relatedInformation = relatedInformationJson as bool?;
    final tagSupportJson = json['tagSupport'];
    final tagSupport = tagSupportJson != null
        ? PublishDiagnosticsClientCapabilitiesTagSupport.fromJson(
            tagSupportJson as Map<String, Object?>)
        : null;
    final versionSupportJson = json['versionSupport'];
    final versionSupport = versionSupportJson as bool?;
    return PublishDiagnosticsClientCapabilities(
      codeDescriptionSupport: codeDescriptionSupport,
      dataSupport: dataSupport,
      relatedInformation: relatedInformation,
      tagSupport: tagSupport,
      versionSupport: versionSupport,
    );
  }

  /// Client supports a codeDescription property
  ///
  /// @since 3.16.0
  final bool? codeDescriptionSupport;

  /// Whether code action supports the `data` property which is preserved
  /// between a `textDocument/publishDiagnostics` and `textDocument/codeAction`
  /// request.
  ///
  /// @since 3.16.0
  final bool? dataSupport;

  /// Whether the clients accepts diagnostics with related information.
  final bool? relatedInformation;

  /// Client supports the tag property to provide meta data about a diagnostic.
  /// Clients supporting tags have to handle unknown tags gracefully.
  ///
  /// @since 3.15.0
  final PublishDiagnosticsClientCapabilitiesTagSupport? tagSupport;

  /// Whether the client interprets the version property of the
  /// `textDocument/publishDiagnostics` notification's parameter.
  ///
  /// @since 3.15.0
  final bool? versionSupport;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (codeDescriptionSupport != null) {
      result['codeDescriptionSupport'] = codeDescriptionSupport;
    }
    if (dataSupport != null) {
      result['dataSupport'] = dataSupport;
    }
    if (relatedInformation != null) {
      result['relatedInformation'] = relatedInformation;
    }
    if (tagSupport != null) {
      result['tagSupport'] = tagSupport?.toJson();
    }
    if (versionSupport != null) {
      result['versionSupport'] = versionSupport;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseBool(obj, reporter, 'codeDescriptionSupport',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'dataSupport',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'relatedInformation',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParsePublishDiagnosticsClientCapabilitiesTagSupport(
          obj, reporter, 'tagSupport',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'versionSupport',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter
          .reportError('must be of type PublishDiagnosticsClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is PublishDiagnosticsClientCapabilities &&
        other.runtimeType == PublishDiagnosticsClientCapabilities &&
        codeDescriptionSupport == other.codeDescriptionSupport &&
        dataSupport == other.dataSupport &&
        relatedInformation == other.relatedInformation &&
        tagSupport == other.tagSupport &&
        versionSupport == other.versionSupport;
  }

  @override
  int get hashCode => Object.hash(
        codeDescriptionSupport,
        dataSupport,
        relatedInformation,
        tagSupport,
        versionSupport,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class PublishDiagnosticsClientCapabilitiesTagSupport implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    PublishDiagnosticsClientCapabilitiesTagSupport.canParse,
    PublishDiagnosticsClientCapabilitiesTagSupport.fromJson,
  );

  PublishDiagnosticsClientCapabilitiesTagSupport({
    required this.valueSet,
  });
  static PublishDiagnosticsClientCapabilitiesTagSupport fromJson(
      Map<String, Object?> json) {
    final valueSetJson = json['valueSet'];
    final valueSet = (valueSetJson as List<Object?>)
        .map((item) => DiagnosticTag.fromJson(item as int))
        .toList();
    return PublishDiagnosticsClientCapabilitiesTagSupport(
      valueSet: valueSet,
    );
  }

  /// The tags supported by the client.
  final List<DiagnosticTag> valueSet;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['valueSet'] = valueSet.map((item) => item.toJson()).toList();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseListDiagnosticTag(obj, reporter, 'valueSet',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError(
          'must be of type PublishDiagnosticsClientCapabilitiesTagSupport');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is PublishDiagnosticsClientCapabilitiesTagSupport &&
        other.runtimeType == PublishDiagnosticsClientCapabilitiesTagSupport &&
        listEqual(valueSet, other.valueSet,
            (DiagnosticTag a, DiagnosticTag b) => a == b);
  }

  @override
  int get hashCode => lspHashCode(valueSet);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The publish diagnostic notification's parameters.
class PublishDiagnosticsParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    PublishDiagnosticsParams.canParse,
    PublishDiagnosticsParams.fromJson,
  );

  PublishDiagnosticsParams({
    required this.diagnostics,
    required this.uri,
    this.version,
  });
  static PublishDiagnosticsParams fromJson(Map<String, Object?> json) {
    final diagnosticsJson = json['diagnostics'];
    final diagnostics = (diagnosticsJson as List<Object?>)
        .map((item) => Diagnostic.fromJson(item as Map<String, Object?>))
        .toList();
    final uriJson = json['uri'];
    final uri = uriJson as String;
    final versionJson = json['version'];
    final version = versionJson as int?;
    return PublishDiagnosticsParams(
      diagnostics: diagnostics,
      uri: uri,
      version: version,
    );
  }

  /// An array of diagnostic information items.
  final List<Diagnostic> diagnostics;

  /// The URI for which diagnostic information is reported.
  final DocumentUri uri;

  /// Optional the version number of the document the diagnostics are published
  /// for.
  ///
  /// @since 3.15.0
  final int? version;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['diagnostics'] = diagnostics.map((item) => item.toJson()).toList();
    result['uri'] = uri;
    if (version != null) {
      result['version'] = version;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListDiagnostic(obj, reporter, 'diagnostics',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'uri',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseInt(obj, reporter, 'version',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type PublishDiagnosticsParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is PublishDiagnosticsParams &&
        other.runtimeType == PublishDiagnosticsParams &&
        listEqual(diagnostics, other.diagnostics,
            (Diagnostic a, Diagnostic b) => a == b) &&
        uri == other.uri &&
        version == other.version;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(diagnostics),
        uri,
        version,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A range in a text document expressed as (zero-based) start and end
/// positions.
///
/// If you want to specify a range that contains a line including the line
/// ending character(s) then use an end position denoting the start of the next
/// line. For example:
/// ```ts
/// {
///     start: { line: 5, character: 23 }
///     end : { line 6, character : 0 }
/// }
/// ```
class Range implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    Range.canParse,
    Range.fromJson,
  );

  Range({
    required this.end,
    required this.start,
  });
  static Range fromJson(Map<String, Object?> json) {
    final endJson = json['end'];
    final end = Position.fromJson(endJson as Map<String, Object?>);
    final startJson = json['start'];
    final start = Position.fromJson(startJson as Map<String, Object?>);
    return Range(
      end: end,
      start: start,
    );
  }

  /// The range's end position.
  final Position end;

  /// The range's start position.
  final Position start;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['end'] = end.toJson();
    result['start'] = start.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParsePosition(obj, reporter, 'end',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParsePosition(obj, reporter, 'start',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type Range');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is Range &&
        other.runtimeType == Range &&
        end == other.end &&
        start == other.start;
  }

  @override
  int get hashCode => Object.hash(
        end,
        start,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Client Capabilities for a ReferencesRequest.
class ReferenceClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ReferenceClientCapabilities.canParse,
    ReferenceClientCapabilities.fromJson,
  );

  ReferenceClientCapabilities({
    this.dynamicRegistration,
  });
  static ReferenceClientCapabilities fromJson(Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    return ReferenceClientCapabilities(
      dynamicRegistration: dynamicRegistration,
    );
  }

  /// Whether references supports dynamic registration.
  final bool? dynamicRegistration;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseBool(obj, reporter, 'dynamicRegistration',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type ReferenceClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ReferenceClientCapabilities &&
        other.runtimeType == ReferenceClientCapabilities &&
        dynamicRegistration == other.dynamicRegistration;
  }

  @override
  int get hashCode => dynamicRegistration.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Value-object that contains additional information when requesting
/// references.
class ReferenceContext implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ReferenceContext.canParse,
    ReferenceContext.fromJson,
  );

  ReferenceContext({
    required this.includeDeclaration,
  });
  static ReferenceContext fromJson(Map<String, Object?> json) {
    final includeDeclarationJson = json['includeDeclaration'];
    final includeDeclaration = includeDeclarationJson as bool;
    return ReferenceContext(
      includeDeclaration: includeDeclaration,
    );
  }

  /// Include the declaration of the current symbol.
  final bool includeDeclaration;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['includeDeclaration'] = includeDeclaration;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseBool(obj, reporter, 'includeDeclaration',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type ReferenceContext');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ReferenceContext &&
        other.runtimeType == ReferenceContext &&
        includeDeclaration == other.includeDeclaration;
  }

  @override
  int get hashCode => includeDeclaration.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Reference options.
class ReferenceOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ReferenceOptions.canParse,
    ReferenceOptions.fromJson,
  );

  ReferenceOptions({
    this.workDoneProgress,
  });
  static ReferenceOptions fromJson(Map<String, Object?> json) {
    if (ReferenceRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return ReferenceRegistrationOptions.fromJson(json);
    }
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return ReferenceOptions(
      workDoneProgress: workDoneProgress,
    );
  }

  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseBool(obj, reporter, 'workDoneProgress',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type ReferenceOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ReferenceOptions &&
        other.runtimeType == ReferenceOptions &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => workDoneProgress.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Parameters for a ReferencesRequest.
class ReferenceParams
    implements
        PartialResultParams,
        TextDocumentPositionParams,
        WorkDoneProgressParams,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ReferenceParams.canParse,
    ReferenceParams.fromJson,
  );

  ReferenceParams({
    required this.context,
    this.partialResultToken,
    required this.position,
    required this.textDocument,
    this.workDoneToken,
  });
  static ReferenceParams fromJson(Map<String, Object?> json) {
    final contextJson = json['context'];
    final context =
        ReferenceContext.fromJson(contextJson as Map<String, Object?>);
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : _eitherIntString(partialResultTokenJson);
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken =
        workDoneTokenJson == null ? null : _eitherIntString(workDoneTokenJson);
    return ReferenceParams(
      context: context,
      partialResultToken: partialResultToken,
      position: position,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  final ReferenceContext context;

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final ProgressToken? partialResultToken;

  /// The position inside the text document.
  @override
  final Position position;

  /// The text document.
  @override
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final ProgressToken? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['context'] = context.toJson();
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    result['position'] = position.toJson();
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseReferenceContext(obj, reporter, 'context',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseIntString(obj, reporter, 'partialResultToken',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParsePosition(obj, reporter, 'position',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseIntString(obj, reporter, 'workDoneToken',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type ReferenceParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ReferenceParams &&
        other.runtimeType == ReferenceParams &&
        context == other.context &&
        partialResultToken == other.partialResultToken &&
        position == other.position &&
        textDocument == other.textDocument &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        context,
        partialResultToken,
        position,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Registration options for a ReferencesRequest.
class ReferenceRegistrationOptions
    implements ReferenceOptions, TextDocumentRegistrationOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ReferenceRegistrationOptions.canParse,
    ReferenceRegistrationOptions.fromJson,
  );

  ReferenceRegistrationOptions({
    this.documentSelector,
    this.workDoneProgress,
  });
  static ReferenceRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return ReferenceRegistrationOptions(
      documentSelector: documentSelector,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListTextDocumentFilterWithScheme(
          obj, reporter, 'documentSelector',
          allowsUndefined: false, allowsNull: true)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'workDoneProgress',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type ReferenceRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ReferenceRegistrationOptions &&
        other.runtimeType == ReferenceRegistrationOptions &&
        listEqual(
            documentSelector,
            other.documentSelector,
            (TextDocumentFilterWithScheme a, TextDocumentFilterWithScheme b) =>
                a == b) &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// General parameters to to register for an notification or to register a
/// provider.
class Registration implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    Registration.canParse,
    Registration.fromJson,
  );

  Registration({
    required this.id,
    required this.method,
    this.registerOptions,
  });
  static Registration fromJson(Map<String, Object?> json) {
    final idJson = json['id'];
    final id = idJson as String;
    final methodJson = json['method'];
    final method = methodJson as String;
    final registerOptionsJson = json['registerOptions'];
    final registerOptions = registerOptionsJson;
    return Registration(
      id: id,
      method: method,
      registerOptions: registerOptions,
    );
  }

  /// The id used to register the request. The id can be used to deregister the
  /// request again.
  final String id;

  /// The method / capability to register for.
  final String method;

  /// Options necessary for the registration.
  final LSPAny registerOptions;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['id'] = id;
    result['method'] = method;
    if (registerOptions != null) {
      result['registerOptions'] = registerOptions;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseString(obj, reporter, 'id',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseString(obj, reporter, 'method',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type Registration');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is Registration &&
        other.runtimeType == Registration &&
        id == other.id &&
        method == other.method &&
        registerOptions == other.registerOptions;
  }

  @override
  int get hashCode => Object.hash(
        id,
        method,
        registerOptions,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class RegistrationParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    RegistrationParams.canParse,
    RegistrationParams.fromJson,
  );

  RegistrationParams({
    required this.registrations,
  });
  static RegistrationParams fromJson(Map<String, Object?> json) {
    final registrationsJson = json['registrations'];
    final registrations = (registrationsJson as List<Object?>)
        .map((item) => Registration.fromJson(item as Map<String, Object?>))
        .toList();
    return RegistrationParams(
      registrations: registrations,
    );
  }

  final List<Registration> registrations;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['registrations'] =
        registrations.map((item) => item.toJson()).toList();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseListRegistration(obj, reporter, 'registrations',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type RegistrationParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is RegistrationParams &&
        other.runtimeType == RegistrationParams &&
        listEqual(registrations, other.registrations,
            (Registration a, Registration b) => a == b);
  }

  @override
  int get hashCode => lspHashCode(registrations);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Client capabilities specific to regular expressions.
///
/// @since 3.16.0
class RegularExpressionsClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    RegularExpressionsClientCapabilities.canParse,
    RegularExpressionsClientCapabilities.fromJson,
  );

  RegularExpressionsClientCapabilities({
    required this.engine,
    this.version,
  });
  static RegularExpressionsClientCapabilities fromJson(
      Map<String, Object?> json) {
    final engineJson = json['engine'];
    final engine = engineJson as String;
    final versionJson = json['version'];
    final version = versionJson as String?;
    return RegularExpressionsClientCapabilities(
      engine: engine,
      version: version,
    );
  }

  /// The engine's name.
  final String engine;

  /// The engine's version.
  final String? version;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['engine'] = engine;
    if (version != null) {
      result['version'] = version;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseString(obj, reporter, 'engine',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseString(obj, reporter, 'version',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter
          .reportError('must be of type RegularExpressionsClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is RegularExpressionsClientCapabilities &&
        other.runtimeType == RegularExpressionsClientCapabilities &&
        engine == other.engine &&
        version == other.version;
  }

  @override
  int get hashCode => Object.hash(
        engine,
        version,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A full diagnostic report with a set of related documents.
///
/// @since 3.17.0
class RelatedFullDocumentDiagnosticReport
    implements FullDocumentDiagnosticReport, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    RelatedFullDocumentDiagnosticReport.canParse,
    RelatedFullDocumentDiagnosticReport.fromJson,
  );

  RelatedFullDocumentDiagnosticReport({
    required this.items,
    this.kind = 'full',
    this.relatedDocuments,
    this.resultId,
  }) {
    if (kind != 'full') {
      throw 'kind may only be the literal \'full\'';
    }
  }
  static RelatedFullDocumentDiagnosticReport fromJson(
      Map<String, Object?> json) {
    final itemsJson = json['items'];
    final items = (itemsJson as List<Object?>)
        .map((item) => Diagnostic.fromJson(item as Map<String, Object?>))
        .toList();
    final kindJson = json['kind'];
    final kind = kindJson as String;
    final relatedDocumentsJson = json['relatedDocuments'];
    final relatedDocuments = (relatedDocumentsJson as Map<Object, Object?>?)
        ?.map((key, value) => MapEntry(
            key as String,
            _eitherFullDocumentDiagnosticReportUnchangedDocumentDiagnosticReport(
                value)));
    final resultIdJson = json['resultId'];
    final resultId = resultIdJson as String?;
    return RelatedFullDocumentDiagnosticReport(
      items: items,
      kind: kind,
      relatedDocuments: relatedDocuments,
      resultId: resultId,
    );
  }

  /// The actual items.
  @override
  final List<Diagnostic> items;

  /// A full document diagnostic report.
  @override
  final String kind;

  /// Diagnostics of related documents. This information is useful in
  /// programming languages where code in a file A can generate diagnostics in a
  /// file B which A depends on. An example of such a language is C/C++ where
  /// marco definitions in a file a.cpp and result in errors in a header file
  /// b.hpp.
  ///
  /// @since 3.17.0
  final Map<
      DocumentUri,
      Either2<FullDocumentDiagnosticReport,
          UnchangedDocumentDiagnosticReport>>? relatedDocuments;

  /// An optional result id. If provided it will be sent on the next diagnostic
  /// request for the same document.
  @override
  final String? resultId;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['items'] = items.map((item) => item.toJson()).toList();
    result['kind'] = kind;
    if (relatedDocuments != null) {
      result['relatedDocuments'] = relatedDocuments;
    }
    if (resultId != null) {
      result['resultId'] = resultId;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListDiagnostic(obj, reporter, 'items',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseLiteral(obj, reporter, 'kind',
          allowsUndefined: false, allowsNull: false, literal: 'full')) {
        return false;
      }
      if (!_canParseMapStringFullDocumentDiagnosticReportUnchangedDocumentDiagnosticReport(
          obj, reporter, 'relatedDocuments',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseString(obj, reporter, 'resultId',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter
          .reportError('must be of type RelatedFullDocumentDiagnosticReport');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is RelatedFullDocumentDiagnosticReport &&
        other.runtimeType == RelatedFullDocumentDiagnosticReport &&
        listEqual(items, other.items, (Diagnostic a, Diagnostic b) => a == b) &&
        kind == other.kind &&
        mapEqual(
            relatedDocuments,
            other.relatedDocuments,
            (Either2<FullDocumentDiagnosticReport,
                            UnchangedDocumentDiagnosticReport>
                        a,
                    Either2<FullDocumentDiagnosticReport,
                            UnchangedDocumentDiagnosticReport>
                        b) =>
                a == b) &&
        resultId == other.resultId;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(items),
        kind,
        lspHashCode(relatedDocuments),
        resultId,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// An unchanged diagnostic report with a set of related documents.
///
/// @since 3.17.0
class RelatedUnchangedDocumentDiagnosticReport
    implements UnchangedDocumentDiagnosticReport, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    RelatedUnchangedDocumentDiagnosticReport.canParse,
    RelatedUnchangedDocumentDiagnosticReport.fromJson,
  );

  RelatedUnchangedDocumentDiagnosticReport({
    this.kind = 'unchanged',
    this.relatedDocuments,
    required this.resultId,
  }) {
    if (kind != 'unchanged') {
      throw 'kind may only be the literal \'unchanged\'';
    }
  }
  static RelatedUnchangedDocumentDiagnosticReport fromJson(
      Map<String, Object?> json) {
    final kindJson = json['kind'];
    final kind = kindJson as String;
    final relatedDocumentsJson = json['relatedDocuments'];
    final relatedDocuments = (relatedDocumentsJson as Map<Object, Object?>?)
        ?.map((key, value) => MapEntry(
            key as String,
            _eitherFullDocumentDiagnosticReportUnchangedDocumentDiagnosticReport(
                value)));
    final resultIdJson = json['resultId'];
    final resultId = resultIdJson as String;
    return RelatedUnchangedDocumentDiagnosticReport(
      kind: kind,
      relatedDocuments: relatedDocuments,
      resultId: resultId,
    );
  }

  /// A document diagnostic report indicating no changes to the last result. A
  /// server can only return `unchanged` if result ids are provided.
  @override
  final String kind;

  /// Diagnostics of related documents. This information is useful in
  /// programming languages where code in a file A can generate diagnostics in a
  /// file B which A depends on. An example of such a language is C/C++ where
  /// marco definitions in a file a.cpp and result in errors in a header file
  /// b.hpp.
  ///
  /// @since 3.17.0
  final Map<
      DocumentUri,
      Either2<FullDocumentDiagnosticReport,
          UnchangedDocumentDiagnosticReport>>? relatedDocuments;

  /// A result id which will be sent on the next diagnostic request for the same
  /// document.
  @override
  final String resultId;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['kind'] = kind;
    if (relatedDocuments != null) {
      result['relatedDocuments'] = relatedDocuments;
    }
    result['resultId'] = resultId;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseLiteral(obj, reporter, 'kind',
          allowsUndefined: false, allowsNull: false, literal: 'unchanged')) {
        return false;
      }
      if (!_canParseMapStringFullDocumentDiagnosticReportUnchangedDocumentDiagnosticReport(
          obj, reporter, 'relatedDocuments',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseString(obj, reporter, 'resultId',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError(
          'must be of type RelatedUnchangedDocumentDiagnosticReport');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is RelatedUnchangedDocumentDiagnosticReport &&
        other.runtimeType == RelatedUnchangedDocumentDiagnosticReport &&
        kind == other.kind &&
        mapEqual(
            relatedDocuments,
            other.relatedDocuments,
            (Either2<FullDocumentDiagnosticReport,
                            UnchangedDocumentDiagnosticReport>
                        a,
                    Either2<FullDocumentDiagnosticReport,
                            UnchangedDocumentDiagnosticReport>
                        b) =>
                a == b) &&
        resultId == other.resultId;
  }

  @override
  int get hashCode => Object.hash(
        kind,
        lspHashCode(relatedDocuments),
        resultId,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A relative pattern is a helper to construct glob patterns that are matched
/// relatively to a base URI. The common value for a `baseUri` is a workspace
/// folder root, but it can be another absolute URI as well.
///
/// @since 3.17.0
class RelativePattern implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    RelativePattern.canParse,
    RelativePattern.fromJson,
  );

  RelativePattern({
    required this.baseUri,
    required this.pattern,
  });
  static RelativePattern fromJson(Map<String, Object?> json) {
    final baseUriJson = json['baseUri'];
    final baseUri = _eitherStringWorkspaceFolder(baseUriJson);
    final patternJson = json['pattern'];
    final pattern = patternJson as String;
    return RelativePattern(
      baseUri: baseUri,
      pattern: pattern,
    );
  }

  /// A workspace folder or a base URI to which this pattern will be matched
  /// against relatively.
  final Either2<LspUri, WorkspaceFolder> baseUri;

  /// The actual glob pattern;
  final LspPattern pattern;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['baseUri'] = baseUri;
    result['pattern'] = pattern;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseStringWorkspaceFolder(obj, reporter, 'baseUri',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseString(obj, reporter, 'pattern',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type RelativePattern');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is RelativePattern &&
        other.runtimeType == RelativePattern &&
        baseUri == other.baseUri &&
        pattern == other.pattern;
  }

  @override
  int get hashCode => Object.hash(
        baseUri,
        pattern,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class RenameClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    RenameClientCapabilities.canParse,
    RenameClientCapabilities.fromJson,
  );

  RenameClientCapabilities({
    this.dynamicRegistration,
    this.honorsChangeAnnotations,
    this.prepareSupport,
    this.prepareSupportDefaultBehavior,
  });
  static RenameClientCapabilities fromJson(Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    final honorsChangeAnnotationsJson = json['honorsChangeAnnotations'];
    final honorsChangeAnnotations = honorsChangeAnnotationsJson as bool?;
    final prepareSupportJson = json['prepareSupport'];
    final prepareSupport = prepareSupportJson as bool?;
    final prepareSupportDefaultBehaviorJson =
        json['prepareSupportDefaultBehavior'];
    final prepareSupportDefaultBehavior =
        prepareSupportDefaultBehaviorJson != null
            ? PrepareSupportDefaultBehavior.fromJson(
                prepareSupportDefaultBehaviorJson as int)
            : null;
    return RenameClientCapabilities(
      dynamicRegistration: dynamicRegistration,
      honorsChangeAnnotations: honorsChangeAnnotations,
      prepareSupport: prepareSupport,
      prepareSupportDefaultBehavior: prepareSupportDefaultBehavior,
    );
  }

  /// Whether rename supports dynamic registration.
  final bool? dynamicRegistration;

  /// Whether the 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 3.12.0
  final bool? prepareSupport;

  /// Client supports the default behavior result.
  ///
  /// The value indicates the default behavior used by the client.
  ///
  /// @since 3.16.0
  final PrepareSupportDefaultBehavior? prepareSupportDefaultBehavior;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    if (honorsChangeAnnotations != null) {
      result['honorsChangeAnnotations'] = honorsChangeAnnotations;
    }
    if (prepareSupport != null) {
      result['prepareSupport'] = prepareSupport;
    }
    if (prepareSupportDefaultBehavior != null) {
      result['prepareSupportDefaultBehavior'] =
          prepareSupportDefaultBehavior?.toJson();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseBool(obj, reporter, 'dynamicRegistration',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'honorsChangeAnnotations',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'prepareSupport',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParsePrepareSupportDefaultBehavior(
          obj, reporter, 'prepareSupportDefaultBehavior',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type RenameClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is RenameClientCapabilities &&
        other.runtimeType == RenameClientCapabilities &&
        dynamicRegistration == other.dynamicRegistration &&
        honorsChangeAnnotations == other.honorsChangeAnnotations &&
        prepareSupport == other.prepareSupport &&
        prepareSupportDefaultBehavior == other.prepareSupportDefaultBehavior;
  }

  @override
  int get hashCode => Object.hash(
        dynamicRegistration,
        honorsChangeAnnotations,
        prepareSupport,
        prepareSupportDefaultBehavior,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Rename file operation
class RenameFile implements ResourceOperation, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    RenameFile.canParse,
    RenameFile.fromJson,
  );

  RenameFile({
    this.annotationId,
    this.kind = 'rename',
    required this.newUri,
    required this.oldUri,
    this.options,
  }) {
    if (kind != 'rename') {
      throw 'kind may only be the literal \'rename\'';
    }
  }
  static RenameFile fromJson(Map<String, Object?> json) {
    final annotationIdJson = json['annotationId'];
    final annotationId = annotationIdJson as String?;
    final kindJson = json['kind'];
    final kind = kindJson as String;
    final newUriJson = json['newUri'];
    final newUri = newUriJson as String;
    final oldUriJson = json['oldUri'];
    final oldUri = oldUriJson as String;
    final optionsJson = json['options'];
    final options = optionsJson != null
        ? RenameFileOptions.fromJson(optionsJson as Map<String, Object?>)
        : null;
    return RenameFile(
      annotationId: annotationId,
      kind: kind,
      newUri: newUri,
      oldUri: oldUri,
      options: options,
    );
  }

  /// An optional annotation identifier describing the operation.
  ///
  /// @since 3.16.0
  @override
  final ChangeAnnotationIdentifier? annotationId;

  /// A rename
  @override
  final String kind;

  /// The new location.
  final DocumentUri newUri;

  /// The old (existing) location.
  final DocumentUri oldUri;

  /// Rename options.
  final RenameFileOptions? options;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (annotationId != null) {
      result['annotationId'] = annotationId;
    }
    result['kind'] = kind;
    result['newUri'] = newUri;
    result['oldUri'] = oldUri;
    if (options != null) {
      result['options'] = options?.toJson();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseString(obj, reporter, 'annotationId',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseLiteral(obj, reporter, 'kind',
          allowsUndefined: false, allowsNull: false, literal: 'rename')) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'newUri',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'oldUri',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseRenameFileOptions(obj, reporter, 'options',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type RenameFile');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is RenameFile &&
        other.runtimeType == RenameFile &&
        annotationId == other.annotationId &&
        kind == other.kind &&
        newUri == other.newUri &&
        oldUri == other.oldUri &&
        options == other.options;
  }

  @override
  int get hashCode => Object.hash(
        annotationId,
        kind,
        newUri,
        oldUri,
        options,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Rename file options
class RenameFileOptions implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    RenameFileOptions.canParse,
    RenameFileOptions.fromJson,
  );

  RenameFileOptions({
    this.ignoreIfExists,
    this.overwrite,
  });
  static RenameFileOptions fromJson(Map<String, Object?> json) {
    final ignoreIfExistsJson = json['ignoreIfExists'];
    final ignoreIfExists = ignoreIfExistsJson as bool?;
    final overwriteJson = json['overwrite'];
    final overwrite = overwriteJson as bool?;
    return RenameFileOptions(
      ignoreIfExists: ignoreIfExists,
      overwrite: overwrite,
    );
  }

  /// Ignores if target exists.
  final bool? ignoreIfExists;

  /// Overwrite target if existing. Overwrite wins over `ignoreIfExists`
  final bool? overwrite;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (ignoreIfExists != null) {
      result['ignoreIfExists'] = ignoreIfExists;
    }
    if (overwrite != null) {
      result['overwrite'] = overwrite;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseBool(obj, reporter, 'ignoreIfExists',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'overwrite',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type RenameFileOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is RenameFileOptions &&
        other.runtimeType == RenameFileOptions &&
        ignoreIfExists == other.ignoreIfExists &&
        overwrite == other.overwrite;
  }

  @override
  int get hashCode => Object.hash(
        ignoreIfExists,
        overwrite,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The parameters sent in notifications/requests for user-initiated renames of
/// files.
///
/// @since 3.16.0
class RenameFilesParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    RenameFilesParams.canParse,
    RenameFilesParams.fromJson,
  );

  RenameFilesParams({
    required this.files,
  });
  static RenameFilesParams fromJson(Map<String, Object?> json) {
    final filesJson = json['files'];
    final files = (filesJson as List<Object?>)
        .map((item) => FileRename.fromJson(item as Map<String, Object?>))
        .toList();
    return RenameFilesParams(
      files: files,
    );
  }

  /// An array of all files/folders renamed in this operation. When a folder is
  /// renamed, only the folder will be included, and not its children.
  final List<FileRename> files;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['files'] = files.map((item) => item.toJson()).toList();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseListFileRename(obj, reporter, 'files',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type RenameFilesParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is RenameFilesParams &&
        other.runtimeType == RenameFilesParams &&
        listEqual(files, other.files, (FileRename a, FileRename b) => a == b);
  }

  @override
  int get hashCode => lspHashCode(files);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Provider options for a RenameRequest.
class RenameOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    RenameOptions.canParse,
    RenameOptions.fromJson,
  );

  RenameOptions({
    this.prepareProvider,
    this.workDoneProgress,
  });
  static RenameOptions fromJson(Map<String, Object?> json) {
    if (RenameRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return RenameRegistrationOptions.fromJson(json);
    }
    final prepareProviderJson = json['prepareProvider'];
    final prepareProvider = prepareProviderJson as bool?;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return RenameOptions(
      prepareProvider: prepareProvider,
      workDoneProgress: workDoneProgress,
    );
  }

  /// Renames should be checked and tested before being executed.
  ///
  /// @since version 3.12.0
  final bool? prepareProvider;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (prepareProvider != null) {
      result['prepareProvider'] = prepareProvider;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseBool(obj, reporter, 'prepareProvider',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'workDoneProgress',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type RenameOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is RenameOptions &&
        other.runtimeType == RenameOptions &&
        prepareProvider == other.prepareProvider &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        prepareProvider,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The parameters of a RenameRequest.
class RenameParams implements WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    RenameParams.canParse,
    RenameParams.fromJson,
  );

  RenameParams({
    required this.newName,
    required this.position,
    required this.textDocument,
    this.workDoneToken,
  });
  static RenameParams fromJson(Map<String, Object?> json) {
    final newNameJson = json['newName'];
    final newName = newNameJson as String;
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken =
        workDoneTokenJson == null ? null : _eitherIntString(workDoneTokenJson);
    return RenameParams(
      newName: newName,
      position: position,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// The new name of the symbol. If the given name is not valid the request
  /// must return a ResponseError with an appropriate message set.
  final String newName;

  /// The position at which this request was sent.
  final Position position;

  /// The document to rename.
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final ProgressToken? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['newName'] = newName;
    result['position'] = position.toJson();
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseString(obj, reporter, 'newName',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParsePosition(obj, reporter, 'position',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseIntString(obj, reporter, 'workDoneToken',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type RenameParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is RenameParams &&
        other.runtimeType == RenameParams &&
        newName == other.newName &&
        position == other.position &&
        textDocument == other.textDocument &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        newName,
        position,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Registration options for a RenameRequest.
class RenameRegistrationOptions
    implements RenameOptions, TextDocumentRegistrationOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    RenameRegistrationOptions.canParse,
    RenameRegistrationOptions.fromJson,
  );

  RenameRegistrationOptions({
    this.documentSelector,
    this.prepareProvider,
    this.workDoneProgress,
  });
  static RenameRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final prepareProviderJson = json['prepareProvider'];
    final prepareProvider = prepareProviderJson as bool?;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return RenameRegistrationOptions(
      documentSelector: documentSelector,
      prepareProvider: prepareProvider,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;

  /// Renames should be checked and tested before being executed.
  ///
  /// @since version 3.12.0
  @override
  final bool? prepareProvider;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (prepareProvider != null) {
      result['prepareProvider'] = prepareProvider;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListTextDocumentFilterWithScheme(
          obj, reporter, 'documentSelector',
          allowsUndefined: false, allowsNull: true)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'prepareProvider',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'workDoneProgress',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type RenameRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is RenameRegistrationOptions &&
        other.runtimeType == RenameRegistrationOptions &&
        listEqual(
            documentSelector,
            other.documentSelector,
            (TextDocumentFilterWithScheme a, TextDocumentFilterWithScheme b) =>
                a == b) &&
        prepareProvider == other.prepareProvider &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        prepareProvider,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A generic resource operation.
class ResourceOperation implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ResourceOperation.canParse,
    ResourceOperation.fromJson,
  );

  ResourceOperation({
    this.annotationId,
    required this.kind,
  });
  static ResourceOperation fromJson(Map<String, Object?> json) {
    if (RenameFile.canParse(json, nullLspJsonReporter)) {
      return RenameFile.fromJson(json);
    }
    if (CreateFile.canParse(json, nullLspJsonReporter)) {
      return CreateFile.fromJson(json);
    }
    if (DeleteFile.canParse(json, nullLspJsonReporter)) {
      return DeleteFile.fromJson(json);
    }
    final annotationIdJson = json['annotationId'];
    final annotationId = annotationIdJson as String?;
    final kindJson = json['kind'];
    final kind = kindJson as String;
    return ResourceOperation(
      annotationId: annotationId,
      kind: kind,
    );
  }

  /// An optional annotation identifier describing the operation.
  ///
  /// @since 3.16.0
  final ChangeAnnotationIdentifier? annotationId;

  /// The resource operation kind.
  final String kind;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (annotationId != null) {
      result['annotationId'] = annotationId;
    }
    result['kind'] = kind;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseString(obj, reporter, 'annotationId',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseString(obj, reporter, 'kind',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type ResourceOperation');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ResourceOperation &&
        other.runtimeType == ResourceOperation &&
        annotationId == other.annotationId &&
        kind == other.kind;
  }

  @override
  int get hashCode => Object.hash(
        annotationId,
        kind,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class ResourceOperationKind implements ToJsonable {
  const ResourceOperationKind._(this._value);
  const ResourceOperationKind.fromJson(this._value);

  final String _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    switch (obj) {
      case 'create':
      case 'delete':
      case 'rename':
        return true;
    }
    return false;
  }

  /// Supports creating new files and folders.
  static const Create = ResourceOperationKind._('create');

  /// Supports deleting existing files and folders.
  static const Delete = ResourceOperationKind._('delete');

  /// Supports renaming existing files and folders.
  static const Rename = ResourceOperationKind._('rename');

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is ResourceOperationKind && other._value == _value;
}

/// Save options.
class SaveOptions implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SaveOptions.canParse,
    SaveOptions.fromJson,
  );

  SaveOptions({
    this.includeText,
  });
  static SaveOptions fromJson(Map<String, Object?> json) {
    if (TextDocumentSaveRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return TextDocumentSaveRegistrationOptions.fromJson(json);
    }
    final includeTextJson = json['includeText'];
    final includeText = includeTextJson as bool?;
    return SaveOptions(
      includeText: includeText,
    );
  }

  /// The client is supposed to include the content on save.
  final bool? includeText;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (includeText != null) {
      result['includeText'] = includeText;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseBool(obj, reporter, 'includeText',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type SaveOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SaveOptions &&
        other.runtimeType == SaveOptions &&
        includeText == other.includeText;
  }

  @override
  int get hashCode => includeText.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A selection range represents a part of a selection hierarchy. A selection
/// range may have a parent selection range that contains it.
class SelectionRange implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SelectionRange.canParse,
    SelectionRange.fromJson,
  );

  SelectionRange({
    this.parent,
    required this.range,
  });
  static SelectionRange fromJson(Map<String, Object?> json) {
    final parentJson = json['parent'];
    final parent = parentJson != null
        ? SelectionRange.fromJson(parentJson as Map<String, Object?>)
        : null;
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    return SelectionRange(
      parent: parent,
      range: range,
    );
  }

  /// The parent selection range containing this range. Therefore `parent.range`
  /// must contain `this.range`.
  final SelectionRange? parent;

  /// The range of this selection range.
  final Range range;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (parent != null) {
      result['parent'] = parent?.toJson();
    }
    result['range'] = range.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseSelectionRange(obj, reporter, 'parent',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseRange(obj, reporter, 'range',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type SelectionRange');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SelectionRange &&
        other.runtimeType == SelectionRange &&
        parent == other.parent &&
        range == other.range;
  }

  @override
  int get hashCode => Object.hash(
        parent,
        range,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SelectionRangeClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SelectionRangeClientCapabilities.canParse,
    SelectionRangeClientCapabilities.fromJson,
  );

  SelectionRangeClientCapabilities({
    this.dynamicRegistration,
  });
  static SelectionRangeClientCapabilities fromJson(Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    return SelectionRangeClientCapabilities(
      dynamicRegistration: dynamicRegistration,
    );
  }

  /// Whether implementation supports dynamic registration for selection range
  /// providers. If this is set to `true` the client supports the new
  /// `SelectionRangeRegistrationOptions` return value for the corresponding
  /// server capability as well.
  final bool? dynamicRegistration;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseBool(obj, reporter, 'dynamicRegistration',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type SelectionRangeClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SelectionRangeClientCapabilities &&
        other.runtimeType == SelectionRangeClientCapabilities &&
        dynamicRegistration == other.dynamicRegistration;
  }

  @override
  int get hashCode => dynamicRegistration.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SelectionRangeOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SelectionRangeOptions.canParse,
    SelectionRangeOptions.fromJson,
  );

  SelectionRangeOptions({
    this.workDoneProgress,
  });
  static SelectionRangeOptions fromJson(Map<String, Object?> json) {
    if (SelectionRangeRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return SelectionRangeRegistrationOptions.fromJson(json);
    }
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return SelectionRangeOptions(
      workDoneProgress: workDoneProgress,
    );
  }

  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseBool(obj, reporter, 'workDoneProgress',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type SelectionRangeOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SelectionRangeOptions &&
        other.runtimeType == SelectionRangeOptions &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => workDoneProgress.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A parameter literal used in selection range requests.
class SelectionRangeParams
    implements PartialResultParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SelectionRangeParams.canParse,
    SelectionRangeParams.fromJson,
  );

  SelectionRangeParams({
    this.partialResultToken,
    required this.positions,
    required this.textDocument,
    this.workDoneToken,
  });
  static SelectionRangeParams fromJson(Map<String, Object?> json) {
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : _eitherIntString(partialResultTokenJson);
    final positionsJson = json['positions'];
    final positions = (positionsJson as List<Object?>)
        .map((item) => Position.fromJson(item as Map<String, Object?>))
        .toList();
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken =
        workDoneTokenJson == null ? null : _eitherIntString(workDoneTokenJson);
    return SelectionRangeParams(
      partialResultToken: partialResultToken,
      positions: positions,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final ProgressToken? partialResultToken;

  /// The positions inside the text document.
  final List<Position> positions;

  /// The text document.
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final ProgressToken? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    result['positions'] = positions.map((item) => item.toJson()).toList();
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseIntString(obj, reporter, 'partialResultToken',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseListPosition(obj, reporter, 'positions',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseIntString(obj, reporter, 'workDoneToken',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type SelectionRangeParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SelectionRangeParams &&
        other.runtimeType == SelectionRangeParams &&
        partialResultToken == other.partialResultToken &&
        listEqual(
            positions, other.positions, (Position a, Position b) => a == b) &&
        textDocument == other.textDocument &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        partialResultToken,
        lspHashCode(positions),
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SelectionRangeRegistrationOptions
    implements
        SelectionRangeOptions,
        StaticRegistrationOptions,
        TextDocumentRegistrationOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SelectionRangeRegistrationOptions.canParse,
    SelectionRangeRegistrationOptions.fromJson,
  );

  SelectionRangeRegistrationOptions({
    this.documentSelector,
    this.id,
    this.workDoneProgress,
  });
  static SelectionRangeRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final idJson = json['id'];
    final id = idJson as String?;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return SelectionRangeRegistrationOptions(
      documentSelector: documentSelector,
      id: id,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;

  /// The id used to register the request. The id can be used to deregister the
  /// request again. See also Registration#id.
  @override
  final String? id;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (id != null) {
      result['id'] = id;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListTextDocumentFilterWithScheme(
          obj, reporter, 'documentSelector',
          allowsUndefined: false, allowsNull: true)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'id',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'workDoneProgress',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type SelectionRangeRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SelectionRangeRegistrationOptions &&
        other.runtimeType == SelectionRangeRegistrationOptions &&
        listEqual(
            documentSelector,
            other.documentSelector,
            (TextDocumentFilterWithScheme a, TextDocumentFilterWithScheme b) =>
                a == b) &&
        id == other.id &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        id,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A set of predefined token modifiers. This set is not fixed an clients can
/// specify additional token types via the corresponding client capabilities.
///
/// @since 3.16.0
class SemanticTokenModifiers implements ToJsonable {
  const SemanticTokenModifiers(this._value);
  const SemanticTokenModifiers.fromJson(this._value);

  final String _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is String;
  static const abstract = SemanticTokenModifiers('abstract');
  static const async = SemanticTokenModifiers('async');
  static const declaration = SemanticTokenModifiers('declaration');
  static const defaultLibrary = SemanticTokenModifiers('defaultLibrary');
  static const definition = SemanticTokenModifiers('definition');
  static const deprecated = SemanticTokenModifiers('deprecated');
  static const documentation = SemanticTokenModifiers('documentation');
  static const modification = SemanticTokenModifiers('modification');
  static const readonly = SemanticTokenModifiers('readonly');
  static const static = SemanticTokenModifiers('static');

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is SemanticTokenModifiers && other._value == _value;
}

/// A set of predefined token types. This set is not fixed an clients can
/// specify additional token types via the corresponding client capabilities.
///
/// @since 3.16.0
class SemanticTokenTypes implements ToJsonable {
  const SemanticTokenTypes(this._value);
  const SemanticTokenTypes.fromJson(this._value);

  final String _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is String;
  static const class_ = SemanticTokenTypes('class');
  static const comment = SemanticTokenTypes('comment');

  /// @since 3.17.0
  static const decorator = SemanticTokenTypes('decorator');
  static const enum_ = SemanticTokenTypes('enum');
  static const enumMember = SemanticTokenTypes('enumMember');
  static const event = SemanticTokenTypes('event');
  static const function = SemanticTokenTypes('function');
  static const interface = SemanticTokenTypes('interface');
  static const keyword = SemanticTokenTypes('keyword');
  static const macro = SemanticTokenTypes('macro');
  static const method = SemanticTokenTypes('method');
  static const modifier = SemanticTokenTypes('modifier');
  static const namespace = SemanticTokenTypes('namespace');
  static const number = SemanticTokenTypes('number');
  static const operator = SemanticTokenTypes('operator');
  static const parameter = SemanticTokenTypes('parameter');
  static const property = SemanticTokenTypes('property');
  static const regexp = SemanticTokenTypes('regexp');
  static const string = SemanticTokenTypes('string');
  static const struct = SemanticTokenTypes('struct');

  /// Represents a generic type. Acts as a fallback for types which can't be
  /// mapped to a specific type like class or enum.
  static const type = SemanticTokenTypes('type');
  static const typeParameter = SemanticTokenTypes('typeParameter');
  static const variable = SemanticTokenTypes('variable');

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is SemanticTokenTypes && other._value == _value;
}

/// @since 3.16.0
class SemanticTokens implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SemanticTokens.canParse,
    SemanticTokens.fromJson,
  );

  SemanticTokens({
    required this.data,
    this.resultId,
  });
  static SemanticTokens fromJson(Map<String, Object?> json) {
    final dataJson = json['data'];
    final data =
        (dataJson as List<Object?>).map((item) => item as int).toList();
    final resultIdJson = json['resultId'];
    final resultId = resultIdJson as String?;
    return SemanticTokens(
      data: data,
      resultId: resultId,
    );
  }

  /// The actual tokens.
  final List<int> data;

  /// An optional result id. If provided and clients support delta updating the
  /// client will include the result id in the next semantic token request. A
  /// server can then instead of computing all semantic tokens again simply send
  /// a delta.
  final String? resultId;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['data'] = data;
    if (resultId != null) {
      result['resultId'] = resultId;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListInt(obj, reporter, 'data',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseString(obj, reporter, 'resultId',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type SemanticTokens');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SemanticTokens &&
        other.runtimeType == SemanticTokens &&
        listEqual(data, other.data, (int a, int b) => a == b) &&
        resultId == other.resultId;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(data),
        resultId,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// @since 3.16.0
class SemanticTokensClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SemanticTokensClientCapabilities.canParse,
    SemanticTokensClientCapabilities.fromJson,
  );

  SemanticTokensClientCapabilities({
    this.augmentsSyntaxTokens,
    this.dynamicRegistration,
    required this.formats,
    this.multilineTokenSupport,
    this.overlappingTokenSupport,
    required this.requests,
    this.serverCancelSupport,
    required this.tokenModifiers,
    required this.tokenTypes,
  });
  static SemanticTokensClientCapabilities fromJson(Map<String, Object?> json) {
    final augmentsSyntaxTokensJson = json['augmentsSyntaxTokens'];
    final augmentsSyntaxTokens = augmentsSyntaxTokensJson as bool?;
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    final formatsJson = json['formats'];
    final formats = (formatsJson as List<Object?>)
        .map((item) => TokenFormat.fromJson(item as String))
        .toList();
    final multilineTokenSupportJson = json['multilineTokenSupport'];
    final multilineTokenSupport = multilineTokenSupportJson as bool?;
    final overlappingTokenSupportJson = json['overlappingTokenSupport'];
    final overlappingTokenSupport = overlappingTokenSupportJson as bool?;
    final requestsJson = json['requests'];
    final requests = SemanticTokensClientCapabilitiesRequests.fromJson(
        requestsJson as Map<String, Object?>);
    final serverCancelSupportJson = json['serverCancelSupport'];
    final serverCancelSupport = serverCancelSupportJson as bool?;
    final tokenModifiersJson = json['tokenModifiers'];
    final tokenModifiers = (tokenModifiersJson as List<Object?>)
        .map((item) => item as String)
        .toList();
    final tokenTypesJson = json['tokenTypes'];
    final tokenTypes = (tokenTypesJson as List<Object?>)
        .map((item) => item as String)
        .toList();
    return SemanticTokensClientCapabilities(
      augmentsSyntaxTokens: augmentsSyntaxTokens,
      dynamicRegistration: dynamicRegistration,
      formats: formats,
      multilineTokenSupport: multilineTokenSupport,
      overlappingTokenSupport: overlappingTokenSupport,
      requests: requests,
      serverCancelSupport: serverCancelSupport,
      tokenModifiers: tokenModifiers,
      tokenTypes: tokenTypes,
    );
  }

  /// Whether the client uses semantic tokens to augment existing syntax tokens.
  /// If set to `true` client side created syntax tokens and semantic tokens are
  /// both used for colorization. If set to `false` the client only uses the
  /// returned semantic tokens for colorization.
  ///
  /// If the value is `undefined` then the client behavior is not specified.
  ///
  /// @since 3.17.0
  final bool? augmentsSyntaxTokens;

  /// Whether implementation supports dynamic registration. If this is set to
  /// `true` the client supports the new `(TextDocumentRegistrationOptions &
  /// StaticRegistrationOptions)` return value for the corresponding server
  /// capability as well.
  final bool? dynamicRegistration;

  /// The token formats the clients supports.
  final List<TokenFormat> formats;

  /// Whether the client supports tokens that can span multiple lines.
  final bool? multilineTokenSupport;

  /// Whether the client supports tokens that can overlap each other.
  final bool? overlappingTokenSupport;

  /// Which requests the client supports and might send to the server depending
  /// on the server's capability. Please note that clients might not show
  /// semantic tokens or degrade some of the user experience if a range or full
  /// request is advertised by the client but not provided by the server. If for
  /// example the client capability `requests.full` and `request.range` are both
  /// set to true but the server only provides a range provider the client might
  /// not render a minimap correctly or might even decide to not show any
  /// semantic tokens at all.
  final SemanticTokensClientCapabilitiesRequests requests;

  /// Whether the client allows the server to actively cancel a semantic token
  /// request, e.g. supports returning LSPErrorCodes.ServerCancelled. If a
  /// server does the client needs to retrigger the request.
  ///
  /// @since 3.17.0
  final bool? serverCancelSupport;

  /// The token modifiers that the client supports.
  final List<String> tokenModifiers;

  /// The token types that the client supports.
  final List<String> tokenTypes;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (augmentsSyntaxTokens != null) {
      result['augmentsSyntaxTokens'] = augmentsSyntaxTokens;
    }
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    result['formats'] = formats.map((item) => item.toJson()).toList();
    if (multilineTokenSupport != null) {
      result['multilineTokenSupport'] = multilineTokenSupport;
    }
    if (overlappingTokenSupport != null) {
      result['overlappingTokenSupport'] = overlappingTokenSupport;
    }
    result['requests'] = requests.toJson();
    if (serverCancelSupport != null) {
      result['serverCancelSupport'] = serverCancelSupport;
    }
    result['tokenModifiers'] = tokenModifiers;
    result['tokenTypes'] = tokenTypes;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseBool(obj, reporter, 'augmentsSyntaxTokens',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'dynamicRegistration',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseListTokenFormat(obj, reporter, 'formats',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'multilineTokenSupport',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'overlappingTokenSupport',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseSemanticTokensClientCapabilitiesRequests(
          obj, reporter, 'requests',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'serverCancelSupport',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseListString(obj, reporter, 'tokenModifiers',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseListString(obj, reporter, 'tokenTypes',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type SemanticTokensClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SemanticTokensClientCapabilities &&
        other.runtimeType == SemanticTokensClientCapabilities &&
        augmentsSyntaxTokens == other.augmentsSyntaxTokens &&
        dynamicRegistration == other.dynamicRegistration &&
        listEqual(
            formats, other.formats, (TokenFormat a, TokenFormat b) => a == b) &&
        multilineTokenSupport == other.multilineTokenSupport &&
        overlappingTokenSupport == other.overlappingTokenSupport &&
        requests == other.requests &&
        serverCancelSupport == other.serverCancelSupport &&
        listEqual(tokenModifiers, other.tokenModifiers,
            (String a, String b) => a == b) &&
        listEqual(tokenTypes, other.tokenTypes, (String a, String b) => a == b);
  }

  @override
  int get hashCode => Object.hash(
        augmentsSyntaxTokens,
        dynamicRegistration,
        lspHashCode(formats),
        multilineTokenSupport,
        overlappingTokenSupport,
        requests,
        serverCancelSupport,
        lspHashCode(tokenModifiers),
        lspHashCode(tokenTypes),
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SemanticTokensClientCapabilitiesRequests implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SemanticTokensClientCapabilitiesRequests.canParse,
    SemanticTokensClientCapabilitiesRequests.fromJson,
  );

  SemanticTokensClientCapabilitiesRequests({
    this.full,
    this.range,
  });
  static SemanticTokensClientCapabilitiesRequests fromJson(
      Map<String, Object?> json) {
    final fullJson = json['full'];
    final full = fullJson == null
        ? null
        : _eitherBoolSemanticTokensClientCapabilitiesRequestsFull(fullJson);
    final rangeJson = json['range'];
    final range = rangeJson == null
        ? null
        : _eitherBoolSemanticTokensClientCapabilitiesRequestsRange(rangeJson);
    return SemanticTokensClientCapabilitiesRequests(
      full: full,
      range: range,
    );
  }

  /// The client will send the `textDocument/semanticTokens/full` request if the
  /// server provides a corresponding handler.
  final Either2<bool, SemanticTokensClientCapabilitiesRequestsFull>? full;

  /// The client will send the `textDocument/semanticTokens/range` request if
  /// the server provides a corresponding handler.
  final Either2<bool, SemanticTokensClientCapabilitiesRequestsRange>? range;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (full != null) {
      result['full'] = full;
    }
    if (range != null) {
      result['range'] = range;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseBoolSemanticTokensClientCapabilitiesRequestsFull(
          obj, reporter, 'full',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseBoolSemanticTokensClientCapabilitiesRequestsRange(
          obj, reporter, 'range',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError(
          'must be of type SemanticTokensClientCapabilitiesRequests');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SemanticTokensClientCapabilitiesRequests &&
        other.runtimeType == SemanticTokensClientCapabilitiesRequests &&
        full == other.full &&
        range == other.range;
  }

  @override
  int get hashCode => Object.hash(
        full,
        range,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SemanticTokensClientCapabilitiesRequestsFull implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SemanticTokensClientCapabilitiesRequestsFull.canParse,
    SemanticTokensClientCapabilitiesRequestsFull.fromJson,
  );

  SemanticTokensClientCapabilitiesRequestsFull({
    this.delta,
  });
  static SemanticTokensClientCapabilitiesRequestsFull fromJson(
      Map<String, Object?> json) {
    final deltaJson = json['delta'];
    final delta = deltaJson as bool?;
    return SemanticTokensClientCapabilitiesRequestsFull(
      delta: delta,
    );
  }

  /// The client will send the `textDocument/semanticTokens/full/delta` request
  /// if the server provides a corresponding handler.
  final bool? delta;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (delta != null) {
      result['delta'] = delta;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseBool(obj, reporter, 'delta',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError(
          'must be of type SemanticTokensClientCapabilitiesRequestsFull');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SemanticTokensClientCapabilitiesRequestsFull &&
        other.runtimeType == SemanticTokensClientCapabilitiesRequestsFull &&
        delta == other.delta;
  }

  @override
  int get hashCode => delta.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SemanticTokensClientCapabilitiesRequestsRange implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SemanticTokensClientCapabilitiesRequestsRange.canParse,
    SemanticTokensClientCapabilitiesRequestsRange.fromJson,
  );

  static SemanticTokensClientCapabilitiesRequestsRange fromJson(
      Map<String, Object?> json) {
    return SemanticTokensClientCapabilitiesRequestsRange();
  }

  @override
  Map<String, Object?> toJson() => {};

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return true;
    } else {
      reporter.reportError(
          'must be of type SemanticTokensClientCapabilitiesRequestsRange');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SemanticTokensClientCapabilitiesRequestsRange &&
        other.runtimeType == SemanticTokensClientCapabilitiesRequestsRange;
  }

  @override
  int get hashCode => 42;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// @since 3.16.0
class SemanticTokensDelta implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SemanticTokensDelta.canParse,
    SemanticTokensDelta.fromJson,
  );

  SemanticTokensDelta({
    required this.edits,
    this.resultId,
  });
  static SemanticTokensDelta fromJson(Map<String, Object?> json) {
    final editsJson = json['edits'];
    final edits = (editsJson as List<Object?>)
        .map(
            (item) => SemanticTokensEdit.fromJson(item as Map<String, Object?>))
        .toList();
    final resultIdJson = json['resultId'];
    final resultId = resultIdJson as String?;
    return SemanticTokensDelta(
      edits: edits,
      resultId: resultId,
    );
  }

  /// The semantic token edits to transform a previous result into a new result.
  final List<SemanticTokensEdit> edits;
  final String? resultId;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['edits'] = edits.map((item) => item.toJson()).toList();
    if (resultId != null) {
      result['resultId'] = resultId;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListSemanticTokensEdit(obj, reporter, 'edits',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseString(obj, reporter, 'resultId',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type SemanticTokensDelta');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SemanticTokensDelta &&
        other.runtimeType == SemanticTokensDelta &&
        listEqual(edits, other.edits,
            (SemanticTokensEdit a, SemanticTokensEdit b) => a == b) &&
        resultId == other.resultId;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(edits),
        resultId,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// @since 3.16.0
class SemanticTokensDeltaParams
    implements PartialResultParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SemanticTokensDeltaParams.canParse,
    SemanticTokensDeltaParams.fromJson,
  );

  SemanticTokensDeltaParams({
    this.partialResultToken,
    required this.previousResultId,
    required this.textDocument,
    this.workDoneToken,
  });
  static SemanticTokensDeltaParams fromJson(Map<String, Object?> json) {
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : _eitherIntString(partialResultTokenJson);
    final previousResultIdJson = json['previousResultId'];
    final previousResultId = previousResultIdJson as String;
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken =
        workDoneTokenJson == null ? null : _eitherIntString(workDoneTokenJson);
    return SemanticTokensDeltaParams(
      partialResultToken: partialResultToken,
      previousResultId: previousResultId,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final ProgressToken? partialResultToken;

  /// The result id of a previous response. The result Id can either point to a
  /// full response or a delta response depending on what was received last.
  final String previousResultId;

  /// The text document.
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final ProgressToken? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    result['previousResultId'] = previousResultId;
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseIntString(obj, reporter, 'partialResultToken',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'previousResultId',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseIntString(obj, reporter, 'workDoneToken',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type SemanticTokensDeltaParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SemanticTokensDeltaParams &&
        other.runtimeType == SemanticTokensDeltaParams &&
        partialResultToken == other.partialResultToken &&
        previousResultId == other.previousResultId &&
        textDocument == other.textDocument &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        partialResultToken,
        previousResultId,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// @since 3.16.0
class SemanticTokensDeltaPartialResult implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SemanticTokensDeltaPartialResult.canParse,
    SemanticTokensDeltaPartialResult.fromJson,
  );

  SemanticTokensDeltaPartialResult({
    required this.edits,
  });
  static SemanticTokensDeltaPartialResult fromJson(Map<String, Object?> json) {
    final editsJson = json['edits'];
    final edits = (editsJson as List<Object?>)
        .map(
            (item) => SemanticTokensEdit.fromJson(item as Map<String, Object?>))
        .toList();
    return SemanticTokensDeltaPartialResult(
      edits: edits,
    );
  }

  final List<SemanticTokensEdit> edits;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['edits'] = edits.map((item) => item.toJson()).toList();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseListSemanticTokensEdit(obj, reporter, 'edits',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type SemanticTokensDeltaPartialResult');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SemanticTokensDeltaPartialResult &&
        other.runtimeType == SemanticTokensDeltaPartialResult &&
        listEqual(edits, other.edits,
            (SemanticTokensEdit a, SemanticTokensEdit b) => a == b);
  }

  @override
  int get hashCode => lspHashCode(edits);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// @since 3.16.0
class SemanticTokensEdit implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SemanticTokensEdit.canParse,
    SemanticTokensEdit.fromJson,
  );

  SemanticTokensEdit({
    this.data,
    required this.deleteCount,
    required this.start,
  });
  static SemanticTokensEdit fromJson(Map<String, Object?> json) {
    final dataJson = json['data'];
    final data =
        (dataJson as List<Object?>?)?.map((item) => item as int).toList();
    final deleteCountJson = json['deleteCount'];
    final deleteCount = deleteCountJson as int;
    final startJson = json['start'];
    final start = startJson as int;
    return SemanticTokensEdit(
      data: data,
      deleteCount: deleteCount,
      start: start,
    );
  }

  /// The elements to insert.
  final List<int>? data;

  /// The count of elements to remove.
  final int deleteCount;

  /// The start offset of the edit.
  final int start;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (data != null) {
      result['data'] = data;
    }
    result['deleteCount'] = deleteCount;
    result['start'] = start;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListInt(obj, reporter, 'data',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseInt(obj, reporter, 'deleteCount',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseInt(obj, reporter, 'start',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type SemanticTokensEdit');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SemanticTokensEdit &&
        other.runtimeType == SemanticTokensEdit &&
        listEqual(data, other.data, (int a, int b) => a == b) &&
        deleteCount == other.deleteCount &&
        start == other.start;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(data),
        deleteCount,
        start,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// @since 3.16.0
class SemanticTokensLegend implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SemanticTokensLegend.canParse,
    SemanticTokensLegend.fromJson,
  );

  SemanticTokensLegend({
    required this.tokenModifiers,
    required this.tokenTypes,
  });
  static SemanticTokensLegend fromJson(Map<String, Object?> json) {
    final tokenModifiersJson = json['tokenModifiers'];
    final tokenModifiers = (tokenModifiersJson as List<Object?>)
        .map((item) => item as String)
        .toList();
    final tokenTypesJson = json['tokenTypes'];
    final tokenTypes = (tokenTypesJson as List<Object?>)
        .map((item) => item as String)
        .toList();
    return SemanticTokensLegend(
      tokenModifiers: tokenModifiers,
      tokenTypes: tokenTypes,
    );
  }

  /// The token modifiers a server uses.
  final List<String> tokenModifiers;

  /// The token types a server uses.
  final List<String> tokenTypes;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['tokenModifiers'] = tokenModifiers;
    result['tokenTypes'] = tokenTypes;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListString(obj, reporter, 'tokenModifiers',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseListString(obj, reporter, 'tokenTypes',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type SemanticTokensLegend');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SemanticTokensLegend &&
        other.runtimeType == SemanticTokensLegend &&
        listEqual(tokenModifiers, other.tokenModifiers,
            (String a, String b) => a == b) &&
        listEqual(tokenTypes, other.tokenTypes, (String a, String b) => a == b);
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(tokenModifiers),
        lspHashCode(tokenTypes),
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// @since 3.16.0
class SemanticTokensOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SemanticTokensOptions.canParse,
    SemanticTokensOptions.fromJson,
  );

  SemanticTokensOptions({
    this.full,
    required this.legend,
    this.range,
    this.workDoneProgress,
  });
  static SemanticTokensOptions fromJson(Map<String, Object?> json) {
    if (SemanticTokensRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return SemanticTokensRegistrationOptions.fromJson(json);
    }
    final fullJson = json['full'];
    final full = fullJson == null
        ? null
        : _eitherBoolSemanticTokensOptionsFull(fullJson);
    final legendJson = json['legend'];
    final legend =
        SemanticTokensLegend.fromJson(legendJson as Map<String, Object?>);
    final rangeJson = json['range'];
    final range = rangeJson == null
        ? null
        : _eitherBoolSemanticTokensOptionsRange(rangeJson);
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return SemanticTokensOptions(
      full: full,
      legend: legend,
      range: range,
      workDoneProgress: workDoneProgress,
    );
  }

  /// Server supports providing semantic tokens for a full document.
  final Either2<bool, SemanticTokensOptionsFull>? full;

  /// The legend used by the server
  final SemanticTokensLegend legend;

  /// Server supports providing semantic tokens for a specific range of a
  /// document.
  final Either2<bool, SemanticTokensOptionsRange>? range;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (full != null) {
      result['full'] = full;
    }
    result['legend'] = legend.toJson();
    if (range != null) {
      result['range'] = range;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseBoolSemanticTokensOptionsFull(obj, reporter, 'full',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseSemanticTokensLegend(obj, reporter, 'legend',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseBoolSemanticTokensOptionsRange(obj, reporter, 'range',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'workDoneProgress',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type SemanticTokensOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SemanticTokensOptions &&
        other.runtimeType == SemanticTokensOptions &&
        full == other.full &&
        legend == other.legend &&
        range == other.range &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        full,
        legend,
        range,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SemanticTokensOptionsFull implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SemanticTokensOptionsFull.canParse,
    SemanticTokensOptionsFull.fromJson,
  );

  SemanticTokensOptionsFull({
    this.delta,
  });
  static SemanticTokensOptionsFull fromJson(Map<String, Object?> json) {
    final deltaJson = json['delta'];
    final delta = deltaJson as bool?;
    return SemanticTokensOptionsFull(
      delta: delta,
    );
  }

  /// The server supports deltas for full documents.
  final bool? delta;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (delta != null) {
      result['delta'] = delta;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseBool(obj, reporter, 'delta',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type SemanticTokensOptionsFull');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SemanticTokensOptionsFull &&
        other.runtimeType == SemanticTokensOptionsFull &&
        delta == other.delta;
  }

  @override
  int get hashCode => delta.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SemanticTokensOptionsRange implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SemanticTokensOptionsRange.canParse,
    SemanticTokensOptionsRange.fromJson,
  );

  static SemanticTokensOptionsRange fromJson(Map<String, Object?> json) {
    return SemanticTokensOptionsRange();
  }

  @override
  Map<String, Object?> toJson() => {};

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return true;
    } else {
      reporter.reportError('must be of type SemanticTokensOptionsRange');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SemanticTokensOptionsRange &&
        other.runtimeType == SemanticTokensOptionsRange;
  }

  @override
  int get hashCode => 42;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// @since 3.16.0
class SemanticTokensParams
    implements PartialResultParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SemanticTokensParams.canParse,
    SemanticTokensParams.fromJson,
  );

  SemanticTokensParams({
    this.partialResultToken,
    required this.textDocument,
    this.workDoneToken,
  });
  static SemanticTokensParams fromJson(Map<String, Object?> json) {
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : _eitherIntString(partialResultTokenJson);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken =
        workDoneTokenJson == null ? null : _eitherIntString(workDoneTokenJson);
    return SemanticTokensParams(
      partialResultToken: partialResultToken,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final ProgressToken? partialResultToken;

  /// The text document.
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final ProgressToken? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseIntString(obj, reporter, 'partialResultToken',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseIntString(obj, reporter, 'workDoneToken',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type SemanticTokensParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SemanticTokensParams &&
        other.runtimeType == SemanticTokensParams &&
        partialResultToken == other.partialResultToken &&
        textDocument == other.textDocument &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        partialResultToken,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// @since 3.16.0
class SemanticTokensPartialResult implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SemanticTokensPartialResult.canParse,
    SemanticTokensPartialResult.fromJson,
  );

  SemanticTokensPartialResult({
    required this.data,
  });
  static SemanticTokensPartialResult fromJson(Map<String, Object?> json) {
    final dataJson = json['data'];
    final data =
        (dataJson as List<Object?>).map((item) => item as int).toList();
    return SemanticTokensPartialResult(
      data: data,
    );
  }

  final List<int> data;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['data'] = data;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseListInt(obj, reporter, 'data',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type SemanticTokensPartialResult');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SemanticTokensPartialResult &&
        other.runtimeType == SemanticTokensPartialResult &&
        listEqual(data, other.data, (int a, int b) => a == b);
  }

  @override
  int get hashCode => lspHashCode(data);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// @since 3.16.0
class SemanticTokensRangeParams
    implements PartialResultParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SemanticTokensRangeParams.canParse,
    SemanticTokensRangeParams.fromJson,
  );

  SemanticTokensRangeParams({
    this.partialResultToken,
    required this.range,
    required this.textDocument,
    this.workDoneToken,
  });
  static SemanticTokensRangeParams fromJson(Map<String, Object?> json) {
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : _eitherIntString(partialResultTokenJson);
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken =
        workDoneTokenJson == null ? null : _eitherIntString(workDoneTokenJson);
    return SemanticTokensRangeParams(
      partialResultToken: partialResultToken,
      range: range,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final ProgressToken? partialResultToken;

  /// The range the semantic tokens are requested for.
  final Range range;

  /// The text document.
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final ProgressToken? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    result['range'] = range.toJson();
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseIntString(obj, reporter, 'partialResultToken',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseRange(obj, reporter, 'range',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseIntString(obj, reporter, 'workDoneToken',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type SemanticTokensRangeParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SemanticTokensRangeParams &&
        other.runtimeType == SemanticTokensRangeParams &&
        partialResultToken == other.partialResultToken &&
        range == other.range &&
        textDocument == other.textDocument &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        partialResultToken,
        range,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// @since 3.16.0
class SemanticTokensRegistrationOptions
    implements
        SemanticTokensOptions,
        StaticRegistrationOptions,
        TextDocumentRegistrationOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SemanticTokensRegistrationOptions.canParse,
    SemanticTokensRegistrationOptions.fromJson,
  );

  SemanticTokensRegistrationOptions({
    this.documentSelector,
    this.full,
    this.id,
    required this.legend,
    this.range,
    this.workDoneProgress,
  });
  static SemanticTokensRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final fullJson = json['full'];
    final full = fullJson == null
        ? null
        : _eitherBoolSemanticTokensOptionsFull(fullJson);
    final idJson = json['id'];
    final id = idJson as String?;
    final legendJson = json['legend'];
    final legend =
        SemanticTokensLegend.fromJson(legendJson as Map<String, Object?>);
    final rangeJson = json['range'];
    final range = rangeJson == null
        ? null
        : _eitherBoolSemanticTokensOptionsRange(rangeJson);
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return SemanticTokensRegistrationOptions(
      documentSelector: documentSelector,
      full: full,
      id: id,
      legend: legend,
      range: range,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;

  /// Server supports providing semantic tokens for a full document.
  @override
  final Either2<bool, SemanticTokensOptionsFull>? full;

  /// The id used to register the request. The id can be used to deregister the
  /// request again. See also Registration#id.
  @override
  final String? id;

  /// The legend used by the server
  @override
  final SemanticTokensLegend legend;

  /// Server supports providing semantic tokens for a specific range of a
  /// document.
  @override
  final Either2<bool, SemanticTokensOptionsRange>? range;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (full != null) {
      result['full'] = full;
    }
    if (id != null) {
      result['id'] = id;
    }
    result['legend'] = legend.toJson();
    if (range != null) {
      result['range'] = range;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListTextDocumentFilterWithScheme(
          obj, reporter, 'documentSelector',
          allowsUndefined: false, allowsNull: true)) {
        return false;
      }
      if (!_canParseBoolSemanticTokensOptionsFull(obj, reporter, 'full',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'id',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseSemanticTokensLegend(obj, reporter, 'legend',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseBoolSemanticTokensOptionsRange(obj, reporter, 'range',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'workDoneProgress',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type SemanticTokensRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SemanticTokensRegistrationOptions &&
        other.runtimeType == SemanticTokensRegistrationOptions &&
        listEqual(
            documentSelector,
            other.documentSelector,
            (TextDocumentFilterWithScheme a, TextDocumentFilterWithScheme b) =>
                a == b) &&
        full == other.full &&
        id == other.id &&
        legend == other.legend &&
        range == other.range &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        full,
        id,
        legend,
        range,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// @since 3.16.0
class SemanticTokensWorkspaceClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SemanticTokensWorkspaceClientCapabilities.canParse,
    SemanticTokensWorkspaceClientCapabilities.fromJson,
  );

  SemanticTokensWorkspaceClientCapabilities({
    this.refreshSupport,
  });
  static SemanticTokensWorkspaceClientCapabilities fromJson(
      Map<String, Object?> json) {
    final refreshSupportJson = json['refreshSupport'];
    final refreshSupport = refreshSupportJson as bool?;
    return SemanticTokensWorkspaceClientCapabilities(
      refreshSupport: refreshSupport,
    );
  }

  /// Whether the client implementation supports a refresh request sent from the
  /// server to the client.
  ///
  /// Note that this event is global and will force the client to refresh all
  /// semantic tokens currently shown. It should be used with absolute care and
  /// is useful for situation where a server for example detects a project wide
  /// change that requires such a calculation.
  final bool? refreshSupport;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (refreshSupport != null) {
      result['refreshSupport'] = refreshSupport;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseBool(obj, reporter, 'refreshSupport',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError(
          'must be of type SemanticTokensWorkspaceClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SemanticTokensWorkspaceClientCapabilities &&
        other.runtimeType == SemanticTokensWorkspaceClientCapabilities &&
        refreshSupport == other.refreshSupport;
  }

  @override
  int get hashCode => refreshSupport.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Defines the capabilities provided by a language server.
class ServerCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ServerCapabilities.canParse,
    ServerCapabilities.fromJson,
  );

  ServerCapabilities({
    this.callHierarchyProvider,
    this.codeActionProvider,
    this.codeLensProvider,
    this.colorProvider,
    this.completionProvider,
    this.declarationProvider,
    this.definitionProvider,
    this.diagnosticProvider,
    this.documentFormattingProvider,
    this.documentHighlightProvider,
    this.documentLinkProvider,
    this.documentOnTypeFormattingProvider,
    this.documentRangeFormattingProvider,
    this.documentSymbolProvider,
    this.executeCommandProvider,
    this.experimental,
    this.foldingRangeProvider,
    this.hoverProvider,
    this.implementationProvider,
    this.inlayHintProvider,
    this.inlineValueProvider,
    this.linkedEditingRangeProvider,
    this.monikerProvider,
    this.notebookDocumentSync,
    this.positionEncoding,
    this.referencesProvider,
    this.renameProvider,
    this.selectionRangeProvider,
    this.semanticTokensProvider,
    this.signatureHelpProvider,
    this.textDocumentSync,
    this.typeDefinitionProvider,
    this.typeHierarchyProvider,
    this.workspace,
    this.workspaceSymbolProvider,
  });
  static ServerCapabilities fromJson(Map<String, Object?> json) {
    final callHierarchyProviderJson = json['callHierarchyProvider'];
    final callHierarchyProvider = callHierarchyProviderJson == null
        ? null
        : _eitherBoolCallHierarchyOptionsCallHierarchyRegistrationOptions(
            callHierarchyProviderJson);
    final codeActionProviderJson = json['codeActionProvider'];
    final codeActionProvider = codeActionProviderJson == null
        ? null
        : _eitherBoolCodeActionOptions(codeActionProviderJson);
    final codeLensProviderJson = json['codeLensProvider'];
    final codeLensProvider = codeLensProviderJson != null
        ? CodeLensOptions.fromJson(codeLensProviderJson as Map<String, Object?>)
        : null;
    final colorProviderJson = json['colorProvider'];
    final colorProvider = colorProviderJson == null
        ? null
        : _eitherBoolDocumentColorOptionsDocumentColorRegistrationOptions(
            colorProviderJson);
    final completionProviderJson = json['completionProvider'];
    final completionProvider = completionProviderJson != null
        ? CompletionOptions.fromJson(
            completionProviderJson as Map<String, Object?>)
        : null;
    final declarationProviderJson = json['declarationProvider'];
    final declarationProvider = declarationProviderJson == null
        ? null
        : _eitherBoolDeclarationOptionsDeclarationRegistrationOptions(
            declarationProviderJson);
    final definitionProviderJson = json['definitionProvider'];
    final definitionProvider = definitionProviderJson == null
        ? null
        : _eitherBoolDefinitionOptions(definitionProviderJson);
    final diagnosticProviderJson = json['diagnosticProvider'];
    final diagnosticProvider = diagnosticProviderJson == null
        ? null
        : _eitherDiagnosticOptionsDiagnosticRegistrationOptions(
            diagnosticProviderJson);
    final documentFormattingProviderJson = json['documentFormattingProvider'];
    final documentFormattingProvider = documentFormattingProviderJson == null
        ? null
        : _eitherBoolDocumentFormattingOptions(documentFormattingProviderJson);
    final documentHighlightProviderJson = json['documentHighlightProvider'];
    final documentHighlightProvider = documentHighlightProviderJson == null
        ? null
        : _eitherBoolDocumentHighlightOptions(documentHighlightProviderJson);
    final documentLinkProviderJson = json['documentLinkProvider'];
    final documentLinkProvider = documentLinkProviderJson != null
        ? DocumentLinkOptions.fromJson(
            documentLinkProviderJson as Map<String, Object?>)
        : null;
    final documentOnTypeFormattingProviderJson =
        json['documentOnTypeFormattingProvider'];
    final documentOnTypeFormattingProvider =
        documentOnTypeFormattingProviderJson != null
            ? DocumentOnTypeFormattingOptions.fromJson(
                documentOnTypeFormattingProviderJson as Map<String, Object?>)
            : null;
    final documentRangeFormattingProviderJson =
        json['documentRangeFormattingProvider'];
    final documentRangeFormattingProvider =
        documentRangeFormattingProviderJson == null
            ? null
            : _eitherBoolDocumentRangeFormattingOptions(
                documentRangeFormattingProviderJson);
    final documentSymbolProviderJson = json['documentSymbolProvider'];
    final documentSymbolProvider = documentSymbolProviderJson == null
        ? null
        : _eitherBoolDocumentSymbolOptions(documentSymbolProviderJson);
    final executeCommandProviderJson = json['executeCommandProvider'];
    final executeCommandProvider = executeCommandProviderJson != null
        ? ExecuteCommandOptions.fromJson(
            executeCommandProviderJson as Map<String, Object?>)
        : null;
    final experimentalJson = json['experimental'];
    final experimental = experimentalJson;
    final foldingRangeProviderJson = json['foldingRangeProvider'];
    final foldingRangeProvider = foldingRangeProviderJson == null
        ? null
        : _eitherBoolFoldingRangeOptionsFoldingRangeRegistrationOptions(
            foldingRangeProviderJson);
    final hoverProviderJson = json['hoverProvider'];
    final hoverProvider = hoverProviderJson == null
        ? null
        : _eitherBoolHoverOptions(hoverProviderJson);
    final implementationProviderJson = json['implementationProvider'];
    final implementationProvider = implementationProviderJson == null
        ? null
        : _eitherBoolImplementationOptionsImplementationRegistrationOptions(
            implementationProviderJson);
    final inlayHintProviderJson = json['inlayHintProvider'];
    final inlayHintProvider = inlayHintProviderJson == null
        ? null
        : _eitherBoolInlayHintOptionsInlayHintRegistrationOptions(
            inlayHintProviderJson);
    final inlineValueProviderJson = json['inlineValueProvider'];
    final inlineValueProvider = inlineValueProviderJson == null
        ? null
        : _eitherBoolInlineValueOptionsInlineValueRegistrationOptions(
            inlineValueProviderJson);
    final linkedEditingRangeProviderJson = json['linkedEditingRangeProvider'];
    final linkedEditingRangeProvider = linkedEditingRangeProviderJson == null
        ? null
        : _eitherBoolLinkedEditingRangeOptionsLinkedEditingRangeRegistrationOptions(
            linkedEditingRangeProviderJson);
    final monikerProviderJson = json['monikerProvider'];
    final monikerProvider = monikerProviderJson == null
        ? null
        : _eitherBoolMonikerOptionsMonikerRegistrationOptions(
            monikerProviderJson);
    final notebookDocumentSyncJson = json['notebookDocumentSync'];
    final notebookDocumentSync = notebookDocumentSyncJson == null
        ? null
        : _eitherNotebookDocumentSyncOptionsNotebookDocumentSyncRegistrationOptions(
            notebookDocumentSyncJson);
    final positionEncodingJson = json['positionEncoding'];
    final positionEncoding = positionEncodingJson != null
        ? PositionEncodingKind.fromJson(positionEncodingJson as String)
        : null;
    final referencesProviderJson = json['referencesProvider'];
    final referencesProvider = referencesProviderJson == null
        ? null
        : _eitherBoolReferenceOptions(referencesProviderJson);
    final renameProviderJson = json['renameProvider'];
    final renameProvider = renameProviderJson == null
        ? null
        : _eitherBoolRenameOptions(renameProviderJson);
    final selectionRangeProviderJson = json['selectionRangeProvider'];
    final selectionRangeProvider = selectionRangeProviderJson == null
        ? null
        : _eitherBoolSelectionRangeOptionsSelectionRangeRegistrationOptions(
            selectionRangeProviderJson);
    final semanticTokensProviderJson = json['semanticTokensProvider'];
    final semanticTokensProvider = semanticTokensProviderJson == null
        ? null
        : _eitherSemanticTokensOptionsSemanticTokensRegistrationOptions(
            semanticTokensProviderJson);
    final signatureHelpProviderJson = json['signatureHelpProvider'];
    final signatureHelpProvider = signatureHelpProviderJson != null
        ? SignatureHelpOptions.fromJson(
            signatureHelpProviderJson as Map<String, Object?>)
        : null;
    final textDocumentSyncJson = json['textDocumentSync'];
    final textDocumentSync = textDocumentSyncJson == null
        ? null
        : _eitherTextDocumentSyncKindTextDocumentSyncOptions(
            textDocumentSyncJson);
    final typeDefinitionProviderJson = json['typeDefinitionProvider'];
    final typeDefinitionProvider = typeDefinitionProviderJson == null
        ? null
        : _eitherBoolTypeDefinitionOptionsTypeDefinitionRegistrationOptions(
            typeDefinitionProviderJson);
    final typeHierarchyProviderJson = json['typeHierarchyProvider'];
    final typeHierarchyProvider = typeHierarchyProviderJson == null
        ? null
        : _eitherBoolTypeHierarchyOptionsTypeHierarchyRegistrationOptions(
            typeHierarchyProviderJson);
    final workspaceJson = json['workspace'];
    final workspace = workspaceJson != null
        ? ServerCapabilitiesWorkspace.fromJson(
            workspaceJson as Map<String, Object?>)
        : null;
    final workspaceSymbolProviderJson = json['workspaceSymbolProvider'];
    final workspaceSymbolProvider = workspaceSymbolProviderJson == null
        ? null
        : _eitherBoolWorkspaceSymbolOptions(workspaceSymbolProviderJson);
    return ServerCapabilities(
      callHierarchyProvider: callHierarchyProvider,
      codeActionProvider: codeActionProvider,
      codeLensProvider: codeLensProvider,
      colorProvider: colorProvider,
      completionProvider: completionProvider,
      declarationProvider: declarationProvider,
      definitionProvider: definitionProvider,
      diagnosticProvider: diagnosticProvider,
      documentFormattingProvider: documentFormattingProvider,
      documentHighlightProvider: documentHighlightProvider,
      documentLinkProvider: documentLinkProvider,
      documentOnTypeFormattingProvider: documentOnTypeFormattingProvider,
      documentRangeFormattingProvider: documentRangeFormattingProvider,
      documentSymbolProvider: documentSymbolProvider,
      executeCommandProvider: executeCommandProvider,
      experimental: experimental,
      foldingRangeProvider: foldingRangeProvider,
      hoverProvider: hoverProvider,
      implementationProvider: implementationProvider,
      inlayHintProvider: inlayHintProvider,
      inlineValueProvider: inlineValueProvider,
      linkedEditingRangeProvider: linkedEditingRangeProvider,
      monikerProvider: monikerProvider,
      notebookDocumentSync: notebookDocumentSync,
      positionEncoding: positionEncoding,
      referencesProvider: referencesProvider,
      renameProvider: renameProvider,
      selectionRangeProvider: selectionRangeProvider,
      semanticTokensProvider: semanticTokensProvider,
      signatureHelpProvider: signatureHelpProvider,
      textDocumentSync: textDocumentSync,
      typeDefinitionProvider: typeDefinitionProvider,
      typeHierarchyProvider: typeHierarchyProvider,
      workspace: workspace,
      workspaceSymbolProvider: workspaceSymbolProvider,
    );
  }

  /// The server provides call hierarchy support.
  ///
  /// @since 3.16.0
  final Either3<bool, CallHierarchyOptions, CallHierarchyRegistrationOptions>?
      callHierarchyProvider;

  /// The server provides code actions. CodeActionOptions may only be specified
  /// if the client states that it supports `codeActionLiteralSupport` in its
  /// initial `initialize` request.
  final Either2<bool, CodeActionOptions>? codeActionProvider;

  /// The server provides code lens.
  final CodeLensOptions? codeLensProvider;

  /// The server provides color provider support.
  final Either3<bool, DocumentColorOptions, DocumentColorRegistrationOptions>?
      colorProvider;

  /// The server provides completion support.
  final CompletionOptions? completionProvider;

  /// The server provides Goto Declaration support.
  final Either3<bool, DeclarationOptions, DeclarationRegistrationOptions>?
      declarationProvider;

  /// The server provides goto definition support.
  final Either2<bool, DefinitionOptions>? definitionProvider;

  /// The server has support for pull model diagnostics.
  ///
  /// @since 3.17.0
  final Either2<DiagnosticOptions, DiagnosticRegistrationOptions>?
      diagnosticProvider;

  /// The server provides document formatting.
  final Either2<bool, DocumentFormattingOptions>? documentFormattingProvider;

  /// The server provides document highlight support.
  final Either2<bool, DocumentHighlightOptions>? documentHighlightProvider;

  /// The server provides document link support.
  final DocumentLinkOptions? documentLinkProvider;

  /// The server provides document formatting on typing.
  final DocumentOnTypeFormattingOptions? documentOnTypeFormattingProvider;

  /// The server provides document range formatting.
  final Either2<bool, DocumentRangeFormattingOptions>?
      documentRangeFormattingProvider;

  /// The server provides document symbol support.
  final Either2<bool, DocumentSymbolOptions>? documentSymbolProvider;

  /// The server provides execute command support.
  final ExecuteCommandOptions? executeCommandProvider;

  /// Experimental server capabilities.
  final LSPAny experimental;

  /// The server provides folding provider support.
  final Either3<bool, FoldingRangeOptions, FoldingRangeRegistrationOptions>?
      foldingRangeProvider;

  /// The server provides hover support.
  final Either2<bool, HoverOptions>? hoverProvider;

  /// The server provides Goto Implementation support.
  final Either3<bool, ImplementationOptions, ImplementationRegistrationOptions>?
      implementationProvider;

  /// The server provides inlay hints.
  ///
  /// @since 3.17.0
  final Either3<bool, InlayHintOptions, InlayHintRegistrationOptions>?
      inlayHintProvider;

  /// The server provides inline values.
  ///
  /// @since 3.17.0
  final Either3<bool, InlineValueOptions, InlineValueRegistrationOptions>?
      inlineValueProvider;

  /// The server provides linked editing range support.
  ///
  /// @since 3.16.0
  final Either3<bool, LinkedEditingRangeOptions,
      LinkedEditingRangeRegistrationOptions>? linkedEditingRangeProvider;

  /// The server provides moniker support.
  ///
  /// @since 3.16.0
  final Either3<bool, MonikerOptions, MonikerRegistrationOptions>?
      monikerProvider;

  /// Defines how notebook documents are synced.
  ///
  /// @since 3.17.0
  final Either2<NotebookDocumentSyncOptions,
      NotebookDocumentSyncRegistrationOptions>? notebookDocumentSync;

  /// The position encoding the server picked from the encodings offered by the
  /// client via the client capability `general.positionEncodings`.
  ///
  /// If the client didn't provide any position encodings the only valid value
  /// that a server can return is 'utf-16'.
  ///
  /// If omitted it defaults to 'utf-16'.
  ///
  /// @since 3.17.0
  final PositionEncodingKind? positionEncoding;

  /// The server provides find references support.
  final Either2<bool, ReferenceOptions>? referencesProvider;

  /// The server provides rename support. RenameOptions may only be specified if
  /// the client states that it supports `prepareSupport` in its initial
  /// `initialize` request.
  final Either2<bool, RenameOptions>? renameProvider;

  /// The server provides selection range support.
  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.
  final Either2<TextDocumentSyncKind, TextDocumentSyncOptions>?
      textDocumentSync;

  /// The server provides Goto Type Definition support.
  final Either3<bool, TypeDefinitionOptions, TypeDefinitionRegistrationOptions>?
      typeDefinitionProvider;

  /// The server provides type hierarchy support.
  ///
  /// @since 3.17.0
  final Either3<bool, TypeHierarchyOptions, TypeHierarchyRegistrationOptions>?
      typeHierarchyProvider;

  /// Workspace specific server capabilities.
  final ServerCapabilitiesWorkspace? workspace;

  /// The server provides workspace symbol support.
  final Either2<bool, WorkspaceSymbolOptions>? workspaceSymbolProvider;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (callHierarchyProvider != null) {
      result['callHierarchyProvider'] = callHierarchyProvider;
    }
    if (codeActionProvider != null) {
      result['codeActionProvider'] = codeActionProvider;
    }
    if (codeLensProvider != null) {
      result['codeLensProvider'] = codeLensProvider?.toJson();
    }
    if (colorProvider != null) {
      result['colorProvider'] = colorProvider;
    }
    if (completionProvider != null) {
      result['completionProvider'] = completionProvider?.toJson();
    }
    if (declarationProvider != null) {
      result['declarationProvider'] = declarationProvider;
    }
    if (definitionProvider != null) {
      result['definitionProvider'] = definitionProvider;
    }
    if (diagnosticProvider != null) {
      result['diagnosticProvider'] = diagnosticProvider;
    }
    if (documentFormattingProvider != null) {
      result['documentFormattingProvider'] = documentFormattingProvider;
    }
    if (documentHighlightProvider != null) {
      result['documentHighlightProvider'] = documentHighlightProvider;
    }
    if (documentLinkProvider != null) {
      result['documentLinkProvider'] = documentLinkProvider?.toJson();
    }
    if (documentOnTypeFormattingProvider != null) {
      result['documentOnTypeFormattingProvider'] =
          documentOnTypeFormattingProvider?.toJson();
    }
    if (documentRangeFormattingProvider != null) {
      result['documentRangeFormattingProvider'] =
          documentRangeFormattingProvider;
    }
    if (documentSymbolProvider != null) {
      result['documentSymbolProvider'] = documentSymbolProvider;
    }
    if (executeCommandProvider != null) {
      result['executeCommandProvider'] = executeCommandProvider?.toJson();
    }
    if (experimental != null) {
      result['experimental'] = experimental;
    }
    if (foldingRangeProvider != null) {
      result['foldingRangeProvider'] = foldingRangeProvider;
    }
    if (hoverProvider != null) {
      result['hoverProvider'] = hoverProvider;
    }
    if (implementationProvider != null) {
      result['implementationProvider'] = implementationProvider;
    }
    if (inlayHintProvider != null) {
      result['inlayHintProvider'] = inlayHintProvider;
    }
    if (inlineValueProvider != null) {
      result['inlineValueProvider'] = inlineValueProvider;
    }
    if (linkedEditingRangeProvider != null) {
      result['linkedEditingRangeProvider'] = linkedEditingRangeProvider;
    }
    if (monikerProvider != null) {
      result['monikerProvider'] = monikerProvider;
    }
    if (notebookDocumentSync != null) {
      result['notebookDocumentSync'] = notebookDocumentSync;
    }
    if (positionEncoding != null) {
      result['positionEncoding'] = positionEncoding?.toJson();
    }
    if (referencesProvider != null) {
      result['referencesProvider'] = referencesProvider;
    }
    if (renameProvider != null) {
      result['renameProvider'] = renameProvider;
    }
    if (selectionRangeProvider != null) {
      result['selectionRangeProvider'] = selectionRangeProvider;
    }
    if (semanticTokensProvider != null) {
      result['semanticTokensProvider'] = semanticTokensProvider;
    }
    if (signatureHelpProvider != null) {
      result['signatureHelpProvider'] = signatureHelpProvider?.toJson();
    }
    if (textDocumentSync != null) {
      result['textDocumentSync'] = textDocumentSync;
    }
    if (typeDefinitionProvider != null) {
      result['typeDefinitionProvider'] = typeDefinitionProvider;
    }
    if (typeHierarchyProvider != null) {
      result['typeHierarchyProvider'] = typeHierarchyProvider;
    }
    if (workspace != null) {
      result['workspace'] = workspace?.toJson();
    }
    if (workspaceSymbolProvider != null) {
      result['workspaceSymbolProvider'] = workspaceSymbolProvider;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseBoolCallHierarchyOptionsCallHierarchyRegistrationOptions(
          obj, reporter, 'callHierarchyProvider',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBoolCodeActionOptions(obj, reporter, 'codeActionProvider',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseCodeLensOptions(obj, reporter, 'codeLensProvider',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBoolDocumentColorOptionsDocumentColorRegistrationOptions(
          obj, reporter, 'colorProvider',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseCompletionOptions(obj, reporter, 'completionProvider',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBoolDeclarationOptionsDeclarationRegistrationOptions(
          obj, reporter, 'declarationProvider',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBoolDefinitionOptions(obj, reporter, 'definitionProvider',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseDiagnosticOptionsDiagnosticRegistrationOptions(
          obj, reporter, 'diagnosticProvider',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBoolDocumentFormattingOptions(
          obj, reporter, 'documentFormattingProvider',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBoolDocumentHighlightOptions(
          obj, reporter, 'documentHighlightProvider',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseDocumentLinkOptions(obj, reporter, 'documentLinkProvider',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseDocumentOnTypeFormattingOptions(
          obj, reporter, 'documentOnTypeFormattingProvider',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBoolDocumentRangeFormattingOptions(
          obj, reporter, 'documentRangeFormattingProvider',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBoolDocumentSymbolOptions(
          obj, reporter, 'documentSymbolProvider',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseExecuteCommandOptions(
          obj, reporter, 'executeCommandProvider',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBoolFoldingRangeOptionsFoldingRangeRegistrationOptions(
          obj, reporter, 'foldingRangeProvider',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBoolHoverOptions(obj, reporter, 'hoverProvider',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBoolImplementationOptionsImplementationRegistrationOptions(
          obj, reporter, 'implementationProvider',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBoolInlayHintOptionsInlayHintRegistrationOptions(
          obj, reporter, 'inlayHintProvider',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBoolInlineValueOptionsInlineValueRegistrationOptions(
          obj, reporter, 'inlineValueProvider',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBoolLinkedEditingRangeOptionsLinkedEditingRangeRegistrationOptions(
          obj, reporter, 'linkedEditingRangeProvider',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBoolMonikerOptionsMonikerRegistrationOptions(
          obj, reporter, 'monikerProvider',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseNotebookDocumentSyncOptionsNotebookDocumentSyncRegistrationOptions(
          obj, reporter, 'notebookDocumentSync',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParsePositionEncodingKind(obj, reporter, 'positionEncoding',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBoolReferenceOptions(obj, reporter, 'referencesProvider',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBoolRenameOptions(obj, reporter, 'renameProvider',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBoolSelectionRangeOptionsSelectionRangeRegistrationOptions(
          obj, reporter, 'selectionRangeProvider',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseSemanticTokensOptionsSemanticTokensRegistrationOptions(
          obj, reporter, 'semanticTokensProvider',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseSignatureHelpOptions(obj, reporter, 'signatureHelpProvider',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseTextDocumentSyncKindTextDocumentSyncOptions(
          obj, reporter, 'textDocumentSync',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBoolTypeDefinitionOptionsTypeDefinitionRegistrationOptions(
          obj, reporter, 'typeDefinitionProvider',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBoolTypeHierarchyOptionsTypeHierarchyRegistrationOptions(
          obj, reporter, 'typeHierarchyProvider',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseServerCapabilitiesWorkspace(obj, reporter, 'workspace',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseBoolWorkspaceSymbolOptions(
          obj, reporter, 'workspaceSymbolProvider',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type ServerCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ServerCapabilities &&
        other.runtimeType == ServerCapabilities &&
        callHierarchyProvider == other.callHierarchyProvider &&
        codeActionProvider == other.codeActionProvider &&
        codeLensProvider == other.codeLensProvider &&
        colorProvider == other.colorProvider &&
        completionProvider == other.completionProvider &&
        declarationProvider == other.declarationProvider &&
        definitionProvider == other.definitionProvider &&
        diagnosticProvider == other.diagnosticProvider &&
        documentFormattingProvider == other.documentFormattingProvider &&
        documentHighlightProvider == other.documentHighlightProvider &&
        documentLinkProvider == other.documentLinkProvider &&
        documentOnTypeFormattingProvider ==
            other.documentOnTypeFormattingProvider &&
        documentRangeFormattingProvider ==
            other.documentRangeFormattingProvider &&
        documentSymbolProvider == other.documentSymbolProvider &&
        executeCommandProvider == other.executeCommandProvider &&
        experimental == other.experimental &&
        foldingRangeProvider == other.foldingRangeProvider &&
        hoverProvider == other.hoverProvider &&
        implementationProvider == other.implementationProvider &&
        inlayHintProvider == other.inlayHintProvider &&
        inlineValueProvider == other.inlineValueProvider &&
        linkedEditingRangeProvider == other.linkedEditingRangeProvider &&
        monikerProvider == other.monikerProvider &&
        notebookDocumentSync == other.notebookDocumentSync &&
        positionEncoding == other.positionEncoding &&
        referencesProvider == other.referencesProvider &&
        renameProvider == other.renameProvider &&
        selectionRangeProvider == other.selectionRangeProvider &&
        semanticTokensProvider == other.semanticTokensProvider &&
        signatureHelpProvider == other.signatureHelpProvider &&
        textDocumentSync == other.textDocumentSync &&
        typeDefinitionProvider == other.typeDefinitionProvider &&
        typeHierarchyProvider == other.typeHierarchyProvider &&
        workspace == other.workspace &&
        workspaceSymbolProvider == other.workspaceSymbolProvider;
  }

  @override
  int get hashCode => Object.hashAll([
        callHierarchyProvider,
        codeActionProvider,
        codeLensProvider,
        colorProvider,
        completionProvider,
        declarationProvider,
        definitionProvider,
        diagnosticProvider,
        documentFormattingProvider,
        documentHighlightProvider,
        documentLinkProvider,
        documentOnTypeFormattingProvider,
        documentRangeFormattingProvider,
        documentSymbolProvider,
        executeCommandProvider,
        experimental,
        foldingRangeProvider,
        hoverProvider,
        implementationProvider,
        inlayHintProvider,
        inlineValueProvider,
        linkedEditingRangeProvider,
        monikerProvider,
        notebookDocumentSync,
        positionEncoding,
        referencesProvider,
        renameProvider,
        selectionRangeProvider,
        semanticTokensProvider,
        signatureHelpProvider,
        textDocumentSync,
        typeDefinitionProvider,
        typeHierarchyProvider,
        workspace,
        workspaceSymbolProvider,
      ]);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class ServerCapabilitiesWorkspace implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ServerCapabilitiesWorkspace.canParse,
    ServerCapabilitiesWorkspace.fromJson,
  );

  ServerCapabilitiesWorkspace({
    this.fileOperations,
    this.workspaceFolders,
  });
  static ServerCapabilitiesWorkspace fromJson(Map<String, Object?> json) {
    final fileOperationsJson = json['fileOperations'];
    final fileOperations = fileOperationsJson != null
        ? FileOperationOptions.fromJson(
            fileOperationsJson as Map<String, Object?>)
        : null;
    final workspaceFoldersJson = json['workspaceFolders'];
    final workspaceFolders = workspaceFoldersJson != null
        ? WorkspaceFoldersServerCapabilities.fromJson(
            workspaceFoldersJson as Map<String, Object?>)
        : null;
    return ServerCapabilitiesWorkspace(
      fileOperations: fileOperations,
      workspaceFolders: workspaceFolders,
    );
  }

  /// The server is interested in notifications/requests for operations on
  /// files.
  ///
  /// @since 3.16.0
  final FileOperationOptions? fileOperations;

  /// The server supports workspace folder.
  ///
  /// @since 3.6.0
  final WorkspaceFoldersServerCapabilities? workspaceFolders;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (fileOperations != null) {
      result['fileOperations'] = fileOperations?.toJson();
    }
    if (workspaceFolders != null) {
      result['workspaceFolders'] = workspaceFolders?.toJson();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseFileOperationOptions(obj, reporter, 'fileOperations',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseWorkspaceFoldersServerCapabilities(
          obj, reporter, 'workspaceFolders',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type ServerCapabilitiesWorkspace');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ServerCapabilitiesWorkspace &&
        other.runtimeType == ServerCapabilitiesWorkspace &&
        fileOperations == other.fileOperations &&
        workspaceFolders == other.workspaceFolders;
  }

  @override
  int get hashCode => Object.hash(
        fileOperations,
        workspaceFolders,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SetTraceParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SetTraceParams.canParse,
    SetTraceParams.fromJson,
  );

  SetTraceParams({
    required this.value,
  });
  static SetTraceParams fromJson(Map<String, Object?> json) {
    final valueJson = json['value'];
    final value = TraceValues.fromJson(valueJson as String);
    return SetTraceParams(
      value: value,
    );
  }

  final TraceValues value;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['value'] = value.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseTraceValues(obj, reporter, 'value',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type SetTraceParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SetTraceParams &&
        other.runtimeType == SetTraceParams &&
        value == other.value;
  }

  @override
  int get hashCode => value.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Client capabilities for the showDocument request.
///
/// @since 3.16.0
class ShowDocumentClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ShowDocumentClientCapabilities.canParse,
    ShowDocumentClientCapabilities.fromJson,
  );

  ShowDocumentClientCapabilities({
    required this.support,
  });
  static ShowDocumentClientCapabilities fromJson(Map<String, Object?> json) {
    final supportJson = json['support'];
    final support = supportJson as bool;
    return ShowDocumentClientCapabilities(
      support: support,
    );
  }

  /// The client has support for the showDocument request.
  final bool support;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['support'] = support;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseBool(obj, reporter, 'support',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type ShowDocumentClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ShowDocumentClientCapabilities &&
        other.runtimeType == ShowDocumentClientCapabilities &&
        support == other.support;
  }

  @override
  int get hashCode => support.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Params to show a document.
///
/// @since 3.16.0
class ShowDocumentParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ShowDocumentParams.canParse,
    ShowDocumentParams.fromJson,
  );

  ShowDocumentParams({
    this.external,
    this.selection,
    this.takeFocus,
    required this.uri,
  });
  static ShowDocumentParams fromJson(Map<String, Object?> json) {
    final externalJson = json['external'];
    final external = externalJson as bool?;
    final selectionJson = json['selection'];
    final selection = selectionJson != null
        ? Range.fromJson(selectionJson as Map<String, Object?>)
        : null;
    final takeFocusJson = json['takeFocus'];
    final takeFocus = takeFocusJson as bool?;
    final uriJson = json['uri'];
    final uri = uriJson as String;
    return ShowDocumentParams(
      external: external,
      selection: selection,
      takeFocus: takeFocus,
      uri: uri,
    );
  }

  /// Indicates to show the resource in an external program. To show for example
  /// `https://code.visualstudio.com/` in the default WEB browser set `external`
  /// to `true`.
  final bool? external;

  /// An optional selection range if the document is a text document. Clients
  /// might ignore the property if an external program is started or the file is
  /// not a text file.
  final Range? selection;

  /// An optional property to indicate whether the editor showing the document
  /// should take focus or not. Clients might ignore this property if an
  /// external program is started.
  final bool? takeFocus;

  /// The document uri to show.
  final LspUri uri;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (external != null) {
      result['external'] = external;
    }
    if (selection != null) {
      result['selection'] = selection?.toJson();
    }
    if (takeFocus != null) {
      result['takeFocus'] = takeFocus;
    }
    result['uri'] = uri;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseBool(obj, reporter, 'external',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseRange(obj, reporter, 'selection',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'takeFocus',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseString(obj, reporter, 'uri',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type ShowDocumentParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ShowDocumentParams &&
        other.runtimeType == ShowDocumentParams &&
        external == other.external &&
        selection == other.selection &&
        takeFocus == other.takeFocus &&
        uri == other.uri;
  }

  @override
  int get hashCode => Object.hash(
        external,
        selection,
        takeFocus,
        uri,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The result of a showDocument request.
///
/// @since 3.16.0
class ShowDocumentResult implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ShowDocumentResult.canParse,
    ShowDocumentResult.fromJson,
  );

  ShowDocumentResult({
    required this.success,
  });
  static ShowDocumentResult fromJson(Map<String, Object?> json) {
    final successJson = json['success'];
    final success = successJson as bool;
    return ShowDocumentResult(
      success: success,
    );
  }

  /// A boolean indicating if the show was successful.
  final bool success;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['success'] = success;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseBool(obj, reporter, 'success',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type ShowDocumentResult');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ShowDocumentResult &&
        other.runtimeType == ShowDocumentResult &&
        success == other.success;
  }

  @override
  int get hashCode => success.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The parameters of a notification message.
class ShowMessageParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ShowMessageParams.canParse,
    ShowMessageParams.fromJson,
  );

  ShowMessageParams({
    required this.message,
    required this.type,
  });
  static ShowMessageParams fromJson(Map<String, Object?> json) {
    final messageJson = json['message'];
    final message = messageJson as String;
    final typeJson = json['type'];
    final type = MessageType.fromJson(typeJson as int);
    return ShowMessageParams(
      message: message,
      type: type,
    );
  }

  /// The actual message.
  final String message;

  /// The message type. See {@link MessageType}
  final MessageType type;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['message'] = message;
    result['type'] = type.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseString(obj, reporter, 'message',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseMessageType(obj, reporter, 'type',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type ShowMessageParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ShowMessageParams &&
        other.runtimeType == ShowMessageParams &&
        message == other.message &&
        type == other.type;
  }

  @override
  int get hashCode => Object.hash(
        message,
        type,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Show message request client capabilities
class ShowMessageRequestClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ShowMessageRequestClientCapabilities.canParse,
    ShowMessageRequestClientCapabilities.fromJson,
  );

  ShowMessageRequestClientCapabilities({
    this.messageActionItem,
  });
  static ShowMessageRequestClientCapabilities fromJson(
      Map<String, Object?> json) {
    final messageActionItemJson = json['messageActionItem'];
    final messageActionItem = messageActionItemJson != null
        ? ShowMessageRequestClientCapabilitiesMessageActionItem.fromJson(
            messageActionItemJson as Map<String, Object?>)
        : null;
    return ShowMessageRequestClientCapabilities(
      messageActionItem: messageActionItem,
    );
  }

  /// Capabilities specific to the `MessageActionItem` type.
  final ShowMessageRequestClientCapabilitiesMessageActionItem?
      messageActionItem;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (messageActionItem != null) {
      result['messageActionItem'] = messageActionItem?.toJson();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseShowMessageRequestClientCapabilitiesMessageActionItem(
          obj, reporter, 'messageActionItem',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter
          .reportError('must be of type ShowMessageRequestClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ShowMessageRequestClientCapabilities &&
        other.runtimeType == ShowMessageRequestClientCapabilities &&
        messageActionItem == other.messageActionItem;
  }

  @override
  int get hashCode => messageActionItem.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class ShowMessageRequestClientCapabilitiesMessageActionItem
    implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ShowMessageRequestClientCapabilitiesMessageActionItem.canParse,
    ShowMessageRequestClientCapabilitiesMessageActionItem.fromJson,
  );

  ShowMessageRequestClientCapabilitiesMessageActionItem({
    this.additionalPropertiesSupport,
  });
  static ShowMessageRequestClientCapabilitiesMessageActionItem fromJson(
      Map<String, Object?> json) {
    final additionalPropertiesSupportJson = json['additionalPropertiesSupport'];
    final additionalPropertiesSupport =
        additionalPropertiesSupportJson as bool?;
    return ShowMessageRequestClientCapabilitiesMessageActionItem(
      additionalPropertiesSupport: additionalPropertiesSupport,
    );
  }

  /// Whether the client supports additional attributes which are preserved and
  /// send back to the server in the request's response.
  final bool? additionalPropertiesSupport;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (additionalPropertiesSupport != null) {
      result['additionalPropertiesSupport'] = additionalPropertiesSupport;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseBool(obj, reporter, 'additionalPropertiesSupport',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError(
          'must be of type ShowMessageRequestClientCapabilitiesMessageActionItem');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ShowMessageRequestClientCapabilitiesMessageActionItem &&
        other.runtimeType ==
            ShowMessageRequestClientCapabilitiesMessageActionItem &&
        additionalPropertiesSupport == other.additionalPropertiesSupport;
  }

  @override
  int get hashCode => additionalPropertiesSupport.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class ShowMessageRequestParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    ShowMessageRequestParams.canParse,
    ShowMessageRequestParams.fromJson,
  );

  ShowMessageRequestParams({
    this.actions,
    required this.message,
    required this.type,
  });
  static ShowMessageRequestParams fromJson(Map<String, Object?> json) {
    final actionsJson = json['actions'];
    final actions = (actionsJson as List<Object?>?)
        ?.map(
            (item) => MessageActionItem.fromJson(item as Map<String, Object?>))
        .toList();
    final messageJson = json['message'];
    final message = messageJson as String;
    final typeJson = json['type'];
    final type = MessageType.fromJson(typeJson as int);
    return ShowMessageRequestParams(
      actions: actions,
      message: message,
      type: type,
    );
  }

  /// The message action items to present.
  final List<MessageActionItem>? actions;

  /// The actual message.
  final String message;

  /// The message type. See {@link MessageType}
  final MessageType type;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (actions != null) {
      result['actions'] = actions?.map((item) => item.toJson()).toList();
    }
    result['message'] = message;
    result['type'] = type.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListMessageActionItem(obj, reporter, 'actions',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'message',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseMessageType(obj, reporter, 'type',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type ShowMessageRequestParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is ShowMessageRequestParams &&
        other.runtimeType == ShowMessageRequestParams &&
        listEqual(actions, other.actions,
            (MessageActionItem a, MessageActionItem b) => a == b) &&
        message == other.message &&
        type == other.type;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(actions),
        message,
        type,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Signature help represents the signature of something callable. There can be
/// multiple signature but only one active and only one active parameter.
class SignatureHelp implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SignatureHelp.canParse,
    SignatureHelp.fromJson,
  );

  SignatureHelp({
    this.activeParameter,
    this.activeSignature,
    required this.signatures,
  });
  static SignatureHelp fromJson(Map<String, Object?> json) {
    final activeParameterJson = json['activeParameter'];
    final activeParameter = activeParameterJson as int?;
    final activeSignatureJson = json['activeSignature'];
    final activeSignature = activeSignatureJson as int?;
    final signaturesJson = json['signatures'];
    final signatures = (signaturesJson as List<Object?>)
        .map((item) =>
            SignatureInformation.fromJson(item as Map<String, Object?>))
        .toList();
    return SignatureHelp(
      activeParameter: activeParameter,
      activeSignature: activeSignature,
      signatures: signatures,
    );
  }

  /// The active parameter of the active signature. If omitted or the value lies
  /// outside the range of `signatures[activeSignature].parameters` defaults to
  /// 0 if the active signature has parameters. If the active signature has no
  /// parameters it is ignored. In future version of the protocol this property
  /// might become mandatory to better express the active parameter if the
  /// active signature does have any.
  final int? activeParameter;

  /// The active signature. If omitted or the value lies outside the range of
  /// `signatures` the value defaults to zero or is ignored if the
  /// `SignatureHelp` has no signatures.
  ///
  /// Whenever possible implementors should make an active decision about the
  /// active signature and shouldn't rely on a default value.
  ///
  /// In future version of the protocol this property might become mandatory to
  /// better express this.
  final int? activeSignature;

  /// One or more signatures.
  final List<SignatureInformation> signatures;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (activeParameter != null) {
      result['activeParameter'] = activeParameter;
    }
    if (activeSignature != null) {
      result['activeSignature'] = activeSignature;
    }
    result['signatures'] = signatures.map((item) => item.toJson()).toList();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseInt(obj, reporter, 'activeParameter',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseInt(obj, reporter, 'activeSignature',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseListSignatureInformation(obj, reporter, 'signatures',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type SignatureHelp');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SignatureHelp &&
        other.runtimeType == SignatureHelp &&
        activeParameter == other.activeParameter &&
        activeSignature == other.activeSignature &&
        listEqual(signatures, other.signatures,
            (SignatureInformation a, SignatureInformation b) => a == b);
  }

  @override
  int get hashCode => Object.hash(
        activeParameter,
        activeSignature,
        lspHashCode(signatures),
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Client Capabilities for a SignatureHelpRequest.
class SignatureHelpClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SignatureHelpClientCapabilities.canParse,
    SignatureHelpClientCapabilities.fromJson,
  );

  SignatureHelpClientCapabilities({
    this.contextSupport,
    this.dynamicRegistration,
    this.signatureInformation,
  });
  static SignatureHelpClientCapabilities fromJson(Map<String, Object?> json) {
    final contextSupportJson = json['contextSupport'];
    final contextSupport = contextSupportJson as bool?;
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    final signatureInformationJson = json['signatureInformation'];
    final signatureInformation = signatureInformationJson != null
        ? SignatureHelpClientCapabilitiesSignatureInformation.fromJson(
            signatureInformationJson as Map<String, Object?>)
        : null;
    return SignatureHelpClientCapabilities(
      contextSupport: contextSupport,
      dynamicRegistration: dynamicRegistration,
      signatureInformation: signatureInformation,
    );
  }

  /// The client supports to send additional context information for a
  /// `textDocument/signatureHelp` request. A client that opts into
  /// contextSupport will also support the `retriggerCharacters` on
  /// `SignatureHelpOptions`.
  ///
  /// @since 3.15.0
  final bool? contextSupport;

  /// Whether signature help supports dynamic registration.
  final bool? dynamicRegistration;

  /// The client supports the following `SignatureInformation` specific
  /// properties.
  final SignatureHelpClientCapabilitiesSignatureInformation?
      signatureInformation;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (contextSupport != null) {
      result['contextSupport'] = contextSupport;
    }
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    if (signatureInformation != null) {
      result['signatureInformation'] = signatureInformation?.toJson();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseBool(obj, reporter, 'contextSupport',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'dynamicRegistration',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseSignatureHelpClientCapabilitiesSignatureInformation(
          obj, reporter, 'signatureInformation',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type SignatureHelpClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SignatureHelpClientCapabilities &&
        other.runtimeType == SignatureHelpClientCapabilities &&
        contextSupport == other.contextSupport &&
        dynamicRegistration == other.dynamicRegistration &&
        signatureInformation == other.signatureInformation;
  }

  @override
  int get hashCode => Object.hash(
        contextSupport,
        dynamicRegistration,
        signatureInformation,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SignatureHelpClientCapabilitiesSignatureInformation
    implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SignatureHelpClientCapabilitiesSignatureInformation.canParse,
    SignatureHelpClientCapabilitiesSignatureInformation.fromJson,
  );

  SignatureHelpClientCapabilitiesSignatureInformation({
    this.activeParameterSupport,
    this.documentationFormat,
    this.parameterInformation,
  });
  static SignatureHelpClientCapabilitiesSignatureInformation fromJson(
      Map<String, Object?> json) {
    final activeParameterSupportJson = json['activeParameterSupport'];
    final activeParameterSupport = activeParameterSupportJson as bool?;
    final documentationFormatJson = json['documentationFormat'];
    final documentationFormat = (documentationFormatJson as List<Object?>?)
        ?.map((item) => MarkupKind.fromJson(item as String))
        .toList();
    final parameterInformationJson = json['parameterInformation'];
    final parameterInformation = parameterInformationJson != null
        ? SignatureInformationParameterInformation.fromJson(
            parameterInformationJson as Map<String, Object?>)
        : null;
    return SignatureHelpClientCapabilitiesSignatureInformation(
      activeParameterSupport: activeParameterSupport,
      documentationFormat: documentationFormat,
      parameterInformation: parameterInformation,
    );
  }

  /// The client supports the `activeParameter` property on
  /// `SignatureInformation` literal.
  ///
  /// @since 3.16.0
  final bool? activeParameterSupport;

  /// Client supports the following content formats for the documentation
  /// property. The order describes the preferred format of the client.
  final List<MarkupKind>? documentationFormat;

  /// Client capabilities specific to parameter information.
  final SignatureInformationParameterInformation? parameterInformation;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (activeParameterSupport != null) {
      result['activeParameterSupport'] = activeParameterSupport;
    }
    if (documentationFormat != null) {
      result['documentationFormat'] =
          documentationFormat?.map((item) => item.toJson()).toList();
    }
    if (parameterInformation != null) {
      result['parameterInformation'] = parameterInformation?.toJson();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseBool(obj, reporter, 'activeParameterSupport',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseListMarkupKind(obj, reporter, 'documentationFormat',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseSignatureInformationParameterInformation(
          obj, reporter, 'parameterInformation',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError(
          'must be of type SignatureHelpClientCapabilitiesSignatureInformation');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SignatureHelpClientCapabilitiesSignatureInformation &&
        other.runtimeType ==
            SignatureHelpClientCapabilitiesSignatureInformation &&
        activeParameterSupport == other.activeParameterSupport &&
        listEqual(documentationFormat, other.documentationFormat,
            (MarkupKind a, MarkupKind b) => a == b) &&
        parameterInformation == other.parameterInformation;
  }

  @override
  int get hashCode => Object.hash(
        activeParameterSupport,
        lspHashCode(documentationFormat),
        parameterInformation,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Additional information about the context in which a signature help request
/// was triggered.
///
/// @since 3.15.0
class SignatureHelpContext implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SignatureHelpContext.canParse,
    SignatureHelpContext.fromJson,
  );

  SignatureHelpContext({
    this.activeSignatureHelp,
    required this.isRetrigger,
    this.triggerCharacter,
    required this.triggerKind,
  });
  static SignatureHelpContext fromJson(Map<String, Object?> json) {
    final activeSignatureHelpJson = json['activeSignatureHelp'];
    final activeSignatureHelp = activeSignatureHelpJson != null
        ? SignatureHelp.fromJson(
            activeSignatureHelpJson as Map<String, Object?>)
        : null;
    final isRetriggerJson = json['isRetrigger'];
    final isRetrigger = isRetriggerJson as bool;
    final triggerCharacterJson = json['triggerCharacter'];
    final triggerCharacter = triggerCharacterJson as String?;
    final triggerKindJson = json['triggerKind'];
    final triggerKind =
        SignatureHelpTriggerKind.fromJson(triggerKindJson as int);
    return SignatureHelpContext(
      activeSignatureHelp: activeSignatureHelp,
      isRetrigger: isRetrigger,
      triggerCharacter: triggerCharacter,
      triggerKind: triggerKind,
    );
  }

  /// The currently active `SignatureHelp`.
  ///
  /// The `activeSignatureHelp` has its `SignatureHelp.activeSignature` field
  /// updated based on the user navigating through available signatures.
  final SignatureHelp? activeSignatureHelp;

  /// `true` if signature help was already showing when it was triggered.
  ///
  /// Retriggers occurs when the signature help is already active and can be
  /// caused by actions such as typing a trigger character, a cursor move, or
  /// document content changes.
  final bool isRetrigger;

  /// Character that caused signature help to be triggered.
  ///
  /// This is undefined when `triggerKind !==
  /// SignatureHelpTriggerKind.TriggerCharacter`
  final String? triggerCharacter;

  /// Action that caused signature help to be triggered.
  final SignatureHelpTriggerKind triggerKind;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (activeSignatureHelp != null) {
      result['activeSignatureHelp'] = activeSignatureHelp?.toJson();
    }
    result['isRetrigger'] = isRetrigger;
    if (triggerCharacter != null) {
      result['triggerCharacter'] = triggerCharacter;
    }
    result['triggerKind'] = triggerKind.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseSignatureHelp(obj, reporter, 'activeSignatureHelp',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'isRetrigger',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'triggerCharacter',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseSignatureHelpTriggerKind(obj, reporter, 'triggerKind',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type SignatureHelpContext');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SignatureHelpContext &&
        other.runtimeType == SignatureHelpContext &&
        activeSignatureHelp == other.activeSignatureHelp &&
        isRetrigger == other.isRetrigger &&
        triggerCharacter == other.triggerCharacter &&
        triggerKind == other.triggerKind;
  }

  @override
  int get hashCode => Object.hash(
        activeSignatureHelp,
        isRetrigger,
        triggerCharacter,
        triggerKind,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Server Capabilities for a SignatureHelpRequest.
class SignatureHelpOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SignatureHelpOptions.canParse,
    SignatureHelpOptions.fromJson,
  );

  SignatureHelpOptions({
    this.retriggerCharacters,
    this.triggerCharacters,
    this.workDoneProgress,
  });
  static SignatureHelpOptions fromJson(Map<String, Object?> json) {
    if (SignatureHelpRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return SignatureHelpRegistrationOptions.fromJson(json);
    }
    final retriggerCharactersJson = json['retriggerCharacters'];
    final retriggerCharacters = (retriggerCharactersJson as List<Object?>?)
        ?.map((item) => item as String)
        .toList();
    final triggerCharactersJson = json['triggerCharacters'];
    final triggerCharacters = (triggerCharactersJson as List<Object?>?)
        ?.map((item) => item as String)
        .toList();
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return SignatureHelpOptions(
      retriggerCharacters: retriggerCharacters,
      triggerCharacters: triggerCharacters,
      workDoneProgress: workDoneProgress,
    );
  }

  /// List of characters that re-trigger signature help.
  ///
  /// These trigger characters are only active when signature help is already
  /// showing. All trigger characters are also counted as re-trigger characters.
  ///
  /// @since 3.15.0
  final List<String>? retriggerCharacters;

  /// List of characters that trigger signature help automatically.
  final List<String>? triggerCharacters;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (retriggerCharacters != null) {
      result['retriggerCharacters'] = retriggerCharacters;
    }
    if (triggerCharacters != null) {
      result['triggerCharacters'] = triggerCharacters;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListString(obj, reporter, 'retriggerCharacters',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseListString(obj, reporter, 'triggerCharacters',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'workDoneProgress',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type SignatureHelpOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SignatureHelpOptions &&
        other.runtimeType == SignatureHelpOptions &&
        listEqual(retriggerCharacters, other.retriggerCharacters,
            (String a, String b) => a == b) &&
        listEqual(triggerCharacters, other.triggerCharacters,
            (String a, String b) => a == b) &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(retriggerCharacters),
        lspHashCode(triggerCharacters),
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Parameters for a SignatureHelpRequest.
class SignatureHelpParams
    implements TextDocumentPositionParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SignatureHelpParams.canParse,
    SignatureHelpParams.fromJson,
  );

  SignatureHelpParams({
    this.context,
    required this.position,
    required this.textDocument,
    this.workDoneToken,
  });
  static SignatureHelpParams fromJson(Map<String, Object?> json) {
    final contextJson = json['context'];
    final context = contextJson != null
        ? SignatureHelpContext.fromJson(contextJson as Map<String, Object?>)
        : null;
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken =
        workDoneTokenJson == null ? null : _eitherIntString(workDoneTokenJson);
    return SignatureHelpParams(
      context: context,
      position: position,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// The signature help context. This is only available if the client specifies
  /// to send this using the client capability
  /// `textDocument.signatureHelp.contextSupport === true`
  ///
  /// @since 3.15.0
  final SignatureHelpContext? context;

  /// The position inside the text document.
  @override
  final Position position;

  /// The text document.
  @override
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final ProgressToken? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (context != null) {
      result['context'] = context?.toJson();
    }
    result['position'] = position.toJson();
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseSignatureHelpContext(obj, reporter, 'context',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParsePosition(obj, reporter, 'position',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseIntString(obj, reporter, 'workDoneToken',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type SignatureHelpParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SignatureHelpParams &&
        other.runtimeType == SignatureHelpParams &&
        context == other.context &&
        position == other.position &&
        textDocument == other.textDocument &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        context,
        position,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Registration options for a SignatureHelpRequest.
class SignatureHelpRegistrationOptions
    implements
        SignatureHelpOptions,
        TextDocumentRegistrationOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SignatureHelpRegistrationOptions.canParse,
    SignatureHelpRegistrationOptions.fromJson,
  );

  SignatureHelpRegistrationOptions({
    this.documentSelector,
    this.retriggerCharacters,
    this.triggerCharacters,
    this.workDoneProgress,
  });
  static SignatureHelpRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final retriggerCharactersJson = json['retriggerCharacters'];
    final retriggerCharacters = (retriggerCharactersJson as List<Object?>?)
        ?.map((item) => item as String)
        .toList();
    final triggerCharactersJson = json['triggerCharacters'];
    final triggerCharacters = (triggerCharactersJson as List<Object?>?)
        ?.map((item) => item as String)
        .toList();
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return SignatureHelpRegistrationOptions(
      documentSelector: documentSelector,
      retriggerCharacters: retriggerCharacters,
      triggerCharacters: triggerCharacters,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;

  /// List of characters that re-trigger signature help.
  ///
  /// These trigger characters are only active when signature help is already
  /// showing. All trigger characters are also counted as re-trigger characters.
  ///
  /// @since 3.15.0
  @override
  final List<String>? retriggerCharacters;

  /// List of characters that trigger signature help automatically.
  @override
  final List<String>? triggerCharacters;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (retriggerCharacters != null) {
      result['retriggerCharacters'] = retriggerCharacters;
    }
    if (triggerCharacters != null) {
      result['triggerCharacters'] = triggerCharacters;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListTextDocumentFilterWithScheme(
          obj, reporter, 'documentSelector',
          allowsUndefined: false, allowsNull: true)) {
        return false;
      }
      if (!_canParseListString(obj, reporter, 'retriggerCharacters',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseListString(obj, reporter, 'triggerCharacters',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'workDoneProgress',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type SignatureHelpRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SignatureHelpRegistrationOptions &&
        other.runtimeType == SignatureHelpRegistrationOptions &&
        listEqual(
            documentSelector,
            other.documentSelector,
            (TextDocumentFilterWithScheme a, TextDocumentFilterWithScheme b) =>
                a == b) &&
        listEqual(retriggerCharacters, other.retriggerCharacters,
            (String a, String b) => a == b) &&
        listEqual(triggerCharacters, other.triggerCharacters,
            (String a, String b) => a == b) &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        lspHashCode(retriggerCharacters),
        lspHashCode(triggerCharacters),
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// How a signature help was triggered.
///
/// @since 3.15.0
class SignatureHelpTriggerKind implements ToJsonable {
  const SignatureHelpTriggerKind(this._value);
  const SignatureHelpTriggerKind.fromJson(this._value);

  final int _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is int;

  /// Signature help was triggered by the cursor moving or by the document
  /// content changing.
  static const ContentChange = SignatureHelpTriggerKind(3);

  /// Signature help was invoked manually by the user or by a command.
  static const Invoked = SignatureHelpTriggerKind(1);

  /// Signature help was triggered by a trigger character.
  static const TriggerCharacter = SignatureHelpTriggerKind(2);

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is SignatureHelpTriggerKind && other._value == _value;
}

/// Represents the signature of something callable. A signature can have a
/// label, like a function-name, a doc-comment, and a set of parameters.
class SignatureInformation implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SignatureInformation.canParse,
    SignatureInformation.fromJson,
  );

  SignatureInformation({
    this.activeParameter,
    this.documentation,
    required this.label,
    this.parameters,
  });
  static SignatureInformation fromJson(Map<String, Object?> json) {
    final activeParameterJson = json['activeParameter'];
    final activeParameter = activeParameterJson as int?;
    final documentationJson = json['documentation'];
    final documentation = documentationJson == null
        ? null
        : _eitherMarkupContentString(documentationJson);
    final labelJson = json['label'];
    final label = labelJson as String;
    final parametersJson = json['parameters'];
    final parameters = (parametersJson as List<Object?>?)
        ?.map((item) =>
            ParameterInformation.fromJson(item as Map<String, Object?>))
        .toList();
    return SignatureInformation(
      activeParameter: activeParameter,
      documentation: documentation,
      label: label,
      parameters: parameters,
    );
  }

  /// The index of the active parameter.
  ///
  /// If provided, this is used in place of `SignatureHelp.activeParameter`.
  ///
  /// @since 3.16.0
  final int? activeParameter;

  /// The human-readable doc-comment of this signature. Will be shown in the UI
  /// but can be omitted.
  final Either2<MarkupContent, String>? documentation;

  /// The label of this signature. Will be shown in the UI.
  final String label;

  /// The parameters of this signature.
  final List<ParameterInformation>? parameters;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (activeParameter != null) {
      result['activeParameter'] = activeParameter;
    }
    if (documentation != null) {
      result['documentation'] = documentation;
    }
    result['label'] = label;
    if (parameters != null) {
      result['parameters'] = parameters?.map((item) => item.toJson()).toList();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseInt(obj, reporter, 'activeParameter',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseMarkupContentString(obj, reporter, 'documentation',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'label',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseListParameterInformation(obj, reporter, 'parameters',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type SignatureInformation');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SignatureInformation &&
        other.runtimeType == SignatureInformation &&
        activeParameter == other.activeParameter &&
        documentation == other.documentation &&
        label == other.label &&
        listEqual(parameters, other.parameters,
            (ParameterInformation a, ParameterInformation b) => a == b);
  }

  @override
  int get hashCode => Object.hash(
        activeParameter,
        documentation,
        label,
        lspHashCode(parameters),
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class SignatureInformationParameterInformation implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SignatureInformationParameterInformation.canParse,
    SignatureInformationParameterInformation.fromJson,
  );

  SignatureInformationParameterInformation({
    this.labelOffsetSupport,
  });
  static SignatureInformationParameterInformation fromJson(
      Map<String, Object?> json) {
    final labelOffsetSupportJson = json['labelOffsetSupport'];
    final labelOffsetSupport = labelOffsetSupportJson as bool?;
    return SignatureInformationParameterInformation(
      labelOffsetSupport: labelOffsetSupport,
    );
  }

  /// The client supports processing label offsets instead of a simple label
  /// string.
  ///
  /// @since 3.14.0
  final bool? labelOffsetSupport;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (labelOffsetSupport != null) {
      result['labelOffsetSupport'] = labelOffsetSupport;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseBool(obj, reporter, 'labelOffsetSupport',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError(
          'must be of type SignatureInformationParameterInformation');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SignatureInformationParameterInformation &&
        other.runtimeType == SignatureInformationParameterInformation &&
        labelOffsetSupport == other.labelOffsetSupport;
  }

  @override
  int get hashCode => labelOffsetSupport.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Static registration options to be returned in the initialize request.
class StaticRegistrationOptions implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    StaticRegistrationOptions.canParse,
    StaticRegistrationOptions.fromJson,
  );

  StaticRegistrationOptions({
    this.id,
  });
  static StaticRegistrationOptions fromJson(Map<String, Object?> json) {
    if (CallHierarchyRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return CallHierarchyRegistrationOptions.fromJson(json);
    }
    if (DeclarationRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DeclarationRegistrationOptions.fromJson(json);
    }
    if (DiagnosticRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DiagnosticRegistrationOptions.fromJson(json);
    }
    if (DocumentColorRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentColorRegistrationOptions.fromJson(json);
    }
    if (FoldingRangeRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return FoldingRangeRegistrationOptions.fromJson(json);
    }
    if (ImplementationRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return ImplementationRegistrationOptions.fromJson(json);
    }
    if (InlayHintRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return InlayHintRegistrationOptions.fromJson(json);
    }
    if (InlineValueRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return InlineValueRegistrationOptions.fromJson(json);
    }
    if (LinkedEditingRangeRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return LinkedEditingRangeRegistrationOptions.fromJson(json);
    }
    if (NotebookDocumentSyncRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return NotebookDocumentSyncRegistrationOptions.fromJson(json);
    }
    if (SelectionRangeRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return SelectionRangeRegistrationOptions.fromJson(json);
    }
    if (SemanticTokensRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return SemanticTokensRegistrationOptions.fromJson(json);
    }
    if (TypeDefinitionRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return TypeDefinitionRegistrationOptions.fromJson(json);
    }
    if (TypeHierarchyRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return TypeHierarchyRegistrationOptions.fromJson(json);
    }
    final idJson = json['id'];
    final id = idJson as String?;
    return StaticRegistrationOptions(
      id: id,
    );
  }

  /// The id used to register the request. The id can be used to deregister the
  /// request again. See also Registration#id.
  final String? id;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (id != null) {
      result['id'] = id;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseString(obj, reporter, 'id',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type StaticRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is StaticRegistrationOptions &&
        other.runtimeType == StaticRegistrationOptions &&
        id == other.id;
  }

  @override
  int get hashCode => id.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Represents information about programming constructs like variables, classes,
/// interfaces etc.
class SymbolInformation implements BaseSymbolInformation, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    SymbolInformation.canParse,
    SymbolInformation.fromJson,
  );

  SymbolInformation({
    this.containerName,
    this.deprecated,
    required this.kind,
    required this.location,
    required this.name,
    this.tags,
  });
  static SymbolInformation fromJson(Map<String, Object?> json) {
    final containerNameJson = json['containerName'];
    final containerName = containerNameJson as String?;
    final deprecatedJson = json['deprecated'];
    final deprecated = deprecatedJson as bool?;
    final kindJson = json['kind'];
    final kind = SymbolKind.fromJson(kindJson as int);
    final locationJson = json['location'];
    final location = Location.fromJson(locationJson as Map<String, Object?>);
    final nameJson = json['name'];
    final name = nameJson as String;
    final tagsJson = json['tags'];
    final tags = (tagsJson as List<Object?>?)
        ?.map((item) => SymbolTag.fromJson(item as int))
        .toList();
    return SymbolInformation(
      containerName: containerName,
      deprecated: deprecated,
      kind: kind,
      location: location,
      name: name,
      tags: tags,
    );
  }

  /// The name of the symbol containing this symbol. This information is for
  /// user interface purposes (e.g. to render a qualifier in the user interface
  /// if necessary). It can't be used to re-infer a hierarchy for the document
  /// symbols.
  @override
  final String? containerName;

  /// Indicates if this symbol is deprecated.
  ///
  /// @deprecated Use tags instead
  final bool? deprecated;

  /// The kind of this symbol.
  @override
  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 than 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 an 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.
  @override
  final String name;

  /// Tags for this symbol.
  ///
  /// @since 3.16.0
  @override
  final List<SymbolTag>? tags;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (containerName != null) {
      result['containerName'] = containerName;
    }
    if (deprecated != null) {
      result['deprecated'] = deprecated;
    }
    result['kind'] = kind.toJson();
    result['location'] = location.toJson();
    result['name'] = name;
    if (tags != null) {
      result['tags'] = tags?.map((item) => item.toJson()).toList();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseString(obj, reporter, 'containerName',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'deprecated',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseSymbolKind(obj, reporter, 'kind',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseLocation(obj, reporter, 'location',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'name',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseListSymbolTag(obj, reporter, 'tags',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type SymbolInformation');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is SymbolInformation &&
        other.runtimeType == SymbolInformation &&
        containerName == other.containerName &&
        deprecated == other.deprecated &&
        kind == other.kind &&
        location == other.location &&
        name == other.name &&
        listEqual(tags, other.tags, (SymbolTag a, SymbolTag b) => a == b);
  }

  @override
  int get hashCode => Object.hash(
        containerName,
        deprecated,
        kind,
        location,
        name,
        lspHashCode(tags),
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A symbol kind.
class SymbolKind implements ToJsonable {
  const SymbolKind(this._value);
  const SymbolKind.fromJson(this._value);

  final int _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is int;
  static const Array = SymbolKind(18);
  static const Boolean = SymbolKind(17);
  static const Class = SymbolKind(5);
  static const Constant = SymbolKind(14);
  static const Constructor = SymbolKind(9);
  static const Enum = SymbolKind(10);
  static const EnumMember = SymbolKind(22);
  static const Event = SymbolKind(24);
  static const Field = SymbolKind(8);
  static const File = SymbolKind(1);
  static const Function = SymbolKind(12);
  static const Interface = SymbolKind(11);
  static const Key = SymbolKind(20);
  static const Method = SymbolKind(6);
  static const Module = SymbolKind(2);
  static const Namespace = SymbolKind(3);
  static const Null = SymbolKind(21);
  static const Number = SymbolKind(16);
  static const Obj = SymbolKind(19);
  static const Operator = SymbolKind(25);
  static const Package = SymbolKind(4);
  static const Property = SymbolKind(7);
  static const Str = SymbolKind(15);
  static const Struct = SymbolKind(23);
  static const TypeParameter = SymbolKind(26);
  static const Variable = SymbolKind(13);

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is SymbolKind && other._value == _value;
}

/// Symbol tags are extra annotations that tweak the rendering of a symbol.
///
/// @since 3.16
class SymbolTag implements ToJsonable {
  const SymbolTag(this._value);
  const SymbolTag.fromJson(this._value);

  final int _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is int;

  /// Render a symbol as obsolete, usually using a strike-out.
  static const Deprecated = SymbolTag(1);

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is SymbolTag && other._value == _value;
}

/// Describe options to be used when registered for text document change events.
class TextDocumentChangeRegistrationOptions
    implements TextDocumentRegistrationOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TextDocumentChangeRegistrationOptions.canParse,
    TextDocumentChangeRegistrationOptions.fromJson,
  );

  TextDocumentChangeRegistrationOptions({
    this.documentSelector,
    required this.syncKind,
  });
  static TextDocumentChangeRegistrationOptions fromJson(
      Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final syncKindJson = json['syncKind'];
    final syncKind = TextDocumentSyncKind.fromJson(syncKindJson as int);
    return TextDocumentChangeRegistrationOptions(
      documentSelector: documentSelector,
      syncKind: syncKind,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;

  /// How documents are synced to the server.
  final TextDocumentSyncKind syncKind;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    result['syncKind'] = syncKind.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListTextDocumentFilterWithScheme(
          obj, reporter, 'documentSelector',
          allowsUndefined: false, allowsNull: true)) {
        return false;
      }
      return _canParseTextDocumentSyncKind(obj, reporter, 'syncKind',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter
          .reportError('must be of type TextDocumentChangeRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is TextDocumentChangeRegistrationOptions &&
        other.runtimeType == TextDocumentChangeRegistrationOptions &&
        listEqual(
            documentSelector,
            other.documentSelector,
            (TextDocumentFilterWithScheme a, TextDocumentFilterWithScheme b) =>
                a == b) &&
        syncKind == other.syncKind;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        syncKind,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Text document specific client capabilities.
class TextDocumentClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TextDocumentClientCapabilities.canParse,
    TextDocumentClientCapabilities.fromJson,
  );

  TextDocumentClientCapabilities({
    this.callHierarchy,
    this.codeAction,
    this.codeLens,
    this.colorProvider,
    this.completion,
    this.declaration,
    this.definition,
    this.diagnostic,
    this.documentHighlight,
    this.documentLink,
    this.documentSymbol,
    this.foldingRange,
    this.formatting,
    this.hover,
    this.implementation,
    this.inlayHint,
    this.inlineValue,
    this.linkedEditingRange,
    this.moniker,
    this.onTypeFormatting,
    this.publishDiagnostics,
    this.rangeFormatting,
    this.references,
    this.rename,
    this.selectionRange,
    this.semanticTokens,
    this.signatureHelp,
    this.synchronization,
    this.typeDefinition,
    this.typeHierarchy,
  });
  static TextDocumentClientCapabilities fromJson(Map<String, Object?> json) {
    final callHierarchyJson = json['callHierarchy'];
    final callHierarchy = callHierarchyJson != null
        ? CallHierarchyClientCapabilities.fromJson(
            callHierarchyJson as Map<String, Object?>)
        : null;
    final codeActionJson = json['codeAction'];
    final codeAction = codeActionJson != null
        ? CodeActionClientCapabilities.fromJson(
            codeActionJson as Map<String, Object?>)
        : null;
    final codeLensJson = json['codeLens'];
    final codeLens = codeLensJson != null
        ? CodeLensClientCapabilities.fromJson(
            codeLensJson as Map<String, Object?>)
        : null;
    final colorProviderJson = json['colorProvider'];
    final colorProvider = colorProviderJson != null
        ? DocumentColorClientCapabilities.fromJson(
            colorProviderJson as Map<String, Object?>)
        : null;
    final completionJson = json['completion'];
    final completion = completionJson != null
        ? CompletionClientCapabilities.fromJson(
            completionJson as Map<String, Object?>)
        : null;
    final declarationJson = json['declaration'];
    final declaration = declarationJson != null
        ? DeclarationClientCapabilities.fromJson(
            declarationJson as Map<String, Object?>)
        : null;
    final definitionJson = json['definition'];
    final definition = definitionJson != null
        ? DefinitionClientCapabilities.fromJson(
            definitionJson as Map<String, Object?>)
        : null;
    final diagnosticJson = json['diagnostic'];
    final diagnostic = diagnosticJson != null
        ? DiagnosticClientCapabilities.fromJson(
            diagnosticJson as Map<String, Object?>)
        : null;
    final documentHighlightJson = json['documentHighlight'];
    final documentHighlight = documentHighlightJson != null
        ? DocumentHighlightClientCapabilities.fromJson(
            documentHighlightJson as Map<String, Object?>)
        : null;
    final documentLinkJson = json['documentLink'];
    final documentLink = documentLinkJson != null
        ? DocumentLinkClientCapabilities.fromJson(
            documentLinkJson as Map<String, Object?>)
        : null;
    final documentSymbolJson = json['documentSymbol'];
    final documentSymbol = documentSymbolJson != null
        ? DocumentSymbolClientCapabilities.fromJson(
            documentSymbolJson as Map<String, Object?>)
        : null;
    final foldingRangeJson = json['foldingRange'];
    final foldingRange = foldingRangeJson != null
        ? FoldingRangeClientCapabilities.fromJson(
            foldingRangeJson as Map<String, Object?>)
        : null;
    final formattingJson = json['formatting'];
    final formatting = formattingJson != null
        ? DocumentFormattingClientCapabilities.fromJson(
            formattingJson as Map<String, Object?>)
        : null;
    final hoverJson = json['hover'];
    final hover = hoverJson != null
        ? HoverClientCapabilities.fromJson(hoverJson as Map<String, Object?>)
        : null;
    final implementationJson = json['implementation'];
    final implementation = implementationJson != null
        ? ImplementationClientCapabilities.fromJson(
            implementationJson as Map<String, Object?>)
        : null;
    final inlayHintJson = json['inlayHint'];
    final inlayHint = inlayHintJson != null
        ? InlayHintClientCapabilities.fromJson(
            inlayHintJson as Map<String, Object?>)
        : null;
    final inlineValueJson = json['inlineValue'];
    final inlineValue = inlineValueJson != null
        ? InlineValueClientCapabilities.fromJson(
            inlineValueJson as Map<String, Object?>)
        : null;
    final linkedEditingRangeJson = json['linkedEditingRange'];
    final linkedEditingRange = linkedEditingRangeJson != null
        ? LinkedEditingRangeClientCapabilities.fromJson(
            linkedEditingRangeJson as Map<String, Object?>)
        : null;
    final monikerJson = json['moniker'];
    final moniker = monikerJson != null
        ? MonikerClientCapabilities.fromJson(
            monikerJson as Map<String, Object?>)
        : null;
    final onTypeFormattingJson = json['onTypeFormatting'];
    final onTypeFormatting = onTypeFormattingJson != null
        ? DocumentOnTypeFormattingClientCapabilities.fromJson(
            onTypeFormattingJson as Map<String, Object?>)
        : null;
    final publishDiagnosticsJson = json['publishDiagnostics'];
    final publishDiagnostics = publishDiagnosticsJson != null
        ? PublishDiagnosticsClientCapabilities.fromJson(
            publishDiagnosticsJson as Map<String, Object?>)
        : null;
    final rangeFormattingJson = json['rangeFormatting'];
    final rangeFormatting = rangeFormattingJson != null
        ? DocumentRangeFormattingClientCapabilities.fromJson(
            rangeFormattingJson as Map<String, Object?>)
        : null;
    final referencesJson = json['references'];
    final references = referencesJson != null
        ? ReferenceClientCapabilities.fromJson(
            referencesJson as Map<String, Object?>)
        : null;
    final renameJson = json['rename'];
    final rename = renameJson != null
        ? RenameClientCapabilities.fromJson(renameJson as Map<String, Object?>)
        : null;
    final selectionRangeJson = json['selectionRange'];
    final selectionRange = selectionRangeJson != null
        ? SelectionRangeClientCapabilities.fromJson(
            selectionRangeJson as Map<String, Object?>)
        : null;
    final semanticTokensJson = json['semanticTokens'];
    final semanticTokens = semanticTokensJson != null
        ? SemanticTokensClientCapabilities.fromJson(
            semanticTokensJson as Map<String, Object?>)
        : null;
    final signatureHelpJson = json['signatureHelp'];
    final signatureHelp = signatureHelpJson != null
        ? SignatureHelpClientCapabilities.fromJson(
            signatureHelpJson as Map<String, Object?>)
        : null;
    final synchronizationJson = json['synchronization'];
    final synchronization = synchronizationJson != null
        ? TextDocumentSyncClientCapabilities.fromJson(
            synchronizationJson as Map<String, Object?>)
        : null;
    final typeDefinitionJson = json['typeDefinition'];
    final typeDefinition = typeDefinitionJson != null
        ? TypeDefinitionClientCapabilities.fromJson(
            typeDefinitionJson as Map<String, Object?>)
        : null;
    final typeHierarchyJson = json['typeHierarchy'];
    final typeHierarchy = typeHierarchyJson != null
        ? TypeHierarchyClientCapabilities.fromJson(
            typeHierarchyJson as Map<String, Object?>)
        : null;
    return TextDocumentClientCapabilities(
      callHierarchy: callHierarchy,
      codeAction: codeAction,
      codeLens: codeLens,
      colorProvider: colorProvider,
      completion: completion,
      declaration: declaration,
      definition: definition,
      diagnostic: diagnostic,
      documentHighlight: documentHighlight,
      documentLink: documentLink,
      documentSymbol: documentSymbol,
      foldingRange: foldingRange,
      formatting: formatting,
      hover: hover,
      implementation: implementation,
      inlayHint: inlayHint,
      inlineValue: inlineValue,
      linkedEditingRange: linkedEditingRange,
      moniker: moniker,
      onTypeFormatting: onTypeFormatting,
      publishDiagnostics: publishDiagnostics,
      rangeFormatting: rangeFormatting,
      references: references,
      rename: rename,
      selectionRange: selectionRange,
      semanticTokens: semanticTokens,
      signatureHelp: signatureHelp,
      synchronization: synchronization,
      typeDefinition: typeDefinition,
      typeHierarchy: typeHierarchy,
    );
  }

  /// Capabilities specific to the various call hierarchy requests.
  ///
  /// @since 3.16.0
  final CallHierarchyClientCapabilities? callHierarchy;

  /// Capabilities specific to the `textDocument/codeAction` request.
  final CodeActionClientCapabilities? codeAction;

  /// Capabilities specific to the `textDocument/codeLens` request.
  final CodeLensClientCapabilities? codeLens;

  /// Capabilities specific to the `textDocument/documentColor` and the
  /// `textDocument/colorPresentation` request.
  ///
  /// @since 3.6.0
  final DocumentColorClientCapabilities? colorProvider;

  /// Capabilities specific to the `textDocument/completion` request.
  final CompletionClientCapabilities? completion;

  /// Capabilities specific to the `textDocument/declaration` request.
  ///
  /// @since 3.14.0
  final DeclarationClientCapabilities? declaration;

  /// Capabilities specific to the `textDocument/definition` request.
  final DefinitionClientCapabilities? definition;

  /// Capabilities specific to the diagnostic pull model.
  ///
  /// @since 3.17.0
  final DiagnosticClientCapabilities? diagnostic;

  /// Capabilities specific to the `textDocument/documentHighlight` request.
  final DocumentHighlightClientCapabilities? documentHighlight;

  /// Capabilities specific to the `textDocument/documentLink` request.
  final DocumentLinkClientCapabilities? documentLink;

  /// Capabilities specific to the `textDocument/documentSymbol` request.
  final DocumentSymbolClientCapabilities? documentSymbol;

  /// Capabilities specific to the `textDocument/foldingRange` request.
  ///
  /// @since 3.10.0
  final FoldingRangeClientCapabilities? foldingRange;

  /// Capabilities specific to the `textDocument/formatting` request.
  final DocumentFormattingClientCapabilities? formatting;

  /// Capabilities specific to the `textDocument/hover` request.
  final HoverClientCapabilities? hover;

  /// Capabilities specific to the `textDocument/implementation` request.
  ///
  /// @since 3.6.0
  final ImplementationClientCapabilities? implementation;

  /// Capabilities specific to the `textDocument/inlayHint` request.
  ///
  /// @since 3.17.0
  final InlayHintClientCapabilities? inlayHint;

  /// Capabilities specific to the `textDocument/inlineValue` request.
  ///
  /// @since 3.17.0
  final InlineValueClientCapabilities? inlineValue;

  /// Capabilities specific to the `textDocument/linkedEditingRange` request.
  ///
  /// @since 3.16.0
  final LinkedEditingRangeClientCapabilities? linkedEditingRange;

  /// Client capabilities specific to the `textDocument/moniker` request.
  ///
  /// @since 3.16.0
  final MonikerClientCapabilities? moniker;

  /// 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 request.
  ///
  /// @since 3.16.0
  final SemanticTokensClientCapabilities? semanticTokens;

  /// Capabilities specific to the `textDocument/signatureHelp` request.
  final SignatureHelpClientCapabilities? signatureHelp;

  /// Defines which synchronization capabilities the client supports.
  final TextDocumentSyncClientCapabilities? synchronization;

  /// Capabilities specific to the `textDocument/typeDefinition` request.
  ///
  /// @since 3.6.0
  final TypeDefinitionClientCapabilities? typeDefinition;

  /// Capabilities specific to the various type hierarchy requests.
  ///
  /// @since 3.17.0
  final TypeHierarchyClientCapabilities? typeHierarchy;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (callHierarchy != null) {
      result['callHierarchy'] = callHierarchy?.toJson();
    }
    if (codeAction != null) {
      result['codeAction'] = codeAction?.toJson();
    }
    if (codeLens != null) {
      result['codeLens'] = codeLens?.toJson();
    }
    if (colorProvider != null) {
      result['colorProvider'] = colorProvider?.toJson();
    }
    if (completion != null) {
      result['completion'] = completion?.toJson();
    }
    if (declaration != null) {
      result['declaration'] = declaration?.toJson();
    }
    if (definition != null) {
      result['definition'] = definition?.toJson();
    }
    if (diagnostic != null) {
      result['diagnostic'] = diagnostic?.toJson();
    }
    if (documentHighlight != null) {
      result['documentHighlight'] = documentHighlight?.toJson();
    }
    if (documentLink != null) {
      result['documentLink'] = documentLink?.toJson();
    }
    if (documentSymbol != null) {
      result['documentSymbol'] = documentSymbol?.toJson();
    }
    if (foldingRange != null) {
      result['foldingRange'] = foldingRange?.toJson();
    }
    if (formatting != null) {
      result['formatting'] = formatting?.toJson();
    }
    if (hover != null) {
      result['hover'] = hover?.toJson();
    }
    if (implementation != null) {
      result['implementation'] = implementation?.toJson();
    }
    if (inlayHint != null) {
      result['inlayHint'] = inlayHint?.toJson();
    }
    if (inlineValue != null) {
      result['inlineValue'] = inlineValue?.toJson();
    }
    if (linkedEditingRange != null) {
      result['linkedEditingRange'] = linkedEditingRange?.toJson();
    }
    if (moniker != null) {
      result['moniker'] = moniker?.toJson();
    }
    if (onTypeFormatting != null) {
      result['onTypeFormatting'] = onTypeFormatting?.toJson();
    }
    if (publishDiagnostics != null) {
      result['publishDiagnostics'] = publishDiagnostics?.toJson();
    }
    if (rangeFormatting != null) {
      result['rangeFormatting'] = rangeFormatting?.toJson();
    }
    if (references != null) {
      result['references'] = references?.toJson();
    }
    if (rename != null) {
      result['rename'] = rename?.toJson();
    }
    if (selectionRange != null) {
      result['selectionRange'] = selectionRange?.toJson();
    }
    if (semanticTokens != null) {
      result['semanticTokens'] = semanticTokens?.toJson();
    }
    if (signatureHelp != null) {
      result['signatureHelp'] = signatureHelp?.toJson();
    }
    if (synchronization != null) {
      result['synchronization'] = synchronization?.toJson();
    }
    if (typeDefinition != null) {
      result['typeDefinition'] = typeDefinition?.toJson();
    }
    if (typeHierarchy != null) {
      result['typeHierarchy'] = typeHierarchy?.toJson();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseCallHierarchyClientCapabilities(
          obj, reporter, 'callHierarchy',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseCodeActionClientCapabilities(obj, reporter, 'codeAction',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseCodeLensClientCapabilities(obj, reporter, 'codeLens',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseDocumentColorClientCapabilities(
          obj, reporter, 'colorProvider',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseCompletionClientCapabilities(obj, reporter, 'completion',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseDeclarationClientCapabilities(obj, reporter, 'declaration',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseDefinitionClientCapabilities(obj, reporter, 'definition',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseDiagnosticClientCapabilities(obj, reporter, 'diagnostic',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseDocumentHighlightClientCapabilities(
          obj, reporter, 'documentHighlight',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseDocumentLinkClientCapabilities(
          obj, reporter, 'documentLink',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseDocumentSymbolClientCapabilities(
          obj, reporter, 'documentSymbol',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseFoldingRangeClientCapabilities(
          obj, reporter, 'foldingRange',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseDocumentFormattingClientCapabilities(
          obj, reporter, 'formatting',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseHoverClientCapabilities(obj, reporter, 'hover',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseImplementationClientCapabilities(
          obj, reporter, 'implementation',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseInlayHintClientCapabilities(obj, reporter, 'inlayHint',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseInlineValueClientCapabilities(obj, reporter, 'inlineValue',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseLinkedEditingRangeClientCapabilities(
          obj, reporter, 'linkedEditingRange',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseMonikerClientCapabilities(obj, reporter, 'moniker',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseDocumentOnTypeFormattingClientCapabilities(
          obj, reporter, 'onTypeFormatting',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParsePublishDiagnosticsClientCapabilities(
          obj, reporter, 'publishDiagnostics',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseDocumentRangeFormattingClientCapabilities(
          obj, reporter, 'rangeFormatting',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseReferenceClientCapabilities(obj, reporter, 'references',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseRenameClientCapabilities(obj, reporter, 'rename',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseSelectionRangeClientCapabilities(
          obj, reporter, 'selectionRange',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseSemanticTokensClientCapabilities(
          obj, reporter, 'semanticTokens',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseSignatureHelpClientCapabilities(
          obj, reporter, 'signatureHelp',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseTextDocumentSyncClientCapabilities(
          obj, reporter, 'synchronization',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseTypeDefinitionClientCapabilities(
          obj, reporter, 'typeDefinition',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseTypeHierarchyClientCapabilities(
          obj, reporter, 'typeHierarchy',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type TextDocumentClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is TextDocumentClientCapabilities &&
        other.runtimeType == TextDocumentClientCapabilities &&
        callHierarchy == other.callHierarchy &&
        codeAction == other.codeAction &&
        codeLens == other.codeLens &&
        colorProvider == other.colorProvider &&
        completion == other.completion &&
        declaration == other.declaration &&
        definition == other.definition &&
        diagnostic == other.diagnostic &&
        documentHighlight == other.documentHighlight &&
        documentLink == other.documentLink &&
        documentSymbol == other.documentSymbol &&
        foldingRange == other.foldingRange &&
        formatting == other.formatting &&
        hover == other.hover &&
        implementation == other.implementation &&
        inlayHint == other.inlayHint &&
        inlineValue == other.inlineValue &&
        linkedEditingRange == other.linkedEditingRange &&
        moniker == other.moniker &&
        onTypeFormatting == other.onTypeFormatting &&
        publishDiagnostics == other.publishDiagnostics &&
        rangeFormatting == other.rangeFormatting &&
        references == other.references &&
        rename == other.rename &&
        selectionRange == other.selectionRange &&
        semanticTokens == other.semanticTokens &&
        signatureHelp == other.signatureHelp &&
        synchronization == other.synchronization &&
        typeDefinition == other.typeDefinition &&
        typeHierarchy == other.typeHierarchy;
  }

  @override
  int get hashCode => Object.hashAll([
        callHierarchy,
        codeAction,
        codeLens,
        colorProvider,
        completion,
        declaration,
        definition,
        diagnostic,
        documentHighlight,
        documentLink,
        documentSymbol,
        foldingRange,
        formatting,
        hover,
        implementation,
        inlayHint,
        inlineValue,
        linkedEditingRange,
        moniker,
        onTypeFormatting,
        publishDiagnostics,
        rangeFormatting,
        references,
        rename,
        selectionRange,
        semanticTokens,
        signatureHelp,
        synchronization,
        typeDefinition,
        typeHierarchy,
      ]);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class TextDocumentContentChangeEvent1 implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TextDocumentContentChangeEvent1.canParse,
    TextDocumentContentChangeEvent1.fromJson,
  );

  TextDocumentContentChangeEvent1({
    required this.range,
    this.rangeLength,
    required this.text,
  });
  static TextDocumentContentChangeEvent1 fromJson(Map<String, Object?> json) {
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    final rangeLengthJson = json['rangeLength'];
    final rangeLength = rangeLengthJson as int?;
    final textJson = json['text'];
    final text = textJson as String;
    return TextDocumentContentChangeEvent1(
      range: range,
      rangeLength: rangeLength,
      text: text,
    );
  }

  /// The range of the document that changed.
  final Range range;

  /// The optional length of the range that got replaced.
  ///
  /// @deprecated use range instead.
  final int? rangeLength;

  /// The new text for the provided range.
  final String text;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['range'] = range.toJson();
    if (rangeLength != null) {
      result['rangeLength'] = rangeLength;
    }
    result['text'] = text;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseRange(obj, reporter, 'range',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseInt(obj, reporter, 'rangeLength',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseString(obj, reporter, 'text',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type TextDocumentContentChangeEvent1');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is TextDocumentContentChangeEvent1 &&
        other.runtimeType == TextDocumentContentChangeEvent1 &&
        range == other.range &&
        rangeLength == other.rangeLength &&
        text == other.text;
  }

  @override
  int get hashCode => Object.hash(
        range,
        rangeLength,
        text,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class TextDocumentContentChangeEvent2 implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TextDocumentContentChangeEvent2.canParse,
    TextDocumentContentChangeEvent2.fromJson,
  );

  TextDocumentContentChangeEvent2({
    required this.text,
  });
  static TextDocumentContentChangeEvent2 fromJson(Map<String, Object?> json) {
    final textJson = json['text'];
    final text = textJson as String;
    return TextDocumentContentChangeEvent2(
      text: text,
    );
  }

  /// The new text of the whole document.
  final String text;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['text'] = text;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseString(obj, reporter, 'text',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type TextDocumentContentChangeEvent2');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is TextDocumentContentChangeEvent2 &&
        other.runtimeType == TextDocumentContentChangeEvent2 &&
        text == other.text;
  }

  @override
  int get hashCode => text.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Describes textual changes on a text document. A TextDocumentEdit describes
/// all changes on a document version Si and after they are applied move the
/// document to version Si+1. So the creator of a TextDocumentEdit doesn't need
/// to sort the array of edits or do any kind of ordering. However the edits
/// must be non overlapping.
class TextDocumentEdit implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TextDocumentEdit.canParse,
    TextDocumentEdit.fromJson,
  );

  TextDocumentEdit({
    required this.edits,
    required this.textDocument,
  });
  static TextDocumentEdit fromJson(Map<String, Object?> json) {
    final editsJson = json['edits'];
    final edits = (editsJson as List<Object?>)
        .map((item) => _eitherAnnotatedTextEditSnippetTextEditTextEdit(item))
        .toList();
    final textDocumentJson = json['textDocument'];
    final textDocument = OptionalVersionedTextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    return TextDocumentEdit(
      edits: edits,
      textDocument: textDocument,
    );
  }

  /// The edits to be applied.
  ///
  /// @since 3.16.0 - support for AnnotatedTextEdit. This is guarded using a
  /// client capability.
  final TextDocumentEditEdits edits;

  /// The text document to change.
  final OptionalVersionedTextDocumentIdentifier textDocument;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['edits'] = edits;
    result['textDocument'] = textDocument.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListAnnotatedTextEditSnippetTextEditTextEdit(
          obj, reporter, 'edits',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseOptionalVersionedTextDocumentIdentifier(
          obj, reporter, 'textDocument',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type TextDocumentEdit');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is TextDocumentEdit &&
        other.runtimeType == TextDocumentEdit &&
        listEqual(
            edits,
            other.edits,
            (Either3<AnnotatedTextEdit, SnippetTextEdit, TextEdit> a,
                    Either3<AnnotatedTextEdit, SnippetTextEdit, TextEdit> b) =>
                a == b) &&
        textDocument == other.textDocument;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(edits),
        textDocument,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class TextDocumentFilter1 implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TextDocumentFilter1.canParse,
    TextDocumentFilter1.fromJson,
  );

  TextDocumentFilter1({
    required this.language,
    this.pattern,
    this.scheme,
  });
  static TextDocumentFilter1 fromJson(Map<String, Object?> json) {
    final languageJson = json['language'];
    final language = languageJson as String;
    final patternJson = json['pattern'];
    final pattern = patternJson as String?;
    final schemeJson = json['scheme'];
    final scheme = schemeJson as String?;
    return TextDocumentFilter1(
      language: language,
      pattern: pattern,
      scheme: scheme,
    );
  }

  /// A language id, like `typescript`. */
  final String language;

  /// A glob pattern, like `*.{ts,js}`. */
  final String? pattern;

  /// A Uri scheme, like `file` or `untitled`. */
  final String? scheme;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['language'] = language;
    if (pattern != null) {
      result['pattern'] = pattern;
    }
    if (scheme != null) {
      result['scheme'] = scheme;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseString(obj, reporter, 'language',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'pattern',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseString(obj, reporter, 'scheme',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type TextDocumentFilter1');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is TextDocumentFilter1 &&
        other.runtimeType == TextDocumentFilter1 &&
        language == other.language &&
        pattern == other.pattern &&
        scheme == other.scheme;
  }

  @override
  int get hashCode => Object.hash(
        language,
        pattern,
        scheme,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class TextDocumentFilter3 implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TextDocumentFilter3.canParse,
    TextDocumentFilter3.fromJson,
  );

  TextDocumentFilter3({
    this.language,
    required this.pattern,
    this.scheme,
  });
  static TextDocumentFilter3 fromJson(Map<String, Object?> json) {
    final languageJson = json['language'];
    final language = languageJson as String?;
    final patternJson = json['pattern'];
    final pattern = patternJson as String;
    final schemeJson = json['scheme'];
    final scheme = schemeJson as String?;
    return TextDocumentFilter3(
      language: language,
      pattern: pattern,
      scheme: scheme,
    );
  }

  /// A language id, like `typescript`. */
  final String? language;

  /// A glob pattern, like `*.{ts,js}`. */
  final String pattern;

  /// A Uri scheme, like `file` or `untitled`. */
  final String? scheme;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (language != null) {
      result['language'] = language;
    }
    result['pattern'] = pattern;
    if (scheme != null) {
      result['scheme'] = scheme;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseString(obj, reporter, 'language',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'pattern',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseString(obj, reporter, 'scheme',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type TextDocumentFilter3');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is TextDocumentFilter3 &&
        other.runtimeType == TextDocumentFilter3 &&
        language == other.language &&
        pattern == other.pattern &&
        scheme == other.scheme;
  }

  @override
  int get hashCode => Object.hash(
        language,
        pattern,
        scheme,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class TextDocumentFilterWithScheme implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TextDocumentFilterWithScheme.canParse,
    TextDocumentFilterWithScheme.fromJson,
  );

  TextDocumentFilterWithScheme({
    this.language,
    this.pattern,
    required this.scheme,
  });
  static TextDocumentFilterWithScheme fromJson(Map<String, Object?> json) {
    final languageJson = json['language'];
    final language = languageJson as String?;
    final patternJson = json['pattern'];
    final pattern = patternJson as String?;
    final schemeJson = json['scheme'];
    final scheme = schemeJson as String;
    return TextDocumentFilterWithScheme(
      language: language,
      pattern: pattern,
      scheme: scheme,
    );
  }

  /// A language id, like `typescript`. */
  final String? language;

  /// A glob pattern, like `*.{ts,js}`. */
  final String? pattern;

  /// A Uri scheme, like `file` or `untitled`. */
  final String scheme;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (language != null) {
      result['language'] = language;
    }
    if (pattern != null) {
      result['pattern'] = pattern;
    }
    result['scheme'] = scheme;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseString(obj, reporter, 'language',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'pattern',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseString(obj, reporter, 'scheme',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type TextDocumentFilterWithScheme');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is TextDocumentFilterWithScheme &&
        other.runtimeType == TextDocumentFilterWithScheme &&
        language == other.language &&
        pattern == other.pattern &&
        scheme == other.scheme;
  }

  @override
  int get hashCode => Object.hash(
        language,
        pattern,
        scheme,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A literal to identify a text document in the client.
class TextDocumentIdentifier implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TextDocumentIdentifier.canParse,
    TextDocumentIdentifier.fromJson,
  );

  TextDocumentIdentifier({
    required this.uri,
  });
  static TextDocumentIdentifier fromJson(Map<String, Object?> json) {
    if (VersionedTextDocumentIdentifier.canParse(json, nullLspJsonReporter)) {
      return VersionedTextDocumentIdentifier.fromJson(json);
    }
    if (OptionalVersionedTextDocumentIdentifier.canParse(
        json, nullLspJsonReporter)) {
      return OptionalVersionedTextDocumentIdentifier.fromJson(json);
    }
    final uriJson = json['uri'];
    final uri = uriJson as String;
    return TextDocumentIdentifier(
      uri: uri,
    );
  }

  /// The text document's uri.
  final DocumentUri uri;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['uri'] = uri;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseString(obj, reporter, 'uri',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type TextDocumentIdentifier');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is TextDocumentIdentifier &&
        other.runtimeType == TextDocumentIdentifier &&
        uri == other.uri;
  }

  @override
  int get hashCode => uri.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// An item to transfer a text document from the client to the server.
class TextDocumentItem implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TextDocumentItem.canParse,
    TextDocumentItem.fromJson,
  );

  TextDocumentItem({
    required this.languageId,
    required this.text,
    required this.uri,
    required this.version,
  });
  static TextDocumentItem fromJson(Map<String, Object?> json) {
    final languageIdJson = json['languageId'];
    final languageId = languageIdJson as String;
    final textJson = json['text'];
    final text = textJson as String;
    final uriJson = json['uri'];
    final uri = uriJson as String;
    final versionJson = json['version'];
    final version = versionJson as int;
    return TextDocumentItem(
      languageId: languageId,
      text: text,
      uri: uri,
      version: version,
    );
  }

  /// The text document's language identifier.
  final String languageId;

  /// The content of the opened text document.
  final String text;

  /// The text document's uri.
  final DocumentUri uri;

  /// The version number of this document (it will increase after each change,
  /// including undo/redo).
  final int version;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['languageId'] = languageId;
    result['text'] = text;
    result['uri'] = uri;
    result['version'] = version;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseString(obj, reporter, 'languageId',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'text',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'uri',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseInt(obj, reporter, 'version',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type TextDocumentItem');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is TextDocumentItem &&
        other.runtimeType == TextDocumentItem &&
        languageId == other.languageId &&
        text == other.text &&
        uri == other.uri &&
        version == other.version;
  }

  @override
  int get hashCode => Object.hash(
        languageId,
        text,
        uri,
        version,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A parameter literal used in requests to pass a text document and a position
/// inside that document.
class TextDocumentPositionParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TextDocumentPositionParams.canParse,
    TextDocumentPositionParams.fromJson,
  );

  TextDocumentPositionParams({
    required this.position,
    required this.textDocument,
  });
  static TextDocumentPositionParams fromJson(Map<String, Object?> json) {
    if (ReferenceParams.canParse(json, nullLspJsonReporter)) {
      return ReferenceParams.fromJson(json);
    }
    if (CompletionParams.canParse(json, nullLspJsonReporter)) {
      return CompletionParams.fromJson(json);
    }
    if (SignatureHelpParams.canParse(json, nullLspJsonReporter)) {
      return SignatureHelpParams.fromJson(json);
    }
    if (CallHierarchyPrepareParams.canParse(json, nullLspJsonReporter)) {
      return CallHierarchyPrepareParams.fromJson(json);
    }
    if (DeclarationParams.canParse(json, nullLspJsonReporter)) {
      return DeclarationParams.fromJson(json);
    }
    if (DefinitionParams.canParse(json, nullLspJsonReporter)) {
      return DefinitionParams.fromJson(json);
    }
    if (DocumentHighlightParams.canParse(json, nullLspJsonReporter)) {
      return DocumentHighlightParams.fromJson(json);
    }
    if (HoverParams.canParse(json, nullLspJsonReporter)) {
      return HoverParams.fromJson(json);
    }
    if (ImplementationParams.canParse(json, nullLspJsonReporter)) {
      return ImplementationParams.fromJson(json);
    }
    if (LinkedEditingRangeParams.canParse(json, nullLspJsonReporter)) {
      return LinkedEditingRangeParams.fromJson(json);
    }
    if (MonikerParams.canParse(json, nullLspJsonReporter)) {
      return MonikerParams.fromJson(json);
    }
    if (PrepareRenameParams.canParse(json, nullLspJsonReporter)) {
      return PrepareRenameParams.fromJson(json);
    }
    if (TypeDefinitionParams.canParse(json, nullLspJsonReporter)) {
      return TypeDefinitionParams.fromJson(json);
    }
    if (TypeHierarchyPrepareParams.canParse(json, nullLspJsonReporter)) {
      return TypeHierarchyPrepareParams.fromJson(json);
    }
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    return TextDocumentPositionParams(
      position: position,
      textDocument: textDocument,
    );
  }

  /// The position inside the text document.
  final Position position;

  /// The text document.
  final TextDocumentIdentifier textDocument;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['position'] = position.toJson();
    result['textDocument'] = textDocument.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParsePosition(obj, reporter, 'position',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type TextDocumentPositionParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is TextDocumentPositionParams &&
        other.runtimeType == TextDocumentPositionParams &&
        position == other.position &&
        textDocument == other.textDocument;
  }

  @override
  int get hashCode => Object.hash(
        position,
        textDocument,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// General text document registration options.
class TextDocumentRegistrationOptions implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TextDocumentRegistrationOptions.canParse,
    TextDocumentRegistrationOptions.fromJson,
  );

  TextDocumentRegistrationOptions({
    this.documentSelector,
  });
  static TextDocumentRegistrationOptions fromJson(Map<String, Object?> json) {
    if (TextDocumentChangeRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return TextDocumentChangeRegistrationOptions.fromJson(json);
    }
    if (CallHierarchyRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return CallHierarchyRegistrationOptions.fromJson(json);
    }
    if (CodeActionRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return CodeActionRegistrationOptions.fromJson(json);
    }
    if (CodeLensRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return CodeLensRegistrationOptions.fromJson(json);
    }
    if (CompletionRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return CompletionRegistrationOptions.fromJson(json);
    }
    if (DeclarationRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DeclarationRegistrationOptions.fromJson(json);
    }
    if (DefinitionRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DefinitionRegistrationOptions.fromJson(json);
    }
    if (DiagnosticRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DiagnosticRegistrationOptions.fromJson(json);
    }
    if (DocumentColorRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentColorRegistrationOptions.fromJson(json);
    }
    if (DocumentFormattingRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return DocumentFormattingRegistrationOptions.fromJson(json);
    }
    if (DocumentHighlightRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return DocumentHighlightRegistrationOptions.fromJson(json);
    }
    if (DocumentLinkRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentLinkRegistrationOptions.fromJson(json);
    }
    if (DocumentOnTypeFormattingRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return DocumentOnTypeFormattingRegistrationOptions.fromJson(json);
    }
    if (DocumentRangeFormattingRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return DocumentRangeFormattingRegistrationOptions.fromJson(json);
    }
    if (DocumentSymbolRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentSymbolRegistrationOptions.fromJson(json);
    }
    if (FoldingRangeRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return FoldingRangeRegistrationOptions.fromJson(json);
    }
    if (HoverRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return HoverRegistrationOptions.fromJson(json);
    }
    if (ImplementationRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return ImplementationRegistrationOptions.fromJson(json);
    }
    if (InlayHintRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return InlayHintRegistrationOptions.fromJson(json);
    }
    if (InlineValueRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return InlineValueRegistrationOptions.fromJson(json);
    }
    if (LinkedEditingRangeRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return LinkedEditingRangeRegistrationOptions.fromJson(json);
    }
    if (MonikerRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return MonikerRegistrationOptions.fromJson(json);
    }
    if (ReferenceRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return ReferenceRegistrationOptions.fromJson(json);
    }
    if (RenameRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return RenameRegistrationOptions.fromJson(json);
    }
    if (SelectionRangeRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return SelectionRangeRegistrationOptions.fromJson(json);
    }
    if (SemanticTokensRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return SemanticTokensRegistrationOptions.fromJson(json);
    }
    if (SignatureHelpRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return SignatureHelpRegistrationOptions.fromJson(json);
    }
    if (TextDocumentSaveRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return TextDocumentSaveRegistrationOptions.fromJson(json);
    }
    if (TypeDefinitionRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return TypeDefinitionRegistrationOptions.fromJson(json);
    }
    if (TypeHierarchyRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return TypeHierarchyRegistrationOptions.fromJson(json);
    }
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    return TextDocumentRegistrationOptions(
      documentSelector: documentSelector,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  final List<TextDocumentFilterWithScheme>? documentSelector;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseListTextDocumentFilterWithScheme(
          obj, reporter, 'documentSelector',
          allowsUndefined: false, allowsNull: true);
    } else {
      reporter.reportError('must be of type TextDocumentRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is TextDocumentRegistrationOptions &&
        other.runtimeType == TextDocumentRegistrationOptions &&
        listEqual(
            documentSelector,
            other.documentSelector,
            (TextDocumentFilterWithScheme a, TextDocumentFilterWithScheme b) =>
                a == b);
  }

  @override
  int get hashCode => lspHashCode(documentSelector);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Represents reasons why a text document is saved.
class TextDocumentSaveReason implements ToJsonable {
  const TextDocumentSaveReason(this._value);
  const TextDocumentSaveReason.fromJson(this._value);

  final int _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is int;

  /// Automatic after a delay.
  static const AfterDelay = TextDocumentSaveReason(2);

  /// When the editor lost focus.
  static const FocusOut = TextDocumentSaveReason(3);

  /// Manually triggered, e.g. by the user pressing save, by starting debugging,
  /// or by an API call.
  static const Manual = TextDocumentSaveReason(1);

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is TextDocumentSaveReason && other._value == _value;
}

/// Save registration options.
class TextDocumentSaveRegistrationOptions
    implements SaveOptions, TextDocumentRegistrationOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TextDocumentSaveRegistrationOptions.canParse,
    TextDocumentSaveRegistrationOptions.fromJson,
  );

  TextDocumentSaveRegistrationOptions({
    this.documentSelector,
    this.includeText,
  });
  static TextDocumentSaveRegistrationOptions fromJson(
      Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final includeTextJson = json['includeText'];
    final includeText = includeTextJson as bool?;
    return TextDocumentSaveRegistrationOptions(
      documentSelector: documentSelector,
      includeText: includeText,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;

  /// The client is supposed to include the content on save.
  @override
  final bool? includeText;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (includeText != null) {
      result['includeText'] = includeText;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListTextDocumentFilterWithScheme(
          obj, reporter, 'documentSelector',
          allowsUndefined: false, allowsNull: true)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'includeText',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter
          .reportError('must be of type TextDocumentSaveRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is TextDocumentSaveRegistrationOptions &&
        other.runtimeType == TextDocumentSaveRegistrationOptions &&
        listEqual(
            documentSelector,
            other.documentSelector,
            (TextDocumentFilterWithScheme a, TextDocumentFilterWithScheme b) =>
                a == b) &&
        includeText == other.includeText;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        includeText,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class TextDocumentSyncClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TextDocumentSyncClientCapabilities.canParse,
    TextDocumentSyncClientCapabilities.fromJson,
  );

  TextDocumentSyncClientCapabilities({
    this.didSave,
    this.dynamicRegistration,
    this.willSave,
    this.willSaveWaitUntil,
  });
  static TextDocumentSyncClientCapabilities fromJson(
      Map<String, Object?> json) {
    final didSaveJson = json['didSave'];
    final didSave = didSaveJson as bool?;
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    final willSaveJson = json['willSave'];
    final willSave = willSaveJson as bool?;
    final willSaveWaitUntilJson = json['willSaveWaitUntil'];
    final willSaveWaitUntil = willSaveWaitUntilJson as bool?;
    return TextDocumentSyncClientCapabilities(
      didSave: didSave,
      dynamicRegistration: dynamicRegistration,
      willSave: willSave,
      willSaveWaitUntil: willSaveWaitUntil,
    );
  }

  /// The client supports did save notifications.
  final bool? didSave;

  /// Whether text document synchronization supports dynamic registration.
  final bool? dynamicRegistration;

  /// The client supports sending will save notifications.
  final bool? willSave;

  /// The client supports sending a will save request and waits for a response
  /// providing text edits which will be applied to the document before it is
  /// saved.
  final bool? willSaveWaitUntil;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (didSave != null) {
      result['didSave'] = didSave;
    }
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    if (willSave != null) {
      result['willSave'] = willSave;
    }
    if (willSaveWaitUntil != null) {
      result['willSaveWaitUntil'] = willSaveWaitUntil;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseBool(obj, reporter, 'didSave',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'dynamicRegistration',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'willSave',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'willSaveWaitUntil',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter
          .reportError('must be of type TextDocumentSyncClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is TextDocumentSyncClientCapabilities &&
        other.runtimeType == TextDocumentSyncClientCapabilities &&
        didSave == other.didSave &&
        dynamicRegistration == other.dynamicRegistration &&
        willSave == other.willSave &&
        willSaveWaitUntil == other.willSaveWaitUntil;
  }

  @override
  int get hashCode => Object.hash(
        didSave,
        dynamicRegistration,
        willSave,
        willSaveWaitUntil,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Defines how the host (editor) should sync document changes to the language
/// server.
class TextDocumentSyncKind implements ToJsonable {
  const TextDocumentSyncKind(this._value);
  const TextDocumentSyncKind.fromJson(this._value);

  final int _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is int;

  /// Documents are synced by always sending the full content of the document.
  static const Full = TextDocumentSyncKind(1);

  /// Documents are synced by sending the full content on open. After that only
  /// incremental updates to the document are send.
  static const Incremental = TextDocumentSyncKind(2);

  /// Documents should not be synced at all.
  static const None = TextDocumentSyncKind(0);

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is TextDocumentSyncKind && other._value == _value;
}

class TextDocumentSyncOptions implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TextDocumentSyncOptions.canParse,
    TextDocumentSyncOptions.fromJson,
  );

  TextDocumentSyncOptions({
    this.change,
    this.openClose,
    this.save,
    this.willSave,
    this.willSaveWaitUntil,
  });
  static TextDocumentSyncOptions fromJson(Map<String, Object?> json) {
    final changeJson = json['change'];
    final change = changeJson != null
        ? TextDocumentSyncKind.fromJson(changeJson as int)
        : null;
    final openCloseJson = json['openClose'];
    final openClose = openCloseJson as bool?;
    final saveJson = json['save'];
    final save = saveJson == null ? null : _eitherBoolSaveOptions(saveJson);
    final willSaveJson = json['willSave'];
    final willSave = willSaveJson as bool?;
    final willSaveWaitUntilJson = json['willSaveWaitUntil'];
    final willSaveWaitUntil = willSaveWaitUntilJson as bool?;
    return TextDocumentSyncOptions(
      change: change,
      openClose: openClose,
      save: save,
      willSave: willSave,
      willSaveWaitUntil: willSaveWaitUntil,
    );
  }

  /// Change notifications are sent to the server. See
  /// TextDocumentSyncKind.None, TextDocumentSyncKind.Full and
  /// TextDocumentSyncKind.Incremental. If omitted it defaults to
  /// TextDocumentSyncKind.None.
  final TextDocumentSyncKind? change;

  /// Open and close notifications are sent to the server. If omitted open close
  /// notification should not be sent.
  final bool? openClose;

  /// If present save notifications are sent to the server. If omitted the
  /// notification should not be sent.
  final Either2<bool, SaveOptions>? save;

  /// If present will save notifications are sent to the server. If omitted the
  /// notification should not be sent.
  final bool? willSave;

  /// If present will save wait until requests are sent to the server. If
  /// omitted the request should not be sent.
  final bool? willSaveWaitUntil;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (change != null) {
      result['change'] = change?.toJson();
    }
    if (openClose != null) {
      result['openClose'] = openClose;
    }
    if (save != null) {
      result['save'] = save;
    }
    if (willSave != null) {
      result['willSave'] = willSave;
    }
    if (willSaveWaitUntil != null) {
      result['willSaveWaitUntil'] = willSaveWaitUntil;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseTextDocumentSyncKind(obj, reporter, 'change',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'openClose',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBoolSaveOptions(obj, reporter, 'save',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'willSave',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'willSaveWaitUntil',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type TextDocumentSyncOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is TextDocumentSyncOptions &&
        other.runtimeType == TextDocumentSyncOptions &&
        change == other.change &&
        openClose == other.openClose &&
        save == other.save &&
        willSave == other.willSave &&
        willSaveWaitUntil == other.willSaveWaitUntil;
  }

  @override
  int get hashCode => Object.hash(
        change,
        openClose,
        save,
        willSave,
        willSaveWaitUntil,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A text edit applicable to a text document.
class TextEdit implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TextEdit.canParse,
    TextEdit.fromJson,
  );

  TextEdit({
    required this.newText,
    required this.range,
  });
  static TextEdit fromJson(Map<String, Object?> json) {
    if (AnnotatedTextEdit.canParse(json, nullLspJsonReporter)) {
      return AnnotatedTextEdit.fromJson(json);
    }
    if (SnippetTextEdit.canParse(json, nullLspJsonReporter)) {
      return SnippetTextEdit.fromJson(json);
    }
    final newTextJson = json['newText'];
    final newText = newTextJson as String;
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    return TextEdit(
      newText: newText,
      range: range,
    );
  }

  /// The string to be inserted. For delete operations use an empty string.
  final String newText;

  /// The range of the text document to be manipulated. To insert text into a
  /// document create a range where start === end.
  final Range range;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['newText'] = newText;
    result['range'] = range.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseString(obj, reporter, 'newText',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseRange(obj, reporter, 'range',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type TextEdit');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is TextEdit &&
        other.runtimeType == TextEdit &&
        newText == other.newText &&
        range == other.range;
  }

  @override
  int get hashCode => Object.hash(
        newText,
        range,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class TokenFormat implements ToJsonable {
  const TokenFormat(this._value);
  const TokenFormat.fromJson(this._value);

  final String _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is String;
  static const Relative = TokenFormat('relative');

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is TokenFormat && other._value == _value;
}

class TraceValues implements ToJsonable {
  const TraceValues(this._value);
  const TraceValues.fromJson(this._value);

  final String _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is String;

  /// Trace messages only.
  static const Messages = TraceValues('messages');

  /// Turn tracing off.
  static const Off = TraceValues('off');

  /// Verbose message tracing.
  static const Verbose = TraceValues('verbose');

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is TraceValues && other._value == _value;
}

/// Since 3.6.0
class TypeDefinitionClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TypeDefinitionClientCapabilities.canParse,
    TypeDefinitionClientCapabilities.fromJson,
  );

  TypeDefinitionClientCapabilities({
    this.dynamicRegistration,
    this.linkSupport,
  });
  static TypeDefinitionClientCapabilities fromJson(Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    final linkSupportJson = json['linkSupport'];
    final linkSupport = linkSupportJson as bool?;
    return TypeDefinitionClientCapabilities(
      dynamicRegistration: dynamicRegistration,
      linkSupport: linkSupport,
    );
  }

  /// Whether implementation supports dynamic registration. If this is set to
  /// `true` the client supports the new `TypeDefinitionRegistrationOptions`
  /// return value for the corresponding server capability as well.
  final bool? dynamicRegistration;

  /// The client supports additional metadata in the form of definition links.
  ///
  /// Since 3.14.0
  final bool? linkSupport;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    if (linkSupport != null) {
      result['linkSupport'] = linkSupport;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseBool(obj, reporter, 'dynamicRegistration',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'linkSupport',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type TypeDefinitionClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is TypeDefinitionClientCapabilities &&
        other.runtimeType == TypeDefinitionClientCapabilities &&
        dynamicRegistration == other.dynamicRegistration &&
        linkSupport == other.linkSupport;
  }

  @override
  int get hashCode => Object.hash(
        dynamicRegistration,
        linkSupport,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class TypeDefinitionOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TypeDefinitionOptions.canParse,
    TypeDefinitionOptions.fromJson,
  );

  TypeDefinitionOptions({
    this.workDoneProgress,
  });
  static TypeDefinitionOptions fromJson(Map<String, Object?> json) {
    if (TypeDefinitionRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return TypeDefinitionRegistrationOptions.fromJson(json);
    }
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return TypeDefinitionOptions(
      workDoneProgress: workDoneProgress,
    );
  }

  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseBool(obj, reporter, 'workDoneProgress',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type TypeDefinitionOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is TypeDefinitionOptions &&
        other.runtimeType == TypeDefinitionOptions &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => workDoneProgress.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class TypeDefinitionParams
    implements
        PartialResultParams,
        TextDocumentPositionParams,
        WorkDoneProgressParams,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TypeDefinitionParams.canParse,
    TypeDefinitionParams.fromJson,
  );

  TypeDefinitionParams({
    this.partialResultToken,
    required this.position,
    required this.textDocument,
    this.workDoneToken,
  });
  static TypeDefinitionParams fromJson(Map<String, Object?> json) {
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : _eitherIntString(partialResultTokenJson);
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken =
        workDoneTokenJson == null ? null : _eitherIntString(workDoneTokenJson);
    return TypeDefinitionParams(
      partialResultToken: partialResultToken,
      position: position,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final ProgressToken? partialResultToken;

  /// The position inside the text document.
  @override
  final Position position;

  /// The text document.
  @override
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final ProgressToken? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    result['position'] = position.toJson();
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseIntString(obj, reporter, 'partialResultToken',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParsePosition(obj, reporter, 'position',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseIntString(obj, reporter, 'workDoneToken',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type TypeDefinitionParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is TypeDefinitionParams &&
        other.runtimeType == TypeDefinitionParams &&
        partialResultToken == other.partialResultToken &&
        position == other.position &&
        textDocument == other.textDocument &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        partialResultToken,
        position,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class TypeDefinitionRegistrationOptions
    implements
        StaticRegistrationOptions,
        TextDocumentRegistrationOptions,
        TypeDefinitionOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TypeDefinitionRegistrationOptions.canParse,
    TypeDefinitionRegistrationOptions.fromJson,
  );

  TypeDefinitionRegistrationOptions({
    this.documentSelector,
    this.id,
    this.workDoneProgress,
  });
  static TypeDefinitionRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final idJson = json['id'];
    final id = idJson as String?;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return TypeDefinitionRegistrationOptions(
      documentSelector: documentSelector,
      id: id,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;

  /// The id used to register the request. The id can be used to deregister the
  /// request again. See also Registration#id.
  @override
  final String? id;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (id != null) {
      result['id'] = id;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListTextDocumentFilterWithScheme(
          obj, reporter, 'documentSelector',
          allowsUndefined: false, allowsNull: true)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'id',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'workDoneProgress',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type TypeDefinitionRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is TypeDefinitionRegistrationOptions &&
        other.runtimeType == TypeDefinitionRegistrationOptions &&
        listEqual(
            documentSelector,
            other.documentSelector,
            (TextDocumentFilterWithScheme a, TextDocumentFilterWithScheme b) =>
                a == b) &&
        id == other.id &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        id,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// @since 3.17.0
class TypeHierarchyClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TypeHierarchyClientCapabilities.canParse,
    TypeHierarchyClientCapabilities.fromJson,
  );

  TypeHierarchyClientCapabilities({
    this.dynamicRegistration,
  });
  static TypeHierarchyClientCapabilities fromJson(Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    return TypeHierarchyClientCapabilities(
      dynamicRegistration: dynamicRegistration,
    );
  }

  /// Whether implementation supports dynamic registration. If this is set to
  /// `true` the client supports the new `(TextDocumentRegistrationOptions &
  /// StaticRegistrationOptions)` return value for the corresponding server
  /// capability as well.
  final bool? dynamicRegistration;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseBool(obj, reporter, 'dynamicRegistration',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type TypeHierarchyClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is TypeHierarchyClientCapabilities &&
        other.runtimeType == TypeHierarchyClientCapabilities &&
        dynamicRegistration == other.dynamicRegistration;
  }

  @override
  int get hashCode => dynamicRegistration.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// @since 3.17.0
class TypeHierarchyItem implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TypeHierarchyItem.canParse,
    TypeHierarchyItem.fromJson,
  );

  TypeHierarchyItem({
    this.data,
    this.detail,
    required this.kind,
    required this.name,
    required this.range,
    required this.selectionRange,
    this.tags,
    required this.uri,
  });
  static TypeHierarchyItem fromJson(Map<String, Object?> json) {
    final dataJson = json['data'];
    final data = dataJson;
    final detailJson = json['detail'];
    final detail = detailJson as String?;
    final kindJson = json['kind'];
    final kind = SymbolKind.fromJson(kindJson as int);
    final nameJson = json['name'];
    final name = nameJson as String;
    final rangeJson = json['range'];
    final range = Range.fromJson(rangeJson as Map<String, Object?>);
    final selectionRangeJson = json['selectionRange'];
    final selectionRange =
        Range.fromJson(selectionRangeJson as Map<String, Object?>);
    final tagsJson = json['tags'];
    final tags = (tagsJson as List<Object?>?)
        ?.map((item) => SymbolTag.fromJson(item as int))
        .toList();
    final uriJson = json['uri'];
    final uri = uriJson as String;
    return TypeHierarchyItem(
      data: data,
      detail: detail,
      kind: kind,
      name: name,
      range: range,
      selectionRange: selectionRange,
      tags: tags,
      uri: uri,
    );
  }

  /// A data entry field that is preserved between a type hierarchy prepare and
  /// supertypes or subtypes requests. It could also be used to identify the
  /// type hierarchy in the server, helping improve the performance on resolving
  /// supertypes and subtypes.
  final LSPAny 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`.
  final Range selectionRange;

  /// Tags for this item.
  final List<SymbolTag>? tags;

  /// The resource identifier of this item.
  final DocumentUri uri;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (data != null) {
      result['data'] = data;
    }
    if (detail != null) {
      result['detail'] = detail;
    }
    result['kind'] = kind.toJson();
    result['name'] = name;
    result['range'] = range.toJson();
    result['selectionRange'] = selectionRange.toJson();
    if (tags != null) {
      result['tags'] = tags?.map((item) => item.toJson()).toList();
    }
    result['uri'] = uri;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseString(obj, reporter, 'detail',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseSymbolKind(obj, reporter, 'kind',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'name',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseRange(obj, reporter, 'range',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseRange(obj, reporter, 'selectionRange',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseListSymbolTag(obj, reporter, 'tags',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseString(obj, reporter, 'uri',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type TypeHierarchyItem');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is TypeHierarchyItem &&
        other.runtimeType == TypeHierarchyItem &&
        data == other.data &&
        detail == other.detail &&
        kind == other.kind &&
        name == other.name &&
        range == other.range &&
        selectionRange == other.selectionRange &&
        listEqual(tags, other.tags, (SymbolTag a, SymbolTag b) => a == b) &&
        uri == other.uri;
  }

  @override
  int get hashCode => Object.hash(
        data,
        detail,
        kind,
        name,
        range,
        selectionRange,
        lspHashCode(tags),
        uri,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Type hierarchy options used during static registration.
///
/// @since 3.17.0
class TypeHierarchyOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TypeHierarchyOptions.canParse,
    TypeHierarchyOptions.fromJson,
  );

  TypeHierarchyOptions({
    this.workDoneProgress,
  });
  static TypeHierarchyOptions fromJson(Map<String, Object?> json) {
    if (TypeHierarchyRegistrationOptions.canParse(json, nullLspJsonReporter)) {
      return TypeHierarchyRegistrationOptions.fromJson(json);
    }
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return TypeHierarchyOptions(
      workDoneProgress: workDoneProgress,
    );
  }

  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseBool(obj, reporter, 'workDoneProgress',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type TypeHierarchyOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is TypeHierarchyOptions &&
        other.runtimeType == TypeHierarchyOptions &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => workDoneProgress.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The parameter of a `textDocument/prepareTypeHierarchy` request.
///
/// @since 3.17.0
class TypeHierarchyPrepareParams
    implements TextDocumentPositionParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TypeHierarchyPrepareParams.canParse,
    TypeHierarchyPrepareParams.fromJson,
  );

  TypeHierarchyPrepareParams({
    required this.position,
    required this.textDocument,
    this.workDoneToken,
  });
  static TypeHierarchyPrepareParams fromJson(Map<String, Object?> json) {
    final positionJson = json['position'];
    final position = Position.fromJson(positionJson as Map<String, Object?>);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken =
        workDoneTokenJson == null ? null : _eitherIntString(workDoneTokenJson);
    return TypeHierarchyPrepareParams(
      position: position,
      textDocument: textDocument,
      workDoneToken: workDoneToken,
    );
  }

  /// The position inside the text document.
  @override
  final Position position;

  /// The text document.
  @override
  final TextDocumentIdentifier textDocument;

  /// An optional token that a server can use to report work done progress.
  @override
  final ProgressToken? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['position'] = position.toJson();
    result['textDocument'] = textDocument.toJson();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParsePosition(obj, reporter, 'position',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseIntString(obj, reporter, 'workDoneToken',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type TypeHierarchyPrepareParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is TypeHierarchyPrepareParams &&
        other.runtimeType == TypeHierarchyPrepareParams &&
        position == other.position &&
        textDocument == other.textDocument &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        position,
        textDocument,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Type hierarchy options used during static or dynamic registration.
///
/// @since 3.17.0
class TypeHierarchyRegistrationOptions
    implements
        StaticRegistrationOptions,
        TextDocumentRegistrationOptions,
        TypeHierarchyOptions,
        ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TypeHierarchyRegistrationOptions.canParse,
    TypeHierarchyRegistrationOptions.fromJson,
  );

  TypeHierarchyRegistrationOptions({
    this.documentSelector,
    this.id,
    this.workDoneProgress,
  });
  static TypeHierarchyRegistrationOptions fromJson(Map<String, Object?> json) {
    final documentSelectorJson = json['documentSelector'];
    final documentSelector = (documentSelectorJson as List<Object?>?)
        ?.map((item) =>
            TextDocumentFilterWithScheme.fromJson(item as Map<String, Object?>))
        .toList();
    final idJson = json['id'];
    final id = idJson as String?;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return TypeHierarchyRegistrationOptions(
      documentSelector: documentSelector,
      id: id,
      workDoneProgress: workDoneProgress,
    );
  }

  /// A document selector to identify the scope of the registration. If set to
  /// null the document selector provided on the client side will be used.
  @override
  final List<TextDocumentFilterWithScheme>? documentSelector;

  /// The id used to register the request. The id can be used to deregister the
  /// request again. See also Registration#id.
  @override
  final String? id;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['documentSelector'] = documentSelector;
    if (id != null) {
      result['id'] = id;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListTextDocumentFilterWithScheme(
          obj, reporter, 'documentSelector',
          allowsUndefined: false, allowsNull: true)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'id',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'workDoneProgress',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type TypeHierarchyRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is TypeHierarchyRegistrationOptions &&
        other.runtimeType == TypeHierarchyRegistrationOptions &&
        listEqual(
            documentSelector,
            other.documentSelector,
            (TextDocumentFilterWithScheme a, TextDocumentFilterWithScheme b) =>
                a == b) &&
        id == other.id &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(documentSelector),
        id,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The parameter of a `typeHierarchy/subtypes` request.
///
/// @since 3.17.0
class TypeHierarchySubtypesParams
    implements PartialResultParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TypeHierarchySubtypesParams.canParse,
    TypeHierarchySubtypesParams.fromJson,
  );

  TypeHierarchySubtypesParams({
    required this.item,
    this.partialResultToken,
    this.workDoneToken,
  });
  static TypeHierarchySubtypesParams fromJson(Map<String, Object?> json) {
    final itemJson = json['item'];
    final item = TypeHierarchyItem.fromJson(itemJson as Map<String, Object?>);
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : _eitherIntString(partialResultTokenJson);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken =
        workDoneTokenJson == null ? null : _eitherIntString(workDoneTokenJson);
    return TypeHierarchySubtypesParams(
      item: item,
      partialResultToken: partialResultToken,
      workDoneToken: workDoneToken,
    );
  }

  final TypeHierarchyItem item;

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final ProgressToken? partialResultToken;

  /// An optional token that a server can use to report work done progress.
  @override
  final ProgressToken? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['item'] = item.toJson();
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseTypeHierarchyItem(obj, reporter, 'item',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseIntString(obj, reporter, 'partialResultToken',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseIntString(obj, reporter, 'workDoneToken',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type TypeHierarchySubtypesParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is TypeHierarchySubtypesParams &&
        other.runtimeType == TypeHierarchySubtypesParams &&
        item == other.item &&
        partialResultToken == other.partialResultToken &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        item,
        partialResultToken,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The parameter of a `typeHierarchy/supertypes` request.
///
/// @since 3.17.0
class TypeHierarchySupertypesParams
    implements PartialResultParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    TypeHierarchySupertypesParams.canParse,
    TypeHierarchySupertypesParams.fromJson,
  );

  TypeHierarchySupertypesParams({
    required this.item,
    this.partialResultToken,
    this.workDoneToken,
  });
  static TypeHierarchySupertypesParams fromJson(Map<String, Object?> json) {
    final itemJson = json['item'];
    final item = TypeHierarchyItem.fromJson(itemJson as Map<String, Object?>);
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : _eitherIntString(partialResultTokenJson);
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken =
        workDoneTokenJson == null ? null : _eitherIntString(workDoneTokenJson);
    return TypeHierarchySupertypesParams(
      item: item,
      partialResultToken: partialResultToken,
      workDoneToken: workDoneToken,
    );
  }

  final TypeHierarchyItem item;

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final ProgressToken? partialResultToken;

  /// An optional token that a server can use to report work done progress.
  @override
  final ProgressToken? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['item'] = item.toJson();
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseTypeHierarchyItem(obj, reporter, 'item',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseIntString(obj, reporter, 'partialResultToken',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseIntString(obj, reporter, 'workDoneToken',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type TypeHierarchySupertypesParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is TypeHierarchySupertypesParams &&
        other.runtimeType == TypeHierarchySupertypesParams &&
        item == other.item &&
        partialResultToken == other.partialResultToken &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        item,
        partialResultToken,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A diagnostic report indicating that the last returned report is still
/// accurate.
///
/// @since 3.17.0
class UnchangedDocumentDiagnosticReport implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    UnchangedDocumentDiagnosticReport.canParse,
    UnchangedDocumentDiagnosticReport.fromJson,
  );

  UnchangedDocumentDiagnosticReport({
    this.kind = 'unchanged',
    required this.resultId,
  }) {
    if (kind != 'unchanged') {
      throw 'kind may only be the literal \'unchanged\'';
    }
  }
  static UnchangedDocumentDiagnosticReport fromJson(Map<String, Object?> json) {
    if (WorkspaceUnchangedDocumentDiagnosticReport.canParse(
        json, nullLspJsonReporter)) {
      return WorkspaceUnchangedDocumentDiagnosticReport.fromJson(json);
    }
    if (RelatedUnchangedDocumentDiagnosticReport.canParse(
        json, nullLspJsonReporter)) {
      return RelatedUnchangedDocumentDiagnosticReport.fromJson(json);
    }
    final kindJson = json['kind'];
    final kind = kindJson as String;
    final resultIdJson = json['resultId'];
    final resultId = resultIdJson as String;
    return UnchangedDocumentDiagnosticReport(
      kind: kind,
      resultId: resultId,
    );
  }

  /// A document diagnostic report indicating no changes to the last result. A
  /// server can only return `unchanged` if result ids are provided.
  final String kind;

  /// A result id which will be sent on the next diagnostic request for the same
  /// document.
  final String resultId;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['kind'] = kind;
    result['resultId'] = resultId;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseLiteral(obj, reporter, 'kind',
          allowsUndefined: false, allowsNull: false, literal: 'unchanged')) {
        return false;
      }
      return _canParseString(obj, reporter, 'resultId',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type UnchangedDocumentDiagnosticReport');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is UnchangedDocumentDiagnosticReport &&
        other.runtimeType == UnchangedDocumentDiagnosticReport &&
        kind == other.kind &&
        resultId == other.resultId;
  }

  @override
  int get hashCode => Object.hash(
        kind,
        resultId,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Moniker uniqueness level to define scope of the moniker.
///
/// @since 3.16.0
class UniquenessLevel implements ToJsonable {
  const UniquenessLevel(this._value);
  const UniquenessLevel.fromJson(this._value);

  final String _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is String;

  /// The moniker is only unique inside a document
  static const document = UniquenessLevel('document');

  /// The moniker is globally unique
  static const global = UniquenessLevel('global');

  /// The moniker is unique inside the group to which a project belongs
  static const group = UniquenessLevel('group');

  /// The moniker is unique inside a project for which a dump got created
  static const project = UniquenessLevel('project');

  /// The moniker is unique inside the moniker scheme.
  static const scheme = UniquenessLevel('scheme');

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is UniquenessLevel && other._value == _value;
}

/// General parameters to unregister a request or notification.
class Unregistration implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    Unregistration.canParse,
    Unregistration.fromJson,
  );

  Unregistration({
    required this.id,
    required this.method,
  });
  static Unregistration fromJson(Map<String, Object?> json) {
    final idJson = json['id'];
    final id = idJson as String;
    final methodJson = json['method'];
    final method = methodJson as String;
    return Unregistration(
      id: id,
      method: method,
    );
  }

  /// The id used to unregister the request or notification. Usually an id
  /// provided during the register request.
  final String id;

  /// The method to unregister for.
  final String method;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['id'] = id;
    result['method'] = method;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseString(obj, reporter, 'id',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseString(obj, reporter, 'method',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type Unregistration');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is Unregistration &&
        other.runtimeType == Unregistration &&
        id == other.id &&
        method == other.method;
  }

  @override
  int get hashCode => Object.hash(
        id,
        method,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class UnregistrationParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    UnregistrationParams.canParse,
    UnregistrationParams.fromJson,
  );

  UnregistrationParams({
    required this.unregisterations,
  });
  static UnregistrationParams fromJson(Map<String, Object?> json) {
    final unregisterationsJson = json['unregisterations'];
    final unregisterations = (unregisterationsJson as List<Object?>)
        .map((item) => Unregistration.fromJson(item as Map<String, Object?>))
        .toList();
    return UnregistrationParams(
      unregisterations: unregisterations,
    );
  }

  final List<Unregistration> unregisterations;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['unregisterations'] =
        unregisterations.map((item) => item.toJson()).toList();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseListUnregistration(obj, reporter, 'unregisterations',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type UnregistrationParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is UnregistrationParams &&
        other.runtimeType == UnregistrationParams &&
        listEqual(unregisterations, other.unregisterations,
            (Unregistration a, Unregistration b) => a == b);
  }

  @override
  int get hashCode => lspHashCode(unregisterations);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A versioned notebook document identifier.
///
/// @since 3.17.0
class VersionedNotebookDocumentIdentifier implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    VersionedNotebookDocumentIdentifier.canParse,
    VersionedNotebookDocumentIdentifier.fromJson,
  );

  VersionedNotebookDocumentIdentifier({
    required this.uri,
    required this.version,
  });
  static VersionedNotebookDocumentIdentifier fromJson(
      Map<String, Object?> json) {
    final uriJson = json['uri'];
    final uri = uriJson as String;
    final versionJson = json['version'];
    final version = versionJson as int;
    return VersionedNotebookDocumentIdentifier(
      uri: uri,
      version: version,
    );
  }

  /// The notebook document's uri.
  final LspUri uri;

  /// The version number of this notebook document.
  final int version;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['uri'] = uri;
    result['version'] = version;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseString(obj, reporter, 'uri',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseInt(obj, reporter, 'version',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter
          .reportError('must be of type VersionedNotebookDocumentIdentifier');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is VersionedNotebookDocumentIdentifier &&
        other.runtimeType == VersionedNotebookDocumentIdentifier &&
        uri == other.uri &&
        version == other.version;
  }

  @override
  int get hashCode => Object.hash(
        uri,
        version,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A text document identifier to denote a specific version of a text document.
class VersionedTextDocumentIdentifier
    implements TextDocumentIdentifier, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    VersionedTextDocumentIdentifier.canParse,
    VersionedTextDocumentIdentifier.fromJson,
  );

  VersionedTextDocumentIdentifier({
    required this.uri,
    required this.version,
  });
  static VersionedTextDocumentIdentifier fromJson(Map<String, Object?> json) {
    final uriJson = json['uri'];
    final uri = uriJson as String;
    final versionJson = json['version'];
    final version = versionJson as int;
    return VersionedTextDocumentIdentifier(
      uri: uri,
      version: version,
    );
  }

  /// The text document's uri.
  @override
  final DocumentUri uri;

  /// The version number of this document.
  final int version;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['uri'] = uri;
    result['version'] = version;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseString(obj, reporter, 'uri',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseInt(obj, reporter, 'version',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type VersionedTextDocumentIdentifier');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is VersionedTextDocumentIdentifier &&
        other.runtimeType == VersionedTextDocumentIdentifier &&
        uri == other.uri &&
        version == other.version;
  }

  @override
  int get hashCode => Object.hash(
        uri,
        version,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WatchKind implements ToJsonable {
  const WatchKind(this._value);
  const WatchKind.fromJson(this._value);

  final int _value;

  static bool canParse(Object? obj, LspJsonReporter reporter) => obj is int;

  /// Interested in change events
  static const Change = WatchKind(2);

  /// Interested in create events.
  static const Create = WatchKind(1);

  /// Interested in delete events
  static const Delete = WatchKind(4);

  @override
  Object toJson() => _value;

  @override
  String toString() => _value.toString();

  @override
  int get hashCode => _value.hashCode;

  @override
  bool operator ==(Object other) =>
      other is WatchKind && other._value == _value;
}

/// The parameters sent in a will save text document notification.
class WillSaveTextDocumentParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WillSaveTextDocumentParams.canParse,
    WillSaveTextDocumentParams.fromJson,
  );

  WillSaveTextDocumentParams({
    required this.reason,
    required this.textDocument,
  });
  static WillSaveTextDocumentParams fromJson(Map<String, Object?> json) {
    final reasonJson = json['reason'];
    final reason = TextDocumentSaveReason.fromJson(reasonJson as int);
    final textDocumentJson = json['textDocument'];
    final textDocument = TextDocumentIdentifier.fromJson(
        textDocumentJson as Map<String, Object?>);
    return WillSaveTextDocumentParams(
      reason: reason,
      textDocument: textDocument,
    );
  }

  /// The 'TextDocumentSaveReason'.
  final TextDocumentSaveReason reason;

  /// The document that will be saved.
  final TextDocumentIdentifier textDocument;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['reason'] = reason.toJson();
    result['textDocument'] = textDocument.toJson();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseTextDocumentSaveReason(obj, reporter, 'reason',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseTextDocumentIdentifier(obj, reporter, 'textDocument',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type WillSaveTextDocumentParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WillSaveTextDocumentParams &&
        other.runtimeType == WillSaveTextDocumentParams &&
        reason == other.reason &&
        textDocument == other.textDocument;
  }

  @override
  int get hashCode => Object.hash(
        reason,
        textDocument,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WindowClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WindowClientCapabilities.canParse,
    WindowClientCapabilities.fromJson,
  );

  WindowClientCapabilities({
    this.showDocument,
    this.showMessage,
    this.workDoneProgress,
  });
  static WindowClientCapabilities fromJson(Map<String, Object?> json) {
    final showDocumentJson = json['showDocument'];
    final showDocument = showDocumentJson != null
        ? ShowDocumentClientCapabilities.fromJson(
            showDocumentJson as Map<String, Object?>)
        : null;
    final showMessageJson = json['showMessage'];
    final showMessage = showMessageJson != null
        ? ShowMessageRequestClientCapabilities.fromJson(
            showMessageJson as Map<String, Object?>)
        : null;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return WindowClientCapabilities(
      showDocument: showDocument,
      showMessage: showMessage,
      workDoneProgress: workDoneProgress,
    );
  }

  /// Capabilities specific to the showDocument request.
  ///
  /// @since 3.16.0
  final ShowDocumentClientCapabilities? showDocument;

  /// Capabilities specific to the showMessage request.
  ///
  /// @since 3.16.0
  final ShowMessageRequestClientCapabilities? showMessage;

  /// It indicates whether the client supports server initiated progress using
  /// the `window/workDoneProgress/create` request.
  ///
  /// The capability also controls Whether client supports handling of progress
  /// notifications. If set servers are allowed to report a `workDoneProgress`
  /// property in the request specific server capabilities.
  ///
  /// @since 3.15.0
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (showDocument != null) {
      result['showDocument'] = showDocument?.toJson();
    }
    if (showMessage != null) {
      result['showMessage'] = showMessage?.toJson();
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseShowDocumentClientCapabilities(
          obj, reporter, 'showDocument',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseShowMessageRequestClientCapabilities(
          obj, reporter, 'showMessage',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'workDoneProgress',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type WindowClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WindowClientCapabilities &&
        other.runtimeType == WindowClientCapabilities &&
        showDocument == other.showDocument &&
        showMessage == other.showMessage &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        showDocument,
        showMessage,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WorkDoneProgressBegin implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkDoneProgressBegin.canParse,
    WorkDoneProgressBegin.fromJson,
  );

  WorkDoneProgressBegin({
    this.cancellable,
    this.kind = 'begin',
    this.message,
    this.percentage,
    required this.title,
  }) {
    if (kind != 'begin') {
      throw 'kind may only be the literal \'begin\'';
    }
  }
  static WorkDoneProgressBegin fromJson(Map<String, Object?> json) {
    final cancellableJson = json['cancellable'];
    final cancellable = cancellableJson as bool?;
    final kindJson = json['kind'];
    final kind = kindJson as String;
    final messageJson = json['message'];
    final message = messageJson as String?;
    final percentageJson = json['percentage'];
    final percentage = percentageJson as int?;
    final titleJson = json['title'];
    final title = titleJson as String;
    return WorkDoneProgressBegin(
      cancellable: cancellable,
      kind: kind,
      message: message,
      percentage: percentage,
      title: title,
    );
  }

  /// Controls if a cancel button should show to allow the user to cancel the
  /// long running operation. Clients that don't support cancellation are
  /// allowed to ignore the setting.
  final bool? cancellable;
  final String kind;

  /// Optional, more detailed associated progress message. Contains
  /// complementary information to the `title`.
  ///
  /// Examples: "3/25 files", "project/src/module2", "node_modules/some_dep". If
  /// unset, the previous progress message (if any) is still valid.
  final String? message;

  /// Optional progress percentage to display (value 100 is considered 100%). If
  /// not provided infinite progress is assumed and clients are allowed to
  /// ignore the `percentage` value in subsequent in report notifications.
  ///
  /// The value should be steadily rising. Clients are free to ignore values
  /// that are not following this rule. The value range is [0, 100].
  final int? percentage;

  /// Mandatory title of the progress operation. Used to briefly inform about
  /// the kind of operation being performed.
  ///
  /// Examples: "Indexing" or "Linking dependencies".
  final String title;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (cancellable != null) {
      result['cancellable'] = cancellable;
    }
    result['kind'] = kind;
    if (message != null) {
      result['message'] = message;
    }
    if (percentage != null) {
      result['percentage'] = percentage;
    }
    result['title'] = title;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseBool(obj, reporter, 'cancellable',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseLiteral(obj, reporter, 'kind',
          allowsUndefined: false, allowsNull: false, literal: 'begin')) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'message',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseInt(obj, reporter, 'percentage',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseString(obj, reporter, 'title',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type WorkDoneProgressBegin');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WorkDoneProgressBegin &&
        other.runtimeType == WorkDoneProgressBegin &&
        cancellable == other.cancellable &&
        kind == other.kind &&
        message == other.message &&
        percentage == other.percentage &&
        title == other.title;
  }

  @override
  int get hashCode => Object.hash(
        cancellable,
        kind,
        message,
        percentage,
        title,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WorkDoneProgressCancelParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkDoneProgressCancelParams.canParse,
    WorkDoneProgressCancelParams.fromJson,
  );

  WorkDoneProgressCancelParams({
    required this.token,
  });
  static WorkDoneProgressCancelParams fromJson(Map<String, Object?> json) {
    final tokenJson = json['token'];
    final token = _eitherIntString(tokenJson);
    return WorkDoneProgressCancelParams(
      token: token,
    );
  }

  /// The token to be used to report progress.
  final ProgressToken token;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['token'] = token;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseIntString(obj, reporter, 'token',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type WorkDoneProgressCancelParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WorkDoneProgressCancelParams &&
        other.runtimeType == WorkDoneProgressCancelParams &&
        token == other.token;
  }

  @override
  int get hashCode => token.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WorkDoneProgressCreateParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkDoneProgressCreateParams.canParse,
    WorkDoneProgressCreateParams.fromJson,
  );

  WorkDoneProgressCreateParams({
    required this.token,
  });
  static WorkDoneProgressCreateParams fromJson(Map<String, Object?> json) {
    final tokenJson = json['token'];
    final token = _eitherIntString(tokenJson);
    return WorkDoneProgressCreateParams(
      token: token,
    );
  }

  /// The token to be used to report progress.
  final ProgressToken token;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['token'] = token;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseIntString(obj, reporter, 'token',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type WorkDoneProgressCreateParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WorkDoneProgressCreateParams &&
        other.runtimeType == WorkDoneProgressCreateParams &&
        token == other.token;
  }

  @override
  int get hashCode => token.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WorkDoneProgressEnd implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkDoneProgressEnd.canParse,
    WorkDoneProgressEnd.fromJson,
  );

  WorkDoneProgressEnd({
    this.kind = 'end',
    this.message,
  }) {
    if (kind != 'end') {
      throw 'kind may only be the literal \'end\'';
    }
  }
  static WorkDoneProgressEnd fromJson(Map<String, Object?> json) {
    final kindJson = json['kind'];
    final kind = kindJson as String;
    final messageJson = json['message'];
    final message = messageJson as String?;
    return WorkDoneProgressEnd(
      kind: kind,
      message: message,
    );
  }

  final String kind;

  /// Optional, a final message indicating to for example indicate the outcome
  /// of the operation.
  final String? message;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['kind'] = kind;
    if (message != null) {
      result['message'] = message;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseLiteral(obj, reporter, 'kind',
          allowsUndefined: false, allowsNull: false, literal: 'end')) {
        return false;
      }
      return _canParseString(obj, reporter, 'message',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type WorkDoneProgressEnd');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WorkDoneProgressEnd &&
        other.runtimeType == WorkDoneProgressEnd &&
        kind == other.kind &&
        message == other.message;
  }

  @override
  int get hashCode => Object.hash(
        kind,
        message,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WorkDoneProgressOptions implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkDoneProgressOptions.canParse,
    WorkDoneProgressOptions.fromJson,
  );

  WorkDoneProgressOptions({
    this.workDoneProgress,
  });
  static WorkDoneProgressOptions fromJson(Map<String, Object?> json) {
    if (DiagnosticOptions.canParse(json, nullLspJsonReporter)) {
      return DiagnosticOptions.fromJson(json);
    }
    if (SemanticTokensOptions.canParse(json, nullLspJsonReporter)) {
      return SemanticTokensOptions.fromJson(json);
    }
    if (ExecuteCommandOptions.canParse(json, nullLspJsonReporter)) {
      return ExecuteCommandOptions.fromJson(json);
    }
    if (CompletionOptions.canParse(json, nullLspJsonReporter)) {
      return CompletionOptions.fromJson(json);
    }
    if (CodeActionOptions.canParse(json, nullLspJsonReporter)) {
      return CodeActionOptions.fromJson(json);
    }
    if (SignatureHelpOptions.canParse(json, nullLspJsonReporter)) {
      return SignatureHelpOptions.fromJson(json);
    }
    if (CodeLensOptions.canParse(json, nullLspJsonReporter)) {
      return CodeLensOptions.fromJson(json);
    }
    if (DocumentLinkOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentLinkOptions.fromJson(json);
    }
    if (DocumentSymbolOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentSymbolOptions.fromJson(json);
    }
    if (InlayHintOptions.canParse(json, nullLspJsonReporter)) {
      return InlayHintOptions.fromJson(json);
    }
    if (RenameOptions.canParse(json, nullLspJsonReporter)) {
      return RenameOptions.fromJson(json);
    }
    if (WorkspaceSymbolOptions.canParse(json, nullLspJsonReporter)) {
      return WorkspaceSymbolOptions.fromJson(json);
    }
    if (CallHierarchyOptions.canParse(json, nullLspJsonReporter)) {
      return CallHierarchyOptions.fromJson(json);
    }
    if (DeclarationOptions.canParse(json, nullLspJsonReporter)) {
      return DeclarationOptions.fromJson(json);
    }
    if (DefinitionOptions.canParse(json, nullLspJsonReporter)) {
      return DefinitionOptions.fromJson(json);
    }
    if (DocumentColorOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentColorOptions.fromJson(json);
    }
    if (DocumentFormattingOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentFormattingOptions.fromJson(json);
    }
    if (DocumentHighlightOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentHighlightOptions.fromJson(json);
    }
    if (DocumentRangeFormattingOptions.canParse(json, nullLspJsonReporter)) {
      return DocumentRangeFormattingOptions.fromJson(json);
    }
    if (FoldingRangeOptions.canParse(json, nullLspJsonReporter)) {
      return FoldingRangeOptions.fromJson(json);
    }
    if (HoverOptions.canParse(json, nullLspJsonReporter)) {
      return HoverOptions.fromJson(json);
    }
    if (ImplementationOptions.canParse(json, nullLspJsonReporter)) {
      return ImplementationOptions.fromJson(json);
    }
    if (InlineValueOptions.canParse(json, nullLspJsonReporter)) {
      return InlineValueOptions.fromJson(json);
    }
    if (LinkedEditingRangeOptions.canParse(json, nullLspJsonReporter)) {
      return LinkedEditingRangeOptions.fromJson(json);
    }
    if (MonikerOptions.canParse(json, nullLspJsonReporter)) {
      return MonikerOptions.fromJson(json);
    }
    if (ReferenceOptions.canParse(json, nullLspJsonReporter)) {
      return ReferenceOptions.fromJson(json);
    }
    if (SelectionRangeOptions.canParse(json, nullLspJsonReporter)) {
      return SelectionRangeOptions.fromJson(json);
    }
    if (TypeDefinitionOptions.canParse(json, nullLspJsonReporter)) {
      return TypeDefinitionOptions.fromJson(json);
    }
    if (TypeHierarchyOptions.canParse(json, nullLspJsonReporter)) {
      return TypeHierarchyOptions.fromJson(json);
    }
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return WorkDoneProgressOptions(
      workDoneProgress: workDoneProgress,
    );
  }

  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseBool(obj, reporter, 'workDoneProgress',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type WorkDoneProgressOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WorkDoneProgressOptions &&
        other.runtimeType == WorkDoneProgressOptions &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => workDoneProgress.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WorkDoneProgressParams implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkDoneProgressParams.canParse,
    WorkDoneProgressParams.fromJson,
  );

  WorkDoneProgressParams({
    this.workDoneToken,
  });
  static WorkDoneProgressParams fromJson(Map<String, Object?> json) {
    if (CodeActionParams.canParse(json, nullLspJsonReporter)) {
      return CodeActionParams.fromJson(json);
    }
    if (ColorPresentationParams.canParse(json, nullLspJsonReporter)) {
      return ColorPresentationParams.fromJson(json);
    }
    if (DocumentRangeFormattingParams.canParse(json, nullLspJsonReporter)) {
      return DocumentRangeFormattingParams.fromJson(json);
    }
    if (InlineValueParams.canParse(json, nullLspJsonReporter)) {
      return InlineValueParams.fromJson(json);
    }
    if (RenameParams.canParse(json, nullLspJsonReporter)) {
      return RenameParams.fromJson(json);
    }
    if (DocumentFormattingParams.canParse(json, nullLspJsonReporter)) {
      return DocumentFormattingParams.fromJson(json);
    }
    if (InlayHintParams.canParse(json, nullLspJsonReporter)) {
      return InlayHintParams.fromJson(json);
    }
    if (SelectionRangeParams.canParse(json, nullLspJsonReporter)) {
      return SelectionRangeParams.fromJson(json);
    }
    if (SemanticTokensDeltaParams.canParse(json, nullLspJsonReporter)) {
      return SemanticTokensDeltaParams.fromJson(json);
    }
    if (SemanticTokensRangeParams.canParse(json, nullLspJsonReporter)) {
      return SemanticTokensRangeParams.fromJson(json);
    }
    if (InitializeParams.canParse(json, nullLspJsonReporter)) {
      return InitializeParams.fromJson(json);
    }
    if (DocumentDiagnosticParams.canParse(json, nullLspJsonReporter)) {
      return DocumentDiagnosticParams.fromJson(json);
    }
    if (ExecuteCommandParams.canParse(json, nullLspJsonReporter)) {
      return ExecuteCommandParams.fromJson(json);
    }
    if (WorkspaceDiagnosticParams.canParse(json, nullLspJsonReporter)) {
      return WorkspaceDiagnosticParams.fromJson(json);
    }
    if (CallHierarchyIncomingCallsParams.canParse(json, nullLspJsonReporter)) {
      return CallHierarchyIncomingCallsParams.fromJson(json);
    }
    if (CallHierarchyOutgoingCallsParams.canParse(json, nullLspJsonReporter)) {
      return CallHierarchyOutgoingCallsParams.fromJson(json);
    }
    if (CodeLensParams.canParse(json, nullLspJsonReporter)) {
      return CodeLensParams.fromJson(json);
    }
    if (DocumentColorParams.canParse(json, nullLspJsonReporter)) {
      return DocumentColorParams.fromJson(json);
    }
    if (DocumentLinkParams.canParse(json, nullLspJsonReporter)) {
      return DocumentLinkParams.fromJson(json);
    }
    if (DocumentSymbolParams.canParse(json, nullLspJsonReporter)) {
      return DocumentSymbolParams.fromJson(json);
    }
    if (FoldingRangeParams.canParse(json, nullLspJsonReporter)) {
      return FoldingRangeParams.fromJson(json);
    }
    if (ReferenceParams.canParse(json, nullLspJsonReporter)) {
      return ReferenceParams.fromJson(json);
    }
    if (SemanticTokensParams.canParse(json, nullLspJsonReporter)) {
      return SemanticTokensParams.fromJson(json);
    }
    if (TypeHierarchySubtypesParams.canParse(json, nullLspJsonReporter)) {
      return TypeHierarchySubtypesParams.fromJson(json);
    }
    if (TypeHierarchySupertypesParams.canParse(json, nullLspJsonReporter)) {
      return TypeHierarchySupertypesParams.fromJson(json);
    }
    if (WorkspaceSymbolParams.canParse(json, nullLspJsonReporter)) {
      return WorkspaceSymbolParams.fromJson(json);
    }
    if (CompletionParams.canParse(json, nullLspJsonReporter)) {
      return CompletionParams.fromJson(json);
    }
    if (SignatureHelpParams.canParse(json, nullLspJsonReporter)) {
      return SignatureHelpParams.fromJson(json);
    }
    if (CallHierarchyPrepareParams.canParse(json, nullLspJsonReporter)) {
      return CallHierarchyPrepareParams.fromJson(json);
    }
    if (DeclarationParams.canParse(json, nullLspJsonReporter)) {
      return DeclarationParams.fromJson(json);
    }
    if (DefinitionParams.canParse(json, nullLspJsonReporter)) {
      return DefinitionParams.fromJson(json);
    }
    if (DocumentHighlightParams.canParse(json, nullLspJsonReporter)) {
      return DocumentHighlightParams.fromJson(json);
    }
    if (HoverParams.canParse(json, nullLspJsonReporter)) {
      return HoverParams.fromJson(json);
    }
    if (ImplementationParams.canParse(json, nullLspJsonReporter)) {
      return ImplementationParams.fromJson(json);
    }
    if (LinkedEditingRangeParams.canParse(json, nullLspJsonReporter)) {
      return LinkedEditingRangeParams.fromJson(json);
    }
    if (MonikerParams.canParse(json, nullLspJsonReporter)) {
      return MonikerParams.fromJson(json);
    }
    if (PrepareRenameParams.canParse(json, nullLspJsonReporter)) {
      return PrepareRenameParams.fromJson(json);
    }
    if (TypeDefinitionParams.canParse(json, nullLspJsonReporter)) {
      return TypeDefinitionParams.fromJson(json);
    }
    if (TypeHierarchyPrepareParams.canParse(json, nullLspJsonReporter)) {
      return TypeHierarchyPrepareParams.fromJson(json);
    }
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken =
        workDoneTokenJson == null ? null : _eitherIntString(workDoneTokenJson);
    return WorkDoneProgressParams(
      workDoneToken: workDoneToken,
    );
  }

  /// An optional token that a server can use to report work done progress.
  final ProgressToken? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseIntString(obj, reporter, 'workDoneToken',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type WorkDoneProgressParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WorkDoneProgressParams &&
        other.runtimeType == WorkDoneProgressParams &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => workDoneToken.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WorkDoneProgressReport implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkDoneProgressReport.canParse,
    WorkDoneProgressReport.fromJson,
  );

  WorkDoneProgressReport({
    this.cancellable,
    this.kind = 'report',
    this.message,
    this.percentage,
  }) {
    if (kind != 'report') {
      throw 'kind may only be the literal \'report\'';
    }
  }
  static WorkDoneProgressReport fromJson(Map<String, Object?> json) {
    final cancellableJson = json['cancellable'];
    final cancellable = cancellableJson as bool?;
    final kindJson = json['kind'];
    final kind = kindJson as String;
    final messageJson = json['message'];
    final message = messageJson as String?;
    final percentageJson = json['percentage'];
    final percentage = percentageJson as int?;
    return WorkDoneProgressReport(
      cancellable: cancellable,
      kind: kind,
      message: message,
      percentage: percentage,
    );
  }

  /// Controls enablement state of a cancel button.
  ///
  /// Clients that don't support cancellation or don't support controlling the
  /// button's enablement state are allowed to ignore the property.
  final bool? cancellable;
  final String kind;

  /// Optional, more detailed associated progress message. Contains
  /// complementary information to the `title`.
  ///
  /// Examples: "3/25 files", "project/src/module2", "node_modules/some_dep". If
  /// unset, the previous progress message (if any) is still valid.
  final String? message;

  /// Optional progress percentage to display (value 100 is considered 100%). If
  /// not provided infinite progress is assumed and clients are allowed to
  /// ignore the `percentage` value in subsequent in report notifications.
  ///
  /// The value should be steadily rising. Clients are free to ignore values
  /// that are not following this rule. The value range is [0, 100]
  final int? percentage;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (cancellable != null) {
      result['cancellable'] = cancellable;
    }
    result['kind'] = kind;
    if (message != null) {
      result['message'] = message;
    }
    if (percentage != null) {
      result['percentage'] = percentage;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseBool(obj, reporter, 'cancellable',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseLiteral(obj, reporter, 'kind',
          allowsUndefined: false, allowsNull: false, literal: 'report')) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'message',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseInt(obj, reporter, 'percentage',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type WorkDoneProgressReport');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WorkDoneProgressReport &&
        other.runtimeType == WorkDoneProgressReport &&
        cancellable == other.cancellable &&
        kind == other.kind &&
        message == other.message &&
        percentage == other.percentage;
  }

  @override
  int get hashCode => Object.hash(
        cancellable,
        kind,
        message,
        percentage,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Workspace specific client capabilities.
class WorkspaceClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceClientCapabilities.canParse,
    WorkspaceClientCapabilities.fromJson,
  );

  WorkspaceClientCapabilities({
    this.applyEdit,
    this.codeLens,
    this.configuration,
    this.diagnostics,
    this.didChangeConfiguration,
    this.didChangeWatchedFiles,
    this.executeCommand,
    this.fileOperations,
    this.inlayHint,
    this.inlineValue,
    this.semanticTokens,
    this.symbol,
    this.workspaceEdit,
    this.workspaceFolders,
  });
  static WorkspaceClientCapabilities fromJson(Map<String, Object?> json) {
    final applyEditJson = json['applyEdit'];
    final applyEdit = applyEditJson as bool?;
    final codeLensJson = json['codeLens'];
    final codeLens = codeLensJson != null
        ? CodeLensWorkspaceClientCapabilities.fromJson(
            codeLensJson as Map<String, Object?>)
        : null;
    final configurationJson = json['configuration'];
    final configuration = configurationJson as bool?;
    final diagnosticsJson = json['diagnostics'];
    final diagnostics = diagnosticsJson != null
        ? DiagnosticWorkspaceClientCapabilities.fromJson(
            diagnosticsJson as Map<String, Object?>)
        : null;
    final didChangeConfigurationJson = json['didChangeConfiguration'];
    final didChangeConfiguration = didChangeConfigurationJson != null
        ? DidChangeConfigurationClientCapabilities.fromJson(
            didChangeConfigurationJson as Map<String, Object?>)
        : null;
    final didChangeWatchedFilesJson = json['didChangeWatchedFiles'];
    final didChangeWatchedFiles = didChangeWatchedFilesJson != null
        ? DidChangeWatchedFilesClientCapabilities.fromJson(
            didChangeWatchedFilesJson as Map<String, Object?>)
        : null;
    final executeCommandJson = json['executeCommand'];
    final executeCommand = executeCommandJson != null
        ? ExecuteCommandClientCapabilities.fromJson(
            executeCommandJson as Map<String, Object?>)
        : null;
    final fileOperationsJson = json['fileOperations'];
    final fileOperations = fileOperationsJson != null
        ? FileOperationClientCapabilities.fromJson(
            fileOperationsJson as Map<String, Object?>)
        : null;
    final inlayHintJson = json['inlayHint'];
    final inlayHint = inlayHintJson != null
        ? InlayHintWorkspaceClientCapabilities.fromJson(
            inlayHintJson as Map<String, Object?>)
        : null;
    final inlineValueJson = json['inlineValue'];
    final inlineValue = inlineValueJson != null
        ? InlineValueWorkspaceClientCapabilities.fromJson(
            inlineValueJson as Map<String, Object?>)
        : null;
    final semanticTokensJson = json['semanticTokens'];
    final semanticTokens = semanticTokensJson != null
        ? SemanticTokensWorkspaceClientCapabilities.fromJson(
            semanticTokensJson as Map<String, Object?>)
        : null;
    final symbolJson = json['symbol'];
    final symbol = symbolJson != null
        ? WorkspaceSymbolClientCapabilities.fromJson(
            symbolJson as Map<String, Object?>)
        : null;
    final workspaceEditJson = json['workspaceEdit'];
    final workspaceEdit = workspaceEditJson != null
        ? WorkspaceEditClientCapabilities.fromJson(
            workspaceEditJson as Map<String, Object?>)
        : null;
    final workspaceFoldersJson = json['workspaceFolders'];
    final workspaceFolders = workspaceFoldersJson as bool?;
    return WorkspaceClientCapabilities(
      applyEdit: applyEdit,
      codeLens: codeLens,
      configuration: configuration,
      diagnostics: diagnostics,
      didChangeConfiguration: didChangeConfiguration,
      didChangeWatchedFiles: didChangeWatchedFiles,
      executeCommand: executeCommand,
      fileOperations: fileOperations,
      inlayHint: inlayHint,
      inlineValue: inlineValue,
      semanticTokens: semanticTokens,
      symbol: symbol,
      workspaceEdit: workspaceEdit,
      workspaceFolders: workspaceFolders,
    );
  }

  /// The client supports applying batch edits to the workspace by supporting
  /// the request
  /// 'workspace/applyEdit'
  final bool? applyEdit;

  /// Capabilities specific to the code lens requests scoped to the workspace.
  ///
  /// @since 3.16.0.
  final CodeLensWorkspaceClientCapabilities? codeLens;

  /// The client supports `workspace/configuration` requests.
  ///
  /// @since 3.6.0
  final bool? configuration;

  /// Capabilities specific to the diagnostic requests scoped to the workspace.
  ///
  /// @since 3.17.0.
  final DiagnosticWorkspaceClientCapabilities? diagnostics;

  /// Capabilities specific to the `workspace/didChangeConfiguration`
  /// notification.
  final DidChangeConfigurationClientCapabilities? didChangeConfiguration;

  /// Capabilities specific to the `workspace/didChangeWatchedFiles`
  /// notification.
  final DidChangeWatchedFilesClientCapabilities? didChangeWatchedFiles;

  /// Capabilities specific to the `workspace/executeCommand` request.
  final ExecuteCommandClientCapabilities? executeCommand;

  /// The client has support for file notifications/requests for user operations
  /// on files.
  ///
  /// Since 3.16.0
  final FileOperationClientCapabilities? fileOperations;

  /// Capabilities specific to the inlay hint requests scoped to the workspace.
  ///
  /// @since 3.17.0.
  final InlayHintWorkspaceClientCapabilities? inlayHint;

  /// Capabilities specific to the inline values requests scoped to the
  /// workspace.
  ///
  /// @since 3.17.0.
  final InlineValueWorkspaceClientCapabilities? inlineValue;

  /// Capabilities specific to the semantic token requests scoped to the
  /// workspace.
  ///
  /// @since 3.16.0.
  final SemanticTokensWorkspaceClientCapabilities? semanticTokens;

  /// Capabilities specific to the `workspace/symbol` request.
  final WorkspaceSymbolClientCapabilities? symbol;

  /// Capabilities specific to `WorkspaceEdit`s.
  final WorkspaceEditClientCapabilities? workspaceEdit;

  /// The client has support for workspace folders.
  ///
  /// @since 3.6.0
  final bool? workspaceFolders;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (applyEdit != null) {
      result['applyEdit'] = applyEdit;
    }
    if (codeLens != null) {
      result['codeLens'] = codeLens?.toJson();
    }
    if (configuration != null) {
      result['configuration'] = configuration;
    }
    if (diagnostics != null) {
      result['diagnostics'] = diagnostics?.toJson();
    }
    if (didChangeConfiguration != null) {
      result['didChangeConfiguration'] = didChangeConfiguration?.toJson();
    }
    if (didChangeWatchedFiles != null) {
      result['didChangeWatchedFiles'] = didChangeWatchedFiles?.toJson();
    }
    if (executeCommand != null) {
      result['executeCommand'] = executeCommand?.toJson();
    }
    if (fileOperations != null) {
      result['fileOperations'] = fileOperations?.toJson();
    }
    if (inlayHint != null) {
      result['inlayHint'] = inlayHint?.toJson();
    }
    if (inlineValue != null) {
      result['inlineValue'] = inlineValue?.toJson();
    }
    if (semanticTokens != null) {
      result['semanticTokens'] = semanticTokens?.toJson();
    }
    if (symbol != null) {
      result['symbol'] = symbol?.toJson();
    }
    if (workspaceEdit != null) {
      result['workspaceEdit'] = workspaceEdit?.toJson();
    }
    if (workspaceFolders != null) {
      result['workspaceFolders'] = workspaceFolders;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseBool(obj, reporter, 'applyEdit',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseCodeLensWorkspaceClientCapabilities(
          obj, reporter, 'codeLens',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'configuration',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseDiagnosticWorkspaceClientCapabilities(
          obj, reporter, 'diagnostics',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseDidChangeConfigurationClientCapabilities(
          obj, reporter, 'didChangeConfiguration',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseDidChangeWatchedFilesClientCapabilities(
          obj, reporter, 'didChangeWatchedFiles',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseExecuteCommandClientCapabilities(
          obj, reporter, 'executeCommand',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseFileOperationClientCapabilities(
          obj, reporter, 'fileOperations',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseInlayHintWorkspaceClientCapabilities(
          obj, reporter, 'inlayHint',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseInlineValueWorkspaceClientCapabilities(
          obj, reporter, 'inlineValue',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseSemanticTokensWorkspaceClientCapabilities(
          obj, reporter, 'semanticTokens',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseWorkspaceSymbolClientCapabilities(obj, reporter, 'symbol',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseWorkspaceEditClientCapabilities(
          obj, reporter, 'workspaceEdit',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'workspaceFolders',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type WorkspaceClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WorkspaceClientCapabilities &&
        other.runtimeType == WorkspaceClientCapabilities &&
        applyEdit == other.applyEdit &&
        codeLens == other.codeLens &&
        configuration == other.configuration &&
        diagnostics == other.diagnostics &&
        didChangeConfiguration == other.didChangeConfiguration &&
        didChangeWatchedFiles == other.didChangeWatchedFiles &&
        executeCommand == other.executeCommand &&
        fileOperations == other.fileOperations &&
        inlayHint == other.inlayHint &&
        inlineValue == other.inlineValue &&
        semanticTokens == other.semanticTokens &&
        symbol == other.symbol &&
        workspaceEdit == other.workspaceEdit &&
        workspaceFolders == other.workspaceFolders;
  }

  @override
  int get hashCode => Object.hash(
        applyEdit,
        codeLens,
        configuration,
        diagnostics,
        didChangeConfiguration,
        didChangeWatchedFiles,
        executeCommand,
        fileOperations,
        inlayHint,
        inlineValue,
        semanticTokens,
        symbol,
        workspaceEdit,
        workspaceFolders,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Parameters of the workspace diagnostic request.
///
/// @since 3.17.0
class WorkspaceDiagnosticParams
    implements PartialResultParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceDiagnosticParams.canParse,
    WorkspaceDiagnosticParams.fromJson,
  );

  WorkspaceDiagnosticParams({
    this.identifier,
    this.partialResultToken,
    required this.previousResultIds,
    this.workDoneToken,
  });
  static WorkspaceDiagnosticParams fromJson(Map<String, Object?> json) {
    final identifierJson = json['identifier'];
    final identifier = identifierJson as String?;
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : _eitherIntString(partialResultTokenJson);
    final previousResultIdsJson = json['previousResultIds'];
    final previousResultIds = (previousResultIdsJson as List<Object?>)
        .map((item) => PreviousResultId.fromJson(item as Map<String, Object?>))
        .toList();
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken =
        workDoneTokenJson == null ? null : _eitherIntString(workDoneTokenJson);
    return WorkspaceDiagnosticParams(
      identifier: identifier,
      partialResultToken: partialResultToken,
      previousResultIds: previousResultIds,
      workDoneToken: workDoneToken,
    );
  }

  /// The additional identifier provided during registration.
  final String? identifier;

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final ProgressToken? partialResultToken;

  /// The currently known diagnostic reports with their previous result ids.
  final List<PreviousResultId> previousResultIds;

  /// An optional token that a server can use to report work done progress.
  @override
  final ProgressToken? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (identifier != null) {
      result['identifier'] = identifier;
    }
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    result['previousResultIds'] =
        previousResultIds.map((item) => item.toJson()).toList();
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseString(obj, reporter, 'identifier',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseIntString(obj, reporter, 'partialResultToken',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseListPreviousResultId(obj, reporter, 'previousResultIds',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseIntString(obj, reporter, 'workDoneToken',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type WorkspaceDiagnosticParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WorkspaceDiagnosticParams &&
        other.runtimeType == WorkspaceDiagnosticParams &&
        identifier == other.identifier &&
        partialResultToken == other.partialResultToken &&
        listEqual(previousResultIds, other.previousResultIds,
            (PreviousResultId a, PreviousResultId b) => a == b) &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        identifier,
        partialResultToken,
        lspHashCode(previousResultIds),
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A workspace diagnostic report.
///
/// @since 3.17.0
class WorkspaceDiagnosticReport implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceDiagnosticReport.canParse,
    WorkspaceDiagnosticReport.fromJson,
  );

  WorkspaceDiagnosticReport({
    required this.items,
  });
  static WorkspaceDiagnosticReport fromJson(Map<String, Object?> json) {
    final itemsJson = json['items'];
    final items = (itemsJson as List<Object?>)
        .map((item) =>
            _eitherWorkspaceFullDocumentDiagnosticReportWorkspaceUnchangedDocumentDiagnosticReport(
                item))
        .toList();
    return WorkspaceDiagnosticReport(
      items: items,
    );
  }

  final List<WorkspaceDocumentDiagnosticReport> items;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['items'] = items;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseListWorkspaceFullDocumentDiagnosticReportWorkspaceUnchangedDocumentDiagnosticReport(
          obj, reporter, 'items',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type WorkspaceDiagnosticReport');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WorkspaceDiagnosticReport &&
        other.runtimeType == WorkspaceDiagnosticReport &&
        listEqual(
            items,
            other.items,
            (WorkspaceDocumentDiagnosticReport a,
                    WorkspaceDocumentDiagnosticReport b) =>
                a == b);
  }

  @override
  int get hashCode => lspHashCode(items);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A partial result for a workspace diagnostic report.
///
/// @since 3.17.0
class WorkspaceDiagnosticReportPartialResult implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceDiagnosticReportPartialResult.canParse,
    WorkspaceDiagnosticReportPartialResult.fromJson,
  );

  WorkspaceDiagnosticReportPartialResult({
    required this.items,
  });
  static WorkspaceDiagnosticReportPartialResult fromJson(
      Map<String, Object?> json) {
    final itemsJson = json['items'];
    final items = (itemsJson as List<Object?>)
        .map((item) =>
            _eitherWorkspaceFullDocumentDiagnosticReportWorkspaceUnchangedDocumentDiagnosticReport(
                item))
        .toList();
    return WorkspaceDiagnosticReportPartialResult(
      items: items,
    );
  }

  final List<WorkspaceDocumentDiagnosticReport> items;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['items'] = items;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseListWorkspaceFullDocumentDiagnosticReportWorkspaceUnchangedDocumentDiagnosticReport(
          obj, reporter, 'items',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError(
          'must be of type WorkspaceDiagnosticReportPartialResult');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WorkspaceDiagnosticReportPartialResult &&
        other.runtimeType == WorkspaceDiagnosticReportPartialResult &&
        listEqual(
            items,
            other.items,
            (WorkspaceDocumentDiagnosticReport a,
                    WorkspaceDocumentDiagnosticReport b) =>
                a == b);
  }

  @override
  int get hashCode => lspHashCode(items);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A workspace edit represents changes to many resources managed in the
/// workspace. The edit should either provide `changes` or `documentChanges`. If
/// documentChanges are present they are preferred over `changes` if the client
/// can handle versioned document edits.
///
/// Since version 3.13.0 a workspace edit can contain resource operations as
/// well. If resource operations are present clients need to execute the
/// operations in the order in which they are provided. So a workspace edit for
/// example can consist of the following two changes:
/// (1) a create file a.txt and (2) a text document edit which insert text into
/// file a.txt.
///
/// An invalid sequence (e.g. (1) delete file a.txt and (2) insert text into
/// file a.txt) will cause failure of the operation. How the client recovers
/// from the failure is described by the client capability:
/// `workspace.workspaceEdit.failureHandling`
class WorkspaceEdit implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceEdit.canParse,
    WorkspaceEdit.fromJson,
  );

  WorkspaceEdit({
    this.changeAnnotations,
    this.changes,
    this.documentChanges,
  });
  static WorkspaceEdit fromJson(Map<String, Object?> json) {
    final changeAnnotationsJson = json['changeAnnotations'];
    final changeAnnotations = (changeAnnotationsJson as Map<Object, Object?>?)
        ?.map((key, value) => MapEntry(key as String,
            ChangeAnnotation.fromJson(value as Map<String, Object?>)));
    final changesJson = json['changes'];
    final changes = (changesJson as Map<Object, Object?>?)?.map((key, value) =>
        MapEntry(
            key as String,
            (value as List<Object?>)
                .map((item) => TextEdit.fromJson(item as Map<String, Object?>))
                .toList()));
    final documentChangesJson = json['documentChanges'];
    final documentChanges = (documentChangesJson as List<Object?>?)
        ?.map((item) =>
            _eitherCreateFileDeleteFileRenameFileTextDocumentEdit(item))
        .toList();
    return WorkspaceEdit(
      changeAnnotations: changeAnnotations,
      changes: changes,
      documentChanges: documentChanges,
    );
  }

  /// A map of change annotations that can be referenced in `AnnotatedTextEdit`s
  /// or create, rename and delete file / folder operations.
  ///
  /// Whether clients honor this property depends on the client capability
  /// `workspace.changeAnnotationSupport`.
  ///
  /// @since 3.16.0
  final Map<ChangeAnnotationIdentifier, ChangeAnnotation>? changeAnnotations;

  /// Holds changes to existing resources.
  final Map<DocumentUri, List<TextEdit>>? changes;

  /// Depending on the client capability
  /// `workspace.workspaceEdit.resourceOperations` document changes are either
  /// an array of `TextDocumentEdit`s to express changes to n different text
  /// documents where each text document edit addresses a specific version of a
  /// text document. Or it can contain above `TextDocumentEdit`s mixed with
  /// create, rename and delete file / folder operations.
  ///
  /// Whether a client supports versioned document edits is expressed via
  /// `workspace.workspaceEdit.documentChanges` client capability.
  ///
  /// If a client neither supports `documentChanges` nor
  /// `workspace.workspaceEdit.resourceOperations` then only plain `TextEdit`s
  /// using the `changes` property are supported.
  final List<Either4<CreateFile, DeleteFile, RenameFile, TextDocumentEdit>>?
      documentChanges;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (changeAnnotations != null) {
      result['changeAnnotations'] = changeAnnotations;
    }
    if (changes != null) {
      result['changes'] = changes;
    }
    if (documentChanges != null) {
      result['documentChanges'] = documentChanges;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseMapStringChangeAnnotation(
          obj, reporter, 'changeAnnotations',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseMapStringListTextEdit(obj, reporter, 'changes',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseListCreateFileDeleteFileRenameFileTextDocumentEdit(
          obj, reporter, 'documentChanges',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type WorkspaceEdit');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WorkspaceEdit &&
        other.runtimeType == WorkspaceEdit &&
        mapEqual(changeAnnotations, other.changeAnnotations,
            (ChangeAnnotation a, ChangeAnnotation b) => a == b) &&
        mapEqual(
            changes,
            other.changes,
            (List<TextEdit> a, List<TextEdit> b) =>
                listEqual(a, b, (TextEdit a, TextEdit b) => a == b)) &&
        listEqual(
            documentChanges,
            other.documentChanges,
            (Either4<CreateFile, DeleteFile, RenameFile, TextDocumentEdit> a,
                    Either4<CreateFile, DeleteFile, RenameFile,
                            TextDocumentEdit>
                        b) =>
                a == b);
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(changeAnnotations),
        lspHashCode(changes),
        lspHashCode(documentChanges),
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WorkspaceEditClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceEditClientCapabilities.canParse,
    WorkspaceEditClientCapabilities.fromJson,
  );

  WorkspaceEditClientCapabilities({
    this.changeAnnotationSupport,
    this.documentChanges,
    this.failureHandling,
    this.normalizesLineEndings,
    this.resourceOperations,
  });
  static WorkspaceEditClientCapabilities fromJson(Map<String, Object?> json) {
    final changeAnnotationSupportJson = json['changeAnnotationSupport'];
    final changeAnnotationSupport = changeAnnotationSupportJson != null
        ? WorkspaceEditClientCapabilitiesChangeAnnotationSupport.fromJson(
            changeAnnotationSupportJson as Map<String, Object?>)
        : null;
    final documentChangesJson = json['documentChanges'];
    final documentChanges = documentChangesJson as bool?;
    final failureHandlingJson = json['failureHandling'];
    final failureHandling = failureHandlingJson != null
        ? FailureHandlingKind.fromJson(failureHandlingJson as String)
        : null;
    final normalizesLineEndingsJson = json['normalizesLineEndings'];
    final normalizesLineEndings = normalizesLineEndingsJson as bool?;
    final resourceOperationsJson = json['resourceOperations'];
    final resourceOperations = (resourceOperationsJson as List<Object?>?)
        ?.map((item) => ResourceOperationKind.fromJson(item as String))
        .toList();
    return WorkspaceEditClientCapabilities(
      changeAnnotationSupport: changeAnnotationSupport,
      documentChanges: documentChanges,
      failureHandling: failureHandling,
      normalizesLineEndings: normalizesLineEndings,
      resourceOperations: resourceOperations,
    );
  }

  /// Whether the client in general supports change annotations on text edits,
  /// create file, rename file and delete file changes.
  ///
  /// @since 3.16.0
  final WorkspaceEditClientCapabilitiesChangeAnnotationSupport?
      changeAnnotationSupport;

  /// The client supports versioned document changes in `WorkspaceEdit`s
  final bool? documentChanges;

  /// The failure handling strategy of a client if applying the workspace edit
  /// fails.
  ///
  /// @since 3.13.0
  final FailureHandlingKind? failureHandling;

  /// Whether the client normalizes line endings to the client specific setting.
  /// If set to `true` the client will normalize line ending characters in a
  /// workspace edit to the client-specified new line character.
  ///
  /// @since 3.16.0
  final bool? normalizesLineEndings;

  /// The resource operations the client supports. Clients should at least
  /// support 'create', 'rename' and 'delete' files and folders.
  ///
  /// @since 3.13.0
  final List<ResourceOperationKind>? resourceOperations;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (changeAnnotationSupport != null) {
      result['changeAnnotationSupport'] = changeAnnotationSupport?.toJson();
    }
    if (documentChanges != null) {
      result['documentChanges'] = documentChanges;
    }
    if (failureHandling != null) {
      result['failureHandling'] = failureHandling?.toJson();
    }
    if (normalizesLineEndings != null) {
      result['normalizesLineEndings'] = normalizesLineEndings;
    }
    if (resourceOperations != null) {
      result['resourceOperations'] =
          resourceOperations?.map((item) => item.toJson()).toList();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseWorkspaceEditClientCapabilitiesChangeAnnotationSupport(
          obj, reporter, 'changeAnnotationSupport',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'documentChanges',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseFailureHandlingKind(obj, reporter, 'failureHandling',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseBool(obj, reporter, 'normalizesLineEndings',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseListResourceOperationKind(
          obj, reporter, 'resourceOperations',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type WorkspaceEditClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WorkspaceEditClientCapabilities &&
        other.runtimeType == WorkspaceEditClientCapabilities &&
        changeAnnotationSupport == other.changeAnnotationSupport &&
        documentChanges == other.documentChanges &&
        failureHandling == other.failureHandling &&
        normalizesLineEndings == other.normalizesLineEndings &&
        listEqual(resourceOperations, other.resourceOperations,
            (ResourceOperationKind a, ResourceOperationKind b) => a == b);
  }

  @override
  int get hashCode => Object.hash(
        changeAnnotationSupport,
        documentChanges,
        failureHandling,
        normalizesLineEndings,
        lspHashCode(resourceOperations),
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WorkspaceEditClientCapabilitiesChangeAnnotationSupport
    implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceEditClientCapabilitiesChangeAnnotationSupport.canParse,
    WorkspaceEditClientCapabilitiesChangeAnnotationSupport.fromJson,
  );

  WorkspaceEditClientCapabilitiesChangeAnnotationSupport({
    this.groupsOnLabel,
  });
  static WorkspaceEditClientCapabilitiesChangeAnnotationSupport fromJson(
      Map<String, Object?> json) {
    final groupsOnLabelJson = json['groupsOnLabel'];
    final groupsOnLabel = groupsOnLabelJson as bool?;
    return WorkspaceEditClientCapabilitiesChangeAnnotationSupport(
      groupsOnLabel: groupsOnLabel,
    );
  }

  /// Whether the client groups edits with equal labels into tree nodes,
  /// for instance all edits labelled with "Changes in Strings" would be a tree
  /// node.
  final bool? groupsOnLabel;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (groupsOnLabel != null) {
      result['groupsOnLabel'] = groupsOnLabel;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseBool(obj, reporter, 'groupsOnLabel',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError(
          'must be of type WorkspaceEditClientCapabilitiesChangeAnnotationSupport');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WorkspaceEditClientCapabilitiesChangeAnnotationSupport &&
        other.runtimeType ==
            WorkspaceEditClientCapabilitiesChangeAnnotationSupport &&
        groupsOnLabel == other.groupsOnLabel;
  }

  @override
  int get hashCode => groupsOnLabel.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A workspace folder inside a client.
class WorkspaceFolder implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceFolder.canParse,
    WorkspaceFolder.fromJson,
  );

  WorkspaceFolder({
    required this.name,
    required this.uri,
  });
  static WorkspaceFolder fromJson(Map<String, Object?> json) {
    final nameJson = json['name'];
    final name = nameJson as String;
    final uriJson = json['uri'];
    final uri = uriJson as String;
    return WorkspaceFolder(
      name: name,
      uri: uri,
    );
  }

  /// The name of the workspace folder. Used to refer to this workspace folder
  /// in the user interface.
  final String name;

  /// The associated URI for this workspace folder.
  final LspUri uri;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['name'] = name;
    result['uri'] = uri;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseString(obj, reporter, 'name',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseString(obj, reporter, 'uri',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type WorkspaceFolder');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WorkspaceFolder &&
        other.runtimeType == WorkspaceFolder &&
        name == other.name &&
        uri == other.uri;
  }

  @override
  int get hashCode => Object.hash(
        name,
        uri,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The workspace folder change event.
class WorkspaceFoldersChangeEvent implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceFoldersChangeEvent.canParse,
    WorkspaceFoldersChangeEvent.fromJson,
  );

  WorkspaceFoldersChangeEvent({
    required this.added,
    required this.removed,
  });
  static WorkspaceFoldersChangeEvent fromJson(Map<String, Object?> json) {
    final addedJson = json['added'];
    final added = (addedJson as List<Object?>)
        .map((item) => WorkspaceFolder.fromJson(item as Map<String, Object?>))
        .toList();
    final removedJson = json['removed'];
    final removed = (removedJson as List<Object?>)
        .map((item) => WorkspaceFolder.fromJson(item as Map<String, Object?>))
        .toList();
    return WorkspaceFoldersChangeEvent(
      added: added,
      removed: removed,
    );
  }

  /// The array of added workspace folders
  final List<WorkspaceFolder> added;

  /// The array of the removed workspace folders
  final List<WorkspaceFolder> removed;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['added'] = added.map((item) => item.toJson()).toList();
    result['removed'] = removed.map((item) => item.toJson()).toList();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListWorkspaceFolder(obj, reporter, 'added',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseListWorkspaceFolder(obj, reporter, 'removed',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type WorkspaceFoldersChangeEvent');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WorkspaceFoldersChangeEvent &&
        other.runtimeType == WorkspaceFoldersChangeEvent &&
        listEqual(added, other.added,
            (WorkspaceFolder a, WorkspaceFolder b) => a == b) &&
        listEqual(removed, other.removed,
            (WorkspaceFolder a, WorkspaceFolder b) => a == b);
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(added),
        lspHashCode(removed),
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WorkspaceFoldersServerCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceFoldersServerCapabilities.canParse,
    WorkspaceFoldersServerCapabilities.fromJson,
  );

  WorkspaceFoldersServerCapabilities({
    this.changeNotifications,
    this.supported,
  });
  static WorkspaceFoldersServerCapabilities fromJson(
      Map<String, Object?> json) {
    final changeNotificationsJson = json['changeNotifications'];
    final changeNotifications = changeNotificationsJson == null
        ? null
        : _eitherBoolString(changeNotificationsJson);
    final supportedJson = json['supported'];
    final supported = supportedJson as bool?;
    return WorkspaceFoldersServerCapabilities(
      changeNotifications: changeNotifications,
      supported: supported,
    );
  }

  /// Whether the server wants to receive workspace folder change notifications.
  ///
  /// If a string is provided the string is treated as an ID under which the
  /// notification is registered on the client side. The ID can be used to
  /// unregister for these events using the `client/unregisterCapability`
  /// request.
  final Either2<bool, String>? changeNotifications;

  /// The server has support for workspace folders
  final bool? supported;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (changeNotifications != null) {
      result['changeNotifications'] = changeNotifications;
    }
    if (supported != null) {
      result['supported'] = supported;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseBoolString(obj, reporter, 'changeNotifications',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'supported',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter
          .reportError('must be of type WorkspaceFoldersServerCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WorkspaceFoldersServerCapabilities &&
        other.runtimeType == WorkspaceFoldersServerCapabilities &&
        changeNotifications == other.changeNotifications &&
        supported == other.supported;
  }

  @override
  int get hashCode => Object.hash(
        changeNotifications,
        supported,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A full document diagnostic report for a workspace diagnostic result.
///
/// @since 3.17.0
class WorkspaceFullDocumentDiagnosticReport
    implements FullDocumentDiagnosticReport, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceFullDocumentDiagnosticReport.canParse,
    WorkspaceFullDocumentDiagnosticReport.fromJson,
  );

  WorkspaceFullDocumentDiagnosticReport({
    required this.items,
    this.kind = 'full',
    this.resultId,
    required this.uri,
    this.version,
  }) {
    if (kind != 'full') {
      throw 'kind may only be the literal \'full\'';
    }
  }
  static WorkspaceFullDocumentDiagnosticReport fromJson(
      Map<String, Object?> json) {
    final itemsJson = json['items'];
    final items = (itemsJson as List<Object?>)
        .map((item) => Diagnostic.fromJson(item as Map<String, Object?>))
        .toList();
    final kindJson = json['kind'];
    final kind = kindJson as String;
    final resultIdJson = json['resultId'];
    final resultId = resultIdJson as String?;
    final uriJson = json['uri'];
    final uri = uriJson as String;
    final versionJson = json['version'];
    final version = versionJson as int?;
    return WorkspaceFullDocumentDiagnosticReport(
      items: items,
      kind: kind,
      resultId: resultId,
      uri: uri,
      version: version,
    );
  }

  /// The actual items.
  @override
  final List<Diagnostic> items;

  /// A full document diagnostic report.
  @override
  final String kind;

  /// An optional result id. If provided it will be sent on the next diagnostic
  /// request for the same document.
  @override
  final String? resultId;

  /// The URI for which diagnostic information is reported.
  final DocumentUri uri;

  /// The version number for which the diagnostics are reported. If the document
  /// is not marked as open `null` can be provided.
  final int? version;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['items'] = items.map((item) => item.toJson()).toList();
    result['kind'] = kind;
    if (resultId != null) {
      result['resultId'] = resultId;
    }
    result['uri'] = uri;
    result['version'] = version;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseListDiagnostic(obj, reporter, 'items',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseLiteral(obj, reporter, 'kind',
          allowsUndefined: false, allowsNull: false, literal: 'full')) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'resultId',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'uri',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseInt(obj, reporter, 'version',
          allowsUndefined: false, allowsNull: true);
    } else {
      reporter
          .reportError('must be of type WorkspaceFullDocumentDiagnosticReport');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WorkspaceFullDocumentDiagnosticReport &&
        other.runtimeType == WorkspaceFullDocumentDiagnosticReport &&
        listEqual(items, other.items, (Diagnostic a, Diagnostic b) => a == b) &&
        kind == other.kind &&
        resultId == other.resultId &&
        uri == other.uri &&
        version == other.version;
  }

  @override
  int get hashCode => Object.hash(
        lspHashCode(items),
        kind,
        resultId,
        uri,
        version,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// A special workspace symbol that supports locations without a range.
///
/// See also SymbolInformation.
///
/// @since 3.17.0
class WorkspaceSymbol implements BaseSymbolInformation, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceSymbol.canParse,
    WorkspaceSymbol.fromJson,
  );

  WorkspaceSymbol({
    this.containerName,
    this.data,
    required this.kind,
    required this.location,
    required this.name,
    this.tags,
  });
  static WorkspaceSymbol fromJson(Map<String, Object?> json) {
    final containerNameJson = json['containerName'];
    final containerName = containerNameJson as String?;
    final dataJson = json['data'];
    final data = dataJson;
    final kindJson = json['kind'];
    final kind = SymbolKind.fromJson(kindJson as int);
    final locationJson = json['location'];
    final location = _eitherLocationWorkspaceSymbolLocation(locationJson);
    final nameJson = json['name'];
    final name = nameJson as String;
    final tagsJson = json['tags'];
    final tags = (tagsJson as List<Object?>?)
        ?.map((item) => SymbolTag.fromJson(item as int))
        .toList();
    return WorkspaceSymbol(
      containerName: containerName,
      data: data,
      kind: kind,
      location: location,
      name: name,
      tags: tags,
    );
  }

  /// The name of the symbol containing this symbol. This information is for
  /// user interface purposes (e.g. to render a qualifier in the user interface
  /// if necessary). It can't be used to re-infer a hierarchy for the document
  /// symbols.
  @override
  final String? containerName;

  /// A data entry field that is preserved on a workspace symbol between a
  /// workspace symbol request and a workspace symbol resolve request.
  final LSPAny data;

  /// The kind of this symbol.
  @override
  final SymbolKind kind;

  /// The location of the symbol. Whether a server is allowed to return a
  /// location without a range depends on the client capability
  /// `workspace.symbol.resolveSupport`.
  ///
  /// See SymbolInformation#location for more details.
  final Either2<Location, WorkspaceSymbolLocation> location;

  /// The name of this symbol.
  @override
  final String name;

  /// Tags for this symbol.
  ///
  /// @since 3.16.0
  @override
  final List<SymbolTag>? tags;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (containerName != null) {
      result['containerName'] = containerName;
    }
    if (data != null) {
      result['data'] = data;
    }
    result['kind'] = kind.toJson();
    result['location'] = location;
    result['name'] = name;
    if (tags != null) {
      result['tags'] = tags?.map((item) => item.toJson()).toList();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseString(obj, reporter, 'containerName',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseSymbolKind(obj, reporter, 'kind',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseLocationWorkspaceSymbolLocation(obj, reporter, 'location',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'name',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseListSymbolTag(obj, reporter, 'tags',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type WorkspaceSymbol');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WorkspaceSymbol &&
        other.runtimeType == WorkspaceSymbol &&
        containerName == other.containerName &&
        data == other.data &&
        kind == other.kind &&
        location == other.location &&
        name == other.name &&
        listEqual(tags, other.tags, (SymbolTag a, SymbolTag b) => a == b);
  }

  @override
  int get hashCode => Object.hash(
        containerName,
        data,
        kind,
        location,
        name,
        lspHashCode(tags),
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Client capabilities for a WorkspaceSymbolRequest.
class WorkspaceSymbolClientCapabilities implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceSymbolClientCapabilities.canParse,
    WorkspaceSymbolClientCapabilities.fromJson,
  );

  WorkspaceSymbolClientCapabilities({
    this.dynamicRegistration,
    this.resolveSupport,
    this.symbolKind,
    this.tagSupport,
  });
  static WorkspaceSymbolClientCapabilities fromJson(Map<String, Object?> json) {
    final dynamicRegistrationJson = json['dynamicRegistration'];
    final dynamicRegistration = dynamicRegistrationJson as bool?;
    final resolveSupportJson = json['resolveSupport'];
    final resolveSupport = resolveSupportJson != null
        ? WorkspaceSymbolClientCapabilitiesResolveSupport.fromJson(
            resolveSupportJson as Map<String, Object?>)
        : null;
    final symbolKindJson = json['symbolKind'];
    final symbolKind = symbolKindJson != null
        ? WorkspaceSymbolClientCapabilitiesSymbolKind.fromJson(
            symbolKindJson as Map<String, Object?>)
        : null;
    final tagSupportJson = json['tagSupport'];
    final tagSupport = tagSupportJson != null
        ? WorkspaceSymbolClientCapabilitiesTagSupport.fromJson(
            tagSupportJson as Map<String, Object?>)
        : null;
    return WorkspaceSymbolClientCapabilities(
      dynamicRegistration: dynamicRegistration,
      resolveSupport: resolveSupport,
      symbolKind: symbolKind,
      tagSupport: tagSupport,
    );
  }

  /// Symbol request supports dynamic registration.
  final bool? dynamicRegistration;

  /// The client support partial workspace symbols. The client will send the
  /// request `workspaceSymbol/resolve` to the server to resolve additional
  /// properties.
  ///
  /// @since 3.17.0
  final WorkspaceSymbolClientCapabilitiesResolveSupport? resolveSupport;

  /// 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;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (dynamicRegistration != null) {
      result['dynamicRegistration'] = dynamicRegistration;
    }
    if (resolveSupport != null) {
      result['resolveSupport'] = resolveSupport?.toJson();
    }
    if (symbolKind != null) {
      result['symbolKind'] = symbolKind?.toJson();
    }
    if (tagSupport != null) {
      result['tagSupport'] = tagSupport?.toJson();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseBool(obj, reporter, 'dynamicRegistration',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseWorkspaceSymbolClientCapabilitiesResolveSupport(
          obj, reporter, 'resolveSupport',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseWorkspaceSymbolClientCapabilitiesSymbolKind(
          obj, reporter, 'symbolKind',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseWorkspaceSymbolClientCapabilitiesTagSupport(
          obj, reporter, 'tagSupport',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type WorkspaceSymbolClientCapabilities');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WorkspaceSymbolClientCapabilities &&
        other.runtimeType == WorkspaceSymbolClientCapabilities &&
        dynamicRegistration == other.dynamicRegistration &&
        resolveSupport == other.resolveSupport &&
        symbolKind == other.symbolKind &&
        tagSupport == other.tagSupport;
  }

  @override
  int get hashCode => Object.hash(
        dynamicRegistration,
        resolveSupport,
        symbolKind,
        tagSupport,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WorkspaceSymbolClientCapabilitiesResolveSupport implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceSymbolClientCapabilitiesResolveSupport.canParse,
    WorkspaceSymbolClientCapabilitiesResolveSupport.fromJson,
  );

  WorkspaceSymbolClientCapabilitiesResolveSupport({
    required this.properties,
  });
  static WorkspaceSymbolClientCapabilitiesResolveSupport fromJson(
      Map<String, Object?> json) {
    final propertiesJson = json['properties'];
    final properties = (propertiesJson as List<Object?>)
        .map((item) => item as String)
        .toList();
    return WorkspaceSymbolClientCapabilitiesResolveSupport(
      properties: properties,
    );
  }

  /// The properties that a client can resolve lazily. Usually `location.range`
  final List<String> properties;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['properties'] = properties;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseListString(obj, reporter, 'properties',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError(
          'must be of type WorkspaceSymbolClientCapabilitiesResolveSupport');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WorkspaceSymbolClientCapabilitiesResolveSupport &&
        other.runtimeType == WorkspaceSymbolClientCapabilitiesResolveSupport &&
        listEqual(properties, other.properties, (String a, String b) => a == b);
  }

  @override
  int get hashCode => lspHashCode(properties);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WorkspaceSymbolClientCapabilitiesSymbolKind implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceSymbolClientCapabilitiesSymbolKind.canParse,
    WorkspaceSymbolClientCapabilitiesSymbolKind.fromJson,
  );

  WorkspaceSymbolClientCapabilitiesSymbolKind({
    this.valueSet,
  });
  static WorkspaceSymbolClientCapabilitiesSymbolKind fromJson(
      Map<String, Object?> json) {
    final valueSetJson = json['valueSet'];
    final valueSet = (valueSetJson as List<Object?>?)
        ?.map((item) => SymbolKind.fromJson(item as int))
        .toList();
    return WorkspaceSymbolClientCapabilitiesSymbolKind(
      valueSet: valueSet,
    );
  }

  /// The symbol kind values the client supports. When this property exists the
  /// client also guarantees that it will handle values outside its set
  /// gracefully and falls back to a default value when unknown.
  ///
  /// If this property is not present the client only supports the symbol kinds
  /// from `File` to `Array` as defined in the initial version of the protocol.
  final List<SymbolKind>? valueSet;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (valueSet != null) {
      result['valueSet'] = valueSet?.map((item) => item.toJson()).toList();
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseListSymbolKind(obj, reporter, 'valueSet',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError(
          'must be of type WorkspaceSymbolClientCapabilitiesSymbolKind');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WorkspaceSymbolClientCapabilitiesSymbolKind &&
        other.runtimeType == WorkspaceSymbolClientCapabilitiesSymbolKind &&
        listEqual(
            valueSet, other.valueSet, (SymbolKind a, SymbolKind b) => a == b);
  }

  @override
  int get hashCode => lspHashCode(valueSet);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WorkspaceSymbolClientCapabilitiesTagSupport implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceSymbolClientCapabilitiesTagSupport.canParse,
    WorkspaceSymbolClientCapabilitiesTagSupport.fromJson,
  );

  WorkspaceSymbolClientCapabilitiesTagSupport({
    required this.valueSet,
  });
  static WorkspaceSymbolClientCapabilitiesTagSupport fromJson(
      Map<String, Object?> json) {
    final valueSetJson = json['valueSet'];
    final valueSet = (valueSetJson as List<Object?>)
        .map((item) => SymbolTag.fromJson(item as int))
        .toList();
    return WorkspaceSymbolClientCapabilitiesTagSupport(
      valueSet: valueSet,
    );
  }

  /// The tags supported by the client.
  final List<SymbolTag> valueSet;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['valueSet'] = valueSet.map((item) => item.toJson()).toList();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseListSymbolTag(obj, reporter, 'valueSet',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError(
          'must be of type WorkspaceSymbolClientCapabilitiesTagSupport');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WorkspaceSymbolClientCapabilitiesTagSupport &&
        other.runtimeType == WorkspaceSymbolClientCapabilitiesTagSupport &&
        listEqual(
            valueSet, other.valueSet, (SymbolTag a, SymbolTag b) => a == b);
  }

  @override
  int get hashCode => lspHashCode(valueSet);

  @override
  String toString() => jsonEncoder.convert(toJson());
}

class WorkspaceSymbolLocation implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceSymbolLocation.canParse,
    WorkspaceSymbolLocation.fromJson,
  );

  WorkspaceSymbolLocation({
    required this.uri,
  });
  static WorkspaceSymbolLocation fromJson(Map<String, Object?> json) {
    final uriJson = json['uri'];
    final uri = uriJson as String;
    return WorkspaceSymbolLocation(
      uri: uri,
    );
  }

  final DocumentUri uri;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['uri'] = uri;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseString(obj, reporter, 'uri',
          allowsUndefined: false, allowsNull: false);
    } else {
      reporter.reportError('must be of type WorkspaceSymbolLocation');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WorkspaceSymbolLocation &&
        other.runtimeType == WorkspaceSymbolLocation &&
        uri == other.uri;
  }

  @override
  int get hashCode => uri.hashCode;

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Server capabilities for a WorkspaceSymbolRequest.
class WorkspaceSymbolOptions implements WorkDoneProgressOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceSymbolOptions.canParse,
    WorkspaceSymbolOptions.fromJson,
  );

  WorkspaceSymbolOptions({
    this.resolveProvider,
    this.workDoneProgress,
  });
  static WorkspaceSymbolOptions fromJson(Map<String, Object?> json) {
    if (WorkspaceSymbolRegistrationOptions.canParse(
        json, nullLspJsonReporter)) {
      return WorkspaceSymbolRegistrationOptions.fromJson(json);
    }
    final resolveProviderJson = json['resolveProvider'];
    final resolveProvider = resolveProviderJson as bool?;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return WorkspaceSymbolOptions(
      resolveProvider: resolveProvider,
      workDoneProgress: workDoneProgress,
    );
  }

  /// The server provides support to resolve additional information for a
  /// workspace symbol.
  ///
  /// @since 3.17.0
  final bool? resolveProvider;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (resolveProvider != null) {
      result['resolveProvider'] = resolveProvider;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseBool(obj, reporter, 'resolveProvider',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'workDoneProgress',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type WorkspaceSymbolOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WorkspaceSymbolOptions &&
        other.runtimeType == WorkspaceSymbolOptions &&
        resolveProvider == other.resolveProvider &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        resolveProvider,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// The parameters of a WorkspaceSymbolRequest.
class WorkspaceSymbolParams
    implements PartialResultParams, WorkDoneProgressParams, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceSymbolParams.canParse,
    WorkspaceSymbolParams.fromJson,
  );

  WorkspaceSymbolParams({
    this.partialResultToken,
    required this.query,
    this.workDoneToken,
  });
  static WorkspaceSymbolParams fromJson(Map<String, Object?> json) {
    final partialResultTokenJson = json['partialResultToken'];
    final partialResultToken = partialResultTokenJson == null
        ? null
        : _eitherIntString(partialResultTokenJson);
    final queryJson = json['query'];
    final query = queryJson as String;
    final workDoneTokenJson = json['workDoneToken'];
    final workDoneToken =
        workDoneTokenJson == null ? null : _eitherIntString(workDoneTokenJson);
    return WorkspaceSymbolParams(
      partialResultToken: partialResultToken,
      query: query,
      workDoneToken: workDoneToken,
    );
  }

  /// An optional token that a server can use to report partial results (e.g.
  /// streaming) to the client.
  @override
  final ProgressToken? partialResultToken;

  /// A query string to filter symbols by. Clients may send an empty string here
  /// to request all symbols.
  final String query;

  /// An optional token that a server can use to report work done progress.
  @override
  final ProgressToken? workDoneToken;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (partialResultToken != null) {
      result['partialResultToken'] = partialResultToken;
    }
    result['query'] = query;
    if (workDoneToken != null) {
      result['workDoneToken'] = workDoneToken;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseIntString(obj, reporter, 'partialResultToken',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'query',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseIntString(obj, reporter, 'workDoneToken',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter.reportError('must be of type WorkspaceSymbolParams');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WorkspaceSymbolParams &&
        other.runtimeType == WorkspaceSymbolParams &&
        partialResultToken == other.partialResultToken &&
        query == other.query &&
        workDoneToken == other.workDoneToken;
  }

  @override
  int get hashCode => Object.hash(
        partialResultToken,
        query,
        workDoneToken,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// Registration options for a WorkspaceSymbolRequest.
class WorkspaceSymbolRegistrationOptions
    implements WorkspaceSymbolOptions, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceSymbolRegistrationOptions.canParse,
    WorkspaceSymbolRegistrationOptions.fromJson,
  );

  WorkspaceSymbolRegistrationOptions({
    this.resolveProvider,
    this.workDoneProgress,
  });
  static WorkspaceSymbolRegistrationOptions fromJson(
      Map<String, Object?> json) {
    final resolveProviderJson = json['resolveProvider'];
    final resolveProvider = resolveProviderJson as bool?;
    final workDoneProgressJson = json['workDoneProgress'];
    final workDoneProgress = workDoneProgressJson as bool?;
    return WorkspaceSymbolRegistrationOptions(
      resolveProvider: resolveProvider,
      workDoneProgress: workDoneProgress,
    );
  }

  /// The server provides support to resolve additional information for a
  /// workspace symbol.
  ///
  /// @since 3.17.0
  @override
  final bool? resolveProvider;
  @override
  final bool? workDoneProgress;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    if (resolveProvider != null) {
      result['resolveProvider'] = resolveProvider;
    }
    if (workDoneProgress != null) {
      result['workDoneProgress'] = workDoneProgress;
    }
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseBool(obj, reporter, 'resolveProvider',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseBool(obj, reporter, 'workDoneProgress',
          allowsUndefined: true, allowsNull: false);
    } else {
      reporter
          .reportError('must be of type WorkspaceSymbolRegistrationOptions');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WorkspaceSymbolRegistrationOptions &&
        other.runtimeType == WorkspaceSymbolRegistrationOptions &&
        resolveProvider == other.resolveProvider &&
        workDoneProgress == other.workDoneProgress;
  }

  @override
  int get hashCode => Object.hash(
        resolveProvider,
        workDoneProgress,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

/// An unchanged document diagnostic report for a workspace diagnostic result.
///
/// @since 3.17.0
class WorkspaceUnchangedDocumentDiagnosticReport
    implements UnchangedDocumentDiagnosticReport, ToJsonable {
  static const jsonHandler = LspJsonHandler(
    WorkspaceUnchangedDocumentDiagnosticReport.canParse,
    WorkspaceUnchangedDocumentDiagnosticReport.fromJson,
  );

  WorkspaceUnchangedDocumentDiagnosticReport({
    this.kind = 'unchanged',
    required this.resultId,
    required this.uri,
    this.version,
  }) {
    if (kind != 'unchanged') {
      throw 'kind may only be the literal \'unchanged\'';
    }
  }
  static WorkspaceUnchangedDocumentDiagnosticReport fromJson(
      Map<String, Object?> json) {
    final kindJson = json['kind'];
    final kind = kindJson as String;
    final resultIdJson = json['resultId'];
    final resultId = resultIdJson as String;
    final uriJson = json['uri'];
    final uri = uriJson as String;
    final versionJson = json['version'];
    final version = versionJson as int?;
    return WorkspaceUnchangedDocumentDiagnosticReport(
      kind: kind,
      resultId: resultId,
      uri: uri,
      version: version,
    );
  }

  /// A document diagnostic report indicating no changes to the last result. A
  /// server can only return `unchanged` if result ids are provided.
  @override
  final String kind;

  /// A result id which will be sent on the next diagnostic request for the same
  /// document.
  @override
  final String resultId;

  /// The URI for which diagnostic information is reported.
  final DocumentUri uri;

  /// The version number for which the diagnostics are reported. If the document
  /// is not marked as open `null` can be provided.
  final int? version;

  @override
  Map<String, Object?> toJson() {
    var result = <String, Object?>{};
    result['kind'] = kind;
    result['resultId'] = resultId;
    result['uri'] = uri;
    result['version'] = version;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseLiteral(obj, reporter, 'kind',
          allowsUndefined: false, allowsNull: false, literal: 'unchanged')) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'resultId',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseString(obj, reporter, 'uri',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      return _canParseInt(obj, reporter, 'version',
          allowsUndefined: false, allowsNull: true);
    } else {
      reporter.reportError(
          'must be of type WorkspaceUnchangedDocumentDiagnosticReport');
      return false;
    }
  }

  @override
  bool operator ==(Object other) {
    return other is WorkspaceUnchangedDocumentDiagnosticReport &&
        other.runtimeType == WorkspaceUnchangedDocumentDiagnosticReport &&
        kind == other.kind &&
        resultId == other.resultId &&
        uri == other.uri &&
        version == other.version;
  }

  @override
  int get hashCode => Object.hash(
        kind,
        resultId,
        uri,
        version,
      );

  @override
  String toString() => jsonEncoder.convert(toJson());
}

bool _canParseBool(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) && value is! bool) {
      reporter.reportError('must be of type bool');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseBoolCallHierarchyOptionsCallHierarchyRegistrationOptions(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! bool &&
            !CallHierarchyOptions.canParse(value, reporter) &&
            !CallHierarchyRegistrationOptions.canParse(value, reporter))) {
      reporter.reportError(
          'must be of type Either3<bool, CallHierarchyOptions, CallHierarchyRegistrationOptions>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseBoolCodeActionOptions(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! bool && !CodeActionOptions.canParse(value, reporter))) {
      reporter.reportError('must be of type Either2<bool, CodeActionOptions>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseBoolDeclarationOptionsDeclarationRegistrationOptions(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! bool &&
            !DeclarationOptions.canParse(value, reporter) &&
            !DeclarationRegistrationOptions.canParse(value, reporter))) {
      reporter.reportError(
          'must be of type Either3<bool, DeclarationOptions, DeclarationRegistrationOptions>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseBoolDefinitionOptions(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! bool && !DefinitionOptions.canParse(value, reporter))) {
      reporter.reportError('must be of type Either2<bool, DefinitionOptions>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseBoolDocumentColorOptionsDocumentColorRegistrationOptions(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! bool &&
            !DocumentColorOptions.canParse(value, reporter) &&
            !DocumentColorRegistrationOptions.canParse(value, reporter))) {
      reporter.reportError(
          'must be of type Either3<bool, DocumentColorOptions, DocumentColorRegistrationOptions>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseBoolDocumentFormattingOptions(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! bool &&
            !DocumentFormattingOptions.canParse(value, reporter))) {
      reporter.reportError(
          'must be of type Either2<bool, DocumentFormattingOptions>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseBoolDocumentHighlightOptions(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! bool &&
            !DocumentHighlightOptions.canParse(value, reporter))) {
      reporter.reportError(
          'must be of type Either2<bool, DocumentHighlightOptions>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseBoolDocumentRangeFormattingOptions(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! bool &&
            !DocumentRangeFormattingOptions.canParse(value, reporter))) {
      reporter.reportError(
          'must be of type Either2<bool, DocumentRangeFormattingOptions>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseBoolDocumentSymbolOptions(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! bool && !DocumentSymbolOptions.canParse(value, reporter))) {
      reporter
          .reportError('must be of type Either2<bool, DocumentSymbolOptions>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseBoolFoldingRangeOptionsFoldingRangeRegistrationOptions(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! bool &&
            !FoldingRangeOptions.canParse(value, reporter) &&
            !FoldingRangeRegistrationOptions.canParse(value, reporter))) {
      reporter.reportError(
          'must be of type Either3<bool, FoldingRangeOptions, FoldingRangeRegistrationOptions>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseBoolHoverOptions(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! bool && !HoverOptions.canParse(value, reporter))) {
      reporter.reportError('must be of type Either2<bool, HoverOptions>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseBoolImplementationOptionsImplementationRegistrationOptions(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! bool &&
            !ImplementationOptions.canParse(value, reporter) &&
            !ImplementationRegistrationOptions.canParse(value, reporter))) {
      reporter.reportError(
          'must be of type Either3<bool, ImplementationOptions, ImplementationRegistrationOptions>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseBoolInlayHintOptionsInlayHintRegistrationOptions(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! bool &&
            !InlayHintOptions.canParse(value, reporter) &&
            !InlayHintRegistrationOptions.canParse(value, reporter))) {
      reporter.reportError(
          'must be of type Either3<bool, InlayHintOptions, InlayHintRegistrationOptions>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseBoolInlineValueOptionsInlineValueRegistrationOptions(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! bool &&
            !InlineValueOptions.canParse(value, reporter) &&
            !InlineValueRegistrationOptions.canParse(value, reporter))) {
      reporter.reportError(
          'must be of type Either3<bool, InlineValueOptions, InlineValueRegistrationOptions>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool
    _canParseBoolLinkedEditingRangeOptionsLinkedEditingRangeRegistrationOptions(
        Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
        {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! bool &&
            !LinkedEditingRangeOptions.canParse(value, reporter) &&
            !LinkedEditingRangeRegistrationOptions.canParse(value, reporter))) {
      reporter.reportError(
          'must be of type Either3<bool, LinkedEditingRangeOptions, LinkedEditingRangeRegistrationOptions>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseBoolMonikerOptionsMonikerRegistrationOptions(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! bool &&
            !MonikerOptions.canParse(value, reporter) &&
            !MonikerRegistrationOptions.canParse(value, reporter))) {
      reporter.reportError(
          'must be of type Either3<bool, MonikerOptions, MonikerRegistrationOptions>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseBoolReferenceOptions(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! bool && !ReferenceOptions.canParse(value, reporter))) {
      reporter.reportError('must be of type Either2<bool, ReferenceOptions>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseBoolRenameOptions(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! bool && !RenameOptions.canParse(value, reporter))) {
      reporter.reportError('must be of type Either2<bool, RenameOptions>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseBoolSaveOptions(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! bool && !SaveOptions.canParse(value, reporter))) {
      reporter.reportError('must be of type Either2<bool, SaveOptions>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseBoolSelectionRangeOptionsSelectionRangeRegistrationOptions(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! bool &&
            !SelectionRangeOptions.canParse(value, reporter) &&
            !SelectionRangeRegistrationOptions.canParse(value, reporter))) {
      reporter.reportError(
          'must be of type Either3<bool, SelectionRangeOptions, SelectionRangeRegistrationOptions>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseBoolSemanticTokensClientCapabilitiesRequestsFull(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! bool &&
            !SemanticTokensClientCapabilitiesRequestsFull.canParse(
                value, reporter))) {
      reporter.reportError(
          'must be of type Either2<bool, SemanticTokensClientCapabilitiesRequestsFull>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseBoolSemanticTokensClientCapabilitiesRequestsRange(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! bool &&
            !SemanticTokensClientCapabilitiesRequestsRange.canParse(
                value, reporter))) {
      reporter.reportError(
          'must be of type Either2<bool, SemanticTokensClientCapabilitiesRequestsRange>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseBoolSemanticTokensOptionsFull(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! bool &&
            !SemanticTokensOptionsFull.canParse(value, reporter))) {
      reporter.reportError(
          'must be of type Either2<bool, SemanticTokensOptionsFull>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseBoolSemanticTokensOptionsRange(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! bool &&
            !SemanticTokensOptionsRange.canParse(value, reporter))) {
      reporter.reportError(
          'must be of type Either2<bool, SemanticTokensOptionsRange>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseBoolString(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) && (value is! bool && value is! String)) {
      reporter.reportError('must be of type Either2<bool, String>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseBoolTypeDefinitionOptionsTypeDefinitionRegistrationOptions(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! bool &&
            !TypeDefinitionOptions.canParse(value, reporter) &&
            !TypeDefinitionRegistrationOptions.canParse(value, reporter))) {
      reporter.reportError(
          'must be of type Either3<bool, TypeDefinitionOptions, TypeDefinitionRegistrationOptions>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseBoolTypeHierarchyOptionsTypeHierarchyRegistrationOptions(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! bool &&
            !TypeHierarchyOptions.canParse(value, reporter) &&
            !TypeHierarchyRegistrationOptions.canParse(value, reporter))) {
      reporter.reportError(
          'must be of type Either3<bool, TypeHierarchyOptions, TypeHierarchyRegistrationOptions>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseBoolWorkspaceSymbolOptions(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! bool && !WorkspaceSymbolOptions.canParse(value, reporter))) {
      reporter
          .reportError('must be of type Either2<bool, WorkspaceSymbolOptions>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseCallHierarchyClientCapabilities(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !CallHierarchyClientCapabilities.canParse(value, reporter)) {
      reporter.reportError('must be of type CallHierarchyClientCapabilities');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseCallHierarchyItem(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !CallHierarchyItem.canParse(value, reporter)) {
      reporter.reportError('must be of type CallHierarchyItem');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseClientCapabilities(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !ClientCapabilities.canParse(value, reporter)) {
      reporter.reportError('must be of type ClientCapabilities');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseCodeActionClientCapabilities(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !CodeActionClientCapabilities.canParse(value, reporter)) {
      reporter.reportError('must be of type CodeActionClientCapabilities');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseCodeActionClientCapabilitiesCodeActionLiteralSupport(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !CodeActionClientCapabilitiesCodeActionLiteralSupport.canParse(
            value, reporter)) {
      reporter.reportError(
          'must be of type CodeActionClientCapabilitiesCodeActionLiteralSupport');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseCodeActionClientCapabilitiesResolveSupport(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !CodeActionClientCapabilitiesResolveSupport.canParse(value, reporter)) {
      reporter.reportError(
          'must be of type CodeActionClientCapabilitiesResolveSupport');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseCodeActionContext(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !CodeActionContext.canParse(value, reporter)) {
      reporter.reportError('must be of type CodeActionContext');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseCodeActionDisabled(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !CodeActionDisabled.canParse(value, reporter)) {
      reporter.reportError('must be of type CodeActionDisabled');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseCodeActionKind(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !CodeActionKind.canParse(value, reporter)) {
      reporter.reportError('must be of type CodeActionKind');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseCodeActionLiteralSupportCodeActionKind(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !CodeActionLiteralSupportCodeActionKind.canParse(value, reporter)) {
      reporter.reportError(
          'must be of type CodeActionLiteralSupportCodeActionKind');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseCodeActionTriggerKind(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !CodeActionTriggerKind.canParse(value, reporter)) {
      reporter.reportError('must be of type CodeActionTriggerKind');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseCodeDescription(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !CodeDescription.canParse(value, reporter)) {
      reporter.reportError('must be of type CodeDescription');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseCodeLensClientCapabilities(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !CodeLensClientCapabilities.canParse(value, reporter)) {
      reporter.reportError('must be of type CodeLensClientCapabilities');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseCodeLensOptions(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !CodeLensOptions.canParse(value, reporter)) {
      reporter.reportError('must be of type CodeLensOptions');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseCodeLensWorkspaceClientCapabilities(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !CodeLensWorkspaceClientCapabilities.canParse(value, reporter)) {
      reporter
          .reportError('must be of type CodeLensWorkspaceClientCapabilities');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseColor(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) && !Color.canParse(value, reporter)) {
      reporter.reportError('must be of type Color');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseCommand(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) && !Command.canParse(value, reporter)) {
      reporter.reportError('must be of type Command');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseCompletionClientCapabilities(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !CompletionClientCapabilities.canParse(value, reporter)) {
      reporter.reportError('must be of type CompletionClientCapabilities');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseCompletionClientCapabilitiesCompletionItem(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !CompletionClientCapabilitiesCompletionItem.canParse(value, reporter)) {
      reporter.reportError(
          'must be of type CompletionClientCapabilitiesCompletionItem');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseCompletionClientCapabilitiesCompletionItemKind(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !CompletionClientCapabilitiesCompletionItemKind.canParse(
            value, reporter)) {
      reporter.reportError(
          'must be of type CompletionClientCapabilitiesCompletionItemKind');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseCompletionClientCapabilitiesCompletionList(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !CompletionClientCapabilitiesCompletionList.canParse(value, reporter)) {
      reporter.reportError(
          'must be of type CompletionClientCapabilitiesCompletionList');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseCompletionContext(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !CompletionContext.canParse(value, reporter)) {
      reporter.reportError('must be of type CompletionContext');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseCompletionItemEditRangeRange(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (!CompletionItemEditRange.canParse(value, reporter) &&
            !Range.canParse(value, reporter))) {
      reporter.reportError(
          'must be of type Either2<CompletionItemEditRange, Range>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseCompletionItemInsertTextModeSupport(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !CompletionItemInsertTextModeSupport.canParse(value, reporter)) {
      reporter
          .reportError('must be of type CompletionItemInsertTextModeSupport');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseCompletionItemKind(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !CompletionItemKind.canParse(value, reporter)) {
      reporter.reportError('must be of type CompletionItemKind');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseCompletionItemLabelDetails(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !CompletionItemLabelDetails.canParse(value, reporter)) {
      reporter.reportError('must be of type CompletionItemLabelDetails');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseCompletionItemResolutionInfo(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !CompletionItemResolutionInfo.canParse(value, reporter)) {
      reporter.reportError('must be of type CompletionItemResolutionInfo');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseCompletionItemResolveSupport(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !CompletionItemResolveSupport.canParse(value, reporter)) {
      reporter.reportError('must be of type CompletionItemResolveSupport');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseCompletionItemTagSupport(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !CompletionItemTagSupport.canParse(value, reporter)) {
      reporter.reportError('must be of type CompletionItemTagSupport');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseCompletionListItemDefaults(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !CompletionListItemDefaults.canParse(value, reporter)) {
      reporter.reportError('must be of type CompletionListItemDefaults');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseCompletionOptions(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !CompletionOptions.canParse(value, reporter)) {
      reporter.reportError('must be of type CompletionOptions');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseCompletionOptionsCompletionItem(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !CompletionOptionsCompletionItem.canParse(value, reporter)) {
      reporter.reportError('must be of type CompletionOptionsCompletionItem');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseCompletionTriggerKind(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !CompletionTriggerKind.canParse(value, reporter)) {
      reporter.reportError('must be of type CompletionTriggerKind');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseCreateFileOptions(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !CreateFileOptions.canParse(value, reporter)) {
      reporter.reportError('must be of type CreateFileOptions');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseDeclarationClientCapabilities(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !DeclarationClientCapabilities.canParse(value, reporter)) {
      reporter.reportError('must be of type DeclarationClientCapabilities');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseDefinitionClientCapabilities(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !DefinitionClientCapabilities.canParse(value, reporter)) {
      reporter.reportError('must be of type DefinitionClientCapabilities');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseDeleteFileOptions(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !DeleteFileOptions.canParse(value, reporter)) {
      reporter.reportError('must be of type DeleteFileOptions');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseDiagnosticClientCapabilities(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !DiagnosticClientCapabilities.canParse(value, reporter)) {
      reporter.reportError('must be of type DiagnosticClientCapabilities');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseDiagnosticOptionsDiagnosticRegistrationOptions(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (!DiagnosticOptions.canParse(value, reporter) &&
            !DiagnosticRegistrationOptions.canParse(value, reporter))) {
      reporter.reportError(
          'must be of type Either2<DiagnosticOptions, DiagnosticRegistrationOptions>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseDiagnosticSeverity(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !DiagnosticSeverity.canParse(value, reporter)) {
      reporter.reportError('must be of type DiagnosticSeverity');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseDiagnosticWorkspaceClientCapabilities(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !DiagnosticWorkspaceClientCapabilities.canParse(value, reporter)) {
      reporter
          .reportError('must be of type DiagnosticWorkspaceClientCapabilities');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseDidChangeConfigurationClientCapabilities(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !DidChangeConfigurationClientCapabilities.canParse(value, reporter)) {
      reporter.reportError(
          'must be of type DidChangeConfigurationClientCapabilities');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseDidChangeWatchedFilesClientCapabilities(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !DidChangeWatchedFilesClientCapabilities.canParse(value, reporter)) {
      reporter.reportError(
          'must be of type DidChangeWatchedFilesClientCapabilities');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseDocumentColorClientCapabilities(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !DocumentColorClientCapabilities.canParse(value, reporter)) {
      reporter.reportError('must be of type DocumentColorClientCapabilities');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseDocumentFormattingClientCapabilities(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !DocumentFormattingClientCapabilities.canParse(value, reporter)) {
      reporter
          .reportError('must be of type DocumentFormattingClientCapabilities');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseDocumentHighlightClientCapabilities(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !DocumentHighlightClientCapabilities.canParse(value, reporter)) {
      reporter
          .reportError('must be of type DocumentHighlightClientCapabilities');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseDocumentHighlightKind(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !DocumentHighlightKind.canParse(value, reporter)) {
      reporter.reportError('must be of type DocumentHighlightKind');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseDocumentLinkClientCapabilities(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !DocumentLinkClientCapabilities.canParse(value, reporter)) {
      reporter.reportError('must be of type DocumentLinkClientCapabilities');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseDocumentLinkOptions(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !DocumentLinkOptions.canParse(value, reporter)) {
      reporter.reportError('must be of type DocumentLinkOptions');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseDocumentOnTypeFormattingClientCapabilities(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !DocumentOnTypeFormattingClientCapabilities.canParse(value, reporter)) {
      reporter.reportError(
          'must be of type DocumentOnTypeFormattingClientCapabilities');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseDocumentOnTypeFormattingOptions(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !DocumentOnTypeFormattingOptions.canParse(value, reporter)) {
      reporter.reportError('must be of type DocumentOnTypeFormattingOptions');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseDocumentRangeFormattingClientCapabilities(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !DocumentRangeFormattingClientCapabilities.canParse(value, reporter)) {
      reporter.reportError(
          'must be of type DocumentRangeFormattingClientCapabilities');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseDocumentSymbolClientCapabilities(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !DocumentSymbolClientCapabilities.canParse(value, reporter)) {
      reporter.reportError('must be of type DocumentSymbolClientCapabilities');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseDocumentSymbolClientCapabilitiesSymbolKind(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !DocumentSymbolClientCapabilitiesSymbolKind.canParse(value, reporter)) {
      reporter.reportError(
          'must be of type DocumentSymbolClientCapabilitiesSymbolKind');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseDocumentSymbolClientCapabilitiesTagSupport(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !DocumentSymbolClientCapabilitiesTagSupport.canParse(value, reporter)) {
      reporter.reportError(
          'must be of type DocumentSymbolClientCapabilitiesTagSupport');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseExecuteCommandClientCapabilities(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !ExecuteCommandClientCapabilities.canParse(value, reporter)) {
      reporter.reportError('must be of type ExecuteCommandClientCapabilities');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseExecuteCommandOptions(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !ExecuteCommandOptions.canParse(value, reporter)) {
      reporter.reportError('must be of type ExecuteCommandOptions');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseExecutionSummary(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !ExecutionSummary.canParse(value, reporter)) {
      reporter.reportError('must be of type ExecutionSummary');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseFailureHandlingKind(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !FailureHandlingKind.canParse(value, reporter)) {
      reporter.reportError('must be of type FailureHandlingKind');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseFileChangeType(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !FileChangeType.canParse(value, reporter)) {
      reporter.reportError('must be of type FileChangeType');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseFileOperationClientCapabilities(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !FileOperationClientCapabilities.canParse(value, reporter)) {
      reporter.reportError('must be of type FileOperationClientCapabilities');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseFileOperationOptions(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !FileOperationOptions.canParse(value, reporter)) {
      reporter.reportError('must be of type FileOperationOptions');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseFileOperationPattern(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !FileOperationPattern.canParse(value, reporter)) {
      reporter.reportError('must be of type FileOperationPattern');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseFileOperationPatternKind(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !FileOperationPatternKind.canParse(value, reporter)) {
      reporter.reportError('must be of type FileOperationPatternKind');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseFileOperationPatternOptions(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !FileOperationPatternOptions.canParse(value, reporter)) {
      reporter.reportError('must be of type FileOperationPatternOptions');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseFileOperationRegistrationOptions(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !FileOperationRegistrationOptions.canParse(value, reporter)) {
      reporter.reportError('must be of type FileOperationRegistrationOptions');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseFoldingRangeClientCapabilities(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !FoldingRangeClientCapabilities.canParse(value, reporter)) {
      reporter.reportError('must be of type FoldingRangeClientCapabilities');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseFoldingRangeClientCapabilitiesFoldingRange(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !FoldingRangeClientCapabilitiesFoldingRange.canParse(value, reporter)) {
      reporter.reportError(
          'must be of type FoldingRangeClientCapabilitiesFoldingRange');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseFoldingRangeClientCapabilitiesFoldingRangeKind(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !FoldingRangeClientCapabilitiesFoldingRangeKind.canParse(
            value, reporter)) {
      reporter.reportError(
          'must be of type FoldingRangeClientCapabilitiesFoldingRangeKind');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseFoldingRangeKind(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !FoldingRangeKind.canParse(value, reporter)) {
      reporter.reportError('must be of type FoldingRangeKind');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseFormattingOptions(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !FormattingOptions.canParse(value, reporter)) {
      reporter.reportError('must be of type FormattingOptions');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseGeneralClientCapabilities(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !GeneralClientCapabilities.canParse(value, reporter)) {
      reporter.reportError('must be of type GeneralClientCapabilities');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseGeneralClientCapabilitiesStaleRequestSupport(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !GeneralClientCapabilitiesStaleRequestSupport.canParse(
            value, reporter)) {
      reporter.reportError(
          'must be of type GeneralClientCapabilitiesStaleRequestSupport');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseHoverClientCapabilities(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !HoverClientCapabilities.canParse(value, reporter)) {
      reporter.reportError('must be of type HoverClientCapabilities');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseImplementationClientCapabilities(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !ImplementationClientCapabilities.canParse(value, reporter)) {
      reporter.reportError('must be of type ImplementationClientCapabilities');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseInitializeParamsClientInfo(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !InitializeParamsClientInfo.canParse(value, reporter)) {
      reporter.reportError('must be of type InitializeParamsClientInfo');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseInitializeResultServerInfo(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !InitializeResultServerInfo.canParse(value, reporter)) {
      reporter.reportError('must be of type InitializeResultServerInfo');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseInlayHintClientCapabilities(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !InlayHintClientCapabilities.canParse(value, reporter)) {
      reporter.reportError('must be of type InlayHintClientCapabilities');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseInlayHintClientCapabilitiesResolveSupport(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !InlayHintClientCapabilitiesResolveSupport.canParse(value, reporter)) {
      reporter.reportError(
          'must be of type InlayHintClientCapabilitiesResolveSupport');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseInlayHintKind(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !InlayHintKind.canParse(value, reporter)) {
      reporter.reportError('must be of type InlayHintKind');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseInlayHintWorkspaceClientCapabilities(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !InlayHintWorkspaceClientCapabilities.canParse(value, reporter)) {
      reporter
          .reportError('must be of type InlayHintWorkspaceClientCapabilities');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseInlineValueClientCapabilities(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !InlineValueClientCapabilities.canParse(value, reporter)) {
      reporter.reportError('must be of type InlineValueClientCapabilities');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseInlineValueContext(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !InlineValueContext.canParse(value, reporter)) {
      reporter.reportError('must be of type InlineValueContext');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseInlineValueWorkspaceClientCapabilities(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !InlineValueWorkspaceClientCapabilities.canParse(value, reporter)) {
      reporter.reportError(
          'must be of type InlineValueWorkspaceClientCapabilities');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseInsertReplaceEditTextEdit(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (!InsertReplaceEdit.canParse(value, reporter) &&
            !TextEdit.canParse(value, reporter))) {
      reporter
          .reportError('must be of type Either2<InsertReplaceEdit, TextEdit>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseInsertTextFormat(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !InsertTextFormat.canParse(value, reporter)) {
      reporter.reportError('must be of type InsertTextFormat');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseInsertTextMode(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !InsertTextMode.canParse(value, reporter)) {
      reporter.reportError('must be of type InsertTextMode');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseInt(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) && value is! int) {
      reporter.reportError('must be of type int');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseIntString(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) && (value is! int && value is! String)) {
      reporter.reportError('must be of type Either2<int, String>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseLinkedEditingRangeClientCapabilities(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !LinkedEditingRangeClientCapabilities.canParse(value, reporter)) {
      reporter
          .reportError('must be of type LinkedEditingRangeClientCapabilities');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseListAnnotatedTextEditSnippetTextEditTextEdit(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! List<Object?> ||
            value.any((item) =>
                !AnnotatedTextEdit.canParse(item, reporter) &&
                !SnippetTextEdit.canParse(item, reporter) &&
                !TextEdit.canParse(item, reporter)))) {
      reporter.reportError(
          'must be of type List<Either3<AnnotatedTextEdit, SnippetTextEdit, TextEdit>>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseListCodeActionKind(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! List<Object?> ||
            value.any((item) => !CodeActionKind.canParse(item, reporter)))) {
      reporter.reportError('must be of type List<CodeActionKind>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseListCompletionItem(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! List<Object?> ||
            value.any((item) => !CompletionItem.canParse(item, reporter)))) {
      reporter.reportError('must be of type List<CompletionItem>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseListCompletionItemKind(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! List<Object?> ||
            value
                .any((item) => !CompletionItemKind.canParse(item, reporter)))) {
      reporter.reportError('must be of type List<CompletionItemKind>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseListCompletionItemTag(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! List<Object?> ||
            value.any((item) => !CompletionItemTag.canParse(item, reporter)))) {
      reporter.reportError('must be of type List<CompletionItemTag>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseListConfigurationItem(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! List<Object?> ||
            value.any((item) => !ConfigurationItem.canParse(item, reporter)))) {
      reporter.reportError('must be of type List<ConfigurationItem>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseListCreateFileDeleteFileRenameFileTextDocumentEdit(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! List<Object?> ||
            value.any((item) =>
                !CreateFile.canParse(item, reporter) &&
                !DeleteFile.canParse(item, reporter) &&
                !RenameFile.canParse(item, reporter) &&
                !TextDocumentEdit.canParse(item, reporter)))) {
      reporter.reportError(
          'must be of type List<Either4<CreateFile, DeleteFile, RenameFile, TextDocumentEdit>>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseListDiagnostic(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! List<Object?> ||
            value.any((item) => !Diagnostic.canParse(item, reporter)))) {
      reporter.reportError('must be of type List<Diagnostic>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseListDiagnosticRelatedInformation(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! List<Object?> ||
            value.any((item) =>
                !DiagnosticRelatedInformation.canParse(item, reporter)))) {
      reporter
          .reportError('must be of type List<DiagnosticRelatedInformation>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseListDiagnosticTag(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! List<Object?> ||
            value.any((item) => !DiagnosticTag.canParse(item, reporter)))) {
      reporter.reportError('must be of type List<DiagnosticTag>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseListDocumentSymbol(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! List<Object?> ||
            value.any((item) => !DocumentSymbol.canParse(item, reporter)))) {
      reporter.reportError('must be of type List<DocumentSymbol>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseListFileCreate(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! List<Object?> ||
            value.any((item) => !FileCreate.canParse(item, reporter)))) {
      reporter.reportError('must be of type List<FileCreate>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseListFileDelete(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! List<Object?> ||
            value.any((item) => !FileDelete.canParse(item, reporter)))) {
      reporter.reportError('must be of type List<FileDelete>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseListFileEvent(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! List<Object?> ||
            value.any((item) => !FileEvent.canParse(item, reporter)))) {
      reporter.reportError('must be of type List<FileEvent>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseListFileOperationFilter(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! List<Object?> ||
            value.any(
                (item) => !FileOperationFilter.canParse(item, reporter)))) {
      reporter.reportError('must be of type List<FileOperationFilter>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseListFileRename(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! List<Object?> ||
            value.any((item) => !FileRename.canParse(item, reporter)))) {
      reporter.reportError('must be of type List<FileRename>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseListFileSystemWatcher(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! List<Object?> ||
            value.any((item) => !FileSystemWatcher.canParse(item, reporter)))) {
      reporter.reportError('must be of type List<FileSystemWatcher>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseListFoldingRangeKind(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! List<Object?> ||
            value.any((item) => !FoldingRangeKind.canParse(item, reporter)))) {
      reporter.reportError('must be of type List<FoldingRangeKind>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseListInlayHintLabelPartString(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! List<Object?> ||
            value.any((item) => !InlayHintLabelPart.canParse(item, reporter)) &&
                value is! String)) {
      reporter.reportError(
          'must be of type Either2<List<InlayHintLabelPart>, String>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseListInsertTextMode(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! List<Object?> ||
            value.any((item) => !InsertTextMode.canParse(item, reporter)))) {
      reporter.reportError('must be of type List<InsertTextMode>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseListInt(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! List<Object?> || value.any((item) => item is! int))) {
      reporter.reportError('must be of type List<int>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseListMarkupKind(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! List<Object?> ||
            value.any((item) => !MarkupKind.canParse(item, reporter)))) {
      reporter.reportError('must be of type List<MarkupKind>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseListMessageActionItem(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! List<Object?> ||
            value.any((item) => !MessageActionItem.canParse(item, reporter)))) {
      reporter.reportError('must be of type List<MessageActionItem>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseListNotebookCell(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! List<Object?> ||
            value.any((item) => !NotebookCell.canParse(item, reporter)))) {
      reporter.reportError('must be of type List<NotebookCell>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseListNotebookDocumentChangeEventCellsTextContent(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! List<Object?> ||
            value.any((item) =>
                !NotebookDocumentChangeEventCellsTextContent.canParse(
                    item, reporter)))) {
      reporter.reportError(
          'must be of type List<NotebookDocumentChangeEventCellsTextContent>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseListNotebookDocumentSyncOptionsNotebookSelector2Cells(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! List<Object?> ||
            value.any((item) =>
                !NotebookDocumentSyncOptionsNotebookSelector2Cells.canParse(
                    item, reporter)))) {
      reporter.reportError(
          'must be of type List<NotebookDocumentSyncOptionsNotebookSelector2Cells>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseListNotebookDocumentSyncOptionsNotebookSelectorCells(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! List<Object?> ||
            value.any((item) =>
                !NotebookDocumentSyncOptionsNotebookSelectorCells.canParse(
                    item, reporter)))) {
      reporter.reportError(
          'must be of type List<NotebookDocumentSyncOptionsNotebookSelectorCells>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool
    _canParseListNotebookDocumentSyncOptionsNotebookSelectorNotebookDocumentSyncOptionsNotebookSelector2(
        Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
        {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! List<Object?> ||
            value.any((item) =>
                !NotebookDocumentSyncOptionsNotebookSelector.canParse(
                    item, reporter) &&
                !NotebookDocumentSyncOptionsNotebookSelector2.canParse(
                    item, reporter)))) {
      reporter.reportError(
          'must be of type List<Either2<NotebookDocumentSyncOptionsNotebookSelector, NotebookDocumentSyncOptionsNotebookSelector2>>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseListObjectNullable(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! List<Object?> || value.any((item) => false))) {
      reporter.reportError('must be of type List<LSPAny>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseListParameterInformation(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! List<Object?> ||
            value.any(
                (item) => !ParameterInformation.canParse(item, reporter)))) {
      reporter.reportError('must be of type List<ParameterInformation>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseListPosition(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! List<Object?> ||
            value.any((item) => !Position.canParse(item, reporter)))) {
      reporter.reportError('must be of type List<Position>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseListPositionEncodingKind(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! List<Object?> ||
            value.any(
                (item) => !PositionEncodingKind.canParse(item, reporter)))) {
      reporter.reportError('must be of type List<PositionEncodingKind>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseListPreviousResultId(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! List<Object?> ||
            value.any((item) => !PreviousResultId.canParse(item, reporter)))) {
      reporter.reportError('must be of type List<PreviousResultId>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseListRange(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! List<Object?> ||
            value.any((item) => !Range.canParse(item, reporter)))) {
      reporter.reportError('must be of type List<Range>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseListRegistration(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! List<Object?> ||
            value.any((item) => !Registration.canParse(item, reporter)))) {
      reporter.reportError('must be of type List<Registration>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseListResourceOperationKind(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! List<Object?> ||
            value.any(
                (item) => !ResourceOperationKind.canParse(item, reporter)))) {
      reporter.reportError('must be of type List<ResourceOperationKind>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseListSemanticTokensEdit(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! List<Object?> ||
            value
                .any((item) => !SemanticTokensEdit.canParse(item, reporter)))) {
      reporter.reportError('must be of type List<SemanticTokensEdit>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseListSignatureInformation(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! List<Object?> ||
            value.any(
                (item) => !SignatureInformation.canParse(item, reporter)))) {
      reporter.reportError('must be of type List<SignatureInformation>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseListString(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! List<Object?> || value.any((item) => item is! String))) {
      reporter.reportError('must be of type List<String>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseListSymbolKind(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! List<Object?> ||
            value.any((item) => !SymbolKind.canParse(item, reporter)))) {
      reporter.reportError('must be of type List<SymbolKind>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseListSymbolTag(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! List<Object?> ||
            value.any((item) => !SymbolTag.canParse(item, reporter)))) {
      reporter.reportError('must be of type List<SymbolTag>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool
    _canParseListTextDocumentContentChangeEvent1TextDocumentContentChangeEvent2(
        Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
        {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! List<Object?> ||
            value.any((item) =>
                !TextDocumentContentChangeEvent1.canParse(item, reporter) &&
                !TextDocumentContentChangeEvent2.canParse(item, reporter)))) {
      reporter
          .reportError('must be of type List<TextDocumentContentChangeEvent>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseListTextDocumentFilterWithScheme(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! List<Object?> ||
            value.any((item) =>
                !TextDocumentFilterWithScheme.canParse(item, reporter)))) {
      reporter
          .reportError('must be of type List<TextDocumentFilterWithScheme>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseListTextDocumentIdentifier(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! List<Object?> ||
            value.any(
                (item) => !TextDocumentIdentifier.canParse(item, reporter)))) {
      reporter.reportError('must be of type List<TextDocumentIdentifier>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseListTextDocumentItem(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! List<Object?> ||
            value.any((item) => !TextDocumentItem.canParse(item, reporter)))) {
      reporter.reportError('must be of type List<TextDocumentItem>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseListTextEdit(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! List<Object?> ||
            value.any((item) => !TextEdit.canParse(item, reporter)))) {
      reporter.reportError('must be of type List<TextEdit>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseListTokenFormat(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! List<Object?> ||
            value.any((item) => !TokenFormat.canParse(item, reporter)))) {
      reporter.reportError('must be of type List<TokenFormat>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseListUnregistration(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! List<Object?> ||
            value.any((item) => !Unregistration.canParse(item, reporter)))) {
      reporter.reportError('must be of type List<Unregistration>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseListWorkspaceFolder(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! List<Object?> ||
            value.any((item) => !WorkspaceFolder.canParse(item, reporter)))) {
      reporter.reportError('must be of type List<WorkspaceFolder>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool
    _canParseListWorkspaceFullDocumentDiagnosticReportWorkspaceUnchangedDocumentDiagnosticReport(
        Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
        {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! List<Object?> ||
            value.any((item) =>
                !WorkspaceFullDocumentDiagnosticReport.canParse(
                    item, reporter) &&
                !WorkspaceUnchangedDocumentDiagnosticReport.canParse(
                    item, reporter)))) {
      reporter.reportError(
          'must be of type List<WorkspaceDocumentDiagnosticReport>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseLiteral(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined,
    required bool allowsNull,
    required String literal}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) && value != literal) {
      reporter.reportError("must be the literal '$literal'");
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseLiteralUnion(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined,
    required bool allowsNull,
    required Iterable<String> literals}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) && !literals.contains(value)) {
      reporter.reportError(
          "must be one of the ${literals.map((e) => "'$e'").join(', ')}");
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseLocation(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) && !Location.canParse(value, reporter)) {
      reporter.reportError('must be of type Location');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseLocationWorkspaceSymbolLocation(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (!Location.canParse(value, reporter) &&
            !WorkspaceSymbolLocation.canParse(value, reporter))) {
      reporter.reportError(
          'must be of type Either2<Location, WorkspaceSymbolLocation>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseMapStringChangeAnnotation(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! Map ||
            (value.keys.any((item) =>
                item is! String ||
                value.values.any(
                    (item) => !ChangeAnnotation.canParse(item, reporter)))))) {
      reporter.reportError(
          'must be of type Map<ChangeAnnotationIdentifier, ChangeAnnotation>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool
    _canParseMapStringFullDocumentDiagnosticReportUnchangedDocumentDiagnosticReport(
        Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
        {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! Map ||
            (value.keys.any((item) =>
                item is! String ||
                value.values.any((item) =>
                    !FullDocumentDiagnosticReport.canParse(item, reporter) &&
                    !UnchangedDocumentDiagnosticReport.canParse(
                        item, reporter)))))) {
      reporter.reportError(
          'must be of type Map<DocumentUri, Either2<FullDocumentDiagnosticReport, UnchangedDocumentDiagnosticReport>>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseMapStringListTextEdit(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! Map ||
            (value.keys.any((item) =>
                item is! String ||
                value.values.any((item) =>
                    item is! List<Object?> ||
                    item.any(
                        (item) => !TextEdit.canParse(item, reporter))))))) {
      reporter.reportError('must be of type Map<DocumentUri, List<TextEdit>>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseMarkdownClientCapabilities(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !MarkdownClientCapabilities.canParse(value, reporter)) {
      reporter.reportError('must be of type MarkdownClientCapabilities');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseMarkupContentString(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (!MarkupContent.canParse(value, reporter) && value is! String)) {
      reporter.reportError('must be of type Either2<MarkupContent, String>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseMarkupKind(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !MarkupKind.canParse(value, reporter)) {
      reporter.reportError('must be of type MarkupKind');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseMessageType(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !MessageType.canParse(value, reporter)) {
      reporter.reportError('must be of type MessageType');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseMonikerClientCapabilities(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !MonikerClientCapabilities.canParse(value, reporter)) {
      reporter.reportError('must be of type MonikerClientCapabilities');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseMonikerKind(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !MonikerKind.canParse(value, reporter)) {
      reporter.reportError('must be of type MonikerKind');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseNotebookCellArrayChange(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !NotebookCellArrayChange.canParse(value, reporter)) {
      reporter.reportError('must be of type NotebookCellArrayChange');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseNotebookCellKind(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !NotebookCellKind.canParse(value, reporter)) {
      reporter.reportError('must be of type NotebookCellKind');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseNotebookDocument(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !NotebookDocument.canParse(value, reporter)) {
      reporter.reportError('must be of type NotebookDocument');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseNotebookDocumentChangeEvent(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !NotebookDocumentChangeEvent.canParse(value, reporter)) {
      reporter.reportError('must be of type NotebookDocumentChangeEvent');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseNotebookDocumentChangeEventCells(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !NotebookDocumentChangeEventCells.canParse(value, reporter)) {
      reporter.reportError('must be of type NotebookDocumentChangeEventCells');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseNotebookDocumentChangeEventCellsStructure(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !NotebookDocumentChangeEventCellsStructure.canParse(value, reporter)) {
      reporter.reportError(
          'must be of type NotebookDocumentChangeEventCellsStructure');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseNotebookDocumentClientCapabilities(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !NotebookDocumentClientCapabilities.canParse(value, reporter)) {
      reporter
          .reportError('must be of type NotebookDocumentClientCapabilities');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool
    _canParseNotebookDocumentFilter1NotebookDocumentFilter2NotebookDocumentFilter3String(
        Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
        {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (!NotebookDocumentFilter1.canParse(value, reporter) &&
            !NotebookDocumentFilter2.canParse(value, reporter) &&
            !NotebookDocumentFilter3.canParse(value, reporter) &&
            value is! String)) {
      reporter.reportError(
          'must be of type Either2<NotebookDocumentFilter, String>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseNotebookDocumentIdentifier(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !NotebookDocumentIdentifier.canParse(value, reporter)) {
      reporter.reportError('must be of type NotebookDocumentIdentifier');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseNotebookDocumentSyncClientCapabilities(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !NotebookDocumentSyncClientCapabilities.canParse(value, reporter)) {
      reporter.reportError(
          'must be of type NotebookDocumentSyncClientCapabilities');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool
    _canParseNotebookDocumentSyncOptionsNotebookDocumentSyncRegistrationOptions(
        Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
        {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (!NotebookDocumentSyncOptions.canParse(value, reporter) &&
            !NotebookDocumentSyncRegistrationOptions.canParse(
                value, reporter))) {
      reporter.reportError(
          'must be of type Either2<NotebookDocumentSyncOptions, NotebookDocumentSyncRegistrationOptions>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseNum(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) && value is! num) {
      reporter.reportError('must be of type num');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseObject(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) && value == null) {
      reporter.reportError('must be of type Object');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseOptionalVersionedTextDocumentIdentifier(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !OptionalVersionedTextDocumentIdentifier.canParse(value, reporter)) {
      reporter.reportError(
          'must be of type OptionalVersionedTextDocumentIdentifier');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParsePosition(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) && !Position.canParse(value, reporter)) {
      reporter.reportError('must be of type Position');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParsePositionEncodingKind(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !PositionEncodingKind.canParse(value, reporter)) {
      reporter.reportError('must be of type PositionEncodingKind');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParsePrepareSupportDefaultBehavior(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !PrepareSupportDefaultBehavior.canParse(value, reporter)) {
      reporter.reportError('must be of type PrepareSupportDefaultBehavior');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParsePublishDiagnosticsClientCapabilities(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !PublishDiagnosticsClientCapabilities.canParse(value, reporter)) {
      reporter
          .reportError('must be of type PublishDiagnosticsClientCapabilities');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParsePublishDiagnosticsClientCapabilitiesTagSupport(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !PublishDiagnosticsClientCapabilitiesTagSupport.canParse(
            value, reporter)) {
      reporter.reportError(
          'must be of type PublishDiagnosticsClientCapabilitiesTagSupport');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseRange(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) && !Range.canParse(value, reporter)) {
      reporter.reportError('must be of type Range');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseReferenceClientCapabilities(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !ReferenceClientCapabilities.canParse(value, reporter)) {
      reporter.reportError('must be of type ReferenceClientCapabilities');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseReferenceContext(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !ReferenceContext.canParse(value, reporter)) {
      reporter.reportError('must be of type ReferenceContext');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseRegularExpressionsClientCapabilities(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !RegularExpressionsClientCapabilities.canParse(value, reporter)) {
      reporter
          .reportError('must be of type RegularExpressionsClientCapabilities');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseRenameClientCapabilities(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !RenameClientCapabilities.canParse(value, reporter)) {
      reporter.reportError('must be of type RenameClientCapabilities');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseRenameFileOptions(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !RenameFileOptions.canParse(value, reporter)) {
      reporter.reportError('must be of type RenameFileOptions');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseSelectionRange(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !SelectionRange.canParse(value, reporter)) {
      reporter.reportError('must be of type SelectionRange');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseSelectionRangeClientCapabilities(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !SelectionRangeClientCapabilities.canParse(value, reporter)) {
      reporter.reportError('must be of type SelectionRangeClientCapabilities');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseSemanticTokensClientCapabilities(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !SemanticTokensClientCapabilities.canParse(value, reporter)) {
      reporter.reportError('must be of type SemanticTokensClientCapabilities');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseSemanticTokensClientCapabilitiesRequests(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !SemanticTokensClientCapabilitiesRequests.canParse(value, reporter)) {
      reporter.reportError(
          'must be of type SemanticTokensClientCapabilitiesRequests');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseSemanticTokensLegend(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !SemanticTokensLegend.canParse(value, reporter)) {
      reporter.reportError('must be of type SemanticTokensLegend');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseSemanticTokensOptionsSemanticTokensRegistrationOptions(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (!SemanticTokensOptions.canParse(value, reporter) &&
            !SemanticTokensRegistrationOptions.canParse(value, reporter))) {
      reporter.reportError(
          'must be of type Either2<SemanticTokensOptions, SemanticTokensRegistrationOptions>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseSemanticTokensWorkspaceClientCapabilities(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !SemanticTokensWorkspaceClientCapabilities.canParse(value, reporter)) {
      reporter.reportError(
          'must be of type SemanticTokensWorkspaceClientCapabilities');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseServerCapabilities(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !ServerCapabilities.canParse(value, reporter)) {
      reporter.reportError('must be of type ServerCapabilities');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseServerCapabilitiesWorkspace(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !ServerCapabilitiesWorkspace.canParse(value, reporter)) {
      reporter.reportError('must be of type ServerCapabilitiesWorkspace');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseShowDocumentClientCapabilities(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !ShowDocumentClientCapabilities.canParse(value, reporter)) {
      reporter.reportError('must be of type ShowDocumentClientCapabilities');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseShowMessageRequestClientCapabilities(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !ShowMessageRequestClientCapabilities.canParse(value, reporter)) {
      reporter
          .reportError('must be of type ShowMessageRequestClientCapabilities');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseShowMessageRequestClientCapabilitiesMessageActionItem(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !ShowMessageRequestClientCapabilitiesMessageActionItem.canParse(
            value, reporter)) {
      reporter.reportError(
          'must be of type ShowMessageRequestClientCapabilitiesMessageActionItem');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseSignatureHelp(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !SignatureHelp.canParse(value, reporter)) {
      reporter.reportError('must be of type SignatureHelp');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseSignatureHelpClientCapabilities(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !SignatureHelpClientCapabilities.canParse(value, reporter)) {
      reporter.reportError('must be of type SignatureHelpClientCapabilities');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseSignatureHelpClientCapabilitiesSignatureInformation(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !SignatureHelpClientCapabilitiesSignatureInformation.canParse(
            value, reporter)) {
      reporter.reportError(
          'must be of type SignatureHelpClientCapabilitiesSignatureInformation');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseSignatureHelpContext(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !SignatureHelpContext.canParse(value, reporter)) {
      reporter.reportError('must be of type SignatureHelpContext');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseSignatureHelpOptions(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !SignatureHelpOptions.canParse(value, reporter)) {
      reporter.reportError('must be of type SignatureHelpOptions');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseSignatureHelpTriggerKind(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !SignatureHelpTriggerKind.canParse(value, reporter)) {
      reporter.reportError('must be of type SignatureHelpTriggerKind');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseSignatureInformationParameterInformation(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !SignatureInformationParameterInformation.canParse(value, reporter)) {
      reporter.reportError(
          'must be of type SignatureInformationParameterInformation');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseString(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) && value is! String) {
      reporter.reportError('must be of type String');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseStringRelativePattern(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! String && !RelativePattern.canParse(value, reporter))) {
      reporter
          .reportError('must be of type Either2<LspPattern, RelativePattern>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseStringWorkspaceFolder(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (value is! String && !WorkspaceFolder.canParse(value, reporter))) {
      reporter.reportError('must be of type Either2<LspUri, WorkspaceFolder>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseSymbolKind(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !SymbolKind.canParse(value, reporter)) {
      reporter.reportError('must be of type SymbolKind');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseTextDocumentClientCapabilities(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !TextDocumentClientCapabilities.canParse(value, reporter)) {
      reporter.reportError('must be of type TextDocumentClientCapabilities');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseTextDocumentIdentifier(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !TextDocumentIdentifier.canParse(value, reporter)) {
      reporter.reportError('must be of type TextDocumentIdentifier');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseTextDocumentItem(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !TextDocumentItem.canParse(value, reporter)) {
      reporter.reportError('must be of type TextDocumentItem');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseTextDocumentSaveReason(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !TextDocumentSaveReason.canParse(value, reporter)) {
      reporter.reportError('must be of type TextDocumentSaveReason');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseTextDocumentSyncClientCapabilities(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !TextDocumentSyncClientCapabilities.canParse(value, reporter)) {
      reporter
          .reportError('must be of type TextDocumentSyncClientCapabilities');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseTextDocumentSyncKind(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !TextDocumentSyncKind.canParse(value, reporter)) {
      reporter.reportError('must be of type TextDocumentSyncKind');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseTextDocumentSyncKindTextDocumentSyncOptions(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        (!TextDocumentSyncKind.canParse(value, reporter) &&
            !TextDocumentSyncOptions.canParse(value, reporter))) {
      reporter.reportError(
          'must be of type Either2<TextDocumentSyncKind, TextDocumentSyncOptions>');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseTextEdit(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) && !TextEdit.canParse(value, reporter)) {
      reporter.reportError('must be of type TextEdit');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseTraceValues(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !TraceValues.canParse(value, reporter)) {
      reporter.reportError('must be of type TraceValues');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseTypeDefinitionClientCapabilities(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !TypeDefinitionClientCapabilities.canParse(value, reporter)) {
      reporter.reportError('must be of type TypeDefinitionClientCapabilities');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseTypeHierarchyClientCapabilities(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !TypeHierarchyClientCapabilities.canParse(value, reporter)) {
      reporter.reportError('must be of type TypeHierarchyClientCapabilities');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseTypeHierarchyItem(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !TypeHierarchyItem.canParse(value, reporter)) {
      reporter.reportError('must be of type TypeHierarchyItem');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseUniquenessLevel(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !UniquenessLevel.canParse(value, reporter)) {
      reporter.reportError('must be of type UniquenessLevel');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseVersionedNotebookDocumentIdentifier(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !VersionedNotebookDocumentIdentifier.canParse(value, reporter)) {
      reporter
          .reportError('must be of type VersionedNotebookDocumentIdentifier');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseVersionedTextDocumentIdentifier(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !VersionedTextDocumentIdentifier.canParse(value, reporter)) {
      reporter.reportError('must be of type VersionedTextDocumentIdentifier');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseWatchKind(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) && !WatchKind.canParse(value, reporter)) {
      reporter.reportError('must be of type WatchKind');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseWindowClientCapabilities(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !WindowClientCapabilities.canParse(value, reporter)) {
      reporter.reportError('must be of type WindowClientCapabilities');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseWorkspaceClientCapabilities(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !WorkspaceClientCapabilities.canParse(value, reporter)) {
      reporter.reportError('must be of type WorkspaceClientCapabilities');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseWorkspaceEdit(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !WorkspaceEdit.canParse(value, reporter)) {
      reporter.reportError('must be of type WorkspaceEdit');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseWorkspaceEditClientCapabilities(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !WorkspaceEditClientCapabilities.canParse(value, reporter)) {
      reporter.reportError('must be of type WorkspaceEditClientCapabilities');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseWorkspaceEditClientCapabilitiesChangeAnnotationSupport(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !WorkspaceEditClientCapabilitiesChangeAnnotationSupport.canParse(
            value, reporter)) {
      reporter.reportError(
          'must be of type WorkspaceEditClientCapabilitiesChangeAnnotationSupport');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseWorkspaceFoldersChangeEvent(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !WorkspaceFoldersChangeEvent.canParse(value, reporter)) {
      reporter.reportError('must be of type WorkspaceFoldersChangeEvent');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseWorkspaceFoldersServerCapabilities(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !WorkspaceFoldersServerCapabilities.canParse(value, reporter)) {
      reporter
          .reportError('must be of type WorkspaceFoldersServerCapabilities');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseWorkspaceSymbolClientCapabilities(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !WorkspaceSymbolClientCapabilities.canParse(value, reporter)) {
      reporter.reportError('must be of type WorkspaceSymbolClientCapabilities');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseWorkspaceSymbolClientCapabilitiesResolveSupport(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !WorkspaceSymbolClientCapabilitiesResolveSupport.canParse(
            value, reporter)) {
      reporter.reportError(
          'must be of type WorkspaceSymbolClientCapabilitiesResolveSupport');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseWorkspaceSymbolClientCapabilitiesSymbolKind(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !WorkspaceSymbolClientCapabilitiesSymbolKind.canParse(
            value, reporter)) {
      reporter.reportError(
          'must be of type WorkspaceSymbolClientCapabilitiesSymbolKind');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseWorkspaceSymbolClientCapabilitiesTagSupport(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !WorkspaceSymbolClientCapabilitiesTagSupport.canParse(
            value, reporter)) {
      reporter.reportError(
          'must be of type WorkspaceSymbolClientCapabilitiesTagSupport');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

Either3<AnnotatedTextEdit, SnippetTextEdit, TextEdit>
    _eitherAnnotatedTextEditSnippetTextEditTextEdit(Object? value) {
  return AnnotatedTextEdit.canParse(value, nullLspJsonReporter)
      ? Either3.t1(AnnotatedTextEdit.fromJson(value as Map<String, Object?>))
      : SnippetTextEdit.canParse(value, nullLspJsonReporter)
          ? Either3.t2(SnippetTextEdit.fromJson(value as Map<String, Object?>))
          : TextEdit.canParse(value, nullLspJsonReporter)
              ? Either3.t3(TextEdit.fromJson(value as Map<String, Object?>))
              : throw '$value was not one of (AnnotatedTextEdit, SnippetTextEdit, TextEdit)';
}

Either3<bool, CallHierarchyOptions, CallHierarchyRegistrationOptions>
    _eitherBoolCallHierarchyOptionsCallHierarchyRegistrationOptions(
        Object? value) {
  return value is bool
      ? Either3.t1(value)
      : CallHierarchyOptions.canParse(value, nullLspJsonReporter)
          ? Either3.t2(
              CallHierarchyOptions.fromJson(value as Map<String, Object?>))
          : CallHierarchyRegistrationOptions.canParse(
                  value, nullLspJsonReporter)
              ? Either3.t3(CallHierarchyRegistrationOptions.fromJson(
                  value as Map<String, Object?>))
              : throw '$value was not one of (bool, CallHierarchyOptions, CallHierarchyRegistrationOptions)';
}

Either2<bool, CodeActionOptions> _eitherBoolCodeActionOptions(Object? value) {
  return value is bool
      ? Either2.t1(value)
      : CodeActionOptions.canParse(value, nullLspJsonReporter)
          ? Either2.t2(
              CodeActionOptions.fromJson(value as Map<String, Object?>))
          : throw '$value was not one of (bool, CodeActionOptions)';
}

Either3<bool, DeclarationOptions, DeclarationRegistrationOptions>
    _eitherBoolDeclarationOptionsDeclarationRegistrationOptions(Object? value) {
  return value is bool
      ? Either3.t1(value)
      : DeclarationOptions.canParse(value, nullLspJsonReporter)
          ? Either3.t2(
              DeclarationOptions.fromJson(value as Map<String, Object?>))
          : DeclarationRegistrationOptions.canParse(value, nullLspJsonReporter)
              ? Either3.t3(DeclarationRegistrationOptions.fromJson(
                  value as Map<String, Object?>))
              : throw '$value was not one of (bool, DeclarationOptions, DeclarationRegistrationOptions)';
}

Either2<bool, DefinitionOptions> _eitherBoolDefinitionOptions(Object? value) {
  return value is bool
      ? Either2.t1(value)
      : DefinitionOptions.canParse(value, nullLspJsonReporter)
          ? Either2.t2(
              DefinitionOptions.fromJson(value as Map<String, Object?>))
          : throw '$value was not one of (bool, DefinitionOptions)';
}

Either3<bool, DocumentColorOptions, DocumentColorRegistrationOptions>
    _eitherBoolDocumentColorOptionsDocumentColorRegistrationOptions(
        Object? value) {
  return value is bool
      ? Either3.t1(value)
      : DocumentColorOptions.canParse(value, nullLspJsonReporter)
          ? Either3.t2(
              DocumentColorOptions.fromJson(value as Map<String, Object?>))
          : DocumentColorRegistrationOptions.canParse(
                  value, nullLspJsonReporter)
              ? Either3.t3(DocumentColorRegistrationOptions.fromJson(
                  value as Map<String, Object?>))
              : throw '$value was not one of (bool, DocumentColorOptions, DocumentColorRegistrationOptions)';
}

Either2<bool, DocumentFormattingOptions> _eitherBoolDocumentFormattingOptions(
    Object? value) {
  return value is bool
      ? Either2.t1(value)
      : DocumentFormattingOptions.canParse(value, nullLspJsonReporter)
          ? Either2.t2(
              DocumentFormattingOptions.fromJson(value as Map<String, Object?>))
          : throw '$value was not one of (bool, DocumentFormattingOptions)';
}

Either2<bool, DocumentHighlightOptions> _eitherBoolDocumentHighlightOptions(
    Object? value) {
  return value is bool
      ? Either2.t1(value)
      : DocumentHighlightOptions.canParse(value, nullLspJsonReporter)
          ? Either2.t2(
              DocumentHighlightOptions.fromJson(value as Map<String, Object?>))
          : throw '$value was not one of (bool, DocumentHighlightOptions)';
}

Either2<bool, DocumentRangeFormattingOptions>
    _eitherBoolDocumentRangeFormattingOptions(Object? value) {
  return value is bool
      ? Either2.t1(value)
      : DocumentRangeFormattingOptions.canParse(value, nullLspJsonReporter)
          ? Either2.t2(DocumentRangeFormattingOptions.fromJson(
              value as Map<String, Object?>))
          : throw '$value was not one of (bool, DocumentRangeFormattingOptions)';
}

Either2<bool, DocumentSymbolOptions> _eitherBoolDocumentSymbolOptions(
    Object? value) {
  return value is bool
      ? Either2.t1(value)
      : DocumentSymbolOptions.canParse(value, nullLspJsonReporter)
          ? Either2.t2(
              DocumentSymbolOptions.fromJson(value as Map<String, Object?>))
          : throw '$value was not one of (bool, DocumentSymbolOptions)';
}

Either3<bool, FoldingRangeOptions, FoldingRangeRegistrationOptions>
    _eitherBoolFoldingRangeOptionsFoldingRangeRegistrationOptions(
        Object? value) {
  return value is bool
      ? Either3.t1(value)
      : FoldingRangeOptions.canParse(value, nullLspJsonReporter)
          ? Either3.t2(
              FoldingRangeOptions.fromJson(value as Map<String, Object?>))
          : FoldingRangeRegistrationOptions.canParse(value, nullLspJsonReporter)
              ? Either3.t3(FoldingRangeRegistrationOptions.fromJson(
                  value as Map<String, Object?>))
              : throw '$value was not one of (bool, FoldingRangeOptions, FoldingRangeRegistrationOptions)';
}

Either2<bool, HoverOptions> _eitherBoolHoverOptions(Object? value) {
  return value is bool
      ? Either2.t1(value)
      : HoverOptions.canParse(value, nullLspJsonReporter)
          ? Either2.t2(HoverOptions.fromJson(value as Map<String, Object?>))
          : throw '$value was not one of (bool, HoverOptions)';
}

Either3<bool, ImplementationOptions, ImplementationRegistrationOptions>
    _eitherBoolImplementationOptionsImplementationRegistrationOptions(
        Object? value) {
  return value is bool
      ? Either3.t1(value)
      : ImplementationOptions.canParse(value, nullLspJsonReporter)
          ? Either3.t2(
              ImplementationOptions.fromJson(value as Map<String, Object?>))
          : ImplementationRegistrationOptions.canParse(
                  value, nullLspJsonReporter)
              ? Either3.t3(ImplementationRegistrationOptions.fromJson(
                  value as Map<String, Object?>))
              : throw '$value was not one of (bool, ImplementationOptions, ImplementationRegistrationOptions)';
}

Either3<bool, InlayHintOptions, InlayHintRegistrationOptions>
    _eitherBoolInlayHintOptionsInlayHintRegistrationOptions(Object? value) {
  return value is bool
      ? Either3.t1(value)
      : InlayHintOptions.canParse(value, nullLspJsonReporter)
          ? Either3.t2(InlayHintOptions.fromJson(value as Map<String, Object?>))
          : InlayHintRegistrationOptions.canParse(value, nullLspJsonReporter)
              ? Either3.t3(InlayHintRegistrationOptions.fromJson(
                  value as Map<String, Object?>))
              : throw '$value was not one of (bool, InlayHintOptions, InlayHintRegistrationOptions)';
}

Either3<bool, InlineValueOptions, InlineValueRegistrationOptions>
    _eitherBoolInlineValueOptionsInlineValueRegistrationOptions(Object? value) {
  return value is bool
      ? Either3.t1(value)
      : InlineValueOptions.canParse(value, nullLspJsonReporter)
          ? Either3.t2(
              InlineValueOptions.fromJson(value as Map<String, Object?>))
          : InlineValueRegistrationOptions.canParse(value, nullLspJsonReporter)
              ? Either3.t3(InlineValueRegistrationOptions.fromJson(
                  value as Map<String, Object?>))
              : throw '$value was not one of (bool, InlineValueOptions, InlineValueRegistrationOptions)';
}

Either3<bool, LinkedEditingRangeOptions, LinkedEditingRangeRegistrationOptions>
    _eitherBoolLinkedEditingRangeOptionsLinkedEditingRangeRegistrationOptions(
        Object? value) {
  return value is bool
      ? Either3.t1(value)
      : LinkedEditingRangeOptions.canParse(value, nullLspJsonReporter)
          ? Either3.t2(
              LinkedEditingRangeOptions.fromJson(value as Map<String, Object?>))
          : LinkedEditingRangeRegistrationOptions.canParse(
                  value, nullLspJsonReporter)
              ? Either3.t3(LinkedEditingRangeRegistrationOptions.fromJson(
                  value as Map<String, Object?>))
              : throw '$value was not one of (bool, LinkedEditingRangeOptions, LinkedEditingRangeRegistrationOptions)';
}

Either3<bool, MonikerOptions, MonikerRegistrationOptions>
    _eitherBoolMonikerOptionsMonikerRegistrationOptions(Object? value) {
  return value is bool
      ? Either3.t1(value)
      : MonikerOptions.canParse(value, nullLspJsonReporter)
          ? Either3.t2(MonikerOptions.fromJson(value as Map<String, Object?>))
          : MonikerRegistrationOptions.canParse(value, nullLspJsonReporter)
              ? Either3.t3(MonikerRegistrationOptions.fromJson(
                  value as Map<String, Object?>))
              : throw '$value was not one of (bool, MonikerOptions, MonikerRegistrationOptions)';
}

Either2<bool, ReferenceOptions> _eitherBoolReferenceOptions(Object? value) {
  return value is bool
      ? Either2.t1(value)
      : ReferenceOptions.canParse(value, nullLspJsonReporter)
          ? Either2.t2(ReferenceOptions.fromJson(value as Map<String, Object?>))
          : throw '$value was not one of (bool, ReferenceOptions)';
}

Either2<bool, RenameOptions> _eitherBoolRenameOptions(Object? value) {
  return value is bool
      ? Either2.t1(value)
      : RenameOptions.canParse(value, nullLspJsonReporter)
          ? Either2.t2(RenameOptions.fromJson(value as Map<String, Object?>))
          : throw '$value was not one of (bool, RenameOptions)';
}

Either2<bool, SaveOptions> _eitherBoolSaveOptions(Object? value) {
  return value is bool
      ? Either2.t1(value)
      : SaveOptions.canParse(value, nullLspJsonReporter)
          ? Either2.t2(SaveOptions.fromJson(value as Map<String, Object?>))
          : throw '$value was not one of (bool, SaveOptions)';
}

Either3<bool, SelectionRangeOptions, SelectionRangeRegistrationOptions>
    _eitherBoolSelectionRangeOptionsSelectionRangeRegistrationOptions(
        Object? value) {
  return value is bool
      ? Either3.t1(value)
      : SelectionRangeOptions.canParse(value, nullLspJsonReporter)
          ? Either3.t2(
              SelectionRangeOptions.fromJson(value as Map<String, Object?>))
          : SelectionRangeRegistrationOptions.canParse(
                  value, nullLspJsonReporter)
              ? Either3.t3(SelectionRangeRegistrationOptions.fromJson(
                  value as Map<String, Object?>))
              : throw '$value was not one of (bool, SelectionRangeOptions, SelectionRangeRegistrationOptions)';
}

Either2<bool, SemanticTokensClientCapabilitiesRequestsFull>
    _eitherBoolSemanticTokensClientCapabilitiesRequestsFull(Object? value) {
  return value is bool
      ? Either2.t1(value)
      : SemanticTokensClientCapabilitiesRequestsFull.canParse(
              value, nullLspJsonReporter)
          ? Either2.t2(SemanticTokensClientCapabilitiesRequestsFull.fromJson(
              value as Map<String, Object?>))
          : throw '$value was not one of (bool, SemanticTokensClientCapabilitiesRequestsFull)';
}

Either2<bool, SemanticTokensClientCapabilitiesRequestsRange>
    _eitherBoolSemanticTokensClientCapabilitiesRequestsRange(Object? value) {
  return value is bool
      ? Either2.t1(value)
      : SemanticTokensClientCapabilitiesRequestsRange.canParse(
              value, nullLspJsonReporter)
          ? Either2.t2(SemanticTokensClientCapabilitiesRequestsRange.fromJson(
              value as Map<String, Object?>))
          : throw '$value was not one of (bool, SemanticTokensClientCapabilitiesRequestsRange)';
}

Either2<bool, SemanticTokensOptionsFull> _eitherBoolSemanticTokensOptionsFull(
    Object? value) {
  return value is bool
      ? Either2.t1(value)
      : SemanticTokensOptionsFull.canParse(value, nullLspJsonReporter)
          ? Either2.t2(
              SemanticTokensOptionsFull.fromJson(value as Map<String, Object?>))
          : throw '$value was not one of (bool, SemanticTokensOptionsFull)';
}

Either2<bool, SemanticTokensOptionsRange> _eitherBoolSemanticTokensOptionsRange(
    Object? value) {
  return value is bool
      ? Either2.t1(value)
      : SemanticTokensOptionsRange.canParse(value, nullLspJsonReporter)
          ? Either2.t2(SemanticTokensOptionsRange.fromJson(
              value as Map<String, Object?>))
          : throw '$value was not one of (bool, SemanticTokensOptionsRange)';
}

Either2<bool, String> _eitherBoolString(Object? value) {
  return value is bool
      ? Either2.t1(value)
      : value is String
          ? Either2.t2(value)
          : throw '$value was not one of (bool, String)';
}

Either3<bool, TypeDefinitionOptions, TypeDefinitionRegistrationOptions>
    _eitherBoolTypeDefinitionOptionsTypeDefinitionRegistrationOptions(
        Object? value) {
  return value is bool
      ? Either3.t1(value)
      : TypeDefinitionOptions.canParse(value, nullLspJsonReporter)
          ? Either3.t2(
              TypeDefinitionOptions.fromJson(value as Map<String, Object?>))
          : TypeDefinitionRegistrationOptions.canParse(
                  value, nullLspJsonReporter)
              ? Either3.t3(TypeDefinitionRegistrationOptions.fromJson(
                  value as Map<String, Object?>))
              : throw '$value was not one of (bool, TypeDefinitionOptions, TypeDefinitionRegistrationOptions)';
}

Either3<bool, TypeHierarchyOptions, TypeHierarchyRegistrationOptions>
    _eitherBoolTypeHierarchyOptionsTypeHierarchyRegistrationOptions(
        Object? value) {
  return value is bool
      ? Either3.t1(value)
      : TypeHierarchyOptions.canParse(value, nullLspJsonReporter)
          ? Either3.t2(
              TypeHierarchyOptions.fromJson(value as Map<String, Object?>))
          : TypeHierarchyRegistrationOptions.canParse(
                  value, nullLspJsonReporter)
              ? Either3.t3(TypeHierarchyRegistrationOptions.fromJson(
                  value as Map<String, Object?>))
              : throw '$value was not one of (bool, TypeHierarchyOptions, TypeHierarchyRegistrationOptions)';
}

Either2<bool, WorkspaceSymbolOptions> _eitherBoolWorkspaceSymbolOptions(
    Object? value) {
  return value is bool
      ? Either2.t1(value)
      : WorkspaceSymbolOptions.canParse(value, nullLspJsonReporter)
          ? Either2.t2(
              WorkspaceSymbolOptions.fromJson(value as Map<String, Object?>))
          : throw '$value was not one of (bool, WorkspaceSymbolOptions)';
}

Either2<CompletionItemEditRange, Range> _eitherCompletionItemEditRangeRange(
    Object? value) {
  return CompletionItemEditRange.canParse(value, nullLspJsonReporter)
      ? Either2.t1(
          CompletionItemEditRange.fromJson(value as Map<String, Object?>))
      : Range.canParse(value, nullLspJsonReporter)
          ? Either2.t2(Range.fromJson(value as Map<String, Object?>))
          : throw '$value was not one of (CompletionItemEditRange, Range)';
}

Either4<CreateFile, DeleteFile, RenameFile, TextDocumentEdit>
    _eitherCreateFileDeleteFileRenameFileTextDocumentEdit(Object? value) {
  return CreateFile.canParse(value, nullLspJsonReporter)
      ? Either4.t1(CreateFile.fromJson(value as Map<String, Object?>))
      : DeleteFile.canParse(value, nullLspJsonReporter)
          ? Either4.t2(DeleteFile.fromJson(value as Map<String, Object?>))
          : RenameFile.canParse(value, nullLspJsonReporter)
              ? Either4.t3(RenameFile.fromJson(value as Map<String, Object?>))
              : TextDocumentEdit.canParse(value, nullLspJsonReporter)
                  ? Either4.t4(
                      TextDocumentEdit.fromJson(value as Map<String, Object?>))
                  : throw '$value was not one of (CreateFile, DeleteFile, RenameFile, TextDocumentEdit)';
}

Either2<DiagnosticOptions, DiagnosticRegistrationOptions>
    _eitherDiagnosticOptionsDiagnosticRegistrationOptions(Object? value) {
  return DiagnosticOptions.canParse(value, nullLspJsonReporter)
      ? Either2.t1(DiagnosticOptions.fromJson(value as Map<String, Object?>))
      : DiagnosticRegistrationOptions.canParse(value, nullLspJsonReporter)
          ? Either2.t2(DiagnosticRegistrationOptions.fromJson(
              value as Map<String, Object?>))
          : throw '$value was not one of (DiagnosticOptions, DiagnosticRegistrationOptions)';
}

Either2<FullDocumentDiagnosticReport, UnchangedDocumentDiagnosticReport>
    _eitherFullDocumentDiagnosticReportUnchangedDocumentDiagnosticReport(
        Object? value) {
  return FullDocumentDiagnosticReport.canParse(value, nullLspJsonReporter)
      ? Either2.t1(
          FullDocumentDiagnosticReport.fromJson(value as Map<String, Object?>))
      : UnchangedDocumentDiagnosticReport.canParse(value, nullLspJsonReporter)
          ? Either2.t2(UnchangedDocumentDiagnosticReport.fromJson(
              value as Map<String, Object?>))
          : throw '$value was not one of (FullDocumentDiagnosticReport, UnchangedDocumentDiagnosticReport)';
}

Either2<InsertReplaceEdit, TextEdit> _eitherInsertReplaceEditTextEdit(
    Object? value) {
  return InsertReplaceEdit.canParse(value, nullLspJsonReporter)
      ? Either2.t1(InsertReplaceEdit.fromJson(value as Map<String, Object?>))
      : TextEdit.canParse(value, nullLspJsonReporter)
          ? Either2.t2(TextEdit.fromJson(value as Map<String, Object?>))
          : throw '$value was not one of (InsertReplaceEdit, TextEdit)';
}

Either2<int, String> _eitherIntString(Object? value) {
  return value is int
      ? Either2.t1(value)
      : value is String
          ? Either2.t2(value)
          : throw '$value was not one of (int, String)';
}

Either2<List<InlayHintLabelPart>, String> _eitherListInlayHintLabelPartString(
    Object? value) {
  return value is List<Object?> &&
          value.every(
              (item) => InlayHintLabelPart.canParse(item, nullLspJsonReporter))
      ? Either2.t1(value
          .map((item) =>
              InlayHintLabelPart.fromJson(item as Map<String, Object?>))
          .toList())
      : value is String
          ? Either2.t2(value)
          : throw '$value was not one of (List<InlayHintLabelPart>, String)';
}

Either2<Location, WorkspaceSymbolLocation>
    _eitherLocationWorkspaceSymbolLocation(Object? value) {
  return Location.canParse(value, nullLspJsonReporter)
      ? Either2.t1(Location.fromJson(value as Map<String, Object?>))
      : WorkspaceSymbolLocation.canParse(value, nullLspJsonReporter)
          ? Either2.t2(
              WorkspaceSymbolLocation.fromJson(value as Map<String, Object?>))
          : throw '$value was not one of (Location, WorkspaceSymbolLocation)';
}

Either2<MarkupContent, String> _eitherMarkupContentString(Object? value) {
  return MarkupContent.canParse(value, nullLspJsonReporter)
      ? Either2.t1(MarkupContent.fromJson(value as Map<String, Object?>))
      : value is String
          ? Either2.t2(value)
          : throw '$value was not one of (MarkupContent, String)';
}

Either3<NotebookDocumentFilter1, NotebookDocumentFilter2,
        NotebookDocumentFilter3>
    _eitherNotebookDocumentFilter1NotebookDocumentFilter2NotebookDocumentFilter3(
        Object? value) {
  return NotebookDocumentFilter1.canParse(value, nullLspJsonReporter)
      ? Either3.t1(
          NotebookDocumentFilter1.fromJson(value as Map<String, Object?>))
      : NotebookDocumentFilter2.canParse(value, nullLspJsonReporter)
          ? Either3.t2(
              NotebookDocumentFilter2.fromJson(value as Map<String, Object?>))
          : NotebookDocumentFilter3.canParse(value, nullLspJsonReporter)
              ? Either3.t3(NotebookDocumentFilter3.fromJson(
                  value as Map<String, Object?>))
              : throw '$value was not one of (NotebookDocumentFilter1, NotebookDocumentFilter2, NotebookDocumentFilter3)';
}

Either2<NotebookDocumentFilter, String>
    _eitherNotebookDocumentFilter1NotebookDocumentFilter2NotebookDocumentFilter3String(
        Object? value) {
  return NotebookDocumentFilter1.canParse(value, nullLspJsonReporter) ||
          NotebookDocumentFilter2.canParse(value, nullLspJsonReporter) ||
          NotebookDocumentFilter3.canParse(value, nullLspJsonReporter)
      ? Either2.t1(
          _eitherNotebookDocumentFilter1NotebookDocumentFilter2NotebookDocumentFilter3(
              value))
      : value is String
          ? Either2.t2(value)
          : throw '$value was not one of (NotebookDocumentFilter, String)';
}

Either2<NotebookDocumentSyncOptions, NotebookDocumentSyncRegistrationOptions>
    _eitherNotebookDocumentSyncOptionsNotebookDocumentSyncRegistrationOptions(
        Object? value) {
  return NotebookDocumentSyncOptions.canParse(value, nullLspJsonReporter)
      ? Either2.t1(
          NotebookDocumentSyncOptions.fromJson(value as Map<String, Object?>))
      : NotebookDocumentSyncRegistrationOptions.canParse(
              value, nullLspJsonReporter)
          ? Either2.t2(NotebookDocumentSyncRegistrationOptions.fromJson(
              value as Map<String, Object?>))
          : throw '$value was not one of (NotebookDocumentSyncOptions, NotebookDocumentSyncRegistrationOptions)';
}

Either2<NotebookDocumentSyncOptionsNotebookSelector,
        NotebookDocumentSyncOptionsNotebookSelector2>
    _eitherNotebookDocumentSyncOptionsNotebookSelectorNotebookDocumentSyncOptionsNotebookSelector2(
        Object? value) {
  return NotebookDocumentSyncOptionsNotebookSelector.canParse(
          value, nullLspJsonReporter)
      ? Either2.t1(NotebookDocumentSyncOptionsNotebookSelector.fromJson(
          value as Map<String, Object?>))
      : NotebookDocumentSyncOptionsNotebookSelector2.canParse(
              value, nullLspJsonReporter)
          ? Either2.t2(NotebookDocumentSyncOptionsNotebookSelector2.fromJson(
              value as Map<String, Object?>))
          : throw '$value was not one of (NotebookDocumentSyncOptionsNotebookSelector, NotebookDocumentSyncOptionsNotebookSelector2)';
}

Either2<SemanticTokensOptions, SemanticTokensRegistrationOptions>
    _eitherSemanticTokensOptionsSemanticTokensRegistrationOptions(
        Object? value) {
  return SemanticTokensOptions.canParse(value, nullLspJsonReporter)
      ? Either2.t1(
          SemanticTokensOptions.fromJson(value as Map<String, Object?>))
      : SemanticTokensRegistrationOptions.canParse(value, nullLspJsonReporter)
          ? Either2.t2(SemanticTokensRegistrationOptions.fromJson(
              value as Map<String, Object?>))
          : throw '$value was not one of (SemanticTokensOptions, SemanticTokensRegistrationOptions)';
}

Either2<LspPattern, RelativePattern> _eitherStringRelativePattern(
    Object? value) {
  return value is String
      ? Either2.t1(value)
      : RelativePattern.canParse(value, nullLspJsonReporter)
          ? Either2.t2(RelativePattern.fromJson(value as Map<String, Object?>))
          : throw '$value was not one of (LspPattern, RelativePattern)';
}

Either2<LspUri, WorkspaceFolder> _eitherStringWorkspaceFolder(Object? value) {
  return value is String
      ? Either2.t1(value)
      : WorkspaceFolder.canParse(value, nullLspJsonReporter)
          ? Either2.t2(WorkspaceFolder.fromJson(value as Map<String, Object?>))
          : throw '$value was not one of (LspUri, WorkspaceFolder)';
}

Either2<TextDocumentContentChangeEvent1, TextDocumentContentChangeEvent2>
    _eitherTextDocumentContentChangeEvent1TextDocumentContentChangeEvent2(
        Object? value) {
  return TextDocumentContentChangeEvent1.canParse(value, nullLspJsonReporter)
      ? Either2.t1(TextDocumentContentChangeEvent1.fromJson(
          value as Map<String, Object?>))
      : TextDocumentContentChangeEvent2.canParse(value, nullLspJsonReporter)
          ? Either2.t2(TextDocumentContentChangeEvent2.fromJson(
              value as Map<String, Object?>))
          : throw '$value was not one of (TextDocumentContentChangeEvent1, TextDocumentContentChangeEvent2)';
}

Either2<TextDocumentSyncKind, TextDocumentSyncOptions>
    _eitherTextDocumentSyncKindTextDocumentSyncOptions(Object? value) {
  return TextDocumentSyncKind.canParse(value, nullLspJsonReporter)
      ? Either2.t1(TextDocumentSyncKind.fromJson(value as int))
      : TextDocumentSyncOptions.canParse(value, nullLspJsonReporter)
          ? Either2.t2(
              TextDocumentSyncOptions.fromJson(value as Map<String, Object?>))
          : throw '$value was not one of (TextDocumentSyncKind, TextDocumentSyncOptions)';
}

Either2<WorkspaceFullDocumentDiagnosticReport,
        WorkspaceUnchangedDocumentDiagnosticReport>
    _eitherWorkspaceFullDocumentDiagnosticReportWorkspaceUnchangedDocumentDiagnosticReport(
        Object? value) {
  return WorkspaceFullDocumentDiagnosticReport.canParse(
          value, nullLspJsonReporter)
      ? Either2.t1(WorkspaceFullDocumentDiagnosticReport.fromJson(
          value as Map<String, Object?>))
      : WorkspaceUnchangedDocumentDiagnosticReport.canParse(
              value, nullLspJsonReporter)
          ? Either2.t2(WorkspaceUnchangedDocumentDiagnosticReport.fromJson(
              value as Map<String, Object?>))
          : throw '$value was not one of (WorkspaceFullDocumentDiagnosticReport, WorkspaceUnchangedDocumentDiagnosticReport)';
}
