1238 lines
41 KiB
Python
1238 lines
41 KiB
Python
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
# Licensed under the MIT License.
|
|
import sys
|
|
from typing import Any, List, Optional, Tuple, Union
|
|
|
|
import attrs
|
|
import cattrs
|
|
|
|
from . import types as lsp_types
|
|
|
|
LSPAny = lsp_types.LSPAny
|
|
OptionalPrimitive = Optional[Union[bool, int, str, float]]
|
|
|
|
# Flag to ensure we only resolve forward references once.
|
|
_resolved_forward_references = False
|
|
|
|
|
|
def _resolve_forward_references() -> None:
|
|
"""Resolve forward references for faster processing with cattrs."""
|
|
global _resolved_forward_references
|
|
if not _resolved_forward_references:
|
|
|
|
def _filter(p: Tuple[str, object]) -> bool:
|
|
return isinstance(p[1], type) and attrs.has(p[1])
|
|
|
|
# Creating a concrete list here because `resolve_types` mutates the provided map.
|
|
items = list(filter(_filter, lsp_types.ALL_TYPES_MAP.items()))
|
|
for _, value in items:
|
|
if isinstance(value, type):
|
|
attrs.resolve_types(value, lsp_types.ALL_TYPES_MAP, {}) # type: ignore
|
|
_resolved_forward_references = True
|
|
|
|
|
|
def register_hooks(converter: cattrs.Converter) -> cattrs.Converter:
|
|
_resolve_forward_references()
|
|
converter = _register_capabilities_hooks(converter)
|
|
converter = _register_required_structure_hooks(converter)
|
|
return _register_custom_property_hooks(converter)
|
|
|
|
|
|
def _register_capabilities_hooks(converter: cattrs.Converter) -> cattrs.Converter:
|
|
def _text_document_sync_hook(
|
|
object_: Any, _: type
|
|
) -> Union[OptionalPrimitive, lsp_types.TextDocumentSyncOptions]:
|
|
if object_ is None:
|
|
return None
|
|
if isinstance(object_, (bool, int, str, float)):
|
|
return object_
|
|
return converter.structure(object_, lsp_types.TextDocumentSyncOptions)
|
|
|
|
def _notebook_document_sync_hook(
|
|
object_: Any, _: type
|
|
) -> Optional[
|
|
Union[
|
|
lsp_types.NotebookDocumentSyncRegistrationOptions,
|
|
lsp_types.NotebookDocumentSyncOptions,
|
|
]
|
|
]:
|
|
if object_ is None:
|
|
return None
|
|
if "id" in object_:
|
|
return converter.structure(
|
|
object_, lsp_types.NotebookDocumentSyncRegistrationOptions
|
|
)
|
|
else:
|
|
return converter.structure(object_, lsp_types.NotebookDocumentSyncOptions)
|
|
|
|
def _hover_provider_hook(
|
|
object_: Any, _: type
|
|
) -> Union[OptionalPrimitive, lsp_types.HoverOptions]:
|
|
if object_ is None:
|
|
return None
|
|
if isinstance(object_, (bool, int, str, float)):
|
|
return object_
|
|
return converter.structure(object_, lsp_types.HoverOptions)
|
|
|
|
def _declaration_provider_hook(
|
|
object_: Any, _: type
|
|
) -> Union[
|
|
OptionalPrimitive,
|
|
lsp_types.DeclarationRegistrationOptions,
|
|
lsp_types.DeclarationOptions,
|
|
]:
|
|
if object_ is None:
|
|
return None
|
|
if isinstance(object_, (bool, int, str, float)):
|
|
return object_
|
|
if "id" in object_:
|
|
return converter.structure(
|
|
object_, lsp_types.DeclarationRegistrationOptions
|
|
)
|
|
else:
|
|
return converter.structure(object_, lsp_types.DeclarationOptions)
|
|
|
|
def _definition_provider_hook(
|
|
object_: Any, _: type
|
|
) -> Union[OptionalPrimitive, lsp_types.DefinitionOptions]:
|
|
if object_ is None:
|
|
return None
|
|
if isinstance(object_, (bool, int, str, float)):
|
|
return object_
|
|
return converter.structure(object_, lsp_types.DefinitionOptions)
|
|
|
|
def _type_definition_provider_hook(
|
|
object_: Any, _: type
|
|
) -> Union[
|
|
OptionalPrimitive,
|
|
lsp_types.TypeDefinitionRegistrationOptions,
|
|
lsp_types.TypeDefinitionOptions,
|
|
]:
|
|
if object_ is None:
|
|
return None
|
|
if isinstance(object_, (bool, int, str, float)):
|
|
return object_
|
|
if "id" in object_:
|
|
return converter.structure(
|
|
object_, lsp_types.TypeDefinitionRegistrationOptions
|
|
)
|
|
else:
|
|
return converter.structure(object_, lsp_types.TypeDefinitionOptions)
|
|
|
|
def _implementation_provider_hook(
|
|
object_: Any, _: type
|
|
) -> Union[
|
|
OptionalPrimitive,
|
|
lsp_types.ImplementationRegistrationOptions,
|
|
lsp_types.ImplementationOptions,
|
|
]:
|
|
if object_ is None:
|
|
return None
|
|
if isinstance(object_, (bool, int, str, float)):
|
|
return object_
|
|
if "id" in object_:
|
|
return converter.structure(
|
|
object_, lsp_types.ImplementationRegistrationOptions
|
|
)
|
|
else:
|
|
return converter.structure(object_, lsp_types.ImplementationOptions)
|
|
|
|
def _references_provider_hook(
|
|
object_: Any, _: type
|
|
) -> Union[OptionalPrimitive, lsp_types.ReferenceOptions]:
|
|
if object_ is None:
|
|
return None
|
|
if isinstance(object_, (bool, int, str, float)):
|
|
return object_
|
|
return converter.structure(object_, lsp_types.ReferenceOptions)
|
|
|
|
def _position_encoding_hook(
|
|
object_: Union[lsp_types.PositionEncodingKind, OptionalPrimitive], _: type
|
|
) -> Union[lsp_types.PositionEncodingKind, OptionalPrimitive]:
|
|
return object_
|
|
|
|
def _document_highlight_provider_hook(
|
|
object_: Any, _: type
|
|
) -> Union[OptionalPrimitive, lsp_types.DocumentHighlightOptions]:
|
|
if object_ is None:
|
|
return None
|
|
if isinstance(object_, (bool, int, str, float)):
|
|
return object_
|
|
return converter.structure(object_, lsp_types.DocumentHighlightOptions)
|
|
|
|
def _document_symbol_provider_hook(
|
|
object_: Any, _: type
|
|
) -> Union[OptionalPrimitive, lsp_types.DocumentSymbolOptions]:
|
|
if object_ is None:
|
|
return None
|
|
if isinstance(object_, (bool, int, str, float)):
|
|
return object_
|
|
return converter.structure(object_, lsp_types.DocumentSymbolOptions)
|
|
|
|
def _code_action_provider_hook(
|
|
object_: Any, _: type
|
|
) -> Union[OptionalPrimitive, lsp_types.CodeActionOptions]:
|
|
if object_ is None:
|
|
return None
|
|
if isinstance(object_, (bool, int, str, float)):
|
|
return object_
|
|
return converter.structure(object_, lsp_types.CodeActionOptions)
|
|
|
|
def _color_provider_hook(
|
|
object_: Any, _: type
|
|
) -> Union[
|
|
OptionalPrimitive,
|
|
lsp_types.DocumentColorRegistrationOptions,
|
|
lsp_types.DocumentColorOptions,
|
|
]:
|
|
if object_ is None:
|
|
return None
|
|
if isinstance(object_, (bool, int, str, float)):
|
|
return object_
|
|
if "id" in object_:
|
|
return converter.structure(
|
|
object_, lsp_types.DocumentColorRegistrationOptions
|
|
)
|
|
else:
|
|
return converter.structure(object_, lsp_types.DocumentColorOptions)
|
|
|
|
def _workspace_symbol_provider_hook(
|
|
object_: Any, _: type
|
|
) -> Union[OptionalPrimitive, lsp_types.WorkspaceSymbolOptions]:
|
|
if object_ is None:
|
|
return None
|
|
if isinstance(object_, (bool, int, str, float)):
|
|
return object_
|
|
return converter.structure(object_, lsp_types.WorkspaceSymbolOptions)
|
|
|
|
def _document_formatting_provider_hook(
|
|
object_: Any, _: type
|
|
) -> Union[OptionalPrimitive, lsp_types.DocumentFormattingOptions]:
|
|
if object_ is None:
|
|
return None
|
|
if isinstance(object_, (bool, int, str, float)):
|
|
return object_
|
|
return converter.structure(object_, lsp_types.DocumentFormattingOptions)
|
|
|
|
def _document_range_formatting_provider_hook(
|
|
object_: Any, _: type
|
|
) -> Union[OptionalPrimitive, lsp_types.DocumentRangeFormattingOptions]:
|
|
if object_ is None:
|
|
return None
|
|
if isinstance(object_, (bool, int, str, float)):
|
|
return object_
|
|
return converter.structure(object_, lsp_types.DocumentRangeFormattingOptions)
|
|
|
|
def _rename_provider_hook(
|
|
object_: Any, _: type
|
|
) -> Union[OptionalPrimitive, lsp_types.RenameOptions]:
|
|
if object_ is None:
|
|
return None
|
|
if isinstance(object_, (bool, int, str, float)):
|
|
return object_
|
|
return converter.structure(object_, lsp_types.RenameOptions)
|
|
|
|
def _folding_range_provider_hook(
|
|
object_: Any, _: type
|
|
) -> Union[
|
|
OptionalPrimitive,
|
|
lsp_types.FoldingRangeRegistrationOptions,
|
|
lsp_types.FoldingRangeOptions,
|
|
]:
|
|
if object_ is None:
|
|
return None
|
|
if isinstance(object_, (bool, int, str, float)):
|
|
return object_
|
|
if "id" in object_:
|
|
return converter.structure(
|
|
object_, lsp_types.FoldingRangeRegistrationOptions
|
|
)
|
|
else:
|
|
return converter.structure(object_, lsp_types.FoldingRangeOptions)
|
|
|
|
def _selection_range_provider_hook(
|
|
object_: Any, _: type
|
|
) -> Union[
|
|
OptionalPrimitive,
|
|
lsp_types.SelectionRangeRegistrationOptions,
|
|
lsp_types.SelectionRangeOptions,
|
|
]:
|
|
if object_ is None:
|
|
return None
|
|
if isinstance(object_, (bool, int, str, float)):
|
|
return object_
|
|
if "id" in object_:
|
|
return converter.structure(
|
|
object_, lsp_types.SelectionRangeRegistrationOptions
|
|
)
|
|
else:
|
|
return converter.structure(object_, lsp_types.SelectionRangeOptions)
|
|
|
|
def _call_hierarchy_provider_hook(
|
|
object_: Any, _: type
|
|
) -> Union[
|
|
OptionalPrimitive,
|
|
lsp_types.CallHierarchyRegistrationOptions,
|
|
lsp_types.CallHierarchyOptions,
|
|
]:
|
|
if object_ is None:
|
|
return None
|
|
if isinstance(object_, (bool, int, str, float)):
|
|
return object_
|
|
if "id" in object_:
|
|
return converter.structure(
|
|
object_, lsp_types.CallHierarchyRegistrationOptions
|
|
)
|
|
else:
|
|
return converter.structure(object_, lsp_types.CallHierarchyOptions)
|
|
|
|
def _linked_editing_range_provider_hook(
|
|
object_: Any, _: type
|
|
) -> Union[
|
|
OptionalPrimitive,
|
|
lsp_types.LinkedEditingRangeRegistrationOptions,
|
|
lsp_types.LinkedEditingRangeOptions,
|
|
]:
|
|
if object_ is None:
|
|
return None
|
|
if isinstance(object_, (bool, int, str, float)):
|
|
return object_
|
|
if "id" in object_:
|
|
return converter.structure(
|
|
object_, lsp_types.LinkedEditingRangeRegistrationOptions
|
|
)
|
|
else:
|
|
return converter.structure(object_, lsp_types.LinkedEditingRangeOptions)
|
|
|
|
def _semantic_tokens_provider_hook(
|
|
object_: Any, _: type
|
|
) -> Union[
|
|
OptionalPrimitive,
|
|
lsp_types.SemanticTokensRegistrationOptions,
|
|
lsp_types.SemanticTokensOptions,
|
|
]:
|
|
if object_ is None:
|
|
return None
|
|
if "id" in object_:
|
|
return converter.structure(
|
|
object_, lsp_types.SemanticTokensRegistrationOptions
|
|
)
|
|
else:
|
|
return converter.structure(object_, lsp_types.SemanticTokensOptions)
|
|
|
|
def _moniker_provider_hook(
|
|
object_: Any, _: type
|
|
) -> Union[
|
|
OptionalPrimitive,
|
|
lsp_types.MonikerRegistrationOptions,
|
|
lsp_types.MonikerOptions,
|
|
]:
|
|
if object_ is None:
|
|
return None
|
|
if isinstance(object_, (bool, int, str, float)):
|
|
return object_
|
|
if "id" in object_:
|
|
return converter.structure(object_, lsp_types.MonikerRegistrationOptions)
|
|
else:
|
|
return converter.structure(object_, lsp_types.MonikerOptions)
|
|
|
|
def _type_hierarchy_provider_hook(
|
|
object_: Any, _: type
|
|
) -> Union[
|
|
OptionalPrimitive,
|
|
lsp_types.TypeHierarchyRegistrationOptions,
|
|
lsp_types.TypeHierarchyOptions,
|
|
]:
|
|
if object_ is None:
|
|
return None
|
|
if isinstance(object_, (bool, int, str, float)):
|
|
return object_
|
|
if "id" in object_:
|
|
return converter.structure(
|
|
object_, lsp_types.TypeHierarchyRegistrationOptions
|
|
)
|
|
else:
|
|
return converter.structure(object_, lsp_types.TypeHierarchyOptions)
|
|
|
|
def _inline_value_provider_hook(
|
|
object_: Any, _: type
|
|
) -> Union[
|
|
OptionalPrimitive,
|
|
lsp_types.InlineValueRegistrationOptions,
|
|
lsp_types.InlineValueOptions,
|
|
]:
|
|
if object_ is None:
|
|
return None
|
|
if isinstance(object_, (bool, int, str, float)):
|
|
return object_
|
|
if "id" in object_:
|
|
return converter.structure(
|
|
object_, lsp_types.InlineValueRegistrationOptions
|
|
)
|
|
else:
|
|
return converter.structure(object_, lsp_types.InlineValueOptions)
|
|
|
|
def _inlay_hint_provider_hook(
|
|
object_: Any, _: type
|
|
) -> Union[
|
|
OptionalPrimitive,
|
|
lsp_types.InlayHintRegistrationOptions,
|
|
lsp_types.InlayHintOptions,
|
|
]:
|
|
if object_ is None:
|
|
return None
|
|
if isinstance(object_, (bool, int, str, float)):
|
|
return object_
|
|
if "id" in object_:
|
|
return converter.structure(object_, lsp_types.InlayHintRegistrationOptions)
|
|
else:
|
|
return converter.structure(object_, lsp_types.InlayHintOptions)
|
|
|
|
def _inlay_hint_label_part_hook(
|
|
object_: Any, _: type
|
|
) -> Union[str, List[lsp_types.InlayHintLabelPart]]:
|
|
if isinstance(object_, str):
|
|
return object_
|
|
|
|
return [
|
|
converter.structure(item, lsp_types.InlayHintLabelPart) for item in object_
|
|
]
|
|
|
|
def _diagnostic_provider_hook(
|
|
object_: Any, _: type
|
|
) -> Union[
|
|
OptionalPrimitive,
|
|
lsp_types.DiagnosticRegistrationOptions,
|
|
lsp_types.DiagnosticOptions,
|
|
]:
|
|
if object_ is None:
|
|
return None
|
|
if "id" in object_:
|
|
return converter.structure(object_, lsp_types.DiagnosticRegistrationOptions)
|
|
else:
|
|
return converter.structure(object_, lsp_types.DiagnosticOptions)
|
|
|
|
def _save_hook(
|
|
object_: Any, _: type
|
|
) -> Union[OptionalPrimitive, lsp_types.SaveOptions]:
|
|
if object_ is None:
|
|
return None
|
|
if isinstance(object_, (bool, int, str, float)):
|
|
return object_
|
|
return converter.structure(object_, lsp_types.SaveOptions)
|
|
|
|
def _code_action_hook(
|
|
object_: Any, _: type
|
|
) -> Union[lsp_types.Command, lsp_types.CodeAction]:
|
|
if "command" in object_:
|
|
return converter.structure(object_, lsp_types.Command)
|
|
else:
|
|
return converter.structure(object_, lsp_types.CodeAction)
|
|
|
|
def _completion_list_hook(
|
|
object_: Any, _: type
|
|
) -> Optional[Union[lsp_types.CompletionList, List[lsp_types.CompletionItem]]]:
|
|
if object_ is None:
|
|
return None
|
|
if isinstance(object_, list):
|
|
return [
|
|
converter.structure(item, lsp_types.CompletionItem) for item in object_
|
|
]
|
|
else:
|
|
return converter.structure(object_, lsp_types.CompletionList)
|
|
|
|
def _location_hook(
|
|
object_: Any, _: type
|
|
) -> Optional[
|
|
Union[
|
|
lsp_types.Location,
|
|
List[lsp_types.Location],
|
|
List[lsp_types.LocationLink],
|
|
]
|
|
]:
|
|
if object_ is None:
|
|
return None
|
|
if isinstance(object_, list):
|
|
if len(object_) == 0:
|
|
return []
|
|
if "targetUri" in object_[0]:
|
|
return [
|
|
converter.structure(item, lsp_types.LocationLink)
|
|
for item in object_
|
|
]
|
|
else:
|
|
return [
|
|
converter.structure(item, lsp_types.Location) for item in object_
|
|
]
|
|
else:
|
|
return converter.structure(object_, lsp_types.Location)
|
|
|
|
def _symbol_hook(
|
|
object_: Any, _: type
|
|
) -> Optional[
|
|
Union[List[lsp_types.DocumentSymbol], List[lsp_types.SymbolInformation]]
|
|
]:
|
|
if object_ is None:
|
|
return None
|
|
if isinstance(object_, list):
|
|
if len(object_) == 0:
|
|
return []
|
|
if "location" in object_[0]:
|
|
return [
|
|
converter.structure(item, lsp_types.SymbolInformation)
|
|
for item in object_
|
|
]
|
|
else:
|
|
return [
|
|
converter.structure(item, lsp_types.DocumentSymbol)
|
|
for item in object_
|
|
]
|
|
else:
|
|
return None
|
|
|
|
def _markup_content_hook(
|
|
object_: Any, _: type
|
|
) -> Optional[
|
|
Union[
|
|
OptionalPrimitive,
|
|
lsp_types.MarkupContent,
|
|
lsp_types.MarkedString_Type1,
|
|
List[Union[OptionalPrimitive, lsp_types.MarkedString_Type1]],
|
|
]
|
|
]:
|
|
if object_ is None:
|
|
return None
|
|
if isinstance(object_, (bool, int, str, float)):
|
|
return object_
|
|
if isinstance(object_, list):
|
|
return [
|
|
(
|
|
item
|
|
if isinstance(item, (bool, int, str, float))
|
|
else converter.structure(item, lsp_types.MarkedString_Type1)
|
|
)
|
|
for item in object_
|
|
]
|
|
if "kind" in object_:
|
|
return converter.structure(object_, lsp_types.MarkupContent)
|
|
else:
|
|
return converter.structure(object_, lsp_types.MarkedString_Type1)
|
|
|
|
def _document_edit_hook(
|
|
object_: Any, _: type
|
|
) -> Optional[
|
|
Union[
|
|
lsp_types.TextDocumentEdit,
|
|
lsp_types.CreateFile,
|
|
lsp_types.RenameFile,
|
|
lsp_types.DeleteFile,
|
|
]
|
|
]:
|
|
if object_ is None:
|
|
return None
|
|
if "kind" in object_:
|
|
if object_["kind"] == "create":
|
|
return converter.structure(object_, lsp_types.CreateFile)
|
|
elif object_["kind"] == "rename":
|
|
return converter.structure(object_, lsp_types.RenameFile)
|
|
elif object_["kind"] == "delete":
|
|
return converter.structure(object_, lsp_types.DeleteFile)
|
|
else:
|
|
raise ValueError("Unknown edit kind: ", object_)
|
|
else:
|
|
return converter.structure(object_, lsp_types.TextDocumentEdit)
|
|
|
|
def _semantic_tokens_hook(
|
|
object_: Any, _: type
|
|
) -> Union[OptionalPrimitive, lsp_types.SemanticTokensOptionsFullType1]:
|
|
if object_ is None:
|
|
return None
|
|
if isinstance(object_, (bool, int, str, float)):
|
|
return object_
|
|
return converter.structure(object_, lsp_types.SemanticTokensOptionsFullType1)
|
|
|
|
def _semantic_tokens_capabilities_hook(
|
|
object_: Any, _: type
|
|
) -> Union[
|
|
OptionalPrimitive,
|
|
lsp_types.SemanticTokensClientCapabilitiesRequestsTypeFullType1,
|
|
]:
|
|
if object_ is None:
|
|
return None
|
|
if isinstance(object_, (bool, int, str, float)):
|
|
return object_
|
|
return converter.structure(
|
|
object_, lsp_types.SemanticTokensClientCapabilitiesRequestsTypeFullType1
|
|
)
|
|
|
|
def _code_action_kind_hook(
|
|
object_: Any, _: type
|
|
) -> Union[OptionalPrimitive, lsp_types.CodeActionKind]:
|
|
if object_ is None:
|
|
return None
|
|
if isinstance(object_, (bool, int, str, float)):
|
|
return object_
|
|
return converter.structure(object_, lsp_types.CodeActionKind)
|
|
|
|
def _position_encoding_kind_hook(
|
|
object_: Any, _: type
|
|
) -> Union[OptionalPrimitive, lsp_types.PositionEncodingKind]:
|
|
if object_ is None:
|
|
return None
|
|
if isinstance(object_, (bool, int, str, float)):
|
|
return object_
|
|
return converter.structure(object_, lsp_types.PositionEncodingKind)
|
|
|
|
def _folding_range_kind_hook(
|
|
object_: Any, _: type
|
|
) -> Union[OptionalPrimitive, lsp_types.FoldingRangeKind]:
|
|
if object_ is None:
|
|
return None
|
|
if isinstance(object_, (bool, int, str, float)):
|
|
return object_
|
|
return converter.structure(object_, lsp_types.FoldingRangeKind)
|
|
|
|
def _semantic_token_types_hook(
|
|
object_: Any, _: type
|
|
) -> Union[OptionalPrimitive, lsp_types.SemanticTokenTypes]:
|
|
if object_ is None:
|
|
return None
|
|
if isinstance(object_, (bool, int, str, float)):
|
|
return object_
|
|
return converter.structure(object_, lsp_types.SemanticTokenTypes)
|
|
|
|
def _semantic_token_modifiers_hook(
|
|
object_: Any, _: type
|
|
) -> Union[OptionalPrimitive, lsp_types.SemanticTokenModifiers]:
|
|
if object_ is None:
|
|
return None
|
|
if isinstance(object_, (bool, int, str, float)):
|
|
return object_
|
|
return converter.structure(object_, lsp_types.SemanticTokenModifiers)
|
|
|
|
def _watch_kind_hook(
|
|
object_: Any, _: type
|
|
) -> Union[OptionalPrimitive, lsp_types.WatchKind]:
|
|
if object_ is None:
|
|
return None
|
|
if isinstance(object_, (bool, int, str, float)):
|
|
return object_
|
|
return converter.structure(object_, lsp_types.WatchKind)
|
|
|
|
def _notebook_sync_option_selector_hook(
|
|
object_: Any, _: type
|
|
) -> Union[
|
|
lsp_types.NotebookDocumentSyncOptionsNotebookSelectorType1,
|
|
lsp_types.NotebookDocumentSyncOptionsNotebookSelectorType2,
|
|
]:
|
|
if "notebook" in object_:
|
|
return converter.structure(
|
|
object_, lsp_types.NotebookDocumentSyncOptionsNotebookSelectorType1
|
|
)
|
|
else:
|
|
return converter.structure(
|
|
object_, lsp_types.NotebookDocumentSyncOptionsNotebookSelectorType2
|
|
)
|
|
|
|
def _semantic_token_registration_options_hook(
|
|
object_: Any, _: type
|
|
) -> Optional[
|
|
Union[OptionalPrimitive, lsp_types.SemanticTokensRegistrationOptionsFullType1]
|
|
]:
|
|
if object_ is None:
|
|
return None
|
|
if isinstance(object_, (bool, int, str, float)):
|
|
return object_
|
|
return converter.structure(
|
|
object_, lsp_types.SemanticTokensRegistrationOptionsFullType1
|
|
)
|
|
|
|
def _inline_completion_provider_hook(
|
|
object_: Any, _: type
|
|
) -> Optional[Union[OptionalPrimitive, lsp_types.InlineCompletionOptions]]:
|
|
if object_ is None:
|
|
return None
|
|
if isinstance(object_, (bool, int, str, float)):
|
|
return object_
|
|
return converter.structure(object_, lsp_types.InlineCompletionOptions)
|
|
|
|
def _inline_completion_list_hook(
|
|
object_: Any, _: type
|
|
) -> Optional[
|
|
Union[lsp_types.InlineCompletionList, List[lsp_types.InlineCompletionItem]]
|
|
]:
|
|
if object_ is None:
|
|
return None
|
|
if isinstance(object_, list):
|
|
return [
|
|
converter.structure(item, lsp_types.InlineCompletionItem)
|
|
for item in object_
|
|
]
|
|
return converter.structure(object_, lsp_types.InlineCompletionList)
|
|
|
|
def _string_value_hook(
|
|
object_: Any, _: type
|
|
) -> Union[OptionalPrimitive, lsp_types.StringValue]:
|
|
if object_ is None:
|
|
return None
|
|
if isinstance(object_, (bool, int, str, float)):
|
|
return object_
|
|
return converter.structure(object_, lsp_types.StringValue)
|
|
|
|
def _symbol_list_hook(
|
|
object_: Any, _: type
|
|
) -> Optional[
|
|
Union[List[lsp_types.SymbolInformation], List[lsp_types.WorkspaceSymbol]]
|
|
]:
|
|
if object_ is None:
|
|
return None
|
|
assert isinstance(object_, list)
|
|
if len(object_) == 0:
|
|
return []
|
|
if "deprecated" in object_[0]:
|
|
return [
|
|
converter.structure(item, lsp_types.SymbolInformation)
|
|
for item in object_
|
|
]
|
|
elif ("data" in object_[0]) or ("range" not in object_[0]["location"]):
|
|
return [
|
|
converter.structure(item, lsp_types.WorkspaceSymbol) for item in object_
|
|
]
|
|
|
|
return [
|
|
converter.structure(item, lsp_types.SymbolInformation) for item in object_
|
|
]
|
|
|
|
def _notebook_sync_registration_option_selector_hook(
|
|
object_: Any, _: type
|
|
) -> Union[
|
|
lsp_types.NotebookDocumentSyncRegistrationOptionsNotebookSelectorType1,
|
|
lsp_types.NotebookDocumentSyncRegistrationOptionsNotebookSelectorType2,
|
|
]:
|
|
if "notebook" in object_:
|
|
return converter.structure(
|
|
object_,
|
|
lsp_types.NotebookDocumentSyncRegistrationOptionsNotebookSelectorType1,
|
|
)
|
|
else:
|
|
return converter.structure(
|
|
object_,
|
|
lsp_types.NotebookDocumentSyncRegistrationOptionsNotebookSelectorType2,
|
|
)
|
|
|
|
structure_hooks = [
|
|
(
|
|
Optional[
|
|
Union[lsp_types.TextDocumentSyncOptions, lsp_types.TextDocumentSyncKind]
|
|
],
|
|
_text_document_sync_hook,
|
|
),
|
|
(
|
|
Optional[
|
|
Union[
|
|
lsp_types.NotebookDocumentSyncOptions,
|
|
lsp_types.NotebookDocumentSyncRegistrationOptions,
|
|
]
|
|
],
|
|
_notebook_document_sync_hook,
|
|
),
|
|
(Optional[Union[bool, lsp_types.HoverOptions]], _hover_provider_hook),
|
|
(
|
|
Optional[
|
|
Union[
|
|
bool,
|
|
lsp_types.DeclarationOptions,
|
|
lsp_types.DeclarationRegistrationOptions,
|
|
]
|
|
],
|
|
_declaration_provider_hook,
|
|
),
|
|
(Optional[Union[bool, lsp_types.DefinitionOptions]], _definition_provider_hook),
|
|
(
|
|
Optional[
|
|
Union[
|
|
bool,
|
|
lsp_types.TypeDefinitionOptions,
|
|
lsp_types.TypeDefinitionRegistrationOptions,
|
|
]
|
|
],
|
|
_type_definition_provider_hook,
|
|
),
|
|
(
|
|
Optional[
|
|
Union[
|
|
bool,
|
|
lsp_types.ImplementationOptions,
|
|
lsp_types.ImplementationRegistrationOptions,
|
|
]
|
|
],
|
|
_implementation_provider_hook,
|
|
),
|
|
(Optional[Union[bool, lsp_types.ReferenceOptions]], _references_provider_hook),
|
|
(
|
|
Optional[Union[bool, lsp_types.DocumentHighlightOptions]],
|
|
_document_highlight_provider_hook,
|
|
),
|
|
(
|
|
Optional[Union[bool, lsp_types.DocumentSymbolOptions]],
|
|
_document_symbol_provider_hook,
|
|
),
|
|
(
|
|
Optional[Union[bool, lsp_types.CodeActionOptions]],
|
|
_code_action_provider_hook,
|
|
),
|
|
(
|
|
Optional[
|
|
Union[
|
|
bool,
|
|
lsp_types.DocumentColorOptions,
|
|
lsp_types.DocumentColorRegistrationOptions,
|
|
]
|
|
],
|
|
_color_provider_hook,
|
|
),
|
|
(
|
|
Optional[Union[bool, lsp_types.WorkspaceSymbolOptions]],
|
|
_workspace_symbol_provider_hook,
|
|
),
|
|
(
|
|
Optional[Union[bool, lsp_types.DocumentFormattingOptions]],
|
|
_document_formatting_provider_hook,
|
|
),
|
|
(
|
|
Optional[Union[bool, lsp_types.DocumentRangeFormattingOptions]],
|
|
_document_range_formatting_provider_hook,
|
|
),
|
|
(Optional[Union[bool, lsp_types.RenameOptions]], _rename_provider_hook),
|
|
(
|
|
Optional[
|
|
Union[
|
|
bool,
|
|
lsp_types.FoldingRangeOptions,
|
|
lsp_types.FoldingRangeRegistrationOptions,
|
|
]
|
|
],
|
|
_folding_range_provider_hook,
|
|
),
|
|
(
|
|
Optional[
|
|
Union[
|
|
bool,
|
|
lsp_types.SelectionRangeOptions,
|
|
lsp_types.SelectionRangeRegistrationOptions,
|
|
]
|
|
],
|
|
_selection_range_provider_hook,
|
|
),
|
|
(
|
|
Optional[
|
|
Union[
|
|
bool,
|
|
lsp_types.CallHierarchyOptions,
|
|
lsp_types.CallHierarchyRegistrationOptions,
|
|
]
|
|
],
|
|
_call_hierarchy_provider_hook,
|
|
),
|
|
(
|
|
Optional[
|
|
Union[
|
|
bool,
|
|
lsp_types.LinkedEditingRangeOptions,
|
|
lsp_types.LinkedEditingRangeRegistrationOptions,
|
|
]
|
|
],
|
|
_linked_editing_range_provider_hook,
|
|
),
|
|
(
|
|
Optional[
|
|
Union[
|
|
lsp_types.SemanticTokensOptions,
|
|
lsp_types.SemanticTokensRegistrationOptions,
|
|
]
|
|
],
|
|
_semantic_tokens_provider_hook,
|
|
),
|
|
(
|
|
Optional[
|
|
Union[
|
|
bool, lsp_types.MonikerOptions, lsp_types.MonikerRegistrationOptions
|
|
]
|
|
],
|
|
_moniker_provider_hook,
|
|
),
|
|
(
|
|
Optional[
|
|
Union[
|
|
bool,
|
|
lsp_types.TypeHierarchyOptions,
|
|
lsp_types.TypeHierarchyRegistrationOptions,
|
|
]
|
|
],
|
|
_type_hierarchy_provider_hook,
|
|
),
|
|
(
|
|
Optional[
|
|
Union[
|
|
bool,
|
|
lsp_types.InlineValueOptions,
|
|
lsp_types.InlineValueRegistrationOptions,
|
|
]
|
|
],
|
|
_inline_value_provider_hook,
|
|
),
|
|
(
|
|
Optional[
|
|
Union[
|
|
bool,
|
|
lsp_types.InlayHintOptions,
|
|
lsp_types.InlayHintRegistrationOptions,
|
|
]
|
|
],
|
|
_inlay_hint_provider_hook,
|
|
),
|
|
(
|
|
Union[str, List[lsp_types.InlayHintLabelPart]],
|
|
_inlay_hint_label_part_hook,
|
|
),
|
|
(
|
|
Optional[
|
|
Union[
|
|
lsp_types.DiagnosticOptions, lsp_types.DiagnosticRegistrationOptions
|
|
]
|
|
],
|
|
_diagnostic_provider_hook,
|
|
),
|
|
(
|
|
Optional[Union[lsp_types.SaveOptions, bool]],
|
|
_save_hook,
|
|
),
|
|
(
|
|
Union[lsp_types.Command, lsp_types.CodeAction],
|
|
_code_action_hook,
|
|
),
|
|
(
|
|
Optional[Union[List[lsp_types.CompletionItem], lsp_types.CompletionList]],
|
|
_completion_list_hook,
|
|
),
|
|
(
|
|
Optional[
|
|
Union[
|
|
lsp_types.Location,
|
|
List[lsp_types.Location],
|
|
List[lsp_types.LocationLink],
|
|
]
|
|
],
|
|
_location_hook,
|
|
),
|
|
(
|
|
Optional[
|
|
Union[List[lsp_types.SymbolInformation], List[lsp_types.DocumentSymbol]]
|
|
],
|
|
_symbol_hook,
|
|
),
|
|
(
|
|
Union[
|
|
lsp_types.MarkupContent,
|
|
str,
|
|
lsp_types.MarkedString_Type1,
|
|
List[Union[str, lsp_types.MarkedString_Type1]],
|
|
],
|
|
_markup_content_hook,
|
|
),
|
|
(
|
|
Union[
|
|
lsp_types.TextDocumentEdit,
|
|
lsp_types.CreateFile,
|
|
lsp_types.RenameFile,
|
|
lsp_types.DeleteFile,
|
|
],
|
|
_document_edit_hook,
|
|
),
|
|
(
|
|
Optional[Union[bool, lsp_types.SemanticTokensOptionsFullType1]],
|
|
_semantic_tokens_hook,
|
|
),
|
|
(
|
|
Optional[
|
|
Union[
|
|
bool,
|
|
lsp_types.SemanticTokensClientCapabilitiesRequestsTypeFullType1,
|
|
]
|
|
],
|
|
_semantic_tokens_capabilities_hook,
|
|
),
|
|
(
|
|
Optional[Union[str, lsp_types.MarkupContent]],
|
|
_markup_content_hook,
|
|
),
|
|
(
|
|
Optional[Union[lsp_types.CodeActionKind, str]],
|
|
_code_action_kind_hook,
|
|
),
|
|
(
|
|
Union[lsp_types.CodeActionKind, str],
|
|
_code_action_kind_hook,
|
|
),
|
|
(
|
|
Union[lsp_types.PositionEncodingKind, str],
|
|
_position_encoding_kind_hook,
|
|
),
|
|
(
|
|
Optional[Union[lsp_types.FoldingRangeKind, str]],
|
|
_folding_range_kind_hook,
|
|
),
|
|
(
|
|
Union[lsp_types.FoldingRangeKind, str],
|
|
_folding_range_kind_hook,
|
|
),
|
|
(
|
|
Union[lsp_types.SemanticTokenTypes, str],
|
|
_semantic_token_types_hook,
|
|
),
|
|
(
|
|
Optional[Union[lsp_types.SemanticTokenTypes, str]],
|
|
_semantic_token_types_hook,
|
|
),
|
|
(
|
|
Union[lsp_types.SemanticTokenModifiers, str],
|
|
_semantic_token_modifiers_hook,
|
|
),
|
|
(
|
|
Optional[Union[lsp_types.SemanticTokenModifiers, str]],
|
|
_semantic_token_modifiers_hook,
|
|
),
|
|
(
|
|
Union[lsp_types.WatchKind, int],
|
|
_watch_kind_hook,
|
|
),
|
|
(
|
|
Optional[Union[lsp_types.WatchKind, int]],
|
|
_watch_kind_hook,
|
|
),
|
|
(
|
|
Union[
|
|
lsp_types.NotebookDocumentSyncOptionsNotebookSelectorType1,
|
|
lsp_types.NotebookDocumentSyncOptionsNotebookSelectorType2,
|
|
],
|
|
_notebook_sync_option_selector_hook,
|
|
),
|
|
(
|
|
Optional[
|
|
Union[
|
|
lsp_types.PositionEncodingKind,
|
|
str,
|
|
]
|
|
],
|
|
_position_encoding_hook,
|
|
),
|
|
(
|
|
Optional[Union[bool, lsp_types.SemanticTokensRegistrationOptionsFullType1]],
|
|
_semantic_token_registration_options_hook,
|
|
),
|
|
(
|
|
Optional[Union[bool, lsp_types.InlineCompletionOptions]],
|
|
_inline_completion_provider_hook,
|
|
),
|
|
(
|
|
Optional[
|
|
Union[
|
|
lsp_types.InlineCompletionList, List[lsp_types.InlineCompletionItem]
|
|
]
|
|
],
|
|
_inline_completion_list_hook,
|
|
),
|
|
(
|
|
Union[str, lsp_types.StringValue],
|
|
_string_value_hook,
|
|
),
|
|
(
|
|
Optional[
|
|
Union[
|
|
List[lsp_types.SymbolInformation], List[lsp_types.WorkspaceSymbol]
|
|
]
|
|
],
|
|
_symbol_list_hook,
|
|
),
|
|
(
|
|
Union[
|
|
lsp_types.NotebookDocumentSyncRegistrationOptionsNotebookSelectorType1,
|
|
lsp_types.NotebookDocumentSyncRegistrationOptionsNotebookSelectorType2,
|
|
],
|
|
_notebook_sync_registration_option_selector_hook,
|
|
),
|
|
]
|
|
for type_, hook in structure_hooks:
|
|
converter.register_structure_hook(type_, hook)
|
|
return converter
|
|
|
|
|
|
def _register_required_structure_hooks(
|
|
converter: cattrs.Converter,
|
|
) -> cattrs.Converter:
|
|
def _lsp_object_hook(object_: Any, type_: type) -> Any:
|
|
return object_
|
|
|
|
def _parameter_information_label_hook(
|
|
object_: Any, type: type
|
|
) -> Union[str, Tuple[int, int]]:
|
|
if isinstance(object_, str):
|
|
return object_
|
|
else:
|
|
return (int(object_[0]), int(object_[1]))
|
|
|
|
def _text_document_filter_hook(
|
|
object_: Any, _: type
|
|
) -> Union[
|
|
str,
|
|
lsp_types.TextDocumentFilter_Type1,
|
|
lsp_types.TextDocumentFilter_Type2,
|
|
lsp_types.TextDocumentFilter_Type3,
|
|
lsp_types.NotebookCellTextDocumentFilter,
|
|
]:
|
|
if isinstance(object_, str):
|
|
return str(object_)
|
|
elif "notebook" in object_:
|
|
return converter.structure(
|
|
object_, lsp_types.NotebookCellTextDocumentFilter
|
|
)
|
|
elif "language" in object_:
|
|
return converter.structure(object_, lsp_types.TextDocumentFilter_Type1)
|
|
elif "scheme" in object_:
|
|
return converter.structure(object_, lsp_types.TextDocumentFilter_Type2)
|
|
else:
|
|
return converter.structure(object_, lsp_types.TextDocumentFilter_Type3)
|
|
|
|
def _notebook_filter_hook(
|
|
object_: Any, _: type
|
|
) -> Union[
|
|
str,
|
|
lsp_types.NotebookDocumentFilter_Type1,
|
|
lsp_types.NotebookDocumentFilter_Type2,
|
|
lsp_types.NotebookDocumentFilter_Type3,
|
|
]:
|
|
if isinstance(object_, str):
|
|
return str(object_)
|
|
elif "notebookType" in object_:
|
|
return converter.structure(object_, lsp_types.NotebookDocumentFilter_Type1)
|
|
elif "scheme" in object_:
|
|
return converter.structure(object_, lsp_types.NotebookDocumentFilter_Type2)
|
|
else:
|
|
return converter.structure(object_, lsp_types.NotebookDocumentFilter_Type3)
|
|
|
|
# TODO: Remove the ignore after this issue with attrs is addressed in either attrs or mypy
|
|
NotebookSelectorItem = attrs.fields(
|
|
lsp_types.NotebookCellTextDocumentFilter
|
|
).notebook.type
|
|
STRUCTURE_HOOKS = [
|
|
(type(None), lambda object_, _type: object_),
|
|
(Optional[Union[int, str]], lambda object_, _type: object_),
|
|
(Union[int, str], lambda object_, _type: object_),
|
|
(lsp_types.LSPAny, _lsp_object_hook),
|
|
(Optional[Union[str, bool]], lambda object_, _type: object_),
|
|
(Optional[Union[bool, Any]], lambda object_, _type: object_),
|
|
(
|
|
Union[
|
|
lsp_types.TextDocumentFilter_Type1,
|
|
lsp_types.TextDocumentFilter_Type2,
|
|
lsp_types.TextDocumentFilter_Type3,
|
|
lsp_types.NotebookCellTextDocumentFilter,
|
|
],
|
|
_text_document_filter_hook,
|
|
),
|
|
(lsp_types.DocumentFilter, _text_document_filter_hook),
|
|
(
|
|
Union[
|
|
str,
|
|
lsp_types.NotebookDocumentFilter_Type1,
|
|
lsp_types.NotebookDocumentFilter_Type2,
|
|
lsp_types.NotebookDocumentFilter_Type3,
|
|
],
|
|
_notebook_filter_hook,
|
|
),
|
|
(NotebookSelectorItem, _notebook_filter_hook),
|
|
(
|
|
Union[lsp_types.LSPObject, List["LSPAny"], str, int, float, bool, None],
|
|
_lsp_object_hook,
|
|
),
|
|
(
|
|
Union[
|
|
lsp_types.LSPObject, List[lsp_types.LSPAny], str, int, float, bool, None
|
|
],
|
|
_lsp_object_hook,
|
|
),
|
|
(
|
|
Union[str, Tuple[int, int]],
|
|
_parameter_information_label_hook,
|
|
),
|
|
(lsp_types.LSPObject, _lsp_object_hook),
|
|
]
|
|
|
|
if sys.version_info > (3, 8):
|
|
STRUCTURE_HOOKS += [
|
|
(
|
|
Union[
|
|
lsp_types.LSPObject,
|
|
List[
|
|
Union[
|
|
lsp_types.LSPObject,
|
|
List["LSPAny"],
|
|
str,
|
|
int,
|
|
float,
|
|
bool,
|
|
None,
|
|
]
|
|
],
|
|
str,
|
|
int,
|
|
float,
|
|
bool,
|
|
None,
|
|
],
|
|
_lsp_object_hook,
|
|
)
|
|
]
|
|
|
|
for type_, hook in STRUCTURE_HOOKS:
|
|
converter.register_structure_hook(type_, hook)
|
|
|
|
return converter
|
|
|
|
|
|
def _register_custom_property_hooks(converter: cattrs.Converter) -> cattrs.Converter:
|
|
def _to_camel_case(name: str) -> str:
|
|
# TODO: when min Python becomes >= 3.9, then update this to:
|
|
# `return name.removesuffix("_")`.
|
|
new_name = name[:-1] if name.endswith("_") else name
|
|
parts = new_name.split("_")
|
|
return parts[0] + "".join(p.title() for p in parts[1:])
|
|
|
|
def _omit(cls: type, prop: str) -> bool:
|
|
special = lsp_types.is_special_property(cls, prop)
|
|
return not special
|
|
|
|
def _with_custom_unstructure(cls: type) -> Any:
|
|
attributes = {
|
|
a.name: cattrs.gen.override(
|
|
rename=_to_camel_case(a.name),
|
|
omit_if_default=_omit(cls, a.name),
|
|
)
|
|
for a in attrs.fields(cls)
|
|
}
|
|
return cattrs.gen.make_dict_unstructure_fn(cls, converter, **attributes)
|
|
|
|
def _with_custom_structure(cls: type) -> Any:
|
|
attributes = {
|
|
a.name: cattrs.gen.override(
|
|
rename=_to_camel_case(a.name),
|
|
omit_if_default=_omit(cls, a.name),
|
|
)
|
|
for a in attrs.fields(cls)
|
|
}
|
|
return cattrs.gen.make_dict_structure_fn(cls, converter, **attributes)
|
|
|
|
converter.register_unstructure_hook_factory(attrs.has, _with_custom_unstructure)
|
|
converter.register_structure_hook_factory(attrs.has, _with_custom_structure)
|
|
return converter
|