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