From a3f77b4f42381398f114524e0fc5a0f0e4152489 Mon Sep 17 00:00:00 2001 From: Alex Carney Date: Mon, 2 Jun 2025 11:09:16 +0100 Subject: [PATCH 1/4] chore: improve type annotations and docstrings This commit updates some of the type annotations in the `JsonRPCProtocol` class to be more accurate, reduce the number of false errors when running pyright lsp and hopefully, improve the quality of completion suggestions. The easiest way to "fix" the `handle_message` appeared to be to create a bunch of `Protocols` that describe the shape of incoming messages and use `isinstance` to pick between them. This does mean duplicating all of our fallback message types but I don't think that can be avoided as you cannot create an instance of a protocol. There are still more cases to fix, but this should be a step in the right direction. --- pygls/exceptions.py | 23 +++-- pygls/protocol/json_rpc.py | 204 +++++++++++++++++++++++++++---------- 2 files changed, 169 insertions(+), 58 deletions(-) diff --git a/pygls/exceptions.py b/pygls/exceptions.py index e1d9b2c0..edcf8bfd 100644 --- a/pygls/exceptions.py +++ b/pygls/exceptions.py @@ -16,6 +16,8 @@ # See the License for the specific language governing permissions and # # limitations under the License. # ############################################################################ +from __future__ import annotations + import traceback from typing import Any from typing import Set @@ -26,16 +28,23 @@ class JsonRpcException(Exception): """A class used as a base class for json rpc exceptions.""" + CODE = -32603 MESSAGE = "" - def __init__(self, message=None, code=None, data=None): - message = message or getattr(self.__class__, "MESSAGE") + def __init__( + self, + message: str | None = None, + code: int | None = None, + data: Any | None = None, + ): + message = message or self.MESSAGE + super().__init__(message) - self.message = message - self.code = code or getattr(self.__class__, "CODE", -32603) + self.message: str = message + self.code: int = code or self.CODE self.data = data - def __eq__(self, other): + def __eq__(self, other: Any): return ( isinstance(other, self.__class__) and self.code == other.code @@ -46,7 +55,7 @@ def __hash__(self): return hash((self.code, self.message)) @staticmethod - def from_error(error): + def from_error(error: ResponseError): for exc_class in _EXCEPTIONS: if exc_class.supports_code(error.code): return exc_class( @@ -65,7 +74,7 @@ def of(cls, exc: Any): ) @classmethod - def supports_code(cls, code): + def supports_code(cls, code: int): # Defaults to UnknownErrorCode return getattr(cls, "CODE", -32001) == code diff --git a/pygls/protocol/json_rpc.py b/pygls/protocol/json_rpc.py index 3a48c60e..76c0502c 100644 --- a/pygls/protocol/json_rpc.py +++ b/pygls/protocol/json_rpc.py @@ -28,7 +28,7 @@ import uuid from concurrent.futures import Future from functools import partial -from typing import Any, Callable, Type, Union +from typing import Any, Callable, Protocol, Type, Union, runtime_checkable import attrs from cattrs.errors import ClassValidationError @@ -68,6 +68,38 @@ MsgId = Union[str, int] +@runtime_checkable +class RPCNotification(Protocol): + method: str + jsonrpc: str + params: Any + + +@runtime_checkable +class RPCRequest(Protocol): + id: MsgId + method: str + jsonrpc: str + params: Any + + +@runtime_checkable +class RPCResponse(Protocol): + id: MsgId + jsonrpc: str + result: Any + + +@runtime_checkable +class RPCError(Protocol): + id: MsgId + jsonrpc: str + error: Any + + +RPCMessage = Union[RPCNotification, RPCResponse, RPCRequest, RPCError] + + @attrs.define class JsonRPCNotification: """A class that represents a generic json rpc notification message. @@ -256,7 +288,7 @@ def _run_generator( except Exception as exc: result_future.set_exception(exc) - def _send_handler_result(self, future: Future[Any], *, msg_id: str | int): + def _send_handler_result(self, future: Future[Any], *, msg_id: MsgId): """Callback function that sends the result of the given future to the client. Used to respond to request messages. @@ -296,7 +328,7 @@ def _check_handler_result(self, future: Future[Any]): error = JsonRpcInternalError.of(sys.exc_info()) self._server._report_server_error(error, FeatureNotificationError) - def _get_handler(self, feature_name): + def _get_handler(self, feature_name: str) -> MessageHandler: """Returns builtin or used defined feature by name if exists.""" if (handler := self.fm.builtin_features.get(feature_name)) is not None: @@ -307,7 +339,7 @@ def _get_handler(self, feature_name): raise JsonRpcMethodNotFound.of(feature_name) - def _handle_cancel_notification(self, msg_id): + def _handle_cancel_notification(self, msg_id: MsgId): """Handles a cancel notification from the client.""" future = self._request_futures.pop(msg_id, None) @@ -388,7 +420,12 @@ def _handle_request(self, msg_id: MsgId, method_name: str, params: Any): self._send_response(msg_id, None, err) self._server._report_server_error(error, FeatureRequestError) - def _handle_response(self, msg_id, result=None, error=None): + def _handle_response( + self, + msg_id: MsgId, + result: Any | None = None, + error: ResponseError | None = None, + ): """Handles a response from the client.""" future = self._request_futures.pop(msg_id, None) @@ -403,7 +440,7 @@ def _handle_response(self, msg_id, result=None, error=None): logger.debug('Received result for message "%s": %s', msg_id, result) future.set_result(result) - def _serialize_message(self, data): + def _serialize_message(self, data: Any) -> dict[str, Any]: """Function used to serialize data sent to the client.""" if hasattr(data, "__attrs_attrs__"): @@ -414,7 +451,7 @@ def _serialize_message(self, data): return data.__dict__ - def structure_message(self, data): + def structure_message(self, data: dict[str, Any]): """Function used to deserialize data recevied from the client.""" if "jsonrpc" not in data: @@ -448,7 +485,7 @@ def structure_message(self, data): logger.error("Unable to deserialize message\n%s", traceback.format_exc()) raise JsonRpcInternalError() from exc - def handle_message(self, message): + def handle_message(self, message: RPCMessage): """Delegates message to handlers depending on message type.""" if message.jsonrpc != JsonRPCProtocol.VERSION: @@ -462,24 +499,23 @@ def handle_message(self, message): # Run each handler within its own context. ctx = contextvars.copy_context() - if hasattr(message, "method"): - if hasattr(message, "id"): - logger.debug("Request %r received", message.method) - ctx.run( - self._handle_request, message.id, message.method, message.params - ) - else: - logger.debug("Notification %r received", message.method) - ctx.run(self._handle_notification, message.method, message.params) + if isinstance(message, RPCRequest): + logger.debug("Request %r received", message.method) + ctx.run(self._handle_request, message.id, message.method, message.params) + + elif isinstance(message, RPCNotification): + logger.debug("Notification %r received", message.method) + ctx.run(self._handle_notification, message.method, message.params) + + elif isinstance(message, RPCResponse): + logger.debug("Response message received.") + ctx.run(self._handle_response, message.id, message.result) + else: - if hasattr(message, "error"): - logger.debug("Error message received.") - ctx.run(self._handle_response, message.id, None, message.error) - else: - logger.debug("Response message received.") - ctx.run(self._handle_response, message.id, message.result) + logger.debug("Error message received.") + ctx.run(self._handle_response, message.id, None, message.error) - def _send_data(self, data): + def _send_data(self, data: Any): """Sends data to the client.""" if not data: return @@ -510,14 +546,28 @@ def _send_data(self, data): self._server._report_server_error(error, JsonRpcInternalError) def _send_response( - self, msg_id, result=None, error: Union[ResponseError, None] = None + self, + msg_id: MsgId, + result: Any | None = None, + error: Union[ResponseError, None] = None, ): - """Sends a JSON RPC response to the client. + """Send a JSON-RPC response + + .. important:: + + You should only set ``result`` OR ``error``. + If both are set, then the ``result`` value will be ignored. + + Parameters + ---------- + msg_id + The id of the message to respond to + + result + The result to send in the event of a success - Args: - msg_id(str): Id from request - result(any): Result returned by handler - error(any): Error returned by handler + error + The error to send in the event of a failure """ if error is not None: @@ -558,9 +608,24 @@ def get_result_type(self, method: str) -> Type[Any] | None: """Return the type definition of the result associated with the given method.""" return None - def notify(self, method: str, params=None): - """Sends a JSON RPC notification to the client.""" + def notify(self, method: str, params: Any | None = None): + """Send a JSON-RPC notification. + .. note:: + + Notifications are "fire-and-forget", there is no way for the recipient to + respond directly to a notification. If you expect a response to this message, + use ``send_request``. + + Parameters + ---------- + method + The method name of the message to send + + params + The payload of the message + + """ logger.debug("Sending notification: '%s' %s", method, params) notification_type = self.get_message_type(method) or JsonRPCNotification @@ -570,15 +635,35 @@ def notify(self, method: str, params=None): self._send_data(notification) - def send_request(self, method, params=None, callback=None, msg_id=None): - """Sends a JSON RPC request to the client. + def send_request( + self, + method: str, + params: Any | None = None, + callback: Callable[[Any], None] | None = None, + msg_id: MsgId | None = None, + ) -> Future[Any]: + """Send a JSON-RPC request + + Parameters + ---------- + method + The method name of the message to send + + params + The payload of the message - Args: - method(str): The method name of the message to send - params(any): The payload of the message + callback + If set, the given callback will be called with the result of the future + when it resolves + + msg_id + Send the request using the given id, if ``None``, an id will be automatically + generated - Returns: - Future that will be resolved once a response has been received + Returns + ------- + Future[Any] + A future that will resolve once a response has been received """ if msg_id is None: @@ -594,12 +679,12 @@ def send_request(self, method, params=None, callback=None, msg_id=None): jsonrpc=JsonRPCProtocol.VERSION, ) - future = Future() # type: ignore[var-annotated] + future: Future[Any] = Future() # If callback function is given, call it when result is received if callback: - def wrapper(future: Future): - result = future.result() + def wrapper(fut: Future[Any]): + result = fut.result() logger.info("Client response for %s received: %s", params, result) callback(result) @@ -612,17 +697,34 @@ def wrapper(future: Future): return future - def send_request_async(self, method, params=None, msg_id=None): - """Calls `send_request` and wraps `concurrent.futures.Future` with - `asyncio.Future` so it can be used with `await` keyword. + def send_request_async( + self, method: str, params: Any | None = None, msg_id: MsgId | None = None + ): + """Send a JSON-RPC request, asynchronously. + + This method calls `send_request`, wrapping the resulting future with + ``asyncio.wrap_future`` so it can be used in an ``async def`` function and + awaited with the ``await`` keyword. + + Parameters + ---------- + method + The method name of the message to send + + params + The payload of the message + + callback + If set, the given callback will be called with the result of the future + when it resolves - Args: - method(str): The method name of the message to send - params(any): The payload of the message - msg_id(str|int): Optional, message id + msg_id + Send the request using the given id, if ``None``, an id will be automatically + generated - Returns: - `asyncio.Future` that can be awaited + Returns + ------- + `asyncio.Future` that can be awaited """ return asyncio.wrap_future( self.send_request(method, params=params, msg_id=msg_id) From 1475823d13f37e4ace1aff9fbe265ef8ff7048bb Mon Sep 17 00:00:00 2001 From: Alex Carney Date: Mon, 2 Jun 2025 12:09:28 +0100 Subject: [PATCH 2/4] fix: crash on unknown message ids --- pygls/protocol/json_rpc.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pygls/protocol/json_rpc.py b/pygls/protocol/json_rpc.py index 76c0502c..c4789d6b 100644 --- a/pygls/protocol/json_rpc.py +++ b/pygls/protocol/json_rpc.py @@ -468,7 +468,8 @@ def structure_message(self, data: dict[str, Any]): return self._converter.structure(data, request_type) else: response_type = ( - self._result_types.pop(data["id"]) or JsonRPCResponseMessage + self._result_types.pop(data["id"], None) + or JsonRPCResponseMessage ) return self._converter.structure(data, response_type) From 245756dc6af9aa84a2882a0068eff7f178f94a1e Mon Sep 17 00:00:00 2001 From: Alex Carney Date: Mon, 2 Jun 2025 10:36:42 +0100 Subject: [PATCH 3/4] chore: improve type annotations in generated code --- pygls/lsp/_base_client.py | 150 ++++++++++++++++++++++---------------- pygls/lsp/_base_server.py | 71 +++++++++++------- scripts/generate_code.py | 86 +++++++++++++++++----- 3 files changed, 198 insertions(+), 109 deletions(-) diff --git a/pygls/lsp/_base_client.py b/pygls/lsp/_base_client.py index 6b9fafb0..54750e23 100644 --- a/pygls/lsp/_base_client.py +++ b/pygls/lsp/_base_client.py @@ -1,15 +1,38 @@ +############################################################################ +# Copyright(c) Open Law Library. All rights reserved. # +# See ThirdPartyNotices.txt in the project root for additional notices. # +# # +# Licensed under the Apache License, Version 2.0 (the "License") # +# you may not use this file except in compliance with the License. # +# You may obtain a copy of the License at # +# # +# http: // www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +############################################################################ + # GENERATED FROM scripts/generate_code.py -- DO NOT EDIT # flake8: noqa -from concurrent.futures import Future +from __future__ import annotations + from lsprotocol import types from pygls.client import JsonRPCClient from pygls.protocol import LanguageServerProtocol from pygls.protocol import default_converter -from typing import Any -from typing import Callable -from typing import Optional -from typing import Sequence -from typing import Union +import typing + +if typing.TYPE_CHECKING: + import cattrs + from concurrent.futures import Future + from typing import Any + from typing import Callable + from typing import Optional + from typing import Sequence + from typing import Union class BaseLanguageClient(JsonRPCClient): @@ -18,19 +41,18 @@ def __init__( self, name: str, version: str, - protocol_cls=LanguageServerProtocol, - converter_factory=default_converter, - **kwargs, + protocol_cls: type[LanguageServerProtocol] = LanguageServerProtocol, + converter_factory: Callable[[], cattrs.Converter] = default_converter, ): self.name = name self.version = version - super().__init__(protocol_cls, converter_factory, **kwargs) + super().__init__(protocol_cls, converter_factory) def call_hierarchy_incoming_calls( self, params: types.CallHierarchyIncomingCallsParams, callback: Optional[Callable[[Optional[Sequence[types.CallHierarchyIncomingCall]]], None]] = None, - ) -> Future: + ) -> Future[Optional[Sequence[types.CallHierarchyIncomingCall]]]: """Make a :lsp:`callHierarchy/incomingCalls` request. A request to resolve the incoming calls for a given `CallHierarchyItem`. @@ -61,7 +83,7 @@ def call_hierarchy_outgoing_calls( self, params: types.CallHierarchyOutgoingCallsParams, callback: Optional[Callable[[Optional[Sequence[types.CallHierarchyOutgoingCall]]], None]] = None, - ) -> Future: + ) -> Future[Optional[Sequence[types.CallHierarchyOutgoingCall]]]: """Make a :lsp:`callHierarchy/outgoingCalls` request. A request to resolve the outgoing calls for a given `CallHierarchyItem`. @@ -92,7 +114,7 @@ def code_action_resolve( self, params: types.CodeAction, callback: Optional[Callable[[types.CodeAction], None]] = None, - ) -> Future: + ) -> Future[types.CodeAction]: """Make a :lsp:`codeAction/resolve` request. Request to resolve additional information for a given code action.The request's @@ -123,7 +145,7 @@ def code_lens_resolve( self, params: types.CodeLens, callback: Optional[Callable[[types.CodeLens], None]] = None, - ) -> Future: + ) -> Future[types.CodeLens]: """Make a :lsp:`codeLens/resolve` request. A request to resolve a command for a given code lens. @@ -150,7 +172,7 @@ def completion_item_resolve( self, params: types.CompletionItem, callback: Optional[Callable[[types.CompletionItem], None]] = None, - ) -> Future: + ) -> Future[types.CompletionItem]: """Make a :lsp:`completionItem/resolve` request. Request to resolve additional information for a given completion item.The request's @@ -181,7 +203,7 @@ def document_link_resolve( self, params: types.DocumentLink, callback: Optional[Callable[[types.DocumentLink], None]] = None, - ) -> Future: + ) -> Future[types.DocumentLink]: """Make a :lsp:`documentLink/resolve` request. Request to resolve additional information for a given document link. The request's @@ -212,7 +234,7 @@ def initialize( self, params: types.InitializeParams, callback: Optional[Callable[[types.InitializeResult], None]] = None, - ) -> Future: + ) -> Future[types.InitializeResult]: """Make a :lsp:`initialize` request. The initialize request is sent from the client to the server. @@ -247,7 +269,7 @@ def inlay_hint_resolve( self, params: types.InlayHint, callback: Optional[Callable[[types.InlayHint], None]] = None, - ) -> Future: + ) -> Future[types.InlayHint]: """Make a :lsp:`inlayHint/resolve` request. A request to resolve additional properties for an inlay hint. @@ -282,7 +304,7 @@ def shutdown( self, params: None, callback: Optional[Callable[[None], None]] = None, - ) -> Future: + ) -> Future[None]: """Make a :lsp:`shutdown` request. A shutdown request is sent from the client to the server. @@ -315,7 +337,7 @@ def text_document_code_action( self, params: types.CodeActionParams, callback: Optional[Callable[[Optional[Sequence[Union[types.Command, types.CodeAction]]]], None]] = None, - ) -> Future: + ) -> Future[Optional[Sequence[Union[types.Command, types.CodeAction]]]]: """Make a :lsp:`textDocument/codeAction` request. A request to provide commands for the given text document and range. @@ -342,7 +364,7 @@ def text_document_code_lens( self, params: types.CodeLensParams, callback: Optional[Callable[[Optional[Sequence[types.CodeLens]]], None]] = None, - ) -> Future: + ) -> Future[Optional[Sequence[types.CodeLens]]]: """Make a :lsp:`textDocument/codeLens` request. A request to provide code lens for the given text document. @@ -369,7 +391,7 @@ def text_document_color_presentation( self, params: types.ColorPresentationParams, callback: Optional[Callable[[Sequence[types.ColorPresentation]], None]] = None, - ) -> Future: + ) -> Future[Sequence[types.ColorPresentation]]: """Make a :lsp:`textDocument/colorPresentation` request. A request to list all presentation for a color. The request's @@ -402,7 +424,7 @@ def text_document_completion( self, params: types.CompletionParams, callback: Optional[Callable[[Union[Sequence[types.CompletionItem], types.CompletionList, None]], None]] = None, - ) -> Future: + ) -> Future[Union[Sequence[types.CompletionItem], types.CompletionList, None]]: """Make a :lsp:`textDocument/completion` request. Request to request completion at a given text document position. The request's @@ -445,7 +467,7 @@ def text_document_declaration( self, params: types.DeclarationParams, callback: Optional[Callable[[Union[types.Location, Sequence[types.Location], Sequence[types.LocationLink], None]], None]] = None, - ) -> Future: + ) -> Future[Union[types.Location, Sequence[types.Location], Sequence[types.LocationLink], None]]: """Make a :lsp:`textDocument/declaration` request. A request to resolve the type definition locations of a symbol at a given text @@ -478,7 +500,7 @@ def text_document_definition( self, params: types.DefinitionParams, callback: Optional[Callable[[Union[types.Location, Sequence[types.Location], Sequence[types.LocationLink], None]], None]] = None, - ) -> Future: + ) -> Future[Union[types.Location, Sequence[types.Location], Sequence[types.LocationLink], None]]: """Make a :lsp:`textDocument/definition` request. A request to resolve the definition location of a symbol at a given text @@ -511,7 +533,7 @@ def text_document_diagnostic( self, params: types.DocumentDiagnosticParams, callback: Optional[Callable[[Union[types.RelatedFullDocumentDiagnosticReport, types.RelatedUnchangedDocumentDiagnosticReport]], None]] = None, - ) -> Future: + ) -> Future[Union[types.RelatedFullDocumentDiagnosticReport, types.RelatedUnchangedDocumentDiagnosticReport]]: """Make a :lsp:`textDocument/diagnostic` request. The document diagnostic request definition. @@ -542,7 +564,7 @@ def text_document_document_color( self, params: types.DocumentColorParams, callback: Optional[Callable[[Sequence[types.ColorInformation]], None]] = None, - ) -> Future: + ) -> Future[Sequence[types.ColorInformation]]: """Make a :lsp:`textDocument/documentColor` request. A request to list all color symbols found in a given text document. The request's @@ -575,7 +597,7 @@ def text_document_document_highlight( self, params: types.DocumentHighlightParams, callback: Optional[Callable[[Optional[Sequence[types.DocumentHighlight]]], None]] = None, - ) -> Future: + ) -> Future[Optional[Sequence[types.DocumentHighlight]]]: """Make a :lsp:`textDocument/documentHighlight` request. Request to resolve a {@link DocumentHighlight} for a given @@ -608,7 +630,7 @@ def text_document_document_link( self, params: types.DocumentLinkParams, callback: Optional[Callable[[Optional[Sequence[types.DocumentLink]]], None]] = None, - ) -> Future: + ) -> Future[Optional[Sequence[types.DocumentLink]]]: """Make a :lsp:`textDocument/documentLink` request. A request to provide document links @@ -635,7 +657,7 @@ def text_document_document_symbol( self, params: types.DocumentSymbolParams, callback: Optional[Callable[[Union[Sequence[types.SymbolInformation], Sequence[types.DocumentSymbol], None]], None]] = None, - ) -> Future: + ) -> Future[Union[Sequence[types.SymbolInformation], Sequence[types.DocumentSymbol], None]]: """Make a :lsp:`textDocument/documentSymbol` request. A request to list all symbols found in a given text document. The request's @@ -668,7 +690,7 @@ def text_document_folding_range( self, params: types.FoldingRangeParams, callback: Optional[Callable[[Optional[Sequence[types.FoldingRange]]], None]] = None, - ) -> Future: + ) -> Future[Optional[Sequence[types.FoldingRange]]]: """Make a :lsp:`textDocument/foldingRange` request. A request to provide folding ranges in a document. The request's @@ -701,7 +723,7 @@ def text_document_formatting( self, params: types.DocumentFormattingParams, callback: Optional[Callable[[Optional[Sequence[types.TextEdit]]], None]] = None, - ) -> Future: + ) -> Future[Optional[Sequence[types.TextEdit]]]: """Make a :lsp:`textDocument/formatting` request. A request to format a whole document. @@ -728,7 +750,7 @@ def text_document_hover( self, params: types.HoverParams, callback: Optional[Callable[[Optional[types.Hover]], None]] = None, - ) -> Future: + ) -> Future[Optional[types.Hover]]: """Make a :lsp:`textDocument/hover` request. Request to request hover information at a given text document position. The request's @@ -759,7 +781,7 @@ def text_document_implementation( self, params: types.ImplementationParams, callback: Optional[Callable[[Union[types.Location, Sequence[types.Location], Sequence[types.LocationLink], None]], None]] = None, - ) -> Future: + ) -> Future[Union[types.Location, Sequence[types.Location], Sequence[types.LocationLink], None]]: """Make a :lsp:`textDocument/implementation` request. A request to resolve the implementation locations of a symbol at a given text @@ -790,7 +812,7 @@ def text_document_inlay_hint( self, params: types.InlayHintParams, callback: Optional[Callable[[Optional[Sequence[types.InlayHint]]], None]] = None, - ) -> Future: + ) -> Future[Optional[Sequence[types.InlayHint]]]: """Make a :lsp:`textDocument/inlayHint` request. A request to provide inlay hints in a document. The request's parameter is of @@ -825,7 +847,7 @@ def text_document_inline_completion( self, params: types.InlineCompletionParams, callback: Optional[Callable[[Union[types.InlineCompletionList, Sequence[types.InlineCompletionItem], None]], None]] = None, - ) -> Future: + ) -> Future[Union[types.InlineCompletionList, Sequence[types.InlineCompletionItem], None]]: """Make a :lsp:`textDocument/inlineCompletion` request. A request to provide inline completions in a document. The request's parameter is of @@ -862,7 +884,7 @@ def text_document_inline_value( self, params: types.InlineValueParams, callback: Optional[Callable[[Optional[Sequence[Union[types.InlineValueText, types.InlineValueVariableLookup, types.InlineValueEvaluatableExpression]]]], None]] = None, - ) -> Future: + ) -> Future[Optional[Sequence[Union[types.InlineValueText, types.InlineValueVariableLookup, types.InlineValueEvaluatableExpression]]]]: """Make a :lsp:`textDocument/inlineValue` request. A request to provide inline values in a document. The request's parameter is of @@ -897,7 +919,7 @@ def text_document_linked_editing_range( self, params: types.LinkedEditingRangeParams, callback: Optional[Callable[[Optional[types.LinkedEditingRanges]], None]] = None, - ) -> Future: + ) -> Future[Optional[types.LinkedEditingRanges]]: """Make a :lsp:`textDocument/linkedEditingRange` request. A request to provide ranges that can be edited together. @@ -928,7 +950,7 @@ def text_document_moniker( self, params: types.MonikerParams, callback: Optional[Callable[[Optional[Sequence[types.Moniker]]], None]] = None, - ) -> Future: + ) -> Future[Optional[Sequence[types.Moniker]]]: """Make a :lsp:`textDocument/moniker` request. A request to get the moniker of a symbol at a given text document position. @@ -959,7 +981,7 @@ def text_document_on_type_formatting( self, params: types.DocumentOnTypeFormattingParams, callback: Optional[Callable[[Optional[Sequence[types.TextEdit]]], None]] = None, - ) -> Future: + ) -> Future[Optional[Sequence[types.TextEdit]]]: """Make a :lsp:`textDocument/onTypeFormatting` request. A request to format a document on type. @@ -986,7 +1008,7 @@ def text_document_prepare_call_hierarchy( self, params: types.CallHierarchyPrepareParams, callback: Optional[Callable[[Optional[Sequence[types.CallHierarchyItem]]], None]] = None, - ) -> Future: + ) -> Future[Optional[Sequence[types.CallHierarchyItem]]]: """Make a :lsp:`textDocument/prepareCallHierarchy` request. A request to result a `CallHierarchyItem` in a document at a given position. @@ -1019,7 +1041,7 @@ def text_document_prepare_rename( self, params: types.PrepareRenameParams, callback: Optional[Callable[[Union[types.Range, types.PrepareRenamePlaceholder, types.PrepareRenameDefaultBehavior, None]], None]] = None, - ) -> Future: + ) -> Future[Union[types.Range, types.PrepareRenamePlaceholder, types.PrepareRenameDefaultBehavior, None]]: """Make a :lsp:`textDocument/prepareRename` request. A request to test and perform the setup necessary for a rename. @@ -1050,7 +1072,7 @@ def text_document_prepare_type_hierarchy( self, params: types.TypeHierarchyPrepareParams, callback: Optional[Callable[[Optional[Sequence[types.TypeHierarchyItem]]], None]] = None, - ) -> Future: + ) -> Future[Optional[Sequence[types.TypeHierarchyItem]]]: """Make a :lsp:`textDocument/prepareTypeHierarchy` request. A request to result a `TypeHierarchyItem` in a document at a given position. @@ -1083,7 +1105,7 @@ def text_document_ranges_formatting( self, params: types.DocumentRangesFormattingParams, callback: Optional[Callable[[Optional[Sequence[types.TextEdit]]], None]] = None, - ) -> Future: + ) -> Future[Optional[Sequence[types.TextEdit]]]: """Make a :lsp:`textDocument/rangesFormatting` request. A request to format ranges in a document. @@ -1116,7 +1138,7 @@ def text_document_range_formatting( self, params: types.DocumentRangeFormattingParams, callback: Optional[Callable[[Optional[Sequence[types.TextEdit]]], None]] = None, - ) -> Future: + ) -> Future[Optional[Sequence[types.TextEdit]]]: """Make a :lsp:`textDocument/rangeFormatting` request. A request to format a range in a document. @@ -1143,7 +1165,7 @@ def text_document_references( self, params: types.ReferenceParams, callback: Optional[Callable[[Optional[Sequence[types.Location]]], None]] = None, - ) -> Future: + ) -> Future[Optional[Sequence[types.Location]]]: """Make a :lsp:`textDocument/references` request. A request to resolve project-wide references for the symbol denoted @@ -1176,7 +1198,7 @@ def text_document_rename( self, params: types.RenameParams, callback: Optional[Callable[[Optional[types.WorkspaceEdit]], None]] = None, - ) -> Future: + ) -> Future[Optional[types.WorkspaceEdit]]: """Make a :lsp:`textDocument/rename` request. A request to rename a symbol. @@ -1203,7 +1225,7 @@ def text_document_selection_range( self, params: types.SelectionRangeParams, callback: Optional[Callable[[Optional[Sequence[types.SelectionRange]]], None]] = None, - ) -> Future: + ) -> Future[Optional[Sequence[types.SelectionRange]]]: """Make a :lsp:`textDocument/selectionRange` request. A request to provide selection ranges in a document. The request's @@ -1236,7 +1258,7 @@ def text_document_semantic_tokens_full( self, params: types.SemanticTokensParams, callback: Optional[Callable[[Optional[types.SemanticTokens]], None]] = None, - ) -> Future: + ) -> Future[Optional[types.SemanticTokens]]: """Make a :lsp:`textDocument/semanticTokens/full` request. @since 3.16.0 @@ -1263,7 +1285,7 @@ def text_document_semantic_tokens_full_delta( self, params: types.SemanticTokensDeltaParams, callback: Optional[Callable[[Union[types.SemanticTokens, types.SemanticTokensDelta, None]], None]] = None, - ) -> Future: + ) -> Future[Union[types.SemanticTokens, types.SemanticTokensDelta, None]]: """Make a :lsp:`textDocument/semanticTokens/full/delta` request. @since 3.16.0 @@ -1290,7 +1312,7 @@ def text_document_semantic_tokens_range( self, params: types.SemanticTokensRangeParams, callback: Optional[Callable[[Optional[types.SemanticTokens]], None]] = None, - ) -> Future: + ) -> Future[Optional[types.SemanticTokens]]: """Make a :lsp:`textDocument/semanticTokens/range` request. @since 3.16.0 @@ -1317,7 +1339,7 @@ def text_document_signature_help( self, params: types.SignatureHelpParams, callback: Optional[Callable[[Optional[types.SignatureHelp]], None]] = None, - ) -> Future: + ) -> Future[Optional[types.SignatureHelp]]: """Make a :lsp:`textDocument/signatureHelp` request. @@ -1344,7 +1366,7 @@ def text_document_type_definition( self, params: types.TypeDefinitionParams, callback: Optional[Callable[[Union[types.Location, Sequence[types.Location], Sequence[types.LocationLink], None]], None]] = None, - ) -> Future: + ) -> Future[Union[types.Location, Sequence[types.Location], Sequence[types.LocationLink], None]]: """Make a :lsp:`textDocument/typeDefinition` request. A request to resolve the type definition locations of a symbol at a given text @@ -1375,7 +1397,7 @@ def text_document_will_save_wait_until( self, params: types.WillSaveTextDocumentParams, callback: Optional[Callable[[Optional[Sequence[types.TextEdit]]], None]] = None, - ) -> Future: + ) -> Future[Optional[Sequence[types.TextEdit]]]: """Make a :lsp:`textDocument/willSaveWaitUntil` request. A document will save request is sent from the client to the server before @@ -1412,7 +1434,7 @@ def type_hierarchy_subtypes( self, params: types.TypeHierarchySubtypesParams, callback: Optional[Callable[[Optional[Sequence[types.TypeHierarchyItem]]], None]] = None, - ) -> Future: + ) -> Future[Optional[Sequence[types.TypeHierarchyItem]]]: """Make a :lsp:`typeHierarchy/subtypes` request. A request to resolve the subtypes for a given `TypeHierarchyItem`. @@ -1443,7 +1465,7 @@ def type_hierarchy_supertypes( self, params: types.TypeHierarchySupertypesParams, callback: Optional[Callable[[Optional[Sequence[types.TypeHierarchyItem]]], None]] = None, - ) -> Future: + ) -> Future[Optional[Sequence[types.TypeHierarchyItem]]]: """Make a :lsp:`typeHierarchy/supertypes` request. A request to resolve the supertypes for a given `TypeHierarchyItem`. @@ -1474,7 +1496,7 @@ def workspace_diagnostic( self, params: types.WorkspaceDiagnosticParams, callback: Optional[Callable[[types.WorkspaceDiagnosticReport], None]] = None, - ) -> Future: + ) -> Future[types.WorkspaceDiagnosticReport]: """Make a :lsp:`workspace/diagnostic` request. The workspace diagnostic request definition. @@ -1505,7 +1527,7 @@ def workspace_execute_command( self, params: types.ExecuteCommandParams, callback: Optional[Callable[[Optional[Any]], None]] = None, - ) -> Future: + ) -> Future[Optional[Any]]: """Make a :lsp:`workspace/executeCommand` request. A request send from the client to the server to execute a command. The request might return @@ -1534,7 +1556,7 @@ def workspace_symbol( self, params: types.WorkspaceSymbolParams, callback: Optional[Callable[[Union[Sequence[types.SymbolInformation], Sequence[types.WorkspaceSymbol], None]], None]] = None, - ) -> Future: + ) -> Future[Union[Sequence[types.SymbolInformation], Sequence[types.WorkspaceSymbol], None]]: """Make a :lsp:`workspace/symbol` request. A request to list project-wide symbols matching the query string given @@ -1575,7 +1597,7 @@ def workspace_symbol_resolve( self, params: types.WorkspaceSymbol, callback: Optional[Callable[[types.WorkspaceSymbol], None]] = None, - ) -> Future: + ) -> Future[types.WorkspaceSymbol]: """Make a :lsp:`workspaceSymbol/resolve` request. A request to resolve the range inside the workspace @@ -1608,7 +1630,7 @@ def workspace_text_document_content( self, params: types.TextDocumentContentParams, callback: Optional[Callable[[types.TextDocumentContentResult], None]] = None, - ) -> Future: + ) -> Future[types.TextDocumentContentResult]: """Make a :lsp:`workspace/textDocumentContent` request. The `workspace/textDocumentContent` request is sent from the client to the @@ -1643,7 +1665,7 @@ def workspace_will_create_files( self, params: types.CreateFilesParams, callback: Optional[Callable[[Optional[types.WorkspaceEdit]], None]] = None, - ) -> Future: + ) -> Future[Optional[types.WorkspaceEdit]]: """Make a :lsp:`workspace/willCreateFiles` request. The will create files request is sent from the client to the server before files are actually @@ -1684,7 +1706,7 @@ def workspace_will_delete_files( self, params: types.DeleteFilesParams, callback: Optional[Callable[[Optional[types.WorkspaceEdit]], None]] = None, - ) -> Future: + ) -> Future[Optional[types.WorkspaceEdit]]: """Make a :lsp:`workspace/willDeleteFiles` request. The did delete files notification is sent from the client to the server when @@ -1717,7 +1739,7 @@ def workspace_will_rename_files( self, params: types.RenameFilesParams, callback: Optional[Callable[[Optional[types.WorkspaceEdit]], None]] = None, - ) -> Future: + ) -> Future[Optional[types.WorkspaceEdit]]: """Make a :lsp:`workspace/willRenameFiles` request. The will rename files request is sent from the client to the server before files are actually diff --git a/pygls/lsp/_base_server.py b/pygls/lsp/_base_server.py index 3dffa173..a6869763 100644 --- a/pygls/lsp/_base_server.py +++ b/pygls/lsp/_base_server.py @@ -1,17 +1,37 @@ +############################################################################ +# Copyright(c) Open Law Library. All rights reserved. # +# See ThirdPartyNotices.txt in the project root for additional notices. # +# # +# Licensed under the Apache License, Version 2.0 (the "License") # +# you may not use this file except in compliance with the License. # +# You may obtain a copy of the License at # +# # +# http: // www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +############################################################################ + # GENERATED FROM scripts/generate_code.py -- DO NOT EDIT # flake8: noqa -from cattrs import Converter -from concurrent.futures import Future +from __future__ import annotations + from lsprotocol import types from pygls.protocol import LanguageServerProtocol from pygls.protocol import default_converter from pygls.server import JsonRPCServer import typing -from typing import Any -from typing import Callable -from typing import Optional -from typing import Sequence -from typing import Type + +if typing.TYPE_CHECKING: + from cattrs import Converter + from concurrent.futures import Future + from typing import Any + from typing import Callable + from typing import Optional + from typing import Sequence class BaseLanguageServer(JsonRPCServer): @@ -20,18 +40,17 @@ class BaseLanguageServer(JsonRPCServer): def __init__( self, - protocol_cls: Type[LanguageServerProtocol] = LanguageServerProtocol, + protocol_cls: type[LanguageServerProtocol] = LanguageServerProtocol, converter_factory: Callable[[], Converter] = default_converter, - max_workers: Optional[int] = None, - **kwargs, + max_workers: int | None = None, ): - super().__init__(protocol_cls, converter_factory, max_workers, **kwargs) + super().__init__(protocol_cls, converter_factory, max_workers) def client_register_capability( self, params: types.RegistrationParams, callback: Optional[Callable[[None], None]] = None, - ) -> Future: + ) -> Future[None]: """Make a :lsp:`client/registerCapability` request. The `client/registerCapability` request is sent from the server to the client to register a new capability @@ -54,7 +73,7 @@ def client_unregister_capability( self, params: types.UnregistrationParams, callback: Optional[Callable[[None], None]] = None, - ) -> Future: + ) -> Future[None]: """Make a :lsp:`client/unregisterCapability` request. The `client/unregisterCapability` request is sent from the server to the client to unregister a previously registered capability @@ -77,7 +96,7 @@ def window_show_document( self, params: types.ShowDocumentParams, callback: Optional[Callable[[types.ShowDocumentResult], None]] = None, - ) -> Future: + ) -> Future[types.ShowDocumentResult]: """Make a :lsp:`window/showDocument` request. A request to show a document. This request might open an @@ -108,7 +127,7 @@ def window_show_message_request( self, params: types.ShowMessageRequestParams, callback: Optional[Callable[[Optional[types.MessageActionItem]], None]] = None, - ) -> Future: + ) -> Future[Optional[types.MessageActionItem]]: """Make a :lsp:`window/showMessageRequest` request. The show message request is sent from the server to the client to show a message @@ -131,7 +150,7 @@ def window_work_done_progress_create( self, params: types.WorkDoneProgressCreateParams, callback: Optional[Callable[[None], None]] = None, - ) -> Future: + ) -> Future[None]: """Make a :lsp:`window/workDoneProgress/create` request. The `window/workDoneProgress/create` request is sent from the server to the client to initiate progress @@ -154,7 +173,7 @@ def workspace_apply_edit( self, params: types.ApplyWorkspaceEditParams, callback: Optional[Callable[[types.ApplyWorkspaceEditResult], None]] = None, - ) -> Future: + ) -> Future[types.ApplyWorkspaceEditResult]: """Make a :lsp:`workspace/applyEdit` request. A request sent from the server to the client to modified certain resources. @@ -175,7 +194,7 @@ def workspace_code_lens_refresh( self, params: None, callback: Optional[Callable[[None], None]] = None, - ) -> Future: + ) -> Future[None]: """Make a :lsp:`workspace/codeLens/refresh` request. A request to refresh all code actions @@ -200,7 +219,7 @@ def workspace_configuration( self, params: types.ConfigurationParams, callback: Optional[Callable[[Sequence[Optional[Any]]], None]] = None, - ) -> Future: + ) -> Future[Sequence[Optional[Any]]]: """Make a :lsp:`workspace/configuration` request. The 'workspace/configuration' request is sent from the server to the client to fetch a certain @@ -233,7 +252,7 @@ def workspace_diagnostic_refresh( self, params: None, callback: Optional[Callable[[None], None]] = None, - ) -> Future: + ) -> Future[None]: """Make a :lsp:`workspace/diagnostic/refresh` request. The diagnostic refresh request definition. @@ -258,7 +277,7 @@ def workspace_folding_range_refresh( self, params: None, callback: Optional[Callable[[None], None]] = None, - ) -> Future: + ) -> Future[None]: """Make a :lsp:`workspace/foldingRange/refresh` request. @since 3.18.0 @@ -281,7 +300,7 @@ def workspace_inlay_hint_refresh( self, params: None, callback: Optional[Callable[[None], None]] = None, - ) -> Future: + ) -> Future[None]: """Make a :lsp:`workspace/inlayHint/refresh` request. @since 3.17.0 @@ -302,7 +321,7 @@ def workspace_inline_value_refresh( self, params: None, callback: Optional[Callable[[None], None]] = None, - ) -> Future: + ) -> Future[None]: """Make a :lsp:`workspace/inlineValue/refresh` request. @since 3.17.0 @@ -323,7 +342,7 @@ def workspace_semantic_tokens_refresh( self, params: None, callback: Optional[Callable[[None], None]] = None, - ) -> Future: + ) -> Future[None]: """Make a :lsp:`workspace/semanticTokens/refresh` request. @since 3.16.0 @@ -344,7 +363,7 @@ def workspace_text_document_content_refresh( self, params: types.TextDocumentContentRefreshParams, callback: Optional[Callable[[None], None]] = None, - ) -> Future: + ) -> Future[None]: """Make a :lsp:`workspace/textDocumentContent/refresh` request. The `workspace/textDocumentContent` request is sent from the server to the client to refresh @@ -373,7 +392,7 @@ def workspace_workspace_folders( self, params: None, callback: Optional[Callable[[Optional[Sequence[types.WorkspaceFolder]]], None]] = None, - ) -> Future: + ) -> Future[Optional[Sequence[types.WorkspaceFolder]]]: """Make a :lsp:`workspace/workspaceFolders` request. The `workspace/workspaceFolders` is sent from the server to the client to fetch the open workspace folders. diff --git a/scripts/generate_code.py b/scripts/generate_code.py index 217b70af..42c03a3e 100644 --- a/scripts/generate_code.py +++ b/scripts/generate_code.py @@ -1,4 +1,4 @@ -"""Script to automatically generate a lanaguge client and server from `lsprotocol` +"""Script to automatically generate a lanaguge client and server from `lsprotocol` type definitons.""" import argparse @@ -20,8 +20,28 @@ ) cli.add_argument("output", type=pathlib.Path) +LICENSE_HEADER = """\ +############################################################################ +# Copyright(c) Open Law Library. All rights reserved. # +# See ThirdPartyNotices.txt in the project root for additional notices. # +# # +# Licensed under the Apache License, Version 2.0 (the "License") # +# you may not use this file except in compliance with the License. # +# You may obtain a copy of the License at # +# # +# http: // www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +############################################################################ +""" + def write_imports(imports: Set[Tuple[str, str]]) -> str: + """Write the standard runtime Python imports for the given set of ``imports``""" lines = [] for import_ in sorted(list(imports), key=lambda i: (i[0], i[1])): @@ -35,6 +55,15 @@ def write_imports(imports: Set[Tuple[str, str]]) -> str: return "\n".join(lines) +def write_typing_imports(imports: Set[Tuple[str, str]]) -> str: + """Write ``TYPE_CHECKING`` imports for the given set of ``imports``""" + lines = [ + "if typing.TYPE_CHECKING:", + textwrap.indent(write_imports(imports), " " * 4), + ] + return "\n".join(lines) + + def to_snake_case(string: str) -> str: return "".join(f"_{c.lower()}" if c.isupper() else c for c in string) @@ -142,7 +171,7 @@ def write_client_method( " self,", f" params: {param_mod}{param_name},", f" callback: Optional[Callable[[{result_type}], None]] = None,", - ") -> Future:", + f") -> Future[{result_type}]:", f' """Make a :lsp:`{method}` request.', "", textwrap.indent(inspect.getdoc(request) or "", " "), @@ -193,7 +222,7 @@ def write_server_method( " self,", f" params: {param_mod}{param_name},", f" callback: Optional[Callable[[{result_type}], None]] = None,", - ") -> Future:", + f") -> Future[{result_type}]:", f' """Make a :lsp:`{method}` request.', "", textwrap.indent(inspect.getdoc(request) or "", " "), @@ -217,11 +246,16 @@ def write_server_method( def generate_client() -> str: methods = [] imports = { - ("concurrent.futures", "Future"), + "typing", ("lsprotocol", "types"), ("pygls.protocol", "LanguageServerProtocol"), ("pygls.protocol", "default_converter"), ("pygls.client", "JsonRPCClient"), + } + + typing_imports = { + "cattrs", + ("concurrent.futures", "Future"), ("typing", "Callable"), ("typing", "Optional"), } @@ -234,19 +268,26 @@ def generate_client() -> str: request, response, params, _ = types if response is None: - method = write_client_notification(method_name, request, params, imports) + method = write_client_notification( + method_name, request, params, typing_imports + ) else: method = write_client_method( - method_name, request, params, response, imports + method_name, request, params, response, typing_imports ) methods.append(textwrap.indent(method, " ")) code = [ + LICENSE_HEADER, "# GENERATED FROM scripts/generate_code.py -- DO NOT EDIT", "# flake8: noqa", + "from __future__ import annotations", + "", write_imports(imports), "", + write_typing_imports(typing_imports), + "", "", "class BaseLanguageClient(JsonRPCClient):", "", @@ -254,13 +295,12 @@ def generate_client() -> str: " self,", " name: str,", " version: str,", - " protocol_cls=LanguageServerProtocol,", - " converter_factory=default_converter,", - " **kwargs,", + " protocol_cls: type[LanguageServerProtocol] = LanguageServerProtocol,", + " converter_factory: Callable[[], cattrs.Converter] = default_converter,", " ):", " self.name = name", " self.version = version", - " super().__init__(protocol_cls, converter_factory, **kwargs)", + " super().__init__(protocol_cls, converter_factory)", "", *methods, ] @@ -271,15 +311,17 @@ def generate_server() -> str: methods = [] imports = { "typing", - ("concurrent.futures", "Future"), ("lsprotocol", "types"), - ("cattrs", "Converter"), ("pygls.protocol", "LanguageServerProtocol"), ("pygls.protocol", "default_converter"), ("pygls.server", "JsonRPCServer"), + } + + typing_imports = { + ("concurrent.futures", "Future"), ("typing", "Callable"), ("typing", "Optional"), - ("typing", "Type"), + ("cattrs", "Converter"), } for method_name, types in METHOD_TO_TYPES.items(): @@ -290,19 +332,26 @@ def generate_server() -> str: request, response, params, _ = types if response is None: - method = write_server_notification(method_name, request, params, imports) + method = write_server_notification( + method_name, request, params, typing_imports + ) else: method = write_server_method( - method_name, request, params, response, imports + method_name, request, params, response, typing_imports ) methods.append(textwrap.indent(method, " ")) code = [ + LICENSE_HEADER, "# GENERATED FROM scripts/generate_code.py -- DO NOT EDIT", "# flake8: noqa", + "from __future__ import annotations", + "", write_imports(imports), "", + write_typing_imports(typing_imports), + "", "", "class BaseLanguageServer(JsonRPCServer):", "", @@ -310,12 +359,11 @@ def generate_server() -> str: "", " def __init__(", " self,", - " protocol_cls: Type[LanguageServerProtocol] = LanguageServerProtocol,", + " protocol_cls: type[LanguageServerProtocol] = LanguageServerProtocol,", " converter_factory: Callable[[], Converter] = default_converter,", - " max_workers: Optional[int] = None,", - " **kwargs,", + " max_workers: int | None = None,", " ):", - " super().__init__(protocol_cls, converter_factory, max_workers, **kwargs)", + " super().__init__(protocol_cls, converter_factory, max_workers)", "", *methods, ] From 16480b8b990f08180788b11d6865c8da33c2def8 Mon Sep 17 00:00:00 2001 From: Alex Carney Date: Mon, 2 Jun 2025 14:52:27 +0100 Subject: [PATCH 4/4] chore: improve typing of get_capability --- pygls/capabilities.py | 19 +- pygls/lsp/_capabilities.py | 877 +++++++++++++++++++++++++++++++++++++ pyproject.toml | 2 +- scripts/generate_code.py | 181 +++++++- 4 files changed, 1060 insertions(+), 19 deletions(-) create mode 100644 pygls/lsp/_capabilities.py diff --git a/pygls/capabilities.py b/pygls/capabilities.py index c8b4e820..cf797c1e 100644 --- a/pygls/capabilities.py +++ b/pygls/capabilities.py @@ -15,11 +15,12 @@ # limitations under the License. # ############################################################################ import logging -from functools import reduce from typing import Any, Dict, List, Optional, Set, TypeVar, Union from lsprotocol import types +from pygls.lsp._capabilities import get_capability + logger = logging.getLogger(__name__) T = TypeVar("T") @@ -32,22 +33,6 @@ ) -def get_capability( - client_capabilities: types.ClientCapabilities, field: str, default: Any = None -) -> Any: - """Check if ClientCapabilities has some nested value without raising - AttributeError. - e.g. get_capability('text_document.synchronization.will_save') - """ - try: - value = reduce(getattr, field.split("."), client_capabilities) - except AttributeError: - return default - - # If we reach the desired leaf value but it's None, return the default. - return default if value is None else value - - class ServerCapabilitiesBuilder: """Create `ServerCapabilities` instance depending on builtin and user registered features. diff --git a/pygls/lsp/_capabilities.py b/pygls/lsp/_capabilities.py new file mode 100644 index 00000000..7ad418eb --- /dev/null +++ b/pygls/lsp/_capabilities.py @@ -0,0 +1,877 @@ +############################################################################ +# Copyright(c) Open Law Library. All rights reserved. # +# See ThirdPartyNotices.txt in the project root for additional notices. # +# # +# Licensed under the Apache License, Version 2.0 (the "License") # +# you may not use this file except in compliance with the License. # +# You may obtain a copy of the License at # +# # +# http: // www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +############################################################################ + +# GENERATED FROM scripts/generate_code.py -- DO NOT EDIT +# flake8: noqa +from __future__ import annotations + +from functools import reduce +import typing + +if typing.TYPE_CHECKING: + from lsprotocol import types + from typing import Any + from typing import Literal + from typing import Sequence + from typing import TypeVar + from typing import Union + + T = TypeVar('T') + +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace'], default: T | None = None) -> types.WorkspaceClientCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.apply_edit'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.workspace_edit'], default: T | None = None) -> types.WorkspaceEditClientCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.workspace_edit.document_changes'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.workspace_edit.resource_operations'], default: T | None = None) -> Sequence[types.ResourceOperationKind] | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.workspace_edit.failure_handling'], default: T | None = None) -> types.FailureHandlingKind | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.workspace_edit.normalizes_line_endings'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.workspace_edit.change_annotation_support'], default: T | None = None) -> types.ChangeAnnotationsSupportOptions | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.workspace_edit.change_annotation_support.groups_on_label'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.workspace_edit.metadata_support'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.workspace_edit.snippet_edit_support'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.did_change_configuration'], default: T | None = None) -> types.DidChangeConfigurationClientCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.did_change_configuration.dynamic_registration'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.did_change_watched_files'], default: T | None = None) -> types.DidChangeWatchedFilesClientCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.did_change_watched_files.dynamic_registration'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.did_change_watched_files.relative_pattern_support'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.symbol'], default: T | None = None) -> types.WorkspaceSymbolClientCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.symbol.dynamic_registration'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.symbol.symbol_kind'], default: T | None = None) -> types.ClientSymbolKindOptions | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.symbol.symbol_kind.value_set'], default: T | None = None) -> Sequence[types.SymbolKind] | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.symbol.tag_support'], default: T | None = None) -> types.ClientSymbolTagOptions | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.symbol.tag_support.value_set'], default: T | None = None) -> types.SymbolTag | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.symbol.resolve_support'], default: T | None = None) -> types.ClientSymbolResolveOptions | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.symbol.resolve_support.properties'], default: T | None = None) -> None | str | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.execute_command'], default: T | None = None) -> types.ExecuteCommandClientCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.execute_command.dynamic_registration'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.workspace_folders'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.configuration'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.semantic_tokens'], default: T | None = None) -> types.SemanticTokensWorkspaceClientCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.semantic_tokens.refresh_support'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.code_lens'], default: T | None = None) -> types.CodeLensWorkspaceClientCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.code_lens.refresh_support'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.file_operations'], default: T | None = None) -> types.FileOperationClientCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.file_operations.dynamic_registration'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.file_operations.did_create'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.file_operations.will_create'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.file_operations.did_rename'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.file_operations.will_rename'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.file_operations.did_delete'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.file_operations.will_delete'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.inline_value'], default: T | None = None) -> types.InlineValueWorkspaceClientCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.inline_value.refresh_support'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.inlay_hint'], default: T | None = None) -> types.InlayHintWorkspaceClientCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.inlay_hint.refresh_support'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.diagnostics'], default: T | None = None) -> types.DiagnosticWorkspaceClientCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.diagnostics.refresh_support'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.folding_range'], default: T | None = None) -> types.FoldingRangeWorkspaceClientCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.folding_range.refresh_support'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.text_document_content'], default: T | None = None) -> types.TextDocumentContentClientCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.text_document_content.dynamic_registration'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document'], default: T | None = None) -> types.TextDocumentClientCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.synchronization'], default: T | None = None) -> types.TextDocumentSyncClientCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.synchronization.dynamic_registration'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.synchronization.will_save'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.synchronization.will_save_wait_until'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.synchronization.did_save'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.filters'], default: T | None = None) -> types.TextDocumentFilterClientCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.filters.relative_pattern_support'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion'], default: T | None = None) -> types.CompletionClientCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.dynamic_registration'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_item'], default: T | None = None) -> types.ClientCompletionItemOptions | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_item.snippet_support'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_item.commit_characters_support'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_item.documentation_format'], default: T | None = None) -> Sequence[types.MarkupKind] | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_item.deprecated_support'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_item.preselect_support'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_item.tag_support'], default: T | None = None) -> types.CompletionItemTagOptions | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_item.tag_support.value_set'], default: T | None = None) -> types.CompletionItemTag | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_item.insert_replace_support'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_item.resolve_support'], default: T | None = None) -> types.ClientCompletionItemResolveOptions | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_item.resolve_support.properties'], default: T | None = None) -> None | str | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_item.insert_text_mode_support'], default: T | None = None) -> types.ClientCompletionItemInsertTextModeOptions | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_item.insert_text_mode_support.value_set'], default: T | None = None) -> types.InsertTextMode | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_item.label_details_support'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_item_kind'], default: T | None = None) -> types.ClientCompletionItemOptionsKind | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_item_kind.value_set'], default: T | None = None) -> Sequence[Union[types.CompletionItemKind, int]] | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.insert_text_mode'], default: T | None = None) -> types.InsertTextMode | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.context_support'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_list'], default: T | None = None) -> types.CompletionListCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_list.item_defaults'], default: T | None = None) -> Sequence[str] | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_list.apply_kind_support'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.hover'], default: T | None = None) -> types.HoverClientCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.hover.dynamic_registration'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.hover.content_format'], default: T | None = None) -> Sequence[types.MarkupKind] | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.signature_help'], default: T | None = None) -> types.SignatureHelpClientCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.signature_help.dynamic_registration'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.signature_help.signature_information'], default: T | None = None) -> types.ClientSignatureInformationOptions | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.signature_help.signature_information.documentation_format'], default: T | None = None) -> Sequence[types.MarkupKind] | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.signature_help.signature_information.parameter_information'], default: T | None = None) -> types.ClientSignatureParameterInformationOptions | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.signature_help.signature_information.parameter_information.label_offset_support'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.signature_help.signature_information.active_parameter_support'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.signature_help.signature_information.no_active_parameter_support'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.signature_help.context_support'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.declaration'], default: T | None = None) -> types.DeclarationClientCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.declaration.dynamic_registration'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.declaration.link_support'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.definition'], default: T | None = None) -> types.DefinitionClientCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.definition.dynamic_registration'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.definition.link_support'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.type_definition'], default: T | None = None) -> types.TypeDefinitionClientCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.type_definition.dynamic_registration'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.type_definition.link_support'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.implementation'], default: T | None = None) -> types.ImplementationClientCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.implementation.dynamic_registration'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.implementation.link_support'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.references'], default: T | None = None) -> types.ReferenceClientCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.references.dynamic_registration'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.document_highlight'], default: T | None = None) -> types.DocumentHighlightClientCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.document_highlight.dynamic_registration'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.document_symbol'], default: T | None = None) -> types.DocumentSymbolClientCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.document_symbol.dynamic_registration'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.document_symbol.symbol_kind'], default: T | None = None) -> types.ClientSymbolKindOptions | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.document_symbol.symbol_kind.value_set'], default: T | None = None) -> Sequence[types.SymbolKind] | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.document_symbol.hierarchical_document_symbol_support'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.document_symbol.tag_support'], default: T | None = None) -> types.ClientSymbolTagOptions | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.document_symbol.tag_support.value_set'], default: T | None = None) -> types.SymbolTag | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.document_symbol.label_support'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.code_action'], default: T | None = None) -> types.CodeActionClientCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.code_action.dynamic_registration'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.code_action.code_action_literal_support'], default: T | None = None) -> types.ClientCodeActionLiteralOptions | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.code_action.code_action_literal_support.code_action_kind'], default: T | None = None) -> types.ClientCodeActionKindOptions | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.code_action.code_action_literal_support.code_action_kind.value_set'], default: T | None = None) -> Union[types.CodeActionKind, str] | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.code_action.is_preferred_support'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.code_action.disabled_support'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.code_action.data_support'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.code_action.resolve_support'], default: T | None = None) -> types.ClientCodeActionResolveOptions | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.code_action.resolve_support.properties'], default: T | None = None) -> None | str | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.code_action.honors_change_annotations'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.code_action.documentation_support'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.code_action.tag_support'], default: T | None = None) -> types.CodeActionTagOptions | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.code_action.tag_support.value_set'], default: T | None = None) -> types.CodeActionTag | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.code_lens'], default: T | None = None) -> types.CodeLensClientCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.code_lens.dynamic_registration'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.code_lens.resolve_support'], default: T | None = None) -> types.ClientCodeLensResolveOptions | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.code_lens.resolve_support.properties'], default: T | None = None) -> None | str | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.document_link'], default: T | None = None) -> types.DocumentLinkClientCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.document_link.dynamic_registration'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.document_link.tooltip_support'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.color_provider'], default: T | None = None) -> types.DocumentColorClientCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.color_provider.dynamic_registration'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.formatting'], default: T | None = None) -> types.DocumentFormattingClientCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.formatting.dynamic_registration'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.range_formatting'], default: T | None = None) -> types.DocumentRangeFormattingClientCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.range_formatting.dynamic_registration'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.range_formatting.ranges_support'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.on_type_formatting'], default: T | None = None) -> types.DocumentOnTypeFormattingClientCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.on_type_formatting.dynamic_registration'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.rename'], default: T | None = None) -> types.RenameClientCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.rename.dynamic_registration'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.rename.prepare_support'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.rename.prepare_support_default_behavior'], default: T | None = None) -> types.PrepareSupportDefaultBehavior | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.rename.honors_change_annotations'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.folding_range'], default: T | None = None) -> types.FoldingRangeClientCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.folding_range.dynamic_registration'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.folding_range.range_limit'], default: T | None = None) -> None | int | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.folding_range.line_folding_only'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.folding_range.folding_range_kind'], default: T | None = None) -> types.ClientFoldingRangeKindOptions | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.folding_range.folding_range_kind.value_set'], default: T | None = None) -> Sequence[Union[types.FoldingRangeKind, str]] | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.folding_range.folding_range'], default: T | None = None) -> types.ClientFoldingRangeOptions | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.folding_range.folding_range.collapsed_text'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.selection_range'], default: T | None = None) -> types.SelectionRangeClientCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.selection_range.dynamic_registration'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.publish_diagnostics'], default: T | None = None) -> types.PublishDiagnosticsClientCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.publish_diagnostics.version_support'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.publish_diagnostics.related_information'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.publish_diagnostics.tag_support'], default: T | None = None) -> types.ClientDiagnosticsTagOptions | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.publish_diagnostics.tag_support.value_set'], default: T | None = None) -> types.DiagnosticTag | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.publish_diagnostics.code_description_support'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.publish_diagnostics.data_support'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.call_hierarchy'], default: T | None = None) -> types.CallHierarchyClientCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.call_hierarchy.dynamic_registration'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.semantic_tokens'], default: T | None = None) -> types.SemanticTokensClientCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.semantic_tokens.requests'], default: T | None = None) -> types.ClientSemanticTokensRequestOptions | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.semantic_tokens.requests.range'], default: T | None = None) -> bool | None | Any | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.semantic_tokens.requests.full'], default: T | None = None) -> types.ClientSemanticTokensRequestFullDelta | bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.semantic_tokens.requests.full.delta'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.semantic_tokens.token_types'], default: T | None = None) -> None | str | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.semantic_tokens.token_modifiers'], default: T | None = None) -> None | str | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.semantic_tokens.formats'], default: T | None = None) -> types.TokenFormat | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.semantic_tokens.dynamic_registration'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.semantic_tokens.overlapping_token_support'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.semantic_tokens.multiline_token_support'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.semantic_tokens.server_cancel_support'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.semantic_tokens.augments_syntax_tokens'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.linked_editing_range'], default: T | None = None) -> types.LinkedEditingRangeClientCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.linked_editing_range.dynamic_registration'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.moniker'], default: T | None = None) -> types.MonikerClientCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.moniker.dynamic_registration'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.type_hierarchy'], default: T | None = None) -> types.TypeHierarchyClientCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.type_hierarchy.dynamic_registration'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.inline_value'], default: T | None = None) -> types.InlineValueClientCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.inline_value.dynamic_registration'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.inlay_hint'], default: T | None = None) -> types.InlayHintClientCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.inlay_hint.dynamic_registration'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.inlay_hint.resolve_support'], default: T | None = None) -> types.ClientInlayHintResolveOptions | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.inlay_hint.resolve_support.properties'], default: T | None = None) -> None | str | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.diagnostic'], default: T | None = None) -> types.DiagnosticClientCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.diagnostic.dynamic_registration'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.diagnostic.related_document_support'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.diagnostic.related_information'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.diagnostic.tag_support'], default: T | None = None) -> types.ClientDiagnosticsTagOptions | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.diagnostic.tag_support.value_set'], default: T | None = None) -> types.DiagnosticTag | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.diagnostic.code_description_support'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.diagnostic.data_support'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.inline_completion'], default: T | None = None) -> types.InlineCompletionClientCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.inline_completion.dynamic_registration'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['notebook_document'], default: T | None = None) -> types.NotebookDocumentClientCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['notebook_document.synchronization'], default: T | None = None) -> types.NotebookDocumentSyncClientCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['notebook_document.synchronization.dynamic_registration'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['notebook_document.synchronization.execution_summary_support'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['window'], default: T | None = None) -> types.WindowClientCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['window.work_done_progress'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['window.show_message'], default: T | None = None) -> types.ShowMessageRequestClientCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['window.show_message.message_action_item'], default: T | None = None) -> types.ClientShowMessageActionItemOptions | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['window.show_message.message_action_item.additional_properties_support'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['window.show_document'], default: T | None = None) -> types.ShowDocumentClientCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['window.show_document.support'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['general'], default: T | None = None) -> types.GeneralClientCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['general.stale_request_support'], default: T | None = None) -> types.StaleRequestSupportOptions | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['general.stale_request_support.cancel'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['general.stale_request_support.retry_on_content_modified'], default: T | None = None) -> None | str | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['general.regular_expressions'], default: T | None = None) -> types.RegularExpressionsClientCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['general.regular_expressions.engine'], default: T | None = None) -> None | str | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['general.regular_expressions.version'], default: T | None = None) -> None | str | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['general.markdown'], default: T | None = None) -> types.MarkdownClientCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['general.markdown.parser'], default: T | None = None) -> None | str | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['general.markdown.version'], default: T | None = None) -> None | str | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['general.markdown.allowed_tags'], default: T | None = None) -> Sequence[str] | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['general.position_encodings'], default: T | None = None) -> Sequence[Union[types.PositionEncodingKind, str]] | None | T: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['experimental'], default: T | None = None) -> None | Any | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['position_encoding'], default: T | None = None) -> types.PositionEncodingKind | None | str | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['text_document_sync'], default: T | None = None) -> types.TextDocumentSyncOptions | types.TextDocumentSyncKind | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['text_document_sync.open_close'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['text_document_sync.change'], default: T | None = None) -> types.TextDocumentSyncKind | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['text_document_sync.will_save'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['text_document_sync.will_save_wait_until'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['text_document_sync.save'], default: T | None = None) -> types.SaveOptions | bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['text_document_sync.save.include_text'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['notebook_document_sync'], default: T | None = None) -> types.NotebookDocumentSyncRegistrationOptions | types.NotebookDocumentSyncOptions | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['notebook_document_sync.notebook_selector'], default: T | None = None) -> Union[types.NotebookDocumentFilterWithNotebook, types.NotebookDocumentFilterWithCells] | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['notebook_document_sync.save'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['notebook_document_sync.id'], default: T | None = None) -> None | str | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['completion_provider'], default: T | None = None) -> types.CompletionOptions | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['completion_provider.trigger_characters'], default: T | None = None) -> Sequence[str] | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['completion_provider.all_commit_characters'], default: T | None = None) -> Sequence[str] | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['completion_provider.resolve_provider'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['completion_provider.completion_item'], default: T | None = None) -> types.ServerCompletionItemOptions | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['completion_provider.completion_item.label_details_support'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['completion_provider.work_done_progress'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['hover_provider'], default: T | None = None) -> types.HoverOptions | bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['hover_provider.work_done_progress'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['signature_help_provider'], default: T | None = None) -> types.SignatureHelpOptions | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['signature_help_provider.trigger_characters'], default: T | None = None) -> Sequence[str] | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['signature_help_provider.retrigger_characters'], default: T | None = None) -> Sequence[str] | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['signature_help_provider.work_done_progress'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['declaration_provider'], default: T | None = None) -> types.DeclarationRegistrationOptions | types.DeclarationOptions | None | bool | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['declaration_provider.work_done_progress'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['declaration_provider.document_selector'], default: T | None = None) -> Sequence[Union[types.TextDocumentFilterLanguage, types.TextDocumentFilterScheme, types.TextDocumentFilterPattern, types.NotebookCellTextDocumentFilter]] | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['declaration_provider.id'], default: T | None = None) -> None | str | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['definition_provider'], default: T | None = None) -> types.DefinitionOptions | bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['definition_provider.work_done_progress'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['type_definition_provider'], default: T | None = None) -> types.TypeDefinitionRegistrationOptions | types.TypeDefinitionOptions | None | bool | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['type_definition_provider.work_done_progress'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['type_definition_provider.document_selector'], default: T | None = None) -> Sequence[Union[types.TextDocumentFilterLanguage, types.TextDocumentFilterScheme, types.TextDocumentFilterPattern, types.NotebookCellTextDocumentFilter]] | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['type_definition_provider.id'], default: T | None = None) -> None | str | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['implementation_provider'], default: T | None = None) -> types.ImplementationRegistrationOptions | types.ImplementationOptions | None | bool | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['implementation_provider.work_done_progress'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['implementation_provider.document_selector'], default: T | None = None) -> Sequence[Union[types.TextDocumentFilterLanguage, types.TextDocumentFilterScheme, types.TextDocumentFilterPattern, types.NotebookCellTextDocumentFilter]] | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['implementation_provider.id'], default: T | None = None) -> None | str | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['references_provider'], default: T | None = None) -> types.ReferenceOptions | bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['references_provider.work_done_progress'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['document_highlight_provider'], default: T | None = None) -> types.DocumentHighlightOptions | bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['document_highlight_provider.work_done_progress'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['document_symbol_provider'], default: T | None = None) -> types.DocumentSymbolOptions | bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['document_symbol_provider.label'], default: T | None = None) -> None | str | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['document_symbol_provider.work_done_progress'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['code_action_provider'], default: T | None = None) -> types.CodeActionOptions | bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['code_action_provider.code_action_kinds'], default: T | None = None) -> Sequence[Union[types.CodeActionKind, str]] | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['code_action_provider.documentation'], default: T | None = None) -> Sequence[types.CodeActionKindDocumentation] | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['code_action_provider.resolve_provider'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['code_action_provider.work_done_progress'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['code_lens_provider'], default: T | None = None) -> types.CodeLensOptions | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['code_lens_provider.resolve_provider'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['code_lens_provider.work_done_progress'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['document_link_provider'], default: T | None = None) -> types.DocumentLinkOptions | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['document_link_provider.resolve_provider'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['document_link_provider.work_done_progress'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['color_provider'], default: T | None = None) -> types.DocumentColorRegistrationOptions | types.DocumentColorOptions | None | bool | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['color_provider.work_done_progress'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['color_provider.document_selector'], default: T | None = None) -> Sequence[Union[types.TextDocumentFilterLanguage, types.TextDocumentFilterScheme, types.TextDocumentFilterPattern, types.NotebookCellTextDocumentFilter]] | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['color_provider.id'], default: T | None = None) -> None | str | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace_symbol_provider'], default: T | None = None) -> types.WorkspaceSymbolOptions | bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace_symbol_provider.resolve_provider'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace_symbol_provider.work_done_progress'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['document_formatting_provider'], default: T | None = None) -> types.DocumentFormattingOptions | bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['document_formatting_provider.work_done_progress'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['document_range_formatting_provider'], default: T | None = None) -> types.DocumentRangeFormattingOptions | bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['document_range_formatting_provider.ranges_support'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['document_range_formatting_provider.work_done_progress'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['document_on_type_formatting_provider'], default: T | None = None) -> types.DocumentOnTypeFormattingOptions | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['document_on_type_formatting_provider.first_trigger_character'], default: T | None = None) -> None | str | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['document_on_type_formatting_provider.more_trigger_character'], default: T | None = None) -> Sequence[str] | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['rename_provider'], default: T | None = None) -> types.RenameOptions | bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['rename_provider.prepare_provider'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['rename_provider.work_done_progress'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['folding_range_provider'], default: T | None = None) -> types.FoldingRangeRegistrationOptions | types.FoldingRangeOptions | None | bool | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['folding_range_provider.work_done_progress'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['folding_range_provider.document_selector'], default: T | None = None) -> Sequence[Union[types.TextDocumentFilterLanguage, types.TextDocumentFilterScheme, types.TextDocumentFilterPattern, types.NotebookCellTextDocumentFilter]] | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['folding_range_provider.id'], default: T | None = None) -> None | str | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['selection_range_provider'], default: T | None = None) -> types.SelectionRangeRegistrationOptions | types.SelectionRangeOptions | None | bool | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['selection_range_provider.work_done_progress'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['selection_range_provider.document_selector'], default: T | None = None) -> Sequence[Union[types.TextDocumentFilterLanguage, types.TextDocumentFilterScheme, types.TextDocumentFilterPattern, types.NotebookCellTextDocumentFilter]] | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['selection_range_provider.id'], default: T | None = None) -> None | str | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['execute_command_provider'], default: T | None = None) -> types.ExecuteCommandOptions | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['execute_command_provider.commands'], default: T | None = None) -> None | str | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['execute_command_provider.work_done_progress'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['call_hierarchy_provider'], default: T | None = None) -> types.CallHierarchyRegistrationOptions | types.CallHierarchyOptions | None | bool | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['call_hierarchy_provider.work_done_progress'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['call_hierarchy_provider.document_selector'], default: T | None = None) -> Sequence[Union[types.TextDocumentFilterLanguage, types.TextDocumentFilterScheme, types.TextDocumentFilterPattern, types.NotebookCellTextDocumentFilter]] | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['call_hierarchy_provider.id'], default: T | None = None) -> None | str | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['linked_editing_range_provider'], default: T | None = None) -> types.LinkedEditingRangeRegistrationOptions | types.LinkedEditingRangeOptions | None | bool | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['linked_editing_range_provider.work_done_progress'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['linked_editing_range_provider.document_selector'], default: T | None = None) -> Sequence[Union[types.TextDocumentFilterLanguage, types.TextDocumentFilterScheme, types.TextDocumentFilterPattern, types.NotebookCellTextDocumentFilter]] | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['linked_editing_range_provider.id'], default: T | None = None) -> None | str | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['semantic_tokens_provider'], default: T | None = None) -> types.SemanticTokensRegistrationOptions | types.SemanticTokensOptions | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['semantic_tokens_provider.legend'], default: T | None = None) -> types.SemanticTokensLegend | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['semantic_tokens_provider.legend.token_types'], default: T | None = None) -> None | str | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['semantic_tokens_provider.legend.token_modifiers'], default: T | None = None) -> None | str | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['semantic_tokens_provider.range'], default: T | None = None) -> bool | None | Any | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['semantic_tokens_provider.full'], default: T | None = None) -> types.SemanticTokensFullDelta | bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['semantic_tokens_provider.full.delta'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['semantic_tokens_provider.work_done_progress'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['semantic_tokens_provider.document_selector'], default: T | None = None) -> Sequence[Union[types.TextDocumentFilterLanguage, types.TextDocumentFilterScheme, types.TextDocumentFilterPattern, types.NotebookCellTextDocumentFilter]] | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['semantic_tokens_provider.id'], default: T | None = None) -> None | str | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['moniker_provider'], default: T | None = None) -> types.MonikerRegistrationOptions | types.MonikerOptions | None | bool | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['moniker_provider.work_done_progress'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['moniker_provider.document_selector'], default: T | None = None) -> Sequence[Union[types.TextDocumentFilterLanguage, types.TextDocumentFilterScheme, types.TextDocumentFilterPattern, types.NotebookCellTextDocumentFilter]] | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['type_hierarchy_provider'], default: T | None = None) -> types.TypeHierarchyRegistrationOptions | types.TypeHierarchyOptions | None | bool | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['type_hierarchy_provider.work_done_progress'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['type_hierarchy_provider.document_selector'], default: T | None = None) -> Sequence[Union[types.TextDocumentFilterLanguage, types.TextDocumentFilterScheme, types.TextDocumentFilterPattern, types.NotebookCellTextDocumentFilter]] | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['type_hierarchy_provider.id'], default: T | None = None) -> None | str | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['inline_value_provider'], default: T | None = None) -> types.InlineValueRegistrationOptions | types.InlineValueOptions | None | bool | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['inline_value_provider.work_done_progress'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['inline_value_provider.document_selector'], default: T | None = None) -> Sequence[Union[types.TextDocumentFilterLanguage, types.TextDocumentFilterScheme, types.TextDocumentFilterPattern, types.NotebookCellTextDocumentFilter]] | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['inline_value_provider.id'], default: T | None = None) -> None | str | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['inlay_hint_provider'], default: T | None = None) -> types.InlayHintRegistrationOptions | types.InlayHintOptions | None | bool | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['inlay_hint_provider.resolve_provider'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['inlay_hint_provider.work_done_progress'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['inlay_hint_provider.document_selector'], default: T | None = None) -> Sequence[Union[types.TextDocumentFilterLanguage, types.TextDocumentFilterScheme, types.TextDocumentFilterPattern, types.NotebookCellTextDocumentFilter]] | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['inlay_hint_provider.id'], default: T | None = None) -> None | str | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['diagnostic_provider'], default: T | None = None) -> types.DiagnosticRegistrationOptions | types.DiagnosticOptions | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['diagnostic_provider.inter_file_dependencies'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['diagnostic_provider.workspace_diagnostics'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['diagnostic_provider.identifier'], default: T | None = None) -> None | str | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['diagnostic_provider.work_done_progress'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['diagnostic_provider.document_selector'], default: T | None = None) -> Sequence[Union[types.TextDocumentFilterLanguage, types.TextDocumentFilterScheme, types.TextDocumentFilterPattern, types.NotebookCellTextDocumentFilter]] | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['diagnostic_provider.id'], default: T | None = None) -> None | str | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['inline_completion_provider'], default: T | None = None) -> types.InlineCompletionOptions | bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['inline_completion_provider.work_done_progress'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace'], default: T | None = None) -> types.WorkspaceOptions | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.workspace_folders'], default: T | None = None) -> types.WorkspaceFoldersServerCapabilities | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.workspace_folders.supported'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.workspace_folders.change_notifications'], default: T | None = None) -> bool | None | str | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations'], default: T | None = None) -> types.FileOperationOptions | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.did_create'], default: T | None = None) -> types.FileOperationRegistrationOptions | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.did_create.filters'], default: T | None = None) -> types.FileOperationFilter | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.did_create.filters.pattern'], default: T | None = None) -> types.FileOperationPattern | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.did_create.filters.pattern.glob'], default: T | None = None) -> None | str | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.did_create.filters.pattern.matches'], default: T | None = None) -> types.FileOperationPatternKind | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.did_create.filters.pattern.options'], default: T | None = None) -> types.FileOperationPatternOptions | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.did_create.filters.pattern.options.ignore_case'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.did_create.filters.scheme'], default: T | None = None) -> None | str | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.will_create'], default: T | None = None) -> types.FileOperationRegistrationOptions | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.will_create.filters'], default: T | None = None) -> types.FileOperationFilter | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.will_create.filters.pattern'], default: T | None = None) -> types.FileOperationPattern | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.will_create.filters.pattern.glob'], default: T | None = None) -> None | str | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.will_create.filters.pattern.matches'], default: T | None = None) -> types.FileOperationPatternKind | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.will_create.filters.pattern.options'], default: T | None = None) -> types.FileOperationPatternOptions | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.will_create.filters.pattern.options.ignore_case'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.will_create.filters.scheme'], default: T | None = None) -> None | str | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.did_rename'], default: T | None = None) -> types.FileOperationRegistrationOptions | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.did_rename.filters'], default: T | None = None) -> types.FileOperationFilter | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.did_rename.filters.pattern'], default: T | None = None) -> types.FileOperationPattern | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.did_rename.filters.pattern.glob'], default: T | None = None) -> None | str | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.did_rename.filters.pattern.matches'], default: T | None = None) -> types.FileOperationPatternKind | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.did_rename.filters.pattern.options'], default: T | None = None) -> types.FileOperationPatternOptions | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.did_rename.filters.pattern.options.ignore_case'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.did_rename.filters.scheme'], default: T | None = None) -> None | str | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.will_rename'], default: T | None = None) -> types.FileOperationRegistrationOptions | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.will_rename.filters'], default: T | None = None) -> types.FileOperationFilter | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.will_rename.filters.pattern'], default: T | None = None) -> types.FileOperationPattern | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.will_rename.filters.pattern.glob'], default: T | None = None) -> None | str | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.will_rename.filters.pattern.matches'], default: T | None = None) -> types.FileOperationPatternKind | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.will_rename.filters.pattern.options'], default: T | None = None) -> types.FileOperationPatternOptions | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.will_rename.filters.pattern.options.ignore_case'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.will_rename.filters.scheme'], default: T | None = None) -> None | str | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.did_delete'], default: T | None = None) -> types.FileOperationRegistrationOptions | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.did_delete.filters'], default: T | None = None) -> types.FileOperationFilter | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.did_delete.filters.pattern'], default: T | None = None) -> types.FileOperationPattern | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.did_delete.filters.pattern.glob'], default: T | None = None) -> None | str | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.did_delete.filters.pattern.matches'], default: T | None = None) -> types.FileOperationPatternKind | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.did_delete.filters.pattern.options'], default: T | None = None) -> types.FileOperationPatternOptions | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.did_delete.filters.pattern.options.ignore_case'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.did_delete.filters.scheme'], default: T | None = None) -> None | str | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.will_delete'], default: T | None = None) -> types.FileOperationRegistrationOptions | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.will_delete.filters'], default: T | None = None) -> types.FileOperationFilter | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.will_delete.filters.pattern'], default: T | None = None) -> types.FileOperationPattern | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.will_delete.filters.pattern.glob'], default: T | None = None) -> None | str | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.will_delete.filters.pattern.matches'], default: T | None = None) -> types.FileOperationPatternKind | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.will_delete.filters.pattern.options'], default: T | None = None) -> types.FileOperationPatternOptions | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.will_delete.filters.pattern.options.ignore_case'], default: T | None = None) -> bool | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.will_delete.filters.scheme'], default: T | None = None) -> None | str | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.text_document_content'], default: T | None = None) -> types.TextDocumentContentRegistrationOptions | types.TextDocumentContentOptions | None | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.text_document_content.schemes'], default: T | None = None) -> None | str | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.text_document_content.id'], default: T | None = None) -> None | str | T: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['experimental'], default: T | None = None) -> None | Any | T: ... +@typing.overload +def get_capability(capabilities: Any, field: str, default: Any | None = None) -> Any | None: ... +def get_capability(capabilities, field, default = None): + """Return the value of some nested capability with a fallback value to use in the + case where it does not exist.""" + try: + value = reduce(getattr, field.split("."), capabilities) + except AttributeError: + return default + + return value if value is not None else default diff --git a/pyproject.toml b/pyproject.toml index c9ce7d88..61c327b5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -91,7 +91,7 @@ line-length = 120 [tool.black] line-length = 88 -extend-exclude = "pygls/lsp/_base_.*.py" +extend-exclude = "pygls/lsp/_base_.*.py|pygls/lsp/_capabilities.py" [tool.coverage.run] parallel = true diff --git a/scripts/generate_code.py b/scripts/generate_code.py index 42c03a3e..0abda2d9 100644 --- a/scripts/generate_code.py +++ b/scripts/generate_code.py @@ -6,12 +6,16 @@ import pathlib import re import textwrap +import typing +from typing import Any from typing import Optional from typing import Set from typing import Tuple from typing import Type from lsprotocol._hooks import _resolve_forward_references +from lsprotocol.types import ClientCapabilities +from lsprotocol.types import ServerCapabilities from lsprotocol.types import METHOD_TO_TYPES from lsprotocol.types import message_direction @@ -133,7 +137,15 @@ def write_server_notification( def get_response_type(response: Type, imports: Set[Tuple[str, str]]) -> str: # Find the response type. result_field = [f for f in response.__attrs_attrs__ if f.name == "result"][0] - result = re.sub(r"", r"\1", str(result_field.type)) + return rewrite_type(str(result_field.type), imports) + + +def rewrite_type(type_name: str, imports: set[tuple[str, str]]) -> str: + result = re.sub(r"", r"\1", type_name) + + # For some reason enum reprs are not namespaced... + result = re.sub(r"", r"types.\1", result) + result = re.sub(r"ForwardRef\('([\w.]+)'\)", r"lsprotocol.types.\1", result) result = result.replace("NoneType", "None") @@ -370,6 +382,169 @@ def generate_server() -> str: return "\n".join(code) +def write_overload(fn: str, args: list[tuple[str, str]], result: str) -> str: + """Write a typing overload for the given function""" + + arguments = ", ".join([f"{pname}: {ptype}" for pname, ptype in args]) + + lines = [ + "@typing.overload", + f"def {fn}({arguments}) -> {result}: ...", + ] + + return "\n".join(lines) + + +def write_capability_overloads_for( + base_type: str, + obj: type[Any], + overloads: list[str], + imports: set[tuple[str, str]], + processed_capabilities: set[str], + prefix: str = "", +): + """Write the ``get_capability`` overloads for the given type + + This function will iterate over all of the fields of ``obj`` and + append a corresponding overload to ``overloads``. It will then + recurse on each of the fields of ``obj`` so that we eventually emit + an overload for each nested field under the original ``base_type``. + + Parameters + ---------- + base_type + The type of the ``capabilities`` argument to ``get_capabilities`` + + obj + The type we are currently generating overloads for + + overloads + The list of overloads written so far + + imports + The set of import statements to add to the generated module + + processed_capabilities + The set of capabilities we have processed so far, used to prevent + generating duplicated overloads. + + prefix + The common prefix to assign to all fields of ``obj`` + e.g. ``text_document.completion`` + """ + + if not hasattr(obj, "__attrs_attrs__"): + return + + base_args = [("capabilities", base_type)] + + for field in obj.__attrs_attrs__: + if prefix: + field_name = f"{prefix}.{field.name}" + else: + field_name = field.name + + result_types = [] + result_type_names = {"T", "None"} + + if "typing." in str(field.type): + inner_types = typing.get_args(field.type) + for field_type in inner_types: + result_types.append(field_type) + field_type_name = rewrite_type(str(field_type), imports) + result_type_names.add(field_type_name) + else: + field_type = field.type + result_types.append(field_type) + result_type_names.add(rewrite_type(str(field_type), imports)) + + args = [ + *base_args, + ("field", f"Literal['{field_name}']"), + ("default", "T | None = None"), + ] + + if field_name not in processed_capabilities: + processed_capabilities.add(field_name) + overloads.append( + write_overload( + "get_capability", + args, + # sort values so that we get a consistent result + " | ".join(sorted(result_type_names, key=len, reverse=True)), + ) + ) + + for nested_type in result_types: + write_capability_overloads_for( + base_type, + nested_type, + overloads, + imports, + processed_capabilities, + prefix=field_name, + ) + + +def generate_capabilities() -> str: + imports = { + "typing", + ("functools", "reduce"), + } + + typing_imports = { + ("typing", "Literal"), + ("typing", "TypeVar"), + ("lsprotocol", "types"), + } + + overloads = [] + write_capability_overloads_for( + "types.ClientCapabilities", + ClientCapabilities, + overloads, + typing_imports, + processed_capabilities=set(), + prefix="", + ) + write_capability_overloads_for( + "types.ServerCapabilities", + ServerCapabilities, + overloads, + typing_imports, + processed_capabilities=set(), + prefix="", + ) + + code = [ + LICENSE_HEADER, + "# GENERATED FROM scripts/generate_code.py -- DO NOT EDIT", + "# flake8: noqa", + "from __future__ import annotations", + "", + write_imports(imports), + "", + write_typing_imports(typing_imports), + "", + " T = TypeVar('T')", + "", + *overloads, + "@typing.overload", + "def get_capability(capabilities: Any, field: str, default: Any | None = None) -> Any | None: ...", + "def get_capability(capabilities, field, default = None):", + ' """Return the value of some nested capability with a fallback value to use in the', + ' case where it does not exist."""' "", + " try:", + ' value = reduce(getattr, field.split("."), capabilities)', + " except AttributeError:", + " return default", + "", + " return value if value is not None else default", + "", + ] + return "\n".join(code) + + def main(): args = cli.parse_args() @@ -384,6 +559,10 @@ def main(): output = args.output / "_base_server.py" output.write_text(server) + capabilities = generate_capabilities() + output = args.output / "_capabilities.py" + output.write_text(capabilities) + if __name__ == "__main__": main()