openlawlibrary / pygls

A pythonic generic language server
https://pygls.readthedocs.io/en/latest/
Apache License 2.0
575 stars 103 forks source link

Demote traceback to debug logging for unknown method #443

Closed nthykier closed 2 weeks ago

nthykier commented 6 months ago

I noticed that pygls raises a KeyError if a client with a traceback if it receives an unknown method. The error seems to be caught and handled with a proper error message on the protocol level (at least according to the log output). Given the error is handled, I would propose that pygls de-emphasises this to a single warning line with the option to see the full traceback via debugging.

Example output:

pygls.feature_manager: info: Registered builtin feature exit
pygls.feature_manager: info: Registered builtin feature initialize
pygls.feature_manager: info: Registered builtin feature initialized
pygls.feature_manager: info: Registered builtin feature notebookDocument/didChange
pygls.feature_manager: info: Registered builtin feature notebookDocument/didClose
pygls.feature_manager: info: Registered builtin feature notebookDocument/didOpen
pygls.feature_manager: info: Registered builtin feature $/setTrace
pygls.feature_manager: info: Registered builtin feature shutdown
pygls.feature_manager: info: Registered builtin feature textDocument/didChange
pygls.feature_manager: info: Registered builtin feature textDocument/didClose
pygls.feature_manager: info: Registered builtin feature textDocument/didOpen
pygls.feature_manager: info: Registered builtin feature window/workDoneProgress/cancel
pygls.feature_manager: info: Registered builtin feature workspace/didChangeWorkspaceFolders
pygls.feature_manager: info: Registered builtin feature workspace/executeCommand
pygls.feature_manager: info: Registered "textDocument/didChange" with options "None"
pygls.feature_manager: info: Registered "textDocument/didOpen" with options "None"
pygls.feature_manager: info: Registered "textDocument/completion" with options "None"
pygls.feature_manager: info: Registered "textDocument/hover" with options "None"
pygls.server: info: Starting TCP server on 127.0.0.1:2087
pygls.protocol.language_server: info: Language server initialized InitializeParams(capabilities=ClientCapabilities(workspace=WorkspaceClientCapabilities(apply_edit=True, workspace_edit=WorkspaceEditClientCapabilities(document_changes=True, resource_operations=None, failure_handling=None, normalizes_line_endings=None, change_annotation_support=None), did_change_configuration=None, did_change_watched_files=DidChangeWatchedFilesClientCapabilities(dynamic_registration=True, relative_pattern_support=None), symbol=WorkspaceSymbolClientCapabilities(dynamic_registration=False, symbol_kind=None, tag_support=None, resolve_support=None), execute_command=ExecuteCommandClientCapabilities(dynamic_registration=False), workspace_folders=True, configuration=True, semantic_tokens=None, code_lens=None, file_operations=None, inline_value=None, inlay_hint=None, diagnostics=None, folding_range=None), text_document=TextDocumentClientCapabilities(synchronization=TextDocumentSyncClientCapabilities(dynamic_registration=False, will_save=True, will_save_wait_until=True, did_save=True), completion=CompletionClientCapabilities(dynamic_registration=False, completion_item=CompletionClientCapabilitiesCompletionItemType(snippet_support=False, commit_characters_support=None, documentation_format=None, deprecated_support=True, preselect_support=None, tag_support=CompletionClientCapabilitiesCompletionItemTypeTagSupportType(value_set=[<CompletionItemTag.Deprecated: 1>]), insert_replace_support=None, resolve_support=CompletionClientCapabilitiesCompletionItemTypeResolveSupportType(properties=['documentation', 'details', 'additionalTextEdits']), insert_text_mode_support=None, label_details_support=None), completion_item_kind=None, insert_text_mode=None, context_support=True, completion_list=None), hover=HoverClientCapabilities(dynamic_registration=False, content_format=[<MarkupKind.PlainText: 'plaintext'>]), signature_help=SignatureHelpClientCapabilities(dynamic_registration=False, signature_information=SignatureHelpClientCapabilitiesSignatureInformationType(documentation_format=[<MarkupKind.PlainText: 'plaintext'>], parameter_information=SignatureHelpClientCapabilitiesSignatureInformationTypeParameterInformationType(label_offset_support=True), active_parameter_support=True), context_support=None), declaration=DeclarationClientCapabilities(dynamic_registration=False, link_support=True), definition=DefinitionClientCapabilities(dynamic_registration=False, link_support=True), type_definition=TypeDefinitionClientCapabilities(dynamic_registration=False, link_support=True), implementation=ImplementationClientCapabilities(dynamic_registration=False, link_support=True), references=ReferenceClientCapabilities(dynamic_registration=False), document_highlight=DocumentHighlightClientCapabilities(dynamic_registration=False), document_symbol=DocumentSymbolClientCapabilities(dynamic_registration=False, symbol_kind=DocumentSymbolClientCapabilitiesSymbolKindType(value_set=[<SymbolKind.File: 1>, <SymbolKind.Module: 2>, <SymbolKind.Namespace: 3>, <SymbolKind.Package: 4>, <SymbolKind.Class: 5>, <SymbolKind.Method: 6>, <SymbolKind.Property: 7>, <SymbolKind.Field: 8>, <SymbolKind.Constructor: 9>, <SymbolKind.Enum: 10>, <SymbolKind.Interface: 11>, <SymbolKind.Function: 12>, <SymbolKind.Variable: 13>, <SymbolKind.Constant: 14>, <SymbolKind.String: 15>, <SymbolKind.Number: 16>, <SymbolKind.Boolean: 17>, <SymbolKind.Array: 18>, <SymbolKind.Object: 19>, <SymbolKind.Key: 20>, <SymbolKind.Null: 21>, <SymbolKind.EnumMember: 22>, <SymbolKind.Struct: 23>, <SymbolKind.Event: 24>, <SymbolKind.Operator: 25>, <SymbolKind.TypeParameter: 26>]), hierarchical_document_symbol_support=True, tag_support=None, label_support=None), code_action=CodeActionClientCapabilities(dynamic_registration=False, code_action_literal_support=CodeActionClientCapabilitiesCodeActionLiteralSupportType(code_action_kind=CodeActionClientCapabilitiesCodeActionLiteralSupportTypeCodeActionKindType(value_set=['quickfix', 'refactor', 'refactor.extract', 'refactor.inline', 'refactor.rewrite', 'source', 'source.organizeImports'])), is_preferred_support=True, disabled_support=None, data_support=None, resolve_support=None, honors_change_annotations=None), code_lens=None, document_link=None, color_provider=None, formatting=DocumentFormattingClientCapabilities(dynamic_registration=False), range_formatting=DocumentRangeFormattingClientCapabilities(dynamic_registration=False, ranges_support=None), on_type_formatting=None, rename=RenameClientCapabilities(dynamic_registration=False, prepare_support=None, prepare_support_default_behavior=None, honors_change_annotations=None), folding_range=None, selection_range=None, publish_diagnostics=PublishDiagnosticsClientCapabilities(related_information=False, tag_support=PublishDiagnosticsClientCapabilitiesTagSupportType(value_set=[<DiagnosticTag.Unnecessary: 1>, <DiagnosticTag.Deprecated: 2>]), version_support=None, code_description_support=False, data_support=None), call_hierarchy=None, semantic_tokens=None, linked_editing_range=None, moniker=None, type_hierarchy=None, inline_value=None, inlay_hint=InlayHintClientCapabilities(dynamic_registration=False, resolve_support=None), diagnostic=None, inline_completion=None), notebook_document=None, window=WindowClientCapabilities(work_done_progress=True, show_message=None, show_document=None), general=GeneralClientCapabilities(stale_request_support=None, regular_expressions=None, markdown=None, position_encodings=['utf-32', 'utf-8', 'utf-16']), experimental={}), process_id=None, client_info=InitializeParamsClientInfoType(name='Eglot', version=None), locale=None, root_path='/path/to/project/', root_uri='file://path/to/project', initialization_options={}, trace=None, work_done_token=None, workspace_folders=[WorkspaceFolder(uri='file://path/to/project', name='/path/to/project/')])
pygls.protocol.json_rpc: info: Sending data: {"id": 1, "jsonrpc": "2.0", "result": {"capabilities": {"positionEncoding": "utf-16", "textDocumentSync": {"openClose": true, "change": 2, "willSave": false, "willSaveWaitUntil": false, "save": false}, "completionProvider": {}, "hoverProvider": true, "executeCommandProvider": {"commands": []}, "workspace": {"workspaceFolders": {"supported": true, "changeNotifications": true}, "fileOperations": {}}}, "serverInfo": {"name": "debputy", "version": "v0.1.20-43-g2e207d9"}}}
debputy: info: Opened/Changed document: path/to/project/debian/changelog (debian-changelog) - running diagnostics for doc version 0
pygls.protocol.json_rpc: warning: Ignoring notification for unknown method "workspace/didChangeConfiguration"
pygls.protocol.json_rpc: error: Failed to handle request 2 textDocument/documentSymbol DocumentSymbolParams(text_document=TextDocumentIdentifier(uri='file://path/to/project/debian/changelog'), work_done_token=None, partial_result_token=None)
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/pygls/protocol/json_rpc.py", line 218, in _get_handler
    return self.fm.builtin_features[feature_name]
           ~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^
KeyError: 'textDocument/documentSymbol'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/pygls/protocol/json_rpc.py", line 221, in _get_handler
    return self.fm.features[feature_name]
           ~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^
KeyError: 'textDocument/documentSymbol'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/pygls/protocol/json_rpc.py", line 260, in _handle_request
    handler = self._get_handler(method_name)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/pygls/protocol/json_rpc.py", line 223, in _get_handler
    raise JsonRpcMethodNotFound.of(feature_name)
pygls.exceptions.JsonRpcMethodNotFound: Method Not Found: textDocument/documentSymbol
pygls.protocol.json_rpc: info: Sending data: {"error": {"code": -32601, "message": "Method Not Found: textDocument/documentSymbol"}, "jsonrpc": "2.0", "id": 2}
tombh commented 6 months ago

Agreed, that seems very reasonable. PRs are welcome. Or of course we may well include this change in other refactoring work.