// 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 [Location].
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 [Location]. 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<TextDocumentFilterWithScheme>;

/// 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 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] or [CompletionList]
/// or a [Future] that resolves to such.
///
/// The request can delay the computation of the [CompletionItem.detail]
/// and [CompletionItem.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 [Future] 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 [Future] 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] or a [Future] 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] or a [Future] that resolves to such.
typedef TextDocumentDocumentSymbolResult
    = Either2<List<DocumentSymbol>, List<SymbolInformation>>?;

/// A document filter denotes a document by different properties like the
/// [TextDocument.languageId], the [Uri.scheme] of its resource, or a
/// glob-pattern that is applied to the [TextDocument.fileName].
///
/// 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 [Future] that resolves to such.
typedef TextDocumentFoldingRangeResult = List<FoldingRange>?;

/// Result for a request 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 [Future] 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
/// [Future] 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] or a [Future] 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] or a [Future] 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] 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 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] or a [Future] 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] or a [Future] 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
/// [Future] 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] or a [Future] 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 an 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 [CallHierarchyIncomingCall.from].
  final List<Range> fromRanges;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      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 = Uri.parse(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
  /// [CallHierarchyItem.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.toString();
    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 _canParseUri(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
  /// [CallHierarchyItemProvider.provideCallHierarchyOutgoingCalls]
  /// and not [CallHierarchyOutgoingCall.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
/// [CodeActionProvider.provideCodeActions] 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 = Uri.parse(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.toString();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseUri(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 [TextEdit] that are applied when selecting
  /// this color presentation. Edits must not overlap with the main
  /// [ColorPresentation.textEdit] nor with themselves.
  final List<TextEdit>? additionalTextEdits;

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

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

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      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 [TextEdit] that are applied when selecting
  /// this completion. Edits must not overlap (including the same insert
  /// position) with the main [CompletionItem.textEdit] 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
  /// [CompletionItem.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 [CompletionItem.label]
  /// is used.
  final String? filterText;

  /// A string that should be inserted into a document when selecting this
  /// completion. When `falsy` the [CompletionItem.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 [CompletionItem.label]
  /// is used.
  final String? sortText;

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

  /// An [TextEdit] which is applied to a document when selecting this
  /// completion. When an edit is provided the value of
  /// [CompletionItem.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
  /// [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
  /// [CompletionItem.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 [CompletionItem] to be presented in the editor.
class CompletionList implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    CompletionList.canParse,
    CompletionList.fromJson,
  );

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

  /// This list 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 = Uri.parse(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.toString();
    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 _canParseUri(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 = Uri.parse(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.toString();
    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 _canParseUri(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 [RelativePattern]
  /// 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());
}

/// The document diagnostic report kinds.
///
/// @since 3.17.0
class DocumentDiagnosticReportKind implements ToJsonable {
  const DocumentDiagnosticReportKind(this._value);
  const DocumentDiagnosticReportKind.fromJson(this._value);

  final String _value;

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

  /// A diagnostic report with a full set of problems.
  static const Full = DocumentDiagnosticReportKind('full');

  /// A report indicating that the last returned report is still accurate.
  static const Unchanged = DocumentDiagnosticReportKind('unchanged');

  @override
  Object toJson() => _value;

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

  @override
  int get hashCode => _value.hashCode;

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

/// A partial result for a document diagnostic report.
///
/// @since 3.17.0
class DocumentDiagnosticReportPartialResult implements ToJsonable {
  static const jsonHandler = LspJsonHandler(
    DocumentDiagnosticReportPartialResult.canParse,
    DocumentDiagnosticReportPartialResult.fromJson,
  );

  DocumentDiagnosticReportPartialResult({
    required this.relatedDocuments,
  });
  static DocumentDiagnosticReportPartialResult fromJson(
      Map<String, Object?> json) {
    final relatedDocumentsJson = json['relatedDocuments'];
    final relatedDocuments = (relatedDocumentsJson as Map<Object, Object?>).map(
        (key, value) => MapEntry(
            Uri.parse(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.map((key, value) => MapEntry(key.toString(), value));
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseMapUriFullDocumentDiagnosticReportUnchangedDocumentDiagnosticReport(
          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 [DocumentHighlightKind.Text].
  final DocumentHighlightKind? kind;

  /// The range this highlight applies to.
  final Range range;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      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);
  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 = Uri.parse(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.toString();
    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 _canParseUri(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 [GlobPattern] 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 != null ? Uri.parse(rootUriJson as String) : null;
    final traceJson = json['trace'];
    final trace =
        traceJson != null ? TraceValues.fromJson(traceJson as String) : null;
    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 TraceValues? 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?.toString();
    if (trace != null) {
      result['trace'] = trace?.toJson();
    }
    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 (!_canParseUri(obj, reporter, 'rootUri',
          allowsUndefined: false, allowsNull: true)) {
        return false;
      }
      if (!_canParseTraceValues(obj, reporter, 'trace',
          allowsUndefined: true, allowsNull: false)) {
        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 = Uri.parse(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.toString();
    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 _canParseUri(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 [Location],
/// 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 = Uri.parse(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.toString();
    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 _canParseUri(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 [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 = Uri.parse(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.toString();
    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 (!_canParseUri(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 = Uri.parse(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.toString();
    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 (!_canParseUri(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 [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 [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 [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 = Uri.parse(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.toString();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseUri(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 = Uri.parse(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.toString();
    result['version'] = version;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseUri(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 = Uri.parse(uriJson as String);
    final valueJson = json['value'];
    final value = valueJson as String;
    return PreviousResultId(
      uri: uri,
      value: value,
    );
  }

  /// The URI for which the client knowns a result id.
  final DocumentUri uri;

  /// The value of the previous result id.
  final String value;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseUri(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 = Uri.parse(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.toString();
    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 (!_canParseUri(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 register for a 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(
            Uri.parse(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
          ?.map((key, value) => MapEntry(key.toString(), value));
    }
    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 (!_canParseMapUriFullDocumentDiagnosticReportUnchangedDocumentDiagnosticReport(
          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(
            Uri.parse(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
          ?.map((key, value) => MapEntry(key.toString(), value));
    }
    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 (!_canParseMapUriFullDocumentDiagnosticReportUnchangedDocumentDiagnosticReport(
          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 = _eitherUriWorkspaceFolder(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 (!_canParseUriWorkspaceFolder(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 = Uri.parse(newUriJson as String);
    final oldUriJson = json['oldUri'];
    final oldUri = Uri.parse(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.toString();
    result['oldUri'] = oldUri.toString();
    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 (!_canParseUri(obj, reporter, 'newUri',
          allowsUndefined: false, allowsNull: false)) {
        return false;
      }
      if (!_canParseUri(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 = Uri.parse(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.toString();
    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 _canParseUri(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 [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 [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 [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 [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 [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 = Uri.parse(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.toString();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseUri(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 = Uri.parse(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.toString();
    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 (!_canParseUri(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) {
    switch (obj) {
      case 'messages':
      case 'off':
      case 'verbose':
        return true;
    }
    return false;
  }

  /// 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 != null
        ? TypeHierarchyItemInfo.fromJson(dataJson as Map<String, Object?>)
        : null;
    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 = Uri.parse(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 TypeHierarchyItemInfo? 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
  /// [TypeHierarchyItem.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?.toJson();
    }
    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.toString();
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseTypeHierarchyItemInfo(obj, reporter, 'data',
          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;
      }
      if (!_canParseListSymbolTag(obj, reporter, 'tags',
          allowsUndefined: true, allowsNull: false)) {
        return false;
      }
      return _canParseUri(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 = Uri.parse(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.toString();
    result['version'] = version;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseUri(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 = Uri.parse(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.toString();
    result['version'] = version;
    return result;
  }

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      if (!_canParseUri(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(
            Uri.parse(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?.map((key, value) => MapEntry(
          key.toString(), value.map((item) => item.toJson()).toList()));
    }
    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 (!_canParseMapUriListTextEdit(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 = Uri.parse(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.toString();
    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 _canParseUri(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 = Uri.parse(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.toString();
    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 (!_canParseUri(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 = Uri.parse(uriJson as String);
    return WorkspaceSymbolLocation(
      uri: uri,
    );
  }

  final DocumentUri uri;

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

  static bool canParse(Object? obj, LspJsonReporter reporter) {
    if (obj is Map<String, Object?>) {
      return _canParseUri(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 = Uri.parse(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.toString();
    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 (!_canParseUri(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 _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
    _canParseMapUriFullDocumentDiagnosticReportUnchangedDocumentDiagnosticReport(
        Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
        {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    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 || Uri.tryParse(item) == null) ||
                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 _canParseMapUriListTextEdit(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    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 || Uri.tryParse(item) == null) ||
                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 _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 _canParseTypeHierarchyItemInfo(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    final value = map[fieldName];
    final nullCheck = allowsNull || allowsUndefined;
    if (!nullCheck && value == null) {
      reporter.reportError('must not be null');
      return false;
    }
    if ((!nullCheck || value != null) &&
        !TypeHierarchyItemInfo.canParse(value, reporter)) {
      reporter.reportError('must be of type TypeHierarchyItemInfo');
      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 _canParseUri(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    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 || Uri.tryParse(value) == null)) {
      reporter.reportError('must be of type Uri');
      return false;
    }
  } finally {
    reporter.pop();
  }
  return true;
}

bool _canParseUriWorkspaceFolder(
    Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
    {required bool allowsUndefined, required bool allowsNull}) {
  reporter.push(fieldName);
  try {
    if (!allowsUndefined && !map.containsKey(fieldName)) {
      reporter.reportError('must not be undefined');
      return false;
    }
    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 || Uri.tryParse(value) == null) &&
            !WorkspaceFolder.canParse(value, reporter))) {
      reporter.reportError('must be of type Either2<LSPUri, WorkspaceFolder>');
      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<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<LSPUri, WorkspaceFolder> _eitherUriWorkspaceFolder(Object? value) {
  return (value is String && Uri.tryParse(value) != null)
      ? Either2.t1(Uri.parse(value))
      : WorkspaceFolder.canParse(value, nullLspJsonReporter)
          ? Either2.t2(WorkspaceFolder.fromJson(value as Map<String, Object?>))
          : throw '$value was not one of (LSPUri, WorkspaceFolder)';
}

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