# 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