From a0a0d38fe5aee909a12d64bdc1c076b81fb6397c Mon Sep 17 00:00:00 2001 From: Christoph Brandau Date: Thu, 3 Sep 2026 07:49:10 +0200 Subject: [PATCH 1/2] docs(readme): remove development/debugging section and license note This change removes outdated development and debugging guidance from the README and streamlines the licensing note. It also deletes the embedded debugger license file and relies on the main LICENSE file for terms. - Remove outdated debugging guidance from README - Delete embedded debugger license file and rely on LICENSE --- README.md | 27 +-------------------------- debugger/NX_TCL_DEBUGGER_LICENSE.txt | 21 --------------------- 2 files changed, 1 insertion(+), 47 deletions(-) delete mode 100644 debugger/NX_TCL_DEBUGGER_LICENSE.txt diff --git a/README.md b/README.md index aa79514..2af36a5 100644 --- a/README.md +++ b/README.md @@ -98,35 +98,10 @@ Simply open any supported file type and enjoy: - Signature help while entering procedure arguments - Remote NX Tcl debugging with breakpoints and full stepping -## Development and debugging - -Install the root and client dependencies before the first debug session: - -```powershell -npm install -npm install --prefix client -npm run test:debugger -``` - -Use one of the checked-in VS Code launch configurations: - -- **Run Extension** debugs the TypeScript extension host. -- **Debug Extension and Python** debugs both the TypeScript extension and the - Python language server. This is the recommended configuration for LSP work. -- **Python Attach** attaches manually to an already running Python process. - -The launch configuration creates a fresh non-minified bundle with embedded -source maps and opens `test/test.tcl` so the extension activates immediately. -For combined debugging, the Python adapter listens on `127.0.0.1:5678`; the -language server waits for that adapter before initialization. The NX -Postprocessor Support output channel reports `Python debug mode: enabled` and -shows `_debug_server.py` in the server command when the debug path is active. - ## Contributing This extension is actively maintained. For issues or feature requests, please visit our [repository](https://git.cbsk-tech.de/Christoph/nx_post_support.git). ## License -AGPL-3.0 License - see LICENSE file for details. The embedded NX Tcl Remote Debugger adapter -retains its MIT notice in `debugger/NX_TCL_DEBUGGER_LICENSE.txt`. +AGPL-3.0 License - see LICENSE file for details. diff --git a/debugger/NX_TCL_DEBUGGER_LICENSE.txt b/debugger/NX_TCL_DEBUGGER_LICENSE.txt deleted file mode 100644 index 8365b5b..0000000 --- a/debugger/NX_TCL_DEBUGGER_LICENSE.txt +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2026 NX Tcl Remote Debugger contributors - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -- 2.54.0 From 53ebc5d05595b5f07439f354a0f449ffb2201de5 Mon Sep 17 00:00:00 2001 From: Christoph Brandau Date: Thu, 3 Sep 2026 08:39:12 +0200 Subject: [PATCH 2/2] chore(lsprotocol): migrate to 2025.0.0 and cleanup artifacts The changes align the project with the 2025.0.0 lsprotocol release, removing the old backport and updating type hints in the protocol hooks to use Sequence where appropriate. The dist-info and packaging metadata for older lsprotocol versions are replaced with the new 2025.0.0 artifacts. - Remove exceptiongroup backport used on Python <3.11 - Use Sequence instead of List in LS protocol hooks - Replace old dist-info with 2025.0.0 metadata --- README.md | 30 +- server/libs/exceptiongroup.py | 19 - .../libs/lsprotocol-2023.0.1.dist-info/RECORD | 12 - .../INSTALLER | 0 .../METADATA | 14 +- .../libs/lsprotocol-2025.0.0.dist-info/RECORD | 12 + .../REQUESTED | 0 .../WHEEL | 0 .../licenses}/LICENSE | 0 server/libs/lsprotocol/_hooks.py | 260 +- server/libs/lsprotocol/types.py | 5513 ++++++++++------- server/libs/packaging-26.2.dist-info/RECORD | 29 - .../INSTALLER | 0 .../METADATA | 6 +- server/libs/packaging-26.3.dist-info/RECORD | 31 + .../REQUESTED | 0 .../WHEEL | 0 .../licenses/LICENSE | 0 .../licenses/LICENSE.APACHE | 0 .../licenses/LICENSE.BSD | 0 server/libs/packaging/__init__.py | 2 +- server/libs/packaging/_elffile.py | 10 +- server/libs/packaging/_manylinux.py | 52 +- server/libs/packaging/_musllinux.py | 7 +- server/libs/packaging/_parser.py | 41 +- server/libs/packaging/_ranges.py | 836 +++ server/libs/packaging/_tokenizer.py | 13 +- server/libs/packaging/dependency_groups.py | 43 +- server/libs/packaging/direct_url.py | 40 +- server/libs/packaging/licenses/__init__.py | 24 +- server/libs/packaging/markers.py | 128 +- server/libs/packaging/metadata.py | 196 +- server/libs/packaging/pylock.py | 54 +- server/libs/packaging/ranges.py | 2067 ++++++ server/libs/packaging/requirements.py | 111 +- server/libs/packaging/specifiers.py | 1174 +--- server/libs/packaging/tags.py | 241 +- server/libs/packaging/utils.py | 94 +- server/libs/packaging/version.py | 43 +- server/libs/pygls-1.3.1.dist-info/RECORD | 26 - .../INSTALLER | 0 .../METADATA | 50 +- server/libs/pygls-2.1.1.dist-info/RECORD | 31 + .../REQUESTED | 0 .../WHEEL | 2 +- .../licenses}/LICENSE.txt | 0 server/libs/pygls/__init__.py | 2 + server/libs/pygls/capabilities.py | 122 +- server/libs/pygls/cli.py | 45 + server/libs/pygls/client.py | 171 +- server/libs/pygls/exceptions.py | 37 +- server/libs/pygls/feature_manager.py | 23 +- server/libs/pygls/io_.py | 296 + server/libs/pygls/lsp/_base_client.py | 2018 ++++++ server/libs/pygls/lsp/_base_server.py | 463 ++ server/libs/pygls/lsp/_capabilities.py | 1238 ++++ server/libs/pygls/lsp/client.py | 1963 +----- server/libs/pygls/lsp/server.py | 126 + server/libs/pygls/protocol/__init__.py | 6 +- server/libs/pygls/protocol/json_rpc.py | 617 +- server/libs/pygls/protocol/language_server.py | 603 +- server/libs/pygls/protocol/lsp_meta.py | 51 - server/libs/pygls/server.py | 645 +- server/libs/pygls/uris.py | 10 +- server/libs/pygls/workspace/__init__.py | 92 +- server/libs/pygls/workspace/position_codec.py | 211 +- server/libs/pygls/workspace/text_document.py | 115 +- server/libs/pygls/workspace/workspace.py | 100 +- .../INSTALLER | 0 .../METADATA | 2 +- .../RECORD | 30 +- .../REQUESTED | 0 .../WHEEL | 2 +- .../entry_points.txt | 0 .../licenses/LICENSE | 0 .../top_level.txt | 0 server/libs/tclint/_version.py | 26 +- server/libs/tclint/commands/builtin.py | 11 +- server/libs/tclint/commands/checks.py | 111 +- server/libs/tclint/commands/schema.py | 18 +- server/libs/tclint/format.py | 81 +- server/libs/tclint/symbol_table.py | 3 + server/libs/tclint/syntax_tree.py | 2 +- .../typing_extensions-4.15.0.dist-info/RECORD | 7 - .../INSTALLER | 0 .../METADATA | 3 +- .../typing_extensions-4.16.0.dist-info/RECORD | 7 + .../REQUESTED | 0 .../WHEEL | 2 +- .../licenses/LICENSE | 0 server/libs/typing_extensions.py | 353 +- server/noxfile.py | 42 +- server/pyproject.toml | 15 +- server/src/lsp_server.py | 30 +- server/src/lsp_tclserver.py | 5 +- server/tests/python_tests/conftest.py | 26 + .../python_tests/test_document_symbols.py | 5 +- server/uv-overrides.txt | 3 + server/uv.lock | 501 +- test/file.cdl | 3 +- test/test.tcl | 9 +- 101 files changed, 13838 insertions(+), 7624 deletions(-) delete mode 100644 server/libs/exceptiongroup.py delete mode 100644 server/libs/lsprotocol-2023.0.1.dist-info/RECORD rename server/libs/{lsprotocol-2023.0.1.dist-info => lsprotocol-2025.0.0.dist-info}/INSTALLER (100%) rename server/libs/{lsprotocol-2023.0.1.dist-info => lsprotocol-2025.0.0.dist-info}/METADATA (86%) create mode 100644 server/libs/lsprotocol-2025.0.0.dist-info/RECORD rename server/libs/{lsprotocol-2023.0.1.dist-info => lsprotocol-2025.0.0.dist-info}/REQUESTED (100%) rename server/libs/{packaging-26.2.dist-info => lsprotocol-2025.0.0.dist-info}/WHEEL (100%) rename server/libs/{lsprotocol-2023.0.1.dist-info => lsprotocol-2025.0.0.dist-info/licenses}/LICENSE (100%) delete mode 100644 server/libs/packaging-26.2.dist-info/RECORD rename server/libs/{packaging-26.2.dist-info => packaging-26.3.dist-info}/INSTALLER (100%) rename server/libs/{packaging-26.2.dist-info => packaging-26.3.dist-info}/METADATA (97%) create mode 100644 server/libs/packaging-26.3.dist-info/RECORD rename server/libs/{packaging-26.2.dist-info => packaging-26.3.dist-info}/REQUESTED (100%) rename server/libs/{typing_extensions-4.15.0.dist-info => packaging-26.3.dist-info}/WHEEL (100%) rename server/libs/{packaging-26.2.dist-info => packaging-26.3.dist-info}/licenses/LICENSE (100%) rename server/libs/{packaging-26.2.dist-info => packaging-26.3.dist-info}/licenses/LICENSE.APACHE (100%) rename server/libs/{packaging-26.2.dist-info => packaging-26.3.dist-info}/licenses/LICENSE.BSD (100%) create mode 100644 server/libs/packaging/_ranges.py create mode 100644 server/libs/packaging/ranges.py delete mode 100644 server/libs/pygls-1.3.1.dist-info/RECORD rename server/libs/{pygls-1.3.1.dist-info => pygls-2.1.1.dist-info}/INSTALLER (100%) rename server/libs/{pygls-1.3.1.dist-info => pygls-2.1.1.dist-info}/METADATA (76%) create mode 100644 server/libs/pygls-2.1.1.dist-info/RECORD rename server/libs/{pygls-1.3.1.dist-info => pygls-2.1.1.dist-info}/REQUESTED (100%) rename server/libs/{pygls-1.3.1.dist-info => pygls-2.1.1.dist-info}/WHEEL (67%) rename server/libs/{pygls-1.3.1.dist-info => pygls-2.1.1.dist-info/licenses}/LICENSE.txt (100%) create mode 100644 server/libs/pygls/cli.py create mode 100644 server/libs/pygls/io_.py create mode 100644 server/libs/pygls/lsp/_base_client.py create mode 100644 server/libs/pygls/lsp/_base_server.py create mode 100644 server/libs/pygls/lsp/_capabilities.py create mode 100644 server/libs/pygls/lsp/server.py delete mode 100644 server/libs/pygls/protocol/lsp_meta.py rename server/libs/{tclint-0.8.0.dist-info => tclint-0.9.0.dist-info}/INSTALLER (100%) rename server/libs/{tclint-0.8.0.dist-info => tclint-0.9.0.dist-info}/METADATA (99%) rename server/libs/{tclint-0.8.0.dist-info => tclint-0.9.0.dist-info}/RECORD (59%) rename server/libs/{tclint-0.8.0.dist-info => tclint-0.9.0.dist-info}/REQUESTED (100%) rename server/libs/{tclint-0.8.0.dist-info => tclint-0.9.0.dist-info}/WHEEL (65%) rename server/libs/{tclint-0.8.0.dist-info => tclint-0.9.0.dist-info}/entry_points.txt (100%) rename server/libs/{tclint-0.8.0.dist-info => tclint-0.9.0.dist-info}/licenses/LICENSE (100%) rename server/libs/{tclint-0.8.0.dist-info => tclint-0.9.0.dist-info}/top_level.txt (100%) delete mode 100644 server/libs/typing_extensions-4.15.0.dist-info/RECORD rename server/libs/{typing_extensions-4.15.0.dist-info => typing_extensions-4.16.0.dist-info}/INSTALLER (100%) rename server/libs/{typing_extensions-4.15.0.dist-info => typing_extensions-4.16.0.dist-info}/METADATA (97%) create mode 100644 server/libs/typing_extensions-4.16.0.dist-info/RECORD rename server/libs/{typing_extensions-4.15.0.dist-info => typing_extensions-4.16.0.dist-info}/REQUESTED (100%) rename server/libs/{lsprotocol-2023.0.1.dist-info => typing_extensions-4.16.0.dist-info}/WHEEL (71%) rename server/libs/{typing_extensions-4.15.0.dist-info => typing_extensions-4.16.0.dist-info}/licenses/LICENSE (100%) create mode 100644 server/tests/python_tests/conftest.py create mode 100644 server/uv-overrides.txt diff --git a/README.md b/README.md index 2af36a5..e231c83 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ A comprehensive VS Code extension providing language support and remote debuggin ## Installation 1. Install from the VS Code Marketplace -2. Install Python 3.11 or higher +2. Install Python 3.12 or higher 3. Open any `.cdl`, `.tcl`, or `.def` file 4. The extension will automatically activate and provide language support @@ -52,20 +52,20 @@ Create `.vscode/launch.json` through **Run and Debug: create a launch.json file* ```json { - "version": "0.2.0", - "configurations": [ - { - "type": "nx-tcl", - "request": "attach", - "name": "Attach to NX Post Tcl", - "host": "127.0.0.1", - "port": 4711, - "connectTimeout": 120000, - "stopOnEntry": false, - "breakOnError": true, - "localRoot": "${workspaceFolder}" - } - ] + "version": "0.2.0", + "configurations": [ + { + "type": "nx-tcl", + "request": "attach", + "name": "Attach to NX Post Tcl", + "host": "127.0.0.1", + "port": 4711, + "connectTimeout": 120000, + "stopOnEntry": false, + "breakOnError": true, + "localRoot": "${workspaceFolder}" + } + ] } ``` diff --git a/server/libs/exceptiongroup.py b/server/libs/exceptiongroup.py deleted file mode 100644 index ea74544..0000000 --- a/server/libs/exceptiongroup.py +++ /dev/null @@ -1,19 +0,0 @@ -from __future__ import annotations - - -class ExceptionGroup(Exception): - """Minimal backport used by bundled libs on Python < 3.11.""" - - def __new__(cls, message, exceptions): - obj = super().__new__(cls, message) - obj.message = message - obj.exceptions = tuple(exceptions) - return obj - - def __init__(self, message, exceptions): - super().__init__(message) - self.message = message - self.exceptions = tuple(exceptions) - - def derive(self, exceptions): - return self.__class__(self.message, exceptions) diff --git a/server/libs/lsprotocol-2023.0.1.dist-info/RECORD b/server/libs/lsprotocol-2023.0.1.dist-info/RECORD deleted file mode 100644 index c64c566..0000000 --- a/server/libs/lsprotocol-2023.0.1.dist-info/RECORD +++ /dev/null @@ -1,12 +0,0 @@ -lsprotocol-2023.0.1.dist-info/INSTALLER,sha256=5hhM4Q4mYTT9z6QB6PGpUAW81PGNFrYrdXMj4oM_6ak,2 -lsprotocol-2023.0.1.dist-info/LICENSE,sha256=ws_MuBL-SCEBqPBFl9_FqZkaaydIJmxHrJG2parhU4M,1141 -lsprotocol-2023.0.1.dist-info/METADATA,sha256=oh7M_V0nCX-lx8MCik5z0_J8Wyd7ApJtdl30wWs4Tb8,2237 -lsprotocol-2023.0.1.dist-info/RECORD,, -lsprotocol-2023.0.1.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -lsprotocol-2023.0.1.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81 -lsprotocol/__init__.py,sha256=zoT6Do2JtGHGb7pOeKpahg4ocXIsSpyowjhOrhUhx8g,94 -lsprotocol/_hooks.py,sha256=PCTq4Ve_dDd02DMcWQ8afu9gj_oyX0B4nDOomPghqYs,41570 -lsprotocol/converters.py,sha256=404tQOVoZL31R9CBrDe6Gx9Nok5cRph3glKlnSx00fo,433 -lsprotocol/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -lsprotocol/types.py,sha256=nZYiI5ZvHEBkRYjtPd8tpqe0n2NpmdaCZ2RLwHxoMLs,454735 -lsprotocol/validators.py,sha256=5UMUmWhk52_Ps66_KFydjNkMfLNUsPH3wmV0Buv645s,1420 diff --git a/server/libs/lsprotocol-2023.0.1.dist-info/INSTALLER b/server/libs/lsprotocol-2025.0.0.dist-info/INSTALLER similarity index 100% rename from server/libs/lsprotocol-2023.0.1.dist-info/INSTALLER rename to server/libs/lsprotocol-2025.0.0.dist-info/INSTALLER diff --git a/server/libs/lsprotocol-2023.0.1.dist-info/METADATA b/server/libs/lsprotocol-2025.0.0.dist-info/METADATA similarity index 86% rename from server/libs/lsprotocol-2023.0.1.dist-info/METADATA rename to server/libs/lsprotocol-2025.0.0.dist-info/METADATA index eb5f7d6..cd39bcb 100644 --- a/server/libs/lsprotocol-2023.0.1.dist-info/METADATA +++ b/server/libs/lsprotocol-2025.0.0.dist-info/METADATA @@ -1,15 +1,14 @@ -Metadata-Version: 2.1 +Metadata-Version: 2.4 Name: lsprotocol -Version: 2023.0.1 -Summary: Python implementation of the Language Server Protocol. +Version: 2025.0.0 +Summary: Python types for Language Server Protocol. Author-email: Microsoft Corporation Maintainer-email: Brett Cannon , Karthik Nadig -Requires-Python: >=3.7 +Requires-Python: >=3.8 Description-Content-Type: text/markdown -Classifier: Development Status :: 5 - Production/Stable +Classifier: Development Status :: 4 - Beta Classifier: License :: OSI Approved :: MIT License Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 Classifier: Programming Language :: Python :: 3.10 @@ -17,6 +16,7 @@ Classifier: Programming Language :: Python :: 3.11 Classifier: Programming Language :: Python :: 3.12 Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: Implementation :: PyPy +License-File: LICENSE Requires-Dist: attrs>=21.3.0 Requires-Dist: cattrs!=23.2.1 Project-URL: Issues, https://github.com/microsoft/lsprotocol/issues @@ -24,7 +24,7 @@ Project-URL: Source, https://github.com/microsoft/lsprotocol # Language Server Protocol Types implementation for Python -`lsprotocol` is a python implementation of object types used in the Language Server Protocol (LSP). This repository contains the code generator and the generated types for LSP. +`lsprotocol` is a Python implementation of object types used in the Language Server Protocol (LSP). This repository contains the code generator and the generated types for LSP. ## Overview diff --git a/server/libs/lsprotocol-2025.0.0.dist-info/RECORD b/server/libs/lsprotocol-2025.0.0.dist-info/RECORD new file mode 100644 index 0000000..eeb0ff1 --- /dev/null +++ b/server/libs/lsprotocol-2025.0.0.dist-info/RECORD @@ -0,0 +1,12 @@ +lsprotocol-2025.0.0.dist-info/INSTALLER,sha256=5hhM4Q4mYTT9z6QB6PGpUAW81PGNFrYrdXMj4oM_6ak,2 +lsprotocol-2025.0.0.dist-info/METADATA,sha256=u3Lb5ZzZi4gH18WQWVPurP9kBvqHDY5U-Utafh8O7Bc,2184 +lsprotocol-2025.0.0.dist-info/RECORD,, +lsprotocol-2025.0.0.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +lsprotocol-2025.0.0.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82 +lsprotocol-2025.0.0.dist-info/licenses/LICENSE,sha256=ws_MuBL-SCEBqPBFl9_FqZkaaydIJmxHrJG2parhU4M,1141 +lsprotocol/__init__.py,sha256=zoT6Do2JtGHGb7pOeKpahg4ocXIsSpyowjhOrhUhx8g,94 +lsprotocol/_hooks.py,sha256=dp-HEi_z7CqTz0cgzCYfT_s32Sr1hcrLlu3ff42lBXI,44624 +lsprotocol/converters.py,sha256=404tQOVoZL31R9CBrDe6Gx9Nok5cRph3glKlnSx00fo,433 +lsprotocol/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +lsprotocol/types.py,sha256=LJbn0uKWsPpveLZG2Wswr-1Gn2Tfimue3zV71xVA5SE,476733 +lsprotocol/validators.py,sha256=5UMUmWhk52_Ps66_KFydjNkMfLNUsPH3wmV0Buv645s,1420 diff --git a/server/libs/lsprotocol-2023.0.1.dist-info/REQUESTED b/server/libs/lsprotocol-2025.0.0.dist-info/REQUESTED similarity index 100% rename from server/libs/lsprotocol-2023.0.1.dist-info/REQUESTED rename to server/libs/lsprotocol-2025.0.0.dist-info/REQUESTED diff --git a/server/libs/packaging-26.2.dist-info/WHEEL b/server/libs/lsprotocol-2025.0.0.dist-info/WHEEL similarity index 100% rename from server/libs/packaging-26.2.dist-info/WHEEL rename to server/libs/lsprotocol-2025.0.0.dist-info/WHEEL diff --git a/server/libs/lsprotocol-2023.0.1.dist-info/LICENSE b/server/libs/lsprotocol-2025.0.0.dist-info/licenses/LICENSE similarity index 100% rename from server/libs/lsprotocol-2023.0.1.dist-info/LICENSE rename to server/libs/lsprotocol-2025.0.0.dist-info/licenses/LICENSE diff --git a/server/libs/lsprotocol/_hooks.py b/server/libs/lsprotocol/_hooks.py index 3f51ce2..be22ad7 100644 --- a/server/libs/lsprotocol/_hooks.py +++ b/server/libs/lsprotocol/_hooks.py @@ -1,7 +1,7 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. import sys -from typing import Any, List, Optional, Tuple, Union +from typing import Any, Optional, Sequence, Tuple, Union import attrs import cattrs @@ -27,7 +27,7 @@ def _resolve_forward_references() -> None: items = list(filter(_filter, lsp_types.ALL_TYPES_MAP.items())) for _, value in items: if isinstance(value, type): - attrs.resolve_types(value, lsp_types.ALL_TYPES_MAP, {}) # type: ignore + attrs.resolve_types(value, lsp_types.ALL_TYPES_MAP, {}) _resolved_forward_references = True @@ -390,7 +390,7 @@ def _register_capabilities_hooks(converter: cattrs.Converter) -> cattrs.Converte def _inlay_hint_label_part_hook( object_: Any, _: type - ) -> Union[str, List[lsp_types.InlayHintLabelPart]]: + ) -> Union[str, Sequence[lsp_types.InlayHintLabelPart]]: if isinstance(object_, str): return object_ @@ -431,7 +431,7 @@ def _register_capabilities_hooks(converter: cattrs.Converter) -> cattrs.Converte def _completion_list_hook( object_: Any, _: type - ) -> Optional[Union[lsp_types.CompletionList, List[lsp_types.CompletionItem]]]: + ) -> Optional[Union[lsp_types.CompletionList, Sequence[lsp_types.CompletionItem]]]: if object_ is None: return None if isinstance(object_, list): @@ -446,8 +446,8 @@ def _register_capabilities_hooks(converter: cattrs.Converter) -> cattrs.Converte ) -> Optional[ Union[ lsp_types.Location, - List[lsp_types.Location], - List[lsp_types.LocationLink], + Sequence[lsp_types.Location], + Sequence[lsp_types.LocationLink], ] ]: if object_ is None: @@ -470,7 +470,7 @@ def _register_capabilities_hooks(converter: cattrs.Converter) -> cattrs.Converte def _symbol_hook( object_: Any, _: type ) -> Optional[ - Union[List[lsp_types.DocumentSymbol], List[lsp_types.SymbolInformation]] + Union[Sequence[lsp_types.DocumentSymbol], Sequence[lsp_types.SymbolInformation]] ]: if object_ is None: return None @@ -496,8 +496,8 @@ def _register_capabilities_hooks(converter: cattrs.Converter) -> cattrs.Converte Union[ OptionalPrimitive, lsp_types.MarkupContent, - lsp_types.MarkedString_Type1, - List[Union[OptionalPrimitive, lsp_types.MarkedString_Type1]], + lsp_types.MarkedStringWithLanguage, + Sequence[Union[OptionalPrimitive, lsp_types.MarkedStringWithLanguage]], ] ]: if object_ is None: @@ -509,14 +509,14 @@ def _register_capabilities_hooks(converter: cattrs.Converter) -> cattrs.Converte ( item if isinstance(item, (bool, int, str, float)) - else converter.structure(item, lsp_types.MarkedString_Type1) + else converter.structure(item, lsp_types.MarkedStringWithLanguage) ) for item in object_ ] if "kind" in object_: return converter.structure(object_, lsp_types.MarkupContent) else: - return converter.structure(object_, lsp_types.MarkedString_Type1) + return converter.structure(object_, lsp_types.MarkedStringWithLanguage) def _document_edit_hook( object_: Any, _: type @@ -544,25 +544,25 @@ def _register_capabilities_hooks(converter: cattrs.Converter) -> cattrs.Converte def _semantic_tokens_hook( object_: Any, _: type - ) -> Union[OptionalPrimitive, lsp_types.SemanticTokensOptionsFullType1]: + ) -> Union[OptionalPrimitive, lsp_types.SemanticTokensFullDelta]: if object_ is None: return None if isinstance(object_, (bool, int, str, float)): return object_ - return converter.structure(object_, lsp_types.SemanticTokensOptionsFullType1) + return converter.structure(object_, lsp_types.SemanticTokensFullDelta) def _semantic_tokens_capabilities_hook( object_: Any, _: type ) -> Union[ OptionalPrimitive, - lsp_types.SemanticTokensClientCapabilitiesRequestsTypeFullType1, + lsp_types.ClientSemanticTokensRequestFullDelta, ]: if object_ is None: return None if isinstance(object_, (bool, int, str, float)): return object_ return converter.structure( - object_, lsp_types.SemanticTokensClientCapabilitiesRequestsTypeFullType1 + object_, lsp_types.ClientSemanticTokensRequestFullDelta ) def _code_action_kind_hook( @@ -622,29 +622,29 @@ def _register_capabilities_hooks(converter: cattrs.Converter) -> cattrs.Converte def _notebook_sync_option_selector_hook( object_: Any, _: type ) -> Union[ - lsp_types.NotebookDocumentSyncOptionsNotebookSelectorType1, - lsp_types.NotebookDocumentSyncOptionsNotebookSelectorType2, + lsp_types.NotebookDocumentFilterWithNotebook, + lsp_types.NotebookDocumentFilterWithCells, ]: if "notebook" in object_: return converter.structure( - object_, lsp_types.NotebookDocumentSyncOptionsNotebookSelectorType1 + object_, lsp_types.NotebookDocumentFilterWithNotebook ) else: return converter.structure( - object_, lsp_types.NotebookDocumentSyncOptionsNotebookSelectorType2 + object_, lsp_types.NotebookDocumentFilterWithCells ) def _semantic_token_registration_options_hook( object_: Any, _: type ) -> Optional[ - Union[OptionalPrimitive, lsp_types.SemanticTokensRegistrationOptionsFullType1] + Union[OptionalPrimitive, lsp_types.ClientSemanticTokensRequestFullDelta] ]: if object_ is None: return None if isinstance(object_, (bool, int, str, float)): return object_ return converter.structure( - object_, lsp_types.SemanticTokensRegistrationOptionsFullType1 + object_, lsp_types.ClientSemanticTokensRequestFullDelta ) def _inline_completion_provider_hook( @@ -659,7 +659,7 @@ def _register_capabilities_hooks(converter: cattrs.Converter) -> cattrs.Converte def _inline_completion_list_hook( object_: Any, _: type ) -> Optional[ - Union[lsp_types.InlineCompletionList, List[lsp_types.InlineCompletionItem]] + Union[lsp_types.InlineCompletionList, Sequence[lsp_types.InlineCompletionItem]] ]: if object_ is None: return None @@ -682,7 +682,9 @@ def _register_capabilities_hooks(converter: cattrs.Converter) -> cattrs.Converte def _symbol_list_hook( object_: Any, _: type ) -> Optional[ - Union[List[lsp_types.SymbolInformation], List[lsp_types.WorkspaceSymbol]] + Union[ + Sequence[lsp_types.SymbolInformation], Sequence[lsp_types.WorkspaceSymbol] + ] ]: if object_ is None: return None @@ -703,22 +705,71 @@ def _register_capabilities_hooks(converter: cattrs.Converter) -> cattrs.Converte converter.structure(item, lsp_types.SymbolInformation) for item in object_ ] - def _notebook_sync_registration_option_selector_hook( + def _language_kind_hook( object_: Any, _: type ) -> Union[ - lsp_types.NotebookDocumentSyncRegistrationOptionsNotebookSelectorType1, - lsp_types.NotebookDocumentSyncRegistrationOptionsNotebookSelectorType2, + lsp_types.LanguageKind, + OptionalPrimitive, ]: - if "notebook" in object_: + if object_ is None: + return None + if isinstance(object_, (bool, int, str, float)): + return object_ + return converter.structure(object_, lsp_types.LanguageKind) + + def _text_edit_hook( + object_: Any, _: type + ) -> Union[ + lsp_types.TextEdit, lsp_types.AnnotatedTextEdit, lsp_types.SnippetTextEdit + ]: + if "snippet" in object_: + return converter.structure(object_, lsp_types.SnippetTextEdit) + if "annotationId" in object_: + return converter.structure(object_, lsp_types.AnnotatedTextEdit) + return converter.structure(object_, lsp_types.TextEdit) + + def _completion_item_kind_hook( + object_: Any, _: type + ) -> Union[lsp_types.CompletionItemKind, OptionalPrimitive]: + if object_ is None: + return None + if isinstance(object_, (bool, int, str, float)): + return object_ + return converter.structure(object_, lsp_types.CompletionItemKind) + + def _relative_pattern_hook( + object_: Any, _: type + ) -> Union[OptionalPrimitive, lsp_types.RelativePattern]: + if object_ is None: + return None + if isinstance(object_, (bool, int, str, float)): + return object_ + return converter.structure(object_, lsp_types.RelativePattern) + + def _workspace_folder_hook( + object_: Any, _: type + ) -> Union[OptionalPrimitive, lsp_types.WorkspaceFolder]: + if object_ is None: + return None + if isinstance(object_, (bool, int, str, float)): + return object_ + return converter.structure(object_, lsp_types.WorkspaceFolder) + + def _text_document_content_hook( + object_: Any, _: type + ) -> Union[ + OptionalPrimitive, + lsp_types.TextDocumentContentRegistrationOptions, + lsp_types.TextDocumentContentOptions, + ]: + if object_ is None: + return None + if "id" in object_: return converter.structure( - object_, - lsp_types.NotebookDocumentSyncRegistrationOptionsNotebookSelectorType1, + object_, lsp_types.TextDocumentContentRegistrationOptions ) else: - return converter.structure( - object_, - lsp_types.NotebookDocumentSyncRegistrationOptionsNotebookSelectorType2, - ) + return converter.structure(object_, lsp_types.TextDocumentContentOptions) structure_hooks = [ ( @@ -892,7 +943,7 @@ def _register_capabilities_hooks(converter: cattrs.Converter) -> cattrs.Converte _inlay_hint_provider_hook, ), ( - Union[str, List[lsp_types.InlayHintLabelPart]], + Union[str, Sequence[lsp_types.InlayHintLabelPart]], _inlay_hint_label_part_hook, ), ( @@ -912,22 +963,27 @@ def _register_capabilities_hooks(converter: cattrs.Converter) -> cattrs.Converte _code_action_hook, ), ( - Optional[Union[List[lsp_types.CompletionItem], lsp_types.CompletionList]], + Optional[ + Union[Sequence[lsp_types.CompletionItem], lsp_types.CompletionList] + ], _completion_list_hook, ), ( Optional[ Union[ lsp_types.Location, - List[lsp_types.Location], - List[lsp_types.LocationLink], + Sequence[lsp_types.Location], + Sequence[lsp_types.LocationLink], ] ], _location_hook, ), ( Optional[ - Union[List[lsp_types.SymbolInformation], List[lsp_types.DocumentSymbol]] + Union[ + Sequence[lsp_types.SymbolInformation], + Sequence[lsp_types.DocumentSymbol], + ] ], _symbol_hook, ), @@ -935,8 +991,8 @@ def _register_capabilities_hooks(converter: cattrs.Converter) -> cattrs.Converte Union[ lsp_types.MarkupContent, str, - lsp_types.MarkedString_Type1, - List[Union[str, lsp_types.MarkedString_Type1]], + lsp_types.MarkedStringWithLanguage, + Sequence[Union[str, lsp_types.MarkedStringWithLanguage]], ], _markup_content_hook, ), @@ -950,14 +1006,14 @@ def _register_capabilities_hooks(converter: cattrs.Converter) -> cattrs.Converte _document_edit_hook, ), ( - Optional[Union[bool, lsp_types.SemanticTokensOptionsFullType1]], + Optional[Union[bool, lsp_types.SemanticTokensFullDelta]], _semantic_tokens_hook, ), ( Optional[ Union[ bool, - lsp_types.SemanticTokensClientCapabilitiesRequestsTypeFullType1, + lsp_types.ClientSemanticTokensRequestFullDelta, ] ], _semantic_tokens_capabilities_hook, @@ -1012,8 +1068,8 @@ def _register_capabilities_hooks(converter: cattrs.Converter) -> cattrs.Converte ), ( Union[ - lsp_types.NotebookDocumentSyncOptionsNotebookSelectorType1, - lsp_types.NotebookDocumentSyncOptionsNotebookSelectorType2, + lsp_types.NotebookDocumentFilterWithNotebook, + lsp_types.NotebookDocumentFilterWithCells, ], _notebook_sync_option_selector_hook, ), @@ -1027,7 +1083,7 @@ def _register_capabilities_hooks(converter: cattrs.Converter) -> cattrs.Converte _position_encoding_hook, ), ( - Optional[Union[bool, lsp_types.SemanticTokensRegistrationOptionsFullType1]], + Optional[Union[bool, lsp_types.ClientSemanticTokensRequestFullDelta]], _semantic_token_registration_options_hook, ), ( @@ -1037,7 +1093,8 @@ def _register_capabilities_hooks(converter: cattrs.Converter) -> cattrs.Converte ( Optional[ Union[ - lsp_types.InlineCompletionList, List[lsp_types.InlineCompletionItem] + lsp_types.InlineCompletionList, + Sequence[lsp_types.InlineCompletionItem], ] ], _inline_completion_list_hook, @@ -1049,17 +1106,63 @@ def _register_capabilities_hooks(converter: cattrs.Converter) -> cattrs.Converte ( Optional[ Union[ - List[lsp_types.SymbolInformation], List[lsp_types.WorkspaceSymbol] + Sequence[lsp_types.SymbolInformation], + Sequence[lsp_types.WorkspaceSymbol], ] ], _symbol_list_hook, ), + ( + Union[lsp_types.LanguageKind, str], + _language_kind_hook, + ), ( Union[ - lsp_types.NotebookDocumentSyncRegistrationOptionsNotebookSelectorType1, - lsp_types.NotebookDocumentSyncRegistrationOptionsNotebookSelectorType2, + lsp_types.TextEdit, + lsp_types.AnnotatedTextEdit, + lsp_types.SnippetTextEdit, ], - _notebook_sync_registration_option_selector_hook, + _text_edit_hook, + ), + ( + Optional[Union[lsp_types.CompletionItemKind, int]], + _completion_item_kind_hook, + ), + ( + Union[lsp_types.CompletionItemKind, int], + _completion_item_kind_hook, + ), + ( + Optional[Union[str, lsp_types.RelativePattern]], + _relative_pattern_hook, + ), + ( + Union[str, lsp_types.RelativePattern], + _relative_pattern_hook, + ), + ( + Optional[Union[lsp_types.WorkspaceFolder, str]], + _workspace_folder_hook, + ), + ( + Union[lsp_types.WorkspaceFolder, str], + _workspace_folder_hook, + ), + ( + Optional[ + Union[ + lsp_types.TextDocumentContentOptions, + lsp_types.TextDocumentContentRegistrationOptions, + ] + ], + _text_document_content_hook, + ), + ( + Union[ + lsp_types.TextDocumentContentOptions, + lsp_types.TextDocumentContentRegistrationOptions, + ], + _text_document_content_hook, ), ] for type_, hook in structure_hooks: @@ -1085,9 +1188,9 @@ def _register_required_structure_hooks( object_: Any, _: type ) -> Union[ str, - lsp_types.TextDocumentFilter_Type1, - lsp_types.TextDocumentFilter_Type2, - lsp_types.TextDocumentFilter_Type3, + lsp_types.TextDocumentFilterLanguage, + lsp_types.TextDocumentFilterScheme, + lsp_types.TextDocumentFilterPattern, lsp_types.NotebookCellTextDocumentFilter, ]: if isinstance(object_, str): @@ -1097,30 +1200,31 @@ def _register_required_structure_hooks( object_, lsp_types.NotebookCellTextDocumentFilter ) elif "language" in object_: - return converter.structure(object_, lsp_types.TextDocumentFilter_Type1) + return converter.structure(object_, lsp_types.TextDocumentFilterLanguage) elif "scheme" in object_: - return converter.structure(object_, lsp_types.TextDocumentFilter_Type2) + return converter.structure(object_, lsp_types.TextDocumentFilterScheme) else: - return converter.structure(object_, lsp_types.TextDocumentFilter_Type3) + return converter.structure(object_, lsp_types.TextDocumentFilterPattern) def _notebook_filter_hook( object_: Any, _: type ) -> Union[ str, - lsp_types.NotebookDocumentFilter_Type1, - lsp_types.NotebookDocumentFilter_Type2, - lsp_types.NotebookDocumentFilter_Type3, + lsp_types.NotebookDocumentFilterNotebookType, + lsp_types.NotebookDocumentFilterScheme, + lsp_types.NotebookDocumentFilterPattern, ]: if isinstance(object_, str): return str(object_) elif "notebookType" in object_: - return converter.structure(object_, lsp_types.NotebookDocumentFilter_Type1) + return converter.structure( + object_, lsp_types.NotebookDocumentFilterNotebookType + ) elif "scheme" in object_: - return converter.structure(object_, lsp_types.NotebookDocumentFilter_Type2) + return converter.structure(object_, lsp_types.NotebookDocumentFilterScheme) else: - return converter.structure(object_, lsp_types.NotebookDocumentFilter_Type3) + return converter.structure(object_, lsp_types.NotebookDocumentFilterPattern) - # TODO: Remove the ignore after this issue with attrs is addressed in either attrs or mypy NotebookSelectorItem = attrs.fields( lsp_types.NotebookCellTextDocumentFilter ).notebook.type @@ -1133,9 +1237,9 @@ def _register_required_structure_hooks( (Optional[Union[bool, Any]], lambda object_, _type: object_), ( Union[ - lsp_types.TextDocumentFilter_Type1, - lsp_types.TextDocumentFilter_Type2, - lsp_types.TextDocumentFilter_Type3, + lsp_types.TextDocumentFilterLanguage, + lsp_types.TextDocumentFilterScheme, + lsp_types.TextDocumentFilterPattern, lsp_types.NotebookCellTextDocumentFilter, ], _text_document_filter_hook, @@ -1144,20 +1248,26 @@ def _register_required_structure_hooks( ( Union[ str, - lsp_types.NotebookDocumentFilter_Type1, - lsp_types.NotebookDocumentFilter_Type2, - lsp_types.NotebookDocumentFilter_Type3, + lsp_types.NotebookDocumentFilterNotebookType, + lsp_types.NotebookDocumentFilterScheme, + lsp_types.NotebookDocumentFilterPattern, ], _notebook_filter_hook, ), (NotebookSelectorItem, _notebook_filter_hook), ( - Union[lsp_types.LSPObject, List["LSPAny"], str, int, float, bool, None], + Union[lsp_types.LSPObject, Sequence["LSPAny"], str, int, float, bool, None], _lsp_object_hook, ), ( Union[ - lsp_types.LSPObject, List[lsp_types.LSPAny], str, int, float, bool, None + lsp_types.LSPObject, + Sequence[lsp_types.LSPAny], + str, + int, + float, + bool, + None, ], _lsp_object_hook, ), @@ -1173,10 +1283,10 @@ def _register_required_structure_hooks( ( Union[ lsp_types.LSPObject, - List[ + Sequence[ Union[ lsp_types.LSPObject, - List["LSPAny"], + Sequence["LSPAny"], str, int, float, @@ -1220,7 +1330,7 @@ def _register_custom_property_hooks(converter: cattrs.Converter) -> cattrs.Conve ) for a in attrs.fields(cls) } - return cattrs.gen.make_dict_unstructure_fn(cls, converter, **attributes) + return cattrs.gen.make_dict_unstructure_fn(cls, converter, **attributes) # type: ignore def _with_custom_structure(cls: type) -> Any: attributes = { @@ -1230,7 +1340,7 @@ def _register_custom_property_hooks(converter: cattrs.Converter) -> cattrs.Conve ) for a in attrs.fields(cls) } - return cattrs.gen.make_dict_structure_fn(cls, converter, **attributes) + return cattrs.gen.make_dict_structure_fn(cls, converter, **attributes) # type: ignore converter.register_unstructure_hook_factory(attrs.has, _with_custom_unstructure) converter.register_structure_hook_factory(attrs.has, _with_custom_structure) diff --git a/server/libs/lsprotocol/types.py b/server/libs/lsprotocol/types.py index 98b2d4b..eb0e3ba 100644 --- a/server/libs/lsprotocol/types.py +++ b/server/libs/lsprotocol/types.py @@ -9,10 +9,8 @@ import enum import functools -from typing import Any, Dict, List, Optional, Tuple, Union - +from typing import Any, Dict, Mapping, Literal, Optional, Sequence, Tuple, Union import attrs - from . import validators __lsp_version__ = "3.17.0" @@ -54,6 +52,9 @@ class SemanticTokenTypes(str, enum.Enum): Decorator = "decorator" """@since 3.17.0""" # Since: 3.17.0 + Label = "label" + """@since 3.18.0""" + # Since: 3.18.0 @enum.unique @@ -132,7 +133,7 @@ class LSPErrorCodes(int, enum.Enum): If a client decides that a result is not of any use anymore the client should cancel the request.""" RequestCancelled = -32800 - """The client has canceled a request and a server as detected + """The client has canceled a request and a server has detected the cancel.""" @@ -254,8 +255,10 @@ class MessageType(int, enum.Enum): Debug = 5 """A debug message. - @since 3.18.0""" + @since 3.18.0 + @proposed""" # Since: 3.18.0 + # Proposed @enum.unique @@ -413,6 +416,20 @@ class CodeActionKind(str, enum.Enum): - Inline variable - Inline constant - ...""" + RefactorMove = "refactor.move" + """Base kind for refactoring move actions: `refactor.move` + + Example move actions: + + - Move a function to a new file + - Move a property between classes + - Move method to base class + - ... + + @since 3.18.0 + @proposed""" + # Since: 3.18.0 + # Proposed RefactorRewrite = "refactor.rewrite" """Base kind for refactoring rewrite actions: 'refactor.rewrite' @@ -438,10 +455,27 @@ class CodeActionKind(str, enum.Enum): @since 3.15.0""" # Since: 3.15.0 + Notebook = "notebook" + """Base kind for all code actions applying to the entire notebook's scope. CodeActionKinds using + this should always begin with `notebook.` + + @since 3.18.0""" + # Since: 3.18.0 @enum.unique -class TraceValues(str, enum.Enum): +class CodeActionTag(int, enum.Enum): + """Code action tags are extra annotations that tweak the behavior of a code action. + + @since 3.18.0 - proposed""" + + # Since: 3.18.0 - proposed + LlmGenerated = 1 + """Marks the code action as LLM-generated.""" + + +@enum.unique +class TraceValue(str, enum.Enum): Off = "off" """Turn tracing off.""" Messages = "messages" @@ -464,6 +498,86 @@ class MarkupKind(str, enum.Enum): """Markdown is supported as a content format""" +class LanguageKind(str, enum.Enum): + """Predefined Language kinds + @since 3.18.0""" + + # Since: 3.18.0 + Abap = "abap" + WindowsBat = "bat" + BibTeX = "bibtex" + Clojure = "clojure" + Coffeescript = "coffeescript" + C = "c" + Cpp = "cpp" + CSharp = "csharp" + Css = "css" + D = "d" + """@since 3.18.0 + @proposed""" + # Since: 3.18.0 + # Proposed + Delphi = "pascal" + """@since 3.18.0 + @proposed""" + # Since: 3.18.0 + # Proposed + Diff = "diff" + Dart = "dart" + Dockerfile = "dockerfile" + Elixir = "elixir" + Erlang = "erlang" + FSharp = "fsharp" + GitCommit = "git-commit" + GitRebase = "rebase" + Go = "go" + Groovy = "groovy" + Handlebars = "handlebars" + Haskell = "haskell" + Html = "html" + Ini = "ini" + Java = "java" + JavaScript = "javascript" + JavaScriptReact = "javascriptreact" + Json = "json" + LaTeX = "latex" + Less = "less" + Lua = "lua" + Makefile = "makefile" + Markdown = "markdown" + ObjectiveC = "objective-c" + ObjectiveCpp = "objective-cpp" + Pascal = "pascal" + """@since 3.18.0 + @proposed""" + # Since: 3.18.0 + # Proposed + Perl = "perl" + Perl6 = "perl6" + Php = "php" + Powershell = "powershell" + Pug = "jade" + Python = "python" + R = "r" + Razor = "razor" + Ruby = "ruby" + Rust = "rust" + Scss = "scss" + Sass = "sass" + Scala = "scala" + ShaderLab = "shaderlab" + ShellScript = "shellscript" + Sql = "sql" + Swift = "swift" + TypeScript = "typescript" + TypeScriptReact = "typescriptreact" + TeX = "tex" + VisualBasic = "vb" + Xml = "xml" + Xsl = "xsl" + Yaml = "yaml" + + @enum.unique class InlineCompletionTriggerKind(int, enum.Enum): """Describes how an {@link InlineCompletionItemProvider inline completion provider} was triggered. @@ -473,9 +587,9 @@ class InlineCompletionTriggerKind(int, enum.Enum): # Since: 3.18.0 # Proposed - Invoked = 0 + Invoked = 1 """Completion was triggered explicitly by a user gesture.""" - Automatic = 1 + Automatic = 2 """Completion was triggered automatically while editing.""" @@ -569,6 +683,24 @@ class CompletionTriggerKind(int, enum.Enum): """Completion was re-triggered as current completion list is incomplete""" +@enum.unique +class ApplyKind(int, enum.Enum): + """Defines how values from a set of defaults and an individual item will be + merged. + + @since 3.18.0""" + + # Since: 3.18.0 + Replace = 1 + """The value from the individual item (if provided and not `null`) will be + used instead of the default.""" + Merge = 2 + """The value from the item will be merged with the default. + + The specific rules for mergeing values are defined against each field + that supports merging.""" + + @enum.unique class SignatureHelpTriggerKind(int, enum.Enum): """How a signature help was triggered. @@ -674,7 +806,7 @@ class LSPObject: pass -Definition = Union["Location", List["Location"]] +Definition = Union["Location", Sequence["Location"]] """The definition of a symbol represented as one or many {@link Location locations}. For most programming languages there is only one location at which a symbol is defined. @@ -690,7 +822,7 @@ Provides additional metadata over normal {@link Location location} definitions, the defining symbol""" -LSPArray = List["LSPAny"] +LSPArray = Sequence["LSPAny"] """LSP arrays. @since 3.17.0""" # Since: 3.17.0 @@ -706,7 +838,7 @@ optional as well. # Since: 3.17.0 -Declaration = Union["Location", List["Location"]] +Declaration = Union["Location", Sequence["Location"]] """The declaration of a symbol representation as one or many {@link Location locations}.""" @@ -746,24 +878,12 @@ pull request. # Since: 3.17.0 -@attrs.define -class PrepareRenameResult_Type1: - range: "Range" = attrs.field() - - placeholder: str = attrs.field(validator=attrs.validators.instance_of(str)) - - -@attrs.define -class PrepareRenameResult_Type2: - default_behavior: bool = attrs.field(validator=attrs.validators.instance_of(bool)) - - PrepareRenameResult = Union[ - "Range", "PrepareRenameResult_Type1", "PrepareRenameResult_Type2" + "Range", "PrepareRenamePlaceholder", "PrepareRenameDefaultBehavior" ] -DocumentSelector = List["DocumentFilter"] +DocumentSelector = Sequence["DocumentFilter"] """A document selector is the combination of one or many document filters. @sample `let sel:DocumentSelector = [{ language: 'typescript' }, { language: 'json', pattern: '**/tsconfig.json' }]`; @@ -789,43 +909,14 @@ WorkspaceDocumentDiagnosticReport = Union[ # Since: 3.17.0 -@attrs.define -class TextDocumentContentChangeEvent_Type1: - range: "Range" = attrs.field() - """The range of the document that changed.""" - - text: str = attrs.field(validator=attrs.validators.instance_of(str)) - """The new text for the provided range.""" - - range_length: Optional[int] = attrs.field( - validator=attrs.validators.optional(validators.uinteger_validator), default=None - ) - """The optional length of the range that got replaced. - - @deprecated use range instead.""" - - -@attrs.define -class TextDocumentContentChangeEvent_Type2: - text: str = attrs.field(validator=attrs.validators.instance_of(str)) - """The new text of the whole document.""" - - TextDocumentContentChangeEvent = Union[ - "TextDocumentContentChangeEvent_Type1", "TextDocumentContentChangeEvent_Type2" + "TextDocumentContentChangePartial", "TextDocumentContentChangeWholeDocument" ] """An event describing a change to a text document. If only a text is provided it is considered to be the full content of the document.""" -@attrs.define -class MarkedString_Type1: - language: str = attrs.field(validator=attrs.validators.instance_of(str)) - - value: str = attrs.field(validator=attrs.validators.instance_of(str)) - - -MarkedString = Union[str, "MarkedString_Type1"] +MarkedString = Union[str, "MarkedStringWithLanguage"] """MarkedString can be used to render human readable text. It is either a markdown string or a code-block that provides a language and a code snippet. The language identifier is semantically equal to the optional language identifier in fenced code blocks in GitHub @@ -844,8 +935,8 @@ DocumentFilter = Union["TextDocumentFilter", "NotebookCellTextDocumentFilter"] """A document filter describes a top level text document or a notebook cell document. -@since 3.17.0 - proposed support for NotebookCellTextDocumentFilter.""" -# Since: 3.17.0 - proposed support for NotebookCellTextDocumentFilter. +@since 3.17.0 - support for NotebookCellTextDocumentFilter.""" +# Since: 3.17.0 - support for NotebookCellTextDocumentFilter. GlobPattern = Union["Pattern", "RelativePattern"] @@ -855,62 +946,10 @@ GlobPattern = Union["Pattern", "RelativePattern"] # Since: 3.17.0 -@attrs.define -class TextDocumentFilter_Type1: - language: str = attrs.field(validator=attrs.validators.instance_of(str)) - """A language id, like `typescript`.""" - - scheme: Optional[str] = attrs.field( - validator=attrs.validators.optional(attrs.validators.instance_of(str)), - default=None, - ) - """A Uri {@link Uri.scheme scheme}, like `file` or `untitled`.""" - - pattern: Optional[str] = attrs.field( - validator=attrs.validators.optional(attrs.validators.instance_of(str)), - default=None, - ) - """A glob pattern, like **/*.{ts,js}. See TextDocumentFilter for examples.""" - - -@attrs.define -class TextDocumentFilter_Type2: - scheme: str = attrs.field(validator=attrs.validators.instance_of(str)) - """A Uri {@link Uri.scheme scheme}, like `file` or `untitled`.""" - - language: Optional[str] = attrs.field( - validator=attrs.validators.optional(attrs.validators.instance_of(str)), - default=None, - ) - """A language id, like `typescript`.""" - - pattern: Optional[str] = attrs.field( - validator=attrs.validators.optional(attrs.validators.instance_of(str)), - default=None, - ) - """A glob pattern, like **/*.{ts,js}. See TextDocumentFilter for examples.""" - - -@attrs.define -class TextDocumentFilter_Type3: - pattern: str = attrs.field(validator=attrs.validators.instance_of(str)) - """A glob pattern, like **/*.{ts,js}. See TextDocumentFilter for examples.""" - - language: Optional[str] = attrs.field( - validator=attrs.validators.optional(attrs.validators.instance_of(str)), - default=None, - ) - """A language id, like `typescript`.""" - - scheme: Optional[str] = attrs.field( - validator=attrs.validators.optional(attrs.validators.instance_of(str)), - default=None, - ) - """A Uri {@link Uri.scheme scheme}, like `file` or `untitled`.""" - - TextDocumentFilter = Union[ - "TextDocumentFilter_Type1", "TextDocumentFilter_Type2", "TextDocumentFilter_Type3" + "TextDocumentFilterLanguage", + "TextDocumentFilterScheme", + "TextDocumentFilterPattern", ] """A document filter denotes a document by different properties like the {@link TextDocument.languageId language}, the {@link Uri.scheme scheme} of @@ -931,64 +970,10 @@ Glob patterns can have the following syntax: # Since: 3.17.0 -@attrs.define -class NotebookDocumentFilter_Type1: - notebook_type: str = attrs.field(validator=attrs.validators.instance_of(str)) - """The type of the enclosing notebook.""" - - scheme: Optional[str] = attrs.field( - validator=attrs.validators.optional(attrs.validators.instance_of(str)), - default=None, - ) - """A Uri {@link Uri.scheme scheme}, like `file` or `untitled`.""" - - pattern: Optional[str] = attrs.field( - validator=attrs.validators.optional(attrs.validators.instance_of(str)), - default=None, - ) - """A glob pattern.""" - - -@attrs.define -class NotebookDocumentFilter_Type2: - scheme: str = attrs.field(validator=attrs.validators.instance_of(str)) - """A Uri {@link Uri.scheme scheme}, like `file` or `untitled`.""" - - notebook_type: Optional[str] = attrs.field( - validator=attrs.validators.optional(attrs.validators.instance_of(str)), - default=None, - ) - """The type of the enclosing notebook.""" - - pattern: Optional[str] = attrs.field( - validator=attrs.validators.optional(attrs.validators.instance_of(str)), - default=None, - ) - """A glob pattern.""" - - -@attrs.define -class NotebookDocumentFilter_Type3: - pattern: str = attrs.field(validator=attrs.validators.instance_of(str)) - """A glob pattern.""" - - notebook_type: Optional[str] = attrs.field( - validator=attrs.validators.optional(attrs.validators.instance_of(str)), - default=None, - ) - """The type of the enclosing notebook.""" - - scheme: Optional[str] = attrs.field( - validator=attrs.validators.optional(attrs.validators.instance_of(str)), - default=None, - ) - """A Uri {@link Uri.scheme scheme}, like `file` or `untitled`.""" - - NotebookDocumentFilter = Union[ - "NotebookDocumentFilter_Type1", - "NotebookDocumentFilter_Type2", - "NotebookDocumentFilter_Type3", + "NotebookDocumentFilterNotebookType", + "NotebookDocumentFilterScheme", + "NotebookDocumentFilterPattern", ] """A notebook document filter denotes a notebook document by different properties. The properties will be match @@ -1011,6 +996,9 @@ Pattern = str # Since: 3.17.0 +RegularExpressionEngineKind = str + + @attrs.define class TextDocumentPositionParams: """A parameter literal used in requests to pass a text document and a position inside that @@ -1200,7 +1188,7 @@ class DidChangeWorkspaceFoldersParams: class ConfigurationParams: """The parameters of a configuration request.""" - items: List["ConfigurationItem"] = attrs.field() + items: Sequence["ConfigurationItem"] = attrs.field() @attrs.define @@ -1291,7 +1279,7 @@ class ColorPresentation: this presentation for the color. When `falsy` the {@link ColorPresentation.label label} is used.""" - additional_text_edits: Optional[List["TextEdit"]] = attrs.field(default=None) + additional_text_edits: Optional[Sequence["TextEdit"]] = attrs.field(default=None) """An optional array of additional {@link TextEdit text edits} that are applied when selecting this color presentation. Edits must not overlap with the main {@link ColorPresentation.textEdit edit} nor with themselves.""" @@ -1314,8 +1302,7 @@ class FoldingRangeParams: @attrs.define class FoldingRange: """Represents a folding range. To be valid, start and end line must be bigger than zero and smaller - than the number of lines in the document. Clients are free to ignore invalid ranges. - """ + than the number of lines in the document. Clients are free to ignore invalid ranges.""" start_line: int = attrs.field(validator=validators.uinteger_validator) """The zero-based start line of the range to fold. The folded area starts after the line's last character. @@ -1336,7 +1323,7 @@ class FoldingRange: """The zero-based character offset before the folded range ends. If not defined, defaults to the length of the end line.""" kind: Optional[Union[FoldingRangeKind, str]] = attrs.field(default=None) - """Describes the kind of the folding range such as `comment' or 'region'. The kind + """Describes the kind of the folding range such as 'comment' or 'region'. The kind is used to categorize folding ranges and used by commands like 'Fold all comments'. See {@link FoldingRangeKind} for an enumeration of standardized kinds.""" @@ -1433,7 +1420,7 @@ class SelectionRangeParams: text_document: "TextDocumentIdentifier" = attrs.field() """The text document.""" - positions: List["Position"] = attrs.field() + positions: Sequence["Position"] = attrs.field() """The positions inside the text document.""" work_done_token: Optional[ProgressToken] = attrs.field(default=None) @@ -1540,7 +1527,7 @@ class CallHierarchyItem: """The range that should be selected and revealed when this symbol is being picked, e.g. the name of a function. Must be contained by the {@link CallHierarchyItem.range `range`}.""" - tags: Optional[List[SymbolTag]] = attrs.field(default=None) + tags: Optional[Sequence[SymbolTag]] = attrs.field(default=None) """Tags for this item.""" detail: Optional[str] = attrs.field( @@ -1624,7 +1611,7 @@ class CallHierarchyIncomingCall: from_: CallHierarchyItem = attrs.field() """The item that makes the call.""" - from_ranges: List["Range"] = attrs.field() + from_ranges: Sequence["Range"] = attrs.field() """The ranges at which the calls appear. This is relative to the caller denoted by {@link CallHierarchyIncomingCall.from `this.from`}.""" @@ -1658,7 +1645,7 @@ class CallHierarchyOutgoingCall: to: CallHierarchyItem = attrs.field() """The item that is called.""" - from_ranges: List["Range"] = attrs.field() + from_ranges: Sequence["Range"] = attrs.field() """The range at which this item is called. This is the range relative to the caller, e.g the item passed to {@link CallHierarchyItemProvider.provideCallHierarchyOutgoingCalls `provideCallHierarchyOutgoingCalls`} and not {@link CallHierarchyOutgoingCall.to `this.to`}.""" @@ -1687,7 +1674,7 @@ class SemanticTokens: # Since: 3.16.0 - data: List[int] = attrs.field() + data: Sequence[int] = attrs.field() """The actual tokens.""" result_id: Optional[str] = attrs.field( @@ -1706,16 +1693,7 @@ class SemanticTokensPartialResult: # Since: 3.16.0 - data: List[int] = attrs.field() - - -@attrs.define -class SemanticTokensOptionsFullType1: - delta: Optional[bool] = attrs.field( - validator=attrs.validators.optional(attrs.validators.instance_of(bool)), - default=None, - ) - """The server supports deltas for full documents.""" + data: Sequence[int] = attrs.field() @attrs.define @@ -1731,9 +1709,7 @@ class SemanticTokensOptions: """Server supports providing semantic tokens for a specific range of a document.""" - full: Optional[Union[bool, "SemanticTokensOptionsFullType1"]] = attrs.field( - default=None - ) + full: Optional[Union[bool, "SemanticTokensFullDelta"]] = attrs.field(default=None) """Server supports providing semantic tokens for a full document.""" work_done_progress: Optional[bool] = attrs.field( @@ -1742,15 +1718,6 @@ class SemanticTokensOptions: ) -@attrs.define -class SemanticTokensRegistrationOptionsFullType1: - delta: Optional[bool] = attrs.field( - validator=attrs.validators.optional(attrs.validators.instance_of(bool)), - default=None, - ) - """The server supports deltas for full documents.""" - - @attrs.define class SemanticTokensRegistrationOptions: """@since 3.16.0""" @@ -1770,9 +1737,7 @@ class SemanticTokensRegistrationOptions: """Server supports providing semantic tokens for a specific range of a document.""" - full: Optional[ - Union[bool, "SemanticTokensRegistrationOptionsFullType1"] - ] = attrs.field(default=None) + full: Optional[Union[bool, "SemanticTokensFullDelta"]] = attrs.field(default=None) """Server supports providing semantic tokens for a full document.""" work_done_progress: Optional[bool] = attrs.field( @@ -1815,7 +1780,7 @@ class SemanticTokensDelta: # Since: 3.16.0 - edits: List["SemanticTokensEdit"] = attrs.field() + edits: Sequence["SemanticTokensEdit"] = attrs.field() """The semantic token edits to transform a previous result into a new result.""" result_id: Optional[str] = attrs.field( @@ -1830,7 +1795,7 @@ class SemanticTokensDeltaPartialResult: # Since: 3.16.0 - edits: List["SemanticTokensEdit"] = attrs.field() + edits: Sequence["SemanticTokensEdit"] = attrs.field() @attrs.define @@ -1920,7 +1885,7 @@ class LinkedEditingRanges: # Since: 3.16.0 - ranges: List["Range"] = attrs.field() + ranges: Sequence["Range"] = attrs.field() """A list of ranges that can be edited together. The ranges must have identical length and contain identical text content. The ranges cannot overlap.""" @@ -1971,7 +1936,7 @@ class CreateFilesParams: # Since: 3.16.0 - files: List["FileCreate"] = attrs.field() + files: Sequence["FileCreate"] = attrs.field() """An array of all files/folders created in this operation.""" @@ -1990,11 +1955,11 @@ class WorkspaceEdit: cause failure of the operation. How the client recovers from the failure is described by the client capability: `workspace.workspaceEdit.failureHandling`""" - changes: Optional[Dict[str, List["TextEdit"]]] = attrs.field(default=None) + changes: Optional[Mapping[str, Sequence["TextEdit"]]] = attrs.field(default=None) """Holds changes to existing resources.""" document_changes: Optional[ - List[Union["TextDocumentEdit", "CreateFile", "RenameFile", "DeleteFile"]] + Sequence[Union["TextDocumentEdit", "CreateFile", "RenameFile", "DeleteFile"]] ] = attrs.field(default=None) """Depending on the client capability `workspace.workspaceEdit.resourceOperations` document changes are either an array of `TextDocumentEdit`s to express changes to n different text documents @@ -2008,7 +1973,7 @@ class WorkspaceEdit: only plain `TextEdit`s using the `changes` property are supported.""" change_annotations: Optional[ - Dict[ChangeAnnotationIdentifier, "ChangeAnnotation"] + Mapping[ChangeAnnotationIdentifier, "ChangeAnnotation"] ] = attrs.field(default=None) """A map of change annotations that can be referenced in `AnnotatedTextEdit`s or create, rename and delete file / folder operations. @@ -2027,7 +1992,7 @@ class FileOperationRegistrationOptions: # Since: 3.16.0 - filters: List["FileOperationFilter"] = attrs.field() + filters: Sequence["FileOperationFilter"] = attrs.field() """The actual filters.""" @@ -2040,7 +2005,7 @@ class RenameFilesParams: # Since: 3.16.0 - files: List["FileRename"] = attrs.field() + files: Sequence["FileRename"] = attrs.field() """An array of all files/folders renamed in this operation. When a folder is renamed, only the folder will be included, and not its children.""" @@ -2054,7 +2019,7 @@ class DeleteFilesParams: # Since: 3.16.0 - files: List["FileDelete"] = attrs.field() + files: Sequence["FileDelete"] = attrs.field() """An array of all files/folders deleted in this operation.""" @@ -2160,7 +2125,7 @@ class TypeHierarchyItem: picked, e.g. the name of a function. Must be contained by the {@link TypeHierarchyItem.range `range`}.""" - tags: Optional[List[SymbolTag]] = attrs.field(default=None) + tags: Optional[Sequence[SymbolTag]] = attrs.field(default=None) """Tags for this item.""" detail: Optional[str] = attrs.field( @@ -2343,9 +2308,12 @@ class InlayHint: # Since: 3.17.0 position: "Position" = attrs.field() - """The position of this hint.""" + """The position of this hint. + + If multiple hints have the same position, they will be shown in the order + they appear in the response.""" - label: Union[str, List["InlayHintLabelPart"]] = attrs.field() + label: Union[str, Sequence["InlayHintLabelPart"]] = attrs.field() """The label of this hint. A human readable string or an array of InlayHintLabelPart label parts. @@ -2355,7 +2323,7 @@ class InlayHint: """The kind of this hint. Can be omitted in which case the client should fall back to a reasonable default.""" - text_edits: Optional[List["TextEdit"]] = attrs.field(default=None) + text_edits: Optional[Sequence["TextEdit"]] = attrs.field(default=None) """Optional text edits that are performed when accepting this inlay hint. *Note* that edits are expected to change the document so that the inlay @@ -2484,7 +2452,7 @@ class DocumentDiagnosticReportPartialResult: # Since: 3.17.0 - related_documents: Dict[ + related_documents: Mapping[ str, Union["FullDocumentDiagnosticReport", "UnchangedDocumentDiagnosticReport"] ] = attrs.field() @@ -2589,7 +2557,7 @@ class WorkspaceDiagnosticParams: # Since: 3.17.0 - previous_result_ids: List["PreviousResultId"] = attrs.field() + previous_result_ids: Sequence["PreviousResultId"] = attrs.field() """The currently known diagnostic reports with their previous result ids.""" @@ -2615,7 +2583,7 @@ class WorkspaceDiagnosticReport: # Since: 3.17.0 - items: List[WorkspaceDocumentDiagnosticReport] = attrs.field() + items: Sequence[WorkspaceDocumentDiagnosticReport] = attrs.field() @attrs.define @@ -2626,7 +2594,7 @@ class WorkspaceDiagnosticReportPartialResult: # Since: 3.17.0 - items: List[WorkspaceDocumentDiagnosticReport] = attrs.field() + items: Sequence[WorkspaceDocumentDiagnosticReport] = attrs.field() @attrs.define @@ -2640,11 +2608,70 @@ class DidOpenNotebookDocumentParams: notebook_document: "NotebookDocument" = attrs.field() """The notebook document that got opened.""" - cell_text_documents: List["TextDocumentItem"] = attrs.field() + cell_text_documents: Sequence["TextDocumentItem"] = attrs.field() """The text documents that represent the content of a notebook cell.""" +@attrs.define +class NotebookDocumentSyncOptions: + """Options specific to a notebook plus its cells + to be synced to the server. + + If a selector provides a notebook document + filter but no cell selector all cells of a + matching notebook document will be synced. + + If a selector provides no notebook document + filter but only a cell selector all notebook + document that contain at least one matching + cell will be synced. + + @since 3.17.0""" + + # Since: 3.17.0 + + notebook_selector: Sequence[ + Union["NotebookDocumentFilterWithNotebook", "NotebookDocumentFilterWithCells"] + ] = attrs.field() + """The notebooks to be synced""" + + save: Optional[bool] = attrs.field( + validator=attrs.validators.optional(attrs.validators.instance_of(bool)), + default=None, + ) + """Whether save notification should be forwarded to + the server. Will only be honored if mode === `notebook`.""" + + +@attrs.define +class NotebookDocumentSyncRegistrationOptions: + """Registration options specific to a notebook. + + @since 3.17.0""" + + # Since: 3.17.0 + + notebook_selector: Sequence[ + Union["NotebookDocumentFilterWithNotebook", "NotebookDocumentFilterWithCells"] + ] = attrs.field() + """The notebooks to be synced""" + + save: Optional[bool] = attrs.field( + validator=attrs.validators.optional(attrs.validators.instance_of(bool)), + default=None, + ) + """Whether save notification should be forwarded to + the server. Will only be honored if mode === `notebook`.""" + + id: Optional[str] = attrs.field( + validator=attrs.validators.optional(attrs.validators.instance_of(str)), + default=None, + ) + """The id used to register the request. The id can be used to deregister + the request again. See also Registration#id.""" + + @attrs.define class DidChangeNotebookDocumentParams: """The params sent in a change notebook document notification. @@ -2698,7 +2725,7 @@ class DidCloseNotebookDocumentParams: notebook_document: "NotebookDocumentIdentifier" = attrs.field() """The notebook document that got closed.""" - cell_text_documents: List["TextDocumentIdentifier"] = attrs.field() + cell_text_documents: Sequence["TextDocumentIdentifier"] = attrs.field() """The text documents that represent the content of a notebook cell that got closed.""" @@ -2737,7 +2764,7 @@ class InlineCompletionList: # Since: 3.18.0 # Proposed - items: List["InlineCompletionItem"] = attrs.field() + items: Sequence["InlineCompletionItem"] = attrs.field() """The inline completion items""" @@ -2812,26 +2839,94 @@ class InlineCompletionRegistrationOptions: the request again. See also Registration#id.""" +@attrs.define +class TextDocumentContentParams: + """Parameters for the `workspace/textDocumentContent` request. + + @since 3.18.0 + @proposed""" + + # Since: 3.18.0 + # Proposed + + uri: str = attrs.field(validator=attrs.validators.instance_of(str)) + """The uri of the text document.""" + + +@attrs.define +class TextDocumentContentResult: + """Result of the `workspace/textDocumentContent` request. + + @since 3.18.0 + @proposed""" + + # Since: 3.18.0 + # Proposed + + text: str = attrs.field(validator=attrs.validators.instance_of(str)) + """The text content of the text document. Please note, that the content of + any subsequent open notifications for the text document might differ + from the returned content due to whitespace and line ending + normalizations done on the client""" + + +@attrs.define +class TextDocumentContentOptions: + """Text document content provider options. + + @since 3.18.0 + @proposed""" + + # Since: 3.18.0 + # Proposed + + schemes: Sequence[str] = attrs.field() + """The schemes for which the server provides content.""" + + +@attrs.define +class TextDocumentContentRegistrationOptions: + """Text document content provider registration options. + + @since 3.18.0 + @proposed""" + + # Since: 3.18.0 + # Proposed + + schemes: Sequence[str] = attrs.field() + """The schemes for which the server provides content.""" + + id: Optional[str] = attrs.field( + validator=attrs.validators.optional(attrs.validators.instance_of(str)), + default=None, + ) + """The id used to register the request. The id can be used to deregister + the request again. See also Registration#id.""" + + +@attrs.define +class TextDocumentContentRefreshParams: + """Parameters for the `workspace/textDocumentContent/refresh` request. + + @since 3.18.0 + @proposed""" + + # Since: 3.18.0 + # Proposed + + uri: str = attrs.field(validator=attrs.validators.instance_of(str)) + """The uri of the text document to refresh.""" + + @attrs.define class RegistrationParams: - registrations: List["Registration"] = attrs.field() + registrations: Sequence["Registration"] = attrs.field() @attrs.define class UnregistrationParams: - unregisterations: List["Unregistration"] = attrs.field() - - -@attrs.define -class InitializeParamsClientInfoType: - name: str = attrs.field(validator=attrs.validators.instance_of(str)) - """The name of the client as defined by the client.""" - - version: Optional[str] = attrs.field( - validator=attrs.validators.optional(attrs.validators.instance_of(str)), - default=None, - ) - """The client's version as defined by the client.""" + unregisterations: Sequence["Unregistration"] = attrs.field() @attrs.define @@ -2848,7 +2943,7 @@ class _InitializeParams: Is `null` if the process has not been started by another process. If the parent process is not alive then the server should exit.""" - client_info: Optional["InitializeParamsClientInfoType"] = attrs.field(default=None) + client_info: Optional["ClientInfo"] = attrs.field(default=None) """Information about the client @since 3.15.0""" @@ -2884,7 +2979,7 @@ class _InitializeParams: initialization_options: Optional[LSPAny] = attrs.field(default=None) """User provided initialization options.""" - trace: Optional[TraceValues] = attrs.field(default=None) + trace: Optional[TraceValue] = attrs.field(default=None) """The initial trace setting. If omitted trace is disabled ('off').""" work_done_token: Optional[ProgressToken] = attrs.field(default=None) @@ -2893,7 +2988,7 @@ class _InitializeParams: @attrs.define class WorkspaceFoldersInitializeParams: - workspace_folders: Optional[Union[List[WorkspaceFolder], None]] = attrs.field( + workspace_folders: Optional[Union[Sequence[WorkspaceFolder], None]] = attrs.field( default=None ) """The workspace folders configured in the client when the server starts. @@ -2918,7 +3013,7 @@ class InitializeParams: Is `null` if the process has not been started by another process. If the parent process is not alive then the server should exit.""" - client_info: Optional["InitializeParamsClientInfoType"] = attrs.field(default=None) + client_info: Optional["ClientInfo"] = attrs.field(default=None) """Information about the client @since 3.15.0""" @@ -2954,13 +3049,13 @@ class InitializeParams: initialization_options: Optional[LSPAny] = attrs.field(default=None) """User provided initialization options.""" - trace: Optional[TraceValues] = attrs.field(default=None) + trace: Optional[TraceValue] = attrs.field(default=None) """The initial trace setting. If omitted trace is disabled ('off').""" work_done_token: Optional[ProgressToken] = attrs.field(default=None) """An optional token that a server can use to report work done progress.""" - workspace_folders: Optional[Union[List[WorkspaceFolder], None]] = attrs.field( + workspace_folders: Optional[Union[Sequence[WorkspaceFolder], None]] = attrs.field( default=None ) """The workspace folders configured in the client when the server starts. @@ -2973,18 +3068,6 @@ class InitializeParams: # Since: 3.6.0 -@attrs.define -class InitializeResultServerInfoType: - name: str = attrs.field(validator=attrs.validators.instance_of(str)) - """The name of the server as defined by the server.""" - - version: Optional[str] = attrs.field( - validator=attrs.validators.optional(attrs.validators.instance_of(str)), - default=None, - ) - """The server's version as defined by the server.""" - - @attrs.define class InitializeResult: """The result returned from an initialize request.""" @@ -2992,7 +3075,7 @@ class InitializeResult: capabilities: "ServerCapabilities" = attrs.field() """The capabilities the language server provides.""" - server_info: Optional["InitializeResultServerInfoType"] = attrs.field(default=None) + server_info: Optional["ServerInfo"] = attrs.field(default=None) """Information about the server. @since 3.15.0""" @@ -3026,7 +3109,7 @@ class DidChangeConfigurationParams: @attrs.define class DidChangeConfigurationRegistrationOptions: - section: Optional[Union[str, List[str]]] = attrs.field(default=None) + section: Optional[Union[str, Sequence[str]]] = attrs.field(default=None) @attrs.define @@ -3048,7 +3131,7 @@ class ShowMessageRequestParams: message: str = attrs.field(validator=attrs.validators.instance_of(str)) """The actual message.""" - actions: Optional[List["MessageActionItem"]] = attrs.field(default=None) + actions: Optional[Sequence["MessageActionItem"]] = attrs.field(default=None) """The message action items to present.""" @@ -3086,7 +3169,7 @@ class DidChangeTextDocumentParams: to the version after all provided content changes have been applied.""" - content_changes: List[TextDocumentContentChangeEvent] = attrs.field() + content_changes: Sequence[TextDocumentContentChangeEvent] = attrs.field() """The actual content changes. The content changes describe single state changes to the document. So if there are two content changes c1 (at array index 0) and c2 (at array index 1) for a document in state S then c1 moves the document from @@ -3193,7 +3276,7 @@ class TextEdit: class DidChangeWatchedFilesParams: """The watched files change notification's parameters.""" - changes: List["FileEvent"] = attrs.field() + changes: Sequence["FileEvent"] = attrs.field() """The actual file events.""" @@ -3201,7 +3284,7 @@ class DidChangeWatchedFilesParams: class DidChangeWatchedFilesRegistrationOptions: """Describe options to be used when registered for text document change events.""" - watchers: List["FileSystemWatcher"] = attrs.field() + watchers: Sequence["FileSystemWatcher"] = attrs.field() """The watchers to register.""" @@ -3212,7 +3295,7 @@ class PublishDiagnosticsParams: uri: str = attrs.field(validator=attrs.validators.instance_of(str)) """The URI for which diagnostic information is reported.""" - diagnostics: List["Diagnostic"] = attrs.field() + diagnostics: Sequence["Diagnostic"] = attrs.field() """An array of diagnostic information items.""" version: Optional[int] = attrs.field( @@ -3266,11 +3349,11 @@ class CompletionItem: @since 3.17.0""" # Since: 3.17.0 - kind: Optional[CompletionItemKind] = attrs.field(default=None) + kind: Optional[Union[CompletionItemKind, int]] = attrs.field(default=None) """The kind of this completion item. Based of the kind an icon is chosen by the editor.""" - tags: Optional[List[CompletionItemTag]] = attrs.field(default=None) + tags: Optional[Sequence[CompletionItemTag]] = attrs.field(default=None) """Tags for this completion item. @since 3.15.0""" @@ -3392,7 +3475,7 @@ class CompletionItem: @since 3.17.0""" # Since: 3.17.0 - additional_text_edits: Optional[List[TextEdit]] = attrs.field(default=None) + additional_text_edits: Optional[Sequence[TextEdit]] = attrs.field(default=None) """An optional array of additional {@link TextEdit text edits} that are applied when selecting this completion. Edits must not overlap (including the same insert position) with the main {@link CompletionItem.textEdit edit} nor with themselves. @@ -3401,7 +3484,7 @@ class CompletionItem: (for example adding an import statement at the top of the file if the completion item will insert an unqualified type).""" - commit_characters: Optional[List[str]] = attrs.field(default=None) + commit_characters: Optional[Sequence[str]] = attrs.field(default=None) """An optional set of characters that when pressed while this completion is active will accept it first and then type that character. *Note* that all commit characters should have `length=1` and that superfluous characters will be ignored.""" @@ -3416,48 +3499,6 @@ class CompletionItem: {@link CompletionRequest} and a {@link CompletionResolveRequest}.""" -@attrs.define -class CompletionListItemDefaultsTypeEditRangeType1: - insert: "Range" = attrs.field() - - replace: "Range" = attrs.field() - - -@attrs.define -class CompletionListItemDefaultsType: - commit_characters: Optional[List[str]] = attrs.field(default=None) - """A default commit character set. - - @since 3.17.0""" - # Since: 3.17.0 - - edit_range: Optional[ - Union["Range", "CompletionListItemDefaultsTypeEditRangeType1"] - ] = attrs.field(default=None) - """A default edit range. - - @since 3.17.0""" - # Since: 3.17.0 - - insert_text_format: Optional[InsertTextFormat] = attrs.field(default=None) - """A default insert text format. - - @since 3.17.0""" - # Since: 3.17.0 - - insert_text_mode: Optional[InsertTextMode] = attrs.field(default=None) - """A default insert text mode. - - @since 3.17.0""" - # Since: 3.17.0 - - data: Optional[LSPAny] = attrs.field(default=None) - """A default data value. - - @since 3.17.0""" - # Since: 3.17.0 - - @attrs.define class CompletionList: """Represents a collection of {@link CompletionItem completion items} to be presented @@ -3469,19 +3510,19 @@ class CompletionList: Recomputed lists have all their items replaced (not appended) in the incomplete completion sessions.""" - items: List[CompletionItem] = attrs.field() + items: Sequence[CompletionItem] = attrs.field() """The completion items.""" - item_defaults: Optional["CompletionListItemDefaultsType"] = attrs.field( - default=None - ) + item_defaults: Optional["CompletionItemDefaults"] = attrs.field(default=None) """In many cases the items of an actual completion result share the same value for properties like `commitCharacters` or the range of a text edit. A completion list can therefore define item defaults which will be used if a completion item itself doesn't specify the value. If a completion list specifies a default value and a completion item - also specifies a corresponding value the one from the item is used. + also specifies a corresponding value, the rules for combining these are + defined by `applyKinds` (if the client supports it), defaulting to + ApplyKind.Replace. Servers are only allowed to return default values if the client signals support for this via the `completionList.itemDefaults` @@ -3490,26 +3531,32 @@ class CompletionList: @since 3.17.0""" # Since: 3.17.0 - -@attrs.define -class CompletionOptionsCompletionItemType: - label_details_support: Optional[bool] = attrs.field( - validator=attrs.validators.optional(attrs.validators.instance_of(bool)), - default=None, - ) - """The server has support for completion item label - details (see also `CompletionItemLabelDetails`) when - receiving a completion item in a resolve call. + apply_kind: Optional["CompletionItemApplyKinds"] = attrs.field(default=None) + """Specifies how fields from a completion item should be combined with those + from `completionList.itemDefaults`. - @since 3.17.0""" - # Since: 3.17.0 + If unspecified, all fields will be treated as ApplyKind.Replace. + + If a field's value is ApplyKind.Replace, the value from a completion item + (if provided and not `null`) will always be used instead of the value + from `completionItem.itemDefaults`. + + If a field's value is ApplyKind.Merge, the values will be merged using + the rules defined against each field below. + + Servers are only allowed to return `applyKind` if the client + signals support for this via the `completionList.applyKindSupport` + capability. + + @since 3.18.0""" + # Since: 3.18.0 @attrs.define class CompletionOptions: """Completion options.""" - trigger_characters: Optional[List[str]] = attrs.field(default=None) + trigger_characters: Optional[Sequence[str]] = attrs.field(default=None) """Most tools trigger completion request automatically without explicitly requesting it using a keyboard shortcut (e.g. Ctrl+Space). Typically they do so when the user starts to type an identifier. For example if the user types `c` in a JavaScript file @@ -3519,7 +3566,7 @@ class CompletionOptions: If code complete should automatically be trigger on characters not being valid inside an identifier (for example `.` in JavaScript) list them in `triggerCharacters`.""" - all_commit_characters: Optional[List[str]] = attrs.field(default=None) + all_commit_characters: Optional[Sequence[str]] = attrs.field(default=None) """The list of all possible characters that commit a completion. This field can be used if clients don't support individual commit characters per completion item. See `ClientCapabilities.textDocument.completion.completionItem.commitCharactersSupport` @@ -3537,9 +3584,7 @@ class CompletionOptions: """The server provides support to resolve additional information for a completion item.""" - completion_item: Optional["CompletionOptionsCompletionItemType"] = attrs.field( - default=None - ) + completion_item: Optional["ServerCompletionItemOptions"] = attrs.field(default=None) """The server supports the following `CompletionItem` specific capabilities. @@ -3552,20 +3597,6 @@ class CompletionOptions: ) -@attrs.define -class CompletionRegistrationOptionsCompletionItemType: - label_details_support: Optional[bool] = attrs.field( - validator=attrs.validators.optional(attrs.validators.instance_of(bool)), - default=None, - ) - """The server has support for completion item label - details (see also `CompletionItemLabelDetails`) when - receiving a completion item in a resolve call. - - @since 3.17.0""" - # Since: 3.17.0 - - @attrs.define class CompletionRegistrationOptions: """Registration options for a {@link CompletionRequest}.""" @@ -3576,7 +3607,7 @@ class CompletionRegistrationOptions: """A document selector to identify the scope of the registration. If set to null the document selector provided on the client side will be used.""" - trigger_characters: Optional[List[str]] = attrs.field(default=None) + trigger_characters: Optional[Sequence[str]] = attrs.field(default=None) """Most tools trigger completion request automatically without explicitly requesting it using a keyboard shortcut (e.g. Ctrl+Space). Typically they do so when the user starts to type an identifier. For example if the user types `c` in a JavaScript file @@ -3586,7 +3617,7 @@ class CompletionRegistrationOptions: If code complete should automatically be trigger on characters not being valid inside an identifier (for example `.` in JavaScript) list them in `triggerCharacters`.""" - all_commit_characters: Optional[List[str]] = attrs.field(default=None) + all_commit_characters: Optional[Sequence[str]] = attrs.field(default=None) """The list of all possible characters that commit a completion. This field can be used if clients don't support individual commit characters per completion item. See `ClientCapabilities.textDocument.completion.completionItem.commitCharactersSupport` @@ -3604,9 +3635,7 @@ class CompletionRegistrationOptions: """The server provides support to resolve additional information for a completion item.""" - completion_item: Optional[ - "CompletionRegistrationOptionsCompletionItemType" - ] = attrs.field(default=None) + completion_item: Optional["ServerCompletionItemOptions"] = attrs.field(default=None) """The server supports the following `CompletionItem` specific capabilities. @@ -3637,7 +3666,9 @@ class HoverParams: class Hover: """The result of a hover request.""" - contents: Union["MarkupContent", MarkedString, List[MarkedString]] = attrs.field() + contents: Union["MarkupContent", MarkedString, Sequence[MarkedString]] = ( + attrs.field() + ) """The hover's content""" range: Optional["Range"] = attrs.field(default=None) @@ -3698,7 +3729,7 @@ class SignatureHelp: callable. There can be multiple signature but only one active and only one active parameter.""" - signatures: List["SignatureInformation"] = attrs.field() + signatures: Sequence["SignatureInformation"] = attrs.field() """One or more signatures.""" active_signature: Optional[int] = attrs.field( @@ -3714,26 +3745,33 @@ class SignatureHelp: In future version of the protocol this property might become mandatory to better express this.""" - active_parameter: Optional[int] = attrs.field( - validator=attrs.validators.optional(validators.uinteger_validator), default=None - ) - """The active parameter of the active signature. If omitted or the value - lies outside the range of `signatures[activeSignature].parameters` - defaults to 0 if the active signature has parameters. If - the active signature has no parameters it is ignored. + active_parameter: Optional[Union[int, None]] = attrs.field(default=None) + """The active parameter of the active signature. + + If `null`, no parameter of the signature is active (for example a named + argument that does not match any declared parameters). This is only valid + if the client specifies the client capability + `textDocument.signatureHelp.noActiveParameterSupport === true` + + If omitted or the value lies outside the range of + `signatures[activeSignature].parameters` defaults to 0 if the active + signature has parameters. + + If the active signature has no parameters it is ignored. + In future version of the protocol this property might become - mandatory to better express the active parameter if the - active signature does have any.""" + mandatory (but still nullable) to better express the active parameter if + the active signature does have any.""" @attrs.define class SignatureHelpOptions: """Server Capabilities for a {@link SignatureHelpRequest}.""" - trigger_characters: Optional[List[str]] = attrs.field(default=None) + trigger_characters: Optional[Sequence[str]] = attrs.field(default=None) """List of characters that trigger signature help automatically.""" - retrigger_characters: Optional[List[str]] = attrs.field(default=None) + retrigger_characters: Optional[Sequence[str]] = attrs.field(default=None) """List of characters that re-trigger signature help. These trigger characters are only active when signature help is already showing. All trigger characters @@ -3758,10 +3796,10 @@ class SignatureHelpRegistrationOptions: """A document selector to identify the scope of the registration. If set to null the document selector provided on the client side will be used.""" - trigger_characters: Optional[List[str]] = attrs.field(default=None) + trigger_characters: Optional[Sequence[str]] = attrs.field(default=None) """List of characters that trigger signature help automatically.""" - retrigger_characters: Optional[List[str]] = attrs.field(default=None) + retrigger_characters: Optional[Sequence[str]] = attrs.field(default=None) """List of characters that re-trigger signature help. These trigger characters are only active when signature help is already showing. All trigger characters @@ -3948,7 +3986,7 @@ class BaseSymbolInformation: kind: SymbolKind = attrs.field() """The kind of this symbol.""" - tags: Optional[List[SymbolTag]] = attrs.field(default=None) + tags: Optional[Sequence[SymbolTag]] = attrs.field(default=None) """Tags for this symbol. @since 3.16.0""" @@ -3994,7 +4032,7 @@ class SymbolInformation: @deprecated Use tags instead""" - tags: Optional[List[SymbolTag]] = attrs.field(default=None) + tags: Optional[Sequence[SymbolTag]] = attrs.field(default=None) """Tags for this symbol. @since 3.16.0""" @@ -4039,7 +4077,7 @@ class DocumentSymbol: ) """More detail for this symbol, e.g the signature of a function.""" - tags: Optional[List[SymbolTag]] = attrs.field(default=None) + tags: Optional[Sequence[SymbolTag]] = attrs.field(default=None) """Tags for this document symbol. @since 3.16.0""" @@ -4053,7 +4091,7 @@ class DocumentSymbol: @deprecated Use tags instead""" - children: Optional[List["DocumentSymbol"]] = attrs.field(default=None) + children: Optional[Sequence["DocumentSymbol"]] = attrs.field(default=None) """Children of this symbol, e.g. properties of a class.""" @@ -4137,26 +4175,28 @@ class Command: command: str = attrs.field(validator=attrs.validators.instance_of(str)) """The identifier of the actual command handler.""" - arguments: Optional[List[LSPAny]] = attrs.field(default=None) + tooltip: Optional[str] = attrs.field( + validator=attrs.validators.optional(attrs.validators.instance_of(str)), + default=None, + ) + """An optional tooltip. + + @since 3.18.0 + @proposed""" + # Since: 3.18.0 + # Proposed + + arguments: Optional[Sequence[LSPAny]] = attrs.field(default=None) """Arguments that the command handler should be invoked with.""" -@attrs.define -class CodeActionDisabledType: - reason: str = attrs.field(validator=attrs.validators.instance_of(str)) - """Human readable description of why the code action is currently disabled. - - This is displayed in the code actions UI.""" - - @attrs.define class CodeAction: """A code action represents a change that can be performed in code, e.g. to fix a problem or to refactor code. - A CodeAction must set either `edit` and/or a `command`. If both are supplied, the `edit` is applied first, then the `command` is executed. - """ + A CodeAction must set either `edit` and/or a `command`. If both are supplied, the `edit` is applied first, then the `command` is executed.""" title: str = attrs.field(validator=attrs.validators.instance_of(str)) """A short, human-readable, title for this code action.""" @@ -4166,7 +4206,7 @@ class CodeAction: Used to filter code actions.""" - diagnostics: Optional[List["Diagnostic"]] = attrs.field(default=None) + diagnostics: Optional[Sequence["Diagnostic"]] = attrs.field(default=None) """The diagnostics that this code action resolves.""" is_preferred: Optional[bool] = attrs.field( @@ -4182,7 +4222,7 @@ class CodeAction: @since 3.15.0""" # Since: 3.15.0 - disabled: Optional["CodeActionDisabledType"] = attrs.field(default=None) + disabled: Optional["CodeActionDisabled"] = attrs.field(default=None) """Marks that the code action cannot currently be applied. Clients should follow the following guidelines regarding disabled code actions: @@ -4215,12 +4255,18 @@ class CodeAction: @since 3.16.0""" # Since: 3.16.0 + tags: Optional[Sequence[CodeActionTag]] = attrs.field(default=None) + """Tags for this code action. + + @since 3.18.0 - proposed""" + # Since: 3.18.0 - proposed + @attrs.define class CodeActionOptions: """Provider options for a {@link CodeActionRequest}.""" - code_action_kinds: Optional[List[Union[CodeActionKind, str]]] = attrs.field( + code_action_kinds: Optional[Sequence[Union[CodeActionKind, str]]] = attrs.field( default=None ) """CodeActionKinds that this server may return. @@ -4228,6 +4274,27 @@ class CodeActionOptions: The list of kinds may be generic, such as `CodeActionKind.Refactor`, or the server may list out every specific kind they provide.""" + documentation: Optional[Sequence["CodeActionKindDocumentation"]] = attrs.field( + default=None + ) + """Static documentation for a class of code actions. + + Documentation from the provider should be shown in the code actions menu if either: + + - Code actions of `kind` are requested by the editor. In this case, the editor will show the documentation that + most closely matches the requested code action kind. For example, if a provider has documentation for + both `Refactor` and `RefactorExtract`, when the user requests code actions for `RefactorExtract`, + the editor will use the documentation for `RefactorExtract` instead of the documentation for `Refactor`. + + - Any code actions of `kind` are returned by the provider. + + At most one documentation entry should be shown per provider. + + @since 3.18.0 + @proposed""" + # Since: 3.18.0 + # Proposed + resolve_provider: Optional[bool] = attrs.field( validator=attrs.validators.optional(attrs.validators.instance_of(bool)), default=None, @@ -4254,7 +4321,7 @@ class CodeActionRegistrationOptions: """A document selector to identify the scope of the registration. If set to null the document selector provided on the client side will be used.""" - code_action_kinds: Optional[List[Union[CodeActionKind, str]]] = attrs.field( + code_action_kinds: Optional[Sequence[Union[CodeActionKind, str]]] = attrs.field( default=None ) """CodeActionKinds that this server may return. @@ -4262,6 +4329,27 @@ class CodeActionRegistrationOptions: The list of kinds may be generic, such as `CodeActionKind.Refactor`, or the server may list out every specific kind they provide.""" + documentation: Optional[Sequence["CodeActionKindDocumentation"]] = attrs.field( + default=None + ) + """Static documentation for a class of code actions. + + Documentation from the provider should be shown in the code actions menu if either: + + - Code actions of `kind` are requested by the editor. In this case, the editor will show the documentation that + most closely matches the requested code action kind. For example, if a provider has documentation for + both `Refactor` and `RefactorExtract`, when the user requests code actions for `RefactorExtract`, + the editor will use the documentation for `RefactorExtract` instead of the documentation for `Refactor`. + + - Any code actions of `kind` are returned by the provider. + + At most one documentation entry should be shown per provider. + + @since 3.18.0 + @proposed""" + # Since: 3.18.0 + # Proposed + resolve_provider: Optional[bool] = attrs.field( validator=attrs.validators.optional(attrs.validators.instance_of(bool)), default=None, @@ -4284,7 +4372,13 @@ class WorkspaceSymbolParams: query: str = attrs.field(validator=attrs.validators.instance_of(str)) """A query string to filter symbols by. Clients may send an empty - string here to request all symbols.""" + string here to request all symbols. + + The `query`-parameter should be interpreted in a *relaxed way* as editors + will apply their own highlighting and scoring on the results. A good rule + of thumb is to match case-insensitive and to simply check that the + characters of *query* appear in their order in a candidate symbol. + Servers shouldn't use prefix, substring, or similar strict matching.""" work_done_token: Optional[ProgressToken] = attrs.field(default=None) """An optional token that a server can use to report work done progress.""" @@ -4294,11 +4388,6 @@ class WorkspaceSymbolParams: the client.""" -@attrs.define -class WorkspaceSymbolLocationType1: - uri: str = attrs.field(validator=attrs.validators.instance_of(str)) - - @attrs.define class WorkspaceSymbol: """A special workspace symbol that supports locations without a range. @@ -4309,7 +4398,7 @@ class WorkspaceSymbol: # Since: 3.17.0 - location: Union[Location, "WorkspaceSymbolLocationType1"] = attrs.field() + location: Union[Location, "LocationUriOnly"] = attrs.field() """The location of the symbol. Whether a server is allowed to return a location without a range depends on the client capability `workspace.symbol.resolveSupport`. @@ -4326,7 +4415,7 @@ class WorkspaceSymbol: """A data entry field that is preserved on a workspace symbol between a workspace symbol request and a workspace symbol resolve request.""" - tags: Optional[List[SymbolTag]] = attrs.field(default=None) + tags: Optional[Sequence[SymbolTag]] = attrs.field(default=None) """Tags for this symbol. @since 3.16.0""" @@ -4657,7 +4746,7 @@ class DocumentRangesFormattingParams: text_document: "TextDocumentIdentifier" = attrs.field() """The document to format.""" - ranges: List["Range"] = attrs.field() + ranges: Sequence["Range"] = attrs.field() """The ranges to format""" options: "FormattingOptions" = attrs.field() @@ -4698,7 +4787,7 @@ class DocumentOnTypeFormattingOptions: ) """A character on which formatting should be triggered, like `{`.""" - more_trigger_character: Optional[List[str]] = attrs.field(default=None) + more_trigger_character: Optional[Sequence[str]] = attrs.field(default=None) """More trigger characters.""" @@ -4717,7 +4806,7 @@ class DocumentOnTypeFormattingRegistrationOptions: """A document selector to identify the scope of the registration. If set to null the document selector provided on the client side will be used.""" - more_trigger_character: Optional[List[str]] = attrs.field(default=None) + more_trigger_character: Optional[Sequence[str]] = attrs.field(default=None) """More trigger characters.""" @@ -4803,7 +4892,7 @@ class ExecuteCommandParams: command: str = attrs.field(validator=attrs.validators.instance_of(str)) """The identifier of the actual command handler.""" - arguments: Optional[List[LSPAny]] = attrs.field(default=None) + arguments: Optional[Sequence[LSPAny]] = attrs.field(default=None) """Arguments that the command should be invoked with.""" work_done_token: Optional[ProgressToken] = attrs.field(default=None) @@ -4814,7 +4903,7 @@ class ExecuteCommandParams: class ExecuteCommandOptions: """The server capabilities of a {@link ExecuteCommandRequest}.""" - commands: List[str] = attrs.field() + commands: Sequence[str] = attrs.field() """The commands to be executed on the server""" work_done_progress: Optional[bool] = attrs.field( @@ -4827,7 +4916,7 @@ class ExecuteCommandOptions: class ExecuteCommandRegistrationOptions: """Registration options for a {@link ExecuteCommandRequest}.""" - commands: List[str] = attrs.field() + commands: Sequence[str] = attrs.field() """The commands to be executed on the server""" work_done_progress: Optional[bool] = attrs.field( @@ -4851,6 +4940,14 @@ class ApplyWorkspaceEditParams: presented in the user interface for example on an undo stack to undo the workspace edit.""" + metadata: Optional["WorkspaceEditMetadata"] = attrs.field(default=None) + """Additional data about the edit. + + @since 3.18.0 + @proposed""" + # Since: 3.18.0 + # Proposed + @attrs.define class ApplyWorkspaceEditResult: @@ -4968,7 +5065,7 @@ class WorkDoneProgressEnd: @attrs.define class SetTraceParams: - value: TraceValues = attrs.field() + value: TraceValue = attrs.field() @attrs.define @@ -5053,10 +5150,10 @@ class Range: class WorkspaceFoldersChangeEvent: """The workspace folder change event.""" - added: List[WorkspaceFolder] = attrs.field() + added: Sequence[WorkspaceFolder] = attrs.field() """The array of added workspace folders""" - removed: List[WorkspaceFolder] = attrs.field() + removed: Sequence[WorkspaceFolder] = attrs.field() """The array of the removed workspace folders""" @@ -5134,19 +5231,13 @@ class Position: # Since: 3.17.0 - support for negotiated position encoding. line: int = attrs.field(validator=validators.uinteger_validator) - """Line position in a document (zero-based). - - If a line number is greater than the number of lines in a document, it defaults back to the number of lines in the document. - If a line number is negative, it defaults to 0.""" + """Line position in a document (zero-based).""" character: int = attrs.field(validator=validators.uinteger_validator) """Character offset on a line in a document (zero-based). The meaning of this offset is determined by the negotiated - `PositionEncodingKind`. - - If the character value is greater than the line length it defaults back to the - line length.""" + `PositionEncodingKind`.""" def __eq__(self, o: object) -> bool: if not isinstance(o, Position): @@ -5174,7 +5265,7 @@ class SemanticTokensEdit: delete_count: int = attrs.field(validator=validators.uinteger_validator) """The count of elements to remove.""" - data: Optional[List[int]] = attrs.field(default=None) + data: Optional[Sequence[int]] = attrs.field(default=None) """The elements to insert.""" @@ -5200,12 +5291,19 @@ class TextDocumentEdit: text_document: "OptionalVersionedTextDocumentIdentifier" = attrs.field() """The text document to change.""" - edits: List[Union[TextEdit, "AnnotatedTextEdit"]] = attrs.field() + edits: Sequence[Union[TextEdit, "AnnotatedTextEdit", "SnippetTextEdit"]] = ( + attrs.field() + ) """The edits to be applied. @since 3.16.0 - support for AnnotatedTextEdit. This is guarded using a + client capability. + + @since 3.18.0 - support for SnippetTextEdit. This is guarded using a client capability.""" - # Since: 3.16.0 - support for AnnotatedTextEdit. This is guarded using aclient capability. + # Since: + # 3.16.0 - support for AnnotatedTextEdit. This is guarded using a client capability. + # 3.18.0 - support for SnippetTextEdit. This is guarded using a client capability. @attrs.define @@ -5517,7 +5615,7 @@ class FullDocumentDiagnosticReport: # Since: 3.17.0 - items: List["Diagnostic"] = attrs.field() + items: Sequence["Diagnostic"] = attrs.field() """The actual items.""" kind: str = attrs.field(validator=attrs.validators.in_(["full"]), default="full") @@ -5540,11 +5638,11 @@ class RelatedFullDocumentDiagnosticReport: # Since: 3.17.0 - items: List["Diagnostic"] = attrs.field() + items: Sequence["Diagnostic"] = attrs.field() """The actual items.""" related_documents: Optional[ - Dict[ + Mapping[ str, Union[FullDocumentDiagnosticReport, "UnchangedDocumentDiagnosticReport"], ] @@ -5605,7 +5703,7 @@ class RelatedUnchangedDocumentDiagnosticReport: diagnostic request for the same document.""" related_documents: Optional[ - Dict[ + Mapping[ str, Union[FullDocumentDiagnosticReport, UnchangedDocumentDiagnosticReport] ] ] = attrs.field(default=None) @@ -5661,7 +5759,7 @@ class NotebookDocument: """The version number of this document (it will increase after each change, including undo/redo).""" - cells: List["NotebookCell"] = attrs.field() + cells: Sequence["NotebookCell"] = attrs.field() """The cells of a notebook.""" metadata: Optional[LSPObject] = attrs.field(default=None) @@ -5679,7 +5777,7 @@ class TextDocumentItem: uri: str = attrs.field(validator=attrs.validators.instance_of(str)) """The text document's uri.""" - language_id: str = attrs.field(validator=attrs.validators.instance_of(str)) + language_id: Union[LanguageKind, str] = attrs.field() """The text document's language identifier.""" version: int = attrs.field(validator=validators.integer_validator) @@ -5705,43 +5803,6 @@ class VersionedNotebookDocumentIdentifier: """The notebook document's uri.""" -@attrs.define -class NotebookDocumentChangeEventCellsTypeStructureType: - array: "NotebookCellArrayChange" = attrs.field() - """The change to the cell array.""" - - did_open: Optional[List[TextDocumentItem]] = attrs.field(default=None) - """Additional opened cell text documents.""" - - did_close: Optional[List[TextDocumentIdentifier]] = attrs.field(default=None) - """Additional closed cell text documents.""" - - -@attrs.define -class NotebookDocumentChangeEventCellsTypeTextContentType: - document: "VersionedTextDocumentIdentifier" = attrs.field() - - changes: List[TextDocumentContentChangeEvent] = attrs.field() - - -@attrs.define -class NotebookDocumentChangeEventCellsType: - structure: Optional[ - "NotebookDocumentChangeEventCellsTypeStructureType" - ] = attrs.field(default=None) - """Changes to the cell structure to add or - remove cells.""" - - data: Optional[List["NotebookCell"]] = attrs.field(default=None) - """Changes to notebook cells properties like its - kind, execution summary or metadata.""" - - text_content: Optional[ - List["NotebookDocumentChangeEventCellsTypeTextContentType"] - ] = attrs.field(default=None) - """Changes to the text content of notebook cells.""" - - @attrs.define class NotebookDocumentChangeEvent: """A change event for a notebook document. @@ -5755,7 +5816,7 @@ class NotebookDocumentChangeEvent: Note: should always be an object literal (e.g. LSPObject)""" - cells: Optional["NotebookDocumentChangeEventCellsType"] = attrs.field(default=None) + cells: Optional["NotebookDocumentCellChanges"] = attrs.field(default=None) """Changes to cells""" @@ -5842,23 +5903,6 @@ class Unregistration: """The method to unregister for.""" -@attrs.define -class ServerCapabilitiesWorkspaceType: - workspace_folders: Optional["WorkspaceFoldersServerCapabilities"] = attrs.field( - default=None - ) - """The server supports workspace folder. - - @since 3.6.0""" - # Since: 3.6.0 - - file_operations: Optional["FileOperationOptions"] = attrs.field(default=None) - """The server is interested in notifications/requests for operations on files. - - @since 3.16.0""" - # Since: 3.16.0 - - @attrs.define class ServerCapabilities: """Defines the capabilities provided by a language @@ -5886,7 +5930,7 @@ class ServerCapabilities: TextDocumentSyncKind number.""" notebook_document_sync: Optional[ - Union["NotebookDocumentSyncOptions", "NotebookDocumentSyncRegistrationOptions"] + Union[NotebookDocumentSyncOptions, NotebookDocumentSyncRegistrationOptions] ] = attrs.field(default=None) """Defines how notebook documents are synced. @@ -5927,14 +5971,14 @@ class ServerCapabilities: ) """The server provides find references support.""" - document_highlight_provider: Optional[ - Union[bool, DocumentHighlightOptions] - ] = attrs.field(default=None) + document_highlight_provider: Optional[Union[bool, DocumentHighlightOptions]] = ( + attrs.field(default=None) + ) """The server provides document highlight support.""" - document_symbol_provider: Optional[ - Union[bool, DocumentSymbolOptions] - ] = attrs.field(default=None) + document_symbol_provider: Optional[Union[bool, DocumentSymbolOptions]] = ( + attrs.field(default=None) + ) """The server provides document symbol support.""" code_action_provider: Optional[Union[bool, CodeActionOptions]] = attrs.field( @@ -5955,14 +5999,14 @@ class ServerCapabilities: ] = attrs.field(default=None) """The server provides color provider support.""" - workspace_symbol_provider: Optional[ - Union[bool, WorkspaceSymbolOptions] - ] = attrs.field(default=None) + workspace_symbol_provider: Optional[Union[bool, WorkspaceSymbolOptions]] = ( + attrs.field(default=None) + ) """The server provides workspace symbol support.""" - document_formatting_provider: Optional[ - Union[bool, DocumentFormattingOptions] - ] = attrs.field(default=None) + document_formatting_provider: Optional[Union[bool, DocumentFormattingOptions]] = ( + attrs.field(default=None) + ) """The server provides document formatting.""" document_range_formatting_provider: Optional[ @@ -5970,9 +6014,9 @@ class ServerCapabilities: ] = attrs.field(default=None) """The server provides document range formatting.""" - document_on_type_formatting_provider: Optional[ - DocumentOnTypeFormattingOptions - ] = attrs.field(default=None) + document_on_type_formatting_provider: Optional[DocumentOnTypeFormattingOptions] = ( + attrs.field(default=None) + ) """The server provides document formatting on typing.""" rename_provider: Optional[Union[bool, RenameOptions]] = attrs.field(default=None) @@ -6059,9 +6103,9 @@ class ServerCapabilities: @since 3.17.0""" # Since: 3.17.0 - inline_completion_provider: Optional[ - Union[bool, InlineCompletionOptions] - ] = attrs.field(default=None) + inline_completion_provider: Optional[Union[bool, InlineCompletionOptions]] = ( + attrs.field(default=None) + ) """Inline completion options used during static registration. @since 3.18.0 @@ -6069,13 +6113,34 @@ class ServerCapabilities: # Since: 3.18.0 # Proposed - workspace: Optional["ServerCapabilitiesWorkspaceType"] = attrs.field(default=None) + workspace: Optional["WorkspaceOptions"] = attrs.field(default=None) """Workspace specific server capabilities.""" experimental: Optional[LSPAny] = attrs.field(default=None) """Experimental server capabilities.""" +@attrs.define +class ServerInfo: + """Information about the server + + @since 3.15.0 + @since 3.18.0 ServerInfo type name added.""" + + # Since: + # 3.15.0 + # 3.18.0 ServerInfo type name added. + + name: str = attrs.field(validator=attrs.validators.instance_of(str)) + """The name of the server as defined by the server.""" + + version: Optional[str] = attrs.field( + validator=attrs.validators.optional(attrs.validators.instance_of(str)), + default=None, + ) + """The server's version as defined by the server.""" + + @attrs.define class VersionedTextDocumentIdentifier: """A text document identifier to denote a specific version of a text document.""" @@ -6124,8 +6189,9 @@ class Diagnostic: """The diagnostic's message. It usually appears in the user interface""" severity: Optional[DiagnosticSeverity] = attrs.field(default=None) - """The diagnostic's severity. Can be omitted. If omitted it is up to the - client to interpret diagnostics as error, warning, info or hint.""" + """The diagnostic's severity. To avoid interpretation mismatches when a + server is used with different clients it is highly recommended that servers + always provide a severity value.""" code: Optional[Union[int, str]] = attrs.field(default=None) """The diagnostic's code, which usually appear in the user interface.""" @@ -6145,14 +6211,14 @@ class Diagnostic: diagnostic, e.g. 'typescript' or 'super lint'. It usually appears in the user interface.""" - tags: Optional[List[DiagnosticTag]] = attrs.field(default=None) + tags: Optional[Sequence[DiagnosticTag]] = attrs.field(default=None) """Additional metadata about the diagnostic. @since 3.15.0""" # Since: 3.15.0 - related_information: Optional[List["DiagnosticRelatedInformation"]] = attrs.field( - default=None + related_information: Optional[Sequence["DiagnosticRelatedInformation"]] = ( + attrs.field(default=None) ) """An array of related diagnostic information, e.g. when symbol-names within a scope collide all definitions can be marked via this property.""" @@ -6221,6 +6287,125 @@ class InsertReplaceEdit: """The range if the replace is requested.""" +@attrs.define +class CompletionItemDefaults: + """In many cases the items of an actual completion result share the same + value for properties like `commitCharacters` or the range of a text + edit. A completion list can therefore define item defaults which will + be used if a completion item itself doesn't specify the value. + + If a completion list specifies a default value and a completion item + also specifies a corresponding value, the rules for combining these are + defined by `applyKinds` (if the client supports it), defaulting to + ApplyKind.Replace. + + Servers are only allowed to return default values if the client + signals support for this via the `completionList.itemDefaults` + capability. + + @since 3.17.0""" + + # Since: 3.17.0 + + commit_characters: Optional[Sequence[str]] = attrs.field(default=None) + """A default commit character set. + + @since 3.17.0""" + # Since: 3.17.0 + + edit_range: Optional[Union[Range, "EditRangeWithInsertReplace"]] = attrs.field( + default=None + ) + """A default edit range. + + @since 3.17.0""" + # Since: 3.17.0 + + insert_text_format: Optional[InsertTextFormat] = attrs.field(default=None) + """A default insert text format. + + @since 3.17.0""" + # Since: 3.17.0 + + insert_text_mode: Optional[InsertTextMode] = attrs.field(default=None) + """A default insert text mode. + + @since 3.17.0""" + # Since: 3.17.0 + + data: Optional[LSPAny] = attrs.field(default=None) + """A default data value. + + @since 3.17.0""" + # Since: 3.17.0 + + +@attrs.define +class CompletionItemApplyKinds: + """Specifies how fields from a completion item should be combined with those + from `completionList.itemDefaults`. + + If unspecified, all fields will be treated as ApplyKind.Replace. + + If a field's value is ApplyKind.Replace, the value from a completion item (if + provided and not `null`) will always be used instead of the value from + `completionItem.itemDefaults`. + + If a field's value is ApplyKind.Merge, the values will be merged using the rules + defined against each field below. + + Servers are only allowed to return `applyKind` if the client + signals support for this via the `completionList.applyKindSupport` + capability. + + @since 3.18.0""" + + # Since: 3.18.0 + + commit_characters: Optional[ApplyKind] = attrs.field(default=None) + """Specifies whether commitCharacters on a completion will replace or be + merged with those in `completionList.itemDefaults.commitCharacters`. + + If ApplyKind.Replace, the commit characters from the completion item will + always be used unless not provided, in which case those from + `completionList.itemDefaults.commitCharacters` will be used. An + empty list can be used if a completion item does not have any commit + characters and also should not use those from + `completionList.itemDefaults.commitCharacters`. + + If ApplyKind.Merge the commitCharacters for the completion will be the + union of all values in both `completionList.itemDefaults.commitCharacters` + and the completion's own `commitCharacters`. + + @since 3.18.0""" + # Since: 3.18.0 + + data: Optional[ApplyKind] = attrs.field(default=None) + """Specifies whether the `data` field on a completion will replace or + be merged with data from `completionList.itemDefaults.data`. + + If ApplyKind.Replace, the data from the completion item will be used if + provided (and not `null`), otherwise + `completionList.itemDefaults.data` will be used. An empty object can + be used if a completion item does not have any data but also should + not use the value from `completionList.itemDefaults.data`. + + If ApplyKind.Merge, a shallow merge will be performed between + `completionList.itemDefaults.data` and the completion's own data + using the following rules: + + - If a completion's `data` field is not provided (or `null`), the + entire `data` field from `completionList.itemDefaults.data` will be + used as-is. + - If a completion's `data` field is provided, each field will + overwrite the field of the same name in + `completionList.itemDefaults.data` but no merging of nested fields + within that value will occur. + + @since 3.18.0""" + # Since: 3.18.0 + + @attrs.define class SignatureHelpContext: """Additional information about the context in which a signature help request was triggered. @@ -6267,15 +6452,19 @@ class SignatureInformation: """The human-readable doc-comment of this signature. Will be shown in the UI but can be omitted.""" - parameters: Optional[List["ParameterInformation"]] = attrs.field(default=None) + parameters: Optional[Sequence["ParameterInformation"]] = attrs.field(default=None) """The parameters of this signature.""" - active_parameter: Optional[int] = attrs.field( - validator=attrs.validators.optional(validators.uinteger_validator), default=None - ) + active_parameter: Optional[Union[int, None]] = attrs.field(default=None) """The index of the active parameter. - If provided, this is used in place of `SignatureHelp.activeParameter`. + If `null`, no parameter of the signature is active (for example a named + argument that does not match any declared parameters). This is only valid + if the client specifies the client capability + `textDocument.signatureHelp.noActiveParameterSupport === true` + + If provided (or `null`), this is used in place of + `SignatureHelp.activeParameter`. @since 3.16.0""" # Since: 3.16.0 @@ -6297,14 +6486,14 @@ class CodeActionContext: """Contains additional diagnostic information about the context in which a {@link CodeActionProvider.provideCodeActions code action} is run.""" - diagnostics: List[Diagnostic] = attrs.field() + diagnostics: Sequence[Diagnostic] = attrs.field() """An array of diagnostics known on the client side overlapping the range provided to the `textDocument/codeAction` request. They are provided so that the server knows which errors are currently presented to the user for the given range. There is no guarantee that these accurately reflect the error state of the resource. The primary parameter to compute code actions is the provided range.""" - only: Optional[List[Union[CodeActionKind, str]]] = attrs.field(default=None) + only: Optional[Sequence[Union[CodeActionKind, str]]] = attrs.field(default=None) """Requested kind of actions to return. Actions not of this kind are filtered out by the client before being shown. So servers @@ -6317,6 +6506,31 @@ class CodeActionContext: # Since: 3.17.0 +@attrs.define +class CodeActionDisabled: + """Captures why the code action is currently disabled. + + @since 3.18.0""" + + # Since: 3.18.0 + + reason: str = attrs.field(validator=attrs.validators.instance_of(str)) + """Human readable description of why the code action is currently disabled. + + This is displayed in the code actions UI.""" + + +@attrs.define +class LocationUriOnly: + """Location with only uri and does not include range. + + @since 3.18.0""" + + # Since: 3.18.0 + + uri: str = attrs.field(validator=attrs.validators.instance_of(str)) + + @attrs.define class FormattingOptions: """Value-object describing what options formatting should use.""" @@ -6355,19 +6569,71 @@ class FormattingOptions: # Since: 3.15.0 +@attrs.define +class PrepareRenamePlaceholder: + """@since 3.18.0""" + + # Since: 3.18.0 + + range: Range = attrs.field() + + placeholder: str = attrs.field(validator=attrs.validators.instance_of(str)) + + +@attrs.define +class PrepareRenameDefaultBehavior: + """@since 3.18.0""" + + # Since: 3.18.0 + + default_behavior: bool = attrs.field(validator=attrs.validators.instance_of(bool)) + + +@attrs.define +class WorkspaceEditMetadata: + """Additional data about a workspace edit. + + @since 3.18.0 + @proposed""" + + # Since: 3.18.0 + # Proposed + + is_refactoring: Optional[bool] = attrs.field( + validator=attrs.validators.optional(attrs.validators.instance_of(bool)), + default=None, + ) + """Signal to the editor that this edit is a refactoring.""" + + @attrs.define class SemanticTokensLegend: """@since 3.16.0""" # Since: 3.16.0 - token_types: List[str] = attrs.field() + token_types: Sequence[str] = attrs.field() """The token types a server uses.""" - token_modifiers: List[str] = attrs.field() + token_modifiers: Sequence[str] = attrs.field() """The token modifiers a server uses.""" +@attrs.define +class SemanticTokensFullDelta: + """Semantic tokens options to support deltas for full documents + + @since 3.18.0""" + + # Since: 3.18.0 + + delta: Optional[bool] = attrs.field( + validator=attrs.validators.optional(attrs.validators.instance_of(bool)), + default=None, + ) + """The server supports deltas for full documents.""" + + @attrs.define class OptionalVersionedTextDocumentIdentifier: """A text document identifier to optionally denote a specific version of a text document.""" @@ -6403,6 +6669,26 @@ class AnnotatedTextEdit: empty string.""" +@attrs.define +class SnippetTextEdit: + """An interactive text edit. + + @since 3.18.0 + @proposed""" + + # Since: 3.18.0 + # Proposed + + range: Range = attrs.field() + """The range of the text document to be manipulated.""" + + snippet: StringValue = attrs.field() + """The snippet to be inserted.""" + + annotation_id: Optional[ChangeAnnotationIdentifier] = attrs.field(default=None) + """The actual identifier of the snippet edit.""" + + @attrs.define class CreateFileOptions: """Options to create a file.""" @@ -6492,7 +6778,7 @@ class WorkspaceFullDocumentDiagnosticReport: uri: str = attrs.field(validator=attrs.validators.instance_of(str)) """The URI for which diagnostic information is reported.""" - items: List[Diagnostic] = attrs.field() + items: Sequence[Diagnostic] = attrs.field() """The actual items.""" version: Optional[Union[int, None]] = attrs.field(default=None) @@ -6569,22 +6855,57 @@ class NotebookCell: @attrs.define -class NotebookCellArrayChange: - """A change describing how to move a `NotebookCell` - array from state S to S'. +class NotebookDocumentFilterWithNotebook: + """@since 3.18.0""" - @since 3.17.0""" + # Since: 3.18.0 - # Since: 3.17.0 + notebook: Union[str, NotebookDocumentFilter] = attrs.field() + """The notebook to be synced If a string + value is provided it matches against the + notebook type. '*' matches every notebook.""" - start: int = attrs.field(validator=validators.uinteger_validator) - """The start oftest of the cell that changed.""" + cells: Optional[Sequence["NotebookCellLanguage"]] = attrs.field(default=None) + """The cells of the matching notebook to be synced.""" - delete_count: int = attrs.field(validator=validators.uinteger_validator) - """The deleted cells""" - cells: Optional[List[NotebookCell]] = attrs.field(default=None) - """The new cells, if any""" +@attrs.define +class NotebookDocumentFilterWithCells: + """@since 3.18.0""" + + # Since: 3.18.0 + + cells: Sequence["NotebookCellLanguage"] = attrs.field() + """The cells of the matching notebook to be synced.""" + + notebook: Optional[Union[str, NotebookDocumentFilter]] = attrs.field(default=None) + """The notebook to be synced If a string + value is provided it matches against the + notebook type. '*' matches every notebook.""" + + +@attrs.define +class NotebookDocumentCellChanges: + """Cell changes to a notebook document. + + @since 3.18.0""" + + # Since: 3.18.0 + + structure: Optional["NotebookDocumentCellChangeStructure"] = attrs.field( + default=None + ) + """Changes to the cell structure to add or + remove cells.""" + + data: Optional[Sequence[NotebookCell]] = attrs.field(default=None) + """Changes to notebook cells properties like its + kind, execution summary or metadata.""" + + text_content: Optional[Sequence["NotebookDocumentCellContentChanges"]] = ( + attrs.field(default=None) + ) + """Changes to the text content of notebook cells.""" @attrs.define @@ -6604,6 +6925,27 @@ class SelectedCompletionInfo: """The text the range will be replaced with if this completion is accepted.""" +@attrs.define +class ClientInfo: + """Information about the client + + @since 3.15.0 + @since 3.18.0 ClientInfo type name added.""" + + # Since: + # 3.15.0 + # 3.18.0 ClientInfo type name added. + + name: str = attrs.field(validator=attrs.validators.instance_of(str)) + """The name of the client as defined by the client.""" + + version: Optional[str] = attrs.field( + validator=attrs.validators.optional(attrs.validators.instance_of(str)), + default=None, + ) + """The client's version as defined by the client.""" + + @attrs.define class ClientCapabilities: """Defines the capabilities provided by the client.""" @@ -6670,185 +7012,66 @@ class TextDocumentSyncOptions: @attrs.define -class NotebookDocumentSyncOptionsNotebookSelectorType1CellsType: - language: str = attrs.field(validator=attrs.validators.instance_of(str)) +class WorkspaceOptions: + """Defines workspace specific capabilities of the server. + @since 3.18.0""" -@attrs.define -class NotebookDocumentSyncOptionsNotebookSelectorType1: - notebook: Union[str, NotebookDocumentFilter] = attrs.field() - """The notebook to be synced If a string - value is provided it matches against the - notebook type. '*' matches every notebook.""" + # Since: 3.18.0 - cells: Optional[ - List["NotebookDocumentSyncOptionsNotebookSelectorType1CellsType"] - ] = attrs.field(default=None) - """The cells of the matching notebook to be synced.""" - - -@attrs.define -class NotebookDocumentSyncOptionsNotebookSelectorType2CellsType: - language: str = attrs.field(validator=attrs.validators.instance_of(str)) - - -@attrs.define -class NotebookDocumentSyncOptionsNotebookSelectorType2: - cells: List[ - "NotebookDocumentSyncOptionsNotebookSelectorType2CellsType" - ] = attrs.field() - """The cells of the matching notebook to be synced.""" - - notebook: Optional[Union[str, NotebookDocumentFilter]] = attrs.field(default=None) - """The notebook to be synced If a string - value is provided it matches against the - notebook type. '*' matches every notebook.""" - - -@attrs.define -class NotebookDocumentSyncOptions: - """Options specific to a notebook plus its cells - to be synced to the server. - - If a selector provides a notebook document - filter but no cell selector all cells of a - matching notebook document will be synced. - - If a selector provides no notebook document - filter but only a cell selector all notebook - document that contain at least one matching - cell will be synced. - - @since 3.17.0""" - - # Since: 3.17.0 - - notebook_selector: List[ - Union[ - "NotebookDocumentSyncOptionsNotebookSelectorType1", - "NotebookDocumentSyncOptionsNotebookSelectorType2", - ] - ] = attrs.field() - """The notebooks to be synced""" - - save: Optional[bool] = attrs.field( - validator=attrs.validators.optional(attrs.validators.instance_of(bool)), - default=None, + workspace_folders: Optional["WorkspaceFoldersServerCapabilities"] = attrs.field( + default=None ) - """Whether save notification should be forwarded to - the server. Will only be honored if mode === `notebook`.""" - - -@attrs.define -class NotebookDocumentSyncRegistrationOptionsNotebookSelectorType1CellsType: - language: str = attrs.field(validator=attrs.validators.instance_of(str)) - - -@attrs.define -class NotebookDocumentSyncRegistrationOptionsNotebookSelectorType1: - notebook: Union[str, NotebookDocumentFilter] = attrs.field() - """The notebook to be synced If a string - value is provided it matches against the - notebook type. '*' matches every notebook.""" - - cells: Optional[ - List["NotebookDocumentSyncRegistrationOptionsNotebookSelectorType1CellsType"] - ] = attrs.field(default=None) - """The cells of the matching notebook to be synced.""" - - -@attrs.define -class NotebookDocumentSyncRegistrationOptionsNotebookSelectorType2CellsType: - language: str = attrs.field(validator=attrs.validators.instance_of(str)) - - -@attrs.define -class NotebookDocumentSyncRegistrationOptionsNotebookSelectorType2: - cells: List[ - "NotebookDocumentSyncRegistrationOptionsNotebookSelectorType2CellsType" - ] = attrs.field() - """The cells of the matching notebook to be synced.""" - - notebook: Optional[Union[str, NotebookDocumentFilter]] = attrs.field(default=None) - """The notebook to be synced If a string - value is provided it matches against the - notebook type. '*' matches every notebook.""" - - -@attrs.define -class NotebookDocumentSyncRegistrationOptions: - """Registration options specific to a notebook. - - @since 3.17.0""" - - # Since: 3.17.0 - - notebook_selector: List[ - Union[ - "NotebookDocumentSyncRegistrationOptionsNotebookSelectorType1", - "NotebookDocumentSyncRegistrationOptionsNotebookSelectorType2", - ] - ] = attrs.field() - """The notebooks to be synced""" - - save: Optional[bool] = attrs.field( - validator=attrs.validators.optional(attrs.validators.instance_of(bool)), - default=None, - ) - """Whether save notification should be forwarded to - the server. Will only be honored if mode === `notebook`.""" - - id: Optional[str] = attrs.field( - validator=attrs.validators.optional(attrs.validators.instance_of(str)), - default=None, - ) - """The id used to register the request. The id can be used to deregister - the request again. See also Registration#id.""" - - -@attrs.define -class WorkspaceFoldersServerCapabilities: - supported: Optional[bool] = attrs.field( - validator=attrs.validators.optional(attrs.validators.instance_of(bool)), - default=None, - ) - """The server has support for workspace folders""" - - change_notifications: Optional[Union[str, bool]] = attrs.field(default=None) - """Whether the server wants to receive workspace folder - change notifications. + """The server supports workspace folder. - If a string is provided the string is treated as an ID - under which the notification is registered on the client - side. The ID can be used to unregister for these events - using the `client/unregisterCapability` request.""" - - -@attrs.define -class FileOperationOptions: - """Options for notifications/requests for user operations on files. + @since 3.6.0""" + # Since: 3.6.0 + file_operations: Optional["FileOperationOptions"] = attrs.field(default=None) + """The server is interested in notifications/requests for operations on files. + @since 3.16.0""" - # Since: 3.16.0 - did_create: Optional[FileOperationRegistrationOptions] = attrs.field(default=None) - """The server is interested in receiving didCreateFiles notifications.""" + text_document_content: Optional[ + Union[TextDocumentContentOptions, TextDocumentContentRegistrationOptions] + ] = attrs.field(default=None) + """The server supports the `workspace/textDocumentContent` request. + + @since 3.18.0 + @proposed""" + # Since: 3.18.0 + # Proposed - will_create: Optional[FileOperationRegistrationOptions] = attrs.field(default=None) - """The server is interested in receiving willCreateFiles requests.""" - did_rename: Optional[FileOperationRegistrationOptions] = attrs.field(default=None) - """The server is interested in receiving didRenameFiles notifications.""" +@attrs.define +class TextDocumentContentChangePartial: + """@since 3.18.0""" - will_rename: Optional[FileOperationRegistrationOptions] = attrs.field(default=None) - """The server is interested in receiving willRenameFiles requests.""" + # Since: 3.18.0 - did_delete: Optional[FileOperationRegistrationOptions] = attrs.field(default=None) - """The server is interested in receiving didDeleteFiles file notifications.""" + range: Range = attrs.field() + """The range of the document that changed.""" - will_delete: Optional[FileOperationRegistrationOptions] = attrs.field(default=None) - """The server is interested in receiving willDeleteFiles file requests.""" + text: str = attrs.field(validator=attrs.validators.instance_of(str)) + """The new text for the provided range.""" + + range_length: Optional[int] = attrs.field( + validator=attrs.validators.optional(validators.uinteger_validator), default=None + ) + """The optional length of the range that got replaced. + + @deprecated use range instead.""" + + +@attrs.define +class TextDocumentContentChangeWholeDocument: + """@since 3.18.0""" + + # Since: 3.18.0 + + text: str = attrs.field(validator=attrs.validators.instance_of(str)) + """The new text of the whole document.""" @attrs.define @@ -6876,6 +7099,49 @@ class DiagnosticRelatedInformation: """The message of this related diagnostic information.""" +@attrs.define +class EditRangeWithInsertReplace: + """Edit range variant that includes ranges for insert and replace operations. + + @since 3.18.0""" + + # Since: 3.18.0 + + insert: Range = attrs.field() + + replace: Range = attrs.field() + + +@attrs.define +class ServerCompletionItemOptions: + """@since 3.18.0""" + + # Since: 3.18.0 + + label_details_support: Optional[bool] = attrs.field( + validator=attrs.validators.optional(attrs.validators.instance_of(bool)), + default=None, + ) + """The server has support for completion item label + details (see also `CompletionItemLabelDetails`) when + receiving a completion item in a resolve call. + + @since 3.17.0""" + # Since: 3.17.0 + + +@attrs.define +class MarkedStringWithLanguage: + """@since 3.18.0 + @deprecated use MarkupContent instead.""" + + # Since: 3.18.0 + + language: str = attrs.field(validator=attrs.validators.instance_of(str)) + + value: str = attrs.field(validator=attrs.validators.instance_of(str)) + + @attrs.define class ParameterInformation: """Represents a parameter of a callable-signature. A parameter can @@ -6888,6 +7154,10 @@ class ParameterInformation: signature label. (see SignatureInformation.label). The offsets are based on a UTF-16 string representation as `Position` and `Range` does. + To avoid ambiguities a server should use the [start, end] offset value instead of using + a substring. Whether a client support this is controlled via `labelOffsetSupport` client + capability. + *Note*: a label of type string should be a substring of its containing signature label. Its intended use case is to highlight the parameter label part in the `SignatureInformation.label`.""" @@ -6896,6 +7166,29 @@ class ParameterInformation: in the UI but can be omitted.""" +@attrs.define +class CodeActionKindDocumentation: + """Documentation for a class of code actions. + + @since 3.18.0 + @proposed""" + + # Since: 3.18.0 + # Proposed + + kind: Union[CodeActionKind, str] = attrs.field() + """The kind of the code action being documented. + + If the kind is generic, such as `CodeActionKind.Refactor`, the documentation will be shown whenever any + refactorings are returned. If the kind if more specific, such as `CodeActionKind.RefactorExtract`, the + documentation will only be shown when extract refactoring code actions are returned.""" + + command: Command = attrs.field() + """Command that is ued to display the documentation to the user. + + The title of this documentation code action is taken from {@linkcode Command.title}""" + + @attrs.define class NotebookCellTextDocumentFilter: """A notebook cell text document filter denotes a cell text @@ -6951,6 +7244,46 @@ class ExecutionSummary: not if known by the client.""" +@attrs.define +class NotebookCellLanguage: + """@since 3.18.0""" + + # Since: 3.18.0 + + language: str = attrs.field(validator=attrs.validators.instance_of(str)) + + +@attrs.define +class NotebookDocumentCellChangeStructure: + """Structural changes to cells in a notebook document. + + @since 3.18.0""" + + # Since: 3.18.0 + + array: "NotebookCellArrayChange" = attrs.field() + """The change to the cell array.""" + + did_open: Optional[Sequence[TextDocumentItem]] = attrs.field(default=None) + """Additional opened cell text documents.""" + + did_close: Optional[Sequence[TextDocumentIdentifier]] = attrs.field(default=None) + """Additional closed cell text documents.""" + + +@attrs.define +class NotebookDocumentCellContentChanges: + """Content changes to a cell in a notebook document. + + @since 3.18.0""" + + # Since: 3.18.0 + + document: VersionedTextDocumentIdentifier = attrs.field() + + changes: Sequence[TextDocumentContentChangeEvent] = attrs.field() + + @attrs.define class WorkspaceClientCapabilities: """Workspace specific client capabilities.""" @@ -6968,14 +7301,14 @@ class WorkspaceClientCapabilities: ) """Capabilities specific to `WorkspaceEdit`s.""" - did_change_configuration: Optional[ - "DidChangeConfigurationClientCapabilities" - ] = attrs.field(default=None) + did_change_configuration: Optional["DidChangeConfigurationClientCapabilities"] = ( + attrs.field(default=None) + ) """Capabilities specific to the `workspace/didChangeConfiguration` notification.""" - did_change_watched_files: Optional[ - "DidChangeWatchedFilesClientCapabilities" - ] = attrs.field(default=None) + did_change_watched_files: Optional["DidChangeWatchedFilesClientCapabilities"] = ( + attrs.field(default=None) + ) """Capabilities specific to the `workspace/didChangeWatchedFiles` notification.""" symbol: Optional["WorkspaceSymbolClientCapabilities"] = attrs.field(default=None) @@ -7004,9 +7337,9 @@ class WorkspaceClientCapabilities: @since 3.6.0""" # Since: 3.6.0 - semantic_tokens: Optional[ - "SemanticTokensWorkspaceClientCapabilities" - ] = attrs.field(default=None) + semantic_tokens: Optional["SemanticTokensWorkspaceClientCapabilities"] = ( + attrs.field(default=None) + ) """Capabilities specific to the semantic token requests scoped to the workspace. @@ -7066,6 +7399,16 @@ class WorkspaceClientCapabilities: # Since: 3.18.0 # Proposed + text_document_content: Optional["TextDocumentContentClientCapabilities"] = ( + attrs.field(default=None) + ) + """Capabilities specific to the `workspace/textDocumentContent` request. + + @since 3.18.0 + @proposed""" + # Since: 3.18.0 + # Proposed + @attrs.define class TextDocumentClientCapabilities: @@ -7076,6 +7419,14 @@ class TextDocumentClientCapabilities: ) """Defines which synchronization capabilities the client supports.""" + filters: Optional["TextDocumentFilterClientCapabilities"] = attrs.field( + default=None + ) + """Defines which filters the client supports. + + @since 3.18.0""" + # Since: 3.18.0 + completion: Optional["CompletionClientCapabilities"] = attrs.field(default=None) """Capabilities specific to the `textDocument/completion` request.""" @@ -7150,14 +7501,14 @@ class TextDocumentClientCapabilities: ) """Capabilities specific to the `textDocument/formatting` request.""" - range_formatting: Optional[ - "DocumentRangeFormattingClientCapabilities" - ] = attrs.field(default=None) + range_formatting: Optional["DocumentRangeFormattingClientCapabilities"] = ( + attrs.field(default=None) + ) """Capabilities specific to the `textDocument/rangeFormatting` request.""" - on_type_formatting: Optional[ - "DocumentOnTypeFormattingClientCapabilities" - ] = attrs.field(default=None) + on_type_formatting: Optional["DocumentOnTypeFormattingClientCapabilities"] = ( + attrs.field(default=None) + ) """Capabilities specific to the `textDocument/onTypeFormatting` request.""" rename: Optional["RenameClientCapabilities"] = attrs.field(default=None) @@ -7200,9 +7551,9 @@ class TextDocumentClientCapabilities: @since 3.16.0""" # Since: 3.16.0 - linked_editing_range: Optional[ - "LinkedEditingRangeClientCapabilities" - ] = attrs.field(default=None) + linked_editing_range: Optional["LinkedEditingRangeClientCapabilities"] = ( + attrs.field(default=None) + ) """Capabilities specific to the `textDocument/linkedEditingRange` request. @since 3.16.0""" @@ -7300,17 +7651,6 @@ class WindowClientCapabilities: # Since: 3.16.0 -@attrs.define -class GeneralClientCapabilitiesStaleRequestSupportType: - cancel: bool = attrs.field(validator=attrs.validators.instance_of(bool)) - """The client will actively cancel the request.""" - - retry_on_content_modified: List[str] = attrs.field() - """The list of requests for which the client - will retry the request if it receives a - response with error code `ContentModified`""" - - @attrs.define class GeneralClientCapabilities: """General client capabilities. @@ -7319,9 +7659,9 @@ class GeneralClientCapabilities: # Since: 3.16.0 - stale_request_support: Optional[ - "GeneralClientCapabilitiesStaleRequestSupportType" - ] = attrs.field(default=None) + stale_request_support: Optional["StaleRequestSupportOptions"] = attrs.field( + default=None + ) """Client capability that signals how the client handles stale requests (e.g. a request for which the client will not process the response @@ -7344,8 +7684,8 @@ class GeneralClientCapabilities: @since 3.16.0""" # Since: 3.16.0 - position_encodings: Optional[List[Union[PositionEncodingKind, str]]] = attrs.field( - default=None + position_encodings: Optional[Sequence[Union[PositionEncodingKind, str]]] = ( + attrs.field(default=None) ) """The position encodings supported by the client. Client and server have to agree on the same position encoding to ensure that offsets @@ -7368,6 +7708,51 @@ class GeneralClientCapabilities: # Since: 3.17.0 +@attrs.define +class WorkspaceFoldersServerCapabilities: + supported: Optional[bool] = attrs.field( + validator=attrs.validators.optional(attrs.validators.instance_of(bool)), + default=None, + ) + """The server has support for workspace folders""" + + change_notifications: Optional[Union[str, bool]] = attrs.field(default=None) + """Whether the server wants to receive workspace folder + change notifications. + + If a string is provided the string is treated as an ID + under which the notification is registered on the client + side. The ID can be used to unregister for these events + using the `client/unregisterCapability` request.""" + + +@attrs.define +class FileOperationOptions: + """Options for notifications/requests for user operations on files. + + @since 3.16.0""" + + # Since: 3.16.0 + + did_create: Optional[FileOperationRegistrationOptions] = attrs.field(default=None) + """The server is interested in receiving didCreateFiles notifications.""" + + will_create: Optional[FileOperationRegistrationOptions] = attrs.field(default=None) + """The server is interested in receiving willCreateFiles requests.""" + + did_rename: Optional[FileOperationRegistrationOptions] = attrs.field(default=None) + """The server is interested in receiving didRenameFiles notifications.""" + + will_rename: Optional[FileOperationRegistrationOptions] = attrs.field(default=None) + """The server is interested in receiving willRenameFiles requests.""" + + did_delete: Optional[FileOperationRegistrationOptions] = attrs.field(default=None) + """The server is interested in receiving didDeleteFiles file notifications.""" + + will_delete: Optional[FileOperationRegistrationOptions] = attrs.field(default=None) + """The server is interested in receiving willDeleteFiles file requests.""" + + @attrs.define class RelativePattern: """A relative pattern is a helper to construct glob patterns that are matched @@ -7387,14 +7772,169 @@ class RelativePattern: @attrs.define -class WorkspaceEditClientCapabilitiesChangeAnnotationSupportType: - groups_on_label: Optional[bool] = attrs.field( - validator=attrs.validators.optional(attrs.validators.instance_of(bool)), +class TextDocumentFilterLanguage: + """A document filter where `language` is required field. + + @since 3.18.0""" + + # Since: 3.18.0 + + language: str = attrs.field(validator=attrs.validators.instance_of(str)) + """A language id, like `typescript`.""" + + scheme: Optional[str] = attrs.field( + validator=attrs.validators.optional(attrs.validators.instance_of(str)), default=None, ) - """Whether the client groups edits with equal labels into tree nodes, - for instance all edits labelled with "Changes in Strings" would - be a tree node.""" + """A Uri {@link Uri.scheme scheme}, like `file` or `untitled`.""" + + pattern: Optional[GlobPattern] = attrs.field(default=None) + """A glob pattern, like **/*.{ts,js}. See TextDocumentFilter for examples. + + @since 3.18.0 - support for relative patterns. Whether clients support + relative patterns depends on the client capability + `textDocuments.filters.relativePatternSupport`.""" + # Since: 3.18.0 - support for relative patterns. Whether clients support relative patterns depends on the client capability `textDocuments.filters.relativePatternSupport`. + + +@attrs.define +class TextDocumentFilterScheme: + """A document filter where `scheme` is required field. + + @since 3.18.0""" + + # Since: 3.18.0 + + scheme: str = attrs.field(validator=attrs.validators.instance_of(str)) + """A Uri {@link Uri.scheme scheme}, like `file` or `untitled`.""" + + language: Optional[str] = attrs.field( + validator=attrs.validators.optional(attrs.validators.instance_of(str)), + default=None, + ) + """A language id, like `typescript`.""" + + pattern: Optional[GlobPattern] = attrs.field(default=None) + """A glob pattern, like **/*.{ts,js}. See TextDocumentFilter for examples. + + @since 3.18.0 - support for relative patterns. Whether clients support + relative patterns depends on the client capability + `textDocuments.filters.relativePatternSupport`.""" + # Since: 3.18.0 - support for relative patterns. Whether clients support relative patterns depends on the client capability `textDocuments.filters.relativePatternSupport`. + + +@attrs.define +class TextDocumentFilterPattern: + """A document filter where `pattern` is required field. + + @since 3.18.0""" + + # Since: 3.18.0 + + pattern: GlobPattern = attrs.field() + """A glob pattern, like **/*.{ts,js}. See TextDocumentFilter for examples. + + @since 3.18.0 - support for relative patterns. Whether clients support + relative patterns depends on the client capability + `textDocuments.filters.relativePatternSupport`.""" + # Since: 3.18.0 - support for relative patterns. Whether clients support relative patterns depends on the client capability `textDocuments.filters.relativePatternSupport`. + + language: Optional[str] = attrs.field( + validator=attrs.validators.optional(attrs.validators.instance_of(str)), + default=None, + ) + """A language id, like `typescript`.""" + + scheme: Optional[str] = attrs.field( + validator=attrs.validators.optional(attrs.validators.instance_of(str)), + default=None, + ) + """A Uri {@link Uri.scheme scheme}, like `file` or `untitled`.""" + + +@attrs.define +class NotebookDocumentFilterNotebookType: + """A notebook document filter where `notebookType` is required field. + + @since 3.18.0""" + + # Since: 3.18.0 + + notebook_type: str = attrs.field(validator=attrs.validators.instance_of(str)) + """The type of the enclosing notebook.""" + + scheme: Optional[str] = attrs.field( + validator=attrs.validators.optional(attrs.validators.instance_of(str)), + default=None, + ) + """A Uri {@link Uri.scheme scheme}, like `file` or `untitled`.""" + + pattern: Optional[GlobPattern] = attrs.field(default=None) + """A glob pattern.""" + + +@attrs.define +class NotebookDocumentFilterScheme: + """A notebook document filter where `scheme` is required field. + + @since 3.18.0""" + + # Since: 3.18.0 + + scheme: str = attrs.field(validator=attrs.validators.instance_of(str)) + """A Uri {@link Uri.scheme scheme}, like `file` or `untitled`.""" + + notebook_type: Optional[str] = attrs.field( + validator=attrs.validators.optional(attrs.validators.instance_of(str)), + default=None, + ) + """The type of the enclosing notebook.""" + + pattern: Optional[GlobPattern] = attrs.field(default=None) + """A glob pattern.""" + + +@attrs.define +class NotebookDocumentFilterPattern: + """A notebook document filter where `pattern` is required field. + + @since 3.18.0""" + + # Since: 3.18.0 + + pattern: GlobPattern = attrs.field() + """A glob pattern.""" + + notebook_type: Optional[str] = attrs.field( + validator=attrs.validators.optional(attrs.validators.instance_of(str)), + default=None, + ) + """The type of the enclosing notebook.""" + + scheme: Optional[str] = attrs.field( + validator=attrs.validators.optional(attrs.validators.instance_of(str)), + default=None, + ) + """A Uri {@link Uri.scheme scheme}, like `file` or `untitled`.""" + + +@attrs.define +class NotebookCellArrayChange: + """A change describing how to move a `NotebookCell` + array from state S to S'. + + @since 3.17.0""" + + # Since: 3.17.0 + + start: int = attrs.field(validator=validators.uinteger_validator) + """The start oftest of the cell that changed.""" + + delete_count: int = attrs.field(validator=validators.uinteger_validator) + """The deleted cells""" + + cells: Optional[Sequence[NotebookCell]] = attrs.field(default=None) + """The new cells, if any""" @attrs.define @@ -7405,7 +7945,7 @@ class WorkspaceEditClientCapabilities: ) """The client supports versioned document changes in `WorkspaceEdit`s""" - resource_operations: Optional[List[ResourceOperationKind]] = attrs.field( + resource_operations: Optional[Sequence[ResourceOperationKind]] = attrs.field( default=None ) """The resource operations the client supports. Clients should at least @@ -7434,15 +7974,37 @@ class WorkspaceEditClientCapabilities: @since 3.16.0""" # Since: 3.16.0 - change_annotation_support: Optional[ - "WorkspaceEditClientCapabilitiesChangeAnnotationSupportType" - ] = attrs.field(default=None) + change_annotation_support: Optional["ChangeAnnotationsSupportOptions"] = ( + attrs.field(default=None) + ) """Whether the client in general supports change annotations on text edits, create file, rename file and delete file changes. @since 3.16.0""" # Since: 3.16.0 + metadata_support: Optional[bool] = attrs.field( + validator=attrs.validators.optional(attrs.validators.instance_of(bool)), + default=None, + ) + """Whether the client supports `WorkspaceEditMetadata` in `WorkspaceEdit`s. + + @since 3.18.0 + @proposed""" + # Since: 3.18.0 + # Proposed + + snippet_edit_support: Optional[bool] = attrs.field( + validator=attrs.validators.optional(attrs.validators.instance_of(bool)), + default=None, + ) + """Whether the client supports snippets as text edits. + + @since 3.18.0 + @proposed""" + # Since: 3.18.0 + # Proposed + @attrs.define class DidChangeConfigurationClientCapabilities: @@ -7474,32 +8036,6 @@ class DidChangeWatchedFilesClientCapabilities: # Since: 3.17.0 -@attrs.define -class WorkspaceSymbolClientCapabilitiesSymbolKindType: - value_set: Optional[List[SymbolKind]] = attrs.field(default=None) - """The symbol kind values the client supports. When this - property exists the client also guarantees that it will - handle values outside its set gracefully and falls back - to a default value when unknown. - - If this property is not present the client only supports - the symbol kinds from `File` to `Array` as defined in - the initial version of the protocol.""" - - -@attrs.define -class WorkspaceSymbolClientCapabilitiesTagSupportType: - value_set: List[SymbolTag] = attrs.field() - """The tags supported by the client.""" - - -@attrs.define -class WorkspaceSymbolClientCapabilitiesResolveSupportType: - properties: List[str] = attrs.field() - """The properties that a client can resolve lazily. Usually - `location.range`""" - - @attrs.define class WorkspaceSymbolClientCapabilities: """Client capabilities for a {@link WorkspaceSymbolRequest}.""" @@ -7510,23 +8046,17 @@ class WorkspaceSymbolClientCapabilities: ) """Symbol request supports dynamic registration.""" - symbol_kind: Optional[ - "WorkspaceSymbolClientCapabilitiesSymbolKindType" - ] = attrs.field(default=None) + symbol_kind: Optional["ClientSymbolKindOptions"] = attrs.field(default=None) """Specific capabilities for the `SymbolKind` in the `workspace/symbol` request.""" - tag_support: Optional[ - "WorkspaceSymbolClientCapabilitiesTagSupportType" - ] = attrs.field(default=None) + tag_support: Optional["ClientSymbolTagOptions"] = attrs.field(default=None) """The client supports tags on `SymbolInformation`. Clients supporting tags have to handle unknown tags gracefully. @since 3.16.0""" # Since: 3.16.0 - resolve_support: Optional[ - "WorkspaceSymbolClientCapabilitiesResolveSupportType" - ] = attrs.field(default=None) + resolve_support: Optional["ClientSymbolResolveOptions"] = attrs.field(default=None) """The client support partial workspace symbols. The client will send the request `workspaceSymbol/resolve` to the server to resolve additional properties. @@ -7729,6 +8259,23 @@ class FoldingRangeWorkspaceClientCapabilities: # Proposed +@attrs.define +class TextDocumentContentClientCapabilities: + """Client capabilities for a text document content provider. + + @since 3.18.0 + @proposed""" + + # Since: 3.18.0 + # Proposed + + dynamic_registration: Optional[bool] = attrs.field( + validator=attrs.validators.optional(attrs.validators.instance_of(bool)), + default=None, + ) + """Text document content provider supports dynamic registration.""" + + @attrs.define class TextDocumentSyncClientCapabilities: dynamic_registration: Optional[bool] = attrs.field( @@ -7759,134 +8306,15 @@ class TextDocumentSyncClientCapabilities: @attrs.define -class CompletionClientCapabilitiesCompletionItemTypeTagSupportType: - value_set: List[CompletionItemTag] = attrs.field() - """The tags supported by the client.""" - - -@attrs.define -class CompletionClientCapabilitiesCompletionItemTypeResolveSupportType: - properties: List[str] = attrs.field() - """The properties that a client can resolve lazily.""" - - -@attrs.define -class CompletionClientCapabilitiesCompletionItemTypeInsertTextModeSupportType: - value_set: List[InsertTextMode] = attrs.field() - - -@attrs.define -class CompletionClientCapabilitiesCompletionItemType: - snippet_support: Optional[bool] = attrs.field( +class TextDocumentFilterClientCapabilities: + relative_pattern_support: Optional[bool] = attrs.field( validator=attrs.validators.optional(attrs.validators.instance_of(bool)), default=None, ) - """Client supports snippets as insert text. + """The client supports Relative Patterns. - A snippet can define tab stops and placeholders with `$1`, `$2` - and `${3:foo}`. `$0` defines the final tab stop, it defaults to - the end of the snippet. Placeholders with equal identifiers are linked, - that is typing in one will update others too.""" - - commit_characters_support: Optional[bool] = attrs.field( - validator=attrs.validators.optional(attrs.validators.instance_of(bool)), - default=None, - ) - """Client supports commit characters on a completion item.""" - - documentation_format: Optional[List[MarkupKind]] = attrs.field(default=None) - """Client supports the following content formats for the documentation - property. The order describes the preferred format of the client.""" - - deprecated_support: Optional[bool] = attrs.field( - validator=attrs.validators.optional(attrs.validators.instance_of(bool)), - default=None, - ) - """Client supports the deprecated property on a completion item.""" - - preselect_support: Optional[bool] = attrs.field( - validator=attrs.validators.optional(attrs.validators.instance_of(bool)), - default=None, - ) - """Client supports the preselect property on a completion item.""" - - tag_support: Optional[ - "CompletionClientCapabilitiesCompletionItemTypeTagSupportType" - ] = attrs.field(default=None) - """Client supports the tag property on a completion item. Clients supporting - tags have to handle unknown tags gracefully. Clients especially need to - preserve unknown tags when sending a completion item back to the server in - a resolve call. - - @since 3.15.0""" - # Since: 3.15.0 - - insert_replace_support: Optional[bool] = attrs.field( - validator=attrs.validators.optional(attrs.validators.instance_of(bool)), - default=None, - ) - """Client support insert replace edit to control different behavior if a - completion item is inserted in the text or should replace text. - - @since 3.16.0""" - # Since: 3.16.0 - - resolve_support: Optional[ - "CompletionClientCapabilitiesCompletionItemTypeResolveSupportType" - ] = attrs.field(default=None) - """Indicates which properties a client can resolve lazily on a completion - item. Before version 3.16.0 only the predefined properties `documentation` - and `details` could be resolved lazily. - - @since 3.16.0""" - # Since: 3.16.0 - - insert_text_mode_support: Optional[ - "CompletionClientCapabilitiesCompletionItemTypeInsertTextModeSupportType" - ] = attrs.field(default=None) - """The client supports the `insertTextMode` property on - a completion item to override the whitespace handling mode - as defined by the client (see `insertTextMode`). - - @since 3.16.0""" - # Since: 3.16.0 - - label_details_support: Optional[bool] = attrs.field( - validator=attrs.validators.optional(attrs.validators.instance_of(bool)), - default=None, - ) - """The client has support for completion item label - details (see also `CompletionItemLabelDetails`). - - @since 3.17.0""" - # Since: 3.17.0 - - -@attrs.define -class CompletionClientCapabilitiesCompletionItemKindType: - value_set: Optional[List[CompletionItemKind]] = attrs.field(default=None) - """The completion item kind values the client supports. When this - property exists the client also guarantees that it will - handle values outside its set gracefully and falls back - to a default value when unknown. - - If this property is not present the client only supports - the completion items kinds from `Text` to `Reference` as defined in - the initial version of the protocol.""" - - -@attrs.define -class CompletionClientCapabilitiesCompletionListType: - item_defaults: Optional[List[str]] = attrs.field(default=None) - """The client supports the following itemDefaults on - a completion list. - - The value lists the supported property names of the - `CompletionList.itemDefaults` object. If omitted - no properties are supported. - - @since 3.17.0""" - # Since: 3.17.0 + @since 3.18.0""" + # Since: 3.18.0 @attrs.define @@ -7899,15 +8327,13 @@ class CompletionClientCapabilities: ) """Whether completion supports dynamic registration.""" - completion_item: Optional[ - "CompletionClientCapabilitiesCompletionItemType" - ] = attrs.field(default=None) + completion_item: Optional["ClientCompletionItemOptions"] = attrs.field(default=None) """The client supports the following `CompletionItem` specific capabilities.""" - completion_item_kind: Optional[ - "CompletionClientCapabilitiesCompletionItemKindType" - ] = attrs.field(default=None) + completion_item_kind: Optional["ClientCompletionItemOptionsKind"] = attrs.field( + default=None + ) insert_text_mode: Optional[InsertTextMode] = attrs.field(default=None) """Defines how the client handles whitespace and indentation @@ -7924,9 +8350,7 @@ class CompletionClientCapabilities: """The client supports to send additional context information for a `textDocument/completion` request.""" - completion_list: Optional[ - "CompletionClientCapabilitiesCompletionListType" - ] = attrs.field(default=None) + completion_list: Optional["CompletionListCapabilities"] = attrs.field(default=None) """The client supports the following `CompletionList` specific capabilities. @@ -7942,46 +8366,11 @@ class HoverClientCapabilities: ) """Whether hover supports dynamic registration.""" - content_format: Optional[List[MarkupKind]] = attrs.field(default=None) + content_format: Optional[Sequence[MarkupKind]] = attrs.field(default=None) """Client supports the following content formats for the content property. The order describes the preferred format of the client.""" -@attrs.define -class SignatureHelpClientCapabilitiesSignatureInformationTypeParameterInformationType: - label_offset_support: Optional[bool] = attrs.field( - validator=attrs.validators.optional(attrs.validators.instance_of(bool)), - default=None, - ) - """The client supports processing label offsets instead of a - simple label string. - - @since 3.14.0""" - # Since: 3.14.0 - - -@attrs.define -class SignatureHelpClientCapabilitiesSignatureInformationType: - documentation_format: Optional[List[MarkupKind]] = attrs.field(default=None) - """Client supports the following content formats for the documentation - property. The order describes the preferred format of the client.""" - - parameter_information: Optional[ - "SignatureHelpClientCapabilitiesSignatureInformationTypeParameterInformationType" - ] = attrs.field(default=None) - """Client capabilities specific to parameter information.""" - - active_parameter_support: Optional[bool] = attrs.field( - validator=attrs.validators.optional(attrs.validators.instance_of(bool)), - default=None, - ) - """The client supports the `activeParameter` property on `SignatureInformation` - literal. - - @since 3.16.0""" - # Since: 3.16.0 - - @attrs.define class SignatureHelpClientCapabilities: """Client Capabilities for a {@link SignatureHelpRequest}.""" @@ -7992,9 +8381,9 @@ class SignatureHelpClientCapabilities: ) """Whether signature help supports dynamic registration.""" - signature_information: Optional[ - "SignatureHelpClientCapabilitiesSignatureInformationType" - ] = attrs.field(default=None) + signature_information: Optional["ClientSignatureInformationOptions"] = attrs.field( + default=None + ) """The client supports the following `SignatureInformation` specific properties.""" @@ -8119,25 +8508,6 @@ class DocumentHighlightClientCapabilities: """Whether document highlight supports dynamic registration.""" -@attrs.define -class DocumentSymbolClientCapabilitiesSymbolKindType: - value_set: Optional[List[SymbolKind]] = attrs.field(default=None) - """The symbol kind values the client supports. When this - property exists the client also guarantees that it will - handle values outside its set gracefully and falls back - to a default value when unknown. - - If this property is not present the client only supports - the symbol kinds from `File` to `Array` as defined in - the initial version of the protocol.""" - - -@attrs.define -class DocumentSymbolClientCapabilitiesTagSupportType: - value_set: List[SymbolTag] = attrs.field() - """The tags supported by the client.""" - - @attrs.define class DocumentSymbolClientCapabilities: """Client Capabilities for a {@link DocumentSymbolRequest}.""" @@ -8148,9 +8518,7 @@ class DocumentSymbolClientCapabilities: ) """Whether document symbol supports dynamic registration.""" - symbol_kind: Optional[ - "DocumentSymbolClientCapabilitiesSymbolKindType" - ] = attrs.field(default=None) + symbol_kind: Optional["ClientSymbolKindOptions"] = attrs.field(default=None) """Specific capabilities for the `SymbolKind` in the `textDocument/documentSymbol` request.""" @@ -8160,9 +8528,7 @@ class DocumentSymbolClientCapabilities: ) """The client supports hierarchical document symbols.""" - tag_support: Optional[ - "DocumentSymbolClientCapabilitiesTagSupportType" - ] = attrs.field(default=None) + tag_support: Optional["ClientSymbolTagOptions"] = attrs.field(default=None) """The client supports tags on `SymbolInformation`. Tags are supported on `DocumentSymbol` if `hierarchicalDocumentSymbolSupport` is set to true. Clients supporting tags have to handle unknown tags gracefully. @@ -8181,30 +8547,6 @@ class DocumentSymbolClientCapabilities: # Since: 3.16.0 -@attrs.define -class CodeActionClientCapabilitiesCodeActionLiteralSupportTypeCodeActionKindType: - value_set: List[Union[CodeActionKind, str]] = attrs.field() - """The code action kind values the client supports. When this - property exists the client also guarantees that it will - handle values outside its set gracefully and falls back - to a default value when unknown.""" - - -@attrs.define -class CodeActionClientCapabilitiesCodeActionLiteralSupportType: - code_action_kind: "CodeActionClientCapabilitiesCodeActionLiteralSupportTypeCodeActionKindType" = ( - attrs.field() - ) - """The code action kind is support with the following value - set.""" - - -@attrs.define -class CodeActionClientCapabilitiesResolveSupportType: - properties: List[str] = attrs.field() - """The properties that a client can resolve lazily.""" - - @attrs.define class CodeActionClientCapabilities: """The Client Capabilities of a {@link CodeActionRequest}.""" @@ -8215,9 +8557,9 @@ class CodeActionClientCapabilities: ) """Whether code action supports dynamic registration.""" - code_action_literal_support: Optional[ - "CodeActionClientCapabilitiesCodeActionLiteralSupportType" - ] = attrs.field(default=None) + code_action_literal_support: Optional["ClientCodeActionLiteralOptions"] = ( + attrs.field(default=None) + ) """The client support code action literals of type `CodeAction` as a valid response of the `textDocument/codeAction` request. If the property is not set the request can only return `Command` literals. @@ -8254,9 +8596,9 @@ class CodeActionClientCapabilities: @since 3.16.0""" # Since: 3.16.0 - resolve_support: Optional[ - "CodeActionClientCapabilitiesResolveSupportType" - ] = attrs.field(default=None) + resolve_support: Optional["ClientCodeActionResolveOptions"] = attrs.field( + default=None + ) """Whether the client supports resolving additional code action properties via a separate `codeAction/resolve` request. @@ -8276,6 +8618,25 @@ class CodeActionClientCapabilities: @since 3.16.0""" # Since: 3.16.0 + documentation_support: Optional[bool] = attrs.field( + validator=attrs.validators.optional(attrs.validators.instance_of(bool)), + default=None, + ) + """Whether the client supports documentation for a class of + code actions. + + @since 3.18.0 + @proposed""" + # Since: 3.18.0 + # Proposed + + tag_support: Optional["CodeActionTagOptions"] = attrs.field(default=None) + """Client supports the tag property on a code action. Clients + supporting tags have to handle unknown tags gracefully. + + @since 3.18.0 - proposed""" + # Since: 3.18.0 - proposed + @attrs.define class CodeLensClientCapabilities: @@ -8287,6 +8648,15 @@ class CodeLensClientCapabilities: ) """Whether code lens supports dynamic registration.""" + resolve_support: Optional["ClientCodeLensResolveOptions"] = attrs.field( + default=None + ) + """Whether the client supports resolving additional code lens + properties via a separate `codeLens/resolve` request. + + @since 3.18.0""" + # Since: 3.18.0 + @attrs.define class DocumentLinkClientCapabilities: @@ -8381,9 +8751,9 @@ class RenameClientCapabilities: @since 3.12.0""" # Since: 3.12.0 - prepare_support_default_behavior: Optional[ - PrepareSupportDefaultBehavior - ] = attrs.field(default=None) + prepare_support_default_behavior: Optional[PrepareSupportDefaultBehavior] = ( + attrs.field(default=None) + ) """Client supports the default behavior result. The value indicates the default behavior used by the @@ -8406,28 +8776,6 @@ class RenameClientCapabilities: # Since: 3.16.0 -@attrs.define -class FoldingRangeClientCapabilitiesFoldingRangeKindType: - value_set: Optional[List[Union[FoldingRangeKind, str]]] = attrs.field(default=None) - """The folding range kind values the client supports. When this - property exists the client also guarantees that it will - handle values outside its set gracefully and falls back - to a default value when unknown.""" - - -@attrs.define -class FoldingRangeClientCapabilitiesFoldingRangeType: - collapsed_text: Optional[bool] = attrs.field( - validator=attrs.validators.optional(attrs.validators.instance_of(bool)), - default=None, - ) - """If set, the client signals that it supports setting collapsedText on - folding ranges to display custom labels instead of the default text. - - @since 3.17.0""" - # Since: 3.17.0 - - @attrs.define class FoldingRangeClientCapabilities: dynamic_registration: Optional[bool] = attrs.field( @@ -8454,17 +8802,15 @@ class FoldingRangeClientCapabilities: If set, client will ignore specified `startCharacter` and `endCharacter` properties in a FoldingRange.""" - folding_range_kind: Optional[ - "FoldingRangeClientCapabilitiesFoldingRangeKindType" - ] = attrs.field(default=None) + folding_range_kind: Optional["ClientFoldingRangeKindOptions"] = attrs.field( + default=None + ) """Specific options for the folding range kind. @since 3.17.0""" # Since: 3.17.0 - folding_range: Optional[ - "FoldingRangeClientCapabilitiesFoldingRangeType" - ] = attrs.field(default=None) + folding_range: Optional["ClientFoldingRangeOptions"] = attrs.field(default=None) """Specific options for the folding range. @since 3.17.0""" @@ -8483,14 +8829,8 @@ class SelectionRangeClientCapabilities: @attrs.define -class PublishDiagnosticsClientCapabilitiesTagSupportType: - value_set: List[DiagnosticTag] = attrs.field() - """The tags supported by the client.""" - - -@attrs.define -class PublishDiagnosticsClientCapabilities: - """The publish diagnostic client capabilities.""" +class DiagnosticsCapabilities: + """General diagnostics capabilities for pull and push model.""" related_information: Optional[bool] = attrs.field( validator=attrs.validators.optional(attrs.validators.instance_of(bool)), @@ -8498,15 +8838,38 @@ class PublishDiagnosticsClientCapabilities: ) """Whether the clients accepts diagnostics with related information.""" - tag_support: Optional[ - "PublishDiagnosticsClientCapabilitiesTagSupportType" - ] = attrs.field(default=None) + tag_support: Optional["ClientDiagnosticsTagOptions"] = attrs.field(default=None) """Client supports the tag property to provide meta data about a diagnostic. Clients supporting tags have to handle unknown tags gracefully. @since 3.15.0""" # Since: 3.15.0 + code_description_support: Optional[bool] = attrs.field( + validator=attrs.validators.optional(attrs.validators.instance_of(bool)), + default=None, + ) + """Client supports a codeDescription property + + @since 3.16.0""" + # Since: 3.16.0 + + data_support: Optional[bool] = attrs.field( + validator=attrs.validators.optional(attrs.validators.instance_of(bool)), + default=None, + ) + """Whether code action supports the `data` property which is + preserved between a `textDocument/publishDiagnostics` and + `textDocument/codeAction` request. + + @since 3.16.0""" + # Since: 3.16.0 + + +@attrs.define +class PublishDiagnosticsClientCapabilities: + """The publish diagnostic client capabilities.""" + version_support: Optional[bool] = attrs.field( validator=attrs.validators.optional(attrs.validators.instance_of(bool)), default=None, @@ -8517,6 +8880,19 @@ class PublishDiagnosticsClientCapabilities: @since 3.15.0""" # Since: 3.15.0 + related_information: Optional[bool] = attrs.field( + validator=attrs.validators.optional(attrs.validators.instance_of(bool)), + default=None, + ) + """Whether the clients accepts diagnostics with related information.""" + + tag_support: Optional["ClientDiagnosticsTagOptions"] = attrs.field(default=None) + """Client supports the tag property to provide meta data about a diagnostic. + Clients supporting tags have to handle unknown tags gracefully. + + @since 3.15.0""" + # Since: 3.15.0 + code_description_support: Optional[bool] = attrs.field( validator=attrs.validators.optional(attrs.validators.instance_of(bool)), default=None, @@ -8553,36 +8929,13 @@ class CallHierarchyClientCapabilities: return value for the corresponding server capability as well.""" -@attrs.define -class SemanticTokensClientCapabilitiesRequestsTypeFullType1: - delta: Optional[bool] = attrs.field( - validator=attrs.validators.optional(attrs.validators.instance_of(bool)), - default=None, - ) - """The client will send the `textDocument/semanticTokens/full/delta` request if - the server provides a corresponding handler.""" - - -@attrs.define -class SemanticTokensClientCapabilitiesRequestsType: - range: Optional[Union[bool, Any]] = attrs.field(default=None) - """The client will send the `textDocument/semanticTokens/range` request if - the server provides a corresponding handler.""" - - full: Optional[ - Union[bool, "SemanticTokensClientCapabilitiesRequestsTypeFullType1"] - ] = attrs.field(default=None) - """The client will send the `textDocument/semanticTokens/full` request if - the server provides a corresponding handler.""" - - @attrs.define class SemanticTokensClientCapabilities: """@since 3.16.0""" # Since: 3.16.0 - requests: "SemanticTokensClientCapabilitiesRequestsType" = attrs.field() + requests: "ClientSemanticTokensRequestOptions" = attrs.field() """Which requests the client supports and might send to the server depending on the server's capability. Please note that clients might not show semantic tokens or degrade some of the user experience if a range @@ -8592,13 +8945,13 @@ class SemanticTokensClientCapabilities: range provider the client might not render a minimap correctly or might even decide to not show any semantic tokens at all.""" - token_types: List[str] = attrs.field() + token_types: Sequence[str] = attrs.field() """The token types that the client supports.""" - token_modifiers: List[str] = attrs.field() + token_modifiers: Sequence[str] = attrs.field() """The token modifiers that the client supports.""" - formats: List[TokenFormat] = attrs.field() + formats: Sequence[TokenFormat] = attrs.field() """The token formats the clients supports.""" dynamic_registration: Optional[bool] = attrs.field( @@ -8714,12 +9067,6 @@ class InlineValueClientCapabilities: """Whether implementation supports dynamic registration for inline value providers.""" -@attrs.define -class InlayHintClientCapabilitiesResolveSupportType: - properties: List[str] = attrs.field() - """The properties that a client can resolve lazily.""" - - @attrs.define class InlayHintClientCapabilities: """Inlay hint client capabilities. @@ -8734,9 +9081,9 @@ class InlayHintClientCapabilities: ) """Whether inlay hints support dynamic registration.""" - resolve_support: Optional[ - "InlayHintClientCapabilitiesResolveSupportType" - ] = attrs.field(default=None) + resolve_support: Optional["ClientInlayHintResolveOptions"] = attrs.field( + default=None + ) """Indicates which properties a client can resolve lazily on an inlay hint.""" @@ -8763,6 +9110,39 @@ class DiagnosticClientCapabilities: ) """Whether the clients supports related documents for document diagnostic pulls.""" + related_information: Optional[bool] = attrs.field( + validator=attrs.validators.optional(attrs.validators.instance_of(bool)), + default=None, + ) + """Whether the clients accepts diagnostics with related information.""" + + tag_support: Optional["ClientDiagnosticsTagOptions"] = attrs.field(default=None) + """Client supports the tag property to provide meta data about a diagnostic. + Clients supporting tags have to handle unknown tags gracefully. + + @since 3.15.0""" + # Since: 3.15.0 + + code_description_support: Optional[bool] = attrs.field( + validator=attrs.validators.optional(attrs.validators.instance_of(bool)), + default=None, + ) + """Client supports a codeDescription property + + @since 3.16.0""" + # Since: 3.16.0 + + data_support: Optional[bool] = attrs.field( + validator=attrs.validators.optional(attrs.validators.instance_of(bool)), + default=None, + ) + """Whether code action supports the `data` property which is + preserved between a `textDocument/publishDiagnostics` and + `textDocument/codeAction` request. + + @since 3.16.0""" + # Since: 3.16.0 + @attrs.define class InlineCompletionClientCapabilities: @@ -8805,24 +9185,13 @@ class NotebookDocumentSyncClientCapabilities: """The client supports sending execution summary data per cell.""" -@attrs.define -class ShowMessageRequestClientCapabilitiesMessageActionItemType: - additional_properties_support: Optional[bool] = attrs.field( - validator=attrs.validators.optional(attrs.validators.instance_of(bool)), - default=None, - ) - """Whether the client supports additional attributes which - are preserved and send back to the server in the - request's response.""" - - @attrs.define class ShowMessageRequestClientCapabilities: """Show message request client capabilities""" - message_action_item: Optional[ - "ShowMessageRequestClientCapabilitiesMessageActionItemType" - ] = attrs.field(default=None) + message_action_item: Optional["ClientShowMessageActionItemOptions"] = attrs.field( + default=None + ) """Capabilities specific to the `MessageActionItem` type.""" @@ -8839,6 +9208,21 @@ class ShowDocumentClientCapabilities: request.""" +@attrs.define +class StaleRequestSupportOptions: + """@since 3.18.0""" + + # Since: 3.18.0 + + cancel: bool = attrs.field(validator=attrs.validators.instance_of(bool)) + """The client will actively cancel the request.""" + + retry_on_content_modified: Sequence[str] = attrs.field() + """The list of requests for which the client + will retry the request if it receives a + response with error code `ContentModified`""" + + @attrs.define class RegularExpressionsClientCapabilities: """Client capabilities specific to regular expressions. @@ -8847,7 +9231,7 @@ class RegularExpressionsClientCapabilities: # Since: 3.16.0 - engine: str = attrs.field(validator=attrs.validators.instance_of(str)) + engine: RegularExpressionEngineKind = attrs.field() """The engine's name.""" version: Optional[str] = attrs.field( @@ -8874,7 +9258,7 @@ class MarkdownClientCapabilities: ) """The version of the parser.""" - allowed_tags: Optional[List[str]] = attrs.field(default=None) + allowed_tags: Optional[Sequence[str]] = attrs.field(default=None) """A list of HTML tags that the client allows / supports in Markdown. @@ -8883,7 +9267,443 @@ class MarkdownClientCapabilities: @attrs.define -class TextDocumentColorPresentationOptions: +class ChangeAnnotationsSupportOptions: + """@since 3.18.0""" + + # Since: 3.18.0 + + groups_on_label: Optional[bool] = attrs.field( + validator=attrs.validators.optional(attrs.validators.instance_of(bool)), + default=None, + ) + """Whether the client groups edits with equal labels into tree nodes, + for instance all edits labelled with "Changes in Strings" would + be a tree node.""" + + +@attrs.define +class ClientSymbolKindOptions: + """@since 3.18.0""" + + # Since: 3.18.0 + + value_set: Optional[Sequence[SymbolKind]] = attrs.field(default=None) + """The symbol kind values the client supports. When this + property exists the client also guarantees that it will + handle values outside its set gracefully and falls back + to a default value when unknown. + + If this property is not present the client only supports + the symbol kinds from `File` to `Array` as defined in + the initial version of the protocol.""" + + +@attrs.define +class ClientSymbolTagOptions: + """@since 3.18.0""" + + # Since: 3.18.0 + + value_set: Sequence[SymbolTag] = attrs.field() + """The tags supported by the client.""" + + +@attrs.define +class ClientSymbolResolveOptions: + """@since 3.18.0""" + + # Since: 3.18.0 + + properties: Sequence[str] = attrs.field() + """The properties that a client can resolve lazily. Usually + `location.range`""" + + +@attrs.define +class ClientCompletionItemOptions: + """@since 3.18.0""" + + # Since: 3.18.0 + + snippet_support: Optional[bool] = attrs.field( + validator=attrs.validators.optional(attrs.validators.instance_of(bool)), + default=None, + ) + """Client supports snippets as insert text. + + A snippet can define tab stops and placeholders with `$1`, `$2` + and `${3:foo}`. `$0` defines the final tab stop, it defaults to + the end of the snippet. Placeholders with equal identifiers are linked, + that is typing in one will update others too.""" + + commit_characters_support: Optional[bool] = attrs.field( + validator=attrs.validators.optional(attrs.validators.instance_of(bool)), + default=None, + ) + """Client supports commit characters on a completion item.""" + + documentation_format: Optional[Sequence[MarkupKind]] = attrs.field(default=None) + """Client supports the following content formats for the documentation + property. The order describes the preferred format of the client.""" + + deprecated_support: Optional[bool] = attrs.field( + validator=attrs.validators.optional(attrs.validators.instance_of(bool)), + default=None, + ) + """Client supports the deprecated property on a completion item.""" + + preselect_support: Optional[bool] = attrs.field( + validator=attrs.validators.optional(attrs.validators.instance_of(bool)), + default=None, + ) + """Client supports the preselect property on a completion item.""" + + tag_support: Optional["CompletionItemTagOptions"] = attrs.field(default=None) + """Client supports the tag property on a completion item. Clients supporting + tags have to handle unknown tags gracefully. Clients especially need to + preserve unknown tags when sending a completion item back to the server in + a resolve call. + + @since 3.15.0""" + # Since: 3.15.0 + + insert_replace_support: Optional[bool] = attrs.field( + validator=attrs.validators.optional(attrs.validators.instance_of(bool)), + default=None, + ) + """Client support insert replace edit to control different behavior if a + completion item is inserted in the text or should replace text. + + @since 3.16.0""" + # Since: 3.16.0 + + resolve_support: Optional["ClientCompletionItemResolveOptions"] = attrs.field( + default=None + ) + """Indicates which properties a client can resolve lazily on a completion + item. Before version 3.16.0 only the predefined properties `documentation` + and `details` could be resolved lazily. + + @since 3.16.0""" + # Since: 3.16.0 + + insert_text_mode_support: Optional["ClientCompletionItemInsertTextModeOptions"] = ( + attrs.field(default=None) + ) + """The client supports the `insertTextMode` property on + a completion item to override the whitespace handling mode + as defined by the client (see `insertTextMode`). + + @since 3.16.0""" + # Since: 3.16.0 + + label_details_support: Optional[bool] = attrs.field( + validator=attrs.validators.optional(attrs.validators.instance_of(bool)), + default=None, + ) + """The client has support for completion item label + details (see also `CompletionItemLabelDetails`). + + @since 3.17.0""" + # Since: 3.17.0 + + +@attrs.define +class ClientCompletionItemOptionsKind: + """@since 3.18.0""" + + # Since: 3.18.0 + + value_set: Optional[Sequence[Union[CompletionItemKind, int]]] = attrs.field( + default=None + ) + """The completion item kind values the client supports. When this + property exists the client also guarantees that it will + handle values outside its set gracefully and falls back + to a default value when unknown. + + If this property is not present the client only supports + the completion items kinds from `Text` to `Reference` as defined in + the initial version of the protocol.""" + + +@attrs.define +class CompletionListCapabilities: + """The client supports the following `CompletionList` specific + capabilities. + + @since 3.17.0""" + + # Since: 3.17.0 + + item_defaults: Optional[Sequence[str]] = attrs.field(default=None) + """The client supports the following itemDefaults on + a completion list. + + The value lists the supported property names of the + `CompletionList.itemDefaults` object. If omitted + no properties are supported. + + @since 3.17.0""" + # Since: 3.17.0 + + apply_kind_support: Optional[bool] = attrs.field( + validator=attrs.validators.optional(attrs.validators.instance_of(bool)), + default=None, + ) + """Specifies whether the client supports `CompletionList.applyKind` to + indicate how supported values from `completionList.itemDefaults` + and `completion` will be combined. + + If a client supports `applyKind` it must support it for all fields + that it supports that are listed in `CompletionList.applyKind`. This + means when clients add support for new/future fields in completion + items the MUST also support merge for them if those fields are + defined in `CompletionList.applyKind`. + + @since 3.18.0""" + # Since: 3.18.0 + + +@attrs.define +class ClientSignatureInformationOptions: + """@since 3.18.0""" + + # Since: 3.18.0 + + documentation_format: Optional[Sequence[MarkupKind]] = attrs.field(default=None) + """Client supports the following content formats for the documentation + property. The order describes the preferred format of the client.""" + + parameter_information: Optional["ClientSignatureParameterInformationOptions"] = ( + attrs.field(default=None) + ) + """Client capabilities specific to parameter information.""" + + active_parameter_support: Optional[bool] = attrs.field( + validator=attrs.validators.optional(attrs.validators.instance_of(bool)), + default=None, + ) + """The client supports the `activeParameter` property on `SignatureInformation` + literal. + + @since 3.16.0""" + # Since: 3.16.0 + + no_active_parameter_support: Optional[bool] = attrs.field( + validator=attrs.validators.optional(attrs.validators.instance_of(bool)), + default=None, + ) + """The client supports the `activeParameter` property on + `SignatureHelp`/`SignatureInformation` being set to `null` to + indicate that no parameter should be active. + + @since 3.18.0 + @proposed""" + # Since: 3.18.0 + # Proposed + + +@attrs.define +class ClientCodeActionLiteralOptions: + """@since 3.18.0""" + + # Since: 3.18.0 + + code_action_kind: "ClientCodeActionKindOptions" = attrs.field() + """The code action kind is support with the following value + set.""" + + +@attrs.define +class ClientCodeActionResolveOptions: + """@since 3.18.0""" + + # Since: 3.18.0 + + properties: Sequence[str] = attrs.field() + """The properties that a client can resolve lazily.""" + + +@attrs.define +class CodeActionTagOptions: + """@since 3.18.0 - proposed""" + + # Since: 3.18.0 - proposed + + value_set: Sequence[CodeActionTag] = attrs.field() + """The tags supported by the client.""" + + +@attrs.define +class ClientCodeLensResolveOptions: + """@since 3.18.0""" + + # Since: 3.18.0 + + properties: Sequence[str] = attrs.field() + """The properties that a client can resolve lazily.""" + + +@attrs.define +class ClientFoldingRangeKindOptions: + """@since 3.18.0""" + + # Since: 3.18.0 + + value_set: Optional[Sequence[Union[FoldingRangeKind, str]]] = attrs.field( + default=None + ) + """The folding range kind values the client supports. When this + property exists the client also guarantees that it will + handle values outside its set gracefully and falls back + to a default value when unknown.""" + + +@attrs.define +class ClientFoldingRangeOptions: + """@since 3.18.0""" + + # Since: 3.18.0 + + collapsed_text: Optional[bool] = attrs.field( + validator=attrs.validators.optional(attrs.validators.instance_of(bool)), + default=None, + ) + """If set, the client signals that it supports setting collapsedText on + folding ranges to display custom labels instead of the default text. + + @since 3.17.0""" + # Since: 3.17.0 + + +@attrs.define +class ClientSemanticTokensRequestOptions: + """@since 3.18.0""" + + # Since: 3.18.0 + + range: Optional[Union[bool, Any]] = attrs.field(default=None) + """The client will send the `textDocument/semanticTokens/range` request if + the server provides a corresponding handler.""" + + full: Optional[Union[bool, "ClientSemanticTokensRequestFullDelta"]] = attrs.field( + default=None + ) + """The client will send the `textDocument/semanticTokens/full` request if + the server provides a corresponding handler.""" + + +@attrs.define +class ClientInlayHintResolveOptions: + """@since 3.18.0""" + + # Since: 3.18.0 + + properties: Sequence[str] = attrs.field() + """The properties that a client can resolve lazily.""" + + +@attrs.define +class ClientShowMessageActionItemOptions: + """@since 3.18.0""" + + # Since: 3.18.0 + + additional_properties_support: Optional[bool] = attrs.field( + validator=attrs.validators.optional(attrs.validators.instance_of(bool)), + default=None, + ) + """Whether the client supports additional attributes which + are preserved and send back to the server in the + request's response.""" + + +@attrs.define +class CompletionItemTagOptions: + """@since 3.18.0""" + + # Since: 3.18.0 + + value_set: Sequence[CompletionItemTag] = attrs.field() + """The tags supported by the client.""" + + +@attrs.define +class ClientCompletionItemResolveOptions: + """@since 3.18.0""" + + # Since: 3.18.0 + + properties: Sequence[str] = attrs.field() + """The properties that a client can resolve lazily.""" + + +@attrs.define +class ClientCompletionItemInsertTextModeOptions: + """@since 3.18.0""" + + # Since: 3.18.0 + + value_set: Sequence[InsertTextMode] = attrs.field() + + +@attrs.define +class ClientSignatureParameterInformationOptions: + """@since 3.18.0""" + + # Since: 3.18.0 + + label_offset_support: Optional[bool] = attrs.field( + validator=attrs.validators.optional(attrs.validators.instance_of(bool)), + default=None, + ) + """The client supports processing label offsets instead of a + simple label string. + + @since 3.14.0""" + # Since: 3.14.0 + + +@attrs.define +class ClientCodeActionKindOptions: + """@since 3.18.0""" + + # Since: 3.18.0 + + value_set: Sequence[Union[CodeActionKind, str]] = attrs.field() + """The code action kind values the client supports. When this + property exists the client also guarantees that it will + handle values outside its set gracefully and falls back + to a default value when unknown.""" + + +@attrs.define +class ClientDiagnosticsTagOptions: + """@since 3.18.0""" + + # Since: 3.18.0 + + value_set: Sequence[DiagnosticTag] = attrs.field() + """The tags supported by the client.""" + + +@attrs.define +class ClientSemanticTokensRequestFullDelta: + """@since 3.18.0""" + + # Since: 3.18.0 + + delta: Optional[bool] = attrs.field( + validator=attrs.validators.optional(attrs.validators.instance_of(bool)), + default=None, + ) + """The client will send the `textDocument/semanticTokens/full/delta` request if + the server provides a corresponding handler.""" + + +@attrs.define +class ColorPresentationRequestOptions: work_done_progress: Optional[bool] = attrs.field( validator=attrs.validators.optional(attrs.validators.instance_of(bool)), default=None, @@ -8916,8 +9736,11 @@ class ResponseErrorMessage: jsonrpc: str = attrs.field(default="2.0") +ImplementationResult = Union[Definition, Sequence[DefinitionLink], None] + + @attrs.define -class TextDocumentImplementationRequest: +class ImplementationRequest: """A request to resolve the implementation locations of a symbol at a given text document position. The request's parameter is of type {@link TextDocumentPositionParams} the response is of type {@link Definition} or a Thenable that resolves to such.""" @@ -8925,21 +9748,24 @@ class TextDocumentImplementationRequest: id: Union[int, str] = attrs.field() """The request id.""" params: ImplementationParams = attrs.field() - method: str = "textDocument/implementation" + method: Literal["textDocument/implementation"] = "textDocument/implementation" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @attrs.define -class TextDocumentImplementationResponse: +class ImplementationResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" - result: Union[Definition, List[DefinitionLink], None] = attrs.field(default=None) + result: Optional[ImplementationResult] = attrs.field(default=None) jsonrpc: str = attrs.field(default="2.0") +TypeDefinitionResult = Union[Definition, Sequence[DefinitionLink], None] + + @attrs.define -class TextDocumentTypeDefinitionRequest: +class TypeDefinitionRequest: """A request to resolve the type definition locations of a symbol at a given text document position. The request's parameter is of type {@link TextDocumentPositionParams} the response is of type {@link Definition} or a Thenable that resolves to such.""" @@ -8947,44 +9773,47 @@ class TextDocumentTypeDefinitionRequest: id: Union[int, str] = attrs.field() """The request id.""" params: TypeDefinitionParams = attrs.field() - method: str = "textDocument/typeDefinition" + method: Literal["textDocument/typeDefinition"] = "textDocument/typeDefinition" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @attrs.define -class TextDocumentTypeDefinitionResponse: +class TypeDefinitionResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" - result: Union[Definition, List[DefinitionLink], None] = attrs.field(default=None) + result: Optional[TypeDefinitionResult] = attrs.field(default=None) jsonrpc: str = attrs.field(default="2.0") +WorkspaceFoldersResult = Union[Sequence[WorkspaceFolder], None] + + @attrs.define -class WorkspaceWorkspaceFoldersRequest: +class WorkspaceFoldersRequest: """The `workspace/workspaceFolders` is sent from the server to the client to fetch the open workspace folders.""" id: Union[int, str] = attrs.field() """The request id.""" params: Optional[None] = attrs.field(default=None) - method: str = "workspace/workspaceFolders" + method: Literal["workspace/workspaceFolders"] = "workspace/workspaceFolders" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @attrs.define -class WorkspaceWorkspaceFoldersResponse: +class WorkspaceFoldersResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" - result: Union[List[WorkspaceFolder], None] = attrs.field(default=None) + result: Optional[WorkspaceFoldersResult] = attrs.field(default=None) jsonrpc: str = attrs.field(default="2.0") -WorkspaceConfigurationParams = ConfigurationParams +ConfigurationResult = Sequence[LSPAny] @attrs.define -class WorkspaceConfigurationRequest: +class ConfigurationRequest: """The 'workspace/configuration' request is sent from the server to the client to fetch a certain configuration setting. @@ -8995,22 +9824,25 @@ class WorkspaceConfigurationRequest: id: Union[int, str] = attrs.field() """The request id.""" - params: WorkspaceConfigurationParams = attrs.field() - method: str = "workspace/configuration" + params: ConfigurationParams = attrs.field() + method: Literal["workspace/configuration"] = "workspace/configuration" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @attrs.define -class WorkspaceConfigurationResponse: +class ConfigurationResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" - result: List[LSPAny] = attrs.field(default=None) + result: ConfigurationResult = attrs.field(default=None) jsonrpc: str = attrs.field(default="2.0") +DocumentColorResult = Sequence[ColorInformation] + + @attrs.define -class TextDocumentDocumentColorRequest: +class DocumentColorRequest: """A request to list all color symbols found in a given text document. The request's parameter is of type {@link DocumentColorParams} the response is of type {@link ColorInformation ColorInformation[]} or a Thenable @@ -9019,21 +9851,24 @@ class TextDocumentDocumentColorRequest: id: Union[int, str] = attrs.field() """The request id.""" params: DocumentColorParams = attrs.field() - method: str = "textDocument/documentColor" + method: Literal["textDocument/documentColor"] = "textDocument/documentColor" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @attrs.define -class TextDocumentDocumentColorResponse: +class DocumentColorResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" - result: List[ColorInformation] = attrs.field(default=None) + result: DocumentColorResult = attrs.field(default=None) jsonrpc: str = attrs.field(default="2.0") +ColorPresentationResult = Sequence[ColorPresentation] + + @attrs.define -class TextDocumentColorPresentationRequest: +class ColorPresentationRequest: """A request to list all presentation for a color. The request's parameter is of type {@link ColorPresentationParams} the response is of type {@link ColorInformation ColorInformation[]} or a Thenable @@ -9042,21 +9877,24 @@ class TextDocumentColorPresentationRequest: id: Union[int, str] = attrs.field() """The request id.""" params: ColorPresentationParams = attrs.field() - method: str = "textDocument/colorPresentation" + method: Literal["textDocument/colorPresentation"] = "textDocument/colorPresentation" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @attrs.define -class TextDocumentColorPresentationResponse: +class ColorPresentationResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" - result: List[ColorPresentation] = attrs.field(default=None) + result: ColorPresentationResult = attrs.field(default=None) jsonrpc: str = attrs.field(default="2.0") +FoldingRangeResult = Union[Sequence[FoldingRange], None] + + @attrs.define -class TextDocumentFoldingRangeRequest: +class FoldingRangeRequest: """A request to provide folding ranges in a document. The request's parameter is of type {@link FoldingRangeParams}, the response is of type {@link FoldingRangeList} or a Thenable @@ -9065,42 +9903,45 @@ class TextDocumentFoldingRangeRequest: id: Union[int, str] = attrs.field() """The request id.""" params: FoldingRangeParams = attrs.field() - method: str = "textDocument/foldingRange" + method: Literal["textDocument/foldingRange"] = "textDocument/foldingRange" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @attrs.define -class TextDocumentFoldingRangeResponse: +class FoldingRangeResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" - result: Union[List[FoldingRange], None] = attrs.field(default=None) + result: Optional[FoldingRangeResult] = attrs.field(default=None) jsonrpc: str = attrs.field(default="2.0") @attrs.define -class WorkspaceFoldingRangeRefreshRequest: +class FoldingRangeRefreshRequest: """@since 3.18.0 @proposed""" id: Union[int, str] = attrs.field() """The request id.""" params: Optional[None] = attrs.field(default=None) - method: str = "workspace/foldingRange/refresh" + method: Literal["workspace/foldingRange/refresh"] = "workspace/foldingRange/refresh" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @attrs.define -class WorkspaceFoldingRangeRefreshResponse: +class FoldingRangeRefreshResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" result: None = attrs.field(default=None) jsonrpc: str = attrs.field(default="2.0") +DeclarationResult = Union[Declaration, Sequence[DeclarationLink], None] + + @attrs.define -class TextDocumentDeclarationRequest: +class DeclarationRequest: """A request to resolve the type definition locations of a symbol at a given text document position. The request's parameter is of type {@link TextDocumentPositionParams} the response is of type {@link Declaration} or a typed array of {@link DeclarationLink} @@ -9109,21 +9950,24 @@ class TextDocumentDeclarationRequest: id: Union[int, str] = attrs.field() """The request id.""" params: DeclarationParams = attrs.field() - method: str = "textDocument/declaration" + method: Literal["textDocument/declaration"] = "textDocument/declaration" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @attrs.define -class TextDocumentDeclarationResponse: +class DeclarationResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" - result: Union[Declaration, List[DeclarationLink], None] = attrs.field(default=None) + result: Optional[DeclarationResult] = attrs.field(default=None) jsonrpc: str = attrs.field(default="2.0") +SelectionRangeResult = Union[Sequence[SelectionRange], None] + + @attrs.define -class TextDocumentSelectionRangeRequest: +class SelectionRangeRequest: """A request to provide selection ranges in a document. The request's parameter is of type {@link SelectionRangeParams}, the response is of type {@link SelectionRange SelectionRange[]} or a Thenable @@ -9132,42 +9976,45 @@ class TextDocumentSelectionRangeRequest: id: Union[int, str] = attrs.field() """The request id.""" params: SelectionRangeParams = attrs.field() - method: str = "textDocument/selectionRange" + method: Literal["textDocument/selectionRange"] = "textDocument/selectionRange" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @attrs.define -class TextDocumentSelectionRangeResponse: +class SelectionRangeResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" - result: Union[List[SelectionRange], None] = attrs.field(default=None) + result: Optional[SelectionRangeResult] = attrs.field(default=None) jsonrpc: str = attrs.field(default="2.0") @attrs.define -class WindowWorkDoneProgressCreateRequest: +class WorkDoneProgressCreateRequest: """The `window/workDoneProgress/create` request is sent from the server to the client to initiate progress reporting from the server.""" id: Union[int, str] = attrs.field() """The request id.""" params: WorkDoneProgressCreateParams = attrs.field() - method: str = "window/workDoneProgress/create" + method: Literal["window/workDoneProgress/create"] = "window/workDoneProgress/create" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @attrs.define -class WindowWorkDoneProgressCreateResponse: +class WorkDoneProgressCreateResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" result: None = attrs.field(default=None) jsonrpc: str = attrs.field(default="2.0") +CallHierarchyPrepareResult = Union[Sequence[CallHierarchyItem], None] + + @attrs.define -class TextDocumentPrepareCallHierarchyRequest: +class CallHierarchyPrepareRequest: """A request to result a `CallHierarchyItem` in a document at a given position. Can be used as an input to an incoming or outgoing call hierarchy. @@ -9176,19 +10023,24 @@ class TextDocumentPrepareCallHierarchyRequest: id: Union[int, str] = attrs.field() """The request id.""" params: CallHierarchyPrepareParams = attrs.field() - method: str = "textDocument/prepareCallHierarchy" + method: Literal["textDocument/prepareCallHierarchy"] = ( + "textDocument/prepareCallHierarchy" + ) """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @attrs.define -class TextDocumentPrepareCallHierarchyResponse: +class CallHierarchyPrepareResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" - result: Union[List[CallHierarchyItem], None] = attrs.field(default=None) + result: Optional[CallHierarchyPrepareResult] = attrs.field(default=None) jsonrpc: str = attrs.field(default="2.0") +CallHierarchyIncomingCallsResult = Union[Sequence[CallHierarchyIncomingCall], None] + + @attrs.define class CallHierarchyIncomingCallsRequest: """A request to resolve the incoming calls for a given `CallHierarchyItem`. @@ -9198,7 +10050,7 @@ class CallHierarchyIncomingCallsRequest: id: Union[int, str] = attrs.field() """The request id.""" params: CallHierarchyIncomingCallsParams = attrs.field() - method: str = "callHierarchy/incomingCalls" + method: Literal["callHierarchy/incomingCalls"] = "callHierarchy/incomingCalls" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @@ -9207,10 +10059,13 @@ class CallHierarchyIncomingCallsRequest: class CallHierarchyIncomingCallsResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" - result: Union[List[CallHierarchyIncomingCall], None] = attrs.field(default=None) + result: Optional[CallHierarchyIncomingCallsResult] = attrs.field(default=None) jsonrpc: str = attrs.field(default="2.0") +CallHierarchyOutgoingCallsResult = Union[Sequence[CallHierarchyOutgoingCall], None] + + @attrs.define class CallHierarchyOutgoingCallsRequest: """A request to resolve the outgoing calls for a given `CallHierarchyItem`. @@ -9220,7 +10075,7 @@ class CallHierarchyOutgoingCallsRequest: id: Union[int, str] = attrs.field() """The request id.""" params: CallHierarchyOutgoingCallsParams = attrs.field() - method: str = "callHierarchy/outgoingCalls" + method: Literal["callHierarchy/outgoingCalls"] = "callHierarchy/outgoingCalls" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @@ -9229,84 +10084,101 @@ class CallHierarchyOutgoingCallsRequest: class CallHierarchyOutgoingCallsResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" - result: Union[List[CallHierarchyOutgoingCall], None] = attrs.field(default=None) + result: Optional[CallHierarchyOutgoingCallsResult] = attrs.field(default=None) jsonrpc: str = attrs.field(default="2.0") +SemanticTokensResult = Union[SemanticTokens, None] + + @attrs.define -class TextDocumentSemanticTokensFullRequest: +class SemanticTokensRequest: """@since 3.16.0""" id: Union[int, str] = attrs.field() """The request id.""" params: SemanticTokensParams = attrs.field() - method: str = "textDocument/semanticTokens/full" + method: Literal["textDocument/semanticTokens/full"] = ( + "textDocument/semanticTokens/full" + ) """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @attrs.define -class TextDocumentSemanticTokensFullResponse: +class SemanticTokensResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" - result: Union[SemanticTokens, None] = attrs.field(default=None) + result: Optional[SemanticTokensResult] = attrs.field(default=None) jsonrpc: str = attrs.field(default="2.0") +SemanticTokensDeltaResult = Union[SemanticTokens, SemanticTokensDelta, None] + + @attrs.define -class TextDocumentSemanticTokensFullDeltaRequest: +class SemanticTokensDeltaRequest: """@since 3.16.0""" id: Union[int, str] = attrs.field() """The request id.""" params: SemanticTokensDeltaParams = attrs.field() - method: str = "textDocument/semanticTokens/full/delta" + method: Literal["textDocument/semanticTokens/full/delta"] = ( + "textDocument/semanticTokens/full/delta" + ) """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @attrs.define -class TextDocumentSemanticTokensFullDeltaResponse: +class SemanticTokensDeltaResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" - result: Union[SemanticTokens, SemanticTokensDelta, None] = attrs.field(default=None) + result: Optional[SemanticTokensDeltaResult] = attrs.field(default=None) jsonrpc: str = attrs.field(default="2.0") +SemanticTokensRangeResult = Union[SemanticTokens, None] + + @attrs.define -class TextDocumentSemanticTokensRangeRequest: +class SemanticTokensRangeRequest: """@since 3.16.0""" id: Union[int, str] = attrs.field() """The request id.""" params: SemanticTokensRangeParams = attrs.field() - method: str = "textDocument/semanticTokens/range" + method: Literal["textDocument/semanticTokens/range"] = ( + "textDocument/semanticTokens/range" + ) """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @attrs.define -class TextDocumentSemanticTokensRangeResponse: +class SemanticTokensRangeResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" - result: Union[SemanticTokens, None] = attrs.field(default=None) + result: Optional[SemanticTokensRangeResult] = attrs.field(default=None) jsonrpc: str = attrs.field(default="2.0") @attrs.define -class WorkspaceSemanticTokensRefreshRequest: +class SemanticTokensRefreshRequest: """@since 3.16.0""" id: Union[int, str] = attrs.field() """The request id.""" params: Optional[None] = attrs.field(default=None) - method: str = "workspace/semanticTokens/refresh" + method: Literal["workspace/semanticTokens/refresh"] = ( + "workspace/semanticTokens/refresh" + ) """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @attrs.define -class WorkspaceSemanticTokensRefreshResponse: +class SemanticTokensRefreshResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" result: None = attrs.field(default=None) @@ -9314,7 +10186,7 @@ class WorkspaceSemanticTokensRefreshResponse: @attrs.define -class WindowShowDocumentRequest: +class ShowDocumentRequest: """A request to show a document. This request might open an external program depending on the value of the URI to open. For example a request to open `https://code.visualstudio.com/` @@ -9325,21 +10197,24 @@ class WindowShowDocumentRequest: id: Union[int, str] = attrs.field() """The request id.""" params: ShowDocumentParams = attrs.field() - method: str = "window/showDocument" + method: Literal["window/showDocument"] = "window/showDocument" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @attrs.define -class WindowShowDocumentResponse: +class ShowDocumentResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" result: ShowDocumentResult = attrs.field(default=None) jsonrpc: str = attrs.field(default="2.0") +LinkedEditingRangeResult = Union[LinkedEditingRanges, None] + + @attrs.define -class TextDocumentLinkedEditingRangeRequest: +class LinkedEditingRangeRequest: """A request to provide ranges that can be edited together. @since 3.16.0""" @@ -9347,21 +10222,26 @@ class TextDocumentLinkedEditingRangeRequest: id: Union[int, str] = attrs.field() """The request id.""" params: LinkedEditingRangeParams = attrs.field() - method: str = "textDocument/linkedEditingRange" + method: Literal["textDocument/linkedEditingRange"] = ( + "textDocument/linkedEditingRange" + ) """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @attrs.define -class TextDocumentLinkedEditingRangeResponse: +class LinkedEditingRangeResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" - result: Union[LinkedEditingRanges, None] = attrs.field(default=None) + result: Optional[LinkedEditingRangeResult] = attrs.field(default=None) jsonrpc: str = attrs.field(default="2.0") +WillCreateFilesResult = Union[WorkspaceEdit, None] + + @attrs.define -class WorkspaceWillCreateFilesRequest: +class WillCreateFilesRequest: """The will create files request is sent from the client to the server before files are actually created as long as the creation is triggered from within the client. @@ -9374,21 +10254,24 @@ class WorkspaceWillCreateFilesRequest: id: Union[int, str] = attrs.field() """The request id.""" params: CreateFilesParams = attrs.field() - method: str = "workspace/willCreateFiles" + method: Literal["workspace/willCreateFiles"] = "workspace/willCreateFiles" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @attrs.define -class WorkspaceWillCreateFilesResponse: +class WillCreateFilesResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" - result: Union[WorkspaceEdit, None] = attrs.field(default=None) + result: Optional[WillCreateFilesResult] = attrs.field(default=None) jsonrpc: str = attrs.field(default="2.0") +WillRenameFilesResult = Union[WorkspaceEdit, None] + + @attrs.define -class WorkspaceWillRenameFilesRequest: +class WillRenameFilesRequest: """The will rename files request is sent from the client to the server before files are actually renamed as long as the rename is triggered from within the client. @@ -9397,21 +10280,24 @@ class WorkspaceWillRenameFilesRequest: id: Union[int, str] = attrs.field() """The request id.""" params: RenameFilesParams = attrs.field() - method: str = "workspace/willRenameFiles" + method: Literal["workspace/willRenameFiles"] = "workspace/willRenameFiles" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @attrs.define -class WorkspaceWillRenameFilesResponse: +class WillRenameFilesResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" - result: Union[WorkspaceEdit, None] = attrs.field(default=None) + result: Optional[WillRenameFilesResult] = attrs.field(default=None) jsonrpc: str = attrs.field(default="2.0") +WillDeleteFilesResult = Union[WorkspaceEdit, None] + + @attrs.define -class WorkspaceWillDeleteFilesRequest: +class WillDeleteFilesRequest: """The did delete files notification is sent from the client to the server when files were deleted from within the client. @@ -9420,21 +10306,24 @@ class WorkspaceWillDeleteFilesRequest: id: Union[int, str] = attrs.field() """The request id.""" params: DeleteFilesParams = attrs.field() - method: str = "workspace/willDeleteFiles" + method: Literal["workspace/willDeleteFiles"] = "workspace/willDeleteFiles" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @attrs.define -class WorkspaceWillDeleteFilesResponse: +class WillDeleteFilesResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" - result: Union[WorkspaceEdit, None] = attrs.field(default=None) + result: Optional[WillDeleteFilesResult] = attrs.field(default=None) jsonrpc: str = attrs.field(default="2.0") +MonikerResult = Union[Sequence[Moniker], None] + + @attrs.define -class TextDocumentMonikerRequest: +class MonikerRequest: """A request to get the moniker of a symbol at a given text document position. The request parameter is of type {@link TextDocumentPositionParams}. The response is of type {@link Moniker Moniker[]} or `null`.""" @@ -9442,21 +10331,24 @@ class TextDocumentMonikerRequest: id: Union[int, str] = attrs.field() """The request id.""" params: MonikerParams = attrs.field() - method: str = "textDocument/moniker" + method: Literal["textDocument/moniker"] = "textDocument/moniker" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @attrs.define -class TextDocumentMonikerResponse: +class MonikerResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" - result: Union[List[Moniker], None] = attrs.field(default=None) + result: Optional[MonikerResult] = attrs.field(default=None) jsonrpc: str = attrs.field(default="2.0") +TypeHierarchyPrepareResult = Union[Sequence[TypeHierarchyItem], None] + + @attrs.define -class TextDocumentPrepareTypeHierarchyRequest: +class TypeHierarchyPrepareRequest: """A request to result a `TypeHierarchyItem` in a document at a given position. Can be used as an input to a subtypes or supertypes type hierarchy. @@ -9465,19 +10357,24 @@ class TextDocumentPrepareTypeHierarchyRequest: id: Union[int, str] = attrs.field() """The request id.""" params: TypeHierarchyPrepareParams = attrs.field() - method: str = "textDocument/prepareTypeHierarchy" + method: Literal["textDocument/prepareTypeHierarchy"] = ( + "textDocument/prepareTypeHierarchy" + ) """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @attrs.define -class TextDocumentPrepareTypeHierarchyResponse: +class TypeHierarchyPrepareResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" - result: Union[List[TypeHierarchyItem], None] = attrs.field(default=None) + result: Optional[TypeHierarchyPrepareResult] = attrs.field(default=None) jsonrpc: str = attrs.field(default="2.0") +TypeHierarchySupertypesResult = Union[Sequence[TypeHierarchyItem], None] + + @attrs.define class TypeHierarchySupertypesRequest: """A request to resolve the supertypes for a given `TypeHierarchyItem`. @@ -9487,7 +10384,7 @@ class TypeHierarchySupertypesRequest: id: Union[int, str] = attrs.field() """The request id.""" params: TypeHierarchySupertypesParams = attrs.field() - method: str = "typeHierarchy/supertypes" + method: Literal["typeHierarchy/supertypes"] = "typeHierarchy/supertypes" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @@ -9496,10 +10393,13 @@ class TypeHierarchySupertypesRequest: class TypeHierarchySupertypesResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" - result: Union[List[TypeHierarchyItem], None] = attrs.field(default=None) + result: Optional[TypeHierarchySupertypesResult] = attrs.field(default=None) jsonrpc: str = attrs.field(default="2.0") +TypeHierarchySubtypesResult = Union[Sequence[TypeHierarchyItem], None] + + @attrs.define class TypeHierarchySubtypesRequest: """A request to resolve the subtypes for a given `TypeHierarchyItem`. @@ -9509,7 +10409,7 @@ class TypeHierarchySubtypesRequest: id: Union[int, str] = attrs.field() """The request id.""" params: TypeHierarchySubtypesParams = attrs.field() - method: str = "typeHierarchy/subtypes" + method: Literal["typeHierarchy/subtypes"] = "typeHierarchy/subtypes" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @@ -9518,12 +10418,15 @@ class TypeHierarchySubtypesRequest: class TypeHierarchySubtypesResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" - result: Union[List[TypeHierarchyItem], None] = attrs.field(default=None) + result: Optional[TypeHierarchySubtypesResult] = attrs.field(default=None) jsonrpc: str = attrs.field(default="2.0") +InlineValueResult = Union[Sequence[InlineValue], None] + + @attrs.define -class TextDocumentInlineValueRequest: +class InlineValueRequest: """A request to provide inline values in a document. The request's parameter is of type {@link InlineValueParams}, the response is of type {@link InlineValue InlineValue[]} or a Thenable that resolves to such. @@ -9533,41 +10436,44 @@ class TextDocumentInlineValueRequest: id: Union[int, str] = attrs.field() """The request id.""" params: InlineValueParams = attrs.field() - method: str = "textDocument/inlineValue" + method: Literal["textDocument/inlineValue"] = "textDocument/inlineValue" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @attrs.define -class TextDocumentInlineValueResponse: +class InlineValueResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" - result: Union[List[InlineValue], None] = attrs.field(default=None) + result: Optional[InlineValueResult] = attrs.field(default=None) jsonrpc: str = attrs.field(default="2.0") @attrs.define -class WorkspaceInlineValueRefreshRequest: +class InlineValueRefreshRequest: """@since 3.17.0""" id: Union[int, str] = attrs.field() """The request id.""" params: Optional[None] = attrs.field(default=None) - method: str = "workspace/inlineValue/refresh" + method: Literal["workspace/inlineValue/refresh"] = "workspace/inlineValue/refresh" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @attrs.define -class WorkspaceInlineValueRefreshResponse: +class InlineValueRefreshResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" result: None = attrs.field(default=None) jsonrpc: str = attrs.field(default="2.0") +InlayHintResult = Union[Sequence[InlayHint], None] + + @attrs.define -class TextDocumentInlayHintRequest: +class InlayHintRequest: """A request to provide inlay hints in a document. The request's parameter is of type {@link InlayHintsParams}, the response is of type {@link InlayHint InlayHint[]} or a Thenable that resolves to such. @@ -9577,16 +10483,16 @@ class TextDocumentInlayHintRequest: id: Union[int, str] = attrs.field() """The request id.""" params: InlayHintParams = attrs.field() - method: str = "textDocument/inlayHint" + method: Literal["textDocument/inlayHint"] = "textDocument/inlayHint" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @attrs.define -class TextDocumentInlayHintResponse: +class InlayHintResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" - result: Union[List[InlayHint], None] = attrs.field(default=None) + result: Optional[InlayHintResult] = attrs.field(default=None) jsonrpc: str = attrs.field(default="2.0") @@ -9601,7 +10507,7 @@ class InlayHintResolveRequest: id: Union[int, str] = attrs.field() """The request id.""" params: InlayHint = attrs.field() - method: str = "inlayHint/resolve" + method: Literal["inlayHint/resolve"] = "inlayHint/resolve" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @@ -9615,19 +10521,19 @@ class InlayHintResolveResponse: @attrs.define -class WorkspaceInlayHintRefreshRequest: +class InlayHintRefreshRequest: """@since 3.17.0""" id: Union[int, str] = attrs.field() """The request id.""" params: Optional[None] = attrs.field(default=None) - method: str = "workspace/inlayHint/refresh" + method: Literal["workspace/inlayHint/refresh"] = "workspace/inlayHint/refresh" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @attrs.define -class WorkspaceInlayHintRefreshResponse: +class InlayHintRefreshResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" result: None = attrs.field(default=None) @@ -9635,7 +10541,7 @@ class WorkspaceInlayHintRefreshResponse: @attrs.define -class TextDocumentDiagnosticRequest: +class DocumentDiagnosticRequest: """The document diagnostic request definition. @since 3.17.0""" @@ -9643,13 +10549,13 @@ class TextDocumentDiagnosticRequest: id: Union[int, str] = attrs.field() """The request id.""" params: DocumentDiagnosticParams = attrs.field() - method: str = "textDocument/diagnostic" + method: Literal["textDocument/diagnostic"] = "textDocument/diagnostic" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @attrs.define -class TextDocumentDiagnosticResponse: +class DocumentDiagnosticResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" result: DocumentDiagnosticReport = attrs.field(default=None) @@ -9665,7 +10571,7 @@ class WorkspaceDiagnosticRequest: id: Union[int, str] = attrs.field() """The request id.""" params: WorkspaceDiagnosticParams = attrs.field() - method: str = "workspace/diagnostic" + method: Literal["workspace/diagnostic"] = "workspace/diagnostic" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @@ -9679,7 +10585,7 @@ class WorkspaceDiagnosticResponse: @attrs.define -class WorkspaceDiagnosticRefreshRequest: +class DiagnosticRefreshRequest: """The diagnostic refresh request definition. @since 3.17.0""" @@ -9687,21 +10593,26 @@ class WorkspaceDiagnosticRefreshRequest: id: Union[int, str] = attrs.field() """The request id.""" params: Optional[None] = attrs.field(default=None) - method: str = "workspace/diagnostic/refresh" + method: Literal["workspace/diagnostic/refresh"] = "workspace/diagnostic/refresh" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @attrs.define -class WorkspaceDiagnosticRefreshResponse: +class DiagnosticRefreshResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" result: None = attrs.field(default=None) jsonrpc: str = attrs.field(default="2.0") +InlineCompletionResult = Union[ + InlineCompletionList, Sequence[InlineCompletionItem], None +] + + @attrs.define -class TextDocumentInlineCompletionRequest: +class InlineCompletionRequest: """A request to provide inline completions in a document. The request's parameter is of type {@link InlineCompletionParams}, the response is of type {@link InlineCompletion InlineCompletion[]} or a Thenable that resolves to such. @@ -9712,36 +10623,63 @@ class TextDocumentInlineCompletionRequest: id: Union[int, str] = attrs.field() """The request id.""" params: InlineCompletionParams = attrs.field() - method: str = "textDocument/inlineCompletion" + method: Literal["textDocument/inlineCompletion"] = "textDocument/inlineCompletion" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @attrs.define -class TextDocumentInlineCompletionResponse: +class InlineCompletionResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" - result: Union[InlineCompletionList, List[InlineCompletionItem], None] = attrs.field( - default=None - ) + result: Optional[InlineCompletionResult] = attrs.field(default=None) jsonrpc: str = attrs.field(default="2.0") @attrs.define -class ClientRegisterCapabilityRequest: - """The `client/registerCapability` request is sent from the server to the client to register a new capability - handler on the client side.""" +class TextDocumentContentRequest: + """The `workspace/textDocumentContent` request is sent from the client to the + server to request the content of a text document. + + @since 3.18.0 + @proposed""" id: Union[int, str] = attrs.field() """The request id.""" - params: RegistrationParams = attrs.field() - method: str = "client/registerCapability" + params: TextDocumentContentParams = attrs.field() + method: Literal["workspace/textDocumentContent"] = "workspace/textDocumentContent" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @attrs.define -class ClientRegisterCapabilityResponse: +class TextDocumentContentResponse: + id: Optional[Union[int, str]] = attrs.field() + """The request id.""" + result: TextDocumentContentResult = attrs.field(default=None) + jsonrpc: str = attrs.field(default="2.0") + + +@attrs.define +class TextDocumentContentRefreshRequest: + """The `workspace/textDocumentContent` request is sent from the server to the client to refresh + the content of a specific text document. + + @since 3.18.0 + @proposed""" + + id: Union[int, str] = attrs.field() + """The request id.""" + params: TextDocumentContentRefreshParams = attrs.field() + method: Literal["workspace/textDocumentContent/refresh"] = ( + "workspace/textDocumentContent/refresh" + ) + """The method to be invoked.""" + jsonrpc: str = attrs.field(default="2.0") + + +@attrs.define +class TextDocumentContentRefreshResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" result: None = attrs.field(default=None) @@ -9749,20 +10687,41 @@ class ClientRegisterCapabilityResponse: @attrs.define -class ClientUnregisterCapabilityRequest: +class RegistrationRequest: + """The `client/registerCapability` request is sent from the server to the client to register a new capability + handler on the client side.""" + + id: Union[int, str] = attrs.field() + """The request id.""" + params: RegistrationParams = attrs.field() + method: Literal["client/registerCapability"] = "client/registerCapability" + """The method to be invoked.""" + jsonrpc: str = attrs.field(default="2.0") + + +@attrs.define +class RegistrationResponse: + id: Optional[Union[int, str]] = attrs.field() + """The request id.""" + result: None = attrs.field(default=None) + jsonrpc: str = attrs.field(default="2.0") + + +@attrs.define +class UnregistrationRequest: """The `client/unregisterCapability` request is sent from the server to the client to unregister a previously registered capability handler on the client side.""" id: Union[int, str] = attrs.field() """The request id.""" params: UnregistrationParams = attrs.field() - method: str = "client/unregisterCapability" + method: Literal["client/unregisterCapability"] = "client/unregisterCapability" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @attrs.define -class ClientUnregisterCapabilityResponse: +class UnregistrationResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" result: None = attrs.field(default=None) @@ -9780,7 +10739,7 @@ class InitializeRequest: id: Union[int, str] = attrs.field() """The request id.""" params: InitializeParams = attrs.field() - method: str = "initialize" + method: Literal["initialize"] = "initialize" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @@ -9803,7 +10762,7 @@ class ShutdownRequest: id: Union[int, str] = attrs.field() """The request id.""" params: Optional[None] = attrs.field(default=None) - method: str = "shutdown" + method: Literal["shutdown"] = "shutdown" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @@ -9816,29 +10775,35 @@ class ShutdownResponse: jsonrpc: str = attrs.field(default="2.0") +ShowMessageResult = Union[MessageActionItem, None] + + @attrs.define -class WindowShowMessageRequestRequest: +class ShowMessageRequest: """The show message request is sent from the server to the client to show a message and a set of options actions to the user.""" id: Union[int, str] = attrs.field() """The request id.""" params: ShowMessageRequestParams = attrs.field() - method: str = "window/showMessageRequest" + method: Literal["window/showMessageRequest"] = "window/showMessageRequest" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @attrs.define -class WindowShowMessageRequestResponse: +class ShowMessageResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" - result: Union[MessageActionItem, None] = attrs.field(default=None) + result: Optional[ShowMessageResult] = attrs.field(default=None) jsonrpc: str = attrs.field(default="2.0") +WillSaveTextDocumentWaitUntilResult = Union[Sequence[TextEdit], None] + + @attrs.define -class TextDocumentWillSaveWaitUntilRequest: +class WillSaveTextDocumentWaitUntilRequest: """A document will save request is sent from the client to the server before the document is actually saved. The request can return an array of TextEdits which will be applied to the text document before it is saved. Please note that @@ -9849,21 +10814,24 @@ class TextDocumentWillSaveWaitUntilRequest: id: Union[int, str] = attrs.field() """The request id.""" params: WillSaveTextDocumentParams = attrs.field() - method: str = "textDocument/willSaveWaitUntil" + method: Literal["textDocument/willSaveWaitUntil"] = "textDocument/willSaveWaitUntil" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @attrs.define -class TextDocumentWillSaveWaitUntilResponse: +class WillSaveTextDocumentWaitUntilResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" - result: Union[List[TextEdit], None] = attrs.field(default=None) + result: Optional[WillSaveTextDocumentWaitUntilResult] = attrs.field(default=None) jsonrpc: str = attrs.field(default="2.0") +CompletionResult = Union[Sequence[CompletionItem], CompletionList, None] + + @attrs.define -class TextDocumentCompletionRequest: +class CompletionRequest: """Request to request completion at a given text document position. The request's parameter is of type {@link TextDocumentPosition} the response is of type {@link CompletionItem CompletionItem[]} or {@link CompletionList} @@ -9877,23 +10845,21 @@ class TextDocumentCompletionRequest: id: Union[int, str] = attrs.field() """The request id.""" params: CompletionParams = attrs.field() - method: str = "textDocument/completion" + method: Literal["textDocument/completion"] = "textDocument/completion" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @attrs.define -class TextDocumentCompletionResponse: +class CompletionResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" - result: Union[List[CompletionItem], CompletionList, None] = attrs.field( - default=None - ) + result: Optional[CompletionResult] = attrs.field(default=None) jsonrpc: str = attrs.field(default="2.0") @attrs.define -class CompletionItemResolveRequest: +class CompletionResolveRequest: """Request to resolve additional information for a given completion item.The request's parameter is of type {@link CompletionItem} the response is of type {@link CompletionItem} or a Thenable that resolves to such.""" @@ -9901,21 +10867,24 @@ class CompletionItemResolveRequest: id: Union[int, str] = attrs.field() """The request id.""" params: CompletionItem = attrs.field() - method: str = "completionItem/resolve" + method: Literal["completionItem/resolve"] = "completionItem/resolve" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @attrs.define -class CompletionItemResolveResponse: +class CompletionResolveResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" result: CompletionItem = attrs.field(default=None) jsonrpc: str = attrs.field(default="2.0") +HoverResult = Union[Hover, None] + + @attrs.define -class TextDocumentHoverRequest: +class HoverRequest: """Request to request hover information at a given text document position. The request's parameter is of type {@link TextDocumentPosition} the response is of type {@link Hover} or a Thenable that resolves to such.""" @@ -9923,39 +10892,45 @@ class TextDocumentHoverRequest: id: Union[int, str] = attrs.field() """The request id.""" params: HoverParams = attrs.field() - method: str = "textDocument/hover" + method: Literal["textDocument/hover"] = "textDocument/hover" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @attrs.define -class TextDocumentHoverResponse: +class HoverResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" - result: Union[Hover, None] = attrs.field(default=None) + result: Optional[HoverResult] = attrs.field(default=None) jsonrpc: str = attrs.field(default="2.0") +SignatureHelpResult = Union[SignatureHelp, None] + + @attrs.define -class TextDocumentSignatureHelpRequest: +class SignatureHelpRequest: id: Union[int, str] = attrs.field() """The request id.""" params: SignatureHelpParams = attrs.field() - method: str = "textDocument/signatureHelp" + method: Literal["textDocument/signatureHelp"] = "textDocument/signatureHelp" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @attrs.define -class TextDocumentSignatureHelpResponse: +class SignatureHelpResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" - result: Union[SignatureHelp, None] = attrs.field(default=None) + result: Optional[SignatureHelpResult] = attrs.field(default=None) jsonrpc: str = attrs.field(default="2.0") +DefinitionResult = Union[Definition, Sequence[DefinitionLink], None] + + @attrs.define -class TextDocumentDefinitionRequest: +class DefinitionRequest: """A request to resolve the definition location of a symbol at a given text document position. The request's parameter is of type {@link TextDocumentPosition} the response is of either type {@link Definition} or a typed array of @@ -9964,21 +10939,24 @@ class TextDocumentDefinitionRequest: id: Union[int, str] = attrs.field() """The request id.""" params: DefinitionParams = attrs.field() - method: str = "textDocument/definition" + method: Literal["textDocument/definition"] = "textDocument/definition" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @attrs.define -class TextDocumentDefinitionResponse: +class DefinitionResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" - result: Union[Definition, List[DefinitionLink], None] = attrs.field(default=None) + result: Optional[DefinitionResult] = attrs.field(default=None) jsonrpc: str = attrs.field(default="2.0") +ReferencesResult = Union[Sequence[Location], None] + + @attrs.define -class TextDocumentReferencesRequest: +class ReferencesRequest: """A request to resolve project-wide references for the symbol denoted by the given text document position. The request's parameter is of type {@link ReferenceParams} the response is of type @@ -9987,21 +10965,24 @@ class TextDocumentReferencesRequest: id: Union[int, str] = attrs.field() """The request id.""" params: ReferenceParams = attrs.field() - method: str = "textDocument/references" + method: Literal["textDocument/references"] = "textDocument/references" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @attrs.define -class TextDocumentReferencesResponse: +class ReferencesResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" - result: Union[List[Location], None] = attrs.field(default=None) + result: Optional[ReferencesResult] = attrs.field(default=None) jsonrpc: str = attrs.field(default="2.0") +DocumentHighlightResult = Union[Sequence[DocumentHighlight], None] + + @attrs.define -class TextDocumentDocumentHighlightRequest: +class DocumentHighlightRequest: """Request to resolve a {@link DocumentHighlight} for a given text document position. The request's parameter is of type {@link TextDocumentPosition} the request response is an array of type {@link DocumentHighlight} @@ -10010,21 +10991,26 @@ class TextDocumentDocumentHighlightRequest: id: Union[int, str] = attrs.field() """The request id.""" params: DocumentHighlightParams = attrs.field() - method: str = "textDocument/documentHighlight" + method: Literal["textDocument/documentHighlight"] = "textDocument/documentHighlight" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @attrs.define -class TextDocumentDocumentHighlightResponse: +class DocumentHighlightResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" - result: Union[List[DocumentHighlight], None] = attrs.field(default=None) + result: Optional[DocumentHighlightResult] = attrs.field(default=None) jsonrpc: str = attrs.field(default="2.0") +DocumentSymbolResult = Union[ + Sequence[SymbolInformation], Sequence[DocumentSymbol], None +] + + @attrs.define -class TextDocumentDocumentSymbolRequest: +class DocumentSymbolRequest: """A request to list all symbols found in a given text document. The request's parameter is of type {@link TextDocumentIdentifier} the response is of type {@link SymbolInformation SymbolInformation[]} or a Thenable @@ -10033,38 +11019,39 @@ class TextDocumentDocumentSymbolRequest: id: Union[int, str] = attrs.field() """The request id.""" params: DocumentSymbolParams = attrs.field() - method: str = "textDocument/documentSymbol" + method: Literal["textDocument/documentSymbol"] = "textDocument/documentSymbol" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @attrs.define -class TextDocumentDocumentSymbolResponse: +class DocumentSymbolResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" - result: Union[List[SymbolInformation], List[DocumentSymbol], None] = attrs.field( - default=None - ) + result: Optional[DocumentSymbolResult] = attrs.field(default=None) jsonrpc: str = attrs.field(default="2.0") +CodeActionResult = Union[Sequence[Union[Command, CodeAction]], None] + + @attrs.define -class TextDocumentCodeActionRequest: +class CodeActionRequest: """A request to provide commands for the given text document and range.""" id: Union[int, str] = attrs.field() """The request id.""" params: CodeActionParams = attrs.field() - method: str = "textDocument/codeAction" + method: Literal["textDocument/codeAction"] = "textDocument/codeAction" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @attrs.define -class TextDocumentCodeActionResponse: +class CodeActionResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" - result: Union[List[Union[Command, CodeAction]], None] = attrs.field(default=None) + result: Optional[CodeActionResult] = attrs.field(default=None) jsonrpc: str = attrs.field(default="2.0") @@ -10077,7 +11064,7 @@ class CodeActionResolveRequest: id: Union[int, str] = attrs.field() """The request id.""" params: CodeAction = attrs.field() - method: str = "codeAction/resolve" + method: Literal["codeAction/resolve"] = "codeAction/resolve" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @@ -10090,6 +11077,11 @@ class CodeActionResolveResponse: jsonrpc: str = attrs.field(default="2.0") +WorkspaceSymbolResult = Union[ + Sequence[SymbolInformation], Sequence[WorkspaceSymbol], None +] + + @attrs.define class WorkspaceSymbolRequest: """A request to list project-wide symbols matching the query string given @@ -10104,7 +11096,7 @@ class WorkspaceSymbolRequest: id: Union[int, str] = attrs.field() """The request id.""" params: WorkspaceSymbolParams = attrs.field() - method: str = "workspace/symbol" + method: Literal["workspace/symbol"] = "workspace/symbol" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @@ -10113,9 +11105,7 @@ class WorkspaceSymbolRequest: class WorkspaceSymbolResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" - result: Union[List[SymbolInformation], List[WorkspaceSymbol], None] = attrs.field( - default=None - ) + result: Optional[WorkspaceSymbolResult] = attrs.field(default=None) jsonrpc: str = attrs.field(default="2.0") @@ -10129,7 +11119,7 @@ class WorkspaceSymbolResolveRequest: id: Union[int, str] = attrs.field() """The request id.""" params: WorkspaceSymbol = attrs.field() - method: str = "workspaceSymbol/resolve" + method: Literal["workspaceSymbol/resolve"] = "workspaceSymbol/resolve" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @@ -10142,23 +11132,26 @@ class WorkspaceSymbolResolveResponse: jsonrpc: str = attrs.field(default="2.0") +CodeLensResult = Union[Sequence[CodeLens], None] + + @attrs.define -class TextDocumentCodeLensRequest: +class CodeLensRequest: """A request to provide code lens for the given text document.""" id: Union[int, str] = attrs.field() """The request id.""" params: CodeLensParams = attrs.field() - method: str = "textDocument/codeLens" + method: Literal["textDocument/codeLens"] = "textDocument/codeLens" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @attrs.define -class TextDocumentCodeLensResponse: +class CodeLensResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" - result: Union[List[CodeLens], None] = attrs.field(default=None) + result: Optional[CodeLensResult] = attrs.field(default=None) jsonrpc: str = attrs.field(default="2.0") @@ -10169,7 +11162,7 @@ class CodeLensResolveRequest: id: Union[int, str] = attrs.field() """The request id.""" params: CodeLens = attrs.field() - method: str = "codeLens/resolve" + method: Literal["codeLens/resolve"] = "codeLens/resolve" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @@ -10183,7 +11176,7 @@ class CodeLensResolveResponse: @attrs.define -class WorkspaceCodeLensRefreshRequest: +class CodeLensRefreshRequest: """A request to refresh all code actions @since 3.16.0""" @@ -10191,36 +11184,39 @@ class WorkspaceCodeLensRefreshRequest: id: Union[int, str] = attrs.field() """The request id.""" params: Optional[None] = attrs.field(default=None) - method: str = "workspace/codeLens/refresh" + method: Literal["workspace/codeLens/refresh"] = "workspace/codeLens/refresh" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @attrs.define -class WorkspaceCodeLensRefreshResponse: +class CodeLensRefreshResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" result: None = attrs.field(default=None) jsonrpc: str = attrs.field(default="2.0") +DocumentLinkResult = Union[Sequence[DocumentLink], None] + + @attrs.define -class TextDocumentDocumentLinkRequest: +class DocumentLinkRequest: """A request to provide document links""" id: Union[int, str] = attrs.field() """The request id.""" params: DocumentLinkParams = attrs.field() - method: str = "textDocument/documentLink" + method: Literal["textDocument/documentLink"] = "textDocument/documentLink" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @attrs.define -class TextDocumentDocumentLinkResponse: +class DocumentLinkResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" - result: Union[List[DocumentLink], None] = attrs.field(default=None) + result: Optional[DocumentLinkResult] = attrs.field(default=None) jsonrpc: str = attrs.field(default="2.0") @@ -10233,7 +11229,7 @@ class DocumentLinkResolveRequest: id: Union[int, str] = attrs.field() """The request id.""" params: DocumentLink = attrs.field() - method: str = "documentLink/resolve" + method: Literal["documentLink/resolve"] = "documentLink/resolve" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @@ -10246,48 +11242,57 @@ class DocumentLinkResolveResponse: jsonrpc: str = attrs.field(default="2.0") +DocumentFormattingResult = Union[Sequence[TextEdit], None] + + @attrs.define -class TextDocumentFormattingRequest: +class DocumentFormattingRequest: """A request to format a whole document.""" id: Union[int, str] = attrs.field() """The request id.""" params: DocumentFormattingParams = attrs.field() - method: str = "textDocument/formatting" + method: Literal["textDocument/formatting"] = "textDocument/formatting" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @attrs.define -class TextDocumentFormattingResponse: +class DocumentFormattingResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" - result: Union[List[TextEdit], None] = attrs.field(default=None) + result: Optional[DocumentFormattingResult] = attrs.field(default=None) jsonrpc: str = attrs.field(default="2.0") +DocumentRangeFormattingResult = Union[Sequence[TextEdit], None] + + @attrs.define -class TextDocumentRangeFormattingRequest: +class DocumentRangeFormattingRequest: """A request to format a range in a document.""" id: Union[int, str] = attrs.field() """The request id.""" params: DocumentRangeFormattingParams = attrs.field() - method: str = "textDocument/rangeFormatting" + method: Literal["textDocument/rangeFormatting"] = "textDocument/rangeFormatting" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @attrs.define -class TextDocumentRangeFormattingResponse: +class DocumentRangeFormattingResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" - result: Union[List[TextEdit], None] = attrs.field(default=None) + result: Optional[DocumentRangeFormattingResult] = attrs.field(default=None) jsonrpc: str = attrs.field(default="2.0") +DocumentRangesFormattingResult = Union[Sequence[TextEdit], None] + + @attrs.define -class TextDocumentRangesFormattingRequest: +class DocumentRangesFormattingRequest: """A request to format ranges in a document. @since 3.18.0 @@ -10296,61 +11301,67 @@ class TextDocumentRangesFormattingRequest: id: Union[int, str] = attrs.field() """The request id.""" params: DocumentRangesFormattingParams = attrs.field() - method: str = "textDocument/rangesFormatting" + method: Literal["textDocument/rangesFormatting"] = "textDocument/rangesFormatting" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @attrs.define -class TextDocumentRangesFormattingResponse: +class DocumentRangesFormattingResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" - result: Union[List[TextEdit], None] = attrs.field(default=None) + result: Optional[DocumentRangesFormattingResult] = attrs.field(default=None) jsonrpc: str = attrs.field(default="2.0") +DocumentOnTypeFormattingResult = Union[Sequence[TextEdit], None] + + @attrs.define -class TextDocumentOnTypeFormattingRequest: +class DocumentOnTypeFormattingRequest: """A request to format a document on type.""" id: Union[int, str] = attrs.field() """The request id.""" params: DocumentOnTypeFormattingParams = attrs.field() - method: str = "textDocument/onTypeFormatting" + method: Literal["textDocument/onTypeFormatting"] = "textDocument/onTypeFormatting" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @attrs.define -class TextDocumentOnTypeFormattingResponse: +class DocumentOnTypeFormattingResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" - result: Union[List[TextEdit], None] = attrs.field(default=None) + result: Optional[DocumentOnTypeFormattingResult] = attrs.field(default=None) jsonrpc: str = attrs.field(default="2.0") +RenameResult = Union[WorkspaceEdit, None] + + @attrs.define -class TextDocumentRenameRequest: +class RenameRequest: """A request to rename a symbol.""" id: Union[int, str] = attrs.field() """The request id.""" params: RenameParams = attrs.field() - method: str = "textDocument/rename" + method: Literal["textDocument/rename"] = "textDocument/rename" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @attrs.define -class TextDocumentRenameResponse: +class RenameResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" - result: Union[WorkspaceEdit, None] = attrs.field(default=None) + result: Optional[RenameResult] = attrs.field(default=None) jsonrpc: str = attrs.field(default="2.0") @attrs.define -class TextDocumentPrepareRenameRequest: +class PrepareRenameRequest: """A request to test and perform the setup necessary for a rename. @since 3.16 - support for default behavior""" @@ -10358,54 +11369,57 @@ class TextDocumentPrepareRenameRequest: id: Union[int, str] = attrs.field() """The request id.""" params: PrepareRenameParams = attrs.field() - method: str = "textDocument/prepareRename" + method: Literal["textDocument/prepareRename"] = "textDocument/prepareRename" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @attrs.define -class TextDocumentPrepareRenameResponse: +class PrepareRenameResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" - result: Union[PrepareRenameResult, None] = attrs.field(default=None) + result: Optional[PrepareRenameResult] = attrs.field(default=None) jsonrpc: str = attrs.field(default="2.0") +ExecuteCommandResult = Union[LSPAny, None] + + @attrs.define -class WorkspaceExecuteCommandRequest: +class ExecuteCommandRequest: """A request send from the client to the server to execute a command. The request might return a workspace edit which the client will apply to the workspace.""" id: Union[int, str] = attrs.field() """The request id.""" params: ExecuteCommandParams = attrs.field() - method: str = "workspace/executeCommand" + method: Literal["workspace/executeCommand"] = "workspace/executeCommand" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @attrs.define -class WorkspaceExecuteCommandResponse: +class ExecuteCommandResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" - result: Union[LSPAny, None] = attrs.field(default=None) + result: Optional[ExecuteCommandResult] = attrs.field(default=None) jsonrpc: str = attrs.field(default="2.0") @attrs.define -class WorkspaceApplyEditRequest: +class ApplyWorkspaceEditRequest: """A request sent from the server to the client to modified certain resources.""" id: Union[int, str] = attrs.field() """The request id.""" params: ApplyWorkspaceEditParams = attrs.field() - method: str = "workspace/applyEdit" + method: Literal["workspace/applyEdit"] = "workspace/applyEdit" """The method to be invoked.""" jsonrpc: str = attrs.field(default="2.0") @attrs.define -class WorkspaceApplyEditResponse: +class ApplyWorkspaceEditResponse: id: Optional[Union[int, str]] = attrs.field() """The request id.""" result: ApplyWorkspaceEditResult = attrs.field(default=None) @@ -10413,12 +11427,12 @@ class WorkspaceApplyEditResponse: @attrs.define -class WorkspaceDidChangeWorkspaceFoldersNotification: +class DidChangeWorkspaceFoldersNotification: """The `workspace/didChangeWorkspaceFolders` notification is sent from the client to the server when the workspace folder configuration changes.""" params: DidChangeWorkspaceFoldersParams = attrs.field() - method: str = attrs.field( + method: Literal["workspace/didChangeWorkspaceFolders"] = attrs.field( validator=attrs.validators.in_(["workspace/didChangeWorkspaceFolders"]), default="workspace/didChangeWorkspaceFolders", ) @@ -10427,12 +11441,12 @@ class WorkspaceDidChangeWorkspaceFoldersNotification: @attrs.define -class WindowWorkDoneProgressCancelNotification: +class WorkDoneProgressCancelNotification: """The `window/workDoneProgress/cancel` notification is sent from the client to the server to cancel a progress initiated on the server side.""" params: WorkDoneProgressCancelParams = attrs.field() - method: str = attrs.field( + method: Literal["window/workDoneProgress/cancel"] = attrs.field( validator=attrs.validators.in_(["window/workDoneProgress/cancel"]), default="window/workDoneProgress/cancel", ) @@ -10441,14 +11455,14 @@ class WindowWorkDoneProgressCancelNotification: @attrs.define -class WorkspaceDidCreateFilesNotification: +class DidCreateFilesNotification: """The did create files notification is sent from the client to the server when files were created from within the client. @since 3.16.0""" params: CreateFilesParams = attrs.field() - method: str = attrs.field( + method: Literal["workspace/didCreateFiles"] = attrs.field( validator=attrs.validators.in_(["workspace/didCreateFiles"]), default="workspace/didCreateFiles", ) @@ -10457,14 +11471,14 @@ class WorkspaceDidCreateFilesNotification: @attrs.define -class WorkspaceDidRenameFilesNotification: +class DidRenameFilesNotification: """The did rename files notification is sent from the client to the server when files were renamed from within the client. @since 3.16.0""" params: RenameFilesParams = attrs.field() - method: str = attrs.field( + method: Literal["workspace/didRenameFiles"] = attrs.field( validator=attrs.validators.in_(["workspace/didRenameFiles"]), default="workspace/didRenameFiles", ) @@ -10473,14 +11487,14 @@ class WorkspaceDidRenameFilesNotification: @attrs.define -class WorkspaceDidDeleteFilesNotification: +class DidDeleteFilesNotification: """The will delete files request is sent from the client to the server before files are actually deleted as long as the deletion is triggered from within the client. @since 3.16.0""" params: DeleteFilesParams = attrs.field() - method: str = attrs.field( + method: Literal["workspace/didDeleteFiles"] = attrs.field( validator=attrs.validators.in_(["workspace/didDeleteFiles"]), default="workspace/didDeleteFiles", ) @@ -10489,13 +11503,13 @@ class WorkspaceDidDeleteFilesNotification: @attrs.define -class NotebookDocumentDidOpenNotification: +class DidOpenNotebookDocumentNotification: """A notification sent when a notebook opens. @since 3.17.0""" params: DidOpenNotebookDocumentParams = attrs.field() - method: str = attrs.field( + method: Literal["notebookDocument/didOpen"] = attrs.field( validator=attrs.validators.in_(["notebookDocument/didOpen"]), default="notebookDocument/didOpen", ) @@ -10504,9 +11518,9 @@ class NotebookDocumentDidOpenNotification: @attrs.define -class NotebookDocumentDidChangeNotification: +class DidChangeNotebookDocumentNotification: params: DidChangeNotebookDocumentParams = attrs.field() - method: str = attrs.field( + method: Literal["notebookDocument/didChange"] = attrs.field( validator=attrs.validators.in_(["notebookDocument/didChange"]), default="notebookDocument/didChange", ) @@ -10515,13 +11529,13 @@ class NotebookDocumentDidChangeNotification: @attrs.define -class NotebookDocumentDidSaveNotification: +class DidSaveNotebookDocumentNotification: """A notification sent when a notebook document is saved. @since 3.17.0""" params: DidSaveNotebookDocumentParams = attrs.field() - method: str = attrs.field( + method: Literal["notebookDocument/didSave"] = attrs.field( validator=attrs.validators.in_(["notebookDocument/didSave"]), default="notebookDocument/didSave", ) @@ -10530,13 +11544,13 @@ class NotebookDocumentDidSaveNotification: @attrs.define -class NotebookDocumentDidCloseNotification: +class DidCloseNotebookDocumentNotification: """A notification sent when a notebook closes. @since 3.17.0""" params: DidCloseNotebookDocumentParams = attrs.field() - method: str = attrs.field( + method: Literal["notebookDocument/didClose"] = attrs.field( validator=attrs.validators.in_(["notebookDocument/didClose"]), default="notebookDocument/didClose", ) @@ -10551,7 +11565,7 @@ class InitializedNotification: is allowed to send requests from the server to the client.""" params: InitializedParams = attrs.field() - method: str = attrs.field( + method: Literal["initialized"] = attrs.field( validator=attrs.validators.in_(["initialized"]), default="initialized", ) @@ -10565,7 +11579,7 @@ class ExitNotification: ask the server to exit its process.""" params: Optional[None] = attrs.field(default=None) - method: str = attrs.field( + method: Literal["exit"] = attrs.field( validator=attrs.validators.in_(["exit"]), default="exit", ) @@ -10574,13 +11588,13 @@ class ExitNotification: @attrs.define -class WorkspaceDidChangeConfigurationNotification: +class DidChangeConfigurationNotification: """The configuration change notification is sent from the client to the server when the client's configuration has changed. The notification contains the changed configuration as defined by the language client.""" params: DidChangeConfigurationParams = attrs.field() - method: str = attrs.field( + method: Literal["workspace/didChangeConfiguration"] = attrs.field( validator=attrs.validators.in_(["workspace/didChangeConfiguration"]), default="workspace/didChangeConfiguration", ) @@ -10589,12 +11603,12 @@ class WorkspaceDidChangeConfigurationNotification: @attrs.define -class WindowShowMessageNotification: +class ShowMessageNotification: """The show message notification is sent from a server to a client to ask the client to display a particular message in the user interface.""" params: ShowMessageParams = attrs.field() - method: str = attrs.field( + method: Literal["window/showMessage"] = attrs.field( validator=attrs.validators.in_(["window/showMessage"]), default="window/showMessage", ) @@ -10603,12 +11617,12 @@ class WindowShowMessageNotification: @attrs.define -class WindowLogMessageNotification: +class LogMessageNotification: """The log message notification is sent from the server to the client to ask the client to log a particular message.""" params: LogMessageParams = attrs.field() - method: str = attrs.field( + method: Literal["window/logMessage"] = attrs.field( validator=attrs.validators.in_(["window/logMessage"]), default="window/logMessage", ) @@ -10622,7 +11636,7 @@ class TelemetryEventNotification: the client to log telemetry data.""" params: LSPAny = attrs.field() - method: str = attrs.field( + method: Literal["telemetry/event"] = attrs.field( validator=attrs.validators.in_(["telemetry/event"]), default="telemetry/event", ) @@ -10631,7 +11645,7 @@ class TelemetryEventNotification: @attrs.define -class TextDocumentDidOpenNotification: +class DidOpenTextDocumentNotification: """The document open notification is sent from the client to the server to signal newly opened text documents. The document's truth is now managed by the client and the server must not try to read the document's truth using the document's @@ -10642,7 +11656,7 @@ class TextDocumentDidOpenNotification: is one.""" params: DidOpenTextDocumentParams = attrs.field() - method: str = attrs.field( + method: Literal["textDocument/didOpen"] = attrs.field( validator=attrs.validators.in_(["textDocument/didOpen"]), default="textDocument/didOpen", ) @@ -10651,12 +11665,12 @@ class TextDocumentDidOpenNotification: @attrs.define -class TextDocumentDidChangeNotification: +class DidChangeTextDocumentNotification: """The document change notification is sent from the client to the server to signal changes to a text document.""" params: DidChangeTextDocumentParams = attrs.field() - method: str = attrs.field( + method: Literal["textDocument/didChange"] = attrs.field( validator=attrs.validators.in_(["textDocument/didChange"]), default="textDocument/didChange", ) @@ -10665,7 +11679,7 @@ class TextDocumentDidChangeNotification: @attrs.define -class TextDocumentDidCloseNotification: +class DidCloseTextDocumentNotification: """The document close notification is sent from the client to the server when the document got closed in the client. The document's truth now exists where the document's uri points to (e.g. if the document's uri is a file uri the @@ -10675,7 +11689,7 @@ class TextDocumentDidCloseNotification: notification requires a previous open notification to be sent.""" params: DidCloseTextDocumentParams = attrs.field() - method: str = attrs.field( + method: Literal["textDocument/didClose"] = attrs.field( validator=attrs.validators.in_(["textDocument/didClose"]), default="textDocument/didClose", ) @@ -10684,12 +11698,12 @@ class TextDocumentDidCloseNotification: @attrs.define -class TextDocumentDidSaveNotification: +class DidSaveTextDocumentNotification: """The document save notification is sent from the client to the server when the document got saved in the client.""" params: DidSaveTextDocumentParams = attrs.field() - method: str = attrs.field( + method: Literal["textDocument/didSave"] = attrs.field( validator=attrs.validators.in_(["textDocument/didSave"]), default="textDocument/didSave", ) @@ -10698,12 +11712,12 @@ class TextDocumentDidSaveNotification: @attrs.define -class TextDocumentWillSaveNotification: +class WillSaveTextDocumentNotification: """A document will save notification is sent from the client to the server before the document is actually saved.""" params: WillSaveTextDocumentParams = attrs.field() - method: str = attrs.field( + method: Literal["textDocument/willSave"] = attrs.field( validator=attrs.validators.in_(["textDocument/willSave"]), default="textDocument/willSave", ) @@ -10712,12 +11726,12 @@ class TextDocumentWillSaveNotification: @attrs.define -class WorkspaceDidChangeWatchedFilesNotification: +class DidChangeWatchedFilesNotification: """The watched files notification is sent from the client to the server when the client detects changes to file watched by the language client.""" params: DidChangeWatchedFilesParams = attrs.field() - method: str = attrs.field( + method: Literal["workspace/didChangeWatchedFiles"] = attrs.field( validator=attrs.validators.in_(["workspace/didChangeWatchedFiles"]), default="workspace/didChangeWatchedFiles", ) @@ -10726,12 +11740,12 @@ class WorkspaceDidChangeWatchedFilesNotification: @attrs.define -class TextDocumentPublishDiagnosticsNotification: +class PublishDiagnosticsNotification: """Diagnostics notification are sent from the server to the client to signal results of validation runs.""" params: PublishDiagnosticsParams = attrs.field() - method: str = attrs.field( + method: Literal["textDocument/publishDiagnostics"] = attrs.field( validator=attrs.validators.in_(["textDocument/publishDiagnostics"]), default="textDocument/publishDiagnostics", ) @@ -10742,7 +11756,7 @@ class TextDocumentPublishDiagnosticsNotification: @attrs.define class SetTraceNotification: params: SetTraceParams = attrs.field() - method: str = attrs.field( + method: Literal["$/setTrace"] = attrs.field( validator=attrs.validators.in_(["$/setTrace"]), default="$/setTrace", ) @@ -10753,7 +11767,7 @@ class SetTraceNotification: @attrs.define class LogTraceNotification: params: LogTraceParams = attrs.field() - method: str = attrs.field( + method: Literal["$/logTrace"] = attrs.field( validator=attrs.validators.in_(["$/logTrace"]), default="$/logTrace", ) @@ -10762,9 +11776,9 @@ class LogTraceNotification: @attrs.define -class CancelRequestNotification: +class CancelNotification: params: CancelParams = attrs.field() - method: str = attrs.field( + method: Literal["$/cancelRequest"] = attrs.field( validator=attrs.validators.in_(["$/cancelRequest"]), default="$/cancelRequest", ) @@ -10775,7 +11789,7 @@ class CancelRequestNotification: @attrs.define class ProgressNotification: params: ProgressParams = attrs.field() - method: str = attrs.field( + method: Literal["$/progress"] = attrs.field( validator=attrs.validators.in_(["$/progress"]), default="$/progress", ) @@ -10879,6 +11893,8 @@ WORKSPACE_INLINE_VALUE_REFRESH = "workspace/inlineValue/refresh" WORKSPACE_SEMANTIC_TOKENS_REFRESH = "workspace/semanticTokens/refresh" WORKSPACE_SYMBOL = "workspace/symbol" WORKSPACE_SYMBOL_RESOLVE = "workspaceSymbol/resolve" +WORKSPACE_TEXT_DOCUMENT_CONTENT = "workspace/textDocumentContent" +WORKSPACE_TEXT_DOCUMENT_CONTENT_REFRESH = "workspace/textDocumentContent/refresh" WORKSPACE_WILL_CREATE_FILES = "workspace/willCreateFiles" WORKSPACE_WILL_DELETE_FILES = "workspace/willDeleteFiles" WORKSPACE_WILL_RENAME_FILES = "workspace/willRenameFiles" @@ -10899,14 +11915,14 @@ METHOD_TO_TYPES = { None, ), CLIENT_REGISTER_CAPABILITY: ( - ClientRegisterCapabilityRequest, - ClientRegisterCapabilityResponse, + RegistrationRequest, + RegistrationResponse, RegistrationParams, None, ), CLIENT_UNREGISTER_CAPABILITY: ( - ClientUnregisterCapabilityRequest, - ClientUnregisterCapabilityResponse, + UnregistrationRequest, + UnregistrationResponse, UnregistrationParams, None, ), @@ -10923,8 +11939,8 @@ METHOD_TO_TYPES = { None, ), COMPLETION_ITEM_RESOLVE: ( - CompletionItemResolveRequest, - CompletionItemResolveResponse, + CompletionResolveRequest, + CompletionResolveResponse, CompletionItem, None, ), @@ -10943,212 +11959,212 @@ METHOD_TO_TYPES = { ), SHUTDOWN: (ShutdownRequest, ShutdownResponse, None, None), TEXT_DOCUMENT_CODE_ACTION: ( - TextDocumentCodeActionRequest, - TextDocumentCodeActionResponse, + CodeActionRequest, + CodeActionResponse, CodeActionParams, CodeActionRegistrationOptions, ), TEXT_DOCUMENT_CODE_LENS: ( - TextDocumentCodeLensRequest, - TextDocumentCodeLensResponse, + CodeLensRequest, + CodeLensResponse, CodeLensParams, CodeLensRegistrationOptions, ), TEXT_DOCUMENT_COLOR_PRESENTATION: ( - TextDocumentColorPresentationRequest, - TextDocumentColorPresentationResponse, + ColorPresentationRequest, + ColorPresentationResponse, ColorPresentationParams, - TextDocumentColorPresentationOptions, + ColorPresentationRequestOptions, ), TEXT_DOCUMENT_COMPLETION: ( - TextDocumentCompletionRequest, - TextDocumentCompletionResponse, + CompletionRequest, + CompletionResponse, CompletionParams, CompletionRegistrationOptions, ), TEXT_DOCUMENT_DECLARATION: ( - TextDocumentDeclarationRequest, - TextDocumentDeclarationResponse, + DeclarationRequest, + DeclarationResponse, DeclarationParams, DeclarationRegistrationOptions, ), TEXT_DOCUMENT_DEFINITION: ( - TextDocumentDefinitionRequest, - TextDocumentDefinitionResponse, + DefinitionRequest, + DefinitionResponse, DefinitionParams, DefinitionRegistrationOptions, ), TEXT_DOCUMENT_DIAGNOSTIC: ( - TextDocumentDiagnosticRequest, - TextDocumentDiagnosticResponse, + DocumentDiagnosticRequest, + DocumentDiagnosticResponse, DocumentDiagnosticParams, DiagnosticRegistrationOptions, ), TEXT_DOCUMENT_DOCUMENT_COLOR: ( - TextDocumentDocumentColorRequest, - TextDocumentDocumentColorResponse, + DocumentColorRequest, + DocumentColorResponse, DocumentColorParams, DocumentColorRegistrationOptions, ), TEXT_DOCUMENT_DOCUMENT_HIGHLIGHT: ( - TextDocumentDocumentHighlightRequest, - TextDocumentDocumentHighlightResponse, + DocumentHighlightRequest, + DocumentHighlightResponse, DocumentHighlightParams, DocumentHighlightRegistrationOptions, ), TEXT_DOCUMENT_DOCUMENT_LINK: ( - TextDocumentDocumentLinkRequest, - TextDocumentDocumentLinkResponse, + DocumentLinkRequest, + DocumentLinkResponse, DocumentLinkParams, DocumentLinkRegistrationOptions, ), TEXT_DOCUMENT_DOCUMENT_SYMBOL: ( - TextDocumentDocumentSymbolRequest, - TextDocumentDocumentSymbolResponse, + DocumentSymbolRequest, + DocumentSymbolResponse, DocumentSymbolParams, DocumentSymbolRegistrationOptions, ), TEXT_DOCUMENT_FOLDING_RANGE: ( - TextDocumentFoldingRangeRequest, - TextDocumentFoldingRangeResponse, + FoldingRangeRequest, + FoldingRangeResponse, FoldingRangeParams, FoldingRangeRegistrationOptions, ), TEXT_DOCUMENT_FORMATTING: ( - TextDocumentFormattingRequest, - TextDocumentFormattingResponse, + DocumentFormattingRequest, + DocumentFormattingResponse, DocumentFormattingParams, DocumentFormattingRegistrationOptions, ), TEXT_DOCUMENT_HOVER: ( - TextDocumentHoverRequest, - TextDocumentHoverResponse, + HoverRequest, + HoverResponse, HoverParams, HoverRegistrationOptions, ), TEXT_DOCUMENT_IMPLEMENTATION: ( - TextDocumentImplementationRequest, - TextDocumentImplementationResponse, + ImplementationRequest, + ImplementationResponse, ImplementationParams, ImplementationRegistrationOptions, ), TEXT_DOCUMENT_INLAY_HINT: ( - TextDocumentInlayHintRequest, - TextDocumentInlayHintResponse, + InlayHintRequest, + InlayHintResponse, InlayHintParams, InlayHintRegistrationOptions, ), TEXT_DOCUMENT_INLINE_COMPLETION: ( - TextDocumentInlineCompletionRequest, - TextDocumentInlineCompletionResponse, + InlineCompletionRequest, + InlineCompletionResponse, InlineCompletionParams, InlineCompletionRegistrationOptions, ), TEXT_DOCUMENT_INLINE_VALUE: ( - TextDocumentInlineValueRequest, - TextDocumentInlineValueResponse, + InlineValueRequest, + InlineValueResponse, InlineValueParams, InlineValueRegistrationOptions, ), TEXT_DOCUMENT_LINKED_EDITING_RANGE: ( - TextDocumentLinkedEditingRangeRequest, - TextDocumentLinkedEditingRangeResponse, + LinkedEditingRangeRequest, + LinkedEditingRangeResponse, LinkedEditingRangeParams, LinkedEditingRangeRegistrationOptions, ), TEXT_DOCUMENT_MONIKER: ( - TextDocumentMonikerRequest, - TextDocumentMonikerResponse, + MonikerRequest, + MonikerResponse, MonikerParams, MonikerRegistrationOptions, ), TEXT_DOCUMENT_ON_TYPE_FORMATTING: ( - TextDocumentOnTypeFormattingRequest, - TextDocumentOnTypeFormattingResponse, + DocumentOnTypeFormattingRequest, + DocumentOnTypeFormattingResponse, DocumentOnTypeFormattingParams, DocumentOnTypeFormattingRegistrationOptions, ), TEXT_DOCUMENT_PREPARE_CALL_HIERARCHY: ( - TextDocumentPrepareCallHierarchyRequest, - TextDocumentPrepareCallHierarchyResponse, + CallHierarchyPrepareRequest, + CallHierarchyPrepareResponse, CallHierarchyPrepareParams, CallHierarchyRegistrationOptions, ), TEXT_DOCUMENT_PREPARE_RENAME: ( - TextDocumentPrepareRenameRequest, - TextDocumentPrepareRenameResponse, + PrepareRenameRequest, + PrepareRenameResponse, PrepareRenameParams, None, ), TEXT_DOCUMENT_PREPARE_TYPE_HIERARCHY: ( - TextDocumentPrepareTypeHierarchyRequest, - TextDocumentPrepareTypeHierarchyResponse, + TypeHierarchyPrepareRequest, + TypeHierarchyPrepareResponse, TypeHierarchyPrepareParams, TypeHierarchyRegistrationOptions, ), TEXT_DOCUMENT_RANGES_FORMATTING: ( - TextDocumentRangesFormattingRequest, - TextDocumentRangesFormattingResponse, + DocumentRangesFormattingRequest, + DocumentRangesFormattingResponse, DocumentRangesFormattingParams, DocumentRangeFormattingRegistrationOptions, ), TEXT_DOCUMENT_RANGE_FORMATTING: ( - TextDocumentRangeFormattingRequest, - TextDocumentRangeFormattingResponse, + DocumentRangeFormattingRequest, + DocumentRangeFormattingResponse, DocumentRangeFormattingParams, DocumentRangeFormattingRegistrationOptions, ), TEXT_DOCUMENT_REFERENCES: ( - TextDocumentReferencesRequest, - TextDocumentReferencesResponse, + ReferencesRequest, + ReferencesResponse, ReferenceParams, ReferenceRegistrationOptions, ), TEXT_DOCUMENT_RENAME: ( - TextDocumentRenameRequest, - TextDocumentRenameResponse, + RenameRequest, + RenameResponse, RenameParams, RenameRegistrationOptions, ), TEXT_DOCUMENT_SELECTION_RANGE: ( - TextDocumentSelectionRangeRequest, - TextDocumentSelectionRangeResponse, + SelectionRangeRequest, + SelectionRangeResponse, SelectionRangeParams, SelectionRangeRegistrationOptions, ), TEXT_DOCUMENT_SEMANTIC_TOKENS_FULL: ( - TextDocumentSemanticTokensFullRequest, - TextDocumentSemanticTokensFullResponse, + SemanticTokensRequest, + SemanticTokensResponse, SemanticTokensParams, SemanticTokensRegistrationOptions, ), TEXT_DOCUMENT_SEMANTIC_TOKENS_FULL_DELTA: ( - TextDocumentSemanticTokensFullDeltaRequest, - TextDocumentSemanticTokensFullDeltaResponse, + SemanticTokensDeltaRequest, + SemanticTokensDeltaResponse, SemanticTokensDeltaParams, SemanticTokensRegistrationOptions, ), TEXT_DOCUMENT_SEMANTIC_TOKENS_RANGE: ( - TextDocumentSemanticTokensRangeRequest, - TextDocumentSemanticTokensRangeResponse, + SemanticTokensRangeRequest, + SemanticTokensRangeResponse, SemanticTokensRangeParams, None, ), TEXT_DOCUMENT_SIGNATURE_HELP: ( - TextDocumentSignatureHelpRequest, - TextDocumentSignatureHelpResponse, + SignatureHelpRequest, + SignatureHelpResponse, SignatureHelpParams, SignatureHelpRegistrationOptions, ), TEXT_DOCUMENT_TYPE_DEFINITION: ( - TextDocumentTypeDefinitionRequest, - TextDocumentTypeDefinitionResponse, + TypeDefinitionRequest, + TypeDefinitionResponse, TypeDefinitionParams, TypeDefinitionRegistrationOptions, ), TEXT_DOCUMENT_WILL_SAVE_WAIT_UNTIL: ( - TextDocumentWillSaveWaitUntilRequest, - TextDocumentWillSaveWaitUntilResponse, + WillSaveTextDocumentWaitUntilRequest, + WillSaveTextDocumentWaitUntilResponse, WillSaveTextDocumentParams, TextDocumentRegistrationOptions, ), @@ -11165,38 +12181,38 @@ METHOD_TO_TYPES = { None, ), WINDOW_SHOW_DOCUMENT: ( - WindowShowDocumentRequest, - WindowShowDocumentResponse, + ShowDocumentRequest, + ShowDocumentResponse, ShowDocumentParams, None, ), WINDOW_SHOW_MESSAGE_REQUEST: ( - WindowShowMessageRequestRequest, - WindowShowMessageRequestResponse, + ShowMessageRequest, + ShowMessageResponse, ShowMessageRequestParams, None, ), WINDOW_WORK_DONE_PROGRESS_CREATE: ( - WindowWorkDoneProgressCreateRequest, - WindowWorkDoneProgressCreateResponse, + WorkDoneProgressCreateRequest, + WorkDoneProgressCreateResponse, WorkDoneProgressCreateParams, None, ), WORKSPACE_APPLY_EDIT: ( - WorkspaceApplyEditRequest, - WorkspaceApplyEditResponse, + ApplyWorkspaceEditRequest, + ApplyWorkspaceEditResponse, ApplyWorkspaceEditParams, None, ), WORKSPACE_CODE_LENS_REFRESH: ( - WorkspaceCodeLensRefreshRequest, - WorkspaceCodeLensRefreshResponse, + CodeLensRefreshRequest, + CodeLensRefreshResponse, None, None, ), WORKSPACE_CONFIGURATION: ( - WorkspaceConfigurationRequest, - WorkspaceConfigurationResponse, + ConfigurationRequest, + ConfigurationResponse, ConfigurationParams, None, ), @@ -11207,38 +12223,38 @@ METHOD_TO_TYPES = { None, ), WORKSPACE_DIAGNOSTIC_REFRESH: ( - WorkspaceDiagnosticRefreshRequest, - WorkspaceDiagnosticRefreshResponse, + DiagnosticRefreshRequest, + DiagnosticRefreshResponse, None, None, ), WORKSPACE_EXECUTE_COMMAND: ( - WorkspaceExecuteCommandRequest, - WorkspaceExecuteCommandResponse, + ExecuteCommandRequest, + ExecuteCommandResponse, ExecuteCommandParams, ExecuteCommandRegistrationOptions, ), WORKSPACE_FOLDING_RANGE_REFRESH: ( - WorkspaceFoldingRangeRefreshRequest, - WorkspaceFoldingRangeRefreshResponse, + FoldingRangeRefreshRequest, + FoldingRangeRefreshResponse, None, None, ), WORKSPACE_INLAY_HINT_REFRESH: ( - WorkspaceInlayHintRefreshRequest, - WorkspaceInlayHintRefreshResponse, + InlayHintRefreshRequest, + InlayHintRefreshResponse, None, None, ), WORKSPACE_INLINE_VALUE_REFRESH: ( - WorkspaceInlineValueRefreshRequest, - WorkspaceInlineValueRefreshResponse, + InlineValueRefreshRequest, + InlineValueRefreshResponse, None, None, ), WORKSPACE_SEMANTIC_TOKENS_REFRESH: ( - WorkspaceSemanticTokensRefreshRequest, - WorkspaceSemanticTokensRefreshResponse, + SemanticTokensRefreshRequest, + SemanticTokensRefreshResponse, None, None, ), @@ -11254,308 +12270,324 @@ METHOD_TO_TYPES = { WorkspaceSymbol, None, ), + WORKSPACE_TEXT_DOCUMENT_CONTENT: ( + TextDocumentContentRequest, + TextDocumentContentResponse, + TextDocumentContentParams, + TextDocumentContentRegistrationOptions, + ), + WORKSPACE_TEXT_DOCUMENT_CONTENT_REFRESH: ( + TextDocumentContentRefreshRequest, + TextDocumentContentRefreshResponse, + TextDocumentContentRefreshParams, + None, + ), WORKSPACE_WILL_CREATE_FILES: ( - WorkspaceWillCreateFilesRequest, - WorkspaceWillCreateFilesResponse, + WillCreateFilesRequest, + WillCreateFilesResponse, CreateFilesParams, FileOperationRegistrationOptions, ), WORKSPACE_WILL_DELETE_FILES: ( - WorkspaceWillDeleteFilesRequest, - WorkspaceWillDeleteFilesResponse, + WillDeleteFilesRequest, + WillDeleteFilesResponse, DeleteFilesParams, FileOperationRegistrationOptions, ), WORKSPACE_WILL_RENAME_FILES: ( - WorkspaceWillRenameFilesRequest, - WorkspaceWillRenameFilesResponse, + WillRenameFilesRequest, + WillRenameFilesResponse, RenameFilesParams, FileOperationRegistrationOptions, ), WORKSPACE_WORKSPACE_FOLDERS: ( - WorkspaceWorkspaceFoldersRequest, - WorkspaceWorkspaceFoldersResponse, + WorkspaceFoldersRequest, + WorkspaceFoldersResponse, None, None, ), # Notifications - CANCEL_REQUEST: (CancelRequestNotification, None, CancelParams, None), + CANCEL_REQUEST: (CancelNotification, None, CancelParams, None), EXIT: (ExitNotification, None, None, None), INITIALIZED: (InitializedNotification, None, InitializedParams, None), LOG_TRACE: (LogTraceNotification, None, LogTraceParams, None), NOTEBOOK_DOCUMENT_DID_CHANGE: ( - NotebookDocumentDidChangeNotification, + DidChangeNotebookDocumentNotification, None, DidChangeNotebookDocumentParams, - None, + NotebookDocumentSyncRegistrationOptions, ), NOTEBOOK_DOCUMENT_DID_CLOSE: ( - NotebookDocumentDidCloseNotification, + DidCloseNotebookDocumentNotification, None, DidCloseNotebookDocumentParams, - None, + NotebookDocumentSyncRegistrationOptions, ), NOTEBOOK_DOCUMENT_DID_OPEN: ( - NotebookDocumentDidOpenNotification, + DidOpenNotebookDocumentNotification, None, DidOpenNotebookDocumentParams, - None, + NotebookDocumentSyncRegistrationOptions, ), NOTEBOOK_DOCUMENT_DID_SAVE: ( - NotebookDocumentDidSaveNotification, + DidSaveNotebookDocumentNotification, None, DidSaveNotebookDocumentParams, - None, + NotebookDocumentSyncRegistrationOptions, ), PROGRESS: (ProgressNotification, None, ProgressParams, None), SET_TRACE: (SetTraceNotification, None, SetTraceParams, None), TELEMETRY_EVENT: (TelemetryEventNotification, None, LSPAny, None), TEXT_DOCUMENT_DID_CHANGE: ( - TextDocumentDidChangeNotification, + DidChangeTextDocumentNotification, None, DidChangeTextDocumentParams, TextDocumentChangeRegistrationOptions, ), TEXT_DOCUMENT_DID_CLOSE: ( - TextDocumentDidCloseNotification, + DidCloseTextDocumentNotification, None, DidCloseTextDocumentParams, TextDocumentRegistrationOptions, ), TEXT_DOCUMENT_DID_OPEN: ( - TextDocumentDidOpenNotification, + DidOpenTextDocumentNotification, None, DidOpenTextDocumentParams, TextDocumentRegistrationOptions, ), TEXT_DOCUMENT_DID_SAVE: ( - TextDocumentDidSaveNotification, + DidSaveTextDocumentNotification, None, DidSaveTextDocumentParams, TextDocumentSaveRegistrationOptions, ), TEXT_DOCUMENT_PUBLISH_DIAGNOSTICS: ( - TextDocumentPublishDiagnosticsNotification, + PublishDiagnosticsNotification, None, PublishDiagnosticsParams, None, ), TEXT_DOCUMENT_WILL_SAVE: ( - TextDocumentWillSaveNotification, + WillSaveTextDocumentNotification, None, WillSaveTextDocumentParams, TextDocumentRegistrationOptions, ), - WINDOW_LOG_MESSAGE: (WindowLogMessageNotification, None, LogMessageParams, None), - WINDOW_SHOW_MESSAGE: (WindowShowMessageNotification, None, ShowMessageParams, None), + WINDOW_LOG_MESSAGE: (LogMessageNotification, None, LogMessageParams, None), + WINDOW_SHOW_MESSAGE: (ShowMessageNotification, None, ShowMessageParams, None), WINDOW_WORK_DONE_PROGRESS_CANCEL: ( - WindowWorkDoneProgressCancelNotification, + WorkDoneProgressCancelNotification, None, WorkDoneProgressCancelParams, None, ), WORKSPACE_DID_CHANGE_CONFIGURATION: ( - WorkspaceDidChangeConfigurationNotification, + DidChangeConfigurationNotification, None, DidChangeConfigurationParams, DidChangeConfigurationRegistrationOptions, ), WORKSPACE_DID_CHANGE_WATCHED_FILES: ( - WorkspaceDidChangeWatchedFilesNotification, + DidChangeWatchedFilesNotification, None, DidChangeWatchedFilesParams, DidChangeWatchedFilesRegistrationOptions, ), WORKSPACE_DID_CHANGE_WORKSPACE_FOLDERS: ( - WorkspaceDidChangeWorkspaceFoldersNotification, + DidChangeWorkspaceFoldersNotification, None, DidChangeWorkspaceFoldersParams, None, ), WORKSPACE_DID_CREATE_FILES: ( - WorkspaceDidCreateFilesNotification, + DidCreateFilesNotification, None, CreateFilesParams, FileOperationRegistrationOptions, ), WORKSPACE_DID_DELETE_FILES: ( - WorkspaceDidDeleteFilesNotification, + DidDeleteFilesNotification, None, DeleteFilesParams, FileOperationRegistrationOptions, ), WORKSPACE_DID_RENAME_FILES: ( - WorkspaceDidRenameFilesNotification, + DidRenameFilesNotification, None, RenameFilesParams, FileOperationRegistrationOptions, ), } REQUESTS = Union[ + ApplyWorkspaceEditRequest, CallHierarchyIncomingCallsRequest, CallHierarchyOutgoingCallsRequest, - ClientRegisterCapabilityRequest, - ClientUnregisterCapabilityRequest, + CallHierarchyPrepareRequest, + CodeActionRequest, CodeActionResolveRequest, + CodeLensRefreshRequest, + CodeLensRequest, CodeLensResolveRequest, - CompletionItemResolveRequest, + ColorPresentationRequest, + CompletionRequest, + CompletionResolveRequest, + ConfigurationRequest, + DeclarationRequest, + DefinitionRequest, + DiagnosticRefreshRequest, + DocumentColorRequest, + DocumentDiagnosticRequest, + DocumentFormattingRequest, + DocumentHighlightRequest, + DocumentLinkRequest, DocumentLinkResolveRequest, + DocumentOnTypeFormattingRequest, + DocumentRangeFormattingRequest, + DocumentRangesFormattingRequest, + DocumentSymbolRequest, + ExecuteCommandRequest, + FoldingRangeRefreshRequest, + FoldingRangeRequest, + HoverRequest, + ImplementationRequest, InitializeRequest, + InlayHintRefreshRequest, + InlayHintRequest, InlayHintResolveRequest, + InlineCompletionRequest, + InlineValueRefreshRequest, + InlineValueRequest, + LinkedEditingRangeRequest, + MonikerRequest, + PrepareRenameRequest, + ReferencesRequest, + RegistrationRequest, + RenameRequest, + SelectionRangeRequest, + SemanticTokensDeltaRequest, + SemanticTokensRangeRequest, + SemanticTokensRefreshRequest, + SemanticTokensRequest, + ShowDocumentRequest, + ShowMessageRequest, ShutdownRequest, - TextDocumentCodeActionRequest, - TextDocumentCodeLensRequest, - TextDocumentColorPresentationRequest, - TextDocumentCompletionRequest, - TextDocumentDeclarationRequest, - TextDocumentDefinitionRequest, - TextDocumentDiagnosticRequest, - TextDocumentDocumentColorRequest, - TextDocumentDocumentHighlightRequest, - TextDocumentDocumentLinkRequest, - TextDocumentDocumentSymbolRequest, - TextDocumentFoldingRangeRequest, - TextDocumentFormattingRequest, - TextDocumentHoverRequest, - TextDocumentImplementationRequest, - TextDocumentInlayHintRequest, - TextDocumentInlineCompletionRequest, - TextDocumentInlineValueRequest, - TextDocumentLinkedEditingRangeRequest, - TextDocumentMonikerRequest, - TextDocumentOnTypeFormattingRequest, - TextDocumentPrepareCallHierarchyRequest, - TextDocumentPrepareRenameRequest, - TextDocumentPrepareTypeHierarchyRequest, - TextDocumentRangeFormattingRequest, - TextDocumentRangesFormattingRequest, - TextDocumentReferencesRequest, - TextDocumentRenameRequest, - TextDocumentSelectionRangeRequest, - TextDocumentSemanticTokensFullDeltaRequest, - TextDocumentSemanticTokensFullRequest, - TextDocumentSemanticTokensRangeRequest, - TextDocumentSignatureHelpRequest, - TextDocumentTypeDefinitionRequest, - TextDocumentWillSaveWaitUntilRequest, + SignatureHelpRequest, + TextDocumentContentRefreshRequest, + TextDocumentContentRequest, + TypeDefinitionRequest, + TypeHierarchyPrepareRequest, TypeHierarchySubtypesRequest, TypeHierarchySupertypesRequest, - WindowShowDocumentRequest, - WindowShowMessageRequestRequest, - WindowWorkDoneProgressCreateRequest, - WorkspaceApplyEditRequest, - WorkspaceCodeLensRefreshRequest, - WorkspaceConfigurationRequest, - WorkspaceDiagnosticRefreshRequest, + UnregistrationRequest, + WillCreateFilesRequest, + WillDeleteFilesRequest, + WillRenameFilesRequest, + WillSaveTextDocumentWaitUntilRequest, + WorkDoneProgressCreateRequest, WorkspaceDiagnosticRequest, - WorkspaceExecuteCommandRequest, - WorkspaceFoldingRangeRefreshRequest, - WorkspaceInlayHintRefreshRequest, - WorkspaceInlineValueRefreshRequest, - WorkspaceSemanticTokensRefreshRequest, + WorkspaceFoldersRequest, WorkspaceSymbolRequest, WorkspaceSymbolResolveRequest, - WorkspaceWillCreateFilesRequest, - WorkspaceWillDeleteFilesRequest, - WorkspaceWillRenameFilesRequest, - WorkspaceWorkspaceFoldersRequest, ] RESPONSES = Union[ + ApplyWorkspaceEditResponse, CallHierarchyIncomingCallsResponse, CallHierarchyOutgoingCallsResponse, - ClientRegisterCapabilityResponse, - ClientUnregisterCapabilityResponse, + CallHierarchyPrepareResponse, CodeActionResolveResponse, + CodeActionResponse, + CodeLensRefreshResponse, CodeLensResolveResponse, - CompletionItemResolveResponse, + CodeLensResponse, + ColorPresentationResponse, + CompletionResolveResponse, + CompletionResponse, + ConfigurationResponse, + DeclarationResponse, + DefinitionResponse, + DiagnosticRefreshResponse, + DocumentColorResponse, + DocumentDiagnosticResponse, + DocumentFormattingResponse, + DocumentHighlightResponse, DocumentLinkResolveResponse, + DocumentLinkResponse, + DocumentOnTypeFormattingResponse, + DocumentRangeFormattingResponse, + DocumentRangesFormattingResponse, + DocumentSymbolResponse, + ExecuteCommandResponse, + FoldingRangeRefreshResponse, + FoldingRangeResponse, + HoverResponse, + ImplementationResponse, InitializeResponse, + InlayHintRefreshResponse, InlayHintResolveResponse, + InlayHintResponse, + InlineCompletionResponse, + InlineValueRefreshResponse, + InlineValueResponse, + LinkedEditingRangeResponse, + MonikerResponse, + PrepareRenameResponse, + ReferencesResponse, + RegistrationResponse, + RenameResponse, + SelectionRangeResponse, + SemanticTokensDeltaResponse, + SemanticTokensRangeResponse, + SemanticTokensRefreshResponse, + SemanticTokensResponse, + ShowDocumentResponse, + ShowMessageResponse, ShutdownResponse, - TextDocumentCodeActionResponse, - TextDocumentCodeLensResponse, - TextDocumentColorPresentationResponse, - TextDocumentCompletionResponse, - TextDocumentDeclarationResponse, - TextDocumentDefinitionResponse, - TextDocumentDiagnosticResponse, - TextDocumentDocumentColorResponse, - TextDocumentDocumentHighlightResponse, - TextDocumentDocumentLinkResponse, - TextDocumentDocumentSymbolResponse, - TextDocumentFoldingRangeResponse, - TextDocumentFormattingResponse, - TextDocumentHoverResponse, - TextDocumentImplementationResponse, - TextDocumentInlayHintResponse, - TextDocumentInlineCompletionResponse, - TextDocumentInlineValueResponse, - TextDocumentLinkedEditingRangeResponse, - TextDocumentMonikerResponse, - TextDocumentOnTypeFormattingResponse, - TextDocumentPrepareCallHierarchyResponse, - TextDocumentPrepareRenameResponse, - TextDocumentPrepareTypeHierarchyResponse, - TextDocumentRangeFormattingResponse, - TextDocumentRangesFormattingResponse, - TextDocumentReferencesResponse, - TextDocumentRenameResponse, - TextDocumentSelectionRangeResponse, - TextDocumentSemanticTokensFullDeltaResponse, - TextDocumentSemanticTokensFullResponse, - TextDocumentSemanticTokensRangeResponse, - TextDocumentSignatureHelpResponse, - TextDocumentTypeDefinitionResponse, - TextDocumentWillSaveWaitUntilResponse, + SignatureHelpResponse, + TextDocumentContentRefreshResponse, + TextDocumentContentResponse, + TypeDefinitionResponse, + TypeHierarchyPrepareResponse, TypeHierarchySubtypesResponse, TypeHierarchySupertypesResponse, - WindowShowDocumentResponse, - WindowShowMessageRequestResponse, - WindowWorkDoneProgressCreateResponse, - WorkspaceApplyEditResponse, - WorkspaceCodeLensRefreshResponse, - WorkspaceConfigurationResponse, - WorkspaceDiagnosticRefreshResponse, + UnregistrationResponse, + WillCreateFilesResponse, + WillDeleteFilesResponse, + WillRenameFilesResponse, + WillSaveTextDocumentWaitUntilResponse, + WorkDoneProgressCreateResponse, WorkspaceDiagnosticResponse, - WorkspaceExecuteCommandResponse, - WorkspaceFoldingRangeRefreshResponse, - WorkspaceInlayHintRefreshResponse, - WorkspaceInlineValueRefreshResponse, - WorkspaceSemanticTokensRefreshResponse, + WorkspaceFoldersResponse, WorkspaceSymbolResolveResponse, WorkspaceSymbolResponse, - WorkspaceWillCreateFilesResponse, - WorkspaceWillDeleteFilesResponse, - WorkspaceWillRenameFilesResponse, - WorkspaceWorkspaceFoldersResponse, ] NOTIFICATIONS = Union[ - CancelRequestNotification, + CancelNotification, + DidChangeConfigurationNotification, + DidChangeNotebookDocumentNotification, + DidChangeTextDocumentNotification, + DidChangeWatchedFilesNotification, + DidChangeWorkspaceFoldersNotification, + DidCloseNotebookDocumentNotification, + DidCloseTextDocumentNotification, + DidCreateFilesNotification, + DidDeleteFilesNotification, + DidOpenNotebookDocumentNotification, + DidOpenTextDocumentNotification, + DidRenameFilesNotification, + DidSaveNotebookDocumentNotification, + DidSaveTextDocumentNotification, ExitNotification, InitializedNotification, + LogMessageNotification, LogTraceNotification, - NotebookDocumentDidChangeNotification, - NotebookDocumentDidCloseNotification, - NotebookDocumentDidOpenNotification, - NotebookDocumentDidSaveNotification, ProgressNotification, + PublishDiagnosticsNotification, SetTraceNotification, + ShowMessageNotification, TelemetryEventNotification, - TextDocumentDidChangeNotification, - TextDocumentDidCloseNotification, - TextDocumentDidOpenNotification, - TextDocumentDidSaveNotification, - TextDocumentPublishDiagnosticsNotification, - TextDocumentWillSaveNotification, - WindowLogMessageNotification, - WindowShowMessageNotification, - WindowWorkDoneProgressCancelNotification, - WorkspaceDidChangeConfigurationNotification, - WorkspaceDidChangeWatchedFilesNotification, - WorkspaceDidChangeWorkspaceFoldersNotification, - WorkspaceDidCreateFilesNotification, - WorkspaceDidDeleteFilesNotification, - WorkspaceDidRenameFilesNotification, + WillSaveTextDocumentNotification, + WorkDoneProgressCancelNotification, ] MESSAGE_TYPES = Union[REQUESTS, RESPONSES, NOTIFICATIONS, ResponseErrorMessage] @@ -11568,216 +12600,222 @@ def is_keyword_class(cls: type) -> bool: _SPECIAL_CLASSES = [ + ApplyWorkspaceEditRequest, + ApplyWorkspaceEditResponse, CallHierarchyIncomingCallsRequest, CallHierarchyIncomingCallsResponse, CallHierarchyOutgoingCallsRequest, CallHierarchyOutgoingCallsResponse, + CallHierarchyPrepareRequest, + CallHierarchyPrepareResponse, CallHierarchyRegistrationOptions, - CancelRequestNotification, - ClientRegisterCapabilityRequest, - ClientRegisterCapabilityResponse, - ClientUnregisterCapabilityRequest, - ClientUnregisterCapabilityResponse, + CancelNotification, CodeActionRegistrationOptions, + CodeActionRequest, CodeActionResolveRequest, CodeActionResolveResponse, + CodeActionResponse, + CodeLensRefreshRequest, + CodeLensRefreshResponse, CodeLensRegistrationOptions, + CodeLensRequest, CodeLensResolveRequest, CodeLensResolveResponse, - CompletionItemResolveRequest, - CompletionItemResolveResponse, + CodeLensResponse, + ColorPresentationRequest, + ColorPresentationRequestOptions, + ColorPresentationResponse, CompletionRegistrationOptions, + CompletionRequest, + CompletionResolveRequest, + CompletionResolveResponse, + CompletionResponse, + ConfigurationRequest, + ConfigurationResponse, CreateFile, DeclarationRegistrationOptions, + DeclarationRequest, + DeclarationResponse, DefinitionRegistrationOptions, + DefinitionRequest, + DefinitionResponse, DeleteFile, + DiagnosticRefreshRequest, + DiagnosticRefreshResponse, DiagnosticRegistrationOptions, + DidChangeConfigurationNotification, + DidChangeNotebookDocumentNotification, + DidChangeTextDocumentNotification, + DidChangeWatchedFilesNotification, + DidChangeWorkspaceFoldersNotification, + DidCloseNotebookDocumentNotification, + DidCloseTextDocumentNotification, + DidCreateFilesNotification, + DidDeleteFilesNotification, + DidOpenNotebookDocumentNotification, + DidOpenTextDocumentNotification, + DidRenameFilesNotification, + DidSaveNotebookDocumentNotification, + DidSaveTextDocumentNotification, DocumentColorRegistrationOptions, + DocumentColorRequest, + DocumentColorResponse, + DocumentDiagnosticRequest, + DocumentDiagnosticResponse, DocumentFormattingRegistrationOptions, + DocumentFormattingRequest, + DocumentFormattingResponse, DocumentHighlightRegistrationOptions, + DocumentHighlightRequest, + DocumentHighlightResponse, DocumentLinkRegistrationOptions, + DocumentLinkRequest, DocumentLinkResolveRequest, DocumentLinkResolveResponse, + DocumentLinkResponse, DocumentOnTypeFormattingRegistrationOptions, + DocumentOnTypeFormattingRequest, + DocumentOnTypeFormattingResponse, DocumentRangeFormattingRegistrationOptions, + DocumentRangeFormattingRequest, + DocumentRangeFormattingResponse, + DocumentRangesFormattingRequest, + DocumentRangesFormattingResponse, DocumentSymbolRegistrationOptions, + DocumentSymbolRequest, + DocumentSymbolResponse, + ExecuteCommandRequest, + ExecuteCommandResponse, ExitNotification, + FoldingRangeRefreshRequest, + FoldingRangeRefreshResponse, FoldingRangeRegistrationOptions, + FoldingRangeRequest, + FoldingRangeResponse, FullDocumentDiagnosticReport, HoverRegistrationOptions, + HoverRequest, + HoverResponse, ImplementationRegistrationOptions, + ImplementationRequest, + ImplementationResponse, InitializeParams, InitializeRequest, InitializeResponse, InitializedNotification, + InlayHintRefreshRequest, + InlayHintRefreshResponse, InlayHintRegistrationOptions, + InlayHintRequest, InlayHintResolveRequest, InlayHintResolveResponse, + InlayHintResponse, InlineCompletionRegistrationOptions, + InlineCompletionRequest, + InlineCompletionResponse, + InlineValueRefreshRequest, + InlineValueRefreshResponse, InlineValueRegistrationOptions, + InlineValueRequest, + InlineValueResponse, LinkedEditingRangeRegistrationOptions, + LinkedEditingRangeRequest, + LinkedEditingRangeResponse, + LogMessageNotification, LogTraceNotification, MonikerRegistrationOptions, - NotebookDocumentDidChangeNotification, - NotebookDocumentDidCloseNotification, - NotebookDocumentDidOpenNotification, - NotebookDocumentDidSaveNotification, + MonikerRequest, + MonikerResponse, OptionalVersionedTextDocumentIdentifier, + PrepareRenameRequest, + PrepareRenameResponse, ProgressNotification, + PublishDiagnosticsNotification, ReferenceRegistrationOptions, + ReferencesRequest, + ReferencesResponse, + RegistrationRequest, + RegistrationResponse, RelatedFullDocumentDiagnosticReport, RelatedUnchangedDocumentDiagnosticReport, RenameFile, RenameRegistrationOptions, + RenameRequest, + RenameResponse, ResponseErrorMessage, SelectionRangeRegistrationOptions, + SelectionRangeRequest, + SelectionRangeResponse, + SemanticTokensDeltaRequest, + SemanticTokensDeltaResponse, + SemanticTokensRangeRequest, + SemanticTokensRangeResponse, + SemanticTokensRefreshRequest, + SemanticTokensRefreshResponse, SemanticTokensRegistrationOptions, + SemanticTokensRequest, + SemanticTokensResponse, SetTraceNotification, + ShowDocumentRequest, + ShowDocumentResponse, + ShowMessageNotification, + ShowMessageRequest, + ShowMessageResponse, ShutdownRequest, ShutdownResponse, + SignatureHelp, SignatureHelpRegistrationOptions, + SignatureHelpRequest, + SignatureHelpResponse, + SignatureInformation, StringValue, TelemetryEventNotification, TextDocumentChangeRegistrationOptions, - TextDocumentCodeActionRequest, - TextDocumentCodeActionResponse, - TextDocumentCodeLensRequest, - TextDocumentCodeLensResponse, - TextDocumentColorPresentationOptions, - TextDocumentColorPresentationRequest, - TextDocumentColorPresentationResponse, - TextDocumentCompletionRequest, - TextDocumentCompletionResponse, - TextDocumentDeclarationRequest, - TextDocumentDeclarationResponse, - TextDocumentDefinitionRequest, - TextDocumentDefinitionResponse, - TextDocumentDiagnosticRequest, - TextDocumentDiagnosticResponse, - TextDocumentDidChangeNotification, - TextDocumentDidCloseNotification, - TextDocumentDidOpenNotification, - TextDocumentDidSaveNotification, - TextDocumentDocumentColorRequest, - TextDocumentDocumentColorResponse, - TextDocumentDocumentHighlightRequest, - TextDocumentDocumentHighlightResponse, - TextDocumentDocumentLinkRequest, - TextDocumentDocumentLinkResponse, - TextDocumentDocumentSymbolRequest, - TextDocumentDocumentSymbolResponse, - TextDocumentFoldingRangeRequest, - TextDocumentFoldingRangeResponse, - TextDocumentFormattingRequest, - TextDocumentFormattingResponse, - TextDocumentHoverRequest, - TextDocumentHoverResponse, - TextDocumentImplementationRequest, - TextDocumentImplementationResponse, - TextDocumentInlayHintRequest, - TextDocumentInlayHintResponse, - TextDocumentInlineCompletionRequest, - TextDocumentInlineCompletionResponse, - TextDocumentInlineValueRequest, - TextDocumentInlineValueResponse, - TextDocumentLinkedEditingRangeRequest, - TextDocumentLinkedEditingRangeResponse, - TextDocumentMonikerRequest, - TextDocumentMonikerResponse, - TextDocumentOnTypeFormattingRequest, - TextDocumentOnTypeFormattingResponse, - TextDocumentPrepareCallHierarchyRequest, - TextDocumentPrepareCallHierarchyResponse, - TextDocumentPrepareRenameRequest, - TextDocumentPrepareRenameResponse, - TextDocumentPrepareTypeHierarchyRequest, - TextDocumentPrepareTypeHierarchyResponse, - TextDocumentPublishDiagnosticsNotification, - TextDocumentRangeFormattingRequest, - TextDocumentRangeFormattingResponse, - TextDocumentRangesFormattingRequest, - TextDocumentRangesFormattingResponse, - TextDocumentReferencesRequest, - TextDocumentReferencesResponse, + TextDocumentContentRefreshRequest, + TextDocumentContentRefreshResponse, + TextDocumentContentRequest, + TextDocumentContentResponse, TextDocumentRegistrationOptions, - TextDocumentRenameRequest, - TextDocumentRenameResponse, TextDocumentSaveRegistrationOptions, - TextDocumentSelectionRangeRequest, - TextDocumentSelectionRangeResponse, - TextDocumentSemanticTokensFullDeltaRequest, - TextDocumentSemanticTokensFullDeltaResponse, - TextDocumentSemanticTokensFullRequest, - TextDocumentSemanticTokensFullResponse, - TextDocumentSemanticTokensRangeRequest, - TextDocumentSemanticTokensRangeResponse, - TextDocumentSignatureHelpRequest, - TextDocumentSignatureHelpResponse, - TextDocumentTypeDefinitionRequest, - TextDocumentTypeDefinitionResponse, - TextDocumentWillSaveNotification, - TextDocumentWillSaveWaitUntilRequest, - TextDocumentWillSaveWaitUntilResponse, TypeDefinitionRegistrationOptions, + TypeDefinitionRequest, + TypeDefinitionResponse, + TypeHierarchyPrepareRequest, + TypeHierarchyPrepareResponse, TypeHierarchyRegistrationOptions, TypeHierarchySubtypesRequest, TypeHierarchySubtypesResponse, TypeHierarchySupertypesRequest, TypeHierarchySupertypesResponse, UnchangedDocumentDiagnosticReport, - WindowLogMessageNotification, - WindowShowDocumentRequest, - WindowShowDocumentResponse, - WindowShowMessageNotification, - WindowShowMessageRequestRequest, - WindowShowMessageRequestResponse, - WindowWorkDoneProgressCancelNotification, - WindowWorkDoneProgressCreateRequest, - WindowWorkDoneProgressCreateResponse, + UnregistrationRequest, + UnregistrationResponse, + WillCreateFilesRequest, + WillCreateFilesResponse, + WillDeleteFilesRequest, + WillDeleteFilesResponse, + WillRenameFilesRequest, + WillRenameFilesResponse, + WillSaveTextDocumentNotification, + WillSaveTextDocumentWaitUntilRequest, + WillSaveTextDocumentWaitUntilResponse, WorkDoneProgressBegin, + WorkDoneProgressCancelNotification, + WorkDoneProgressCreateRequest, + WorkDoneProgressCreateResponse, WorkDoneProgressEnd, WorkDoneProgressReport, - WorkspaceApplyEditRequest, - WorkspaceApplyEditResponse, - WorkspaceCodeLensRefreshRequest, - WorkspaceCodeLensRefreshResponse, - WorkspaceConfigurationRequest, - WorkspaceConfigurationResponse, - WorkspaceDiagnosticRefreshRequest, - WorkspaceDiagnosticRefreshResponse, WorkspaceDiagnosticRequest, WorkspaceDiagnosticResponse, - WorkspaceDidChangeConfigurationNotification, - WorkspaceDidChangeWatchedFilesNotification, - WorkspaceDidChangeWorkspaceFoldersNotification, - WorkspaceDidCreateFilesNotification, - WorkspaceDidDeleteFilesNotification, - WorkspaceDidRenameFilesNotification, - WorkspaceExecuteCommandRequest, - WorkspaceExecuteCommandResponse, WorkspaceFoldersInitializeParams, - WorkspaceFoldingRangeRefreshRequest, - WorkspaceFoldingRangeRefreshResponse, + WorkspaceFoldersRequest, + WorkspaceFoldersResponse, WorkspaceFullDocumentDiagnosticReport, - WorkspaceInlayHintRefreshRequest, - WorkspaceInlayHintRefreshResponse, - WorkspaceInlineValueRefreshRequest, - WorkspaceInlineValueRefreshResponse, - WorkspaceSemanticTokensRefreshRequest, - WorkspaceSemanticTokensRefreshResponse, WorkspaceSymbolRequest, WorkspaceSymbolResolveRequest, WorkspaceSymbolResolveResponse, WorkspaceSymbolResponse, WorkspaceUnchangedDocumentDiagnosticReport, - WorkspaceWillCreateFilesRequest, - WorkspaceWillCreateFilesResponse, - WorkspaceWillDeleteFilesRequest, - WorkspaceWillDeleteFilesResponse, - WorkspaceWillRenameFilesRequest, - WorkspaceWillRenameFilesResponse, - WorkspaceWorkspaceFoldersRequest, - WorkspaceWorkspaceFoldersResponse, _InitializeParams, ] @@ -11788,6 +12826,10 @@ def is_special_class(cls: type) -> bool: _SPECIAL_PROPERTIES = [ + "ApplyWorkspaceEditRequest.jsonrpc", + "ApplyWorkspaceEditRequest.method", + "ApplyWorkspaceEditResponse.jsonrpc", + "ApplyWorkspaceEditResponse.result", "CallHierarchyIncomingCallsRequest.jsonrpc", "CallHierarchyIncomingCallsRequest.method", "CallHierarchyIncomingCallsResponse.jsonrpc", @@ -11796,54 +12838,171 @@ _SPECIAL_PROPERTIES = [ "CallHierarchyOutgoingCallsRequest.method", "CallHierarchyOutgoingCallsResponse.jsonrpc", "CallHierarchyOutgoingCallsResponse.result", + "CallHierarchyPrepareRequest.jsonrpc", + "CallHierarchyPrepareRequest.method", + "CallHierarchyPrepareResponse.jsonrpc", + "CallHierarchyPrepareResponse.result", "CallHierarchyRegistrationOptions.document_selector", - "CancelRequestNotification.jsonrpc", - "CancelRequestNotification.method", - "ClientRegisterCapabilityRequest.jsonrpc", - "ClientRegisterCapabilityRequest.method", - "ClientRegisterCapabilityResponse.jsonrpc", - "ClientRegisterCapabilityResponse.result", - "ClientUnregisterCapabilityRequest.jsonrpc", - "ClientUnregisterCapabilityRequest.method", - "ClientUnregisterCapabilityResponse.jsonrpc", - "ClientUnregisterCapabilityResponse.result", + "CancelNotification.jsonrpc", + "CancelNotification.method", "CodeActionRegistrationOptions.document_selector", + "CodeActionRequest.jsonrpc", + "CodeActionRequest.method", "CodeActionResolveRequest.jsonrpc", "CodeActionResolveRequest.method", "CodeActionResolveResponse.jsonrpc", "CodeActionResolveResponse.result", + "CodeActionResponse.jsonrpc", + "CodeActionResponse.result", + "CodeLensRefreshRequest.jsonrpc", + "CodeLensRefreshRequest.method", + "CodeLensRefreshResponse.jsonrpc", + "CodeLensRefreshResponse.result", "CodeLensRegistrationOptions.document_selector", + "CodeLensRequest.jsonrpc", + "CodeLensRequest.method", "CodeLensResolveRequest.jsonrpc", "CodeLensResolveRequest.method", "CodeLensResolveResponse.jsonrpc", "CodeLensResolveResponse.result", - "CompletionItemResolveRequest.jsonrpc", - "CompletionItemResolveRequest.method", - "CompletionItemResolveResponse.jsonrpc", - "CompletionItemResolveResponse.result", + "CodeLensResponse.jsonrpc", + "CodeLensResponse.result", + "ColorPresentationRequest.jsonrpc", + "ColorPresentationRequest.method", + "ColorPresentationRequestOptions.document_selector", + "ColorPresentationResponse.jsonrpc", + "ColorPresentationResponse.result", "CompletionRegistrationOptions.document_selector", + "CompletionRequest.jsonrpc", + "CompletionRequest.method", + "CompletionResolveRequest.jsonrpc", + "CompletionResolveRequest.method", + "CompletionResolveResponse.jsonrpc", + "CompletionResolveResponse.result", + "CompletionResponse.jsonrpc", + "CompletionResponse.result", + "ConfigurationRequest.jsonrpc", + "ConfigurationRequest.method", + "ConfigurationResponse.jsonrpc", + "ConfigurationResponse.result", "CreateFile.kind", "DeclarationRegistrationOptions.document_selector", + "DeclarationRequest.jsonrpc", + "DeclarationRequest.method", + "DeclarationResponse.jsonrpc", + "DeclarationResponse.result", "DefinitionRegistrationOptions.document_selector", + "DefinitionRequest.jsonrpc", + "DefinitionRequest.method", + "DefinitionResponse.jsonrpc", + "DefinitionResponse.result", "DeleteFile.kind", + "DiagnosticRefreshRequest.jsonrpc", + "DiagnosticRefreshRequest.method", + "DiagnosticRefreshResponse.jsonrpc", + "DiagnosticRefreshResponse.result", "DiagnosticRegistrationOptions.document_selector", + "DidChangeConfigurationNotification.jsonrpc", + "DidChangeConfigurationNotification.method", + "DidChangeNotebookDocumentNotification.jsonrpc", + "DidChangeNotebookDocumentNotification.method", + "DidChangeTextDocumentNotification.jsonrpc", + "DidChangeTextDocumentNotification.method", + "DidChangeWatchedFilesNotification.jsonrpc", + "DidChangeWatchedFilesNotification.method", + "DidChangeWorkspaceFoldersNotification.jsonrpc", + "DidChangeWorkspaceFoldersNotification.method", + "DidCloseNotebookDocumentNotification.jsonrpc", + "DidCloseNotebookDocumentNotification.method", + "DidCloseTextDocumentNotification.jsonrpc", + "DidCloseTextDocumentNotification.method", + "DidCreateFilesNotification.jsonrpc", + "DidCreateFilesNotification.method", + "DidDeleteFilesNotification.jsonrpc", + "DidDeleteFilesNotification.method", + "DidOpenNotebookDocumentNotification.jsonrpc", + "DidOpenNotebookDocumentNotification.method", + "DidOpenTextDocumentNotification.jsonrpc", + "DidOpenTextDocumentNotification.method", + "DidRenameFilesNotification.jsonrpc", + "DidRenameFilesNotification.method", + "DidSaveNotebookDocumentNotification.jsonrpc", + "DidSaveNotebookDocumentNotification.method", + "DidSaveTextDocumentNotification.jsonrpc", + "DidSaveTextDocumentNotification.method", "DocumentColorRegistrationOptions.document_selector", + "DocumentColorRequest.jsonrpc", + "DocumentColorRequest.method", + "DocumentColorResponse.jsonrpc", + "DocumentColorResponse.result", + "DocumentDiagnosticRequest.jsonrpc", + "DocumentDiagnosticRequest.method", + "DocumentDiagnosticResponse.jsonrpc", + "DocumentDiagnosticResponse.result", "DocumentFormattingRegistrationOptions.document_selector", + "DocumentFormattingRequest.jsonrpc", + "DocumentFormattingRequest.method", + "DocumentFormattingResponse.jsonrpc", + "DocumentFormattingResponse.result", "DocumentHighlightRegistrationOptions.document_selector", + "DocumentHighlightRequest.jsonrpc", + "DocumentHighlightRequest.method", + "DocumentHighlightResponse.jsonrpc", + "DocumentHighlightResponse.result", "DocumentLinkRegistrationOptions.document_selector", + "DocumentLinkRequest.jsonrpc", + "DocumentLinkRequest.method", "DocumentLinkResolveRequest.jsonrpc", "DocumentLinkResolveRequest.method", "DocumentLinkResolveResponse.jsonrpc", "DocumentLinkResolveResponse.result", + "DocumentLinkResponse.jsonrpc", + "DocumentLinkResponse.result", "DocumentOnTypeFormattingRegistrationOptions.document_selector", + "DocumentOnTypeFormattingRequest.jsonrpc", + "DocumentOnTypeFormattingRequest.method", + "DocumentOnTypeFormattingResponse.jsonrpc", + "DocumentOnTypeFormattingResponse.result", "DocumentRangeFormattingRegistrationOptions.document_selector", + "DocumentRangeFormattingRequest.jsonrpc", + "DocumentRangeFormattingRequest.method", + "DocumentRangeFormattingResponse.jsonrpc", + "DocumentRangeFormattingResponse.result", + "DocumentRangesFormattingRequest.jsonrpc", + "DocumentRangesFormattingRequest.method", + "DocumentRangesFormattingResponse.jsonrpc", + "DocumentRangesFormattingResponse.result", "DocumentSymbolRegistrationOptions.document_selector", + "DocumentSymbolRequest.jsonrpc", + "DocumentSymbolRequest.method", + "DocumentSymbolResponse.jsonrpc", + "DocumentSymbolResponse.result", + "ExecuteCommandRequest.jsonrpc", + "ExecuteCommandRequest.method", + "ExecuteCommandResponse.jsonrpc", + "ExecuteCommandResponse.result", "ExitNotification.jsonrpc", "ExitNotification.method", + "FoldingRangeRefreshRequest.jsonrpc", + "FoldingRangeRefreshRequest.method", + "FoldingRangeRefreshResponse.jsonrpc", + "FoldingRangeRefreshResponse.result", "FoldingRangeRegistrationOptions.document_selector", + "FoldingRangeRequest.jsonrpc", + "FoldingRangeRequest.method", + "FoldingRangeResponse.jsonrpc", + "FoldingRangeResponse.result", "FullDocumentDiagnosticReport.kind", "HoverRegistrationOptions.document_selector", + "HoverRequest.jsonrpc", + "HoverRequest.method", + "HoverResponse.jsonrpc", + "HoverResponse.result", "ImplementationRegistrationOptions.document_selector", + "ImplementationRequest.jsonrpc", + "ImplementationRequest.method", + "ImplementationResponse.jsonrpc", + "ImplementationResponse.result", "InitializeParams.process_id", "InitializeParams.root_path", "InitializeParams.root_uri", @@ -11854,204 +13013,143 @@ _SPECIAL_PROPERTIES = [ "InitializeResponse.result", "InitializedNotification.jsonrpc", "InitializedNotification.method", + "InlayHintRefreshRequest.jsonrpc", + "InlayHintRefreshRequest.method", + "InlayHintRefreshResponse.jsonrpc", + "InlayHintRefreshResponse.result", "InlayHintRegistrationOptions.document_selector", + "InlayHintRequest.jsonrpc", + "InlayHintRequest.method", "InlayHintResolveRequest.jsonrpc", "InlayHintResolveRequest.method", "InlayHintResolveResponse.jsonrpc", "InlayHintResolveResponse.result", + "InlayHintResponse.jsonrpc", + "InlayHintResponse.result", "InlineCompletionRegistrationOptions.document_selector", + "InlineCompletionRequest.jsonrpc", + "InlineCompletionRequest.method", + "InlineCompletionResponse.jsonrpc", + "InlineCompletionResponse.result", + "InlineValueRefreshRequest.jsonrpc", + "InlineValueRefreshRequest.method", + "InlineValueRefreshResponse.jsonrpc", + "InlineValueRefreshResponse.result", "InlineValueRegistrationOptions.document_selector", + "InlineValueRequest.jsonrpc", + "InlineValueRequest.method", + "InlineValueResponse.jsonrpc", + "InlineValueResponse.result", "LinkedEditingRangeRegistrationOptions.document_selector", + "LinkedEditingRangeRequest.jsonrpc", + "LinkedEditingRangeRequest.method", + "LinkedEditingRangeResponse.jsonrpc", + "LinkedEditingRangeResponse.result", + "LogMessageNotification.jsonrpc", + "LogMessageNotification.method", "LogTraceNotification.jsonrpc", "LogTraceNotification.method", "MonikerRegistrationOptions.document_selector", - "NotebookDocumentDidChangeNotification.jsonrpc", - "NotebookDocumentDidChangeNotification.method", - "NotebookDocumentDidCloseNotification.jsonrpc", - "NotebookDocumentDidCloseNotification.method", - "NotebookDocumentDidOpenNotification.jsonrpc", - "NotebookDocumentDidOpenNotification.method", - "NotebookDocumentDidSaveNotification.jsonrpc", - "NotebookDocumentDidSaveNotification.method", + "MonikerRequest.jsonrpc", + "MonikerRequest.method", + "MonikerResponse.jsonrpc", + "MonikerResponse.result", "OptionalVersionedTextDocumentIdentifier.version", + "PrepareRenameRequest.jsonrpc", + "PrepareRenameRequest.method", + "PrepareRenameResponse.jsonrpc", + "PrepareRenameResponse.result", "ProgressNotification.jsonrpc", "ProgressNotification.method", + "PublishDiagnosticsNotification.jsonrpc", + "PublishDiagnosticsNotification.method", "ReferenceRegistrationOptions.document_selector", + "ReferencesRequest.jsonrpc", + "ReferencesRequest.method", + "ReferencesResponse.jsonrpc", + "ReferencesResponse.result", + "RegistrationRequest.jsonrpc", + "RegistrationRequest.method", + "RegistrationResponse.jsonrpc", + "RegistrationResponse.result", "RelatedFullDocumentDiagnosticReport.kind", "RelatedUnchangedDocumentDiagnosticReport.kind", "RenameFile.kind", "RenameRegistrationOptions.document_selector", + "RenameRequest.jsonrpc", + "RenameRequest.method", + "RenameResponse.jsonrpc", + "RenameResponse.result", "ResponseErrorMessage.error", "ResponseErrorMessage.jsonrpc", "SelectionRangeRegistrationOptions.document_selector", + "SelectionRangeRequest.jsonrpc", + "SelectionRangeRequest.method", + "SelectionRangeResponse.jsonrpc", + "SelectionRangeResponse.result", + "SemanticTokensDeltaRequest.jsonrpc", + "SemanticTokensDeltaRequest.method", + "SemanticTokensDeltaResponse.jsonrpc", + "SemanticTokensDeltaResponse.result", + "SemanticTokensRangeRequest.jsonrpc", + "SemanticTokensRangeRequest.method", + "SemanticTokensRangeResponse.jsonrpc", + "SemanticTokensRangeResponse.result", + "SemanticTokensRefreshRequest.jsonrpc", + "SemanticTokensRefreshRequest.method", + "SemanticTokensRefreshResponse.jsonrpc", + "SemanticTokensRefreshResponse.result", "SemanticTokensRegistrationOptions.document_selector", + "SemanticTokensRequest.jsonrpc", + "SemanticTokensRequest.method", + "SemanticTokensResponse.jsonrpc", + "SemanticTokensResponse.result", "SetTraceNotification.jsonrpc", "SetTraceNotification.method", + "ShowDocumentRequest.jsonrpc", + "ShowDocumentRequest.method", + "ShowDocumentResponse.jsonrpc", + "ShowDocumentResponse.result", + "ShowMessageNotification.jsonrpc", + "ShowMessageNotification.method", + "ShowMessageRequest.jsonrpc", + "ShowMessageRequest.method", + "ShowMessageResponse.jsonrpc", + "ShowMessageResponse.result", "ShutdownRequest.jsonrpc", "ShutdownRequest.method", "ShutdownResponse.jsonrpc", "ShutdownResponse.result", + "SignatureHelp.active_parameter", "SignatureHelpRegistrationOptions.document_selector", + "SignatureHelpRequest.jsonrpc", + "SignatureHelpRequest.method", + "SignatureHelpResponse.jsonrpc", + "SignatureHelpResponse.result", + "SignatureInformation.active_parameter", "StringValue.kind", "TelemetryEventNotification.jsonrpc", "TelemetryEventNotification.method", "TextDocumentChangeRegistrationOptions.document_selector", - "TextDocumentCodeActionRequest.jsonrpc", - "TextDocumentCodeActionRequest.method", - "TextDocumentCodeActionResponse.jsonrpc", - "TextDocumentCodeActionResponse.result", - "TextDocumentCodeLensRequest.jsonrpc", - "TextDocumentCodeLensRequest.method", - "TextDocumentCodeLensResponse.jsonrpc", - "TextDocumentCodeLensResponse.result", - "TextDocumentColorPresentationOptions.document_selector", - "TextDocumentColorPresentationRequest.jsonrpc", - "TextDocumentColorPresentationRequest.method", - "TextDocumentColorPresentationResponse.jsonrpc", - "TextDocumentColorPresentationResponse.result", - "TextDocumentCompletionRequest.jsonrpc", - "TextDocumentCompletionRequest.method", - "TextDocumentCompletionResponse.jsonrpc", - "TextDocumentCompletionResponse.result", - "TextDocumentDeclarationRequest.jsonrpc", - "TextDocumentDeclarationRequest.method", - "TextDocumentDeclarationResponse.jsonrpc", - "TextDocumentDeclarationResponse.result", - "TextDocumentDefinitionRequest.jsonrpc", - "TextDocumentDefinitionRequest.method", - "TextDocumentDefinitionResponse.jsonrpc", - "TextDocumentDefinitionResponse.result", - "TextDocumentDiagnosticRequest.jsonrpc", - "TextDocumentDiagnosticRequest.method", - "TextDocumentDiagnosticResponse.jsonrpc", - "TextDocumentDiagnosticResponse.result", - "TextDocumentDidChangeNotification.jsonrpc", - "TextDocumentDidChangeNotification.method", - "TextDocumentDidCloseNotification.jsonrpc", - "TextDocumentDidCloseNotification.method", - "TextDocumentDidOpenNotification.jsonrpc", - "TextDocumentDidOpenNotification.method", - "TextDocumentDidSaveNotification.jsonrpc", - "TextDocumentDidSaveNotification.method", - "TextDocumentDocumentColorRequest.jsonrpc", - "TextDocumentDocumentColorRequest.method", - "TextDocumentDocumentColorResponse.jsonrpc", - "TextDocumentDocumentColorResponse.result", - "TextDocumentDocumentHighlightRequest.jsonrpc", - "TextDocumentDocumentHighlightRequest.method", - "TextDocumentDocumentHighlightResponse.jsonrpc", - "TextDocumentDocumentHighlightResponse.result", - "TextDocumentDocumentLinkRequest.jsonrpc", - "TextDocumentDocumentLinkRequest.method", - "TextDocumentDocumentLinkResponse.jsonrpc", - "TextDocumentDocumentLinkResponse.result", - "TextDocumentDocumentSymbolRequest.jsonrpc", - "TextDocumentDocumentSymbolRequest.method", - "TextDocumentDocumentSymbolResponse.jsonrpc", - "TextDocumentDocumentSymbolResponse.result", - "TextDocumentFoldingRangeRequest.jsonrpc", - "TextDocumentFoldingRangeRequest.method", - "TextDocumentFoldingRangeResponse.jsonrpc", - "TextDocumentFoldingRangeResponse.result", - "TextDocumentFormattingRequest.jsonrpc", - "TextDocumentFormattingRequest.method", - "TextDocumentFormattingResponse.jsonrpc", - "TextDocumentFormattingResponse.result", - "TextDocumentHoverRequest.jsonrpc", - "TextDocumentHoverRequest.method", - "TextDocumentHoverResponse.jsonrpc", - "TextDocumentHoverResponse.result", - "TextDocumentImplementationRequest.jsonrpc", - "TextDocumentImplementationRequest.method", - "TextDocumentImplementationResponse.jsonrpc", - "TextDocumentImplementationResponse.result", - "TextDocumentInlayHintRequest.jsonrpc", - "TextDocumentInlayHintRequest.method", - "TextDocumentInlayHintResponse.jsonrpc", - "TextDocumentInlayHintResponse.result", - "TextDocumentInlineCompletionRequest.jsonrpc", - "TextDocumentInlineCompletionRequest.method", - "TextDocumentInlineCompletionResponse.jsonrpc", - "TextDocumentInlineCompletionResponse.result", - "TextDocumentInlineValueRequest.jsonrpc", - "TextDocumentInlineValueRequest.method", - "TextDocumentInlineValueResponse.jsonrpc", - "TextDocumentInlineValueResponse.result", - "TextDocumentLinkedEditingRangeRequest.jsonrpc", - "TextDocumentLinkedEditingRangeRequest.method", - "TextDocumentLinkedEditingRangeResponse.jsonrpc", - "TextDocumentLinkedEditingRangeResponse.result", - "TextDocumentMonikerRequest.jsonrpc", - "TextDocumentMonikerRequest.method", - "TextDocumentMonikerResponse.jsonrpc", - "TextDocumentMonikerResponse.result", - "TextDocumentOnTypeFormattingRequest.jsonrpc", - "TextDocumentOnTypeFormattingRequest.method", - "TextDocumentOnTypeFormattingResponse.jsonrpc", - "TextDocumentOnTypeFormattingResponse.result", - "TextDocumentPrepareCallHierarchyRequest.jsonrpc", - "TextDocumentPrepareCallHierarchyRequest.method", - "TextDocumentPrepareCallHierarchyResponse.jsonrpc", - "TextDocumentPrepareCallHierarchyResponse.result", - "TextDocumentPrepareRenameRequest.jsonrpc", - "TextDocumentPrepareRenameRequest.method", - "TextDocumentPrepareRenameResponse.jsonrpc", - "TextDocumentPrepareRenameResponse.result", - "TextDocumentPrepareTypeHierarchyRequest.jsonrpc", - "TextDocumentPrepareTypeHierarchyRequest.method", - "TextDocumentPrepareTypeHierarchyResponse.jsonrpc", - "TextDocumentPrepareTypeHierarchyResponse.result", - "TextDocumentPublishDiagnosticsNotification.jsonrpc", - "TextDocumentPublishDiagnosticsNotification.method", - "TextDocumentRangeFormattingRequest.jsonrpc", - "TextDocumentRangeFormattingRequest.method", - "TextDocumentRangeFormattingResponse.jsonrpc", - "TextDocumentRangeFormattingResponse.result", - "TextDocumentRangesFormattingRequest.jsonrpc", - "TextDocumentRangesFormattingRequest.method", - "TextDocumentRangesFormattingResponse.jsonrpc", - "TextDocumentRangesFormattingResponse.result", - "TextDocumentReferencesRequest.jsonrpc", - "TextDocumentReferencesRequest.method", - "TextDocumentReferencesResponse.jsonrpc", - "TextDocumentReferencesResponse.result", + "TextDocumentContentRefreshRequest.jsonrpc", + "TextDocumentContentRefreshRequest.method", + "TextDocumentContentRefreshResponse.jsonrpc", + "TextDocumentContentRefreshResponse.result", + "TextDocumentContentRequest.jsonrpc", + "TextDocumentContentRequest.method", + "TextDocumentContentResponse.jsonrpc", + "TextDocumentContentResponse.result", "TextDocumentRegistrationOptions.document_selector", - "TextDocumentRenameRequest.jsonrpc", - "TextDocumentRenameRequest.method", - "TextDocumentRenameResponse.jsonrpc", - "TextDocumentRenameResponse.result", "TextDocumentSaveRegistrationOptions.document_selector", - "TextDocumentSelectionRangeRequest.jsonrpc", - "TextDocumentSelectionRangeRequest.method", - "TextDocumentSelectionRangeResponse.jsonrpc", - "TextDocumentSelectionRangeResponse.result", - "TextDocumentSemanticTokensFullDeltaRequest.jsonrpc", - "TextDocumentSemanticTokensFullDeltaRequest.method", - "TextDocumentSemanticTokensFullDeltaResponse.jsonrpc", - "TextDocumentSemanticTokensFullDeltaResponse.result", - "TextDocumentSemanticTokensFullRequest.jsonrpc", - "TextDocumentSemanticTokensFullRequest.method", - "TextDocumentSemanticTokensFullResponse.jsonrpc", - "TextDocumentSemanticTokensFullResponse.result", - "TextDocumentSemanticTokensRangeRequest.jsonrpc", - "TextDocumentSemanticTokensRangeRequest.method", - "TextDocumentSemanticTokensRangeResponse.jsonrpc", - "TextDocumentSemanticTokensRangeResponse.result", - "TextDocumentSignatureHelpRequest.jsonrpc", - "TextDocumentSignatureHelpRequest.method", - "TextDocumentSignatureHelpResponse.jsonrpc", - "TextDocumentSignatureHelpResponse.result", - "TextDocumentTypeDefinitionRequest.jsonrpc", - "TextDocumentTypeDefinitionRequest.method", - "TextDocumentTypeDefinitionResponse.jsonrpc", - "TextDocumentTypeDefinitionResponse.result", - "TextDocumentWillSaveNotification.jsonrpc", - "TextDocumentWillSaveNotification.method", - "TextDocumentWillSaveWaitUntilRequest.jsonrpc", - "TextDocumentWillSaveWaitUntilRequest.method", - "TextDocumentWillSaveWaitUntilResponse.jsonrpc", - "TextDocumentWillSaveWaitUntilResponse.result", "TypeDefinitionRegistrationOptions.document_selector", + "TypeDefinitionRequest.jsonrpc", + "TypeDefinitionRequest.method", + "TypeDefinitionResponse.jsonrpc", + "TypeDefinitionResponse.result", + "TypeHierarchyPrepareRequest.jsonrpc", + "TypeHierarchyPrepareRequest.method", + "TypeHierarchyPrepareResponse.jsonrpc", + "TypeHierarchyPrepareResponse.result", "TypeHierarchyRegistrationOptions.document_selector", "TypeHierarchySubtypesRequest.jsonrpc", "TypeHierarchySubtypesRequest.method", @@ -12062,82 +13160,48 @@ _SPECIAL_PROPERTIES = [ "TypeHierarchySupertypesResponse.jsonrpc", "TypeHierarchySupertypesResponse.result", "UnchangedDocumentDiagnosticReport.kind", - "WindowLogMessageNotification.jsonrpc", - "WindowLogMessageNotification.method", - "WindowShowDocumentRequest.jsonrpc", - "WindowShowDocumentRequest.method", - "WindowShowDocumentResponse.jsonrpc", - "WindowShowDocumentResponse.result", - "WindowShowMessageNotification.jsonrpc", - "WindowShowMessageNotification.method", - "WindowShowMessageRequestRequest.jsonrpc", - "WindowShowMessageRequestRequest.method", - "WindowShowMessageRequestResponse.jsonrpc", - "WindowShowMessageRequestResponse.result", - "WindowWorkDoneProgressCancelNotification.jsonrpc", - "WindowWorkDoneProgressCancelNotification.method", - "WindowWorkDoneProgressCreateRequest.jsonrpc", - "WindowWorkDoneProgressCreateRequest.method", - "WindowWorkDoneProgressCreateResponse.jsonrpc", - "WindowWorkDoneProgressCreateResponse.result", + "UnregistrationRequest.jsonrpc", + "UnregistrationRequest.method", + "UnregistrationResponse.jsonrpc", + "UnregistrationResponse.result", + "WillCreateFilesRequest.jsonrpc", + "WillCreateFilesRequest.method", + "WillCreateFilesResponse.jsonrpc", + "WillCreateFilesResponse.result", + "WillDeleteFilesRequest.jsonrpc", + "WillDeleteFilesRequest.method", + "WillDeleteFilesResponse.jsonrpc", + "WillDeleteFilesResponse.result", + "WillRenameFilesRequest.jsonrpc", + "WillRenameFilesRequest.method", + "WillRenameFilesResponse.jsonrpc", + "WillRenameFilesResponse.result", + "WillSaveTextDocumentNotification.jsonrpc", + "WillSaveTextDocumentNotification.method", + "WillSaveTextDocumentWaitUntilRequest.jsonrpc", + "WillSaveTextDocumentWaitUntilRequest.method", + "WillSaveTextDocumentWaitUntilResponse.jsonrpc", + "WillSaveTextDocumentWaitUntilResponse.result", "WorkDoneProgressBegin.kind", + "WorkDoneProgressCancelNotification.jsonrpc", + "WorkDoneProgressCancelNotification.method", + "WorkDoneProgressCreateRequest.jsonrpc", + "WorkDoneProgressCreateRequest.method", + "WorkDoneProgressCreateResponse.jsonrpc", + "WorkDoneProgressCreateResponse.result", "WorkDoneProgressEnd.kind", "WorkDoneProgressReport.kind", - "WorkspaceApplyEditRequest.jsonrpc", - "WorkspaceApplyEditRequest.method", - "WorkspaceApplyEditResponse.jsonrpc", - "WorkspaceApplyEditResponse.result", - "WorkspaceCodeLensRefreshRequest.jsonrpc", - "WorkspaceCodeLensRefreshRequest.method", - "WorkspaceCodeLensRefreshResponse.jsonrpc", - "WorkspaceCodeLensRefreshResponse.result", - "WorkspaceConfigurationRequest.jsonrpc", - "WorkspaceConfigurationRequest.method", - "WorkspaceConfigurationResponse.jsonrpc", - "WorkspaceConfigurationResponse.result", - "WorkspaceDiagnosticRefreshRequest.jsonrpc", - "WorkspaceDiagnosticRefreshRequest.method", - "WorkspaceDiagnosticRefreshResponse.jsonrpc", - "WorkspaceDiagnosticRefreshResponse.result", "WorkspaceDiagnosticRequest.jsonrpc", "WorkspaceDiagnosticRequest.method", "WorkspaceDiagnosticResponse.jsonrpc", "WorkspaceDiagnosticResponse.result", - "WorkspaceDidChangeConfigurationNotification.jsonrpc", - "WorkspaceDidChangeConfigurationNotification.method", - "WorkspaceDidChangeWatchedFilesNotification.jsonrpc", - "WorkspaceDidChangeWatchedFilesNotification.method", - "WorkspaceDidChangeWorkspaceFoldersNotification.jsonrpc", - "WorkspaceDidChangeWorkspaceFoldersNotification.method", - "WorkspaceDidCreateFilesNotification.jsonrpc", - "WorkspaceDidCreateFilesNotification.method", - "WorkspaceDidDeleteFilesNotification.jsonrpc", - "WorkspaceDidDeleteFilesNotification.method", - "WorkspaceDidRenameFilesNotification.jsonrpc", - "WorkspaceDidRenameFilesNotification.method", - "WorkspaceExecuteCommandRequest.jsonrpc", - "WorkspaceExecuteCommandRequest.method", - "WorkspaceExecuteCommandResponse.jsonrpc", - "WorkspaceExecuteCommandResponse.result", "WorkspaceFoldersInitializeParams.workspace_folders", - "WorkspaceFoldingRangeRefreshRequest.jsonrpc", - "WorkspaceFoldingRangeRefreshRequest.method", - "WorkspaceFoldingRangeRefreshResponse.jsonrpc", - "WorkspaceFoldingRangeRefreshResponse.result", + "WorkspaceFoldersRequest.jsonrpc", + "WorkspaceFoldersRequest.method", + "WorkspaceFoldersResponse.jsonrpc", + "WorkspaceFoldersResponse.result", "WorkspaceFullDocumentDiagnosticReport.kind", "WorkspaceFullDocumentDiagnosticReport.version", - "WorkspaceInlayHintRefreshRequest.jsonrpc", - "WorkspaceInlayHintRefreshRequest.method", - "WorkspaceInlayHintRefreshResponse.jsonrpc", - "WorkspaceInlayHintRefreshResponse.result", - "WorkspaceInlineValueRefreshRequest.jsonrpc", - "WorkspaceInlineValueRefreshRequest.method", - "WorkspaceInlineValueRefreshResponse.jsonrpc", - "WorkspaceInlineValueRefreshResponse.result", - "WorkspaceSemanticTokensRefreshRequest.jsonrpc", - "WorkspaceSemanticTokensRefreshRequest.method", - "WorkspaceSemanticTokensRefreshResponse.jsonrpc", - "WorkspaceSemanticTokensRefreshResponse.result", "WorkspaceSymbolRequest.jsonrpc", "WorkspaceSymbolRequest.method", "WorkspaceSymbolResolveRequest.jsonrpc", @@ -12148,22 +13212,6 @@ _SPECIAL_PROPERTIES = [ "WorkspaceSymbolResponse.result", "WorkspaceUnchangedDocumentDiagnosticReport.kind", "WorkspaceUnchangedDocumentDiagnosticReport.version", - "WorkspaceWillCreateFilesRequest.jsonrpc", - "WorkspaceWillCreateFilesRequest.method", - "WorkspaceWillCreateFilesResponse.jsonrpc", - "WorkspaceWillCreateFilesResponse.result", - "WorkspaceWillDeleteFilesRequest.jsonrpc", - "WorkspaceWillDeleteFilesRequest.method", - "WorkspaceWillDeleteFilesResponse.jsonrpc", - "WorkspaceWillDeleteFilesResponse.result", - "WorkspaceWillRenameFilesRequest.jsonrpc", - "WorkspaceWillRenameFilesRequest.method", - "WorkspaceWillRenameFilesResponse.jsonrpc", - "WorkspaceWillRenameFilesResponse.result", - "WorkspaceWorkspaceFoldersRequest.jsonrpc", - "WorkspaceWorkspaceFoldersRequest.method", - "WorkspaceWorkspaceFoldersResponse.jsonrpc", - "WorkspaceWorkspaceFoldersResponse.result", "_InitializeParams.process_id", "_InitializeParams.root_path", "_InitializeParams.root_uri", @@ -12188,7 +13236,10 @@ def is_special_property(cls: type, property_name: str) -> bool: ALL_TYPES_MAP: Dict[str, Union[type, object]] = { "AnnotatedTextEdit": AnnotatedTextEdit, + "ApplyKind": ApplyKind, "ApplyWorkspaceEditParams": ApplyWorkspaceEditParams, + "ApplyWorkspaceEditRequest": ApplyWorkspaceEditRequest, + "ApplyWorkspaceEditResponse": ApplyWorkspaceEditResponse, "ApplyWorkspaceEditResult": ApplyWorkspaceEditResult, "BaseSymbolInformation": BaseSymbolInformation, "CallHierarchyClientCapabilities": CallHierarchyClientCapabilities, @@ -12196,76 +13247,111 @@ ALL_TYPES_MAP: Dict[str, Union[type, object]] = { "CallHierarchyIncomingCallsParams": CallHierarchyIncomingCallsParams, "CallHierarchyIncomingCallsRequest": CallHierarchyIncomingCallsRequest, "CallHierarchyIncomingCallsResponse": CallHierarchyIncomingCallsResponse, + "CallHierarchyIncomingCallsResult": CallHierarchyIncomingCallsResult, "CallHierarchyItem": CallHierarchyItem, "CallHierarchyOptions": CallHierarchyOptions, "CallHierarchyOutgoingCall": CallHierarchyOutgoingCall, "CallHierarchyOutgoingCallsParams": CallHierarchyOutgoingCallsParams, "CallHierarchyOutgoingCallsRequest": CallHierarchyOutgoingCallsRequest, "CallHierarchyOutgoingCallsResponse": CallHierarchyOutgoingCallsResponse, + "CallHierarchyOutgoingCallsResult": CallHierarchyOutgoingCallsResult, "CallHierarchyPrepareParams": CallHierarchyPrepareParams, + "CallHierarchyPrepareRequest": CallHierarchyPrepareRequest, + "CallHierarchyPrepareResponse": CallHierarchyPrepareResponse, + "CallHierarchyPrepareResult": CallHierarchyPrepareResult, "CallHierarchyRegistrationOptions": CallHierarchyRegistrationOptions, + "CancelNotification": CancelNotification, "CancelParams": CancelParams, - "CancelRequestNotification": CancelRequestNotification, "ChangeAnnotation": ChangeAnnotation, "ChangeAnnotationIdentifier": ChangeAnnotationIdentifier, + "ChangeAnnotationsSupportOptions": ChangeAnnotationsSupportOptions, "ClientCapabilities": ClientCapabilities, - "ClientRegisterCapabilityRequest": ClientRegisterCapabilityRequest, - "ClientRegisterCapabilityResponse": ClientRegisterCapabilityResponse, - "ClientUnregisterCapabilityRequest": ClientUnregisterCapabilityRequest, - "ClientUnregisterCapabilityResponse": ClientUnregisterCapabilityResponse, + "ClientCodeActionKindOptions": ClientCodeActionKindOptions, + "ClientCodeActionLiteralOptions": ClientCodeActionLiteralOptions, + "ClientCodeActionResolveOptions": ClientCodeActionResolveOptions, + "ClientCodeLensResolveOptions": ClientCodeLensResolveOptions, + "ClientCompletionItemInsertTextModeOptions": ClientCompletionItemInsertTextModeOptions, + "ClientCompletionItemOptions": ClientCompletionItemOptions, + "ClientCompletionItemOptionsKind": ClientCompletionItemOptionsKind, + "ClientCompletionItemResolveOptions": ClientCompletionItemResolveOptions, + "ClientDiagnosticsTagOptions": ClientDiagnosticsTagOptions, + "ClientFoldingRangeKindOptions": ClientFoldingRangeKindOptions, + "ClientFoldingRangeOptions": ClientFoldingRangeOptions, + "ClientInfo": ClientInfo, + "ClientInlayHintResolveOptions": ClientInlayHintResolveOptions, + "ClientSemanticTokensRequestFullDelta": ClientSemanticTokensRequestFullDelta, + "ClientSemanticTokensRequestOptions": ClientSemanticTokensRequestOptions, + "ClientShowMessageActionItemOptions": ClientShowMessageActionItemOptions, + "ClientSignatureInformationOptions": ClientSignatureInformationOptions, + "ClientSignatureParameterInformationOptions": ClientSignatureParameterInformationOptions, + "ClientSymbolKindOptions": ClientSymbolKindOptions, + "ClientSymbolResolveOptions": ClientSymbolResolveOptions, + "ClientSymbolTagOptions": ClientSymbolTagOptions, "CodeAction": CodeAction, "CodeActionClientCapabilities": CodeActionClientCapabilities, - "CodeActionClientCapabilitiesCodeActionLiteralSupportType": CodeActionClientCapabilitiesCodeActionLiteralSupportType, - "CodeActionClientCapabilitiesCodeActionLiteralSupportTypeCodeActionKindType": CodeActionClientCapabilitiesCodeActionLiteralSupportTypeCodeActionKindType, - "CodeActionClientCapabilitiesResolveSupportType": CodeActionClientCapabilitiesResolveSupportType, "CodeActionContext": CodeActionContext, - "CodeActionDisabledType": CodeActionDisabledType, + "CodeActionDisabled": CodeActionDisabled, "CodeActionKind": CodeActionKind, + "CodeActionKindDocumentation": CodeActionKindDocumentation, "CodeActionOptions": CodeActionOptions, "CodeActionParams": CodeActionParams, "CodeActionRegistrationOptions": CodeActionRegistrationOptions, + "CodeActionRequest": CodeActionRequest, "CodeActionResolveRequest": CodeActionResolveRequest, "CodeActionResolveResponse": CodeActionResolveResponse, + "CodeActionResponse": CodeActionResponse, + "CodeActionResult": CodeActionResult, + "CodeActionTag": CodeActionTag, + "CodeActionTagOptions": CodeActionTagOptions, "CodeActionTriggerKind": CodeActionTriggerKind, "CodeDescription": CodeDescription, "CodeLens": CodeLens, "CodeLensClientCapabilities": CodeLensClientCapabilities, "CodeLensOptions": CodeLensOptions, "CodeLensParams": CodeLensParams, + "CodeLensRefreshRequest": CodeLensRefreshRequest, + "CodeLensRefreshResponse": CodeLensRefreshResponse, "CodeLensRegistrationOptions": CodeLensRegistrationOptions, + "CodeLensRequest": CodeLensRequest, "CodeLensResolveRequest": CodeLensResolveRequest, "CodeLensResolveResponse": CodeLensResolveResponse, + "CodeLensResponse": CodeLensResponse, + "CodeLensResult": CodeLensResult, "CodeLensWorkspaceClientCapabilities": CodeLensWorkspaceClientCapabilities, "Color": Color, "ColorInformation": ColorInformation, "ColorPresentation": ColorPresentation, "ColorPresentationParams": ColorPresentationParams, + "ColorPresentationRequest": ColorPresentationRequest, + "ColorPresentationRequestOptions": ColorPresentationRequestOptions, + "ColorPresentationResponse": ColorPresentationResponse, + "ColorPresentationResult": ColorPresentationResult, "Command": Command, "CompletionClientCapabilities": CompletionClientCapabilities, - "CompletionClientCapabilitiesCompletionItemKindType": CompletionClientCapabilitiesCompletionItemKindType, - "CompletionClientCapabilitiesCompletionItemType": CompletionClientCapabilitiesCompletionItemType, - "CompletionClientCapabilitiesCompletionItemTypeInsertTextModeSupportType": CompletionClientCapabilitiesCompletionItemTypeInsertTextModeSupportType, - "CompletionClientCapabilitiesCompletionItemTypeResolveSupportType": CompletionClientCapabilitiesCompletionItemTypeResolveSupportType, - "CompletionClientCapabilitiesCompletionItemTypeTagSupportType": CompletionClientCapabilitiesCompletionItemTypeTagSupportType, - "CompletionClientCapabilitiesCompletionListType": CompletionClientCapabilitiesCompletionListType, "CompletionContext": CompletionContext, "CompletionItem": CompletionItem, + "CompletionItemApplyKinds": CompletionItemApplyKinds, + "CompletionItemDefaults": CompletionItemDefaults, "CompletionItemKind": CompletionItemKind, "CompletionItemLabelDetails": CompletionItemLabelDetails, - "CompletionItemResolveRequest": CompletionItemResolveRequest, - "CompletionItemResolveResponse": CompletionItemResolveResponse, "CompletionItemTag": CompletionItemTag, + "CompletionItemTagOptions": CompletionItemTagOptions, "CompletionList": CompletionList, - "CompletionListItemDefaultsType": CompletionListItemDefaultsType, - "CompletionListItemDefaultsTypeEditRangeType1": CompletionListItemDefaultsTypeEditRangeType1, + "CompletionListCapabilities": CompletionListCapabilities, "CompletionOptions": CompletionOptions, - "CompletionOptionsCompletionItemType": CompletionOptionsCompletionItemType, "CompletionParams": CompletionParams, "CompletionRegistrationOptions": CompletionRegistrationOptions, - "CompletionRegistrationOptionsCompletionItemType": CompletionRegistrationOptionsCompletionItemType, + "CompletionRequest": CompletionRequest, + "CompletionResolveRequest": CompletionResolveRequest, + "CompletionResolveResponse": CompletionResolveResponse, + "CompletionResponse": CompletionResponse, + "CompletionResult": CompletionResult, "CompletionTriggerKind": CompletionTriggerKind, "ConfigurationItem": ConfigurationItem, "ConfigurationParams": ConfigurationParams, + "ConfigurationRequest": ConfigurationRequest, + "ConfigurationResponse": ConfigurationResponse, + "ConfigurationResult": ConfigurationResult, "CreateFile": CreateFile, "CreateFileOptions": CreateFileOptions, "CreateFilesParams": CreateFilesParams, @@ -12275,87 +13361,138 @@ ALL_TYPES_MAP: Dict[str, Union[type, object]] = { "DeclarationOptions": DeclarationOptions, "DeclarationParams": DeclarationParams, "DeclarationRegistrationOptions": DeclarationRegistrationOptions, + "DeclarationRequest": DeclarationRequest, + "DeclarationResponse": DeclarationResponse, + "DeclarationResult": DeclarationResult, "Definition": Definition, "DefinitionClientCapabilities": DefinitionClientCapabilities, "DefinitionLink": DefinitionLink, "DefinitionOptions": DefinitionOptions, "DefinitionParams": DefinitionParams, "DefinitionRegistrationOptions": DefinitionRegistrationOptions, + "DefinitionRequest": DefinitionRequest, + "DefinitionResponse": DefinitionResponse, + "DefinitionResult": DefinitionResult, "DeleteFile": DeleteFile, "DeleteFileOptions": DeleteFileOptions, "DeleteFilesParams": DeleteFilesParams, "Diagnostic": Diagnostic, "DiagnosticClientCapabilities": DiagnosticClientCapabilities, "DiagnosticOptions": DiagnosticOptions, + "DiagnosticRefreshRequest": DiagnosticRefreshRequest, + "DiagnosticRefreshResponse": DiagnosticRefreshResponse, "DiagnosticRegistrationOptions": DiagnosticRegistrationOptions, "DiagnosticRelatedInformation": DiagnosticRelatedInformation, "DiagnosticServerCancellationData": DiagnosticServerCancellationData, "DiagnosticSeverity": DiagnosticSeverity, "DiagnosticTag": DiagnosticTag, "DiagnosticWorkspaceClientCapabilities": DiagnosticWorkspaceClientCapabilities, + "DiagnosticsCapabilities": DiagnosticsCapabilities, "DidChangeConfigurationClientCapabilities": DidChangeConfigurationClientCapabilities, + "DidChangeConfigurationNotification": DidChangeConfigurationNotification, "DidChangeConfigurationParams": DidChangeConfigurationParams, "DidChangeConfigurationRegistrationOptions": DidChangeConfigurationRegistrationOptions, + "DidChangeNotebookDocumentNotification": DidChangeNotebookDocumentNotification, "DidChangeNotebookDocumentParams": DidChangeNotebookDocumentParams, + "DidChangeTextDocumentNotification": DidChangeTextDocumentNotification, "DidChangeTextDocumentParams": DidChangeTextDocumentParams, "DidChangeWatchedFilesClientCapabilities": DidChangeWatchedFilesClientCapabilities, + "DidChangeWatchedFilesNotification": DidChangeWatchedFilesNotification, "DidChangeWatchedFilesParams": DidChangeWatchedFilesParams, "DidChangeWatchedFilesRegistrationOptions": DidChangeWatchedFilesRegistrationOptions, + "DidChangeWorkspaceFoldersNotification": DidChangeWorkspaceFoldersNotification, "DidChangeWorkspaceFoldersParams": DidChangeWorkspaceFoldersParams, + "DidCloseNotebookDocumentNotification": DidCloseNotebookDocumentNotification, "DidCloseNotebookDocumentParams": DidCloseNotebookDocumentParams, + "DidCloseTextDocumentNotification": DidCloseTextDocumentNotification, "DidCloseTextDocumentParams": DidCloseTextDocumentParams, + "DidCreateFilesNotification": DidCreateFilesNotification, + "DidDeleteFilesNotification": DidDeleteFilesNotification, + "DidOpenNotebookDocumentNotification": DidOpenNotebookDocumentNotification, "DidOpenNotebookDocumentParams": DidOpenNotebookDocumentParams, + "DidOpenTextDocumentNotification": DidOpenTextDocumentNotification, "DidOpenTextDocumentParams": DidOpenTextDocumentParams, + "DidRenameFilesNotification": DidRenameFilesNotification, + "DidSaveNotebookDocumentNotification": DidSaveNotebookDocumentNotification, "DidSaveNotebookDocumentParams": DidSaveNotebookDocumentParams, + "DidSaveTextDocumentNotification": DidSaveTextDocumentNotification, "DidSaveTextDocumentParams": DidSaveTextDocumentParams, "DocumentColorClientCapabilities": DocumentColorClientCapabilities, "DocumentColorOptions": DocumentColorOptions, "DocumentColorParams": DocumentColorParams, "DocumentColorRegistrationOptions": DocumentColorRegistrationOptions, + "DocumentColorRequest": DocumentColorRequest, + "DocumentColorResponse": DocumentColorResponse, + "DocumentColorResult": DocumentColorResult, "DocumentDiagnosticParams": DocumentDiagnosticParams, "DocumentDiagnosticReport": DocumentDiagnosticReport, "DocumentDiagnosticReportKind": DocumentDiagnosticReportKind, "DocumentDiagnosticReportPartialResult": DocumentDiagnosticReportPartialResult, + "DocumentDiagnosticRequest": DocumentDiagnosticRequest, + "DocumentDiagnosticResponse": DocumentDiagnosticResponse, "DocumentFilter": DocumentFilter, "DocumentFormattingClientCapabilities": DocumentFormattingClientCapabilities, "DocumentFormattingOptions": DocumentFormattingOptions, "DocumentFormattingParams": DocumentFormattingParams, "DocumentFormattingRegistrationOptions": DocumentFormattingRegistrationOptions, + "DocumentFormattingRequest": DocumentFormattingRequest, + "DocumentFormattingResponse": DocumentFormattingResponse, + "DocumentFormattingResult": DocumentFormattingResult, "DocumentHighlight": DocumentHighlight, "DocumentHighlightClientCapabilities": DocumentHighlightClientCapabilities, "DocumentHighlightKind": DocumentHighlightKind, "DocumentHighlightOptions": DocumentHighlightOptions, "DocumentHighlightParams": DocumentHighlightParams, "DocumentHighlightRegistrationOptions": DocumentHighlightRegistrationOptions, + "DocumentHighlightRequest": DocumentHighlightRequest, + "DocumentHighlightResponse": DocumentHighlightResponse, + "DocumentHighlightResult": DocumentHighlightResult, "DocumentLink": DocumentLink, "DocumentLinkClientCapabilities": DocumentLinkClientCapabilities, "DocumentLinkOptions": DocumentLinkOptions, "DocumentLinkParams": DocumentLinkParams, "DocumentLinkRegistrationOptions": DocumentLinkRegistrationOptions, + "DocumentLinkRequest": DocumentLinkRequest, "DocumentLinkResolveRequest": DocumentLinkResolveRequest, "DocumentLinkResolveResponse": DocumentLinkResolveResponse, + "DocumentLinkResponse": DocumentLinkResponse, + "DocumentLinkResult": DocumentLinkResult, "DocumentOnTypeFormattingClientCapabilities": DocumentOnTypeFormattingClientCapabilities, "DocumentOnTypeFormattingOptions": DocumentOnTypeFormattingOptions, "DocumentOnTypeFormattingParams": DocumentOnTypeFormattingParams, "DocumentOnTypeFormattingRegistrationOptions": DocumentOnTypeFormattingRegistrationOptions, + "DocumentOnTypeFormattingRequest": DocumentOnTypeFormattingRequest, + "DocumentOnTypeFormattingResponse": DocumentOnTypeFormattingResponse, + "DocumentOnTypeFormattingResult": DocumentOnTypeFormattingResult, "DocumentRangeFormattingClientCapabilities": DocumentRangeFormattingClientCapabilities, "DocumentRangeFormattingOptions": DocumentRangeFormattingOptions, "DocumentRangeFormattingParams": DocumentRangeFormattingParams, "DocumentRangeFormattingRegistrationOptions": DocumentRangeFormattingRegistrationOptions, + "DocumentRangeFormattingRequest": DocumentRangeFormattingRequest, + "DocumentRangeFormattingResponse": DocumentRangeFormattingResponse, + "DocumentRangeFormattingResult": DocumentRangeFormattingResult, "DocumentRangesFormattingParams": DocumentRangesFormattingParams, + "DocumentRangesFormattingRequest": DocumentRangesFormattingRequest, + "DocumentRangesFormattingResponse": DocumentRangesFormattingResponse, + "DocumentRangesFormattingResult": DocumentRangesFormattingResult, "DocumentSelector": DocumentSelector, "DocumentSymbol": DocumentSymbol, "DocumentSymbolClientCapabilities": DocumentSymbolClientCapabilities, - "DocumentSymbolClientCapabilitiesSymbolKindType": DocumentSymbolClientCapabilitiesSymbolKindType, - "DocumentSymbolClientCapabilitiesTagSupportType": DocumentSymbolClientCapabilitiesTagSupportType, "DocumentSymbolOptions": DocumentSymbolOptions, "DocumentSymbolParams": DocumentSymbolParams, "DocumentSymbolRegistrationOptions": DocumentSymbolRegistrationOptions, + "DocumentSymbolRequest": DocumentSymbolRequest, + "DocumentSymbolResponse": DocumentSymbolResponse, + "DocumentSymbolResult": DocumentSymbolResult, + "EditRangeWithInsertReplace": EditRangeWithInsertReplace, "ErrorCodes": ErrorCodes, "ExecuteCommandClientCapabilities": ExecuteCommandClientCapabilities, "ExecuteCommandOptions": ExecuteCommandOptions, "ExecuteCommandParams": ExecuteCommandParams, "ExecuteCommandRegistrationOptions": ExecuteCommandRegistrationOptions, + "ExecuteCommandRequest": ExecuteCommandRequest, + "ExecuteCommandResponse": ExecuteCommandResponse, + "ExecuteCommandResult": ExecuteCommandResult, "ExecutionSummary": ExecutionSummary, "ExitNotification": ExitNotification, "FailureHandlingKind": FailureHandlingKind, @@ -12374,46 +13511,56 @@ ALL_TYPES_MAP: Dict[str, Union[type, object]] = { "FileSystemWatcher": FileSystemWatcher, "FoldingRange": FoldingRange, "FoldingRangeClientCapabilities": FoldingRangeClientCapabilities, - "FoldingRangeClientCapabilitiesFoldingRangeKindType": FoldingRangeClientCapabilitiesFoldingRangeKindType, - "FoldingRangeClientCapabilitiesFoldingRangeType": FoldingRangeClientCapabilitiesFoldingRangeType, "FoldingRangeKind": FoldingRangeKind, "FoldingRangeOptions": FoldingRangeOptions, "FoldingRangeParams": FoldingRangeParams, + "FoldingRangeRefreshRequest": FoldingRangeRefreshRequest, + "FoldingRangeRefreshResponse": FoldingRangeRefreshResponse, "FoldingRangeRegistrationOptions": FoldingRangeRegistrationOptions, + "FoldingRangeRequest": FoldingRangeRequest, + "FoldingRangeResponse": FoldingRangeResponse, + "FoldingRangeResult": FoldingRangeResult, "FoldingRangeWorkspaceClientCapabilities": FoldingRangeWorkspaceClientCapabilities, "FormattingOptions": FormattingOptions, "FullDocumentDiagnosticReport": FullDocumentDiagnosticReport, "GeneralClientCapabilities": GeneralClientCapabilities, - "GeneralClientCapabilitiesStaleRequestSupportType": GeneralClientCapabilitiesStaleRequestSupportType, "GlobPattern": GlobPattern, "Hover": Hover, "HoverClientCapabilities": HoverClientCapabilities, "HoverOptions": HoverOptions, "HoverParams": HoverParams, "HoverRegistrationOptions": HoverRegistrationOptions, + "HoverRequest": HoverRequest, + "HoverResponse": HoverResponse, + "HoverResult": HoverResult, "ImplementationClientCapabilities": ImplementationClientCapabilities, "ImplementationOptions": ImplementationOptions, "ImplementationParams": ImplementationParams, "ImplementationRegistrationOptions": ImplementationRegistrationOptions, + "ImplementationRequest": ImplementationRequest, + "ImplementationResponse": ImplementationResponse, + "ImplementationResult": ImplementationResult, "InitializeError": InitializeError, "InitializeParams": InitializeParams, - "InitializeParamsClientInfoType": InitializeParamsClientInfoType, "InitializeRequest": InitializeRequest, "InitializeResponse": InitializeResponse, "InitializeResult": InitializeResult, - "InitializeResultServerInfoType": InitializeResultServerInfoType, "InitializedNotification": InitializedNotification, "InitializedParams": InitializedParams, "InlayHint": InlayHint, "InlayHintClientCapabilities": InlayHintClientCapabilities, - "InlayHintClientCapabilitiesResolveSupportType": InlayHintClientCapabilitiesResolveSupportType, "InlayHintKind": InlayHintKind, "InlayHintLabelPart": InlayHintLabelPart, "InlayHintOptions": InlayHintOptions, "InlayHintParams": InlayHintParams, + "InlayHintRefreshRequest": InlayHintRefreshRequest, + "InlayHintRefreshResponse": InlayHintRefreshResponse, "InlayHintRegistrationOptions": InlayHintRegistrationOptions, + "InlayHintRequest": InlayHintRequest, "InlayHintResolveRequest": InlayHintResolveRequest, "InlayHintResolveResponse": InlayHintResolveResponse, + "InlayHintResponse": InlayHintResponse, + "InlayHintResult": InlayHintResult, "InlayHintWorkspaceClientCapabilities": InlayHintWorkspaceClientCapabilities, "InlineCompletionClientCapabilities": InlineCompletionClientCapabilities, "InlineCompletionContext": InlineCompletionContext, @@ -12422,6 +13569,9 @@ ALL_TYPES_MAP: Dict[str, Union[type, object]] = { "InlineCompletionOptions": InlineCompletionOptions, "InlineCompletionParams": InlineCompletionParams, "InlineCompletionRegistrationOptions": InlineCompletionRegistrationOptions, + "InlineCompletionRequest": InlineCompletionRequest, + "InlineCompletionResponse": InlineCompletionResponse, + "InlineCompletionResult": InlineCompletionResult, "InlineCompletionTriggerKind": InlineCompletionTriggerKind, "InlineValue": InlineValue, "InlineValueClientCapabilities": InlineValueClientCapabilities, @@ -12429,7 +13579,12 @@ ALL_TYPES_MAP: Dict[str, Union[type, object]] = { "InlineValueEvaluatableExpression": InlineValueEvaluatableExpression, "InlineValueOptions": InlineValueOptions, "InlineValueParams": InlineValueParams, + "InlineValueRefreshRequest": InlineValueRefreshRequest, + "InlineValueRefreshResponse": InlineValueRefreshResponse, "InlineValueRegistrationOptions": InlineValueRegistrationOptions, + "InlineValueRequest": InlineValueRequest, + "InlineValueResponse": InlineValueResponse, + "InlineValueResult": InlineValueResult, "InlineValueText": InlineValueText, "InlineValueVariableLookup": InlineValueVariableLookup, "InlineValueWorkspaceClientCapabilities": InlineValueWorkspaceClientCapabilities, @@ -12440,19 +13595,25 @@ ALL_TYPES_MAP: Dict[str, Union[type, object]] = { "LSPArray": LSPArray, "LSPErrorCodes": LSPErrorCodes, "LSPObject": LSPObject, + "LanguageKind": LanguageKind, "LinkedEditingRangeClientCapabilities": LinkedEditingRangeClientCapabilities, "LinkedEditingRangeOptions": LinkedEditingRangeOptions, "LinkedEditingRangeParams": LinkedEditingRangeParams, "LinkedEditingRangeRegistrationOptions": LinkedEditingRangeRegistrationOptions, + "LinkedEditingRangeRequest": LinkedEditingRangeRequest, + "LinkedEditingRangeResponse": LinkedEditingRangeResponse, + "LinkedEditingRangeResult": LinkedEditingRangeResult, "LinkedEditingRanges": LinkedEditingRanges, "Location": Location, "LocationLink": LocationLink, + "LocationUriOnly": LocationUriOnly, + "LogMessageNotification": LogMessageNotification, "LogMessageParams": LogMessageParams, "LogTraceNotification": LogTraceNotification, "LogTraceParams": LogTraceParams, "MarkdownClientCapabilities": MarkdownClientCapabilities, "MarkedString": MarkedString, - "MarkedString_Type1": MarkedString_Type1, + "MarkedStringWithLanguage": MarkedStringWithLanguage, "MarkupContent": MarkupContent, "MarkupKind": MarkupKind, "MessageActionItem": MessageActionItem, @@ -12464,53 +13625,49 @@ ALL_TYPES_MAP: Dict[str, Union[type, object]] = { "MonikerOptions": MonikerOptions, "MonikerParams": MonikerParams, "MonikerRegistrationOptions": MonikerRegistrationOptions, + "MonikerRequest": MonikerRequest, + "MonikerResponse": MonikerResponse, + "MonikerResult": MonikerResult, "NotebookCell": NotebookCell, "NotebookCellArrayChange": NotebookCellArrayChange, "NotebookCellKind": NotebookCellKind, + "NotebookCellLanguage": NotebookCellLanguage, "NotebookCellTextDocumentFilter": NotebookCellTextDocumentFilter, "NotebookDocument": NotebookDocument, + "NotebookDocumentCellChangeStructure": NotebookDocumentCellChangeStructure, + "NotebookDocumentCellChanges": NotebookDocumentCellChanges, + "NotebookDocumentCellContentChanges": NotebookDocumentCellContentChanges, "NotebookDocumentChangeEvent": NotebookDocumentChangeEvent, - "NotebookDocumentChangeEventCellsType": NotebookDocumentChangeEventCellsType, - "NotebookDocumentChangeEventCellsTypeStructureType": NotebookDocumentChangeEventCellsTypeStructureType, - "NotebookDocumentChangeEventCellsTypeTextContentType": NotebookDocumentChangeEventCellsTypeTextContentType, "NotebookDocumentClientCapabilities": NotebookDocumentClientCapabilities, - "NotebookDocumentDidChangeNotification": NotebookDocumentDidChangeNotification, - "NotebookDocumentDidCloseNotification": NotebookDocumentDidCloseNotification, - "NotebookDocumentDidOpenNotification": NotebookDocumentDidOpenNotification, - "NotebookDocumentDidSaveNotification": NotebookDocumentDidSaveNotification, "NotebookDocumentFilter": NotebookDocumentFilter, - "NotebookDocumentFilter_Type1": NotebookDocumentFilter_Type1, - "NotebookDocumentFilter_Type2": NotebookDocumentFilter_Type2, - "NotebookDocumentFilter_Type3": NotebookDocumentFilter_Type3, + "NotebookDocumentFilterNotebookType": NotebookDocumentFilterNotebookType, + "NotebookDocumentFilterPattern": NotebookDocumentFilterPattern, + "NotebookDocumentFilterScheme": NotebookDocumentFilterScheme, + "NotebookDocumentFilterWithCells": NotebookDocumentFilterWithCells, + "NotebookDocumentFilterWithNotebook": NotebookDocumentFilterWithNotebook, "NotebookDocumentIdentifier": NotebookDocumentIdentifier, "NotebookDocumentSyncClientCapabilities": NotebookDocumentSyncClientCapabilities, "NotebookDocumentSyncOptions": NotebookDocumentSyncOptions, - "NotebookDocumentSyncOptionsNotebookSelectorType1": NotebookDocumentSyncOptionsNotebookSelectorType1, - "NotebookDocumentSyncOptionsNotebookSelectorType1CellsType": NotebookDocumentSyncOptionsNotebookSelectorType1CellsType, - "NotebookDocumentSyncOptionsNotebookSelectorType2": NotebookDocumentSyncOptionsNotebookSelectorType2, - "NotebookDocumentSyncOptionsNotebookSelectorType2CellsType": NotebookDocumentSyncOptionsNotebookSelectorType2CellsType, "NotebookDocumentSyncRegistrationOptions": NotebookDocumentSyncRegistrationOptions, - "NotebookDocumentSyncRegistrationOptionsNotebookSelectorType1": NotebookDocumentSyncRegistrationOptionsNotebookSelectorType1, - "NotebookDocumentSyncRegistrationOptionsNotebookSelectorType1CellsType": NotebookDocumentSyncRegistrationOptionsNotebookSelectorType1CellsType, - "NotebookDocumentSyncRegistrationOptionsNotebookSelectorType2": NotebookDocumentSyncRegistrationOptionsNotebookSelectorType2, - "NotebookDocumentSyncRegistrationOptionsNotebookSelectorType2CellsType": NotebookDocumentSyncRegistrationOptionsNotebookSelectorType2CellsType, "OptionalVersionedTextDocumentIdentifier": OptionalVersionedTextDocumentIdentifier, "ParameterInformation": ParameterInformation, "PartialResultParams": PartialResultParams, "Pattern": Pattern, "Position": Position, "PositionEncodingKind": PositionEncodingKind, + "PrepareRenameDefaultBehavior": PrepareRenameDefaultBehavior, "PrepareRenameParams": PrepareRenameParams, + "PrepareRenamePlaceholder": PrepareRenamePlaceholder, + "PrepareRenameRequest": PrepareRenameRequest, + "PrepareRenameResponse": PrepareRenameResponse, "PrepareRenameResult": PrepareRenameResult, - "PrepareRenameResult_Type1": PrepareRenameResult_Type1, - "PrepareRenameResult_Type2": PrepareRenameResult_Type2, "PrepareSupportDefaultBehavior": PrepareSupportDefaultBehavior, "PreviousResultId": PreviousResultId, "ProgressNotification": ProgressNotification, "ProgressParams": ProgressParams, "ProgressToken": ProgressToken, "PublishDiagnosticsClientCapabilities": PublishDiagnosticsClientCapabilities, - "PublishDiagnosticsClientCapabilitiesTagSupportType": PublishDiagnosticsClientCapabilitiesTagSupportType, + "PublishDiagnosticsNotification": PublishDiagnosticsNotification, "PublishDiagnosticsParams": PublishDiagnosticsParams, "Range": Range, "ReferenceClientCapabilities": ReferenceClientCapabilities, @@ -12518,8 +13675,14 @@ ALL_TYPES_MAP: Dict[str, Union[type, object]] = { "ReferenceOptions": ReferenceOptions, "ReferenceParams": ReferenceParams, "ReferenceRegistrationOptions": ReferenceRegistrationOptions, + "ReferencesRequest": ReferencesRequest, + "ReferencesResponse": ReferencesResponse, + "ReferencesResult": ReferencesResult, "Registration": Registration, "RegistrationParams": RegistrationParams, + "RegistrationRequest": RegistrationRequest, + "RegistrationResponse": RegistrationResponse, + "RegularExpressionEngineKind": RegularExpressionEngineKind, "RegularExpressionsClientCapabilities": RegularExpressionsClientCapabilities, "RelatedFullDocumentDiagnosticReport": RelatedFullDocumentDiagnosticReport, "RelatedUnchangedDocumentDiagnosticReport": RelatedUnchangedDocumentDiagnosticReport, @@ -12531,6 +13694,9 @@ ALL_TYPES_MAP: Dict[str, Union[type, object]] = { "RenameOptions": RenameOptions, "RenameParams": RenameParams, "RenameRegistrationOptions": RenameRegistrationOptions, + "RenameRequest": RenameRequest, + "RenameResponse": RenameResponse, + "RenameResult": RenameResult, "ResourceOperation": ResourceOperation, "ResourceOperationKind": ResourceOperationKind, "ResponseError": ResponseError, @@ -12542,48 +13708,68 @@ ALL_TYPES_MAP: Dict[str, Union[type, object]] = { "SelectionRangeOptions": SelectionRangeOptions, "SelectionRangeParams": SelectionRangeParams, "SelectionRangeRegistrationOptions": SelectionRangeRegistrationOptions, + "SelectionRangeRequest": SelectionRangeRequest, + "SelectionRangeResponse": SelectionRangeResponse, + "SelectionRangeResult": SelectionRangeResult, "SemanticTokenModifiers": SemanticTokenModifiers, "SemanticTokenTypes": SemanticTokenTypes, "SemanticTokens": SemanticTokens, "SemanticTokensClientCapabilities": SemanticTokensClientCapabilities, - "SemanticTokensClientCapabilitiesRequestsType": SemanticTokensClientCapabilitiesRequestsType, - "SemanticTokensClientCapabilitiesRequestsTypeFullType1": SemanticTokensClientCapabilitiesRequestsTypeFullType1, "SemanticTokensDelta": SemanticTokensDelta, "SemanticTokensDeltaParams": SemanticTokensDeltaParams, "SemanticTokensDeltaPartialResult": SemanticTokensDeltaPartialResult, + "SemanticTokensDeltaRequest": SemanticTokensDeltaRequest, + "SemanticTokensDeltaResponse": SemanticTokensDeltaResponse, + "SemanticTokensDeltaResult": SemanticTokensDeltaResult, "SemanticTokensEdit": SemanticTokensEdit, + "SemanticTokensFullDelta": SemanticTokensFullDelta, "SemanticTokensLegend": SemanticTokensLegend, "SemanticTokensOptions": SemanticTokensOptions, - "SemanticTokensOptionsFullType1": SemanticTokensOptionsFullType1, "SemanticTokensParams": SemanticTokensParams, "SemanticTokensPartialResult": SemanticTokensPartialResult, "SemanticTokensRangeParams": SemanticTokensRangeParams, + "SemanticTokensRangeRequest": SemanticTokensRangeRequest, + "SemanticTokensRangeResponse": SemanticTokensRangeResponse, + "SemanticTokensRangeResult": SemanticTokensRangeResult, + "SemanticTokensRefreshRequest": SemanticTokensRefreshRequest, + "SemanticTokensRefreshResponse": SemanticTokensRefreshResponse, "SemanticTokensRegistrationOptions": SemanticTokensRegistrationOptions, - "SemanticTokensRegistrationOptionsFullType1": SemanticTokensRegistrationOptionsFullType1, + "SemanticTokensRequest": SemanticTokensRequest, + "SemanticTokensResponse": SemanticTokensResponse, + "SemanticTokensResult": SemanticTokensResult, "SemanticTokensWorkspaceClientCapabilities": SemanticTokensWorkspaceClientCapabilities, "ServerCapabilities": ServerCapabilities, - "ServerCapabilitiesWorkspaceType": ServerCapabilitiesWorkspaceType, + "ServerCompletionItemOptions": ServerCompletionItemOptions, + "ServerInfo": ServerInfo, "SetTraceNotification": SetTraceNotification, "SetTraceParams": SetTraceParams, "ShowDocumentClientCapabilities": ShowDocumentClientCapabilities, "ShowDocumentParams": ShowDocumentParams, + "ShowDocumentRequest": ShowDocumentRequest, + "ShowDocumentResponse": ShowDocumentResponse, "ShowDocumentResult": ShowDocumentResult, + "ShowMessageNotification": ShowMessageNotification, "ShowMessageParams": ShowMessageParams, + "ShowMessageRequest": ShowMessageRequest, "ShowMessageRequestClientCapabilities": ShowMessageRequestClientCapabilities, - "ShowMessageRequestClientCapabilitiesMessageActionItemType": ShowMessageRequestClientCapabilitiesMessageActionItemType, "ShowMessageRequestParams": ShowMessageRequestParams, + "ShowMessageResponse": ShowMessageResponse, + "ShowMessageResult": ShowMessageResult, "ShutdownRequest": ShutdownRequest, "ShutdownResponse": ShutdownResponse, "SignatureHelp": SignatureHelp, "SignatureHelpClientCapabilities": SignatureHelpClientCapabilities, - "SignatureHelpClientCapabilitiesSignatureInformationType": SignatureHelpClientCapabilitiesSignatureInformationType, - "SignatureHelpClientCapabilitiesSignatureInformationTypeParameterInformationType": SignatureHelpClientCapabilitiesSignatureInformationTypeParameterInformationType, "SignatureHelpContext": SignatureHelpContext, "SignatureHelpOptions": SignatureHelpOptions, "SignatureHelpParams": SignatureHelpParams, "SignatureHelpRegistrationOptions": SignatureHelpRegistrationOptions, + "SignatureHelpRequest": SignatureHelpRequest, + "SignatureHelpResponse": SignatureHelpResponse, + "SignatureHelpResult": SignatureHelpResult, "SignatureHelpTriggerKind": SignatureHelpTriggerKind, "SignatureInformation": SignatureInformation, + "SnippetTextEdit": SnippetTextEdit, + "StaleRequestSupportOptions": StaleRequestSupportOptions, "StaticRegistrationOptions": StaticRegistrationOptions, "StringValue": StringValue, "SymbolInformation": SymbolInformation, @@ -12592,189 +13778,115 @@ ALL_TYPES_MAP: Dict[str, Union[type, object]] = { "TelemetryEventNotification": TelemetryEventNotification, "TextDocumentChangeRegistrationOptions": TextDocumentChangeRegistrationOptions, "TextDocumentClientCapabilities": TextDocumentClientCapabilities, - "TextDocumentCodeActionRequest": TextDocumentCodeActionRequest, - "TextDocumentCodeActionResponse": TextDocumentCodeActionResponse, - "TextDocumentCodeLensRequest": TextDocumentCodeLensRequest, - "TextDocumentCodeLensResponse": TextDocumentCodeLensResponse, - "TextDocumentColorPresentationOptions": TextDocumentColorPresentationOptions, - "TextDocumentColorPresentationRequest": TextDocumentColorPresentationRequest, - "TextDocumentColorPresentationResponse": TextDocumentColorPresentationResponse, - "TextDocumentCompletionRequest": TextDocumentCompletionRequest, - "TextDocumentCompletionResponse": TextDocumentCompletionResponse, "TextDocumentContentChangeEvent": TextDocumentContentChangeEvent, - "TextDocumentContentChangeEvent_Type1": TextDocumentContentChangeEvent_Type1, - "TextDocumentContentChangeEvent_Type2": TextDocumentContentChangeEvent_Type2, - "TextDocumentDeclarationRequest": TextDocumentDeclarationRequest, - "TextDocumentDeclarationResponse": TextDocumentDeclarationResponse, - "TextDocumentDefinitionRequest": TextDocumentDefinitionRequest, - "TextDocumentDefinitionResponse": TextDocumentDefinitionResponse, - "TextDocumentDiagnosticRequest": TextDocumentDiagnosticRequest, - "TextDocumentDiagnosticResponse": TextDocumentDiagnosticResponse, - "TextDocumentDidChangeNotification": TextDocumentDidChangeNotification, - "TextDocumentDidCloseNotification": TextDocumentDidCloseNotification, - "TextDocumentDidOpenNotification": TextDocumentDidOpenNotification, - "TextDocumentDidSaveNotification": TextDocumentDidSaveNotification, - "TextDocumentDocumentColorRequest": TextDocumentDocumentColorRequest, - "TextDocumentDocumentColorResponse": TextDocumentDocumentColorResponse, - "TextDocumentDocumentHighlightRequest": TextDocumentDocumentHighlightRequest, - "TextDocumentDocumentHighlightResponse": TextDocumentDocumentHighlightResponse, - "TextDocumentDocumentLinkRequest": TextDocumentDocumentLinkRequest, - "TextDocumentDocumentLinkResponse": TextDocumentDocumentLinkResponse, - "TextDocumentDocumentSymbolRequest": TextDocumentDocumentSymbolRequest, - "TextDocumentDocumentSymbolResponse": TextDocumentDocumentSymbolResponse, + "TextDocumentContentChangePartial": TextDocumentContentChangePartial, + "TextDocumentContentChangeWholeDocument": TextDocumentContentChangeWholeDocument, + "TextDocumentContentClientCapabilities": TextDocumentContentClientCapabilities, + "TextDocumentContentOptions": TextDocumentContentOptions, + "TextDocumentContentParams": TextDocumentContentParams, + "TextDocumentContentRefreshParams": TextDocumentContentRefreshParams, + "TextDocumentContentRefreshRequest": TextDocumentContentRefreshRequest, + "TextDocumentContentRefreshResponse": TextDocumentContentRefreshResponse, + "TextDocumentContentRegistrationOptions": TextDocumentContentRegistrationOptions, + "TextDocumentContentRequest": TextDocumentContentRequest, + "TextDocumentContentResponse": TextDocumentContentResponse, + "TextDocumentContentResult": TextDocumentContentResult, "TextDocumentEdit": TextDocumentEdit, "TextDocumentFilter": TextDocumentFilter, - "TextDocumentFilter_Type1": TextDocumentFilter_Type1, - "TextDocumentFilter_Type2": TextDocumentFilter_Type2, - "TextDocumentFilter_Type3": TextDocumentFilter_Type3, - "TextDocumentFoldingRangeRequest": TextDocumentFoldingRangeRequest, - "TextDocumentFoldingRangeResponse": TextDocumentFoldingRangeResponse, - "TextDocumentFormattingRequest": TextDocumentFormattingRequest, - "TextDocumentFormattingResponse": TextDocumentFormattingResponse, - "TextDocumentHoverRequest": TextDocumentHoverRequest, - "TextDocumentHoverResponse": TextDocumentHoverResponse, + "TextDocumentFilterClientCapabilities": TextDocumentFilterClientCapabilities, + "TextDocumentFilterLanguage": TextDocumentFilterLanguage, + "TextDocumentFilterPattern": TextDocumentFilterPattern, + "TextDocumentFilterScheme": TextDocumentFilterScheme, "TextDocumentIdentifier": TextDocumentIdentifier, - "TextDocumentImplementationRequest": TextDocumentImplementationRequest, - "TextDocumentImplementationResponse": TextDocumentImplementationResponse, - "TextDocumentInlayHintRequest": TextDocumentInlayHintRequest, - "TextDocumentInlayHintResponse": TextDocumentInlayHintResponse, - "TextDocumentInlineCompletionRequest": TextDocumentInlineCompletionRequest, - "TextDocumentInlineCompletionResponse": TextDocumentInlineCompletionResponse, - "TextDocumentInlineValueRequest": TextDocumentInlineValueRequest, - "TextDocumentInlineValueResponse": TextDocumentInlineValueResponse, "TextDocumentItem": TextDocumentItem, - "TextDocumentLinkedEditingRangeRequest": TextDocumentLinkedEditingRangeRequest, - "TextDocumentLinkedEditingRangeResponse": TextDocumentLinkedEditingRangeResponse, - "TextDocumentMonikerRequest": TextDocumentMonikerRequest, - "TextDocumentMonikerResponse": TextDocumentMonikerResponse, - "TextDocumentOnTypeFormattingRequest": TextDocumentOnTypeFormattingRequest, - "TextDocumentOnTypeFormattingResponse": TextDocumentOnTypeFormattingResponse, "TextDocumentPositionParams": TextDocumentPositionParams, - "TextDocumentPrepareCallHierarchyRequest": TextDocumentPrepareCallHierarchyRequest, - "TextDocumentPrepareCallHierarchyResponse": TextDocumentPrepareCallHierarchyResponse, - "TextDocumentPrepareRenameRequest": TextDocumentPrepareRenameRequest, - "TextDocumentPrepareRenameResponse": TextDocumentPrepareRenameResponse, - "TextDocumentPrepareTypeHierarchyRequest": TextDocumentPrepareTypeHierarchyRequest, - "TextDocumentPrepareTypeHierarchyResponse": TextDocumentPrepareTypeHierarchyResponse, - "TextDocumentPublishDiagnosticsNotification": TextDocumentPublishDiagnosticsNotification, - "TextDocumentRangeFormattingRequest": TextDocumentRangeFormattingRequest, - "TextDocumentRangeFormattingResponse": TextDocumentRangeFormattingResponse, - "TextDocumentRangesFormattingRequest": TextDocumentRangesFormattingRequest, - "TextDocumentRangesFormattingResponse": TextDocumentRangesFormattingResponse, - "TextDocumentReferencesRequest": TextDocumentReferencesRequest, - "TextDocumentReferencesResponse": TextDocumentReferencesResponse, "TextDocumentRegistrationOptions": TextDocumentRegistrationOptions, - "TextDocumentRenameRequest": TextDocumentRenameRequest, - "TextDocumentRenameResponse": TextDocumentRenameResponse, "TextDocumentSaveReason": TextDocumentSaveReason, "TextDocumentSaveRegistrationOptions": TextDocumentSaveRegistrationOptions, - "TextDocumentSelectionRangeRequest": TextDocumentSelectionRangeRequest, - "TextDocumentSelectionRangeResponse": TextDocumentSelectionRangeResponse, - "TextDocumentSemanticTokensFullDeltaRequest": TextDocumentSemanticTokensFullDeltaRequest, - "TextDocumentSemanticTokensFullDeltaResponse": TextDocumentSemanticTokensFullDeltaResponse, - "TextDocumentSemanticTokensFullRequest": TextDocumentSemanticTokensFullRequest, - "TextDocumentSemanticTokensFullResponse": TextDocumentSemanticTokensFullResponse, - "TextDocumentSemanticTokensRangeRequest": TextDocumentSemanticTokensRangeRequest, - "TextDocumentSemanticTokensRangeResponse": TextDocumentSemanticTokensRangeResponse, - "TextDocumentSignatureHelpRequest": TextDocumentSignatureHelpRequest, - "TextDocumentSignatureHelpResponse": TextDocumentSignatureHelpResponse, "TextDocumentSyncClientCapabilities": TextDocumentSyncClientCapabilities, "TextDocumentSyncKind": TextDocumentSyncKind, "TextDocumentSyncOptions": TextDocumentSyncOptions, - "TextDocumentTypeDefinitionRequest": TextDocumentTypeDefinitionRequest, - "TextDocumentTypeDefinitionResponse": TextDocumentTypeDefinitionResponse, - "TextDocumentWillSaveNotification": TextDocumentWillSaveNotification, - "TextDocumentWillSaveWaitUntilRequest": TextDocumentWillSaveWaitUntilRequest, - "TextDocumentWillSaveWaitUntilResponse": TextDocumentWillSaveWaitUntilResponse, "TextEdit": TextEdit, "TokenFormat": TokenFormat, - "TraceValues": TraceValues, + "TraceValue": TraceValue, "TypeDefinitionClientCapabilities": TypeDefinitionClientCapabilities, "TypeDefinitionOptions": TypeDefinitionOptions, "TypeDefinitionParams": TypeDefinitionParams, "TypeDefinitionRegistrationOptions": TypeDefinitionRegistrationOptions, + "TypeDefinitionRequest": TypeDefinitionRequest, + "TypeDefinitionResponse": TypeDefinitionResponse, + "TypeDefinitionResult": TypeDefinitionResult, "TypeHierarchyClientCapabilities": TypeHierarchyClientCapabilities, "TypeHierarchyItem": TypeHierarchyItem, "TypeHierarchyOptions": TypeHierarchyOptions, "TypeHierarchyPrepareParams": TypeHierarchyPrepareParams, + "TypeHierarchyPrepareRequest": TypeHierarchyPrepareRequest, + "TypeHierarchyPrepareResponse": TypeHierarchyPrepareResponse, + "TypeHierarchyPrepareResult": TypeHierarchyPrepareResult, "TypeHierarchyRegistrationOptions": TypeHierarchyRegistrationOptions, "TypeHierarchySubtypesParams": TypeHierarchySubtypesParams, "TypeHierarchySubtypesRequest": TypeHierarchySubtypesRequest, "TypeHierarchySubtypesResponse": TypeHierarchySubtypesResponse, + "TypeHierarchySubtypesResult": TypeHierarchySubtypesResult, "TypeHierarchySupertypesParams": TypeHierarchySupertypesParams, "TypeHierarchySupertypesRequest": TypeHierarchySupertypesRequest, "TypeHierarchySupertypesResponse": TypeHierarchySupertypesResponse, + "TypeHierarchySupertypesResult": TypeHierarchySupertypesResult, "UnchangedDocumentDiagnosticReport": UnchangedDocumentDiagnosticReport, "UniquenessLevel": UniquenessLevel, "Unregistration": Unregistration, "UnregistrationParams": UnregistrationParams, + "UnregistrationRequest": UnregistrationRequest, + "UnregistrationResponse": UnregistrationResponse, "VersionedNotebookDocumentIdentifier": VersionedNotebookDocumentIdentifier, "VersionedTextDocumentIdentifier": VersionedTextDocumentIdentifier, "WatchKind": WatchKind, + "WillCreateFilesRequest": WillCreateFilesRequest, + "WillCreateFilesResponse": WillCreateFilesResponse, + "WillCreateFilesResult": WillCreateFilesResult, + "WillDeleteFilesRequest": WillDeleteFilesRequest, + "WillDeleteFilesResponse": WillDeleteFilesResponse, + "WillDeleteFilesResult": WillDeleteFilesResult, + "WillRenameFilesRequest": WillRenameFilesRequest, + "WillRenameFilesResponse": WillRenameFilesResponse, + "WillRenameFilesResult": WillRenameFilesResult, + "WillSaveTextDocumentNotification": WillSaveTextDocumentNotification, "WillSaveTextDocumentParams": WillSaveTextDocumentParams, + "WillSaveTextDocumentWaitUntilRequest": WillSaveTextDocumentWaitUntilRequest, + "WillSaveTextDocumentWaitUntilResponse": WillSaveTextDocumentWaitUntilResponse, + "WillSaveTextDocumentWaitUntilResult": WillSaveTextDocumentWaitUntilResult, "WindowClientCapabilities": WindowClientCapabilities, - "WindowLogMessageNotification": WindowLogMessageNotification, - "WindowShowDocumentRequest": WindowShowDocumentRequest, - "WindowShowDocumentResponse": WindowShowDocumentResponse, - "WindowShowMessageNotification": WindowShowMessageNotification, - "WindowShowMessageRequestRequest": WindowShowMessageRequestRequest, - "WindowShowMessageRequestResponse": WindowShowMessageRequestResponse, - "WindowWorkDoneProgressCancelNotification": WindowWorkDoneProgressCancelNotification, - "WindowWorkDoneProgressCreateRequest": WindowWorkDoneProgressCreateRequest, - "WindowWorkDoneProgressCreateResponse": WindowWorkDoneProgressCreateResponse, "WorkDoneProgressBegin": WorkDoneProgressBegin, + "WorkDoneProgressCancelNotification": WorkDoneProgressCancelNotification, "WorkDoneProgressCancelParams": WorkDoneProgressCancelParams, "WorkDoneProgressCreateParams": WorkDoneProgressCreateParams, + "WorkDoneProgressCreateRequest": WorkDoneProgressCreateRequest, + "WorkDoneProgressCreateResponse": WorkDoneProgressCreateResponse, "WorkDoneProgressEnd": WorkDoneProgressEnd, "WorkDoneProgressOptions": WorkDoneProgressOptions, "WorkDoneProgressParams": WorkDoneProgressParams, "WorkDoneProgressReport": WorkDoneProgressReport, - "WorkspaceApplyEditRequest": WorkspaceApplyEditRequest, - "WorkspaceApplyEditResponse": WorkspaceApplyEditResponse, "WorkspaceClientCapabilities": WorkspaceClientCapabilities, - "WorkspaceCodeLensRefreshRequest": WorkspaceCodeLensRefreshRequest, - "WorkspaceCodeLensRefreshResponse": WorkspaceCodeLensRefreshResponse, - "WorkspaceConfigurationParams": WorkspaceConfigurationParams, - "WorkspaceConfigurationRequest": WorkspaceConfigurationRequest, - "WorkspaceConfigurationResponse": WorkspaceConfigurationResponse, "WorkspaceDiagnosticParams": WorkspaceDiagnosticParams, - "WorkspaceDiagnosticRefreshRequest": WorkspaceDiagnosticRefreshRequest, - "WorkspaceDiagnosticRefreshResponse": WorkspaceDiagnosticRefreshResponse, "WorkspaceDiagnosticReport": WorkspaceDiagnosticReport, "WorkspaceDiagnosticReportPartialResult": WorkspaceDiagnosticReportPartialResult, "WorkspaceDiagnosticRequest": WorkspaceDiagnosticRequest, "WorkspaceDiagnosticResponse": WorkspaceDiagnosticResponse, - "WorkspaceDidChangeConfigurationNotification": WorkspaceDidChangeConfigurationNotification, - "WorkspaceDidChangeWatchedFilesNotification": WorkspaceDidChangeWatchedFilesNotification, - "WorkspaceDidChangeWorkspaceFoldersNotification": WorkspaceDidChangeWorkspaceFoldersNotification, - "WorkspaceDidCreateFilesNotification": WorkspaceDidCreateFilesNotification, - "WorkspaceDidDeleteFilesNotification": WorkspaceDidDeleteFilesNotification, - "WorkspaceDidRenameFilesNotification": WorkspaceDidRenameFilesNotification, "WorkspaceDocumentDiagnosticReport": WorkspaceDocumentDiagnosticReport, "WorkspaceEdit": WorkspaceEdit, "WorkspaceEditClientCapabilities": WorkspaceEditClientCapabilities, - "WorkspaceEditClientCapabilitiesChangeAnnotationSupportType": WorkspaceEditClientCapabilitiesChangeAnnotationSupportType, - "WorkspaceExecuteCommandRequest": WorkspaceExecuteCommandRequest, - "WorkspaceExecuteCommandResponse": WorkspaceExecuteCommandResponse, + "WorkspaceEditMetadata": WorkspaceEditMetadata, "WorkspaceFolder": WorkspaceFolder, "WorkspaceFoldersChangeEvent": WorkspaceFoldersChangeEvent, "WorkspaceFoldersInitializeParams": WorkspaceFoldersInitializeParams, + "WorkspaceFoldersRequest": WorkspaceFoldersRequest, + "WorkspaceFoldersResponse": WorkspaceFoldersResponse, + "WorkspaceFoldersResult": WorkspaceFoldersResult, "WorkspaceFoldersServerCapabilities": WorkspaceFoldersServerCapabilities, - "WorkspaceFoldingRangeRefreshRequest": WorkspaceFoldingRangeRefreshRequest, - "WorkspaceFoldingRangeRefreshResponse": WorkspaceFoldingRangeRefreshResponse, "WorkspaceFullDocumentDiagnosticReport": WorkspaceFullDocumentDiagnosticReport, - "WorkspaceInlayHintRefreshRequest": WorkspaceInlayHintRefreshRequest, - "WorkspaceInlayHintRefreshResponse": WorkspaceInlayHintRefreshResponse, - "WorkspaceInlineValueRefreshRequest": WorkspaceInlineValueRefreshRequest, - "WorkspaceInlineValueRefreshResponse": WorkspaceInlineValueRefreshResponse, - "WorkspaceSemanticTokensRefreshRequest": WorkspaceSemanticTokensRefreshRequest, - "WorkspaceSemanticTokensRefreshResponse": WorkspaceSemanticTokensRefreshResponse, + "WorkspaceOptions": WorkspaceOptions, "WorkspaceSymbol": WorkspaceSymbol, "WorkspaceSymbolClientCapabilities": WorkspaceSymbolClientCapabilities, - "WorkspaceSymbolClientCapabilitiesResolveSupportType": WorkspaceSymbolClientCapabilitiesResolveSupportType, - "WorkspaceSymbolClientCapabilitiesSymbolKindType": WorkspaceSymbolClientCapabilitiesSymbolKindType, - "WorkspaceSymbolClientCapabilitiesTagSupportType": WorkspaceSymbolClientCapabilitiesTagSupportType, - "WorkspaceSymbolLocationType1": WorkspaceSymbolLocationType1, "WorkspaceSymbolOptions": WorkspaceSymbolOptions, "WorkspaceSymbolParams": WorkspaceSymbolParams, "WorkspaceSymbolRegistrationOptions": WorkspaceSymbolRegistrationOptions, @@ -12782,15 +13894,8 @@ ALL_TYPES_MAP: Dict[str, Union[type, object]] = { "WorkspaceSymbolResolveRequest": WorkspaceSymbolResolveRequest, "WorkspaceSymbolResolveResponse": WorkspaceSymbolResolveResponse, "WorkspaceSymbolResponse": WorkspaceSymbolResponse, + "WorkspaceSymbolResult": WorkspaceSymbolResult, "WorkspaceUnchangedDocumentDiagnosticReport": WorkspaceUnchangedDocumentDiagnosticReport, - "WorkspaceWillCreateFilesRequest": WorkspaceWillCreateFilesRequest, - "WorkspaceWillCreateFilesResponse": WorkspaceWillCreateFilesResponse, - "WorkspaceWillDeleteFilesRequest": WorkspaceWillDeleteFilesRequest, - "WorkspaceWillDeleteFilesResponse": WorkspaceWillDeleteFilesResponse, - "WorkspaceWillRenameFilesRequest": WorkspaceWillRenameFilesRequest, - "WorkspaceWillRenameFilesResponse": WorkspaceWillRenameFilesResponse, - "WorkspaceWorkspaceFoldersRequest": WorkspaceWorkspaceFoldersRequest, - "WorkspaceWorkspaceFoldersResponse": WorkspaceWorkspaceFoldersResponse, "_InitializeParams": _InitializeParams, } @@ -12859,6 +13964,8 @@ _MESSAGE_DIRECTION: Dict[str, str] = { WORKSPACE_SEMANTIC_TOKENS_REFRESH: "serverToClient", WORKSPACE_SYMBOL: "clientToServer", WORKSPACE_SYMBOL_RESOLVE: "clientToServer", + WORKSPACE_TEXT_DOCUMENT_CONTENT: "clientToServer", + WORKSPACE_TEXT_DOCUMENT_CONTENT_REFRESH: "serverToClient", WORKSPACE_WILL_CREATE_FILES: "clientToServer", WORKSPACE_WILL_DELETE_FILES: "clientToServer", WORKSPACE_WILL_RENAME_FILES: "clientToServer", diff --git a/server/libs/packaging-26.2.dist-info/RECORD b/server/libs/packaging-26.2.dist-info/RECORD deleted file mode 100644 index e84f245..0000000 --- a/server/libs/packaging-26.2.dist-info/RECORD +++ /dev/null @@ -1,29 +0,0 @@ -packaging-26.2.dist-info/INSTALLER,sha256=5hhM4Q4mYTT9z6QB6PGpUAW81PGNFrYrdXMj4oM_6ak,2 -packaging-26.2.dist-info/METADATA,sha256=T5y815M0FaR5P3dnyYoralEsgj_IHIczeBVwXyMOyr8,3543 -packaging-26.2.dist-info/RECORD,, -packaging-26.2.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -packaging-26.2.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82 -packaging-26.2.dist-info/licenses/LICENSE,sha256=ytHvW9NA1z4HS6YU0m996spceUDD2MNIUuZcSQlobEg,197 -packaging-26.2.dist-info/licenses/LICENSE.APACHE,sha256=DVQuDIgE45qn836wDaWnYhSdxoLXgpRRKH4RuTjpRZQ,10174 -packaging-26.2.dist-info/licenses/LICENSE.BSD,sha256=tw5-m3QvHMb5SLNMFqo5_-zpQZY2S8iP8NIYDwAo-sU,1344 -packaging/__init__.py,sha256=QhMEdPu2XogrJzV3S0KWS6t7l0I9k8EeDRJl4fnw87s,494 -packaging/_elffile.py,sha256=-sKkptYqzYw2-x3QByJa5mB4rfPWu1pxkZHRx1WAFCY,3211 -packaging/_manylinux.py,sha256=Hf6nB0cOrayEs96-p3oIXAgGnFquv20DO5l-o2_Xnv0,9559 -packaging/_musllinux.py,sha256=Z6swjH3MA7XS3qXnmMN7QPhqP3fnoYI0eQ18e9-HgAE,2707 -packaging/_parser.py,sha256=Kf2nsDw4c54X82pY8ba4F02Bve6OygGMAjL-Begqcew,11698 -packaging/_structures.py,sha256=60jRbF78p8z5MKnNd6cAprgOadCJHV0DlmUmRBqFZcs,1109 -packaging/_tokenizer.py,sha256=tFU2Wr-ZZJdAbkXLEJo7qUQDJaIkfft9DqaifiEND7A,5391 -packaging/dependency_groups.py,sha256=XZIAVFK9uHG4RCGprmJn3VInUWMesxha_kytJuMO9eY,10218 -packaging/direct_url.py,sha256=eKmbDiPP1sLV4Mj_kCSZqqknrIyVO9Sr7JpF8KCjp4U,10917 -packaging/errors.py,sha256=6hfEYXAf8v_IF65-lFadJOMIieBP2xIKtyEXjG1nGIs,2680 -packaging/licenses/__init__.py,sha256=_Jx0XRiD_58palsWnyLrLuh59ZpGCPIPXLKdZo9OJvQ,7293 -packaging/licenses/_spdx.py,sha256=WW7DXiyg68up_YND_wpRYlr1SHhiV4FfJLQffghhMxQ,51122 -packaging/markers.py,sha256=8fDIUhAF6YMnCNB5FSiwh9pEIusiFzAF73J-0OB8bTk,17055 -packaging/metadata.py,sha256=crAh0E3GVGVqPlu6EdRFsaG-Y6UYznTUqjuGKRGPv6c,38770 -packaging/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -packaging/pylock.py,sha256=G_1gncTmDbRLY1jo4VDI9Uw-b5IErh_Q9V_BbVJTmD8,33890 -packaging/requirements.py,sha256=dd1c9aa1gp5NI6btF6UFRQjPn1nxQXnE_T34yDDTEpc,4383 -packaging/specifiers.py,sha256=Mfp8avQg0lVot17to9lVKBtZD1FsWBTItoGwFUZ3wtg,71514 -packaging/tags.py,sha256=NQ1weo69_Sjte3xBZ1I_G63CIgCmaN0C24mz-z3hGYo,34224 -packaging/utils.py,sha256=M7-JMKic2sP1YtV_8aW7eVGB-x3ADuKCiSrsVeCd2Uo,9848 -packaging/version.py,sha256=Y1aTtxe3sn2xOMa5BdI85-AcHuybbanOVkEvvSRRC8I,38369 diff --git a/server/libs/packaging-26.2.dist-info/INSTALLER b/server/libs/packaging-26.3.dist-info/INSTALLER similarity index 100% rename from server/libs/packaging-26.2.dist-info/INSTALLER rename to server/libs/packaging-26.3.dist-info/INSTALLER diff --git a/server/libs/packaging-26.2.dist-info/METADATA b/server/libs/packaging-26.3.dist-info/METADATA similarity index 97% rename from server/libs/packaging-26.2.dist-info/METADATA rename to server/libs/packaging-26.3.dist-info/METADATA index d7ca456..9a85a75 100644 --- a/server/libs/packaging-26.2.dist-info/METADATA +++ b/server/libs/packaging-26.3.dist-info/METADATA @@ -1,9 +1,9 @@ Metadata-Version: 2.4 Name: packaging -Version: 26.2 +Version: 26.3 Summary: Core utilities for Python packages Author-email: Donald Stufft -Requires-Python: >=3.8 +Requires-Python: >=3.9 Description-Content-Type: text/x-rst License-Expression: Apache-2.0 OR BSD-2-Clause Classifier: Development Status :: 5 - Production/Stable @@ -11,13 +11,13 @@ Classifier: Intended Audience :: Developers Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3 :: Only -Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 Classifier: Programming Language :: Python :: 3.10 Classifier: Programming Language :: Python :: 3.11 Classifier: Programming Language :: Python :: 3.12 Classifier: Programming Language :: Python :: 3.13 Classifier: Programming Language :: Python :: 3.14 +Classifier: Programming Language :: Python :: 3.15 Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: Implementation :: PyPy Classifier: Programming Language :: Python :: Free Threading :: 4 - Resilient diff --git a/server/libs/packaging-26.3.dist-info/RECORD b/server/libs/packaging-26.3.dist-info/RECORD new file mode 100644 index 0000000..e97e3ed --- /dev/null +++ b/server/libs/packaging-26.3.dist-info/RECORD @@ -0,0 +1,31 @@ +packaging-26.3.dist-info/INSTALLER,sha256=5hhM4Q4mYTT9z6QB6PGpUAW81PGNFrYrdXMj4oM_6ak,2 +packaging-26.3.dist-info/METADATA,sha256=cP24n8TUqaBDv3NyuJcrzIg_3f80q1Xpz4DXOHU4R2M,3544 +packaging-26.3.dist-info/RECORD,, +packaging-26.3.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +packaging-26.3.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82 +packaging-26.3.dist-info/licenses/LICENSE,sha256=ytHvW9NA1z4HS6YU0m996spceUDD2MNIUuZcSQlobEg,197 +packaging-26.3.dist-info/licenses/LICENSE.APACHE,sha256=DVQuDIgE45qn836wDaWnYhSdxoLXgpRRKH4RuTjpRZQ,10174 +packaging-26.3.dist-info/licenses/LICENSE.BSD,sha256=tw5-m3QvHMb5SLNMFqo5_-zpQZY2S8iP8NIYDwAo-sU,1344 +packaging/__init__.py,sha256=bnWM3QAossrXTHObmtycnwbwVJMjBigLh4v-WdOSGbU,494 +packaging/_elffile.py,sha256=HwJfVMVz8ahXQMT72QjMHR-wwXfBQ3fr9fCdbNU2h4A,3236 +packaging/_manylinux.py,sha256=W26EMkxCU4q0zbFI4kMP26NvBEJ7Dv2lW-oIOjX6YTY,10000 +packaging/_musllinux.py,sha256=Ayj7gnsRcMd99MEH1Jvo3403JiEDSQph6Kytii-crf8,2774 +packaging/_parser.py,sha256=iKNIEVIJMnSX5FO2NeXbCZ_VkvkzXXEMcxOynNswxQw,12639 +packaging/_ranges.py,sha256=t7WV8uaSrrNpfFRbhcJMu8tFUvKtxtkFmqgtCHfoFrc,30850 +packaging/_structures.py,sha256=60jRbF78p8z5MKnNd6cAprgOadCJHV0DlmUmRBqFZcs,1109 +packaging/_tokenizer.py,sha256=zCXlfA1WTInhUHNHHW4cJkKZypRvsXwOHkr1TvdxPuY,5573 +packaging/dependency_groups.py,sha256=UwnMVkyjAi37WUgW6dWTuwnN80IIwfuMXsmvtsZwJ4w,11224 +packaging/direct_url.py,sha256=hDuqldBMu0kojenZ_XfulG6GLLYDEj5-RqaeFx-n0Gs,11645 +packaging/errors.py,sha256=6hfEYXAf8v_IF65-lFadJOMIieBP2xIKtyEXjG1nGIs,2680 +packaging/licenses/__init__.py,sha256=WQ0S7uc92-xTtOnuW_xk2cs6rLSUDo68uiYHV85WdAs,7859 +packaging/licenses/_spdx.py,sha256=WW7DXiyg68up_YND_wpRYlr1SHhiV4FfJLQffghhMxQ,51122 +packaging/markers.py,sha256=bL6GDTXZjStZnn8Oxz_qsSTgFXEbML6QReZ4ySlA2cw,20554 +packaging/metadata.py,sha256=k0FJ9CClRJ5vN2qmHW8moII-uCzHxqHIzeWqe-Q9D2M,42059 +packaging/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +packaging/pylock.py,sha256=G84Kn-Y-Qrh-jO0F2icrrxamiqcEs3GEBeJzWmESRnw,35232 +packaging/ranges.py,sha256=tHgc6RPl3_ngeQbyBYXFTDAo4ff_VjQYKOedUi3b-rY,83054 +packaging/requirements.py,sha256=RZR26yEH_jDmsTEAUaW9tEx9O3944Oh7raJoKCy6YvU,7040 +packaging/specifiers.py,sha256=ZhrTHd9F_7hh0mJnNPTj1mlmApuP23lYa7EFgl2NnVk,52798 +packaging/tags.py,sha256=DnF6CCp5Yg15zwMhtCDfFVk8SRb82gPCfLnYLgfvXW4,38302 +packaging/utils.py,sha256=oTdCzZmU7spa37AknRJkCMR4Am6x9Iy5evvy_p8o7MY,12215 +packaging/version.py,sha256=VYsvtQ_RmMZgpMCC-WuJGcVlkRtrS24H80trYMB0vpc,39040 diff --git a/server/libs/packaging-26.2.dist-info/REQUESTED b/server/libs/packaging-26.3.dist-info/REQUESTED similarity index 100% rename from server/libs/packaging-26.2.dist-info/REQUESTED rename to server/libs/packaging-26.3.dist-info/REQUESTED diff --git a/server/libs/typing_extensions-4.15.0.dist-info/WHEEL b/server/libs/packaging-26.3.dist-info/WHEEL similarity index 100% rename from server/libs/typing_extensions-4.15.0.dist-info/WHEEL rename to server/libs/packaging-26.3.dist-info/WHEEL diff --git a/server/libs/packaging-26.2.dist-info/licenses/LICENSE b/server/libs/packaging-26.3.dist-info/licenses/LICENSE similarity index 100% rename from server/libs/packaging-26.2.dist-info/licenses/LICENSE rename to server/libs/packaging-26.3.dist-info/licenses/LICENSE diff --git a/server/libs/packaging-26.2.dist-info/licenses/LICENSE.APACHE b/server/libs/packaging-26.3.dist-info/licenses/LICENSE.APACHE similarity index 100% rename from server/libs/packaging-26.2.dist-info/licenses/LICENSE.APACHE rename to server/libs/packaging-26.3.dist-info/licenses/LICENSE.APACHE diff --git a/server/libs/packaging-26.2.dist-info/licenses/LICENSE.BSD b/server/libs/packaging-26.3.dist-info/licenses/LICENSE.BSD similarity index 100% rename from server/libs/packaging-26.2.dist-info/licenses/LICENSE.BSD rename to server/libs/packaging-26.3.dist-info/licenses/LICENSE.BSD diff --git a/server/libs/packaging/__init__.py b/server/libs/packaging/__init__.py index a6bdf59..5a96915 100644 --- a/server/libs/packaging/__init__.py +++ b/server/libs/packaging/__init__.py @@ -6,7 +6,7 @@ __title__ = "packaging" __summary__ = "Core utilities for Python packages" __uri__ = "https://github.com/pypa/packaging" -__version__ = "26.2" +__version__ = "26.3" __author__ = "Donald Stufft and individual contributors" __email__ = "donald@stufft.io" diff --git a/server/libs/packaging/_elffile.py b/server/libs/packaging/_elffile.py index 497b064..1ce081d 100644 --- a/server/libs/packaging/_elffile.py +++ b/server/libs/packaging/_elffile.py @@ -34,7 +34,7 @@ class EMachine(enum.IntEnum): S390 = 22 Arm = 40 X8664 = 62 - AArc64 = 183 + AArch64 = 183 class ELFFile: @@ -57,8 +57,8 @@ class ELFFile: self.encoding = ident[5] # Data structure encoding (endianness). try: - # e_fmt: Format for program header. - # p_fmt: Format for section header. + # e_fmt: Format for the ELF header. + # p_fmt: Format for a program header. # p_idx: Indexes to find p_type, p_offset, and p_filesz. e_fmt, self._p_fmt, self._p_idx = { (1, 1): (" Generator[ELFFile | None, None, None]: try: @@ -136,11 +138,11 @@ def _glibc_version_string_ctypes() -> str | None: # glibc. return None - # Call gnu_get_libc_version, which returns a string like "2.5" + # Call gnu_get_libc_version, which returns a string like "2.5". gnu_get_libc_version.restype = ctypes.c_char_p - version_str: str = gnu_get_libc_version() - # py2 / py3 compatibility: - if not isinstance(version_str, str): + # A c_char_p restype comes back as bytes, so decode to text. + version_str: str | bytes = gnu_get_libc_version() + if isinstance(version_str, bytes): version_str = version_str.decode("ascii") return version_str @@ -179,30 +181,44 @@ def _get_glibc_version() -> _GLibCVersion: # From PEP 513, PEP 600 +@functools.lru_cache(maxsize=1) +def _get_manylinux_module() -> types.ModuleType | None: + """Return the ``_manylinux`` C extension module, or None if unavailable. + + The result is cached for the lifetime of the process, since the presence + of the module does not change while running. + """ + try: + return __import__("_manylinux") + except ImportError: + return None + + def _is_compatible(arch: str, version: _GLibCVersion) -> bool: sys_glibc = _get_glibc_version() if sys_glibc < version: return False # Check for presence of _manylinux module. - try: - import _manylinux # noqa: PLC0415 - except ImportError: + manylinux_mod = _get_manylinux_module() + if manylinux_mod is None: return True - if hasattr(_manylinux, "manylinux_compatible"): - result = _manylinux.manylinux_compatible(version[0], version[1], arch) + if hasattr(manylinux_mod, "manylinux_compatible"): + result = manylinux_mod.manylinux_compatible(version[0], version[1], arch) if result is not None: return bool(result) return True - if version == _GLibCVersion(2, 5) and hasattr(_manylinux, "manylinux1_compatible"): - return bool(_manylinux.manylinux1_compatible) + if version == _GLibCVersion(2, 5) and hasattr( + manylinux_mod, "manylinux1_compatible" + ): + return bool(manylinux_mod.manylinux1_compatible) if version == _GLibCVersion(2, 12) and hasattr( - _manylinux, "manylinux2010_compatible" + manylinux_mod, "manylinux2010_compatible" ): - return bool(_manylinux.manylinux2010_compatible) + return bool(manylinux_mod.manylinux2010_compatible) if version == _GLibCVersion(2, 17) and hasattr( - _manylinux, "manylinux2014_compatible" + manylinux_mod, "manylinux2014_compatible" ): - return bool(_manylinux.manylinux2014_compatible) + return bool(manylinux_mod.manylinux2014_compatible) return True diff --git a/server/libs/packaging/_musllinux.py b/server/libs/packaging/_musllinux.py index 4e8116a..74c4136 100644 --- a/server/libs/packaging/_musllinux.py +++ b/server/libs/packaging/_musllinux.py @@ -10,10 +10,13 @@ import functools import re import subprocess import sys -from typing import Iterator, NamedTuple, Sequence +from typing import TYPE_CHECKING, NamedTuple from ._elffile import ELFFile +if TYPE_CHECKING: + from collections.abc import Iterator, Sequence + class _MuslVersion(NamedTuple): major: int @@ -81,5 +84,5 @@ if __name__ == "__main__": # pragma: no cover print("plat:", plat) print("musl:", _get_musl_version(sys.executable)) print("tags:", end=" ") - for t in platform_tags(re.sub(r"[.-]", "_", plat.split("-", 1)[-1])): + for t in platform_tags([re.sub(r"[.-]", "_", plat.split("-", 1)[-1])]): print(t, end="\n ") diff --git a/server/libs/packaging/_parser.py b/server/libs/packaging/_parser.py index d320269..9331b4b 100644 --- a/server/libs/packaging/_parser.py +++ b/server/libs/packaging/_parser.py @@ -7,9 +7,10 @@ the implementation. from __future__ import annotations import ast -from typing import List, Literal, NamedTuple, Sequence, Tuple, Union +from collections.abc import Sequence +from typing import Literal, NamedTuple, Union -from ._tokenizer import DEFAULT_RULES, Tokenizer +from ._tokenizer import DEFAULT_RULES, ParserSyntaxError, Tokenizer class Node: @@ -67,7 +68,14 @@ class Value(Node): __slots__ = () def serialize(self) -> str: - return f'"{self}"' + value = str(self) + if '"' not in value: + return f'"{value}"' + if "'" not in value: + return f"'{value}'" + raise ValueError( + "Cannot serialize marker value containing both quote characters" + ) class Op(Node): @@ -79,9 +87,9 @@ class Op(Node): MarkerLogical = Literal["and", "or"] MarkerVar = Union[Variable, Value] -MarkerItem = Tuple[MarkerVar, Op, MarkerVar] +MarkerItem = tuple[MarkerVar, Op, MarkerVar] MarkerAtom = Union[MarkerItem, Sequence["MarkerAtom"]] -MarkerList = List[Union["MarkerList", MarkerAtom, MarkerLogical]] +MarkerList = list[Union["MarkerList", MarkerAtom, MarkerLogical]] class ParsedRequirement(NamedTuple): @@ -264,10 +272,19 @@ def _parse_version_many(tokenizer: Tokenizer) -> str: parsed_specifiers = "" while tokenizer.check("SPECIFIER"): span_start = tokenizer.position - parsed_specifiers += tokenizer.read().text + specifier = tokenizer.read().text + parsed_specifiers += specifier if tokenizer.check("VERSION_PREFIX_TRAIL", peek=True): + message = ".* suffix can only be used with `==` or `!=` operators" + if specifier.startswith("!=") or ( + specifier.startswith("==") and not specifier.startswith("===") + ): + message = ( + ".* suffix cannot be used with pre-release, post-release, " + "dev or local versions" + ) tokenizer.raise_syntax_error( - ".* suffix can only be used with `==` or `!=` operators", + message, span_start=span_start, span_end=tokenizer.position + 1, ) @@ -354,7 +371,15 @@ def _parse_marker_var(tokenizer: Tokenizer) -> MarkerVar: # noqa: RET503 if tokenizer.check("VARIABLE"): return process_env_var(tokenizer.read().text.replace(".", "_")) elif tokenizer.check("QUOTED_STRING"): - return process_python_str(tokenizer.read().text) + token = tokenizer.read() + try: + return process_python_str(token.text) + except (SyntaxError, ValueError) as exc: + raise ParserSyntaxError( + "Invalid quoted string", + source=tokenizer.source, + span=(token.position, token.position + len(token.text)), + ) from exc else: tokenizer.raise_syntax_error( message="Expected a marker variable or quoted string" diff --git a/server/libs/packaging/_ranges.py b/server/libs/packaging/_ranges.py new file mode 100644 index 0000000..5370ec8 --- /dev/null +++ b/server/libs/packaging/_ranges.py @@ -0,0 +1,836 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +"""Private version-range helpers used by :mod:`packaging.specifiers`.""" + +from __future__ import annotations + +import enum +import functools +from typing import ( + TYPE_CHECKING, + Any, + Final, +) + +from .version import InvalidVersion, Version + +if TYPE_CHECKING: + from collections.abc import Callable, Iterable, Iterator, Sequence + from typing import Union + + # Total-order key for comparing two boundaries (boundary-vs-boundary only). + # The post slot may be ``_BOUNDARY_INF`` for an AFTER_POSTS boundary. + _BoundaryOrderSuffix = tuple[int, int, int, Union[int, float], int, int] + _BoundaryOrderKey = tuple[int, tuple[int, ...], _BoundaryOrderSuffix, float] + +__all__ = [ + "FULL_RANGE", + "bounds_for_spec", + "coerce_version", + "filter_by_ranges", + "intersect_ranges", + "intersect_specifier_bounds", + "least_version_above", + "matches_bounds_only", + "range_is_empty", + "ranges_are_prerelease_only", + "resolve_prereleases", + "standard_ranges", + "wildcard_ranges", +] + +#: The smallest possible PEP 440 version. No valid version is less than this. +MIN_VERSION: Final[Version] = Version("0.dev0") + +#: The smallest non-pre-release version, i.e. the nearest non-pre-release at or +#: above the ``-inf`` floor. +MIN_RELEASE: Final[Version] = Version("0") + +#: Sorts above any real post number and any local label, so a boundary can be +#: ordered above the version family it covers when two boundaries are compared. +_BOUNDARY_INF: Final[float] = float("inf") + + +class BoundaryKind(enum.Enum): + """Where a boundary marker sits in the version ordering.""" + + AFTER_LOCALS = enum.auto() # after V+local, before V.post0 + AFTER_POSTS = enum.auto() # after V.postN, before next release + + +@functools.total_ordering +class BoundaryVersion: + """A point on the version line between two real PEP 440 versions. + + Relative to a base version V:: + + V < V+local < AFTER_LOCALS(V) < V.post0 < AFTER_POSTS(V) + + AFTER_LOCALS is the upper bound of ``<=V``, ``==V``, ``!=V`` (no + local), and the lower bound of the upper-side range of ``!=V``. + AFTER_POSTS is the lower bound of ``>V`` (V final or pre-release), + excluding V's post-releases per PEP 440. + """ + + __slots__ = ( + "_cached_dev", + "_cached_epoch", + "_cached_post", + "_cached_pre", + "_cached_trimmed_release", + "kind", + "version", + ) + + def __init__(self, version: Version, kind: BoundaryKind) -> None: + self.version = version + self.kind = kind + self._cached_trimmed_release = trim_release(version.release) + self._cached_epoch = version.epoch + self._cached_pre = version.pre + self._cached_post = version.post + self._cached_dev = version.dev + + def _is_family(self, other: Version) -> bool: + """Is ``other`` a version that this boundary sorts above?""" + if other.epoch != self._cached_epoch: + return False + # Inline release-trim comparison: other.release matches the + # trimmed release iff its leading slice is equal and any extra + # components are zero. Avoids trim_release's tuple allocation. + other_release = other.release + trimmed_release = self._cached_trimmed_release + trimmed_length = len(trimmed_release) + if len(other_release) < trimmed_length: + return False + if other_release[:trimmed_length] != trimmed_release: + return False + for i in range(trimmed_length, len(other_release)): + if other_release[i] != 0: + return False + if other.pre != self._cached_pre: + return False + if self.kind == BoundaryKind.AFTER_LOCALS: + # Local family: same public version, any local label. + return other.post == self._cached_post and other.dev == self._cached_dev + # Post family: V itself + any post-release of V. + return other.dev == self._cached_dev or other.post is not None + + def _order_key(self) -> _BoundaryOrderKey: + """Sort key placing this boundary just above the versions it covers. + + It extends ``V``'s comparison key ``(epoch, release, suffix)`` with + a trailing ``_BOUNDARY_INF`` local component, so the key sorts after + ``V`` and every ``V+local`` (whose keys carry a real, finite local + segment). ``suffix`` is the 6-int comparison suffix + ``(pre_rank, pre_n, post_rank, post_n, dev_rank, dev_n)``. + + For an AFTER_POSTS boundary the suffix is replaced with one whose + post number is ``_BOUNDARY_INF``, so the key also sorts after every + ``V.postN``. An AFTER_LOCALS boundary uses ``V``'s suffix unchanged. + """ + version_key = self.version._key + suffix: _BoundaryOrderSuffix = version_key[2] + + if self.kind == BoundaryKind.AFTER_POSTS: + suffix = (suffix[0], suffix[1], 1, _BOUNDARY_INF, 1, 0) + + return version_key[0], version_key[1], suffix, _BOUNDARY_INF + + def __eq__(self, other: object) -> bool: + # Key off the order key so equality matches the ``<`` / ``>`` order: + # ``AFTER_POSTS(1.0)`` and ``AFTER_POSTS(1.0.post1)`` are the same point. + if isinstance(other, BoundaryVersion): + return self._order_key() == other._order_key() + return NotImplemented + + def __lt__(self, other: BoundaryVersion | Version) -> bool: + if isinstance(other, BoundaryVersion): + return self._order_key() < other._order_key() + # boundary < other_version iff V < other AND other not in family. + # The cheap V >= other path short-circuits before the family check. + if not (self.version < other): + return False + return not self._is_family(other) + + def __gt__(self, other: BoundaryVersion | Version) -> bool: + # Defined directly to bypass functools.total_ordering's + # NotImplemented round-trip on reflected ``Version < boundary``. + if isinstance(other, BoundaryVersion): + return self._order_key() > other._order_key() + if self.version >= other: + return True + return self._is_family(other) + + def __hash__(self) -> int: + # Keyed to ``__eq__`` (the order key), so equal boundaries hash equal. + return hash(self._order_key()) + + def __repr__(self) -> str: + return f"{self.__class__.__name__}({self.version!r}, {self.kind.name})" + + +if TYPE_CHECKING: + _VersionOrBoundary = Union[Version, BoundaryVersion, None] + + +@functools.total_ordering +class LowerBound: + """Lower bound of a version range. + + A version *v* of ``None`` means unbounded below (-inf). + At equal versions, ``[v`` sorts before ``(v`` because an inclusive + bound starts earlier. + """ + + __slots__ = ("_above", "inclusive", "version") + + def __init__(self, version: _VersionOrBoundary, inclusive: bool) -> None: + self.version = version + self.inclusive = inclusive + # Pre-bind a predicate "is parsed at or above this lower + # bound?" for the hot filter / contains loops. One direct + # call per check, no operator-dispatch chain. + if version is None: + self._above: Callable[[Version], bool] | None = None + elif isinstance(version, BoundaryVersion): + # >V produces an AFTER_POSTS lower bound; the upper-side + # range of !=V produces an AFTER_LOCALS lower bound. + if version.kind == BoundaryKind.AFTER_POSTS: + self._above = _make_above_after_posts(version.version) + else: + self._above = _make_above_after_locals(version.version) + elif inclusive: + self._above = version.__le__ + else: + self._above = version.__lt__ + + def __eq__(self, other: object) -> bool: + if not isinstance(other, LowerBound): + return NotImplemented + return self.version == other.version and self.inclusive == other.inclusive + + def __lt__(self, other: LowerBound) -> bool: + if not isinstance(other, LowerBound): + return NotImplemented + # -inf < anything (except -inf itself). + if self.version is None: + return other.version is not None + if other.version is None: + return False + if self.version != other.version: + return self.version < other.version + # [v < (v: inclusive starts earlier. + return self.inclusive and not other.inclusive + + def __hash__(self) -> int: + return hash((self.version, self.inclusive)) + + def __repr__(self) -> str: + bracket = "[" if self.inclusive else "(" + return f"<{self.__class__.__name__} {bracket}{self.version!r}>" + + +@functools.total_ordering +class UpperBound: + """Upper bound of a version range. + + A version *v* of ``None`` means unbounded above (+inf). + At equal versions, ``v)`` sorts before ``v]`` because an exclusive + bound ends earlier. + """ + + __slots__ = ("_below", "inclusive", "version") + + def __init__(self, version: _VersionOrBoundary, inclusive: bool) -> None: + self.version = version + self.inclusive = inclusive + # Pre-bind a predicate "is parsed at or below this upper + # bound?". See LowerBound for the rationale. + if version is None: + self._below: Callable[[Version], bool] | None = None + elif isinstance(version, BoundaryVersion): + # Standard specifiers only ever produce AFTER_LOCALS upper + # bounds (from <=V / ==V / !=V with no local). + if version.kind == BoundaryKind.AFTER_LOCALS: + self._below = _make_below_after_locals(version.version) + else: + # An AFTER_POSTS upper is not produced by any specifier, but + # range algebra reaches it: complementing ``>V`` flips the + # ``AFTER_POSTS(V)`` lower into this upper bound. + self._below = version.__ge__ + elif inclusive: + self._below = version.__ge__ + else: + self._below = version.__gt__ + + def __eq__(self, other: object) -> bool: + if not isinstance(other, UpperBound): + return NotImplemented + return self.version == other.version and self.inclusive == other.inclusive + + def __lt__(self, other: UpperBound) -> bool: + if not isinstance(other, UpperBound): + return NotImplemented + # Nothing < +inf (except +inf itself). + if self.version is None: + return False + if other.version is None: + return True + if self.version != other.version: + return self.version < other.version + # v) < v]: exclusive ends earlier. + return not self.inclusive and other.inclusive + + def __hash__(self) -> int: + return hash((self.version, self.inclusive)) + + def __repr__(self) -> str: + bracket = "]" if self.inclusive else ")" + return f"<{self.__class__.__name__} {self.version!r}{bracket}>" + + +if TYPE_CHECKING: + #: A single contiguous interval as a (lower, upper) bound pair. + Interval = tuple[LowerBound, UpperBound] + + +NEG_INF: Final[LowerBound] = LowerBound(None, False) +POS_INF: Final[UpperBound] = UpperBound(None, False) +FULL_RANGE: Final[tuple[Interval]] = ((NEG_INF, POS_INF),) + + +def trim_release(release: tuple[int, ...]) -> tuple[int, ...]: + """Strip trailing zeros from a release tuple for normalized comparison.""" + end = len(release) + while end > 1 and release[end - 1] == 0: + end -= 1 + return release if end == len(release) else release[:end] + + +def _next_prefix_dev0(version: Version) -> Version: + """Smallest version in the next prefix: 1.2 -> 1.3.dev0.""" + release = (*version.release[:-1], version.release[-1] + 1) + return Version.from_parts(epoch=version.epoch, release=release, dev=0) + + +def _base_dev0(version: Version) -> Version: + """The .dev0 of a version's base release: 1.2 -> 1.2.dev0.""" + return Version.from_parts(epoch=version.epoch, release=version.release, dev=0) + + +def coerce_version(version: Version | str) -> Version | None: + if not isinstance(version, Version): + try: + version = Version(version) + except InvalidVersion: + return None + return version + + +def _make_above_after_posts(version: Version) -> Callable[[Version], bool]: + """Predicate ``parsed > AFTER_POSTS(V)`` for a lower bound. + + Per PEP 440, ``>V`` excludes V's post-releases unless V is itself + a post-release. AFTER_POSTS sits above V and every V.postN (with + or without local), and just below the next release. + """ + version_ge = version.__ge__ + version_epoch = version.epoch + version_pre = version.pre + version_release_trimmed = trim_release(version.release) + trimmed_length = len(version_release_trimmed) + + def above(parsed: Version) -> bool: + if version_ge(parsed): + return False + # parsed > V cmpkey-wise: above the boundary iff NOT in V's + # post family. + if parsed.epoch != version_epoch: + return True + parsed_release = parsed.release + if len(parsed_release) < trimmed_length: + return True + if parsed_release[:trimmed_length] != version_release_trimmed: + return True + for i in range(trimmed_length, len(parsed_release)): + if parsed_release[i] != 0: + return True + if parsed.pre != version_pre: + return True + + # Same release and pre as V: parsed is in V's post family (V itself, + # V+local, or V.postN), which the boundary sits above. A V.devN + # (different dev, no post) sorts before V and was already caught by + # ``version_ge`` above, so the answer here is always "not above". + return False + + return above + + +def _make_above_after_locals(version: Version) -> Callable[[Version], bool]: + """Predicate ``parsed > AFTER_LOCALS(V)`` for a lower bound. + + Used by the upper-side range of ``!=V`` (when V has no local + segment). AFTER_LOCALS sits above V and every ``V+local`` but + just below ``V.post0``. + """ + version_ge = version.__ge__ + version_epoch = version.epoch + version_pre = version.pre + version_post = version.post + version_dev = version.dev + version_release_trimmed = trim_release(version.release) + trimmed_length = len(version_release_trimmed) + + def above(parsed: Version) -> bool: + if version_ge(parsed): + return False + # parsed > V cmpkey-wise: above the boundary iff NOT in V's + # local family (same public version, any local segment). + if parsed.epoch != version_epoch: + return True + parsed_release = parsed.release + if len(parsed_release) < trimmed_length: + return True + if parsed_release[:trimmed_length] != version_release_trimmed: + return True + for i in range(trimmed_length, len(parsed_release)): + if parsed_release[i] != 0: + return True + if parsed.pre != version_pre: + return True + if parsed.post != version_post: + return True + return parsed.dev != version_dev + + return above + + +def _make_below_after_locals(version: Version) -> Callable[[Version], bool]: + """Predicate ``parsed <= AFTER_LOCALS(V)`` for an upper bound. + + Used by ``<=V``, ``==V``, ``!=V`` (no local). ``parsed`` is at or + below the boundary when it is at or below V cmpkey-wise, or when + it is in V's local family. + """ + version_ge = version.__ge__ + version_epoch = version.epoch + version_pre = version.pre + version_post = version.post + version_dev = version.dev + version_release_trimmed = trim_release(version.release) + trimmed_length = len(version_release_trimmed) + + def below(parsed: Version) -> bool: + if version_ge(parsed): + return True + # parsed > V cmpkey-wise: below the boundary iff in V's local + # family. + if parsed.epoch != version_epoch: + return False + parsed_release = parsed.release + if len(parsed_release) < trimmed_length: + return False + if parsed_release[:trimmed_length] != version_release_trimmed: + return False + for i in range(trimmed_length, len(parsed_release)): + if parsed_release[i] != 0: + return False + if parsed.pre != version_pre: + return False + if parsed.post != version_post: + return False + return parsed.dev == version_dev + + return below + + +def least_version_above(boundary: BoundaryVersion) -> Version | None: + """Smallest real version strictly above *boundary*, or ``None`` if none exists.""" + base = boundary.version + + if boundary.kind == BoundaryKind.AFTER_LOCALS: + # AFTER_LOCALS(V) sits just below V.post0, so its least successor is + # V.post0.dev0 (V.dev(N+1) if V has a dev, V.post(N+1).dev0 if a post). + if base.dev is not None: + return base.__replace__(dev=base.dev + 1, local=None) + next_post = (base.post + 1) if base.post is not None else 0 + return base.__replace__(post=next_post, dev=0, local=None) + + # AFTER_POSTS(V): a pre-release V steps to the next pre-release's .dev0; + # a final-release AFTER_POSTS has no least successor. + if base.pre is not None: + kind, number = base.pre + return base.__replace__(pre=(kind, number + 1), post=None, dev=0, local=None) + + return None + + +def range_is_empty(lower: LowerBound, upper: UpperBound) -> bool: + """True when the range defined by *lower* and *upper* contains no versions. + + A boundary lower sits just below the next real version, so an ordered pair + is still empty when the upper excludes that least successor: + ``(AFTER_POSTS(1.0a1), 1.0a2.dev0)`` holds no version. + """ + if upper.version is None: + return False + + if lower.version is None: + # Nothing sorts below MIN_VERSION, so an exclusive upper at or below it + # leaves an empty floor interval such as ``(-inf, 0.dev0)``. + return ( + not upper.inclusive + and isinstance(upper.version, Version) + and upper.version <= MIN_VERSION + ) + + if isinstance(lower.version, BoundaryVersion): + successor = least_version_above(lower.version) + if successor is not None: + if upper.version == successor: + return not upper.inclusive + return upper.version < successor + + if lower.version == upper.version: + return not (lower.inclusive and upper.inclusive) + + return lower.version > upper.version + + +def intersect_ranges( + left: Sequence[Interval], + right: Sequence[Interval], +) -> list[Interval]: + """Intersect two sorted, non-overlapping range lists (two-pointer merge).""" + result: list[Interval] = [] + left_index = right_index = 0 + while left_index < len(left) and right_index < len(right): + left_lower, left_upper = left[left_index] + right_lower, right_upper = right[right_index] + + lower = max(left_lower, right_lower) + upper = min(left_upper, right_upper) + + if not range_is_empty(lower, upper): + result.append((lower, upper)) + + # Advance whichever side has the smaller upper bound. + if left_upper < right_upper: + left_index += 1 + else: + right_index += 1 + + return result + + +def filter_by_ranges( + ranges: Sequence[Interval], + iterable: Iterable[Any], + key: Callable[[Any], Version | str] | None, + prereleases: bool | None, + region: Sequence[Interval] = (), +) -> Iterator[Any]: + """Filter *iterable* against precomputed version *ranges*. + + With ``prereleases=None``, the PEP 440 default applies: pre-releases are + excluded unless no final matches, in which case buffered pre-releases come + out at the end. A pre-release inside the opt-in ``region`` is the exception: + it is force-admitted in place, as ``prereleases=True`` would yield it. A + force-admitted pre-release is not a final, so it never suppresses the buffer. + """ + if prereleases is None: + prerelease_buffer: list[Any] = [] + found_final = False + + if len(ranges) == 1: + # Hot path: most specifiers and small SpecifierSets reduce to + # a single contiguous range. + lower, upper = ranges[0] + above = lower._above + below = upper._below + for item in iterable: + parsed = coerce_version(item if key is None else key(item)) + if parsed is None: + continue + if above is not None and not above(parsed): + continue + if below is not None and not below(parsed): + continue + if not parsed.is_prerelease: + found_final = True + yield item + elif region and matches_bounds_only(region, parsed): + yield item + elif not found_final: + prerelease_buffer.append(item) + if not found_final: + yield from prerelease_buffer + return + + for item in iterable: + parsed = coerce_version(item if key is None else key(item)) + if parsed is None: + continue + for lower, upper in ranges: + above = lower._above + if above is not None and not above(parsed): + break + below = upper._below + if below is None or below(parsed): + if not parsed.is_prerelease: + found_final = True + yield item + elif region and matches_bounds_only(region, parsed): + yield item + elif not found_final: + prerelease_buffer.append(item) + break + if not found_final: + yield from prerelease_buffer + return + + exclude_prereleases = prereleases is False + + if len(ranges) == 1: + # Hot path: most specifiers and small SpecifierSets reduce to + # a single contiguous range. + lower, upper = ranges[0] + above = lower._above + below = upper._below + for item in iterable: + parsed = coerce_version(item if key is None else key(item)) + if parsed is None: + continue + if exclude_prereleases and parsed.is_prerelease: + continue + if above is not None and not above(parsed): + continue + if below is None or below(parsed): + yield item + return + + for item in iterable: + parsed = coerce_version(item if key is None else key(item)) + if parsed is None: + continue + if exclude_prereleases and parsed.is_prerelease: + continue + for lower, upper in ranges: + above = lower._above + if above is not None and not above(parsed): + break + below = upper._below + if below is None or below(parsed): + yield item + break + + +def _nearest_release_above_prerelease(version: Version) -> Version: + """Smallest non-pre-release at or above a pre-release *version*.""" + if version.pre is not None: + # An a/b/rc pre-release drops to its final release, which outranks + # every post-release of that pre-release (1.0a1.post0 -> 1.0). + return version.__replace__(pre=None, post=None, dev=None, local=None) + + # A dev-only release keeps its post-release (1.0.post0.dev0 -> 1.0.post0, + # whose final 1.0 sorts below it). + return version.__replace__(dev=None, local=None) + + +def _lowest_release_at_or_above(value: Version | BoundaryVersion | None) -> Version: + """Smallest non-pre-release version at or above *value*. + + ``None`` is the ``-inf`` floor, whose nearest non-pre-release is + :data:`MIN_RELEASE`. + """ + if value is None: + return MIN_RELEASE + if isinstance(value, BoundaryVersion): + inner_version = value.version + if inner_version.is_prerelease: + return _nearest_release_above_prerelease(inner_version) + # AFTER_LOCALS(1.0) -> nearest non-pre is 1.0.post0 + # AFTER_LOCALS(1.0.post0) -> nearest non-pre is 1.0.post1 + next_post = (inner_version.post + 1) if inner_version.post is not None else 0 + return inner_version.__replace__(post=next_post, local=None) + + if not value.is_prerelease: + return value + + return _nearest_release_above_prerelease(value) + + +def ranges_are_prerelease_only(ranges: Sequence[Interval]) -> bool: + """True when every range in *ranges* contains only pre-releases. + + Used to detect unsatisfiable specifier sets when ``prereleases=False``: + if every range is pre-release-only, every contained version is excluded. + """ + for lower, upper in ranges: + nearest = _lowest_release_at_or_above(lower.version) + if upper.version is None or nearest < upper.version: + return False + if nearest == upper.version and upper.inclusive: + return False + return True + + +def wildcard_ranges(op: str, base: Version) -> list[Interval]: + """Ranges for ==V.* and !=V.*. + + ==1.2.* -> [1.2.dev0, 1.3.dev0); !=1.2.* -> complement. + """ + lower = _base_dev0(base) + upper = _next_prefix_dev0(base) + if op == "==": + return [(LowerBound(lower, True), UpperBound(upper, False))] + # != + return [ + (NEG_INF, UpperBound(lower, False)), + (LowerBound(upper, True), POS_INF), + ] + + +def standard_ranges(op: str, version: Version, has_local: bool) -> list[Interval]: + """Ranges for the standard PEP 440 operators (no wildcard, no ===). + + *has_local* indicates whether the spec string included a ``+local`` + segment; relevant only for ``==`` / ``!=`` to decide whether the + upper bound includes V's local family. + """ + if op == ">=": + return [(LowerBound(version, True), POS_INF)] + + if op == "<=": + return [ + ( + NEG_INF, + UpperBound(BoundaryVersion(version, BoundaryKind.AFTER_LOCALS), True), + ) + ] + + if op == ">": + if version.dev is not None: + # >V.devN: dev versions have no post-releases, so the + # next real version is V.dev(N+1). + lower_bound = version.__replace__(dev=version.dev + 1, local=None) + return [(LowerBound(lower_bound, True), POS_INF)] + if version.post is not None: + # >V.postN: next real version is V.post(N+1).dev0. + lower_bound = version.__replace__(post=version.post + 1, dev=0, local=None) + return [(LowerBound(lower_bound, True), POS_INF)] + # >V (final or pre-release V): exclude V itself, V+local, and + # every V.postN per PEP 440. + return [ + ( + LowerBound(BoundaryVersion(version, BoundaryKind.AFTER_POSTS), False), + POS_INF, + ) + ] + + if op == "<": + # list[Interval]: + """Ranges for one specifier's ``(op, version_str)``. + + Dispatches between the wildcard and standard builders. ``version`` is the + parsed ``version_str`` (its base, without the trailing ``.*``, for + wildcards). ``===`` is not handled here; its match is a literal string + compared in :mod:`packaging.specifiers`. + """ + if version_str.endswith(".*"): + return wildcard_ranges(op, version) + + return standard_ranges(op, version, "+" in version_str) + + +def intersect_specifier_bounds( + per_specifier_ranges: Iterable[Sequence[Interval]], +) -> Sequence[Interval]: + """Intersect each specifier's ranges into a single sequence. + + Short-circuits once the running intersection is empty, since no later + specifier can revive it. Callers must pass at least one specifier. + """ + result: Sequence[Interval] | None = None + for sub in per_specifier_ranges: + if result is None: + result = sub + else: + result = intersect_ranges(result, sub) + if not result: + break + + if result is None: # pragma: no cover - callers guard non-empty input + raise RuntimeError("intersect_specifier_bounds called with no specifiers") + + return result + + +def matches_bounds_only(ranges: Sequence[Interval], version: Version) -> bool: + """Whether ``version`` falls within any of ``ranges``. + + The pure bounds membership test, for a single already-parsed version with + no pre-release policy applied. ``ranges`` are sorted and non-overlapping, + so a version below one range's lower bound is below every later range too. + """ + for lower, upper in ranges: + above = lower._above + if above is not None and not above(version): + return False + + below = upper._below + if below is None or below(version): + return True + + return False + + +def resolve_prereleases( + configured: bool | None, autodetected: bool | None +) -> bool | None: + """Resolve a specifier's effective default pre-release policy. + + An explicit ``configured`` value wins; otherwise an autodetected ``True`` + propagates and anything else falls back to the PEP 440 default (``None``). + """ + if configured is not None: + return configured + + if autodetected: + return True + + return None diff --git a/server/libs/packaging/_tokenizer.py b/server/libs/packaging/_tokenizer.py index 5ab891c..db7cd17 100644 --- a/server/libs/packaging/_tokenizer.py +++ b/server/libs/packaging/_tokenizer.py @@ -3,13 +3,18 @@ from __future__ import annotations import contextlib import re from dataclasses import dataclass -from typing import Generator, Mapping, NoReturn +from typing import TYPE_CHECKING, NoReturn from .specifiers import Specifier +if TYPE_CHECKING: + from collections.abc import Generator, Mapping + @dataclass class Token: + __slots__ = ("name", "position", "text") + name: str text: str position: int @@ -84,7 +89,7 @@ DEFAULT_RULES: dict[str, re.Pattern[str]] = { "VERSION_PREFIX_TRAIL": re.compile(r"\.\*"), "VERSION_LOCAL_LABEL_TRAIL": re.compile(r"\+[a-z0-9]+(?:[-_\.][a-z0-9]+)*"), "WS": re.compile(r"[ \t]+"), - "END": re.compile(r"$"), + "END": re.compile(r"\Z"), } @@ -95,6 +100,8 @@ class Tokenizer: matches. """ + __slots__ = ("next_token", "position", "rules", "source") + def __init__( self, source: str, @@ -135,7 +142,7 @@ class Tokenizer: def expect(self, name: str, *, expected: str) -> Token: """Expect a certain token name next, failing with a syntax error otherwise. - The token is *not* read. + The token is read and returned. """ if not self.check(name): raise self.raise_syntax_error(f"Expected {expected}") diff --git a/server/libs/packaging/dependency_groups.py b/server/libs/packaging/dependency_groups.py index 413e5cb..0ad2d01 100644 --- a/server/libs/packaging/dependency_groups.py +++ b/server/libs/packaging/dependency_groups.py @@ -4,7 +4,7 @@ import re from collections.abc import Mapping, Sequence from .errors import _ErrorCollector -from .requirements import Requirement +from .requirements import InvalidRequirement, Requirement __all__ = [ "CyclicDependencyGroup", @@ -28,12 +28,16 @@ def __dir__() -> list[str]: class DuplicateGroupNames(ValueError): """ The same dependency groups were defined twice, with different non-normalized names. + + .. versionadded:: 26.1 """ class CyclicDependencyGroup(ValueError): """ The dependency group includes form a cycle. + + .. versionadded:: 26.1 """ def __init__(self, requested_group: str, group: str, include_group: str) -> None: @@ -50,6 +54,10 @@ class CyclicDependencyGroup(ValueError): f"{requested_group}: {reason}" ) + # Support pickling; ``args`` does not match ``__init__``'s signature. + def __reduce__(self) -> tuple[type[CyclicDependencyGroup], tuple[str, str, str]]: + return (self.__class__, (self.requested_group, self.group, self.include_group)) + # in the PEP 735 spec, the tables in dependency group lists were described as # "Dependency Object Specifiers", but the only defined type of object was a @@ -58,6 +66,8 @@ class InvalidDependencyGroupObject(ValueError): """ A member of a dependency group was identified as a dict, but was not in a valid format. + + .. versionadded:: 26.1 """ @@ -67,6 +77,12 @@ class InvalidDependencyGroupObject(ValueError): class DependencyGroupInclude: + """ + A reference to another dependency group by name. + + .. versionadded:: 26.1 + """ + __slots__ = ("include_group",) def __init__(self, include_group: str) -> None: @@ -91,6 +107,8 @@ class DependencyGroupResolver: :param dependency_groups: A mapping, as provided via pyproject ``[dependency-groups]``. + + .. versionadded:: 26.1 """ def __init__( @@ -227,9 +245,10 @@ class DependencyGroupResolver: for item in raw_group: if isinstance(item, str): # packaging.requirements.Requirement parsing ensures that this is a - # valid PEP 508 Dependency Specifier - # raises InvalidRequirement on failure - elements.append(Requirement(item)) + # valid PEP 508 Dependency Specifier. Collect InvalidRequirement + # if it throws that. + with errors.collect(InvalidRequirement): + elements.append(Requirement(item)) elif isinstance(item, Mapping): if tuple(item.keys()) != ("include-group",): errors.error( @@ -239,10 +258,22 @@ class DependencyGroupResolver: ) else: include_group = item["include-group"] - elements.append(DependencyGroupInclude(include_group=include_group)) + if not isinstance(include_group, str): + msg = ( + "Dependency group include-group value is not a string: " + f"{item!r}" + ) + errors.error(TypeError(msg)) + else: + elements.append( + DependencyGroupInclude(include_group=include_group) + ) else: errors.error(TypeError(f"Invalid dependency group item: {item!r}")) + if errors.errors: + return () + self._parsed_groups[group] = tuple(elements) return self._parsed_groups[group] @@ -261,6 +292,8 @@ def resolve_dependency_groups( :param dependency_groups: the parsed contents of the ``[dependency-groups]`` table from ``pyproject.toml`` :param groups: the name of the group(s) to resolve + + .. versionadded:: 26.1 """ resolver = DependencyGroupResolver(dependency_groups) return tuple(str(r) for group in groups for r in resolver.resolve(group)) diff --git a/server/libs/packaging/direct_url.py b/server/libs/packaging/direct_url.py index 5d1c56c..4de7acc 100644 --- a/server/libs/packaging/direct_url.py +++ b/server/libs/packaging/direct_url.py @@ -9,6 +9,7 @@ from typing import TYPE_CHECKING, Any, Protocol, TypeVar if TYPE_CHECKING: # pragma: no cover import sys from collections.abc import Collection + from urllib.parse import SplitResult if sys.version_info >= (3, 11): from typing import Self @@ -83,7 +84,7 @@ _PEP610_USER_PASS_ENV_VARS_REGEX = re.compile( def _strip_auth_from_netloc(netloc: str, safe_user_passwords: Collection[str]) -> str: if "@" not in netloc: return netloc - user_pass, netloc_no_user_pass = netloc.split("@", 1) + user_pass, netloc_no_user_pass = netloc.rsplit("@", 1) if user_pass in safe_user_passwords: return netloc if _PEP610_USER_PASS_ENV_VARS_REGEX.match(user_pass): @@ -109,8 +110,15 @@ def _strip_url(url: str, safe_user_passwords: Collection[str]) -> str: ) +def _file_url_has_absolute_path(parsed_url: SplitResult) -> bool: + return parsed_url.path.startswith("/") + + class DirectUrlValidationError(Exception): - """Raised when when input data is not spec-compliant.""" + """Raised when when input data is not spec-compliant. + + .. versionadded:: 26.1 + """ context: str | None = None message: str @@ -146,6 +154,8 @@ class _DirectUrlRequiredKeyError(DirectUrlValidationError): @dataclasses.dataclass(frozen=True, init=False) class VcsInfo: + """The version control information of a :class:`DirectUrl`.""" + vcs: str commit_id: str requested_revision: str | None = None @@ -173,6 +183,8 @@ class VcsInfo: @dataclasses.dataclass(frozen=True, init=False) class ArchiveInfo: + """The archive information of a :class:`DirectUrl`.""" + hashes: Mapping[str, str] | None = None def __init__( @@ -219,6 +231,8 @@ class ArchiveInfo: @dataclasses.dataclass(frozen=True, init=False) class DirInfo: + """The local directory information of a :class:`DirectUrl`.""" + editable: bool | None = None def __init__( @@ -237,7 +251,10 @@ class DirInfo: @dataclasses.dataclass(frozen=True, init=False) class DirectUrl: - """A class representing a direct URL.""" + """A class representing a direct URL. + + .. versionadded:: 26.1 + """ url: str archive_info: ArchiveInfo | None = None @@ -277,11 +294,18 @@ class DirectUrl: raise DirectUrlValidationError( "Exactly one of vcs_info, archive_info, dir_info must be present" ) - if direct_url.dir_info is not None and not direct_url.url.startswith("file://"): - raise DirectUrlValidationError( - "URL scheme must be file:// when dir_info is present", - context="url", - ) + if direct_url.dir_info is not None: + parsed_url = urllib.parse.urlsplit(direct_url.url) + if parsed_url.scheme != "file": + raise DirectUrlValidationError( + "URL scheme must be file:// when dir_info is present", + context="url", + ) + if not _file_url_has_absolute_path(parsed_url): + raise DirectUrlValidationError( + "File URL must be absolute when dir_info is present", + context="url", + ) # XXX subdirectory must be relative, can we, should we validate that here? return direct_url diff --git a/server/libs/packaging/licenses/__init__.py b/server/libs/packaging/licenses/__init__.py index 36e46ed..f95ac02 100644 --- a/server/libs/packaging/licenses/__init__.py +++ b/server/libs/packaging/licenses/__init__.py @@ -48,7 +48,7 @@ def __dir__() -> list[str]: return __all__ -license_ref_allowed = re.compile("^[A-Za-z0-9.-]*$") +license_ref_allowed = re.compile("^[A-Za-z0-9.-]+$") NormalizedLicenseExpression = NewType("NormalizedLicenseExpression", str) """ @@ -64,7 +64,7 @@ class InvalidLicenseExpression(ValueError): >>> canonicalize_license_expression("invalid") Traceback (most recent call last): ... - packaging.licenses.InvalidLicenseExpression: Invalid license expression: 'invalid' + packaging.licenses.InvalidLicenseExpression: Unknown license: 'invalid' """ @@ -148,9 +148,18 @@ def canonicalize_license_expression( # Take a final pass to check for unknown licenses/exceptions. normalized_tokens = [] - for token in tokens: + last_license_start = False + for index, token in enumerate(tokens): if token in {"or", "and", "with", "(", ")"}: + if token == "with" and ( + not last_license_start + or index + 1 == len(tokens) + or tokens[index + 1] in {"or", "and", "with", "(", ")"} + ): + message = f"Invalid license expression: {raw_license_expression!r}" + raise InvalidLicenseExpression(message) normalized_tokens.append(token.upper()) + last_license_start = False continue if normalized_tokens and normalized_tokens[-1] == "WITH": @@ -159,6 +168,7 @@ def canonicalize_license_expression( raise InvalidLicenseExpression(message) normalized_tokens.append(EXCEPTIONS[token]["id"]) + last_license_start = False else: if token.endswith("+"): final_token = token[:-1] @@ -168,15 +178,17 @@ def canonicalize_license_expression( suffix = "" if final_token.startswith("licenseref-"): - if not license_ref_allowed.match(final_token): - message = f"Invalid licenseref: {final_token!r}" + license_ref_id = final_token[len("licenseref-") :] + if suffix or not license_ref_allowed.match(license_ref_id): + message = f"Invalid licenseref: {token!r}" raise InvalidLicenseExpression(message) - normalized_tokens.append(license_refs[final_token] + suffix) + normalized_tokens.append(license_refs[final_token]) else: if final_token not in LICENSES: message = f"Unknown license: {final_token!r}" raise InvalidLicenseExpression(message) normalized_tokens.append(LICENSES[final_token]["id"] + suffix) + last_license_start = True normalized_expression = " ".join(normalized_tokens) diff --git a/server/libs/packaging/markers.py b/server/libs/packaging/markers.py index 564451f..51b6036 100644 --- a/server/libs/packaging/markers.py +++ b/server/libs/packaging/markers.py @@ -4,11 +4,13 @@ from __future__ import annotations +import functools import operator import os import platform import sys -from typing import AbstractSet, Callable, Literal, Mapping, TypedDict, Union, cast +from collections.abc import Set as AbstractSet +from typing import TYPE_CHECKING, Callable, Literal, TypedDict, Union, cast from ._parser import MarkerAtom, MarkerList, Op, Value, Variable from ._parser import parse_marker as _parse_marker @@ -16,6 +18,9 @@ from ._tokenizer import ParserSyntaxError from .specifiers import InvalidSpecifier, Specifier from .utils import canonicalize_name +if TYPE_CHECKING: + from collections.abc import Mapping + __all__ = [ "Environment", "EvaluateContext", @@ -40,6 +45,8 @@ Valid values for the ``context`` passed to :meth:`Marker.evaluate` are: * ``"metadata"`` (for core metadata; default) * ``"lock_file"`` (for lock files) * ``"requirement"`` (i.e. all other situations) + +.. versionadded:: 25.0 """ MARKERS_ALLOWING_SET = {"extras", "dependency_groups"} @@ -68,8 +75,17 @@ class UndefinedComparison(ValueError): """ -class UndefinedEnvironmentName(ValueError): - """Raised when evaluating a marker that references a missing environment key.""" +class UndefinedEnvironmentName(KeyError): + """Raised when evaluating a marker that references a missing environment key. + + Subclasses :class:`KeyError` so that code catching the bare ``KeyError`` that + a missing environment lookup historically produced keeps working. + + .. versionchanged:: 26.3 + Now subclasses :class:`KeyError` (was :class:`ValueError`) and is raised by + :meth:`Marker.evaluate` for missing environment keys, where a bare + ``KeyError`` was raised before. + """ class Environment(TypedDict): @@ -152,16 +168,30 @@ class Environment(TypedDict): def _normalize_extras( result: MarkerList | MarkerAtom | str, ) -> MarkerList | MarkerAtom | str: + if isinstance(result, list): + return [_normalize_extras(r) for r in result] if not isinstance(result, tuple): return result lhs, op, rhs = result - if isinstance(lhs, Variable) and lhs.value == "extra": + if isinstance(lhs, Variable) and lhs.value == "extra" and isinstance(rhs, Value): normalized_extra = canonicalize_name(rhs.value) rhs = Value(normalized_extra) - elif isinstance(rhs, Variable) and rhs.value == "extra": + elif isinstance(rhs, Variable) and rhs.value == "extra" and isinstance(lhs, Value): normalized_extra = canonicalize_name(lhs.value) lhs = Value(normalized_extra) + elif ( + isinstance(rhs, Variable) + and rhs.value in MARKERS_ALLOWING_SET + and isinstance(lhs, Value) + ): + # PEP 685 (extras) / PEP 735 (dependency_groups): the set-valued membership + # literal must also be normalized. evaluate() already canonicalizes both + # operands for these keys (see _normalize), so normalizing the literal at + # parse time keeps __str__/__eq__/__hash__ consistent with evaluate() -- e.g. + # Marker('"Foo" in extras') and Marker('"foo" in extras') must compare and + # hash equal (the membership variable is always the right-hand operand). + lhs = Value(canonicalize_name(lhs.value)) return lhs, op, rhs @@ -178,16 +208,14 @@ def _format_marker( ) -> str: assert isinstance(marker, (list, tuple, str)) - # Sometimes we have a structure like [[...]] which is a single item list - # where the single item is itself it's own list. In that case we want skip - # the rest of this function so that we don't get extraneous () on the - # outside. + # Unwrap a redundant [[...]] wrapper, but keep the nesting context so a + # nested group keeps the parentheses its and/or precedence needs. if ( isinstance(marker, list) and len(marker) == 1 and isinstance(marker[0], (list, tuple)) ): - return _format_marker(marker[0]) + return _format_marker(marker[0], first=first) if isinstance(marker, list): inner = (_format_marker(m, first=False) for m in marker) @@ -251,6 +279,15 @@ def _normalize( return lhs, rhs +def _lookup_environment( + environment: dict[str, str | AbstractSet[str]], key: str +) -> str | AbstractSet[str]: + try: + return environment[key] + except KeyError: + raise UndefinedEnvironmentName(key) from None + + def _evaluate_markers( markers: MarkerList, environment: dict[str, str | AbstractSet[str]] ) -> bool: @@ -264,14 +301,20 @@ def _evaluate_markers( if isinstance(lhs, Variable): environment_key = lhs.value - lhs_value = environment[environment_key] + lhs_value = _lookup_environment(environment, environment_key) rhs_value = rhs.value else: lhs_value = lhs.value environment_key = rhs.value - rhs_value = environment[environment_key] + rhs_value = _lookup_environment(environment, environment_key) - assert isinstance(lhs_value, str), "lhs must be a string" + if not isinstance(lhs_value, str): + raise UndefinedComparison( + f"Set-valued marker {environment_key!r} can only be used " + f'with the membership form (e.g. "" in ' + f"{environment_key}); it cannot appear on the left-hand " + f"side of {op.serialize()!r}." + ) lhs_value, rhs_value = _normalize(lhs_value, rhs_value, key=environment_key) groups[-1].append(_eval_op(lhs_value, op, rhs_value, key=environment_key)) elif marker == "or": @@ -292,10 +335,14 @@ def _format_full_version(info: sys._version_info) -> str: return version -def default_environment() -> Environment: - """Return the default marker environment for the current Python process. +@functools.cache +def _cached_default_environment() -> Environment: + """Build the default marker environment for the current Python process. - This is the base environment used by :meth:`Marker.evaluate`. + The values are derived from process-constant data (the running interpreter + and the host platform), so this is cached and built only once. The result is + shared between callers and must never be mutated; :func:`default_environment` + returns a fresh copy. """ iver = _format_full_version(sys.implementation.version) implementation_name = sys.implementation.name @@ -314,6 +361,22 @@ def default_environment() -> Environment: } +def default_environment() -> Environment: + """Return the default marker environment for the current Python process. + + This is the base environment used by :meth:`Marker.evaluate`. A fresh copy + is returned on every call so callers may freely mutate the result; a shallow + copy suffices because all values are immutable strings. + + .. versionchanged:: 26.3 + The environment is computed once per process and cached, since it is + derived from process-constant data. Patching ``platform``/``sys``/``os`` + after the first call has no effect; pass an explicit ``environment`` to + :meth:`Marker.evaluate` to evaluate against different values. + """ + return cast("Environment", dict(_cached_default_environment())) + + class Marker: """Represents a parsed dependency marker expression. @@ -421,11 +484,19 @@ class Marker: raise TypeError(f"Cannot restore Marker from {state!r}") def __and__(self, other: Marker) -> Marker: + """Combine this marker with another using ``and``. + + .. versionadded:: 26.1 + """ if not isinstance(other, Marker): return NotImplemented return self._from_markers([self._markers, "and", other._markers]) def __or__(self, other: Marker) -> Marker: + """Combine this marker with another using ``or``. + + .. versionadded:: 26.1 + """ if not isinstance(other, Marker): return NotImplemented return self._from_markers([self._markers, "or", other._markers]) @@ -454,19 +525,23 @@ class Marker: is missing from the evaluation environment. :returns: ``True`` if the marker matches, otherwise ``False``. + .. versionchanged:: 25.0 + Added the ``context`` parameter, which influences which marker names + are considered valid. """ current_environment = cast( "dict[str, str | AbstractSet[str]]", default_environment() ) if context == "lock_file": - current_environment.update( - extras=frozenset(), dependency_groups=frozenset() - ) + current_environment |= { + "extras": frozenset(), + "dependency_groups": frozenset(), + } elif context == "metadata": current_environment["extra"] = "" if environment is not None: - current_environment.update(environment) + current_environment |= environment if "extra" in current_environment: # The API used to allow setting extra to None. We need to handle # this case for backwards compatibility. Also skip running @@ -479,6 +554,16 @@ class Marker: ) +def _pep440_python_full_version(python_full_version: str) -> str: + """ + Work around platform.python_version() returning something that is not PEP 440 + compliant for non-tagged Python builds. + """ + if python_full_version.endswith("+"): + return f"{python_full_version}local" + return python_full_version + + def _repair_python_full_version( env: dict[str, str | AbstractSet[str]], ) -> dict[str, str | AbstractSet[str]]: @@ -487,6 +572,5 @@ def _repair_python_full_version( compliant for non-tagged Python builds. """ python_full_version = cast("str", env["python_full_version"]) - if python_full_version.endswith("+"): - env["python_full_version"] = f"{python_full_version}local" + env["python_full_version"] = _pep440_python_full_version(python_full_version) return env diff --git a/server/libs/packaging/metadata.py b/server/libs/packaging/metadata.py index dccb627..1061105 100644 --- a/server/libs/packaging/metadata.py +++ b/server/libs/packaging/metadata.py @@ -6,6 +6,7 @@ import email.parser import email.policy import keyword import pathlib +import re import typing from typing import ( Any, @@ -22,6 +23,7 @@ from .errors import ExceptionGroup, _ErrorCollector if typing.TYPE_CHECKING: from .licenses import NormalizedLicenseExpression + from .version import Version T = typing.TypeVar("T") @@ -42,7 +44,10 @@ def __dir__() -> list[str]: class InvalidMetadata(ValueError): - """A metadata field contains invalid data.""" + """A metadata field contains invalid data. + + .. versionadded:: 23.2 + """ field: str """The name of the field that contains invalid data.""" @@ -51,6 +56,10 @@ class InvalidMetadata(ValueError): self.field = field super().__init__(message) + # Support pickling; ``args`` does not match ``__init__``'s signature. + def __reduce__(self) -> tuple[type[InvalidMetadata], tuple[str, str]]: + return (self.__class__, (self.field, self.args[0])) + # The RawMetadata class attempts to make as few assumptions about the underlying # serialization formats as possible. The idea is that as long as a serialization @@ -125,11 +134,17 @@ class RawMetadata(TypedDict, total=False): # Metadata 2.4 - PEP 639 license_expression: str + """.. versionadded:: 24.2""" license_files: list[str] + """.. versionadded:: 24.2""" # Metadata 2.5 - PEP 794 import_names: list[str] + """.. versionadded:: 26.0""" import_namespaces: list[str] + """.. versionadded:: 26.0""" + + # Metadata 2.6 - PEP 808 (no new fields, behavior change for Dynamic) # 'keywords' is special as it's a string in the core metadata spec, but we @@ -225,13 +240,19 @@ def _get_payload(msg: email.message.Message, source: bytes | str) -> str: # and we don't need to deal with it. if isinstance(source, str): payload = msg.get_payload() - assert isinstance(payload, str) + # A multipart payload makes get_payload() return a list of messages + # rather than a str; route it to ``unparsed``. + if not isinstance(payload, str): + raise ValueError("payload is not a string") # noqa: TRY004 return payload # If our source is a bytes, then we're managing the encoding and we need # to deal with it. else: bpayload = msg.get_payload(decode=True) - assert isinstance(bpayload, bytes) + # A multipart payload makes get_payload(decode=True) return None; + # route it to ``unparsed``. + if not isinstance(bpayload, bytes): + raise ValueError("payload in an invalid encoding") # noqa: TRY004 try: return bpayload.decode("utf8", "strict") except UnicodeDecodeError as exc: @@ -287,11 +308,19 @@ _EMAIL_TO_RAW_MAPPING = { _RAW_TO_EMAIL_MAPPING = {raw: email for email, raw in _EMAIL_TO_RAW_MAPPING.items()} +# A bare "\r" makes the email generator raise ``HeaderWriteError``, and on +# CPython releases without the CVE-2024-6923 fix any ``str.splitlines`` +# boundary ends the header line, so fold all of them, not just "\n". +_LINE_BOUNDARY_RE = re.compile(r"\r\n|[\n\r\v\f\x1c\x1d\x1e\x85\u2028\u2029]") + + # This class is for writing RFC822 messages class RFC822Policy(email.policy.EmailPolicy): """ This is :class:`email.policy.EmailPolicy`, but with a simple ``header_store_parse`` implementation that handles multi-line values, and some nice defaults. + + .. versionadded:: 26.0 """ utf8 = True @@ -300,7 +329,7 @@ class RFC822Policy(email.policy.EmailPolicy): def header_store_parse(self, name: str, value: str) -> tuple[str, str]: size = len(name) + 2 - value = value.replace("\n", "\n" + " " * size) + value = _LINE_BOUNDARY_RE.sub("\n" + " " * size, value) return (name, value) @@ -310,6 +339,8 @@ class RFC822Message(email.message.EmailMessage): This is :class:`email.message.EmailMessage` with two small changes: it defaults to our `RFC822Policy`, and it correctly writes unicode when being called with `bytes()`. + + .. versionadded:: 26.0 """ def __init__(self) -> None: @@ -511,8 +542,20 @@ _NOT_FOUND = object() # Keep the two values in sync. -_VALID_METADATA_VERSIONS = ["1.0", "1.1", "1.2", "2.1", "2.2", "2.3", "2.4", "2.5"] -_MetadataVersion = Literal["1.0", "1.1", "1.2", "2.1", "2.2", "2.3", "2.4", "2.5"] +_VALID_METADATA_VERSIONS = [ + "1.0", + "1.1", + "1.2", + "2.1", + "2.2", + "2.3", + "2.4", + "2.5", + "2.6", +] +_MetadataVersion = Literal[ + "1.0", "1.1", "1.2", "2.1", "2.2", "2.3", "2.4", "2.5", "2.6" +] _REQUIRED_ATTRS = frozenset(["metadata_version", "name", "version"]) @@ -572,9 +615,7 @@ class _Validator(Generic[T]): def _invalid_metadata( self, msg: str, cause: Exception | None = None ) -> InvalidMetadata: - exc = InvalidMetadata( - self.raw_name, msg.format_map({"field": repr(self.raw_name)}) - ) + exc = InvalidMetadata(self.raw_name, msg) exc.__cause__ = cause return exc @@ -586,67 +627,82 @@ class _Validator(Generic[T]): def _process_name(self, value: str) -> str: if not value: - raise self._invalid_metadata("{field} is a required field") + raise self._invalid_metadata(f"{self.raw_name!r} is a required field") # Validate the name as a side-effect. try: utils.canonicalize_name(value, validate=True) except utils.InvalidName as exc: raise self._invalid_metadata( - f"{value!r} is invalid for {{field}}", cause=exc + f"{value!r} is invalid for {self.raw_name!r}", cause=exc ) from exc else: return value - def _process_version(self, value: str) -> version_module.Version: + def _process_version(self, value: str) -> Version: if not value: - raise self._invalid_metadata("{field} is a required field") + raise self._invalid_metadata(f"{self.raw_name!r} is a required field") try: return version_module.parse(value) except version_module.InvalidVersion as exc: raise self._invalid_metadata( - f"{value!r} is invalid for {{field}}", cause=exc + f"{value!r} is invalid for {self.raw_name!r}", cause=exc ) from exc def _process_summary(self, value: str) -> str: - """Check the field contains no newlines.""" - if "\n" in value: - raise self._invalid_metadata("{field} must be a single line") + """Check the field contains no line breaks.""" + if _LINE_BOUNDARY_RE.search(value): + raise self._invalid_metadata(f"{self.raw_name!r} must be a single line") return value def _process_description_content_type(self, value: str) -> str: content_types = {"text/plain", "text/x-rst", "text/markdown"} + invalid_msg = ( + f"{self.raw_name!r} must be one of {list(content_types)}, not {value!r}" + ) message = email.message.EmailMessage() - message["content-type"] = value + try: + message["content-type"] = value + # The email parser can raise IndexError on malformed RFC 2231 + # parameters such as "text/plain; x*". + except (ValueError, IndexError) as exc: + msg = f"{value!r} is not a valid content type for {self.raw_name!r}" + raise self._invalid_metadata(msg, cause=exc) from exc + content_type_header = message["content-type"] + if content_type_header.defects: + defect = content_type_header.defects[0] + msg = ( + f"{value!r} is not a valid content type for {self.raw_name!r}: {defect}" + ) + raise self._invalid_metadata(msg, cause=defect) from defect content_type, parameters = ( # Defaults to `text/plain` if parsing failed. message.get_content_type().lower(), - message["content-type"].params, + content_type_header.params, ) # Check if content-type is valid or defaulted to `text/plain` and thus was # not parseable. if content_type not in content_types or content_type not in value.lower(): - raise self._invalid_metadata( - f"{{field}} must be one of {list(content_types)}, not {value!r}" - ) + raise self._invalid_metadata(invalid_msg) charset = parameters.get("charset", "UTF-8") - if charset != "UTF-8": + if charset.lower() != "utf-8": raise self._invalid_metadata( - f"{{field}} can only specify the UTF-8 charset, not {charset!r}" + f"{self.raw_name!r} can only specify the UTF-8 charset, not {charset!r}" ) markdown_variants = {"GFM", "CommonMark"} variant = parameters.get("variant", "GFM") # Use an acceptable default. if content_type == "text/markdown" and variant not in markdown_variants: raise self._invalid_metadata( - f"valid Markdown variants for {{field}} are {list(markdown_variants)}, " - f"not {variant!r}", + f"valid Markdown variants for {self.raw_name!r} are " + f"{list(markdown_variants)}, not {variant!r}", ) return value def _process_dynamic(self, value: list[str]) -> list[str]: - for dynamic_field in map(str.lower, value): + dynamic_fields = list(map(str.lower, value)) + for dynamic_field in dynamic_fields: if dynamic_field in {"name", "version", "metadata-version"}: raise self._invalid_metadata( f"{dynamic_field!r} is not allowed as a dynamic field" @@ -655,7 +711,7 @@ class _Validator(Generic[T]): raise self._invalid_metadata( f"{dynamic_field!r} is not a valid dynamic field" ) - return list(map(str.lower, value)) + return dynamic_fields def _process_provides_extra( self, @@ -667,7 +723,7 @@ class _Validator(Generic[T]): normalized_names.append(utils.canonicalize_name(name, validate=True)) except utils.InvalidName as exc: raise self._invalid_metadata( - f"{name!r} is invalid for {{field}}", cause=exc + f"{name!r} is invalid for {self.raw_name!r}", cause=exc ) from exc else: return normalized_names @@ -677,7 +733,7 @@ class _Validator(Generic[T]): return specifiers.SpecifierSet(value) except specifiers.InvalidSpecifier as exc: raise self._invalid_metadata( - f"{value!r} is invalid for {{field}}", cause=exc + f"{value!r} is invalid for {self.raw_name!r}", cause=exc ) from exc def _process_requires_dist( @@ -690,7 +746,7 @@ class _Validator(Generic[T]): reqs.append(requirements.Requirement(req)) except requirements.InvalidRequirement as exc: raise self._invalid_metadata( - f"{req!r} is invalid for {{field}}", cause=exc + f"{req!r} is invalid for {self.raw_name!r}", cause=exc ) from exc else: return reqs @@ -700,7 +756,7 @@ class _Validator(Generic[T]): return licenses.canonicalize_license_expression(value) except ValueError as exc: raise self._invalid_metadata( - f"{value!r} is invalid for {{field}}", cause=exc + f"{value!r} is invalid for {self.raw_name!r}", cause=exc ) from exc def _process_license_files(self, value: list[str]) -> list[str]: @@ -708,23 +764,24 @@ class _Validator(Generic[T]): for path in value: if ".." in path: raise self._invalid_metadata( - f"{path!r} is invalid for {{field}}, " + f"{path!r} is invalid for {self.raw_name!r}, " "parent directory indicators are not allowed" ) if "*" in path: raise self._invalid_metadata( - f"{path!r} is invalid for {{field}}, paths must be resolved" + f"{path!r} is invalid for {self.raw_name!r}, paths must be resolved" ) if ( pathlib.PurePosixPath(path).is_absolute() or pathlib.PureWindowsPath(path).is_absolute() ): raise self._invalid_metadata( - f"{path!r} is invalid for {{field}}, paths must be relative" + f"{path!r} is invalid for {self.raw_name!r}, paths must be relative" ) if pathlib.PureWindowsPath(path).as_posix() != path: raise self._invalid_metadata( - f"{path!r} is invalid for {{field}}, paths must use '/' delimiter" + f"{path!r} is invalid for {self.raw_name!r}, " + "paths must use '/' delimiter" ) paths.append(path) return paths @@ -736,17 +793,17 @@ class _Validator(Generic[T]): for identifier in name.split("."): if not identifier.isidentifier(): raise self._invalid_metadata( - f"{name!r} is invalid for {{field}}; " + f"{name!r} is invalid for {self.raw_name!r}; " f"{identifier!r} is not a valid identifier" ) elif keyword.iskeyword(identifier): raise self._invalid_metadata( - f"{name!r} is invalid for {{field}}; " + f"{name!r} is invalid for {self.raw_name!r}; " f"{identifier!r} is a keyword" ) if semicolon and private.lstrip() != "private": raise self._invalid_metadata( - f"{import_name!r} is invalid for {{field}}; " + f"{import_name!r} is invalid for {self.raw_name!r}; " "the only valid option is 'private'" ) return value @@ -761,6 +818,12 @@ class Metadata: metadata fields instead of only using built-in types. Any invalid metadata will cause :exc:`InvalidMetadata` to be raised (with a :py:attr:`~BaseException.__cause__` attribute as appropriate). + + .. versionadded:: 23.2 + + .. versionchanged:: 24.0 + Optional attributes now return None when the field is absent instead of + raising. """ _raw: RawMetadata @@ -769,8 +832,9 @@ class Metadata: def from_raw(cls, data: RawMetadata, *, validate: bool = True) -> Metadata: """Create an instance from :class:`RawMetadata`. - If *validate* is true, all metadata will be validated. All exceptions - related to validation will be gathered and raised as an :class:`ExceptionGroup`. + If *validate* is true, all metadata will be validated and all related + exceptions will be gathered and raised as an :class:`ExceptionGroup`; + otherwise, validation happens per attribute when it is accessed. """ ins = cls() ins._raw = data.copy() # Mutations occur due to caching enriched values. @@ -829,20 +893,32 @@ class Metadata: raw, unparsed = parse_email(data) if validate: - with _ErrorCollector().on_exit("unparsed") as collector: + with _ErrorCollector().on_exit("invalid or unparsed metadata") as collector: for unparsed_key in unparsed: if unparsed_key in _EMAIL_TO_RAW_MAPPING: message = f"{unparsed_key!r} has invalid data" else: message = f"unrecognized field: {unparsed_key!r}" collector.error(InvalidMetadata(unparsed_key, message)) + try: + validated = cls.from_raw(raw, validate=validate) + except ExceptionGroup as exc_group: + # The no-branch pragmas cover arcs only seen by Python 3.9. + for exc in exc_group.exceptions: # pragma: no branch + # A required field reported above as unparsed is absent + # from `raw`, so skip from_raw's duplicate "missing" + # complaint. + if not ( + isinstance(exc, InvalidMetadata) + and exc.field in unparsed + and _EMAIL_TO_RAW_MAPPING.get(exc.field) not in raw + ): + collector.error(exc) + else: + if not collector.errors: # pragma: no branch + return validated - try: - return cls.from_raw(raw, validate=validate) - except ExceptionGroup as exc_group: - raise ExceptionGroup( - "invalid or unparsed metadata", exc_group.exceptions - ) from None + return cls.from_raw(raw, validate=validate) metadata_version: _Validator[_MetadataVersion] = _Validator() """:external:ref:`core-metadata-metadata-version` @@ -853,7 +929,7 @@ class Metadata: """:external:ref:`core-metadata-name` (required; validated using :func:`~packaging.utils.canonicalize_name` and its *validate* parameter)""" - version: _Validator[version_module.Version] = _Validator() + version: _Validator[Version] = _Validator() """:external:ref:`core-metadata-version` (required)""" dynamic: _Validator[list[str] | None] = _Validator( added="2.2", @@ -889,9 +965,15 @@ class Metadata: license_expression: _Validator[NormalizedLicenseExpression | None] = _Validator( added="2.4" ) - """:external:ref:`core-metadata-license-expression`""" + """:external:ref:`core-metadata-license-expression` + + .. versionadded:: 24.2 + """ license_files: _Validator[list[str] | None] = _Validator(added="2.4") - """:external:ref:`core-metadata-license-file`""" + """:external:ref:`core-metadata-license-file` + + .. versionadded:: 24.2 + """ classifiers: _Validator[list[str] | None] = _Validator(added="1.1") """:external:ref:`core-metadata-classifier`""" requires_dist: _Validator[list[requirements.Requirement] | None] = _Validator( @@ -919,9 +1001,15 @@ class Metadata: obsoletes_dist: _Validator[list[str] | None] = _Validator(added="1.2") """:external:ref:`core-metadata-obsoletes-dist`""" import_names: _Validator[list[str] | None] = _Validator(added="2.5") - """:external:ref:`core-metadata-import-name`""" + """:external:ref:`core-metadata-import-name` + + .. versionadded:: 26.0 + """ import_namespaces: _Validator[list[str] | None] = _Validator(added="2.5") - """:external:ref:`core-metadata-import-namespace`""" + """:external:ref:`core-metadata-import-namespace` + + .. versionadded:: 26.0 + """ requires: _Validator[list[str] | None] = _Validator(added="1.1") """``Requires`` (deprecated)""" provides: _Validator[list[str] | None] = _Validator(added="1.1") @@ -932,6 +1020,8 @@ class Metadata: def as_rfc822(self) -> RFC822Message: """ Return an RFC822 message with the metadata. + + .. versionadded:: 26.0 """ message = RFC822Message() self._write_metadata(message) diff --git a/server/libs/packaging/pylock.py b/server/libs/packaging/pylock.py index 84e2537..b797623 100644 --- a/server/libs/packaging/pylock.py +++ b/server/libs/packaging/pylock.py @@ -14,9 +14,14 @@ from typing import ( TypeVar, cast, ) -from urllib.parse import urlparse +from urllib.parse import unquote, urlparse -from .markers import Environment, Marker, default_environment +from .markers import ( + Environment, + Marker, + _pep440_python_full_version, + default_environment, +) from .specifiers import SpecifierSet from .tags import create_compatible_tags_selector, sys_tags from .utils import ( @@ -45,6 +50,7 @@ __all__ = [ "PackageVcs", "PackageWheel", "Pylock", + "PylockSelectError", "PylockUnsupportedVersionError", "PylockValidationError", "is_valid_pylock_path", @@ -99,7 +105,10 @@ def _get(d: Mapping[str, Any], expected_type: type[_T], key: str) -> _T | None: """Get a value from the dictionary and verify it's the expected type.""" if (value := d.get(key)) is None: return None - if not isinstance(value, expected_type): + if not isinstance(value, expected_type) or ( + # Special case: bool is a subclass of int, but TOML distinguishes the two + expected_type is int and isinstance(value, bool) + ): raise PylockValidationError( f"Unexpected type {type(value).__name__} " f"(expected {expected_type.__name__})", @@ -255,7 +264,8 @@ def _url_name(url: str | None) -> str | None: if not url: return None url_path = urlparse(url).path - return url_path.rsplit("/", 1)[-1] + # The last path component is percent-encoded, so decode it to the file name + return unquote(url_path.rsplit("/", 1)[-1]) def _validate_hashes(hashes: Mapping[str, Any]) -> Mapping[str, Any]: @@ -306,7 +316,10 @@ class PylockUnsupportedVersionError(PylockValidationError): class PylockSelectError(Exception): - """Base exception for errors raised by :meth:`Pylock.select`.""" + """Base exception for errors raised by :meth:`Pylock.select`. + + .. versionadded:: 26.1 + """ @dataclass(frozen=True, init=False) @@ -460,7 +473,10 @@ class PackageSdist: @property def filename(self) -> str: - """Get the filename of the sdist.""" + """Get the filename of the sdist. + + .. versionadded:: 26.1 + """ filename = self.name or _path_name(self.path) or _url_name(self.url) if not filename: raise PylockValidationError("Cannot determine sdist filename") @@ -737,6 +753,7 @@ class Pylock: tags: Sequence[Tag] | None = None, extras: Collection[str] | None = None, dependency_groups: Collection[str] | None = None, + prefer_sdist_predicate: Callable[[NormalizedName], bool] | None = None, ) -> Iterator[ tuple[ Package, @@ -758,11 +775,23 @@ class Pylock: The *dependency_groups* parameter represents the groups to install. If unspecified, the default groups are used. + The *prefer_sdist_predicate* parameter is called for packages with a source + distribution. If it returns ``True``, the source distribution is selected + before attempting wheel compatibility. If no source distribution is + available, wheel selection proceeds as usual without calling the predicate. + This method must be used on valid Pylock instances (i.e. one obtained from :meth:`Pylock.from_dict` or if constructed manually, after calling :meth:`Pylock.validate`). + + .. versionadded:: 26.1 + + .. versionchanged:: 26.3 + Added the *prefer_sdist_predicate* parameter. """ - compatible_tags_selector = create_compatible_tags_selector(tags or sys_tags()) + compatible_tags_selector = create_compatible_tags_selector( + tags if tags is not None else sys_tags() + ) # #. Gather the extras and dependency groups to install and set ``extras`` and # ``dependency_groups`` for marker evaluation, respectively. @@ -782,7 +811,7 @@ class Pylock: ), ), ) - env_python_full_version = ( + env_python_full_version = _pep440_python_full_version( environment["python_full_version"] if environment else default_environment()["python_full_version"] @@ -870,6 +899,15 @@ class Pylock: elif package.archive is not None: yield package, package.archive + # - Else if source preference selects an available + # :ref:`pylock-packages-sdist`: + elif ( + package.sdist is not None + and prefer_sdist_predicate is not None + and prefer_sdist_predicate(package.name) + ): + yield package, package.sdist + # - Else if there are entries for :ref:`pylock-packages-wheels`: elif package.wheels: # #. Look for the appropriate wheel file based on diff --git a/server/libs/packaging/ranges.py b/server/libs/packaging/ranges.py new file mode 100644 index 0000000..8144a65 --- /dev/null +++ b/server/libs/packaging/ranges.py @@ -0,0 +1,2067 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +"""Public :class:`VersionRange` API. + +A set-algebra view of the versions accepted by a +:class:`~packaging.specifiers.SpecifierSet`. Ranges support intersection, +union, complement, and difference; membership and filtering match the +originating specifier set; and conversion back to a +:class:`~packaging.specifiers.SpecifierSet` is available where a PEP 440 form +exists. + +.. testsetup:: + + from packaging.ranges import VersionRange + from packaging.specifiers import SpecifierSet + from packaging.version import Version +""" + +from __future__ import annotations + +import enum +import typing +from typing import ( + TYPE_CHECKING, + Any, + TypeVar, + Union, +) + +from ._ranges import ( + FULL_RANGE, + MIN_VERSION, + NEG_INF, + POS_INF, + BoundaryKind, + BoundaryVersion, + LowerBound, + UpperBound, + coerce_version, + filter_by_ranges, + intersect_ranges, + least_version_above, + matches_bounds_only, + range_is_empty, + ranges_are_prerelease_only, + trim_release, +) +from .version import Version + +if TYPE_CHECKING: + from collections.abc import Callable, Iterable, Iterator, Sequence + + from ._ranges import Interval + from .specifiers import SpecifierSet + + +__all__ = ["VersionRange"] + +T = TypeVar("T") +UnparsedVersion = Union[Version, str] +UnparsedVersionVar = TypeVar("UnparsedVersionVar", bound=UnparsedVersion) + +#: The most ``!=`` exclusion fragments (``!=V`` points or ``!=P.*`` prefixes) +#: that :meth:`VersionRange.to_specifier_set` will materialize to spell a +#: single gap or run. Every site that expands a version-number-driven chain +#: charges it against this cap, and chains that spell one gap together share +#: it (see :func:`_decompose_dev0_gap` and :func:`_encode_gap`), +#: so no gap ever materializes more than this many exclusions. Past the cap +#: the recovery returns ``None`` rather than emit the unbounded chain a range +#: such as ``==5.* | ==1000000.*`` would otherwise drive. +_MAX_EXCLUSION_RUN = 128 + + +class _SetOp(enum.Enum): + """The binary set operation ``_combine_literals`` resolves over ``===`` literals.""" + + INTERSECTION = enum.auto() + UNION = enum.auto() + DIFFERENCE = enum.auto() + + +def __dir__() -> list[str]: + return __all__ + + +# Range algebra: intersection and the empty-interval test live in the engine +# (``intersect_ranges`` / ``range_is_empty``); union and complement are only +# needed here, so they live in this module. + + +def _union_ranges( + left: Sequence[Interval], + right: Sequence[Interval], +) -> list[Interval]: + """Union two sorted, non-overlapping interval lists. + + A linear merge over the two pre-sorted inputs followed by a single + coalescing pass: adjacent or overlapping intervals collapse so the result + is itself sorted and non-overlapping. + """ + if not left: + return list(right) + if not right: + return list(left) + + merged_input: list[Interval] = [] + left_index = right_index = 0 + while left_index < len(left) and right_index < len(right): + if left[left_index][0] <= right[right_index][0]: + merged_input.append(left[left_index]) + left_index += 1 + else: + merged_input.append(right[right_index]) + right_index += 1 + merged_input.extend(left[left_index:]) + merged_input.extend(right[right_index:]) + + merged: list[Interval] = [merged_input[0]] + for lower, upper in merged_input[1:]: + prev_lower, prev_upper = merged[-1] + + if ( + prev_upper.version is None + or lower.version is None + or prev_upper.version > lower.version + ): + overlaps = True + elif prev_upper.version == lower.version: + overlaps = prev_upper.inclusive or lower.inclusive + else: + # An ordering gap may still hold no version when the two bounds + # straddle a synthetic boundary; merge across an empty gap to + # stay canonical. + gap_lower = LowerBound(prev_upper.version, not prev_upper.inclusive) + gap_upper = UpperBound(lower.version, not lower.inclusive) + overlaps = range_is_empty(gap_lower, gap_upper) + + if overlaps: + merged[-1] = (prev_lower, max(prev_upper, upper)) + else: + merged.append((lower, upper)) + + return merged + + +def _complement_ranges(ranges: Sequence[Interval]) -> list[Interval]: + """Complement a sorted, non-overlapping interval list. + + Yields the gaps between intervals plus a leading gap before the first and + a trailing gap after the last. Bound inclusivity flips so that + complement-of-complement round-trips back to the input. + """ + if not ranges: + return list(FULL_RANGE) + + result: list[Interval] = [] + prev_upper: UpperBound | None = None + + for lower, upper in ranges: + if prev_upper is None: + # Leading gap below the first interval. Every range reaching here is + # floor-canonical: ``_canonical_floor`` has already folded an + # inclusive lower at or below ``0.dev0`` into ``-inf``. So a finite + # first lower always leaves a non-empty gap down to ``-inf``, while a + # ``-inf`` lower leaves no leading gap at all. + if lower.version is not None: + gap_upper = UpperBound(lower.version, not lower.inclusive) + result.append((NEG_INF, gap_upper)) + else: + gap_lower = LowerBound(prev_upper.version, not prev_upper.inclusive) + gap_upper = UpperBound(lower.version, not lower.inclusive) + # Input intervals are canonical (sorted, disjoint, non-touching), + # so the gap between two of them always holds at least one version. + result.append((gap_lower, gap_upper)) + prev_upper = upper + + # The empty-input early return guarantees the loop ran. + assert prev_upper is not None + if prev_upper.version is not None: + gap_lower = LowerBound(prev_upper.version, not prev_upper.inclusive) + result.append((gap_lower, POS_INF)) + + return result + + +def _canonical_floor(bounds: tuple[Interval, ...]) -> tuple[Interval, ...]: + """Collapse the PEP 440 floor in a sorted interval list. + + Only the first interval can touch ``0.dev0`` (the minimum version). An + inclusive lower at or below it admits everything below, the same as + ``-inf``, so ``>=0.dev0`` becomes the one canonical full range. An + exclusive upper at or below it leaves the interval empty, so it is dropped. + """ + if not bounds: + return bounds + + lower, upper = bounds[0] + if range_is_empty(NEG_INF, upper): + return bounds[1:] + + if ( + lower.inclusive + and isinstance(lower.version, Version) + and lower.version <= MIN_VERSION + ): + return ((NEG_INF, upper), *bounds[1:]) + + return bounds + + +def _predecessor_boundary(version: Version) -> BoundaryVersion | None: + """The boundary whose least successor is *version*, or ``None``. + + Inverse of :func:`~packaging._ranges.least_version_above`. A plain version + that is exactly such a successor (``1.0a2.dev0`` sits just above + ``AFTER_POSTS(1.0a1)``) folds back to that boundary, so ``>=1.0a2.dev0`` and + ``>1.0a1`` share one form. The proposed boundary is confirmed by + round-tripping through ``least_version_above``. + """ + # Only a least successor carries a dev segment, so nothing else can fold. + if version.dev is None: + return None + + candidate: BoundaryVersion | None = None + if version.pre is not None and version.dev == 0 and version.post is None: + # 1.0a2.dev0 -> AFTER_POSTS(1.0a1) + kind, number = version.pre + if number >= 1: + candidate = BoundaryVersion( + version.__replace__(pre=(kind, number - 1), dev=None), + BoundaryKind.AFTER_POSTS, + ) + elif version.dev >= 1: + # 1.0.dev3 -> AFTER_LOCALS(1.0.dev2) + candidate = BoundaryVersion( + version.__replace__(dev=version.dev - 1), BoundaryKind.AFTER_LOCALS + ) + elif version.dev == 0 and version.post is not None: + # 1.0.post1.dev0 -> AFTER_LOCALS(1.0.post0); 1.0.post0.dev0 -> AFTER_LOCALS(1.0) + base = ( + version.__replace__(post=None, dev=None) + if version.post == 0 + else version.__replace__(post=version.post - 1, dev=None) + ) + candidate = BoundaryVersion(base, BoundaryKind.AFTER_LOCALS) + + if candidate is not None and least_version_above(candidate) == version: + return candidate + return None + + +def _canonicalize(bounds: tuple[Interval, ...]) -> tuple[Interval, ...]: + """Fold least-successor bounds to their boundary form. + + ``>=1.0a2.dev0`` and ``>1.0a1`` denote the same set, so both must reduce to + one representation for ``==`` and ``hash`` to agree. An inclusive lower or + exclusive upper sitting on a boundary's least successor becomes that + boundary; the engine's emptiness check has already dropped the synthetic + gaps such intervals would otherwise leave. + """ + result: list[Interval] = [] + for lower, upper in bounds: + new_lower, new_upper = lower, upper + + if isinstance(lower.version, Version) and lower.inclusive: + boundary = _predecessor_boundary(lower.version) + if boundary is not None: + new_lower = LowerBound(boundary, inclusive=False) + + if isinstance(upper.version, Version) and not upper.inclusive: + boundary = _predecessor_boundary(upper.version) + if boundary is not None: + new_upper = UpperBound(boundary, inclusive=True) + + result.append((new_lower, new_upper)) + return tuple(result) + + +def _struct_admits( + bounds: tuple[Interval, ...], admit_arbitrary: bool, literal: str +) -> bool: + """True when the bounds (plus arbitrary admission) admit ``literal``. + + Skips the explicit admit/reject sets, which the caller layers on top. A + non-version string matches via ``admit_arbitrary`` only on full bounds; + on narrower bounds the flag is metadata only. + """ + parsed = coerce_version(literal) + if parsed is None: + return admit_arbitrary and bounds == FULL_RANGE + + return matches_bounds_only(bounds, parsed) + + +# Repr helpers: + + +def _bound_version_str(value: BoundaryVersion | Version) -> str: + """Printout for a bound's inner value, kind-tagged for boundaries.""" + if isinstance(value, BoundaryVersion): + return f"{value.version}[{value.kind.name}]" + return str(value) + + +def _format_lower(bound: LowerBound) -> str: + if bound.version is None: + return "(-inf" + bracket = "[" if bound.inclusive else "(" + return f"{bracket}{_bound_version_str(bound.version)}" + + +def _format_upper(bound: UpperBound) -> str: + if bound.version is None: + return "+inf)" + bracket = "]" if bound.inclusive else ")" + return f"{_bound_version_str(bound.version)}{bracket}" + + +def _format_intervals(intervals: Sequence[Interval]) -> str: + """Render a sorted interval list as ``lower, upper | lower, upper``.""" + return " | ".join( + f"{_format_lower(lower)}, {_format_upper(upper)}" for lower, upper in intervals + ) + + +# ``to_specifier_set`` recovery: encode a range's interval list back into +# specifier fragments. Each helper returns ``None`` when its shape has no +# PEP 440 form. The ``keep_dev0`` argument threaded through is a spelling +# mode, not a pre-release policy: false emits a prerelease-free form (no +# synthetic ``.dev0``, so the recovered range has an empty opt-in region), +# true keeps the ``.dev0`` markers (so the range opts its bounds in). +# ``to_specifier_set`` encodes in both modes and keeps whichever round-trips. +# +# Bound and interval encoding: turn one interval's bounds into fragments. + + +def _is_dev0_version(version: Version) -> bool: + """True when version is exactly ``X[.Y]*.dev0`` (the shape `` list[str] | None: + """A prerelease-free spelling for an inclusive ``[version`` lower, or ``None``. + + Several ``[V`` lowers come from an operator whose own spelling carries no + synthetic ``.dev0``. Recovering that spelling gives the range an empty opt-in + region, so it is offered in the prerelease-free spelling mode (see + :meth:`VersionRange.to_specifier_set`). + """ + if version.dev != 0 or version.pre is not None or version.local is not None: + return None + + # ``[B.post(k).dev0`` is the lower ``>B.post(k-1)`` builds (k >= 1). + if version.post is not None: + if version.post < 1: + return None + return [f">{version.__replace__(post=version.post - 1, dev=None)}"] + + # ``[F.dev0`` is family F's base. The prefix P just below F has + # ``==P.* == [P.dev0, F.dev0)``, so ``>=P,!=P.*`` lands exactly on ``[F.dev0``. + family = trim_release(version.release) + last = family[-1] + if last < 1: + return None + + below_release = (*family[:-1], last - 1) + below = Version.from_parts(epoch=version.epoch, release=below_release) + + # At the epoch-0 floor ``==P.*`` already reaches ``0.dev0``, so the ``>=P`` + # half is redundant: ``[1.dev0, +inf)`` is plain ``!=0.*``. + if version.epoch == 0 and not any(below_release): + return [f"!={below}.*"] + + return [f">={below}", f"!={below}.*"] + + +def _epoch_floor_lower( + lower: LowerBound, upper: UpperBound +) -> tuple[Version, int, bool] | None: + """The ``E!0`` family of a lower sitting on an epoch>0 zero-family floor. + + An epoch>0 zero-family base such as ``1!0.dev0`` has no ``>=P,!=P.*`` spelling + since no version sorts below ``E!0`` within the epoch. While the interval + stays within ``==E!0.*`` it is that wildcard, trimmed by the upper and with a + leading ``.dev`` run excluded: an ``AFTER_LOCALS(E!0.dev(k))`` lower drops + ``E!0.dev0..E!0.dev(k)``, a plain inclusive ``E!0.dev0`` lower drops none. + Returns the ``E!0`` family, how many leading ``.dev`` releases to exclude, and + whether the upper sits at the family cap (so ``==E!0.*`` needs no upper), else + ``None``. + """ + version = lower.version + if isinstance(version, BoundaryVersion): + if version.kind != BoundaryKind.AFTER_LOCALS: + return None + version = version.version + if version.dev is None: + return None + excluded_devs = version.dev + 1 + elif isinstance(version, Version) and lower.inclusive: + # A plain inclusive lower only reaches the floor as ``>=E!0.dev0``; + # higher ``.dev`` would have canonicalized to an AFTER_LOCALS boundary. + if version.dev != 0: + return None + excluded_devs = 0 + else: + return None + + # Only the bare ``E!0`` floor of a non-zero epoch qualifies. + if version.epoch == 0: + return None + if version.pre is not None or version.post is not None or version.local is not None: + return None + if any(trim_release(version.release)): + return None + + # ``==E!0.*`` spans ``[E!0.dev0, E!1.dev0)``; it fits only below that cap. + next_family = Version.from_parts(epoch=version.epoch, release=(1,), dev=0) + cap = UpperBound(next_family, False) + if upper > cap: + return None + + family = Version.from_parts(epoch=version.epoch, release=(0,)) + return family, excluded_devs, upper == cap + + +def _dev_family_anchor(family: Version) -> list[str] | None: + """Prerelease-free fragments for ``[family, ..)``, or ``None`` if it has none. + + ``family`` is an ``X.dev0``. The floor gives ``[]`` (every version); a release + base its ``_clean_lower`` family-floor spelling (``!=0.*`` ...); an ``X.post0`` + base ``>=X,!=X``. A pre-release base has no prerelease-free spelling. + """ + if family <= MIN_VERSION: + return [] + clean = _clean_lower(family) + if clean is not None: + return clean + if family.pre is None and family.post == 0: + base = family.__replace__(post=None, dev=None) + return [f">={base}", f"!={base}"] + return None + + +def _encode_lower(lower: LowerBound, keep_dev0: bool) -> list[str] | None: + """Encode a lower bound as specifier fragments, or ``None``. + + ``[]`` for ``-inf``. An ``AFTER_POSTS(V)`` lower is ``>V``. An + ``AFTER_LOCALS(V)`` lower is the set ``[successor, ..)`` and emits ``>=V,!=V``, + except in the prerelease-free spelling mode (``keep_dev0`` false), where it + recovers a spelling with no synthetic ``.dev0`` when one exists: + ``>3.8.post1`` for a post release, or a dev family's anchor plus the dev run + up to V for a ``.dev`` release. + """ + lower_version = lower.version + if lower_version is None: + return [] + + if isinstance(lower_version, BoundaryVersion): + if lower_version.kind == BoundaryKind.AFTER_POSTS: + # AFTER_POSTS only ever appears as an exclusive ``>V`` lower. + return [f">{lower_version.version}"] + inner = lower_version.version + if inner <= MIN_VERSION: + # The ``(-inf, V)`` side was dropped at the floor, so the lone + # ``(AFTER_LOCALS(0.dev0), +inf)`` interval is exactly ``!=0.dev0``. + return [f"!={inner}"] + # An ``(AFTER_LOCALS(V), ..)`` lower is the set ``[successor, ..)``. In + # the prerelease-free mode, recover a spelling with no synthetic ``.dev0`` + # so the range's opt-in region stays empty. + if not keep_dev0: + if inner.dev is not None: + # A ``.dev`` V makes ``[successor, ..)`` its dev family's + # prerelease-free anchor minus the finite dev run up to ``V`` + # (e.g. ``>=1.0,!=1.0,!=1.0.post0.dev0``), carrying no synthetic + # ``.dev0``. + family = inner.__replace__(dev=0) + anchor = _dev_family_anchor(family) + if anchor is not None: + if inner.dev + 1 > _MAX_EXCLUSION_RUN: + return None + run = [ + f"!={family.__replace__(dev=d)}" for d in range(inner.dev + 1) + ] + return anchor + run + else: + # A ``.post`` release recovers its prerelease-free ``>`` spelling + # from the successor (``>3.8.post1`` for ``AFTER_LOCALS(3.8.post1)``). + successor = least_version_above(lower_version) + clean = _clean_lower(successor) if successor is not None else None + if clean is not None: + return clean + # Otherwise it is ``[V, ..)`` minus V's local family, i.e. ``>=V,!=V``. + # The prerelease-free recoveries above have already returned in that mode; + # a residual ``.dev`` V here opts pre-releases in, so this spelling round + # trips only for a range whose opt-in region wants it. + return [f">={inner}", f"!={inner}"] + + if not lower.inclusive: + return None + + # In the prerelease-free mode a ``.dev0`` lower prefers its clean spelling. + if not keep_dev0: + clean = _clean_lower(lower_version) + if clean is not None: + return clean + return [f">={lower_version}"] + + +def _encode_upper(upper: UpperBound, keep_dev0: bool) -> list[str] | None: + """Encode an upper bound as specifier fragments, or ``None``. + + ``[]`` for ``+inf``. In the prerelease-free spelling mode (``keep_dev0`` + false) the `` Version | None: + """If ``[lower, upper)`` is the ``==V.*`` shape, return ``V``.""" + if isinstance(lower.version, BoundaryVersion) or isinstance( + upper.version, BoundaryVersion + ): + return None + if lower.version is None or upper.version is None: + return None + if not lower.inclusive or upper.inclusive: + return None + if not (_is_dev0_version(lower.version) and _is_dev0_version(upper.version)): + return None + if lower.version.epoch != upper.version.epoch: + return None + + lower_release = trim_release(lower.version.release) + upper_release = trim_release(upper.version.release) + padded_length = max(len(lower_release), len(upper_release)) + assert padded_length > 0 + lower_release += (0,) * (padded_length - len(lower_release)) + upper_release += (0,) * (padded_length - len(upper_release)) + + if lower_release[:-1] != upper_release[:-1]: + return None + + # A genuine ``==V.*`` spans one family: the upper is exactly the next prefix. + # A wider span like ``[3.8.dev0, 3.14.dev0)`` shares the prefix but is not a + # single wildcard, so it falls through to the generic ``>=...,<...`` form. + if upper_release[-1] != lower_release[-1] + 1: + return None + + return lower.version.__replace__(release=lower_release, dev=None) + + +def _encode_interval( + lower: LowerBound, upper: UpperBound, keep_dev0: bool +) -> list[str] | None: + """Encode one interval as specifier fragments, or ``None``. + + Special-cases the ``==V`` singleton (``[V, AFTER_LOCALS(V)]`` for a plain + ``V``, and ``[V+local, V+local]`` for a local one) and the ``==V.*`` shape + so the fragment is one equality rather than a bound pair. + """ + # ``[V+local, V+local]`` (an inclusive local point) is the singleton ``==V+local``. + if ( + lower.version is not None + and upper.version is not None + and not isinstance(lower.version, BoundaryVersion) + and not isinstance(upper.version, BoundaryVersion) + and lower.inclusive + and upper.inclusive + and lower.version == upper.version + and lower.version.local is not None + ): + return [f"=={lower.version}"] + + # ``[V, AFTER_LOCALS(V)]`` (V without a local) is the singleton ``==V``, + # which also matches V's local family: one equality, not ``>=V,<=V``. + if ( + isinstance(lower.version, Version) + and lower.inclusive + and upper.inclusive + and isinstance(upper.version, BoundaryVersion) + and upper.version.kind == BoundaryKind.AFTER_LOCALS + and upper.version.version == lower.version + ): + return [f"=={lower.version}"] + + wildcard = _detect_equal_wildcard(lower, upper) + if wildcard is not None: + return [f"=={wildcard}.*"] + + # A ``[E!0.dev0`` lower has no prerelease-free ``>=`` spelling; within its own + # family it is ``==E!0.*`` trimmed by the upper. + floor = _epoch_floor_lower(lower, upper) if not keep_dev0 else None + if floor is not None: + family, excluded_devs, upper_at_cap = floor + if excluded_devs > _MAX_EXCLUSION_RUN: + return None + parts = [f"=={family}.*"] + parts.extend(f"!={family.__replace__(dev=d)}" for d in range(excluded_devs)) + + # ``==E!0.*`` already caps at the next family; add the upper only if tighter. + if not upper_at_cap: + upper_parts = _encode_upper(upper, keep_dev0) + if upper_parts is None: + return None + parts.extend(upper_parts) + + return parts + + lower_parts = _encode_lower(lower, keep_dev0) + if lower_parts is None: + return None + + upper_parts = _encode_upper(upper, keep_dev0) + if upper_parts is None: + return None + + return lower_parts + upper_parts + + +# Gap encoding: spell the gap between two adjacent intervals as exclusions. + + +def _detect_not_equal( + left_upper: UpperBound, right_lower: LowerBound +) -> list[Version] | None: + """If the gap between two intervals is a ``!=V`` chain, list its points. + + A plain exclusive left upper names the first excluded V directly; an inclusive + boundary left upper names it via its least successor. Adjacent exclusions + (``V`` and its immediate successors) share a single gap spanning a contiguous + dev run, so one gap can name a short chain: ``!=1.0,!=1.0.post0.dev0`` is one + gap from ``1.0`` up to ``AFTER_LOCALS(1.0.post0.dev0)``. + """ + if isinstance(left_upper.version, BoundaryVersion): + # A boundary upper is always inclusive; its least successor is the first + # excluded V (``None`` for a final AFTER_POSTS, which names no point). + first = least_version_above(left_upper.version) + if first is None: + return None + elif left_upper.version is None or left_upper.inclusive: + return None + else: + first = left_upper.version + + if not isinstance(right_lower.version, BoundaryVersion): + if ( + right_lower.version is not None + and not right_lower.inclusive + and right_lower.version == first + and first.local is not None + ): + return [first] + return None + + if right_lower.version.kind != BoundaryKind.AFTER_LOCALS: + return None + + # The right interval resumes just above the last excluded V and its locals. + last = right_lower.version.version + if first == last: + return [first] + + # Adjacent exclusions: the successor of ``first`` opens a ``.dev`` family and + # every later point is a higher ``.dev`` in that same family, so the gap is + # exactly ``first`` plus a contiguous dev run up to ``last``. Any other gap + # (e.g. ``2.3`` to ``AFTER_LOCALS(2.7)`` from complementing ``>=2.3,<=2.7``) + # spans a whole interval and fails this test. + second = least_version_above(BoundaryVersion(first, BoundaryKind.AFTER_LOCALS)) + if ( + second is not None + and second.dev is not None + and last.dev is not None + and last.dev >= second.dev + and last.__replace__(dev=second.dev) == second + ): + # ``first`` and the run spell this gap together, so they share the cap. + if last.dev - second.dev + 2 > _MAX_EXCLUSION_RUN: + return None + run = (second.__replace__(dev=d) for d in range(second.dev, last.dev + 1)) + return [first, *run] + return None + + +def _decompose_dev0_gap( + lower_trim: tuple[int, ...], + upper_trim: tuple[int, ...], + epoch: int, + budget: int = _MAX_EXCLUSION_RUN, +) -> list[Version] | None: + """Decompose the gap ``[L.dev0, U.dev0)`` into wildcard prefixes. + + ``lower_trim``/``upper_trim`` are trimmed release tuples with + ``lower_trim < upper_trim`` lexicographically. The chain sweeps at the + first differing level. The gap is undecomposable when L has trailing + components below that level (the chain cannot escape L's subtree), or when + the chain, summed across levels, would exceed ``budget`` prefixes. + """ + diff = 0 + while ( + diff < len(lower_trim) + and diff < len(upper_trim) + and lower_trim[diff] == upper_trim[diff] + ): + diff += 1 + + if len(lower_trim) > diff + 1: + return None + + common = lower_trim[:diff] + lower_val = lower_trim[diff] if len(lower_trim) > diff else 0 + upper_val = upper_trim[diff] + + span = upper_val - lower_val + if span > budget: + return None + + fragments = [ + Version.from_parts(epoch=epoch, release=(*common, segment)) + for segment in range(lower_val, upper_val) + ] + + if len(upper_trim) == diff + 1: + return fragments + + # Recurse into the next release component, charging at least one to the budget + # per level (not just the span), so a run of zero-span levels (a release with + # many trailing components) exhausts the budget and returns None instead of + # recursing past the interpreter's stack limit. + tail = _decompose_dev0_gap( + (*common, upper_val), upper_trim, epoch, budget - max(span, 1) + ) + if tail is None: + return None + return fragments + tail + + +def _encode_gap(left_upper: UpperBound, right_lower: LowerBound) -> list[str] | None: + """Encode the gap between two adjacent intervals as ``!=`` fragments. + + A point chain becomes ``!=V`` fragments and a dev0 family span becomes + ``!=P.*`` prefixes, followed by a leading dev run in the last family when + the gap ends inside it. Any other gap has no exclusion form and returns + ``None``. + """ + # Cheapest first: a plain ``!=V`` chain never pays for the budgeted + # wildcard sweep below. + points = _detect_not_equal(left_upper, right_lower) + if points is not None: + return [f"!={point}" for point in points] + + # Both wildcard shapes start at an exclusive family base ``L.dev0``. + left_v = left_upper.version + if ( + not isinstance(left_v, Version) + or left_upper.inclusive + or not _is_dev0_version(left_v) + ): + return None + + right_v = right_lower.version + if isinstance(right_v, Version) and right_lower.inclusive: + # ``[L.dev0, U.dev0)`` is a pure ``!=P.*`` chain up to U's family. + upper_dev0 = right_v + run_length = 0 + budget = _MAX_EXCLUSION_RUN + elif ( + isinstance(right_v, BoundaryVersion) + and right_v.kind == BoundaryKind.AFTER_LOCALS + and not right_lower.inclusive + ): + # ``[L.dev0, AFTER_LOCALS(U.dev(k))]`` ends inside U's family: the + # ``!=P.*`` chain, then the ``U.dev0..U.dev(k)`` run. Both spell the + # gap together, so they share one ``_MAX_EXCLUSION_RUN`` budget. + upper = right_v.version + if upper.dev is None or upper.dev + 1 > _MAX_EXCLUSION_RUN: + return None + upper_dev0 = upper.__replace__(dev=0) + run_length = upper.dev + 1 + budget = _MAX_EXCLUSION_RUN - run_length + else: + return None + + # ``U`` must be a plain release base in L's epoch, above L. + # ``_is_dev0_version`` on ``U.dev0`` rejects any pre/post/local on ``U``. + if not _is_dev0_version(upper_dev0): + return None + if left_v.epoch != upper_dev0.epoch or left_v >= upper_dev0: + return None + + prefixes = _decompose_dev0_gap( + trim_release(left_v.release), + trim_release(upper_dev0.release), + left_v.epoch, + budget, + ) + if prefixes is None: + return None + + exclusions = [f"!={prefix}.*" for prefix in prefixes] + exclusions.extend(f"!={upper_dev0.__replace__(dev=d)}" for d in range(run_length)) + return exclusions + + +def _encode_gaps(bounds: Sequence[Interval]) -> list[str] | None: + """Encode every between-interval gap as ``!=`` fragments, or ``None``. + + When each gap has an exclusion spelling, the intervals fuse into one + contiguous span (``==1.* | ==3.*`` is ``!=0.*,!=2.*,<4``): the outer + interval across all the bounds plus these exclusions. A gap with no + exclusion spelling makes the bounds a disjoint union, which no single + set expresses. + """ + exclusions: list[str] = [] + + for index in range(1, len(bounds)): + gap = _encode_gap(bounds[index - 1][1], bounds[index][0]) + if gap is None: + return None + exclusions.extend(gap) + + return exclusions + + +def _tighten_no_prereleases(bounds: tuple[Interval, ...]) -> tuple[Interval, ...]: + """Snap the range's final upper out of the pre-release band ``False`` drops. + + An exclusive upper at a final ``V`` admits the versions in ``[V.dev0, V)`` at + the bounds level, but a ``prereleases=False`` policy filters them all out, so + it accepts the same releases as ``>> r = SpecifierSet(">=1.0,<2.0").to_range() + >>> "1.5" in r + True + >>> "2.0" in r + False + >>> SpecifierSet(">=2.0,<1.0").to_range().is_empty + True + + PEP 440's ``===`` operator matches a candidate string verbatim + (case-insensitive) rather than a set of versions. Ranges built from + ``===`` specifiers still support membership, set operations, and conversion + back to a :class:`~packaging.specifiers.SpecifierSet`; matching follows the + literal-equality rule. A ``===`` literal that names a pre-release is + admitted under the default policy by both :meth:`contains` and + :meth:`filter`, since it was named outright. + + .. versionadded:: 26.3 + """ + + __slots__ = ( + "_admit", + "_admit_arbitrary", + "_bounds", + "_pre_region", + "_prereleases_configured", + "_reject", + ) + + #: The disjoint, sorted, non-overlapping interval list. + _bounds: tuple[Interval, ...] + + #: Whether this range matches non-version strings as well as versions. + #: True only by construction on ``SpecifierSet("")`` / :meth:`full`. The flag + #: rides set algebra but is inert except at full bounds (see + #: :meth:`_arbitrary_active`). An intersection or difference that shrinks + #: the bounds drops it (``full() & ~full()`` is plain empty, and + #: ``full() - r == full() & ~r``); :meth:`complement` and a union of + #: empty-bounds operands keep it, so ``~~full() == full()`` and + #: ``~full() | ~full() == ~full()``. Part of equality, since membership + #: reads it. + _admit_arbitrary: bool + + #: Case-folded strings the range admits in addition to its bounds. + #: ``===wat`` produces ``_admit = {"wat"}``. + _admit: frozenset[str] + + #: Case-folded strings the range rejects (overrides ``_admit`` and the + #: bounds). Populated by :meth:`complement` of an admit-bearing range and by + #: literal resolution in :meth:`_combine_literals`. + _reject: frozenset[str] + + #: Sorted, disjoint intervals where pre-releases are force-admitted under + #: the PEP 440 default policy (a ``None`` ``prereleases`` argument and no + #: configured override). The opt-in flows only from the pre-release-naming + #: specifiers that built the range. :meth:`_build` clips the region to the + #: bounds, so it is always a subset of them: an opt-in that overflowed its + #: own cap cannot ride a later union into versions no specifier asked for. + #: :meth:`union` and :meth:`intersection` accumulate the operands' clipped + #: regions and re-clip to the result bounds; :meth:`difference` keeps only + #: the minuend's; and :meth:`complement` drops it, since an exclusion grants + #: no opt-in. Equality keys on the clipped region, so it stays a congruence. + _pre_region: tuple[Interval, ...] + + #: Raw configured pre-release override of the originating specifier set + #: (an explicit ``True`` / ``False``, else ``None``). When set, :meth:`_build` + #: forces ``_pre_region`` empty since the policy governs globally. + #: :meth:`intersection` and :meth:`union` require it to match on both + #: operands. Part of equality. + _prereleases_configured: bool | None + + def __new__(cls, *args: object, **kwargs: object) -> VersionRange: # noqa: PYI034 + raise TypeError( + "cannot create 'VersionRange' instances directly; use " + "SpecifierSet.to_range(), VersionRange.full(), " + "VersionRange.empty(), or VersionRange.singleton() instead" + ) + + @classmethod + def _build( + cls, + bounds: tuple[Interval, ...], + admit: frozenset[str] = frozenset(), + reject: frozenset[str] = frozenset(), + admit_arbitrary: bool = False, + *, + pre_region: tuple[Interval, ...] = (), + prereleases_configured: bool | None = None, + ) -> VersionRange: + """Internal factory; bypasses :meth:`__new__`. + + Canonicalizes the bounds so equal version sets share one representation, + then drops admit literals the bounds already admit and reject literals + the bounds do not match anyway. Reject wins over admit on overlap. The + pre-release policy is set here and never reassigned afterwards; + ``pre_region`` is canonicalized like the bounds and clipped to them, + or dropped when a configured policy makes it inert. + """ + bounds = _canonicalize(bounds) + + if admit and reject: + admit = admit - reject + if admit: + admit = frozenset( + literal + for literal in admit + if not _struct_admits(bounds, admit_arbitrary, literal) + ) + if reject: + reject = frozenset( + literal + for literal in reject + if _struct_admits(bounds, admit_arbitrary, literal) + ) + + instance = object.__new__(cls) + instance._bounds = bounds + instance._admit = admit + instance._reject = reject + instance._admit_arbitrary = admit_arbitrary + instance._prereleases_configured = prereleases_configured + + # A configured policy makes the region inert, so drop it. Otherwise fold + # least-successor bounds (_from_specifier_set passes the region unfolded), + # so ``>1.0a1`` and ``>=1.0a2.dev0`` carry the same region, then clip it + # to the bounds so the opt-in never reaches past the range's own versions. + if prereleases_configured is not None or not pre_region: + instance._pre_region = () + else: + instance._pre_region = tuple( + intersect_ranges(_canonicalize(pre_region), bounds) + ) + + return instance + + def _has_literals(self) -> bool: + return bool(self._admit) or bool(self._reject) + + def _arbitrary_active(self) -> bool: + """True when ``_admit_arbitrary`` actually admits non-version strings. + + The flag rides through set algebra but only fires admission on full + bounds. Intersection and difference drop it when the bounds shrink, so + away from full bounds it survives only on empty-bounds ranges, where + it keeps ``~~full() == full()`` and union idempotent. + """ + return self._admit_arbitrary and self._bounds == FULL_RANGE + + def _is_plain(self) -> bool: + """True when membership is decided by ``_bounds`` alone, enabling the + bounds-only fast paths in :meth:`is_subset` and :meth:`is_disjoint`. + """ + return ( + not self._has_literals() + and not self._admit_arbitrary + and self._prereleases_configured is not False + ) + + def _check_policy_compat(self, other: VersionRange) -> None: + """Refuse combining ranges with different pre-release policies.""" + if not isinstance(other, VersionRange): + raise TypeError(f"expected VersionRange, got {type(other).__name__}") + if self._prereleases_configured != other._prereleases_configured: + raise ValueError( + "Cannot combine VersionRange operands with different " + f"pre-release policies: {self._prereleases_configured!r} " + f"and {other._prereleases_configured!r}" + ) + + def _merged_region(self, other: VersionRange) -> tuple[Interval, ...]: + """Union of ``self`` and ``other``'s opt-in regions. + + Used by :meth:`union` and :meth:`intersection`; :meth:`_build` clips the + merge to the result bounds. A configured operand carries an empty region, + so it contributes nothing to the merge. + """ + # Reuse an operand's canonical tuple when only one side has a region; + # an empty side contributes nothing to the union. + if not other._pre_region: + return self._pre_region + if not self._pre_region: + return other._pre_region + + # Both sides carry a region; merge them. _build re-canonicalizes and + # clips, so the plain union is fine here. + return tuple(_union_ranges(self._pre_region, other._pre_region)) + + def _with_policy( + self, *, pre_region: tuple[Interval, ...], configured: bool | None + ) -> VersionRange: + """A structural copy of this range carrying the given pre-release policy.""" + return self._build( + self._bounds, + admit=self._admit, + reject=self._reject, + admit_arbitrary=self._admit_arbitrary, + pre_region=pre_region, + prereleases_configured=configured, + ) + + @classmethod + def empty(cls, *, prereleases: bool | None = None) -> VersionRange: + """Return the empty range. No version satisfies it. + + >>> VersionRange.empty().is_empty + True + >>> "1.0" in VersionRange.empty() + False + """ + return cls._build((), prereleases_configured=prereleases) + + @classmethod + def full( + cls, *, admit_arbitrary: bool = True, prereleases: bool | None = None + ) -> VersionRange: + """Return the full range. Every PEP 440 version satisfies it. + + ``admit_arbitrary=False`` restricts the range to PEP 440 versions only + (matching the same versions as ``SpecifierSet(">=0.dev0").to_range()``); + its complement is :meth:`empty`. The flag propagates through set algebra + and is part of equality. Default ``True`` so that ``r & full()`` + preserves ``r``'s own flag structurally. + + >>> "1.0" in VersionRange.full() + True + >>> "wat" in VersionRange.full() + True + >>> "wat" in VersionRange.full(admit_arbitrary=False) + False + """ + return cls._build( + FULL_RANGE, + admit_arbitrary=admit_arbitrary, + prereleases_configured=prereleases, + ) + + @classmethod + def singleton( + cls, version: Version | str, *, prereleases: bool | None = None + ) -> VersionRange: + """Return the strict singleton range ``{version}``. + + Built as the closed interval ``[version, version]`` with strict + equality. ``Specifier("==V")`` matches ``V+local`` too, so the strict + singleton is narrower: + + >>> "1.0+local" in VersionRange.singleton("1.0") + False + >>> "1.0+local" in SpecifierSet("==1.0").to_range() + True + + :raises packaging.version.InvalidVersion: if version is a string that + does not parse as a PEP 440 version. + """ + if not isinstance(version, Version): + version = Version(version) + + lower = LowerBound(version, True) + upper = UpperBound(version, True) + + # Collapse the floor: nothing sorts below ``MIN_VERSION``, so the + # ``0.dev0`` singleton is ``(-inf, 0.dev0]`` in canonical form. + return cls._build( + _canonical_floor(((lower, upper),)), + prereleases_configured=prereleases, + ) + + def intersection(self, other: VersionRange) -> VersionRange: + """Range containing exactly the versions in both self and other. + + Both operands must share the same configured pre-release policy; + otherwise :exc:`ValueError` is raised. + + >>> a = SpecifierSet(">=1.0").to_range() + >>> b = SpecifierSet("<2.0").to_range() + >>> a.intersection(b) == SpecifierSet(">=1.0,<2.0").to_range() + True + """ + self._check_policy_compat(other) + + configured = self._prereleases_configured + new_bounds = tuple(intersect_ranges(self._bounds, other._bounds)) + new_region = self._merged_region(other) + + # An empty intersection (e.g. ``full() & ~full()``) is the empty range, + # so it drops the arbitrary flag, agreeing with difference when the + # subtrahend consumes the bounds. + combined_arb = ( + self._admit_arbitrary and other._admit_arbitrary and bool(new_bounds) + ) + + if not self._has_literals() and not other._has_literals(): + return self._build( + new_bounds, + admit_arbitrary=combined_arb, + pre_region=new_region, + prereleases_configured=configured, + ) + + return self._combine_literals( + other, + new_bounds, + op=_SetOp.INTERSECTION, + admit_arbitrary=combined_arb, + pre_region=new_region, + prereleases_configured=configured, + ) + + def union(self, other: VersionRange) -> VersionRange: + """Range containing every version in self or other. + + Both operands must share the same configured pre-release policy; + otherwise :exc:`ValueError` is raised. + + >>> a = VersionRange.singleton("1.0") + >>> b = VersionRange.singleton("2.0") + >>> "1.0" in a.union(b) and "2.0" in a.union(b) + True + >>> "1.5" in a.union(b) + False + """ + self._check_policy_compat(other) + + configured = self._prereleases_configured + new_bounds = tuple(_union_ranges(self._bounds, other._bounds)) + new_region = self._merged_region(other) + + # An empty-bounds operand (e.g. ``~full()``) carries an inert arbitrary + # flag only to keep complement an involution; it admits nothing, so it + # must not revive arbitrary admission as the union re-widens the bounds. + if new_bounds: + combined_arb = (self._admit_arbitrary and bool(self._bounds)) or ( + other._admit_arbitrary and bool(other._bounds) + ) + else: + # Nothing widened, so keeping the flags keeps ``r | r == r``. + combined_arb = self._admit_arbitrary or other._admit_arbitrary + + if not self._has_literals() and not other._has_literals(): + return self._build( + new_bounds, + admit_arbitrary=combined_arb, + pre_region=new_region, + prereleases_configured=configured, + ) + + return self._combine_literals( + other, + new_bounds, + op=_SetOp.UNION, + admit_arbitrary=combined_arb, + pre_region=new_region, + prereleases_configured=configured, + ) + + def complement(self) -> VersionRange: + """Range containing every version not in self. + + Preserves the configured pre-release policy. On the version set, double + negation holds for a range with no ``===`` literals (the arbitrary-string + flag round-trips, so ``~~full() == full()``); for ``===`` ranges + complement is one-way. The opt-in region is not restored (see below). + + The opt-in region is dropped: a complement is an exclusion, and an + exclusion expresses no pre-release preference. This is what lets + ``a & ~b`` shed ``b``'s opt-in, so an excluded ``b`` never force-admits a + pre-release into the result. Complement stays involutive on the version + set, but not on the opt-in region: ``~~r`` covers the same versions as + ``r`` yet force-admits none of its pre-releases. + + >>> r = SpecifierSet(">=1.0").to_range() + >>> "0.5" in r.complement() + True + >>> "1.5" in r.complement() + False + >>> r.complement().complement() == r + True + """ + # Complement swaps literal admission: what the range rejects, its + # complement admits. + return self._build( + tuple(_complement_ranges(self._bounds)), + admit=self._reject, + reject=self._admit, + admit_arbitrary=self._admit_arbitrary, + pre_region=(), + prereleases_configured=self._prereleases_configured, + ) + + def difference(self, other: VersionRange) -> VersionRange: + """Range containing the versions in self but not in other. + + Matches ``self & ~other`` on the version set and the opt-in region; + ``other`` acts as a bounds-only exclusion that grants no opt-in. The + arbitrary-string flag survives only when ``other`` removed no versions: + a difference that shrinks the bounds forgets it, as ``self & ~other`` + would, so no later widening union can revive it. They still part on + ``===`` literals, whose complement is one-way: a ``===`` literal stays + when ``self`` admits it and ``other`` does not. Both operands must + share the same configured pre-release policy (as :meth:`intersection` + and :meth:`union` require); otherwise :exc:`ValueError` is raised. + ``a - empty()`` returns a range equal to ``a``. + + >>> a = SpecifierSet(">=1.0").to_range() + >>> b = SpecifierSet(">=2.0").to_range() + >>> "1.5" in a.difference(b) + True + >>> "2.0" in a.difference(b) + False + >>> a.difference(VersionRange.empty()) == a + True + """ + self._check_policy_compat(other) + + # Subtracting a nothing-admitting set is a no-op; return self unchanged. + if not other._bounds and not other._admit: + return self + + # Bound complement is two-way, so subtracting other's versions is an + # intersection with its gaps. + new_bounds = tuple( + intersect_ranges(self._bounds, _complement_ranges(other._bounds)) + ) + + # Match ``self & ~other`` on the opt-in region: a complement carries no + # opt-in, so only ``self``'s region survives. ``other`` acts as a + # bounds-only exclusion. A configured ``self`` keeps no region. + new_region: tuple[Interval, ...] = () + if self._prereleases_configured is None: + new_region = self._pre_region + + # Keep self's arbitrary admission only when subtracting removed no + # versions. A difference that shrinks the bounds forgets the flag, as + # ``self & ~other`` would, so no later widening union can revive an + # admission neither operand had. + combined_arb = self._admit_arbitrary and new_bounds == self._bounds + + if not self._has_literals() and not other._has_literals(): + return self._build( + new_bounds, + admit_arbitrary=combined_arb, + pre_region=new_region, + prereleases_configured=self._prereleases_configured, + ) + + return self._combine_literals( + other, + new_bounds, + op=_SetOp.DIFFERENCE, + admit_arbitrary=combined_arb, + pre_region=new_region, + prereleases_configured=self._prereleases_configured, + ) + + def _combine_literals( + self, + other: VersionRange, + new_bounds: tuple[Interval, ...], + *, + op: _SetOp, + admit_arbitrary: bool, + pre_region: tuple[Interval, ...], + prereleases_configured: bool | None, + ) -> VersionRange: + """Resolve admit/reject for ``self`` ``op`` ``other`` over their literals.""" + admits: set[str] = set() + rejects: set[str] = set() + + # Each literal is decided independently of the others. + for literal in self._admit | self._reject | other._admit | other._reject: + self_in = self._matches_literal(literal) + other_in = other._matches_literal(literal) + + if op is _SetOp.INTERSECTION: + want = self_in and other_in + elif op is _SetOp.UNION: + want = self_in or other_in + else: + want = self_in and not other_in + + if want: + admits.add(literal) + else: + rejects.add(literal) + + return self._build( + new_bounds, + admit=frozenset(admits), + reject=frozenset(rejects), + admit_arbitrary=admit_arbitrary, + pre_region=pre_region, + prereleases_configured=prereleases_configured, + ) + + def _matches_literal(self, literal: str) -> bool: + """Whether literal (case-folded) matches this range's predicate.""" + if literal in self._reject: + return False + if literal in self._admit: + return True + + parsed = coerce_version(literal) + if parsed is None: + return self._arbitrary_active() + return matches_bounds_only(self._bounds, parsed) + + def __and__(self, other: object) -> VersionRange: + """Operator alias for :meth:`intersection`.""" + if not isinstance(other, VersionRange): + return NotImplemented + return self.intersection(other) + + def __or__(self, other: object) -> VersionRange: + """Operator alias for :meth:`union`.""" + if not isinstance(other, VersionRange): + return NotImplemented + return self.union(other) + + def __invert__(self) -> VersionRange: + """Operator alias for :meth:`complement`.""" + return self.complement() + + def __sub__(self, other: object) -> VersionRange: + """Operator alias for :meth:`difference`.""" + if not isinstance(other, VersionRange): + return NotImplemented + return self.difference(other) + + def is_subset(self, other: VersionRange) -> bool: + """Return whether every member of self is also a member of other. + + On versions and ``===`` literals this is + ``self.difference(other).is_empty``: subtracting other leaves nothing + behind. A live arbitrary admission (the flag at full bounds) is only a + subset of another live one. + + Both operands must share the same configured pre-release policy; + otherwise :exc:`ValueError` is raised. + + >>> inner = SpecifierSet(">=1.5,<1.8").to_range() + >>> outer = SpecifierSet(">=1.0,<2.0").to_range() + >>> inner.is_subset(outer) + True + >>> outer.is_subset(inner) + False + >>> VersionRange.empty().is_subset(outer) + True + """ + self._check_policy_compat(other) + + # A live arbitrary admission has non-version strings as members, which + # no bounds cover; only another live admission contains them. + if self._arbitrary_active() and not other._arbitrary_active(): + return False + + # Plain ranges: subset reduces to bounds containment, no algebra needed. + if self._is_plain() and other._is_plain(): + return not intersect_ranges(self._bounds, _complement_ranges(other._bounds)) + + # difference (unlike intersection with the one-way complement) resolves + # ``===`` literals against both operands, so it stays correct for them. + return self.difference(other).is_empty + + def is_superset(self, other: VersionRange) -> bool: + """Return whether every member of other is also a member of self. + + The mirror of :meth:`is_subset`: ``a.is_superset(b)`` is + ``b.is_subset(a)``. + + Both operands must share the same configured pre-release policy; + otherwise :exc:`ValueError` is raised. + + >>> outer = SpecifierSet(">=1.0,<2.0").to_range() + >>> outer.is_superset(SpecifierSet(">=1.5,<1.8").to_range()) + True + """ + # Type-guards a non-VersionRange other before delegating to is_subset. + self._check_policy_compat(other) + return other.is_subset(self) + + def is_disjoint(self, other: VersionRange) -> bool: + """Return whether self and other share no member. + + Equivalent to ``(self & other).is_empty``. + + Both operands must share the same configured pre-release policy; + otherwise :exc:`ValueError` is raised. + + >>> a = SpecifierSet(">=1.0,<2.0").to_range() + >>> a.is_disjoint(SpecifierSet(">=2.0,<3.0").to_range()) + True + >>> a.is_disjoint(SpecifierSet(">=1.5,<2.5").to_range()) + False + """ + self._check_policy_compat(other) + + # Plain ranges: disjointness is an empty bounds intersection. + if self._is_plain() and other._is_plain(): + return not intersect_ranges(self._bounds, other._bounds) + return self.intersection(other).is_empty + + def _same_releases(self, other: VersionRange) -> bool: + """Whether self and other admit the same non-pre-release versions. + + Used by :meth:`to_specifier_set` under a ``prereleases=False`` policy, + where pre-releases are unobservable: the symmetric difference is empty + exactly when the two ranges accept the same releases. Both operands + carry that policy, so the difference below reads emptiness through it. + """ + return self.difference(other).is_empty and other.difference(self).is_empty + + @typing.overload + def filter( + self, + iterable: Iterable[UnparsedVersionVar], + prereleases: bool | None = None, + key: None = ..., + ) -> Iterator[UnparsedVersionVar]: ... + + @typing.overload + def filter( + self, + iterable: Iterable[T], + prereleases: bool | None = None, + key: Callable[[T], UnparsedVersion] = ..., + ) -> Iterator[T]: ... + + def filter( + self, + iterable: Iterable[Any], + prereleases: bool | None = None, + key: Callable[[Any], Version | str] | None = None, + ) -> Iterator[Any]: + """Yield items from iterable whose version falls inside the range. + + With prereleases ``None`` the PEP 440 default applies: pre-releases are + buffered and only emitted if no final release in iterable is in range, + except that a pre-release inside the autodetected opt-in region, or named + outright by a ``===`` literal, is force-admitted in place (as + ``prereleases=True`` would yield it). A flushed buffer comes after + every in-place yield, so the output is not version-sorted. + + The signature mirrors + :meth:`~packaging.specifiers.SpecifierSet.filter`. + + >>> r = SpecifierSet(">=1.0,<2.0").to_range() + >>> list(r.filter(["0.9", "1.5", "2.0"])) + ['1.5'] + """ + region: tuple[Interval, ...] = () + if prereleases is None: + # The region applies only under the autodetect default; a configured + # policy governs instead (and then ``_pre_region`` is already empty). + prereleases = self._prereleases_configured + region = self._pre_region + + arbitrary_active = self._arbitrary_active() + if not self._admit and not self._reject and not arbitrary_active: + # A region spanning the whole bounds force-admits every in-bounds + # pre-release, i.e. ``prereleases=True``; take the cheaper no-buffer + # path. (Confined to this branch: the admission path orders arbitrary + # strings differently under True than under the region.) + if region and region == self._bounds: + return filter_by_ranges(self._bounds, iterable, key, True) + return filter_by_ranges(self._bounds, iterable, key, prereleases, region) + return self._filter_with_admission( + iterable, key, prereleases, arbitrary_active, region + ) + + def _filter_with_admission( + self, + iterable: Iterable[Any], + key: Callable[[Any], Version | str] | None, + prereleases: bool | None, + arbitrary_active: bool, + region: tuple[Interval, ...], + ) -> Iterator[Any]: + """Filter for ranges with admit/reject literals or live arbitrary + admission (including the universal ``SpecifierSet("")`` range).""" + admit_set = self._admit + reject_set = self._reject + + def admit(item: Any) -> tuple[bool, Version | None, bool]: # noqa: ANN401 + raw: Version | str = item if key is None else key(item) + raw_lower = str(raw).lower() + + if reject_set and raw_lower in reject_set: + return False, None, False + if admit_set and raw_lower in admit_set: + # An explicit ``===`` literal names this version outright. + return True, coerce_version(raw), True + + parsed = coerce_version(raw) + if parsed is None: + return arbitrary_active, None, False + if not matches_bounds_only(self._bounds, parsed): + return False, None, False + return True, parsed, False + + if prereleases is True: + for item in iterable: + ok, _, _ = admit(item) + if ok: + yield item + return + + if prereleases is False: + for item in iterable: + ok, parsed, _ = admit(item) + if not ok: + continue + if parsed is not None and parsed.is_prerelease: + continue + yield item + return + + # PEP 440 default: emit finals eagerly and buffer the other pre-releases, + # releasing the buffer only if no final ever matches. + all_nonfinal: list[Any] = [] + arbitrary_strings: list[Any] = [] + found_final = False + + for item in iterable: + ok, parsed, by_literal = admit(item) + if not ok: + continue + + if parsed is None: + if found_final: + yield item + else: + arbitrary_strings.append(item) + all_nonfinal.append(item) + continue + + if not parsed.is_prerelease: + if not found_final: + yield from arbitrary_strings + arbitrary_strings.clear() + found_final = True + yield item + continue + + # A pre-release is force-admitted when it is named outright by a + # ``===`` literal or falls in the opt-in region, as ``prereleases=True`` + # would yield it; otherwise the PEP 440 default buffers it. + if by_literal or (region and matches_bounds_only(region, parsed)): + yield item + continue + + if not found_final: + all_nonfinal.append(item) + + if not found_final: + yield from all_nonfinal + + @classmethod + def _from_specifier_set(cls, specifier_set: SpecifierSet) -> VersionRange: + """Build the range accepted by ``specifier_set``. + + Friend constructor for :meth:`~packaging.specifiers.SpecifierSet.to_range`. + The intersection of every specifier in the set: an empty set yields the + full range, an unsatisfiable set yields the empty range, and ``===`` + specifiers contribute literal-string admission. + """ + if not specifier_set: + result = cls.full() + elif not specifier_set._has_arbitrary: + result = cls._build( + bounds=_canonical_floor(tuple(specifier_set._get_ranges())) + ) + else: + result = cls.full() + for spec in specifier_set: + if spec.operator == "===": + operand = cls._build( + bounds=(), admit=frozenset({spec.version.lower()}) + ) + else: + operand = cls._build( + bounds=_canonical_floor(tuple(spec._to_ranges())) + ) + result = result.intersection(operand) + + # Each pre-release-naming specifier opts its own versions in; their union, + # clipped to the set's bounds by _build, is the region. Clipping refolds + # under intersection, so a set built directly equals one built by + # intersecting its specifiers one at a time. + region: list[Interval] = [] + if specifier_set._prereleases is None: # a configured policy has no region + for spec in specifier_set: + # ``===`` literals are not a range; filter force-admits them. + if spec.operator != "===" and spec.prereleases: + spec_bounds = _canonical_floor(tuple(spec._to_ranges())) + region = _union_ranges(region, spec_bounds) + + return result._with_policy( + pre_region=tuple(region), + configured=specifier_set._prereleases, + ) + + def to_specifier_set(self) -> SpecifierSet | None: + """Return a :class:`~packaging.specifiers.SpecifierSet` matching the same + versions as self, or ``None`` if no single set expresses it. + + PEP 440 has no syntax for the strict singleton ``{V}`` (an exclusive + plain-version bound), a disjoint union of two or more intervals, or a + partial pre-release opt-in region, so ranges built by set algebra often + return ``None``. A gap that takes more than ``_MAX_EXCLUSION_RUN`` + contiguous ``!=`` exclusions to spell returns ``None`` too, + rather than a pathologically long chain; reaching that cap takes either + set algebra or a specifier set that already spells the gap out with + over a hundred contiguous ``!=N.*`` exclusions. An empty range maps to + ``SpecifierSet("<0")``, unless it still carries the arbitrary-string + flag (which no set reproduces), and a full range that admits arbitrary + strings maps to ``SpecifierSet("")``. + + A range built from a :class:`~packaging.specifiers.SpecifierSet` + re-encodes, short of that exclusion cap. The result is the simplest + candidate whose own + :meth:`~packaging.specifiers.SpecifierSet.to_range` reproduces self + exactly (bounds, ``===`` literals, and the opt-in region are all part of + equality), so it filters the same versions. Two cases relax that + exactness without changing what is filtered: an empty range recovers as + the canonical empty range (same versions, none, but not self's bounds), + and under a ``prereleases=False`` policy the result need only match self's + releases, so ``(-inf, 3.14)`` recovers as the tighter ``<3.14`` rather + than ``!=3.14,<=3.14``. + + Each call encodes a handful of candidate spellings and keeps the + simplest one that verifies, where verifying means parsing the candidate + and round-tripping it through + :meth:`~packaging.specifiers.SpecifierSet.to_range`. The work grows + with the number of intervals and exclusions in the range, and the + result is not cached, so convert once and reuse the returned set rather + than converting per candidate version in a hot loop. + + >>> str(SpecifierSet(">=1.0,<2.0").to_range().to_specifier_set()) + '<2.0,>=1.0' + >>> str(SpecifierSet("==1.0").to_range().to_specifier_set()) + '==1.0' + >>> VersionRange.singleton("1.5").to_specifier_set() is None + True + """ + from .specifiers import InvalidSpecifier, SpecifierSet # noqa: PLC0415 + + configured = self._prereleases_configured + + if self._reject: + return None + if self._admit_arbitrary and self._bounds != FULL_RANGE: + return None + if self.is_empty: + # Every member-free spelling accepts the same versions (none), so the + # canonical ``<0`` stands in for all of them; a configured policy + # rides along it. + return SpecifierSet("<0", prereleases=configured) + + if not self._bounds: + # Pure ``===`` literals; only a single literal has a single-set form. + if len(self._admit) != 1: + return None + (literal,) = self._admit + bases = [f"==={literal}"] + elif self._admit: + # Bounds plus literals cannot be one set. + return None + elif self._bounds == FULL_RANGE: + bases = ["" if self._admit_arbitrary else ">=0.dev0"] + else: + # Under ``prereleases=False`` an exclusive final upper admits the same + # releases as ``=0.dev0`` floor restores a ``True`` opt-in that + # rode on a floor the clean encoding dropped (e.g. ``>=0.dev0,!=1.0``). + # It always recovers the whole bounds as the opt-in region, so it can + # only round-trip when self opts everything in. + add_floor = configured is None and self._pre_region == self._bounds + + # Keep the simplest candidate that recovers self. ``==`` compares bounds, + # literals, and the opt-in region, so a candidate that would filter + # differently, or an op-built range with no single-set form, is rejected + # below. Under ``prereleases=False`` a candidate need only match self's + # releases (policies never mix, so the excluded pre-releases are + # unobservable), which admits the tightened spellings above. + best: SpecifierSet | None = None + best_key = (0, 0) + + for base in bases: + candidates = [base] + if add_floor: + candidates.append(f"{base},>=0.dev0" if base else ">=0.dev0") + + for spec_str in candidates: + # A ``===`` literal can hold a comma (its arbitrary version + # excludes only whitespace, ``;`` and ``)``), which the set + # string splits on. Such a literal has no single specifier-set + # spelling, so drop the unparsable candidate and let the range + # fall through to ``None`` rather than raise. + try: + recovered = SpecifierSet(spec_str, prereleases=configured) + except InvalidSpecifier: + continue + # Fewest fragments, then shortest string. Rank before the round + # trip so a candidate that cannot beat the best skips the check + # (its ``==`` and, under ``False``, two ``difference`` calls). + key = (len(recovered), len(str(recovered))) + if best is not None and key >= best_key: + continue + + # Accept an exact round trip, or (under ``False``) one that only + # matches the releases the policy leaves observable. + candidate = recovered.to_range() + matches = candidate == self or ( + configured is False and self._same_releases(candidate) + ) + if matches: + best, best_key = recovered, key + + return best + + @property + def is_empty(self) -> bool: + """``True`` if no version or string satisfies this range. + + Agrees with :meth:`~packaging.specifiers.SpecifierSet.is_unsatisfiable`, + including the pre-release policy: a range whose only members are + pre-releases is empty when that policy excludes them. + + >>> SpecifierSet(">=2,<1").to_range().is_empty + True + >>> SpecifierSet(">=1,<2").to_range().is_empty + False + >>> SpecifierSet("==1.0a1", prereleases=False).to_range().is_empty + True + """ + # An arbitrary-string admission or a surviving ``===`` literal is a + # member; a literal that is a pre-release is dropped when the policy is. + if self._arbitrary_active(): + return False + + excludes_prereleases = self._prereleases_configured is False + for literal in self._admit: + if excludes_prereleases: + parsed = coerce_version(literal) + if parsed is not None and parsed.is_prerelease: + continue + return False + + if not self._bounds: + return True + + return excludes_prereleases and ranges_are_prerelease_only(self._bounds) + + def contains( + self, + item: Version | str, + prereleases: bool | None = None, + installed: bool | None = None, + ) -> bool: + """Return whether item is contained in this range. + + :param item: a version string or :class:`~packaging.version.Version`. + :param prereleases: whether to match pre-releases. ``None`` (default) + uses the range's own policy. + :param installed: when ``True``, accept a pre-release item even if the + range would not otherwise allow it. + + Unlike :meth:`filter`, this does not consult the autodetected pre-release + opt-in region; it reads only the configured policy. This mirrors + :meth:`~packaging.specifiers.SpecifierSet.contains` versus + :meth:`~packaging.specifiers.SpecifierSet.filter`. + + Unparsable strings do not match, except where the full + ``SpecifierSet`` would also match: the full range admits any string, + and a ``===`` range admits items equal to the literal + case-insensitively. + + >>> r = SpecifierSet(">=1.0,<2.0").to_range() + >>> r.contains("1.5") + True + >>> r.contains("2.0") + False + + :raises TypeError: if item is not a str or Version. + """ + if not isinstance(item, (str, Version)): + raise TypeError( + f"VersionRange.contains() expected str or Version, " + f"got {type(item).__name__}" + ) + + parsed: Version | None = item if isinstance(item, Version) else None + if installed and parsed is None: + parsed = coerce_version(item) + if installed and parsed is not None and parsed.is_prerelease: + prereleases = True + + effective_pre = ( + self._prereleases_configured if prereleases is None else prereleases + ) + + if self._admit or self._reject: + item_str = str(item).lower() + if item_str in self._reject: + return False + if item_str in self._admit: + if effective_pre is False: + literal_parsed = coerce_version(item_str) + if literal_parsed is not None and literal_parsed.is_prerelease: + return False + return True + + if not isinstance(item, Version): + if parsed is None: + parsed = coerce_version(item) + if parsed is None: + return self._arbitrary_active() + item = parsed + + if effective_pre is False and item.is_prerelease: + return False + return matches_bounds_only(self._bounds, item) + + def __contains__(self, item: Version | str) -> bool: + """Return whether item is contained in this range. + + Forwards to :meth:`contains` with default arguments. + + >>> "1.5" in SpecifierSet(">=1.0,<2.0").to_range() + True + """ + return self.contains(item) + + def __eq__(self, other: object) -> bool: + """Structural equality. + + Compares the bounds, the ``===`` admit/reject literals, the + arbitrary-string flag, the configured pre-release policy, and the + opt-in region, not just the version set. Keying on the region makes + equality a congruence (equal ranges stay equal under further operations), + so equal implies same :meth:`contains` and :meth:`filter`, but not the + converse: an empty range keeps the flag it was built with, so two empty + ranges need not be equal. + + Different specifiers for the same range fold to one canonical form: + + >>> SpecifierSet(">1.0a1").to_range() == SpecifierSet(">=1.0a2.dev0").to_range() + True + + The opt-in region is part of equality, so ``<=1.0`` (no pre-releases) and + ``<1.0.post0.dev0`` (autodetects a ``.dev`` opt-in) cover the same + versions yet compare unequal: + + >>> le, lt = SpecifierSet("<=1.0"), SpecifierSet("<1.0.post0.dev0") + >>> le.to_range() == lt.to_range() + False + + >>> r = SpecifierSet(">=1.0,<2.0").to_range() + >>> r == SpecifierSet(">=1.0,<2.0").to_range() + True + """ + if not isinstance(other, VersionRange): + return NotImplemented + return ( + self._bounds == other._bounds + and self._admit == other._admit + and self._reject == other._reject + and self._admit_arbitrary == other._admit_arbitrary + and self._prereleases_configured == other._prereleases_configured + and self._pre_region == other._pre_region + ) + + def __hash__(self) -> int: + return hash( + ( + self._bounds, + self._admit, + self._reject, + self._admit_arbitrary, + self._prereleases_configured, + self._pre_region, + ) + ) + + def __repr__(self) -> str: + """Human-readable representation for debugging. + + >>> SpecifierSet(">=1.0,<2.0").to_range() + + >>> SpecifierSet("").to_range() + + >>> SpecifierSet(">=2.0,<1.0").to_range() + + """ + # Body: the bounds and any ``===``-admitted literals. + parts: list[str] = [] + if self._bounds: + parts.append(_format_intervals(self._bounds)) + if self._admit: + parts.append("{" + ", ".join(sorted(self._admit)) + "}") + body = " | ".join(parts) if parts else "(empty)" + + # Rejected literals subtract from the body. + if self._reject: + body = f"{body} \\ {{{', '.join(sorted(self._reject))}}}" + + # Tail: the policy flags carried alongside the version set. + tail = "" + if self._admit_arbitrary: + tail += " arbitrary" + if self._prereleases_configured is not None: + tail += f" pre={self._prereleases_configured}" + if self._pre_region: + tail += f" pre-region={_format_intervals(self._pre_region)!r}" + + return f"<{self.__class__.__name__} {body!r}{tail}>" diff --git a/server/libs/packaging/requirements.py b/server/libs/packaging/requirements.py index 5892aee..adcc8ad 100644 --- a/server/libs/packaging/requirements.py +++ b/server/libs/packaging/requirements.py @@ -3,14 +3,17 @@ # for complete details. from __future__ import annotations -from typing import Iterator +from typing import TYPE_CHECKING from ._parser import parse_requirement as _parse_requirement from ._tokenizer import ParserSyntaxError from .markers import Marker, _normalize_extra_values -from .specifiers import SpecifierSet +from .specifiers import InvalidSpecifier, SpecifierSet from .utils import canonicalize_name +if TYPE_CHECKING: + from collections.abc import Iterator + __all__ = [ "InvalidRequirement", "Requirement", @@ -24,6 +27,8 @@ def __dir__() -> list[str]: class InvalidRequirement(ValueError): """ An invalid requirement was found, users should refer to PEP 508. + + .. versionadded:: 16.1 """ @@ -34,6 +39,18 @@ class Requirement: URL, and extras. Raises InvalidRequirement on a badly-formed requirement string. + .. versionadded:: 16.1 + + .. versionchanged:: 22.0 + Added equality (``__eq__``) and hashing (``__hash__``) so requirements + can be compared and stored in sets / dicts. + + .. versionchanged:: 23.2 + Equality and hashing began canonicalizing requirement names, so + requirements whose names differ only by normalization (e.g. + ``Requirement("Foo")`` vs ``Requirement("foo")``) now compare and hash + equal. + Instances are safe to serialize with :mod:`pickle`. They use a stable format so the same pickle can be loaded in future packaging releases. @@ -43,6 +60,16 @@ class Requirement: be unpickled with future releases. Backward compatibility with pickles from packaging < 26.2 is supported but may be removed in a future release. + + .. versionchanged:: 26.3 + + The dedicated pickle support introduced in 26.2 did not preserve the + specifier's explicit :attr:`~packaging.specifiers.SpecifierSet.prereleases` + override; it is now included again. + + Equality and hashing normalize requirement names, extras, and + equivalent specifiers. The string representation still preserves the + parsed name and extras spelling. """ # TODO: Can we test whether something is contained within a requirement? @@ -50,6 +77,8 @@ class Requirement: # the thing as well as the version? What about the markers? # TODO: Can we normalize the name and extra name? + __slots__ = ("extras", "marker", "name", "specifier", "url") + def __init__(self, requirement_string: str) -> None: try: parsed = _parse_requirement(requirement_string) @@ -58,8 +87,11 @@ class Requirement: self.name: str = parsed.name self.url: str | None = parsed.url or None - self.extras: set[str] = set(parsed.extras or []) - self.specifier: SpecifierSet = SpecifierSet(parsed.specifier) + self.extras: set[str] = set(parsed.extras) + try: + self.specifier: SpecifierSet = SpecifierSet(parsed.specifier) + except InvalidSpecifier as e: + raise InvalidRequirement(str(e)) from e self.marker: Marker | None = None if parsed.marker is not None: self.marker = Marker.__new__(Marker) @@ -83,29 +115,44 @@ class Requirement: if self.marker: yield f"; {self.marker}" - def __getstate__(self) -> str: - # Return the requirement string for compactness and stability. - # Re-parsed on load to reconstruct all fields. - return str(self) + def __getstate__(self) -> tuple[str, bool | None]: + # Return the requirement string for compactness and stability, paired + # with the specifier's explicit prereleases override, which is not + # captured by the string form. Re-parsed on load to reconstruct all + # other fields. + return (str(self), self.specifier._prereleases) def __setstate__(self, state: object) -> None: if isinstance(state, str): - # New format (26.2+): just the requirement string. - try: - tmp = Requirement(state) - except InvalidRequirement as exc: - raise TypeError(f"Cannot restore Requirement from {state!r}") from exc - self.name = tmp.name - self.url = tmp.url - self.extras = tmp.extras - self.specifier = tmp.specifier - self.marker = tmp.marker - return - if isinstance(state, dict): + # Format (26.2): just the requirement string. + requirement_string: str = state + prereleases: bool | None = None + elif ( + isinstance(state, tuple) + and len(state) == 2 + and isinstance(state[0], str) + and (state[1] is None or isinstance(state[1], bool)) + ): + # New format (26.3+): (requirement string, specifier prereleases). + requirement_string, prereleases = state + elif isinstance(state, dict) and state.keys() >= set(self.__slots__): # Old format (packaging <= 26.1, no __slots__): plain __dict__. - self.__dict__.update(state) + for key in self.__slots__: + setattr(self, key, state[key]) return - raise TypeError(f"Cannot restore Requirement from {state!r}") + else: + raise TypeError(f"Cannot restore Requirement from {state!r}") + + try: + tmp = Requirement(requirement_string) + except InvalidRequirement as exc: + raise TypeError(f"Cannot restore Requirement from {state!r}") from exc + self.name = tmp.name + self.url = tmp.url + self.extras = tmp.extras + self.specifier = tmp.specifier + self.specifier._prereleases = prereleases + self.marker = tmp.marker def __str__(self) -> str: return "".join(self._iter_parts(self.name)) @@ -114,15 +161,31 @@ class Requirement: return f"<{self.__class__.__name__}({str(self)!r})>" def __hash__(self) -> int: - return hash(tuple(self._iter_parts(canonicalize_name(self.name)))) + # Mirror __eq__ by hashing the canonical specifier object rather than + # its raw string. ``_iter_parts`` yields ``str(self.specifier)``, which + # is non-canonical, so trailing-zero-equivalent requirements such as + # ``foo==1.0.0`` and ``foo==1.0.0.0`` (which compare equal) would + # otherwise hash differently, breaking the hash/__eq__ invariant. + return hash( + ( + canonicalize_name(self.name), + frozenset(canonicalize_name(e) for e in self.extras), + self.specifier, + self.url, + self.marker, + ) + ) def __eq__(self, other: object) -> bool: if not isinstance(other, Requirement): return NotImplemented + # Extras must be normalized before comparison as per PEP 685. + self_extras = frozenset(canonicalize_name(e) for e in self.extras) + other_extras = frozenset(canonicalize_name(e) for e in other.extras) return ( canonicalize_name(self.name) == canonicalize_name(other.name) - and self.extras == other.extras + and self_extras == other_extras and self.specifier == other.specifier and self.url == other.url and self.marker == other.marker diff --git a/server/libs/packaging/specifiers.py b/server/libs/packaging/specifiers.py index b165dc0..a6a61af 100644 --- a/server/libs/packaging/specifiers.py +++ b/server/libs/packaging/specifiers.py @@ -11,31 +11,43 @@ from __future__ import annotations import abc -import enum -import functools -import itertools import re -import sys import typing from typing import ( TYPE_CHECKING, Any, Callable, Final, - Iterable, - Iterator, - Sequence, TypeVar, Union, ) +from ._ranges import ( + FULL_RANGE, + bounds_for_spec, + coerce_version, + filter_by_ranges, + intersect_specifier_bounds, + matches_bounds_only, + ranges_are_prerelease_only, + resolve_prereleases, + trim_release, +) from .utils import canonicalize_version -from .version import InvalidVersion, Version +from .version import Version + +if TYPE_CHECKING: + import sys + from collections.abc import Iterable, Iterator, Sequence + + if sys.version_info >= (3, 10): + from typing import TypeGuard + else: + from typing_extensions import TypeGuard + + from . import ranges + from ._ranges import Interval -if sys.version_info >= (3, 10): - from typing import TypeGuard # pragma: no cover -elif TYPE_CHECKING: - from typing_extensions import TypeGuard __all__ = [ "BaseSpecifier", @@ -65,280 +77,46 @@ def _validate_pre(pre: object, /) -> TypeGuard[bool | None]: T = TypeVar("T") UnparsedVersion = Union[Version, str] UnparsedVersionVar = TypeVar("UnparsedVersionVar", bound=UnparsedVersion) -CallableOperator = Callable[[Version, str], bool] - -# The smallest possible PEP 440 version. No valid version is less than this. -_MIN_VERSION: Final[Version] = Version("0.dev0") -def _trim_release(release: tuple[int, ...]) -> tuple[int, ...]: - """Strip trailing zeros from a release tuple for normalized comparison.""" - end = len(release) - while end > 1 and release[end - 1] == 0: - end -= 1 - return release if end == len(release) else release[:end] +# Operators whose result is just a direct Version comparison, given a parsed +# item with no local. ``<=``/``==``/``!=`` need that no-local guard because +# PEP 440 strips locals on those; ``>=`` works regardless. +_DIRECT_COMPARE_OPS: dict[str, Callable[[Version, Version], bool]] = { + ">=": Version.__ge__, + "<=": Version.__le__, + "==": Version.__eq__, + "!=": Version.__ne__, +} -class _BoundaryKind(enum.Enum): - """Where a boundary marker sits in the version ordering.""" +def _fast_match(specifier: Specifier, parsed: Version) -> bool | None: + """Match ``parsed`` against ``specifier`` without building a range. - AFTER_LOCALS = enum.auto() # after V+local, before V.post0 - AFTER_POSTS = enum.auto() # after V.postN, before next release - - -@functools.total_ordering -class _BoundaryVersion: - """A point on the version line between two real PEP 440 versions. - - Some specifier semantics imply boundaries between real versions: - ``<=1.0`` includes ``1.0+local`` and ``>1.0`` excludes - ``1.0.post0``. No real :class:`Version` falls on those boundaries, - so this class creates values that sort between the real versions - on either side. - - Two kinds exist, shown relative to a base version V:: - - V < V+local < AFTER_LOCALS(V) < V.post0 < AFTER_POSTS(V) - - ``AFTER_LOCALS`` sits after V and every V+local, but before - V.post0. Upper bound of ``<=V``, ``==V``, ``!=V``. - - ``AFTER_POSTS`` sits after every V.postN, but before the next - release segment. Lower bound of ``>V`` (final or pre-release V) - to exclude post-releases per PEP 440. + Handles ``>=``, ``<=``, ``==``, ``!=``, ``<``, ``>`` when the spec is + not a wildcard and ``parsed`` has no local. Returns ``None`` when the + range path must be used. Pre-release policy is left to the caller. """ - - __slots__ = ("_kind", "_trimmed_release", "version") - - def __init__(self, version: Version, kind: _BoundaryKind) -> None: - self.version = version - self._kind = kind - self._trimmed_release = _trim_release(version.release) - - def _is_family(self, other: Version) -> bool: - """Is ``other`` a version that this boundary sorts above?""" - v = self.version - if not ( - other.epoch == v.epoch - and _trim_release(other.release) == self._trimmed_release - and other.pre == v.pre - ): - return False - if self._kind == _BoundaryKind.AFTER_LOCALS: - # Local family: exact same public version (any local label). - return other.post == v.post and other.dev == v.dev - # Post family: same base + any post-release (or identical). - return other.dev == v.dev or other.post is not None - - def __eq__(self, other: object) -> bool: - if isinstance(other, _BoundaryVersion): - return self.version == other.version and self._kind == other._kind - return NotImplemented - - def __lt__(self, other: _BoundaryVersion | Version) -> bool: - if isinstance(other, _BoundaryVersion): - if self.version != other.version: - return self.version < other.version - return self._kind.value < other._kind.value - return not self._is_family(other) and self.version < other - - def __hash__(self) -> int: - return hash((self.version, self._kind)) - - def __repr__(self) -> str: - return f"{self.__class__.__name__}({self.version!r}, {self._kind.name})" - - -@functools.total_ordering -class _LowerBound: - """Lower bound of a version range. - - A version *v* of ``None`` means unbounded below (-inf). - At equal versions, ``[v`` sorts before ``(v`` because an inclusive - bound starts earlier. - """ - - __slots__ = ("inclusive", "version") - - def __init__(self, version: _VersionOrBoundary, inclusive: bool) -> None: - self.version = version - self.inclusive = inclusive - - def __eq__(self, other: object) -> bool: - if not isinstance(other, _LowerBound): - return NotImplemented # pragma: no cover - return self.version == other.version and self.inclusive == other.inclusive - - def __lt__(self, other: _LowerBound) -> bool: - if not isinstance(other, _LowerBound): # pragma: no cover - return NotImplemented - # -inf < anything (except -inf). - if self.version is None: - return other.version is not None - if other.version is None: - return False - if self.version != other.version: - return self.version < other.version - # [v < (v: inclusive starts earlier. - return self.inclusive and not other.inclusive - - def __hash__(self) -> int: - return hash((self.version, self.inclusive)) - - def __repr__(self) -> str: - bracket = "[" if self.inclusive else "(" - return f"<{self.__class__.__name__} {bracket}{self.version!r}>" - - -@functools.total_ordering -class _UpperBound: - """Upper bound of a version range. - - A version *v* of ``None`` means unbounded above (+inf). - At equal versions, ``v)`` sorts before ``v]`` because an exclusive - bound ends earlier. - """ - - __slots__ = ("inclusive", "version") - - def __init__(self, version: _VersionOrBoundary, inclusive: bool) -> None: - self.version = version - self.inclusive = inclusive - - def __eq__(self, other: object) -> bool: - if not isinstance(other, _UpperBound): - return NotImplemented # pragma: no cover - return self.version == other.version and self.inclusive == other.inclusive - - def __lt__(self, other: _UpperBound) -> bool: - if not isinstance(other, _UpperBound): # pragma: no cover - return NotImplemented - # Nothing < +inf (except +inf itself). - if self.version is None: - return False - if other.version is None: - return True - if self.version != other.version: - return self.version < other.version - # v) < v]: exclusive ends earlier. - return not self.inclusive and other.inclusive - - def __hash__(self) -> int: - return hash((self.version, self.inclusive)) - - def __repr__(self) -> str: - bracket = "]" if self.inclusive else ")" - return f"<{self.__class__.__name__} {self.version!r}{bracket}>" - - -if typing.TYPE_CHECKING: - _VersionOrBoundary = Union[Version, _BoundaryVersion, None] - - #: A single contiguous version range, represented as a - #: (lower bound, upper bound) pair. - _VersionRange = tuple[_LowerBound, _UpperBound] - -_NEG_INF = _LowerBound(None, False) -_POS_INF = _UpperBound(None, False) -_FULL_RANGE: tuple[_VersionRange] = ((_NEG_INF, _POS_INF),) - - -def _range_is_empty(lower: _LowerBound, upper: _UpperBound) -> bool: - """True when the range defined by *lower* and *upper* contains no versions.""" - if lower.version is None or upper.version is None: - return False - if lower.version == upper.version: - return not (lower.inclusive and upper.inclusive) - return lower.version > upper.version - - -def _intersect_ranges( - left: Sequence[_VersionRange], - right: Sequence[_VersionRange], -) -> list[_VersionRange]: - """Intersect two sorted, non-overlapping range lists (two-pointer merge).""" - result: list[_VersionRange] = [] - left_index = right_index = 0 - while left_index < len(left) and right_index < len(right): - left_lower, left_upper = left[left_index] - right_lower, right_upper = right[right_index] - - lower = max(left_lower, right_lower) - upper = min(left_upper, right_upper) - - if not _range_is_empty(lower, upper): - result.append((lower, upper)) - - # Advance whichever side has the smaller upper bound. - if left_upper < right_upper: - left_index += 1 - else: - right_index += 1 - - return result - - -def _next_prefix_dev0(version: Version) -> Version: - """Smallest version in the next prefix: 1.2 -> 1.3.dev0.""" - release = (*version.release[:-1], version.release[-1] + 1) - return Version.from_parts(epoch=version.epoch, release=release, dev=0) - - -def _base_dev0(version: Version) -> Version: - """The .dev0 of a version's base release: 1.2 -> 1.2.dev0.""" - return Version.from_parts(epoch=version.epoch, release=version.release, dev=0) - - -def _coerce_version(version: UnparsedVersion) -> Version | None: - if not isinstance(version, Version): - try: - version = Version(version) - except InvalidVersion: - return None - return version - - -def _public_version(version: Version) -> Version: - if version.local is None: - return version - return version.__replace__(local=None) - - -def _post_base(version: Version) -> Version: - """The version that *version* is a post-release of. - - 1.0.post1 -> 1.0, 1.0a1.post0 -> 1.0a1, 1.0.post0.dev1 -> 1.0. - """ - return version.__replace__(post=None, dev=None, local=None) - - -def _earliest_prerelease(version: Version) -> Version: - """Earliest pre-release of *version*. - - 1.2 -> 1.2.dev0, 1.2.post1 -> 1.2.post1.dev0. - """ - return version.__replace__(dev=0, local=None) - - -def _nearest_non_prerelease( - v: _VersionOrBoundary, -) -> Version | None: - """Smallest non-pre-release version at or above *v*, or None.""" - if v is None: + op_str, ver_str = specifier._spec + if ver_str.endswith(".*") or parsed.local is not None: return None - if isinstance(v, _BoundaryVersion): - inner = v.version - if inner.is_prerelease: - # AFTER_LOCALS(1.0a1) -> nearest non-pre is 1.0 - return inner.__replace__(pre=None, dev=None, local=None) - # AFTER_LOCALS(1.0) -> nearest non-pre is 1.0.post0 - # AFTER_LOCALS(1.0.post0) -> nearest non-pre is 1.0.post1 - k = (inner.post + 1) if inner.post is not None else 0 - return inner.__replace__(post=k, local=None) - if not v.is_prerelease: - return v - # Strip pre/dev to get the final or post-release form. - return v.__replace__(pre=None, dev=None, local=None) + + direct_compare = _DIRECT_COMPARE_OPS.get(op_str) + if direct_compare is not None: + return direct_compare(parsed, specifier._require_spec_version(ver_str)) + + if op_str in ("<", ">"): + spec_v = specifier._require_spec_version(ver_str) + # ``V`` carve out V's family (pre/dev/post); that only + # matters when parsed shares V's epoch and trimmed release. + # Otherwise a direct cmpkey comparison is correct. + if parsed.epoch != spec_v.epoch or trim_release(parsed.release) != trim_release( + spec_v.release + ): + return parsed < spec_v if op_str == "<" else parsed > spec_v + return None + + return None class InvalidSpecifier(ValueError): @@ -354,6 +132,10 @@ class InvalidSpecifier(ValueError): class BaseSpecifier(metaclass=abc.ABCMeta): + """ + Abstract base class for :class:`Specifier` and :class:`SpecifierSet`. + """ + __slots__ = () __match_args__ = ("_str",) @@ -460,7 +242,6 @@ class Specifier(BaseSpecifier): "_ranges", "_spec", "_spec_version", - "_wildcard_split", ) _specifier_regex_str = r""" @@ -559,6 +340,7 @@ class Specifier(BaseSpecifier): r"\s*" + _specifier_regex_str + r"\s*", re.VERBOSE | re.IGNORECASE ) + # Legacy unused attribute, kept for backward compatibility _operators: Final = { "~=": "compatible", "==": "equal", @@ -602,18 +384,15 @@ class Specifier(BaseSpecifier): # Specifier version cache self._spec_version: tuple[str, Version] | None = None - # Populated on first wildcard (==X.*) comparison - self._wildcard_split: tuple[list[str], int] | None = None - # Version range cache (populated by _to_ranges) - self._ranges: Sequence[_VersionRange] | None = None + self._ranges: Sequence[Interval] | None = None def _get_spec_version(self, version: str) -> Version | None: """One element cache, as only one spec Version is needed per Specifier.""" if self._spec_version is not None and self._spec_version[0] == version: return self._spec_version[1] - version_specifier = _coerce_version(version) + version_specifier = coerce_version(version) if version_specifier is None: return None @@ -630,7 +409,7 @@ class Specifier(BaseSpecifier): assert spec_version is not None return spec_version - def _to_ranges(self) -> Sequence[_VersionRange]: + def _to_ranges(self) -> Sequence[Interval]: """Convert this specifier to sorted, non-overlapping version ranges. Each standard operator maps to one or two ranges. ``===`` is @@ -643,92 +422,14 @@ class Specifier(BaseSpecifier): ver_str = self.version if op == "===": - self._ranges = _FULL_RANGE - return _FULL_RANGE - - if ver_str.endswith(".*"): - result = self._wildcard_ranges(op, ver_str) + result: Sequence[Interval] = FULL_RANGE else: - result = self._standard_ranges(op, ver_str) + version = self._require_spec_version(ver_str.removesuffix(".*")) + result = bounds_for_spec(op, ver_str, version) self._ranges = result return result - def _wildcard_ranges(self, op: str, ver_str: str) -> list[_VersionRange]: - # ==1.2.* -> [1.2.dev0, 1.3.dev0); !=1.2.* -> complement. - base = self._require_spec_version(ver_str[:-2]) - lower = _base_dev0(base) - upper = _next_prefix_dev0(base) - if op == "==": - return [(_LowerBound(lower, True), _UpperBound(upper, False))] - # != - return [ - (_NEG_INF, _UpperBound(lower, False)), - (_LowerBound(upper, True), _POS_INF), - ] - - def _standard_ranges(self, op: str, ver_str: str) -> list[_VersionRange]: - v = self._require_spec_version(ver_str) - - if op == ">=": - return [(_LowerBound(v, True), _POS_INF)] - - if op == "<=": - return [ - ( - _NEG_INF, - _UpperBound(_BoundaryVersion(v, _BoundaryKind.AFTER_LOCALS), True), - ) - ] - - if op == ">": - if v.dev is not None: - # >V.devN: dev versions have no post-releases, so the - # next real version is V.dev(N+1). - lower_ver = v.__replace__(dev=v.dev + 1, local=None) - return [(_LowerBound(lower_ver, True), _POS_INF)] - if v.post is not None: - # >V.postN: next real version is V.post(N+1).dev0. - lower_ver = v.__replace__(post=v.post + 1, dev=0, local=None) - return [(_LowerBound(lower_ver, True), _POS_INF)] - # >V (final or pre-release): skip V+local and all V.postN. - return [ - ( - _LowerBound(_BoundaryVersion(v, _BoundaryKind.AFTER_POSTS), False), - _POS_INF, - ) - ] - - if op == "<": - # bool | None: # If there is an explicit prereleases set for this, then we'll just @@ -770,7 +471,6 @@ class Specifier(BaseSpecifier): def __setstate__(self, state: object) -> None: # Always discard cached values - they will be recomputed on demand. self._spec_version = None - self._wildcard_split = None self._ranges = None if isinstance(state, tuple): @@ -893,159 +593,6 @@ class Specifier(BaseSpecifier): return self._canonical_spec == other._canonical_spec - def _get_operator(self, op: str) -> CallableOperator: - operator_callable: CallableOperator = getattr( - self, f"_compare_{self._operators[op]}" - ) - return operator_callable - - def _compare_compatible(self, prospective: Version, spec: str) -> bool: - # Compatible releases have an equivalent combination of >= and ==. That - # is that ~=2.2 is equivalent to >=2.2,==2.*. This allows us to - # implement this in terms of the other specifiers instead of - # implementing it ourselves. The only thing we need to do is construct - # the other specifiers. - - # We want everything but the last item in the version, but we want to - # ignore suffix segments. - prefix = _version_join( - list(itertools.takewhile(_is_not_suffix, _version_split(spec)))[:-1] - ) - - # Add the prefix notation to the end of our string - prefix += ".*" - - return (self._compare_greater_than_equal(prospective, spec)) and ( - self._compare_equal(prospective, prefix) - ) - - def _get_wildcard_split(self, spec: str) -> tuple[list[str], int]: - """Cached split of a wildcard spec into components and numeric length. - - >>> Specifier("==1.*")._get_wildcard_split("1.*") - (['0', '1'], 2) - >>> Specifier("==3.10.*")._get_wildcard_split("3.10.*") - (['0', '3', '10'], 3) - """ - wildcard_split = self._wildcard_split - if wildcard_split is None: - normalized = canonicalize_version(spec[:-2], strip_trailing_zero=False) - split_spec = _version_split(normalized) - wildcard_split = (split_spec, _numeric_prefix_len(split_spec)) - self._wildcard_split = wildcard_split - return wildcard_split - - def _compare_equal(self, prospective: Version, spec: str) -> bool: - # We need special logic to handle prefix matching - if spec.endswith(".*"): - split_spec, spec_numeric_len = self._get_wildcard_split(spec) - - # In the case of prefix matching we want to ignore local segment. - normalized_prospective = canonicalize_version( - _public_version(prospective), strip_trailing_zero=False - ) - # Split the prospective version out by bangs and dots, and pretend - # that there is an implicit dot in between a release segment and - # a pre-release segment. - split_prospective = _version_split(normalized_prospective) - - # 0-pad the prospective version before shortening it to get the correct - # shortened version. - padded_prospective = _left_pad(split_prospective, spec_numeric_len) - - # Shorten the prospective version to be the same length as the spec - # so that we can determine if the specifier is a prefix of the - # prospective version or not. - shortened_prospective = padded_prospective[: len(split_spec)] - - return shortened_prospective == split_spec - else: - # Convert our spec string into a Version - spec_version = self._require_spec_version(spec) - - # If the specifier does not have a local segment, then we want to - # act as if the prospective version also does not have a local - # segment. - if not spec_version.local: - prospective = _public_version(prospective) - - return prospective == spec_version - - def _compare_not_equal(self, prospective: Version, spec: str) -> bool: - return not self._compare_equal(prospective, spec) - - def _compare_less_than_equal(self, prospective: Version, spec: str) -> bool: - # NB: Local version identifiers are NOT permitted in the version - # specifier, so local version labels can be universally removed from - # the prospective version. - return _public_version(prospective) <= self._require_spec_version(spec) - - def _compare_greater_than_equal(self, prospective: Version, spec: str) -> bool: - # NB: Local version identifiers are NOT permitted in the version - # specifier, so local version labels can be universally removed from - # the prospective version. - return _public_version(prospective) >= self._require_spec_version(spec) - - def _compare_less_than(self, prospective: Version, spec_str: str) -> bool: - # Convert our spec to a Version instance, since we'll want to work with - # it as a version. - spec = self._require_spec_version(spec_str) - - # Check to see if the prospective version is less than the spec - # version. If it's not we can short circuit and just return False now - # instead of doing extra unneeded work. - if not prospective < spec: - return False - - # The spec says: "= _earliest_prerelease(spec) - ): - return False - - # If we've gotten to here, it means that prospective version is both - # less than the spec version *and* it's not a pre-release of the same - # version in the spec. - return True - - def _compare_greater_than(self, prospective: Version, spec_str: str) -> bool: - # Convert our spec to a Version instance, since we'll want to work with - # it as a version. - spec = self._require_spec_version(spec_str) - - # Check to see if the prospective version is greater than the spec - # version. If it's not we can short circuit and just return False now - # instead of doing extra unneeded work. - if not prospective > spec: - return False - - # The spec says: ">V MUST NOT allow a post-release of the specified - # version unless the specified version is itself a post-release." - if ( - not spec.is_postrelease - and prospective.is_postrelease - and _post_base(prospective) == spec - ): - return False - - # Per the spec: ">V MUST NOT match a local version of the specified - # version". A "local version of V" is any version whose public part - # equals V. So >1.0a1 must not match 1.0a1+local, but must still - # match 1.0a2+local. - if prospective.local is not None and _public_version(prospective) == spec: - return False - - # If we've gotten to here, it means that prospective version is both - # greater than the spec version *and* it's not a pre-release of the - # same version in the spec. - return True - - def _compare_arbitrary(self, prospective: Version | str, spec: str) -> bool: - return str(prospective).lower() == str(spec).lower() - def __contains__(self, item: str | Version) -> bool: """Return whether or not the item is contained in this specifier. @@ -1072,7 +619,7 @@ class Specifier(BaseSpecifier): :param item: The item to check for, which can be a version string or a - :class:`Version` instance. + :class:`~packaging.version.Version` instance. :param prereleases: Whether or not to match prereleases with this Specifier. If set to ``None`` (the default), it will follow the recommendation from @@ -1090,9 +637,38 @@ class Specifier(BaseSpecifier): False >>> Specifier(">=1.2.3").contains("1.3.0a1") True - """ - return bool(list(self.filter([item], prereleases=prereleases))) + .. versionchanged:: 26.0 + + With ``prereleases=None``, a prerelease now matches. A single + version has no alternatives, so the :pep:`440` rule to accept + prereleases when nothing else satisfies the specifier applies. + Earlier versions rejected it. An unparsable version now returns + ``False`` instead of raising :exc:`~packaging.version.InvalidVersion`. + """ + # ``===`` compares the raw string, so a Version parse here would + # be wasted. + if self._spec[0] == "===": + return bool(list(self.filter([item], prereleases=prereleases))) + + parsed = coerce_version(item) + if parsed is None: + # Standard operators never match an unparsable input. + return False + + if prereleases is None: + prereleases = resolve_prereleases(self._prereleases, self.prereleases) + + if prereleases is False and parsed.is_prerelease: + return False + + # ``_fast_match`` answers the simple operators without building a + # range; otherwise fall back to the engine's bounds membership. + match = _fast_match(self, parsed) + if match is not None: + return match + + return matches_bounds_only(self._to_ranges(), parsed) @typing.overload def filter( @@ -1119,16 +695,17 @@ class Specifier(BaseSpecifier): """Filter items in the given iterable, that match the specifier. :param iterable: - An iterable that can contain version strings and :class:`Version` instances. - The items in the iterable will be filtered according to the specifier. + An iterable that can contain version strings and + :class:`~packaging.version.Version` instances. The items in the + iterable will be filtered according to the specifier. :param prereleases: Whether or not to allow prereleases in the returned iterator. If set to ``None`` (the default), it will follow the recommendation from :pep:`440` and match prereleases if there are no other versions. :param key: A callable that takes a single argument (an item from the iterable) and - returns a version string or :class:`Version` instance to be used for - filtering. + returns a version string or :class:`~packaging.version.Version` + instance to be used for filtering. >>> list(Specifier(">=1.2.3").filter(["1.2", "1.3", "1.5a1"])) ['1.3'] @@ -1144,193 +721,48 @@ class Specifier(BaseSpecifier): ... [{"ver": "1.2"}, {"ver": "1.3"}], ... key=lambda x: x["ver"])) [{'ver': '1.3'}] + + .. versionchanged:: 26.1 + + Added the ``key`` parameter. """ - prereleases_versions = [] - found_non_prereleases = False + if prereleases is None: + prereleases = resolve_prereleases(self._prereleases, self.prereleases) - # Determine if to include prereleases by default - include_prereleases = ( - prereleases if prereleases is not None else self.prereleases - ) + if self.operator == "===": + spec_lower = self.version.lower() + matches = ( + item + for item in iterable + if str(item if key is None else key(item)).lower() == spec_lower + ) + return _apply_prereleases_filter(matches, key, prereleases) - # Get the matching operator - operator_callable = self._get_operator(self.operator) - - # Filter versions - for version in iterable: - parsed_version = _coerce_version(version if key is None else key(version)) - match = False - if parsed_version is None: - # === operator can match arbitrary (non-version) strings - if self.operator == "===" and self._compare_arbitrary( - version, self.version - ): - yield version - elif self.operator == "===": - match = self._compare_arbitrary( - version if key is None else key(version), self.version - ) - else: - match = operator_callable(parsed_version, self.version) - - if match and parsed_version is not None: - # If it's not a prerelease or prereleases are allowed, yield it directly - if not parsed_version.is_prerelease or include_prereleases: - found_non_prereleases = True - yield version - # Otherwise collect prereleases for potential later use - elif prereleases is None and self._prereleases is not False: - prereleases_versions.append(version) - - # If no non-prereleases were found and prereleases weren't - # explicitly forbidden, yield the collected prereleases - if ( - not found_non_prereleases - and prereleases is None - and self._prereleases is not False - ): - yield from prereleases_versions + return filter_by_ranges(self._to_ranges(), iterable, key, prereleases) -_prefix_regex = re.compile(r"([0-9]+)((?:a|b|c|rc)[0-9]+)") - - -def _pep440_filter_prereleases( - iterable: Iterable[Any], key: Callable[[Any], UnparsedVersion] | None +def _apply_prereleases_filter( + matches: Iterable[Any], + key: Callable[[Any], UnparsedVersion] | None, + prereleases: bool | None, ) -> Iterator[Any]: - """Filter per PEP 440: exclude prereleases unless no finals exist.""" - # Two lists used: - # * all_nonfinal to preserve order if no finals exist - # * arbitrary_strings for streaming when first final found - all_nonfinal: list[Any] = [] - arbitrary_strings: list[Any] = [] + """Apply ``prereleases=`` handling to an already-matched iterable. - found_final = False - for item in iterable: - parsed = _coerce_version(item if key is None else key(item)) - - if parsed is None: - # Arbitrary strings are always included as it is not - # possible to determine if they are prereleases, - # and they have already passed all specifiers. - if found_final: - yield item - else: - arbitrary_strings.append(item) - all_nonfinal.append(item) - continue - - if not parsed.is_prerelease: - # Final release found - flush arbitrary strings, then yield - if not found_final: - yield from arbitrary_strings - found_final = True - yield item - continue - - # Prerelease - buffer if no finals yet, otherwise skip - if not found_final: - all_nonfinal.append(item) - - # No finals found - yield all buffered items - if not found_final: - yield from all_nonfinal - - -def _version_split(version: str) -> list[str]: - """Split version into components. - - The split components are intended for version comparison. The logic does - not attempt to retain the original version string, so joining the - components back with :func:`_version_join` may not produce the original - version string. + ``None`` means PEP 440 default (buffer pre-releases until a final + appears); ``True`` yields everything; ``False`` drops pre-releases. """ - result: list[str] = [] - - epoch, _, rest = version.rpartition("!") - result.append(epoch or "0") - - for item in rest.split("."): - match = _prefix_regex.fullmatch(item) - if match: - result.extend(match.groups()) - else: - result.append(item) - return result - - -def _version_join(components: list[str]) -> str: - """Join split version components into a version string. - - This function assumes the input came from :func:`_version_split`, where the - first component must be the epoch (either empty or numeric), and all other - components numeric. - """ - epoch, *rest = components - return f"{epoch}!{'.'.join(rest)}" - - -def _is_not_suffix(segment: str) -> bool: - return not any( - segment.startswith(prefix) for prefix in ("dev", "a", "b", "rc", "post") + if prereleases is None: + return _pep440_filter_prereleases(matches, key) + if prereleases: + return iter(matches) + return ( + item + for item in matches + if (parsed := coerce_version(item if key is None else key(item))) is None + or not parsed.is_prerelease ) -def _numeric_prefix_len(split: list[str]) -> int: - """Count leading numeric components in a :func:`_version_split` result. - - >>> _numeric_prefix_len(["0", "1", "2", "a1"]) - 3 - """ - count = 0 - for segment in split: - if not segment.isdigit(): - break - count += 1 - return count - - -def _left_pad(split: list[str], target_numeric_len: int) -> list[str]: - """Pad a :func:`_version_split` result with ``"0"`` segments to reach - ``target_numeric_len`` numeric components. Suffix segments are preserved. - - >>> _left_pad(["0", "1", "a1"], 4) - ['0', '1', '0', '0', 'a1'] - """ - numeric_len = _numeric_prefix_len(split) - pad_needed = target_numeric_len - numeric_len - if pad_needed <= 0: - return split - return [*split[:numeric_len], *(["0"] * pad_needed), *split[numeric_len:]] - - -def _operator_cost(op_entry: tuple[CallableOperator, str, str]) -> int: - """Sort key for Cost Based Ordering of specifier operators in _filter_versions. - - Operators run sequentially on a shrinking candidate set, so operators that - reject the most versions should run first to minimize work for later ones. - - Tier 0: Exact equality (==, ===), likely to narrow candidates to one version - Tier 1: Range checks (>=, <=, >, <), cheap and usually reject a large portion - Tier 2: Wildcard equality (==.*) and compatible release (~=), more expensive - Tier 3: Exact !=, cheap but rarely rejects - Tier 4: Wildcard !=.*, expensive and rarely rejects - """ - _, ver, op = op_entry - if op == "==": - return 0 if not ver.endswith(".*") else 2 - if op in (">=", "<=", ">", "<"): - return 1 - if op == "~=": - return 2 - if op == "!=": - return 3 if not ver.endswith(".*") else 4 - if op == "===": - return 0 - - raise ValueError(f"Unknown operator: {op!r}") # pragma: no cover - - class SpecifierSet(BaseSpecifier): """This class abstracts handling of a set of version specifiers. @@ -1355,7 +787,7 @@ class SpecifierSet(BaseSpecifier): "_has_arbitrary", "_is_unsatisfiable", "_prereleases", - "_resolved_ops", + "_ranges", "_specs", ) @@ -1396,21 +828,18 @@ class SpecifierSet(BaseSpecifier): self._has_arbitrary = any("===" in str(s) for s in self._specs) self._canonicalized = len(self._specs) <= 1 - self._resolved_ops: list[tuple[CallableOperator, str, str]] | None = None + self._is_unsatisfiable: bool | None = None + self._ranges: Sequence[Interval] | None = None # Store our prereleases value so we can use it later to determine if # we accept prereleases or not. self._prereleases = prereleases - self._is_unsatisfiable: bool | None = None - def _canonical_specs(self) -> tuple[Specifier, ...]: """Deduplicate, sort, and cache specs for order-sensitive operations.""" if not self._canonicalized: self._specs = tuple(dict.fromkeys(sorted(self._specs, key=str))) self._canonicalized = True - self._resolved_ops = None - self._is_unsatisfiable = None return self._specs @property @@ -1446,7 +875,7 @@ class SpecifierSet(BaseSpecifier): def __setstate__(self, state: object) -> None: # Always discard cached values - they will be recomputed on demand. - self._resolved_ops = None + self._ranges = None self._is_unsatisfiable = None if isinstance(state, tuple): @@ -1557,7 +986,6 @@ class SpecifierSet(BaseSpecifier): specifier._specs = self._specs + other._specs specifier._canonicalized = len(specifier._specs) <= 1 specifier._has_arbitrary = self._has_arbitrary or other._has_arbitrary - specifier._resolved_ops = None # Combine prerelease settings: use common or non-None value if self._prereleases is None or self._prereleases == other._prereleases: @@ -1611,27 +1039,17 @@ class SpecifierSet(BaseSpecifier): """ return iter(self._specs) - def _get_ranges(self) -> Sequence[_VersionRange]: - """Intersect all specifiers into a single list of version ranges. + def _get_ranges(self) -> Sequence[Interval]: + """Intersect all specifiers into a single sequence of version ranges. - Returns an empty list when unsatisfiable. ``===`` specs are - modeled as full range; string matching is checked separately - by :meth:`_check_arbitrary_unsatisfiable`. + Empty when unsatisfiable. Callers must ensure ``self._specs`` + is non-empty. """ - specs = self._specs + if self._ranges is not None: + return self._ranges - result: Sequence[_VersionRange] | None = None - for s in specs: - if result is None: - result = s._to_ranges() - else: - result = _intersect_ranges(result, s._to_ranges()) - if not result: - break - - if result is None: # pragma: no cover - raise RuntimeError("_get_ranges called with no specs") - return result + self._ranges = intersect_specifier_bounds(s._to_ranges() for s in self._specs) + return self._ranges def is_unsatisfiable(self) -> bool: """Check whether this specifier set can never be satisfied. @@ -1646,6 +1064,8 @@ class SpecifierSet(BaseSpecifier): False >>> SpecifierSet("==1.0,!=1.0").is_unsatisfiable() True + + .. versionadded:: 26.1 """ cached = self._is_unsatisfiable if cached is not None: @@ -1661,24 +1081,11 @@ class SpecifierSet(BaseSpecifier): result = self._check_arbitrary_unsatisfiable() if not result and self.prereleases is False: - result = self._check_prerelease_only_ranges() + result = ranges_are_prerelease_only(self._get_ranges()) self._is_unsatisfiable = result return result - def _check_prerelease_only_ranges(self) -> bool: - """With prereleases=False, check if every range contains only - pre-release versions (which would be excluded from matching).""" - for lower, upper in self._get_ranges(): - nearest = _nearest_non_prerelease(lower.version) - if nearest is None: - return False - if upper.version is None or nearest < upper.version: - return False - if nearest == upper.version and upper.inclusive: - return False - return True - def _check_arbitrary_unsatisfiable(self) -> bool: """Check === (arbitrary equality) specs for unsatisfiability. @@ -1697,7 +1104,7 @@ class SpecifierSet(BaseSpecifier): # The sole candidate is the === version string. Check whether # it can satisfy every standard spec. - candidate = _coerce_version(arbitrary[0].version) + candidate = coerce_version(arbitrary[0].version) # With prereleases=False, a prerelease candidate is excluded # by contains() before the === string check even runs. @@ -1718,6 +1125,85 @@ class SpecifierSet(BaseSpecifier): return not all(s.contains(candidate) for s in standard) + def to_range(self) -> ranges.VersionRange: + """Return the :class:`~packaging.ranges.VersionRange` this set accepts. + + An empty set yields the full range; an unsatisfiable set yields the + empty range. ``===`` specifiers contribute literal-string admission. + + >>> SpecifierSet(">=1.0,<2.0").to_range() + + + .. versionadded:: 26.3 + """ + from .ranges import VersionRange # noqa: PLC0415 + + return VersionRange._from_specifier_set(self) + + def _check_relation_operand(self, other: object) -> None: + if not isinstance(other, SpecifierSet): + raise TypeError("expected a SpecifierSet") + if self._has_arbitrary or other._has_arbitrary: + raise ValueError("set relations do not support === specifiers") + + def is_subset(self, other: SpecifierSet) -> bool: + """Return whether every version matching this set also matches other. + + :raises ValueError: + If either set uses ``===`` specifiers, or the two sets were + given different ``prereleases`` arguments (unset on one side + counts as different). + :raises TypeError: + If other is not a :class:`SpecifierSet`. + + >>> SpecifierSet(">=3.12,<3.13").is_subset(SpecifierSet(">=3.12")) + True + >>> SpecifierSet(">=3.12").is_subset(SpecifierSet(">=3.12,<3.13")) + False + + .. versionadded:: 26.3 + """ + self._check_relation_operand(other) + return self.to_range().is_subset(other.to_range()) + + def is_superset(self, other: SpecifierSet) -> bool: + """Return whether every version matching other also matches this set. + + :raises ValueError: + If either set uses ``===`` specifiers, or the two sets were + given different ``prereleases`` arguments (unset on one side + counts as different). + :raises TypeError: + If other is not a :class:`SpecifierSet`. + + >>> SpecifierSet(">=3.12").is_superset(SpecifierSet(">=3.12,<3.13")) + True + + .. versionadded:: 26.3 + """ + self._check_relation_operand(other) + return self.to_range().is_superset(other.to_range()) + + def is_disjoint(self, other: SpecifierSet) -> bool: + """Return whether this set and other share no matching versions. + + :raises ValueError: + If either set uses ``===`` specifiers, or the two sets were + given different ``prereleases`` arguments (unset on one side + counts as different). + :raises TypeError: + If other is not a :class:`SpecifierSet`. + + >>> SpecifierSet("<3.12").is_disjoint(SpecifierSet(">=3.12")) + True + >>> SpecifierSet("<3.12").is_disjoint(SpecifierSet(">=3.11")) + False + + .. versionadded:: 26.3 + """ + self._check_relation_operand(other) + return self.to_range().is_disjoint(other.to_range()) + def __contains__(self, item: UnparsedVersion) -> bool: """Return whether or not the item is contained in this specifier. @@ -1749,7 +1235,7 @@ class SpecifierSet(BaseSpecifier): :param item: The item to check for, which can be a version string or a - :class:`Version` instance. + :class:`~packaging.version.Version` instance. :param prereleases: Whether or not to match prereleases with this SpecifierSet. If set to ``None`` (the default), it will follow the recommendation from :pep:`440` @@ -1770,8 +1256,16 @@ class SpecifierSet(BaseSpecifier): False >>> SpecifierSet(">=1.0.0,!=1.0.1").contains("1.3.0a1", prereleases=True) True + + .. versionchanged:: 26.0 + + With ``prereleases=None``, a prerelease now matches. A single + version has no alternatives, so the :pep:`440` rule to accept + prereleases when nothing else satisfies the specifiers applies. + Earlier versions rejected it. An unparsable version now returns + ``False`` instead of raising :exc:`~packaging.version.InvalidVersion`. """ - version = _coerce_version(item) + version = coerce_version(item) if version is not None and installed and version.is_prerelease: prereleases = True @@ -1782,6 +1276,41 @@ class SpecifierSet(BaseSpecifier): check_item = item else: check_item = version + + # Fast path: a parseable, local-free version against a rangelike set. + # A local on ``version`` needs PEP 440 stripping that the range path + # applies. + if ( + version is not None + and not self._has_arbitrary + and version.local is None + and self._specs + ): + if version.is_prerelease and ( + prereleases is False + or (prereleases is None and self._prereleases is False) + ): + return False + + bounds = self._ranges + if bounds is None: + # Per-spec ``_fast_match`` answers a set of simple specifiers + # without folding anything. If a spec needs the range path, + # fold the intersected bounds once and cache them so repeated + # checks on the same set stay cheap. + for spec in self._specs: + match = _fast_match(spec, version) + if match is None: + break + if not match: + return False + else: + return True + + bounds = self._ranges = self._get_ranges() + + return matches_bounds_only(bounds, version) + return bool(list(self.filter([check_item], prereleases=prereleases))) @typing.overload @@ -1809,16 +1338,17 @@ class SpecifierSet(BaseSpecifier): """Filter items in the given iterable, that match the specifiers in this set. :param iterable: - An iterable that can contain version strings and :class:`Version` instances. - The items in the iterable will be filtered according to the specifier. + An iterable that can contain version strings and + :class:`~packaging.version.Version` instances. The items in the + iterable will be filtered according to the specifier. :param prereleases: Whether or not to allow prereleases in the returned iterator. If set to ``None`` (the default), it will follow the recommendation from :pep:`440` and match prereleases if there are no other versions. :param key: A callable that takes a single argument (an item from the iterable) and - returns a version string or :class:`Version` instance to be used for - filtering. + returns a version string or :class:`~packaging.version.Version` + instance to be used for filtering. >>> list(SpecifierSet(">=1.2.3").filter(["1.2", "1.3", "1.5a1"])) ['1.3'] @@ -1846,6 +1376,15 @@ class SpecifierSet(BaseSpecifier): ['1.3', '1.5a1'] >>> list(SpecifierSet("").filter(["1.3", "1.5a1"], prereleases=True)) ['1.3', '1.5a1'] + + .. versionchanged:: 26.0 + + Prerelease filtering now follows the PEP 440 recommendation of + yielding prereleases only when no final release is present. + + .. versionchanged:: 26.1 + + Added the ``key`` parameter. """ # Determine if we're forcing a prerelease or not, if we're not forcing # one for this particular filter call, then we'll use whatever the @@ -1853,91 +1392,66 @@ class SpecifierSet(BaseSpecifier): if prereleases is None and self.prereleases is not None: prereleases = self.prereleases - # Filter versions that match all specifiers using Cost Based Ordering. if self._specs: - # When prereleases is None, we need to let all versions through - # the individual filters, then decide about prereleases at the end - # based on whether any non-prereleases matched ALL specs. - - # Fast path: single specifier, delegate directly. - if len(self._specs) == 1: - filtered = self._specs[0].filter( - iterable, - prereleases=True if prereleases is None else prereleases, - key=key, - ) - else: - filtered = self._filter_versions( - iterable, - key, - prereleases=True if prereleases is None else prereleases, + if self._has_arbitrary: + # Slow path for === + specs = self._specs + matches = ( + item + for item in iterable + if all( + s.contains(item if key is None else key(item), prereleases=True) + for s in specs + ) ) + return _apply_prereleases_filter(matches, key, prereleases) - if prereleases is not None: - return filtered + ranges = self._ranges + if ranges is None: + ranges = self._get_ranges() + return filter_by_ranges(ranges, iterable, key, prereleases) - return _pep440_filter_prereleases(filtered, key) + # Empty SpecifierSet. + return _apply_prereleases_filter(iterable, key, prereleases) - # Handle Empty SpecifierSet. - if prereleases is True: - return iter(iterable) - if prereleases is False: - return ( - item - for item in iterable - if ( - (version := _coerce_version(item if key is None else key(item))) - is None - or not version.is_prerelease - ) - ) +def _pep440_filter_prereleases( + iterable: Iterable[Any], key: Callable[[Any], UnparsedVersion] | None +) -> Iterator[Any]: + """Filter per PEP 440: exclude prereleases unless no finals exist.""" + # Two lists used: + # * all_nonfinal to preserve order if no finals exist + # * arbitrary_strings for streaming when first final found + all_nonfinal: list[Any] = [] + arbitrary_strings: list[Any] = [] - # PEP 440: exclude prereleases unless no final releases matched - return _pep440_filter_prereleases(iterable, key) + found_final = False + for item in iterable: + parsed = coerce_version(item if key is None else key(item)) - def _filter_versions( - self, - iterable: Iterable[Any], - key: Callable[[Any], UnparsedVersion] | None, - prereleases: bool | None = None, - ) -> Iterator[Any]: - """Filter versions against all specifiers in a single pass. - - Uses Cost Based Ordering: specifiers are sorted by _operator_cost so - that cheap range operators reject versions early, avoiding expensive - wildcard or compatible operators on versions that would have been - rejected anyway. - """ - # Pre-resolve operators and sort (cached after first call). - if self._resolved_ops is None: - self._resolved_ops = sorted( - ( - (spec._get_operator(spec.operator), spec.version, spec.operator) - for spec in self._specs - ), - key=_operator_cost, - ) - ops = self._resolved_ops - exclude_prereleases = prereleases is False - - for item in iterable: - parsed = _coerce_version(item if key is None else key(item)) - - if parsed is None: - # Only === can match non-parseable versions. - if all( - op == "===" and str(item).lower() == ver.lower() - for _, ver, op in ops - ): - yield item - elif exclude_prereleases and parsed.is_prerelease: - pass - elif all( - str(item if key is None else key(item)).lower() == ver.lower() - if op == "===" - else op_fn(parsed, ver) - for op_fn, ver, op in ops - ): - # Short-circuits on the first failing operator. + if parsed is None: + # Arbitrary strings are always included as it is not + # possible to determine if they are prereleases, + # and they have already passed all specifiers. + if found_final: yield item + else: + arbitrary_strings.append(item) + all_nonfinal.append(item) + continue + + if not parsed.is_prerelease: + # Final release found - flush arbitrary strings, then yield + if not found_final: + yield from arbitrary_strings + found_final = True + yield item + continue + + # Prerelease - buffer if no finals yet, otherwise skip + if not found_final: + all_nonfinal.append(item) + + # No finals found - yield all buffered items + if not found_final: + yield from all_nonfinal diff --git a/server/libs/packaging/tags.py b/server/libs/packaging/tags.py index 9980ab3..dd1ea91 100644 --- a/server/libs/packaging/tags.py +++ b/server/libs/packaging/tags.py @@ -12,13 +12,10 @@ import struct import subprocess import sys import sysconfig +from collections.abc import Iterable, Iterator, Sequence from importlib.machinery import EXTENSION_SUFFIXES from typing import ( TYPE_CHECKING, - Iterable, - Iterator, - Sequence, - Tuple, TypeVar, cast, ) @@ -26,15 +23,17 @@ from typing import ( from . import _manylinux, _musllinux if TYPE_CHECKING: - from collections.abc import Callable, Iterable - from typing import AbstractSet + from collections.abc import Callable + from collections.abc import Set as AbstractSet __all__ = [ "INTERPRETER_SHORT_NAMES", "AppleVersion", + "InvalidTag", "PythonVersion", "Tag", + "TooManyTagsError", "UnsortedTagsError", "android_platforms", "compatible_tags", @@ -47,6 +46,7 @@ __all__ = [ "mac_platforms", "parse_tag", "platform_tags", + "pure_python_tags", "sys_tags", ] @@ -58,7 +58,18 @@ def __dir__() -> list[str]: logger = logging.getLogger(__name__) PythonVersion = Sequence[int] -AppleVersion = Tuple[int, int] +""" +A sequence of integers describing a Python version, e.g. ``(3, 13)``. + +.. versionadded:: 20.0 +""" + +AppleVersion = tuple[int, int] +""" +A ``(major, minor)`` integer pair describing an Apple OS version. + +.. versionadded:: 24.2 +""" _T = TypeVar("_T") INTERPRETER_SHORT_NAMES: dict[str, str] = { @@ -82,6 +93,25 @@ _32_BIT_INTERPRETER = _compute_32_bit_interpreter() class UnsortedTagsError(ValueError): """ Raised when a tag component is not in sorted order per PEP 425. + + .. versionadded:: 26.1 + """ + + +class InvalidTag(ValueError): + """ + Raised when an interpreter component is not an identifier, a tag component + is empty, or a tag does not have exactly three components. + + .. versionadded:: 26.3 + """ + + +class TooManyTagsError(ValueError): + """ + Raised when a compressed tag set exceeds the configured limit. + + .. versionadded:: 26.3 """ @@ -200,7 +230,9 @@ class Tag: raise TypeError(f"Cannot restore Tag from {state!r}") -def parse_tag(tag: str, *, validate_order: bool = False) -> frozenset[Tag]: +def parse_tag( + tag: str, *, validate_order: bool = False, limit: int | None = None +) -> frozenset[Tag]: """ Parses the provided tag (e.g. `py3-none-any`) into a frozenset of :class:`Tag` instances. @@ -212,29 +244,70 @@ def parse_tag(tag: str, *, validate_order: bool = False) -> frozenset[Tag]: If **validate_order** is true, compressed tag set components are checked to be in sorted order as required by PEP 425. + If **limit** is not ``None``, the compressed tag set can generate at most + that many tags. + :param str tag: The tag to parse, e.g. ``"py3-none-any"``. :param bool validate_order: Check whether compressed tag set components are in sorted order. + :param int | None limit: The maximum number of tags to parse. :raises UnsortedTagsError: If **validate_order** is true and any compressed tag set component is not in sorted order. + :raises InvalidTag: If the interpreter field is not an identifier; if the + interpreter, ABI, or platform field (or any member of a compressed tag + set) is empty; or if the tag does not have exactly three components. + :raises TooManyTagsError: If **limit** is not ``None`` and the compressed tag + set would generate more than **limit** tags. + :raises ValueError: If **limit** is negative. .. versionadded:: 26.1 The *validate_order* parameter. + + .. versionadded:: 26.3 + Raises :class:`InvalidTag` when an interpreter component is not an + identifier, a tag component is empty, or a tag does not have exactly + three components. + Added the *limit* parameter. Raises :class:`TooManyTagsError` if the compressed + tag set would generate more than *limit* tags. """ - tags = set() - interpreters, abis, platforms = tag.split("-") - if validate_order: - for component in (interpreters, abis, platforms): - parts = component.split(".") - if parts != sorted(parts): - raise UnsortedTagsError( - f"Tag component {component!r} is not in sorted order per PEP 425" - ) - for interpreter in interpreters.split("."): - for abi in abis.split("."): - for platform_ in platforms.split("."): - tags.add(Tag(interpreter, abi, platform_)) - return frozenset(tags) + + if limit is not None and limit < 0: + raise ValueError("limit must be non-negative") + + component_parts = [component.split(".") for component in tag.split("-")] + for parts in component_parts: + if "" in parts: + component = ".".join(parts) + raise InvalidTag(f"Tag {tag!r} has an empty component: {component!r}") + if validate_order and parts != sorted(parts): + component = ".".join(parts) + raise UnsortedTagsError( + f"Tag component {component!r} is not in sorted order per PEP 425" + ) + + tag_count = 1 + for parts in component_parts: + tag_count *= len(parts) + + if limit is not None and tag_count > limit: + raise TooManyTagsError( + f"Compressed tag set would generate {tag_count} tags, exceeding " + f"limit {limit}" + ) + + try: + interpreters, abis, platforms = component_parts + except ValueError as exc: + raise InvalidTag(f"Tag {tag!r} must have exactly three components") from exc + for interpreter in interpreters: + if not interpreter.isidentifier(): + raise InvalidTag(f"Tag {tag!r} has an invalid interpreter: {interpreter!r}") + return frozenset( + Tag(interpreter, abi, platform_) + for interpreter in interpreters + for abi in abis + for platform_ in platforms + ) def _get_config_var(name: str, warn: bool = False) -> int | str | None: @@ -355,6 +428,8 @@ def cpython_tags( :param Iterable platforms: Iterable of compatible platforms. Defaults to the platforms compatible with the current system. :param bool warn: Whether warnings should be logged. Defaults to ``False``. + + .. versionadded:: 20.0 """ if not python_version: python_version = sys.version_info[:2] @@ -364,8 +439,10 @@ def cpython_tags( if abis is None: abis = _cpython_abis(python_version, warn) if len(python_version) > 1 else [] abis = list(abis) - # 'abi3' and 'none' are explicitly handled later. - for explicit_abi in ("abi3", "none"): + threading = _is_threaded_cpython(abis) + # Stable ABIs and 'none' are explicitly handled later. + explicit_abis = ("abi3", "abi3t", "none") if threading else ("abi3", "none") + for explicit_abi in explicit_abis: try: abis.remove(explicit_abi) except ValueError: # noqa: PERF203 @@ -376,10 +453,8 @@ def cpython_tags( for platform_ in platforms: yield Tag(interpreter, abi, platform_) - threading = _is_threaded_cpython(abis) use_abi3 = _abi3_applies(python_version, threading) use_abi3t = _abi3t_applies(python_version, threading) - if use_abi3: yield from (Tag(interpreter, "abi3", platform_) for platform_ in platforms) if use_abi3t: @@ -417,7 +492,7 @@ def _generic_abi() -> list[str]: # => graalpy_38_native ext_suffix = _get_config_var("EXT_SUFFIX", warn=True) - if not isinstance(ext_suffix, str) or ext_suffix[0] != ".": + if not isinstance(ext_suffix, str) or not ext_suffix.startswith("."): raise SystemError("invalid sysconfig.get_config_var('EXT_SUFFIX')") parts = ext_suffix.split(".") if len(parts) < 3: @@ -426,7 +501,10 @@ def _generic_abi() -> list[str]: soabi = parts[1] if soabi.startswith("cpython"): # non-windows - abi = "cp" + soabi.split("-")[1] + cpython_parts = soabi.split("-") + if len(cpython_parts) < 2 or not cpython_parts[1]: + raise SystemError("invalid sysconfig.get_config_var('EXT_SUFFIX')") + abi = "cp" + cpython_parts[1] elif soabi.startswith("cp"): # windows abi = soabi.split("-")[0] @@ -469,6 +547,8 @@ def generic_tags( :param Iterable platforms: Iterable of compatible platforms. Defaults to the platforms compatible with the current system. :param bool warn: Whether warnings should be logged. Defaults to ``False``. + + .. versionadded:: 20.0 """ if not interpreter: interp_name = interpreter_name() @@ -498,6 +578,30 @@ def _py_interpreter_range(py_version: PythonVersion) -> Iterator[str]: yield f"py{_version_nodot((py_version[0], minor))}" +def pure_python_tags( + python_version: PythonVersion | None = None, +) -> Iterator[Tag]: + """ + Yields the pure-Python tags compatible with ``python_version``. + + The tags use the ``"none"`` ABI and ``"any"`` platform, so their + generation does not depend on the running platform. + + .. versionadded:: 26.3 + + :param Sequence python_version: A one- or two-item sequence representing the + compatible version of Python. Defaults to + ``sys.version_info[:2]``. + :raises ValueError: If ``python_version`` is an empty sequence. + """ + if python_version is None: + python_version = sys.version_info[:2] + elif not python_version: + raise ValueError("python_version must contain at least one item") + for version in _py_interpreter_range(python_version): + yield Tag(version, "none", "any") + + def compatible_tags( python_version: PythonVersion | None = None, interpreter: str | None = None, @@ -520,6 +624,8 @@ def compatible_tags( ``"cp38"``. Defaults to the current interpreter. :param Iterable platforms: Iterable of compatible platforms. Defaults to the platforms compatible with the current system. + + .. versionadded:: 20.0 """ if not python_version: python_version = sys.version_info[:2] @@ -529,8 +635,7 @@ def compatible_tags( yield Tag(version, "none", platform_) if interpreter: yield Tag(interpreter, "none", "any") - for version in _py_interpreter_range(python_version): - yield Tag(version, "none", "any") + yield from pure_python_tags(python_version) def _mac_arch(arch: str, is_32bit: bool = _32_BIT_INTERPRETER) -> str: @@ -548,12 +653,12 @@ def _mac_binary_formats(version: AppleVersion, cpu_arch: str) -> list[str]: if cpu_arch == "x86_64": if version < (10, 4): return [] - formats.extend(["intel", "fat64", "fat32"]) + formats.extend(["intel", "fat64", "fat3"]) elif cpu_arch == "i386": if version < (10, 4): return [] - formats.extend(["intel", "fat32", "fat"]) + formats.extend(["intel", "fat3", "fat"]) elif cpu_arch == "ppc64": # TODO: Need to care about 32-bit PPC for ppc64 through 10.2? @@ -564,7 +669,7 @@ def _mac_binary_formats(version: AppleVersion, cpu_arch: str) -> list[str]: elif cpu_arch == "ppc": if version > (10, 6): return [] - formats.extend(["fat32", "fat"]) + formats.extend(["fat3", "fat"]) if cpu_arch in {"arm64", "x86_64"}: formats.append("universal2") @@ -598,29 +703,33 @@ def mac_platforms( - On Windows, platform compatibility is statically specified - On Linux, code must be run on the system itself to determine compatibility - """ - version_str, _, cpu_arch = platform.mac_ver() - if version is None: - version = cast("AppleVersion", tuple(map(int, version_str.split(".")[:2]))) - if version == (10, 16): - # When built against an older macOS SDK, Python will report macOS 10.16 - # instead of the real version. - version_str = subprocess.run( - [ - sys.executable, - "-sS", - "-c", - "import platform; print(platform.mac_ver()[0])", - ], - check=True, - env={"SYSTEM_VERSION_COMPAT": "0"}, - stdout=subprocess.PIPE, - text=True, - ).stdout - version = cast("AppleVersion", tuple(map(int, version_str.split(".")[:2]))) - if arch is None: - arch = _mac_arch(cpu_arch) + .. versionadded:: 20.0 + """ + if version is None or arch is None: + version_str, _, cpu_arch = platform.mac_ver() + if version is None: + version = cast("AppleVersion", tuple(map(int, version_str.split(".")[:2]))) + if version == (10, 16): + # When built against an older macOS SDK, Python will report macOS 10.16 + # instead of the real version. + version_str = subprocess.run( + [ + sys.executable, + "-sS", + "-c", + "import platform; print(platform.mac_ver()[0])", + ], + check=True, + env={"SYSTEM_VERSION_COMPAT": "0"}, + stdout=subprocess.PIPE, + text=True, + ).stdout + version = cast( + "AppleVersion", tuple(map(int, version_str.split(".")[:2])) + ) + if arch is None: + arch = _mac_arch(cpu_arch) if (10, 0) <= version < (11, 0): # Prior to Mac OS 11, each yearly release of Mac OS bumped the @@ -642,7 +751,6 @@ def mac_platforms( for binary_format in binary_formats: yield f"macosx_{major_version}_{minor_version}_{binary_format}" - if version >= (11, 0): # Mac OS 11 on x86_64 is compatible with binaries from previous releases. # Arm64 support was introduced in 11.0, so no Arm binaries from previous # releases exist. @@ -681,6 +789,8 @@ def ios_platforms( .. note:: Behavior of this method is undefined if invoked on non-iOS platforms without providing explicit version and multiarch arguments. + + .. versionadded:: 24.2 """ if version is None: # if iOS is the current platform, ios_ver *must* be defined. However, @@ -740,6 +850,8 @@ def android_platforms( e.g. ``arm64_v8a``. Defaults to the current system's ABI , as returned by ``sysconfig.get_platform``. Hyphens and periods will be replaced with underscores. + + .. versionadded:: 25.0 """ if platform.system() != "Android" and (api_level is None or abi is None): raise TypeError( @@ -776,10 +888,10 @@ def _linux_platforms(is_32bit: bool = _32_BIT_INTERPRETER) -> Iterator[str]: linux = "linux_armv8l" _, arch = linux.split("_", 1) archs = {"armv8l": ["armv8l", "armv7l"]}.get(arch, [arch]) - yield from _manylinux.platform_tags(archs) - yield from _musllinux.platform_tags(archs) for arch in archs: yield f"linux_{arch}" + yield from _manylinux.platform_tags(archs) + yield from _musllinux.platform_tags(archs) def _emscripten_platforms() -> Iterator[str]: @@ -798,6 +910,8 @@ def _generic_platforms() -> Iterator[str]: def platform_tags() -> Iterator[str]: """ Yields the :attr:`~Tag.platform` tags for the running interpreter. + + .. versionadded:: 21.1 """ if platform.system() == "Darwin": return mac_platforms() @@ -821,6 +935,8 @@ def interpreter_name() -> str: be returned when appropriate. This typically acts as the prefix to the :attr:`~Tag.interpreter` tag. + + .. versionadded:: 20.0 """ name = sys.implementation.name return INTERPRETER_SHORT_NAMES.get(name) or name @@ -833,6 +949,8 @@ def interpreter_version(*, warn: bool = False) -> str: This typically acts as the suffix to the :attr:`~Tag.interpreter` tag. :param bool warn: Whether warnings should be logged. Defaults to ``False``. + + .. versionadded:: 20.0 """ version = _get_config_var("py_version_nodot", warn=warn) return str(version) if version else _version_nodot(sys.version_info[:2]) @@ -867,15 +985,18 @@ def sys_tags(*, warn: bool = False) -> Iterator[Tag]: .. versionchanged:: 21.3 Added the `pp3-none-any` tag (:issue:`311`). - .. versionchanged:: 27.0 + .. versionchanged:: 26.1 Added the `abi3t` tag (:issue:`1099`). + .. versionchanged:: 26.3 + Native ``linux_*`` platform tags are now ordered before ``manylinux`` + and ``musllinux`` tags (:issue:`160`). """ interp_name = interpreter_name() if interp_name == "cp": yield from cpython_tags(warn=warn) else: - yield from generic_tags() + yield from generic_tags(warn=warn) if interp_name == "pp": interp = "pp3" diff --git a/server/libs/packaging/utils.py b/server/libs/packaging/utils.py index cbd3be2..2f0ce20 100644 --- a/server/libs/packaging/utils.py +++ b/server/libs/packaging/utils.py @@ -5,9 +5,9 @@ from __future__ import annotations import re -from typing import NewType, Tuple, Union, cast +from typing import NewType, Union, cast -from .tags import Tag, UnsortedTagsError, parse_tag +from .tags import InvalidTag, Tag, UnsortedTagsError, parse_tag from .version import InvalidVersion, Version, _TrimmedRelease __all__ = [ @@ -28,29 +28,42 @@ def __dir__() -> list[str]: return __all__ -BuildTag = Union[Tuple[()], Tuple[int, str]] +BuildTag = Union[tuple[()], tuple[int, str]] +""" +A wheel build tag: an empty tuple, or a ``(build number, build tag suffix)`` pair. + +.. versionadded:: 20.9 +""" NormalizedName = NewType("NormalizedName", str) """ A :class:`typing.NewType` of :class:`str`, representing a normalized name. + +.. versionadded:: 20.4 """ class InvalidName(ValueError): """ An invalid distribution name; users should refer to the packaging user guide. + + .. versionadded:: 23.2 """ class InvalidWheelFilename(ValueError): """ An invalid wheel filename was found, users should refer to PEP 427. + + .. versionadded:: 20.9 """ class InvalidSdistFilename(ValueError): """ An invalid sdist filename was found, users should refer to the packaging user guide. + + .. versionadded:: 20.9 """ @@ -58,9 +71,12 @@ class InvalidSdistFilename(ValueError): _validate_regex = re.compile( r"[a-z0-9]|[a-z0-9][a-z0-9._-]*[a-z0-9]", re.IGNORECASE | re.ASCII ) -_normalized_regex = re.compile(r"[a-z0-9]|[a-z0-9]([a-z0-9-](?!--))*[a-z0-9]", re.ASCII) +_normalized_regex = re.compile(r"[a-z0-9]+(?:-[a-z0-9]+)*", re.ASCII) # PEP 427: The build number must start with a digit. _build_tag_regex = re.compile(r"(\d+)(.*)", re.ASCII) +# PEP 427: Valid characters for an escaped project name in a wheel filename. +# Requires at least one character so an empty project name is rejected. +_wheel_name_regex = re.compile(r"^[\w._]+\Z", re.UNICODE) def canonicalize_name(name: str, *, validate: bool = False) -> NormalizedName: @@ -87,6 +103,14 @@ def canonicalize_name(name: str, *, validate: bool = False) -> NormalizedName: 'oslo-concurrency' >>> canonicalize_name("requests") 'requests' + + .. versionadded:: 16.2 + + .. versionchanged:: 20.4 + The return type was changed to :class:`NormalizedName`. + + .. versionchanged:: 23.2 + Added the *validate* keyword parameter. """ if validate and not _validate_regex.fullmatch(name): raise InvalidName(f"name is invalid: {name!r}") @@ -102,16 +126,27 @@ def canonicalize_name(name: str, *, validate: bool = False) -> NormalizedName: def is_normalized_name(name: str) -> bool: """ - Check if a name is already normalized (i.e. :func:`canonicalize_name` would - roundtrip to the same value). + Check if a name is a normalized project name (i.e. a valid name that + :func:`canonicalize_name` would roundtrip to the same value). + + The roundtrip only characterizes normalized names for *valid* names. A name + must start and end with an ASCII letter or digit, which + :func:`canonicalize_name` does not enforce: it leaves a leading or trailing + hyphen in place, so such a name roundtrips without being normalized. :param str name: The name to check. - >>> from packaging.utils import is_normalized_name + >>> from packaging.utils import canonicalize_name, is_normalized_name >>> is_normalized_name("requests") True >>> is_normalized_name("Django") False + >>> canonicalize_name("_not_legal") + '-not-legal' + >>> is_normalized_name("-not-legal") # roundtrips, but not a valid name + False + + .. versionadded:: 23.2 """ return _normalized_regex.fullmatch(name) is not None @@ -145,6 +180,14 @@ def canonicalize_version( >>> canonicalize_version('1.4.0.0.0') '1.4' + + .. versionadded:: 17.1 + + .. versionchanged:: 21.0 + The return type was narrowed to :class:`str`. + + .. versionchanged:: 22.0 + Added the *strip_trailing_zero* keyword parameter. """ if isinstance(version, str): try: @@ -196,8 +239,18 @@ def parse_wheel_filename( >>> not build True + .. versionadded:: 20.9 + + .. versionchanged:: 23.2 + Raises :class:`InvalidWheelFilename` when the version component is invalid. + .. versionadded:: 26.1 The *validate_order* parameter. + + .. versionchanged:: 26.3 + Raises :class:`InvalidWheelFilename` when an interpreter component is + not an identifier, a tag set component is empty, or the project name is + empty. """ if not filename.endswith(".whl"): raise InvalidWheelFilename( @@ -214,7 +267,7 @@ def parse_wheel_filename( parts = filename.split("-", dashes - 2) name_part = parts[0] # See PEP 427 for the rules on escaping the project name. - if "__" in name_part or re.match(r"^[\w\d._]*$", name_part, re.UNICODE) is None: + if "__" in name_part or _wheel_name_regex.match(name_part) is None: raise InvalidWheelFilename(f"Invalid project name: {filename!r}") name = canonicalize_name(name_part) @@ -243,6 +296,10 @@ def parse_wheel_filename( f"Invalid wheel filename (compressed tag set components must be in " f"sorted order per PEP 425): {filename!r}" ) from None + except InvalidTag: + raise InvalidWheelFilename( + f"Invalid wheel filename (invalid tag component): {filename!r}" + ) from None return (name, version, build, tags) @@ -255,8 +312,10 @@ def parse_sdist_filename(filename: str) -> tuple[NormalizedName, Version]: :param str filename: The name of the sdist file. :raises InvalidSdistFilename: If the filename does not end - with an sdist extension (``.zip`` or ``.tar.gz``), or if it does not - contain a dash separating the name and the version of the distribution. + with an sdist extension (``.zip`` or ``.tar.gz``), if it does not + contain a dash separating the name and the version of the distribution, + if the project name is empty, or if the version portion is not a valid + version. >>> from packaging.utils import parse_sdist_filename >>> from packaging.version import Version @@ -266,6 +325,17 @@ def parse_sdist_filename(filename: str) -> tuple[NormalizedName, Version]: >>> ver == Version('1.0') True + .. versionadded:: 20.9 + + .. versionchanged:: 21.0 + Added support for ``.zip`` source distributions. + + .. versionchanged:: 23.2 + Raises :class:`InvalidSdistFilename` when the version component is invalid. + + .. versionchanged:: 26.3 + Raises :class:`InvalidSdistFilename` on an empty project name. + .. _Source distribution format: https://packaging.python.org/specifications/source-distribution-format/#source-distribution-file-name """ if filename.endswith(".tar.gz"): @@ -283,6 +353,10 @@ def parse_sdist_filename(filename: str) -> tuple[NormalizedName, Version]: name_part, sep, version_part = file_stem.rpartition("-") if not sep: raise InvalidSdistFilename(f"Invalid sdist filename: {filename!r}") + if not name_part: + raise InvalidSdistFilename( + f"Invalid sdist filename (empty project name): {filename!r}" + ) name = canonicalize_name(name_part) diff --git a/server/libs/packaging/version.py b/server/libs/packaging/version.py index 97f23fd..5a964bd 100644 --- a/server/libs/packaging/version.py +++ b/server/libs/packaging/version.py @@ -18,7 +18,6 @@ from typing import ( Literal, NamedTuple, SupportsInt, - Tuple, TypedDict, Union, ) @@ -67,13 +66,13 @@ def __dir__() -> list[str]: return __all__ -LocalType = Tuple[Union[int, str], ...] +LocalType = tuple[Union[int, str], ...] -CmpLocalType = Tuple[Tuple[int, str], ...] -CmpSuffix = Tuple[int, int, int, int, int, int] +CmpLocalType = tuple[tuple[int, str], ...] +CmpSuffix = tuple[int, int, int, int, int, int] CmpKey = Union[ - Tuple[int, Tuple[int, ...], CmpSuffix], - Tuple[int, Tuple[int, ...], CmpSuffix, CmpLocalType], + tuple[int, tuple[int, ...], CmpSuffix], + tuple[int, tuple[int, ...], CmpSuffix, CmpLocalType], ] VersionComparisonMethod = Callable[[CmpKey, CmpKey], bool] @@ -288,10 +287,15 @@ def _validate_pre(value: object, /) -> tuple[Literal["a", "b", "rc"], int] | Non return value if isinstance(value, tuple) and len(value) == 2: letter, number = value - letter = normalize_pre(letter) - if letter in {"a", "b", "rc"} and isinstance(number, int) and number >= 0: + # The letter must be a string before it can be normalized. + if ( + isinstance(letter, str) + and (normalized := normalize_pre(letter)) in {"a", "b", "rc"} + and isinstance(number, int) + and number >= 0 + ): # type checkers can't infer the Literal type here on letter - return (letter, number) # type: ignore[return-value] + return (normalized, number) # type: ignore[return-value] msg = f"pre must be a tuple of ('a'|'b'|'rc', non-negative int), got {value}" raise InvalidVersion(msg) @@ -411,9 +415,16 @@ class Version(_BaseVersion): If the ``version`` does not conform to PEP 440 in any way then this exception will be raised. """ - if _SIMPLE_VERSION_INDICATORS.issuperset(version): + try: + is_simple = _SIMPLE_VERSION_INDICATORS.issuperset(version) + except TypeError: + raise InvalidVersion(f"Invalid version: {version!r}") from None + + if is_simple: try: self._release = tuple(map(int, version.split("."))) + except AttributeError: + raise InvalidVersion(f"Invalid version: {version!r}") from None except ValueError: # Empty parts (from "1..2", ".1", etc.) are invalid versions. # Any other ValueError (e.g. int str-digits limit) should @@ -433,7 +444,10 @@ class Version(_BaseVersion): return # Validate the version and parse it into pieces - match = self._regex.fullmatch(version) + try: + match = self._regex.fullmatch(version) + except TypeError: + raise InvalidVersion(f"Invalid version: {version!r}") from None if not match: raise InvalidVersion(f"Invalid version: {version!r}") self._epoch = int(match.group("epoch")) if match.group("epoch") else 0 @@ -1041,6 +1055,8 @@ class Version(_BaseVersion): >>> Version("1.2.3").major 1 + + .. versionadded:: 20.0 """ return self.release[0] if len(self.release) >= 1 else 0 @@ -1052,6 +1068,8 @@ class Version(_BaseVersion): 2 >>> Version("1").minor 0 + + .. versionadded:: 20.0 """ return self.release[1] if len(self.release) >= 2 else 0 @@ -1063,6 +1081,8 @@ class Version(_BaseVersion): 3 >>> Version("1").micro 0 + + .. versionadded:: 20.0 """ return self.release[2] if len(self.release) >= 3 else 0 @@ -1079,6 +1099,7 @@ class _TrimmedRelease(Version): self._post = version._post self._local = version._local self._key_cache = version._key_cache + self._hash_cache = version._hash_cache return super().__init__(version) # pragma: no cover diff --git a/server/libs/pygls-1.3.1.dist-info/RECORD b/server/libs/pygls-1.3.1.dist-info/RECORD deleted file mode 100644 index 950a21a..0000000 --- a/server/libs/pygls-1.3.1.dist-info/RECORD +++ /dev/null @@ -1,26 +0,0 @@ -pygls-1.3.1.dist-info/INSTALLER,sha256=5hhM4Q4mYTT9z6QB6PGpUAW81PGNFrYrdXMj4oM_6ak,2 -pygls-1.3.1.dist-info/LICENSE.txt,sha256=b0kVxr8adbxhHDGM8t6T3jWLMbQJ7QLrngwkWnnWCl8,11367 -pygls-1.3.1.dist-info/METADATA,sha256=ZZmXz51Jk7TTtWO1hLfSWQynv6rDCM798YWVbloCqHk,4726 -pygls-1.3.1.dist-info/RECORD,, -pygls-1.3.1.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -pygls-1.3.1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88 -pygls/__init__.py,sha256=rdTb3X-53tCjgNpS5dRsxv0ukMDjEly2pVEOPTnjx5k,1488 -pygls/capabilities.py,sha256=3tl-cqu82QpxHz-Z3NtlU6z-gbPqIvyvZ6gyZ-dr0-0,16756 -pygls/client.py,sha256=loVwqagoY0BnS6RwfpYtXwhg0NiIE6Tvbj2DzpOF7GA,6292 -pygls/constants.py,sha256=0YsX4Egp9jVLuAu9v8T_ThrObrVKGP916-X-9bkmId8,1470 -pygls/exceptions.py,sha256=skJKYaJCXI5At2eS1pNdQ6r3_B9Z-SMlyqr0_dwUVEw,6302 -pygls/feature_manager.py,sha256=7C--ra3GaG44LoZd8MaZ6Jh_8uxQMZo5jzykGwT7Fdg,8494 -pygls/lsp/__init__.py,sha256=pp9PCQhGzgPPFfWID47cdz_Q0LpZjT2kFPgTS-N7iVM,5236 -pygls/lsp/client.py,sha256=8JVgyjXXOblPlDhLAvNbukK-qrQNf__757elz9XYkCo,76358 -pygls/progress.py,sha256=Ml8vgJ9ueFC4YUqwvrgHatX8l_O3odhvmoPOLIcMNok,2789 -pygls/protocol/__init__.py,sha256=YI5xMBILWYKexx343wUDrHUVPuJFu9A48VSf0ieXYJM,1822 -pygls/protocol/json_rpc.py,sha256=01nqJoCNDmZQ78tyFxPfA9_kEBHyuBe-7ZUXCqwmu4g,20124 -pygls/protocol/language_server.py,sha256=b6X30DCLN4sdG85OhLVdrBJ9cweL4eKVgsc10bnMzXk,20109 -pygls/protocol/lsp_meta.py,sha256=kX1nL7XGVIYWp6UUyT3yDFnhcvpoCU_3mdyzpDTtUyQ,1593 -pygls/py.typed,sha256=ZfGKUcVseOxYpg6BU9EuhkP4dErsepCA4apkj_9YnYc,65 -pygls/server.py,sha256=T-k2wsP0W5a6KHmE9Afrv2PTy3qACEuCPGSJPmzC30w,20753 -pygls/uris.py,sha256=lknA_8hNYfs47mOFQxnFYW2TWH-8iL68ghTVD0Cccsc,5764 -pygls/workspace/__init__.py,sha256=tD6ahYMIPVsDdsWJ32EhF8wK-IJy6IQGInkI-BmIAxY,2883 -pygls/workspace/position_codec.py,sha256=UDv1kXFMyCDnu-iGhEbylCJP74L0TAL2hFvhoFrSpOY,8019 -pygls/workspace/text_document.py,sha256=8LcxsQeawuPNDrNDm3A2oMjWxYA3YxXm3NiHyQJQp8M,9031 -pygls/workspace/workspace.py,sha256=Zpd96kvVM7po7cI_XLenRAq8Wp3mjlMBX_YxO6Ecvs8,11556 diff --git a/server/libs/pygls-1.3.1.dist-info/INSTALLER b/server/libs/pygls-2.1.1.dist-info/INSTALLER similarity index 100% rename from server/libs/pygls-1.3.1.dist-info/INSTALLER rename to server/libs/pygls-2.1.1.dist-info/INSTALLER diff --git a/server/libs/pygls-1.3.1.dist-info/METADATA b/server/libs/pygls-2.1.1.dist-info/METADATA similarity index 76% rename from server/libs/pygls-1.3.1.dist-info/METADATA rename to server/libs/pygls-2.1.1.dist-info/METADATA index 70de8e1..f038aef 100644 --- a/server/libs/pygls-1.3.1.dist-info/METADATA +++ b/server/libs/pygls-2.1.1.dist-info/METADATA @@ -1,27 +1,26 @@ -Metadata-Version: 2.1 +Metadata-Version: 2.4 Name: pygls -Version: 1.3.1 +Version: 2.1.1 Summary: A pythonic generic language server (pronounced like 'pie glass') -Home-page: https://github.com/openlawlibrary/pygls -License: Apache-2.0 +License-Expression: Apache-2.0 +License-File: LICENSE.txt Author: Open Law Library Author-email: info@openlawlib.org Maintainer: Tom BH Maintainer-email: tom@tombh.co.uk -Requires-Python: >=3.8 -Classifier: License :: OSI Approved :: Apache Software License +Requires-Python: >=3.9 Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 Classifier: Programming Language :: Python :: 3.10 Classifier: Programming Language :: Python :: 3.11 Classifier: Programming Language :: Python :: 3.12 +Classifier: Programming Language :: Python :: 3.13 +Classifier: Programming Language :: Python :: 3.14 Provides-Extra: ws +Requires-Dist: attrs (>=24.3.0) Requires-Dist: cattrs (>=23.1.2) -Requires-Dist: lsprotocol (==2023.0.1) -Requires-Dist: websockets (>=11.0.3) ; extra == "ws" -Project-URL: Documentation, https://pygls.readthedocs.io/en/latest -Project-URL: Repository, https://github.com/openlawlibrary/pygls +Requires-Dist: lsprotocol (==2025.0.0) +Requires-Dist: websockets (>=13.0) ; extra == "ws" Description-Content-Type: text/markdown [![PyPI Version](https://img.shields.io/pypi/v/pygls.svg)](https://pypi.org/project/pygls/) ![!pyversions](https://img.shields.io/pypi/pyversions/pygls.svg) ![license](https://img.shields.io/pypi/l/pygls.svg) [![Documentation Status](https://img.shields.io/badge/docs-latest-green.svg)](https://pygls.readthedocs.io/en/latest/) @@ -32,27 +31,22 @@ _pygls_ (pronounced like "pie glass") is a pythonic generic implementation of th ## Quickstart ```python -from pygls.server import LanguageServer -from lsprotocol.types import ( - TEXT_DOCUMENT_COMPLETION, - CompletionItem, - CompletionList, - CompletionParams, -) +from pygls.lsp.server import LanguageServer +from lsprotocol import types server = LanguageServer("example-server", "v0.1") -@server.feature(TEXT_DOCUMENT_COMPLETION) -def completions(params: CompletionParams): +@server.feature(types.TEXT_DOCUMENT_COMPLETION) +def completions(params: types.CompletionParams): items = [] - document = server.workspace.get_document(params.text_document.uri) + document = server.workspace.get_text_document(params.text_document.uri) current_line = document.lines[params.position.line].strip() if current_line.endswith("hello."): items = [ - CompletionItem(label="world"), - CompletionItem(label="friend"), + types.CompletionItem(label="world"), + types.CompletionItem(label="friend"), ] - return CompletionList(is_incomplete=False, items=items) + return types.CompletionList(is_incomplete=False, items=items) server.start_io() ``` @@ -79,12 +73,10 @@ There are also other Language Servers with "general" in their descriptons, or at * https://github.com/jose-elias-alvarez/null-ls.nvim (Neovim only) ## Tests -All Pygls sub-tasks require the Poetry `poe` plugin: https://github.com/nat-n/poethepoet - -* `poetry install --all-extras` -* `poetry run poe test` -* `poetry run poe test-pyodide` +All Pygls sub-tasks require the `uv`: https://docs.astral.sh/uv/getting-started/installation +* `uv run --all-extras poe test` +* `uv run --all-extras poe test-pyodide` ## Contributing diff --git a/server/libs/pygls-2.1.1.dist-info/RECORD b/server/libs/pygls-2.1.1.dist-info/RECORD new file mode 100644 index 0000000..ae7b700 --- /dev/null +++ b/server/libs/pygls-2.1.1.dist-info/RECORD @@ -0,0 +1,31 @@ +pygls-2.1.1.dist-info/INSTALLER,sha256=5hhM4Q4mYTT9z6QB6PGpUAW81PGNFrYrdXMj4oM_6ak,2 +pygls-2.1.1.dist-info/METADATA,sha256=irBCbsPjhAwIG_0lZcboG7qJQ7R8OwGyI4heqlbWW4I,4531 +pygls-2.1.1.dist-info/RECORD,, +pygls-2.1.1.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pygls-2.1.1.dist-info/WHEEL,sha256=kJCRJT_g0adfAJzTx2GUMmS80rTJIVHRCfG0DQgLq3o,88 +pygls-2.1.1.dist-info/licenses/LICENSE.txt,sha256=b0kVxr8adbxhHDGM8t6T3jWLMbQJ7QLrngwkWnnWCl8,11367 +pygls/__init__.py,sha256=pK-9Xb-tbL9uXGziKDv8Av3tQCJuMiktoqKdkV80V4w,1553 +pygls/capabilities.py,sha256=bVu1cR9pTDypI9pEMGE2i87wGmMot6CdfC6gwjH2p-o,17596 +pygls/cli.py,sha256=EC99J1HzlitNY6DB-9CmjKbE0NsDN427YkT9Num4TCU,2319 +pygls/client.py,sha256=hlhN5nqrI-CV64Cu0yCtiawF2w9vORLSlW0uVMHSSkI,7585 +pygls/constants.py,sha256=0YsX4Egp9jVLuAu9v8T_ThrObrVKGP916-X-9bkmId8,1470 +pygls/exceptions.py,sha256=MXJO0-qgqck6RiXYBrtROEeXtAw0AddQRnBu8nQMxOk,6724 +pygls/feature_manager.py,sha256=ozsF68bUYCFKyv0ycB9pISDEmUns7LEDflTdkRRKXSw,8895 +pygls/io_.py,sha256=HeP3Q0j7fg0KvZtKDxEf1WZJ7C5O4_CpZ_S0P1DSJOA,9244 +pygls/lsp/__init__.py,sha256=pp9PCQhGzgPPFfWID47cdz_Q0LpZjT2kFPgTS-N7iVM,5236 +pygls/lsp/_base_client.py,sha256=kFEuMlXk1skc6Y8x02EIwOod1oD5Qs8pMfsIW1oiZMo,81733 +pygls/lsp/_base_server.py,sha256=HVvEndKfPamr5FrGILD5naZIQDuOT3H4SbOhoZfMImE,17854 +pygls/lsp/_capabilities.py,sha256=YIgOkdqcUl9tTZ4pz40ZmuGaDjWnauM4L5MOz2Oz9Gs,121441 +pygls/lsp/client.py,sha256=zah7RZWnFSF5GYoomsbdz7VR2xuZS1krCaBzFJIHw5Y,160 +pygls/lsp/server.py,sha256=2rkJ6Chq_pC7DonZ2j1MTsIBTij1N1MOkFbkRlidxvs,4174 +pygls/progress.py,sha256=Ml8vgJ9ueFC4YUqwvrgHatX8l_O3odhvmoPOLIcMNok,2789 +pygls/protocol/__init__.py,sha256=XYUCEBA9Cl4sF1gtmjruHWVcKRdYN-LYsdbqIuqQCkg,1718 +pygls/protocol/json_rpc.py,sha256=wKy8Knv3xbszSe5PFjq7wauDQBfWtXJ4MHdeBp3q1P8,23796 +pygls/protocol/language_server.py,sha256=qLFRnlEaDrycm0nJKzXI0tI21E-m_Ewk9GlyPMZcGjc,15495 +pygls/py.typed,sha256=ZfGKUcVseOxYpg6BU9EuhkP4dErsepCA4apkj_9YnYc,65 +pygls/server.py,sha256=MvRmgoGqEBPQGrwcvZl021CHGhWeDH9NvdeFaCDKye0,9627 +pygls/uris.py,sha256=wAjK_kL-gOWcSe86BnBlsDPZ47aTm3S1EuCr9gmcMEU,5800 +pygls/workspace/__init__.py,sha256=AxU6NydTtfHIih_Xd8lSUm8AydhPopVXKGRuSGnzOok,274 +pygls/workspace/position_codec.py,sha256=CFRzod1pr-2vdpyGV2wNk2cxq6cqJo8WNtLH3KktfNs,9381 +pygls/workspace/text_document.py,sha256=4SKRRF9gRRtljtghiPHJYram2_h-4zj2DE0MyjxZYkE,12303 +pygls/workspace/workspace.py,sha256=QgeN0URYraABW6W_qATVYdStVhMCw5LGN0DFuPmx5fo,10112 diff --git a/server/libs/pygls-1.3.1.dist-info/REQUESTED b/server/libs/pygls-2.1.1.dist-info/REQUESTED similarity index 100% rename from server/libs/pygls-1.3.1.dist-info/REQUESTED rename to server/libs/pygls-2.1.1.dist-info/REQUESTED diff --git a/server/libs/pygls-1.3.1.dist-info/WHEEL b/server/libs/pygls-2.1.1.dist-info/WHEEL similarity index 67% rename from server/libs/pygls-1.3.1.dist-info/WHEEL rename to server/libs/pygls-2.1.1.dist-info/WHEEL index d73ccaa..7894e88 100644 --- a/server/libs/pygls-1.3.1.dist-info/WHEEL +++ b/server/libs/pygls-2.1.1.dist-info/WHEEL @@ -1,4 +1,4 @@ Wheel-Version: 1.0 -Generator: poetry-core 1.9.0 +Generator: poetry-core 2.3.1 Root-Is-Purelib: true Tag: py3-none-any diff --git a/server/libs/pygls-1.3.1.dist-info/LICENSE.txt b/server/libs/pygls-2.1.1.dist-info/licenses/LICENSE.txt similarity index 100% rename from server/libs/pygls-1.3.1.dist-info/LICENSE.txt rename to server/libs/pygls-2.1.1.dist-info/licenses/LICENSE.txt diff --git a/server/libs/pygls/__init__.py b/server/libs/pygls/__init__.py index 147cd9e..4cd0dc8 100644 --- a/server/libs/pygls/__init__.py +++ b/server/libs/pygls/__init__.py @@ -21,5 +21,7 @@ import sys IS_WIN = os.name == "nt" IS_PYODIDE = "pyodide" in sys.modules +IS_WASI = sys.platform == "wasi" +IS_WASM = IS_PYODIDE or IS_WASI pygls = "pygls" diff --git a/server/libs/pygls/capabilities.py b/server/libs/pygls/capabilities.py index 9db4744..27ff4d5 100644 --- a/server/libs/pygls/capabilities.py +++ b/server/libs/pygls/capabilities.py @@ -14,31 +14,23 @@ # See the License for the specific language governing permissions and # # limitations under the License. # ############################################################################ -from functools import reduce -from typing import Any, Dict, List, Optional, Set, Union, TypeVar import logging +from typing import Any, Dict, List, Optional, Set, TypeVar, Union from lsprotocol import types +from pygls.lsp._capabilities import get_capability as get_capability logger = logging.getLogger(__name__) T = TypeVar("T") - -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 +_SUPPORTED_ENCODINGS = frozenset( + [ + types.PositionEncodingKind.Utf8, + types.PositionEncodingKind.Utf16, + types.PositionEncodingKind.Utf32, + ] +) class ServerCapabilitiesBuilder: @@ -54,6 +46,9 @@ class ServerCapabilitiesBuilder: commands: List[str], text_document_sync_kind: types.TextDocumentSyncKind, notebook_document_sync: Optional[types.NotebookDocumentSyncOptions] = None, + position_encoding: Union[ + types.PositionEncodingKind, str + ] = types.PositionEncodingKind.Utf16, ): self.client_capabilities = client_capabilities self.features = features @@ -63,12 +58,37 @@ class ServerCapabilitiesBuilder: self.notebook_document_sync = notebook_document_sync self.server_cap = types.ServerCapabilities() + self.server_cap.position_encoding = position_encoding def _provider_options(self, feature: str, default: T) -> Optional[Union[T, Any]]: if feature in self.features: return self.feature_options.get(feature, default) return None + @classmethod + def choose_position_encoding( + cls, client_capabilities: types.ClientCapabilities + ) -> Union[types.PositionEncodingKind, str]: + server_encoding: Union[types.PositionEncodingKind, str] = ( + types.PositionEncodingKind.Utf16 + ) + + if (general := client_capabilities.general) is None: + return server_encoding + + if (encodings := general.position_encodings) is None: + return server_encoding + + # We match client preference where this an overlap between its and our supported encodings. + for client_encoding in encodings: + if client_encoding in _SUPPORTED_ENCODINGS: + server_encoding = client_encoding + return server_encoding + + logger.warning(f"Unknown `PositionEncoding`s: {encodings}") + + return server_encoding + def _with_text_document_sync(self): open_close = ( types.TEXT_DOCUMENT_DID_OPEN in self.features @@ -145,7 +165,7 @@ class ServerCapabilitiesBuilder: def _with_type_definition(self): value = self._provider_options( - types.TEXT_DOCUMENT_TYPE_DEFINITION, default=types.TypeDefinitionOptions() + types.TEXT_DOCUMENT_TYPE_DEFINITION, default=True ) if value is not None: self.server_cap.type_definition_provider = value @@ -161,9 +181,7 @@ class ServerCapabilitiesBuilder: return self def _with_implementation(self): - value = self._provider_options( - types.TEXT_DOCUMENT_IMPLEMENTATION, default=types.ImplementationOptions() - ) + value = self._provider_options(types.TEXT_DOCUMENT_IMPLEMENTATION, default=True) if value is not None: self.server_cap.implementation_provider = value return self @@ -201,6 +219,7 @@ class ServerCapabilitiesBuilder: types.TEXT_DOCUMENT_CODE_LENS, default=types.CodeLensOptions() ) if value is not None: + value.resolve_provider = types.CODE_LENS_RESOLVE in self.features self.server_cap.code_lens_provider = value return self @@ -209,6 +228,7 @@ class ServerCapabilitiesBuilder: types.TEXT_DOCUMENT_DOCUMENT_LINK, default=types.DocumentLinkOptions() ) if value is not None: + value.resolve_provider = types.DOCUMENT_LINK_RESOLVE in self.features self.server_cap.document_link_provider = value return self @@ -241,9 +261,25 @@ class ServerCapabilitiesBuilder: return self def _with_rename(self): - value = self._provider_options(types.TEXT_DOCUMENT_RENAME, default=True) - if value is not None: - self.server_cap.rename_provider = value + server_supports_rename = types.TEXT_DOCUMENT_RENAME in self.features + if server_supports_rename is False: + return self + + client_prepare_support = get_capability( + self.client_capabilities, "text_document.rename.prepare_support", False + ) + + # From the spec: + # > RenameOptions may only be specified if the client states that it supports + # > prepareSupport in its initial initialize request. + if not client_prepare_support: + self.server_cap.rename_provider = server_supports_rename + + else: + self.server_cap.rename_provider = types.RenameOptions( + prepare_provider=types.TEXT_DOCUMENT_PREPARE_RENAME in self.features + ) + return self def _with_folding_range(self): @@ -302,12 +338,12 @@ class ServerCapabilitiesBuilder: self.server_cap.semantic_tokens_provider = value return self - full_support: Union[bool, types.SemanticTokensOptionsFullType1] = ( + full_support: Union[bool, types.SemanticTokensFullDelta] = ( types.TEXT_DOCUMENT_SEMANTIC_TOKENS_FULL in self.features ) if types.TEXT_DOCUMENT_SEMANTIC_TOKENS_FULL_DELTA in self.features: - full_support = types.SemanticTokensOptionsFullType1(delta=True) + full_support = types.SemanticTokensFullDelta(delta=True) options = types.SemanticTokensOptions( legend=value, @@ -364,7 +400,7 @@ class ServerCapabilitiesBuilder: value = self._provider_options(method_name, default=None) setattr(file_operations, capability_name, value) - self.server_cap.workspace = types.ServerCapabilitiesWorkspaceType( + self.server_cap.workspace = types.WorkspaceOptions( workspace_folders=types.WorkspaceFoldersServerCapabilities( supported=True, change_notifications=True, @@ -391,30 +427,12 @@ class ServerCapabilitiesBuilder: self.server_cap.inline_value_provider = value return self - def _with_position_encodings(self): - self.server_cap.position_encoding = types.PositionEncodingKind.Utf16 - - general = self.client_capabilities.general - if general is None: - return self - - encodings = general.position_encodings - if encodings is None: - return self - - if types.PositionEncodingKind.Utf16 in encodings: - return self - - if types.PositionEncodingKind.Utf32 in encodings: - self.server_cap.position_encoding = types.PositionEncodingKind.Utf32 - return self - - if types.PositionEncodingKind.Utf8 in encodings: - self.server_cap.position_encoding = types.PositionEncodingKind.Utf8 - return self - - logger.warning(f"Unknown `PositionEncoding`s: {encodings}") - + def _with_inline_completion_provider(self): + value = self._provider_options( + types.TEXT_DOCUMENT_INLINE_COMPLETION, default=None + ) + if value is not None: + self.server_cap.inline_completion_provider = value return self def _build(self): @@ -455,6 +473,6 @@ class ServerCapabilitiesBuilder: ._with_workspace_capabilities() ._with_diagnostic_provider() ._with_inline_value_provider() - ._with_position_encodings() + ._with_inline_completion_provider() ._build() ) diff --git a/server/libs/pygls/cli.py b/server/libs/pygls/cli.py new file mode 100644 index 0000000..bfcb4d8 --- /dev/null +++ b/server/libs/pygls/cli.py @@ -0,0 +1,45 @@ +############################################################################ +# 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. # +############################################################################ +"""A simple cli wrapper for pygls servers.""" +from __future__ import annotations + +import argparse +import typing + +if typing.TYPE_CHECKING: + from pygls.server import JsonRPCServer + + +def start_server(server: JsonRPCServer, args: list[str] | None = None): + """A helper function that implements a simple cli wrapper for a pygls server + allowing the user to select between the supported transports.""" + + name = type(server).__name__ + parser = argparse.ArgumentParser(description=f"start a {name} instance") + parser.add_argument("--tcp", action="store_true", help="start a TCP server") + parser.add_argument("--ws", action="store_true", help="start a WebSocket server") + parser.add_argument("--host", default="127.0.0.1", help="bind to this address") + parser.add_argument("--port", type=int, default=8888, help="bind to this port") + + arguments = parser.parse_args(args) + + if arguments.tcp: + server.start_tcp(arguments.host, arguments.port) + elif arguments.ws: + server.start_ws(arguments.host, arguments.port) + else: + server.start_io() diff --git a/server/libs/pygls/client.py b/server/libs/pygls/client.py index 577f05e..1e79bbd 100644 --- a/server/libs/pygls/client.py +++ b/server/libs/pygls/client.py @@ -14,63 +14,30 @@ # See the License for the specific language governing permissions and # # limitations under the License. # ############################################################################ +from __future__ import annotations + import asyncio import logging -import re +import sys +import typing from threading import Event -from typing import Any -from typing import Callable -from typing import List -from typing import Optional -from typing import Type -from typing import Union -from cattrs import Converter - -from pygls.exceptions import PyglsError, JsonRpcException +from pygls.exceptions import JsonRpcException, PyglsError +from pygls.io_ import run_async, run_websocket from pygls.protocol import JsonRPCProtocol, default_converter +if typing.TYPE_CHECKING: + from typing import Any + from typing import Callable + from typing import List + from typing import Optional + from typing import Type + + from cattrs import Converter logger = logging.getLogger(__name__) -async def aio_readline(stop_event, reader, message_handler): - CONTENT_LENGTH_PATTERN = re.compile(rb"^Content-Length: (\d+)\r\n$") - - # Initialize message buffer - message = [] - content_length = 0 - - while not stop_event.is_set(): - # Read a header line - header = await reader.readline() - if not header: - break - message.append(header) - - # Extract content length if possible - if not content_length: - match = CONTENT_LENGTH_PATTERN.fullmatch(header) - if match: - content_length = int(match.group(1)) - logger.debug("Content length: %s", content_length) - - # Check if all headers have been read (as indicated by an empty line \r\n) - if content_length and not header.strip(): - # Read body - body = await reader.readexactly(content_length) - if not body: - break - message.append(body) - - # Pass message to protocol - message_handler(b"".join(message)) - - # Reset the buffer - message = [] - content_length = 0 - - class JsonRPCClient: """Base JSON-RPC client.""" @@ -79,14 +46,14 @@ class JsonRPCClient: protocol_cls: Type[JsonRPCProtocol] = JsonRPCProtocol, converter_factory: Callable[[], Converter] = default_converter, ): - # Strictly speaking `JsonRPCProtocol` wants a `LanguageServer`, not a - # `JsonRPCClient`. However there similar enough for our purposes, which is - # that this client will mostly be used in testing contexts. + # Strictly speaking, `JsonRPCProtocol` wants a `JsonRPCServer`, not a + # `JsonRPCClient`. However they're similar enough for our purposes, which + # is that this client will mostly be used in testing contexts. self.protocol = protocol_cls(self, converter_factory()) # type: ignore self._server: Optional[asyncio.subprocess.Process] = None self._stop_event = Event() - self._async_tasks: List[asyncio.Task] = [] + self._async_tasks: List[asyncio.Task[Any]] = [] @property def stopped(self) -> bool: @@ -128,39 +95,112 @@ class JsonRPCClient: **kwargs, ) - self.protocol.connection_made(server.stdin) # type: ignore + # Keep mypy happy + if server.stdout is None: + raise RuntimeError("Server process is missing a stdout stream") + + # Keep mypy happy + if server.stdin is None: + raise RuntimeError("Server process is missing a stdin stream") + + self.protocol.set_writer(server.stdin) connection = asyncio.create_task( - aio_readline(self._stop_event, server.stdout, self.protocol.data_received) + run_async( + stop_event=self._stop_event, + reader=server.stdout, + protocol=self.protocol, + logger=logger, + error_handler=self.report_server_error, + ) ) notify_exit = asyncio.create_task(self._server_exit()) self._server = server self._async_tasks.extend([connection, notify_exit]) - async def _server_exit(self): - if self._server is not None: - await self._server.wait() - logger.debug( - "Server process %s exited with return code: %s", - self._server.pid, - self._server.returncode, + async def start_tcp(self, host: str, port: int): + """Start communicating with a server over TCP.""" + reader, writer = await asyncio.open_connection(host, port) + + self.protocol.set_writer(writer) + connection = asyncio.create_task( + run_async( + stop_event=self._stop_event, + reader=reader, + protocol=self.protocol, + logger=logger, + error_handler=self.report_server_error, ) + ) + + self._async_tasks.extend([connection]) + + async def start_ws(self, host: str, port: int): + """Start communicating with a server over WebSockets.""" + + try: + from websockets.asyncio.client import connect + except ImportError: + logger.exception( + "Run `pip install pygls[ws]` to install dependencies required for websockets." + ) + sys.exit(1) + + uri = f"ws://{host}:{port}" + websocket = await connect(uri) + connection = asyncio.create_task( + run_websocket( + stop_event=self._stop_event, + websocket=websocket, + protocol=self.protocol, + logger=logger, + error_handler=self.report_server_error, + ) + ) + self._async_tasks.extend([connection]) + + # Yield control to the event loop, gives the run_websocket task chance to spin up. + await asyncio.sleep(0) + + async def _server_exit(self): + """Cleanup handler that runs when the server process managed by the client exits""" + if self._server is None: + return + + await self._server.wait() + + pid = self._server.pid + returncode = self._server.returncode + + reason = f"Server process {pid} exited with return code: {returncode}" + logger.debug(reason) + + # Cancel any pending requests + for id_, fut in self.protocol._request_futures.items(): + if not fut.done(): + fut.set_exception(RuntimeError(reason)) + logger.debug("Cancelled pending request '%s': %s", id_, reason) + + try: await self.server_exit(self._server) - self._stop_event.set() + except Exception: + logger.exception("Error in server_exit handler") + + self._stop_event.set() async def server_exit(self, server: asyncio.subprocess.Process): """Called when the server process exits.""" def _report_server_error( - self, error: Exception, source: Union[PyglsError, JsonRpcException] + self, error: Exception, source: type[PyglsError] | type[JsonRpcException] ): try: self.report_server_error(error, source) except Exception: - logger.error("Unable to report error", exc_info=True) + logger.exception("Unable to report error") def report_server_error( - self, error: Exception, source: Union[PyglsError, JsonRpcException] + self, error: Exception, source: type[PyglsError] | type[JsonRpcException] ): """Called when the server does something unexpected e.g. respond with malformed JSON.""" @@ -169,8 +209,7 @@ class JsonRPCClient: self._stop_event.set() if self._server is not None and self._server.returncode is None: - logger.debug("Terminating server process: %s", self._server.pid) - self._server.terminate() + await self._server.wait() if len(self._async_tasks) > 0: await asyncio.gather(*self._async_tasks) diff --git a/server/libs/pygls/exceptions.py b/server/libs/pygls/exceptions.py index 5faf269..edcf8bf 100644 --- a/server/libs/pygls/exceptions.py +++ b/server/libs/pygls/exceptions.py @@ -16,7 +16,10 @@ # 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 from typing import Type from lsprotocol.types import ResponseError @@ -25,14 +28,23 @@ from lsprotocol.types import ResponseError class JsonRpcException(Exception): """A class used as a base class for json rpc exceptions.""" - def __init__(self, message=None, code=None, data=None): - message = message or getattr(self.__class__, "MESSAGE") + CODE = -32603 + 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") + 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 @@ -43,7 +55,7 @@ class JsonRpcException(Exception): 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( @@ -53,7 +65,16 @@ class JsonRpcException(Exception): return JsonRpcException(code=error.code, message=error.message, data=error.data) @classmethod - def supports_code(cls, code): + def of(cls, exc: Any): + """Default ``of`` implementation that raises a ``JsonRpcException`` derived from + the given exception + """ + return cls( + message=f"{cls.MESSAGE}: {exc}", + ) + + @classmethod + def supports_code(cls, code: int): # Defaults to UnknownErrorCode return getattr(cls, "CODE", -32001) == code @@ -91,7 +112,7 @@ class JsonRpcMethodNotFound(JsonRpcException): MESSAGE = "Method Not Found" @classmethod - def of(cls, method): + def of(cls, method: str): return cls(message=cls.MESSAGE + ": " + method) diff --git a/server/libs/pygls/feature_manager.py b/server/libs/pygls/feature_manager.py index d00283a..7bfe7ed 100644 --- a/server/libs/pygls/feature_manager.py +++ b/server/libs/pygls/feature_manager.py @@ -55,13 +55,21 @@ def get_help_attrs(f): ) -def has_ls_param_or_annotation(f, annotation): - """Returns true if callable has first parameter named `ls` or type of - annotation""" +def has_ls_param_or_annotation(f, actual_type): + """Returns true if the given callable's first parameter is + + - named `ls` + - has a type annotation compatible with the given type + """ try: sig = inspect.signature(f) first_p = next(itertools.islice(sig.parameters.values(), 0, 1)) - return first_p.name == PARAM_LS or get_type_hints(f)[first_p.name] == annotation + + if first_p.name == PARAM_LS: + return True + + expected_type = get_type_hints(f)[first_p.name] + return issubclass(actual_type, expected_type) except Exception: return False @@ -80,6 +88,10 @@ def wrap_with_server(f, server): async def wrapped(*args, **kwargs): return await f(server, *args, **kwargs) + # Used by `workspace/executeCommand` to access the original function's + # signature. Mirrors how functools.partial works. + wrapped.func = f # type: ignore[attr-defined] + else: wrapped = functools.partial(f, server) if is_thread_function(f): @@ -196,7 +208,8 @@ class FeatureManager: raise TypeError( ( f'Options of method "{feature_name}"' - f" should be instance of type {options_type}" + f" is instance of type {type(options)}" + f" which is not a subtype of {options_type}" ) ) self._feature_options[feature_name] = options diff --git a/server/libs/pygls/io_.py b/server/libs/pygls/io_.py new file mode 100644 index 0000000..c6f89b6 --- /dev/null +++ b/server/libs/pygls/io_.py @@ -0,0 +1,296 @@ +############################################################################ +# 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. # +############################################################################ +from __future__ import annotations + +import asyncio +import json +import logging +import re +import typing + +from pygls.exceptions import JsonRpcException + +if typing.TYPE_CHECKING: + import logging + import threading + from collections.abc import Awaitable + from concurrent.futures import ThreadPoolExecutor + from typing import Any, BinaryIO, Callable, Protocol + + from websockets.asyncio.client import ClientConnection + from websockets.asyncio.server import ServerConnection + + from pygls.protocol import JsonRPCProtocol + + class Reader(Protocol): + """An synchronous reader.""" + + def readline(self) -> bytes: ... + + def read(self, n: int) -> bytes: ... + + class Writer(Protocol): + """An synchronous writer.""" + + def close(self) -> None: ... + + def write(self, data: bytes) -> None: ... + + class AsyncReader(typing.Protocol): + """An asynchronous reader.""" + + def readline(self) -> Awaitable[bytes]: ... + + def readexactly(self, n: int) -> Awaitable[bytes]: ... + + class AsyncWriter(typing.Protocol): + """An asynchronous writer.""" + + def close(self) -> Awaitable[None]: ... + + def write(self, data: bytes) -> Awaitable[None]: ... + + +class StdinAsyncReader: + """Read from stdin asynchronously.""" + + def __init__(self, stdin: BinaryIO, executor: ThreadPoolExecutor | None = None): + self.stdin = stdin + self._loop: asyncio.AbstractEventLoop | None = None + self.executor = executor + + @property + def loop(self): + if self._loop is None: + self._loop = asyncio.get_running_loop() + + return self._loop + + def readline(self) -> Awaitable[bytes]: + return self.loop.run_in_executor(self.executor, self.stdin.readline) + + def readexactly(self, n: int) -> Awaitable[bytes]: + return self.loop.run_in_executor(self.executor, self.stdin.read, n) + + +class StdoutWriter: + """Align a stdout stream with pygls' writer interface.""" + + def __init__(self, stdout: BinaryIO): + self._stdout = stdout + + def close(self): + self._stdout.close() + + def write(self, data: bytes) -> None: + self._stdout.write(data) + self._stdout.flush() + + +class WebSocketWriter: + """Align a websocket connection with pygls' writer interface""" + + def __init__(self, ws: ServerConnection | ClientConnection): + self._ws = ws + + def close(self) -> Awaitable[None]: + return self._ws.close() + + def write(self, data: bytes) -> Awaitable[None]: + return self._ws.send(data) + + +async def run_async( + stop_event: threading.Event, + reader: AsyncReader, + protocol: JsonRPCProtocol, + logger: logging.Logger | None = None, + error_handler: Callable[[Exception, type[JsonRpcException]], Any] | None = None, +): + """Run a main message processing loop, asynchronously + + Parameters + ---------- + stop_event + A ``threading.Event`` used to break the main loop + + reader + The reader to read messages from + + protocol + The protocol instance that should handle the messages + + logger + The logger instance to use + """ + + CONTENT_LENGTH_PATTERN = re.compile(rb"^Content-Length: (\d+)\r\n$") + content_length = 0 + logger = logger or logging.getLogger(__name__) + + while not stop_event.is_set(): + # Read a header line + header = await reader.readline() + if not header: + break + + # Extract content length if possible + if not content_length: + match = CONTENT_LENGTH_PATTERN.fullmatch(header) + if match: + content_length = int(match.group(1)) + logger.debug("Content length: %s", content_length) + + # Check if all headers have been read (as indicated by an empty line \r\n) + if content_length and not header.strip(): + # Read body + body = await reader.readexactly(content_length) + if not body: + break + + try: + message = json.loads(body, object_hook=protocol.structure_message) + protocol.handle_message(message) + except Exception as exc: + logger.exception("Unable to handle message") + if error_handler: + error_handler(exc, JsonRpcException) + finally: + # Reset + content_length = 0 + + +def run( + stop_event: threading.Event, + reader: Reader, + protocol: JsonRPCProtocol, + logger: logging.Logger | None = None, + error_handler: Callable[[Exception, type[JsonRpcException]], Any] | None = None, +): + """Run a main message processing loop, synchronously + + Parameters + ---------- + stop_event + A ``threading.Event`` used to break the main loop + + reader + The reader to read messages from + + protocol + The protocol instance that should handle the messages + + logger + The logger instance to use + + error_handler + Function to call when an error is encountered. + """ + + CONTENT_LENGTH_PATTERN = re.compile(rb"^Content-Length: (\d+)\r\n$") + content_length = 0 + logger = logger or logging.getLogger(__name__) + + while not stop_event.is_set(): + # Read a header line + header = reader.readline() + if not header: + break + + # Extract content length if possible + if not content_length: + match = CONTENT_LENGTH_PATTERN.fullmatch(header) + if match: + content_length = int(match.group(1)) + logger.debug("Content length: %s", content_length) + + # Check if all headers have been read (as indicated by an empty line \r\n) + if content_length and not header.strip(): + # Read body + body = reader.read(content_length) + if not body: + break + + try: + message = json.loads(body, object_hook=protocol.structure_message) + protocol.handle_message(message) + except Exception as exc: + logger.exception("Unable to handle message") + if error_handler: + error_handler(exc, JsonRpcException) + finally: + # Reset + content_length = 0 + + +async def run_websocket( + websocket: ClientConnection | ServerConnection, + stop_event: threading.Event, + protocol: JsonRPCProtocol, + logger: logging.Logger | None = None, + error_handler: Callable[[Exception, type[JsonRpcException]], Any] | None = None, +): + """Run the main message processing loop, over websockets. + + Parameters + ---------- + stop_event + A ``threading.Event`` used to break the main loop + + websocket + The websocket to read messages from + + protocol + The protocol instance that should handle the messages + + logger + The logger instance to use + + error_handler + Function to call when an error is encountered. + """ + + logger = logger or logging.getLogger(__name__) + protocol.set_writer(WebSocketWriter(websocket), include_headers=False) + + try: + from websockets.exceptions import ConnectionClosed + except ImportError: + logger.exception( + "Run `pip install pygls[ws]` to install dependencies required for websockets." + ) + return + + while not stop_event.is_set(): + try: + logger.debug("waiting for a message...") + data = await websocket.recv(decode=False) + except ConnectionClosed: + logger.debug("Websocket connection closed.") + stop_event.set() + break + + try: + message = json.loads(data, object_hook=protocol.structure_message) + protocol.handle_message(message) + except Exception as exc: + logger.exception("Unable to handle message") + if error_handler: + error_handler(exc, JsonRpcException) + + logger.debug("Exiting main loop") + await websocket.close() diff --git a/server/libs/pygls/lsp/_base_client.py b/server/libs/pygls/lsp/_base_client.py new file mode 100644 index 0000000..54750e2 --- /dev/null +++ b/server/libs/pygls/lsp/_base_client.py @@ -0,0 +1,2018 @@ +############################################################################ +# 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 lsprotocol import types +from pygls.client import JsonRPCClient +from pygls.protocol import LanguageServerProtocol +from pygls.protocol import default_converter +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): + + def __init__( + self, + name: str, + version: str, + protocol_cls: type[LanguageServerProtocol] = LanguageServerProtocol, + converter_factory: Callable[[], cattrs.Converter] = default_converter, + ): + self.name = name + self.version = version + 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[Optional[Sequence[types.CallHierarchyIncomingCall]]]: + """Make a :lsp:`callHierarchy/incomingCalls` request. + + A request to resolve the incoming calls for a given `CallHierarchyItem`. + + @since 3.16.0 + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return self.protocol.send_request("callHierarchy/incomingCalls", params, callback) + + async def call_hierarchy_incoming_calls_async( + self, + params: types.CallHierarchyIncomingCallsParams, + ) -> Optional[Sequence[types.CallHierarchyIncomingCall]]: + """Make a :lsp:`callHierarchy/incomingCalls` request. + + A request to resolve the incoming calls for a given `CallHierarchyItem`. + + @since 3.16.0 + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return await self.protocol.send_request_async("callHierarchy/incomingCalls", params) + + def call_hierarchy_outgoing_calls( + self, + params: types.CallHierarchyOutgoingCallsParams, + callback: Optional[Callable[[Optional[Sequence[types.CallHierarchyOutgoingCall]]], None]] = None, + ) -> Future[Optional[Sequence[types.CallHierarchyOutgoingCall]]]: + """Make a :lsp:`callHierarchy/outgoingCalls` request. + + A request to resolve the outgoing calls for a given `CallHierarchyItem`. + + @since 3.16.0 + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return self.protocol.send_request("callHierarchy/outgoingCalls", params, callback) + + async def call_hierarchy_outgoing_calls_async( + self, + params: types.CallHierarchyOutgoingCallsParams, + ) -> Optional[Sequence[types.CallHierarchyOutgoingCall]]: + """Make a :lsp:`callHierarchy/outgoingCalls` request. + + A request to resolve the outgoing calls for a given `CallHierarchyItem`. + + @since 3.16.0 + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return await self.protocol.send_request_async("callHierarchy/outgoingCalls", params) + + def code_action_resolve( + self, + params: types.CodeAction, + callback: Optional[Callable[[types.CodeAction], None]] = None, + ) -> Future[types.CodeAction]: + """Make a :lsp:`codeAction/resolve` request. + + Request to resolve additional information for a given code action.The request's + parameter is of type {@link CodeAction} the response + is of type {@link CodeAction} or a Thenable that resolves to such. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return self.protocol.send_request("codeAction/resolve", params, callback) + + async def code_action_resolve_async( + self, + params: types.CodeAction, + ) -> types.CodeAction: + """Make a :lsp:`codeAction/resolve` request. + + Request to resolve additional information for a given code action.The request's + parameter is of type {@link CodeAction} the response + is of type {@link CodeAction} or a Thenable that resolves to such. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return await self.protocol.send_request_async("codeAction/resolve", params) + + def code_lens_resolve( + self, + params: types.CodeLens, + callback: Optional[Callable[[types.CodeLens], None]] = None, + ) -> Future[types.CodeLens]: + """Make a :lsp:`codeLens/resolve` request. + + A request to resolve a command for a given code lens. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return self.protocol.send_request("codeLens/resolve", params, callback) + + async def code_lens_resolve_async( + self, + params: types.CodeLens, + ) -> types.CodeLens: + """Make a :lsp:`codeLens/resolve` request. + + A request to resolve a command for a given code lens. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return await self.protocol.send_request_async("codeLens/resolve", params) + + def completion_item_resolve( + self, + params: types.CompletionItem, + callback: Optional[Callable[[types.CompletionItem], None]] = None, + ) -> Future[types.CompletionItem]: + """Make a :lsp:`completionItem/resolve` request. + + Request to resolve additional information for a given completion item.The request's + parameter is of type {@link CompletionItem} the response + is of type {@link CompletionItem} or a Thenable that resolves to such. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return self.protocol.send_request("completionItem/resolve", params, callback) + + async def completion_item_resolve_async( + self, + params: types.CompletionItem, + ) -> types.CompletionItem: + """Make a :lsp:`completionItem/resolve` request. + + Request to resolve additional information for a given completion item.The request's + parameter is of type {@link CompletionItem} the response + is of type {@link CompletionItem} or a Thenable that resolves to such. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return await self.protocol.send_request_async("completionItem/resolve", params) + + def document_link_resolve( + self, + params: types.DocumentLink, + callback: Optional[Callable[[types.DocumentLink], None]] = None, + ) -> Future[types.DocumentLink]: + """Make a :lsp:`documentLink/resolve` request. + + Request to resolve additional information for a given document link. The request's + parameter is of type {@link DocumentLink} the response + is of type {@link DocumentLink} or a Thenable that resolves to such. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return self.protocol.send_request("documentLink/resolve", params, callback) + + async def document_link_resolve_async( + self, + params: types.DocumentLink, + ) -> types.DocumentLink: + """Make a :lsp:`documentLink/resolve` request. + + Request to resolve additional information for a given document link. The request's + parameter is of type {@link DocumentLink} the response + is of type {@link DocumentLink} or a Thenable that resolves to such. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return await self.protocol.send_request_async("documentLink/resolve", params) + + def initialize( + self, + params: types.InitializeParams, + callback: Optional[Callable[[types.InitializeResult], None]] = None, + ) -> Future[types.InitializeResult]: + """Make a :lsp:`initialize` request. + + The initialize request is sent from the client to the server. + It is sent once as the request after starting up the server. + The requests parameter is of type {@link InitializeParams} + the response if of type {@link InitializeResult} of a Thenable that + resolves to such. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return self.protocol.send_request("initialize", params, callback) + + async def initialize_async( + self, + params: types.InitializeParams, + ) -> types.InitializeResult: + """Make a :lsp:`initialize` request. + + The initialize request is sent from the client to the server. + It is sent once as the request after starting up the server. + The requests parameter is of type {@link InitializeParams} + the response if of type {@link InitializeResult} of a Thenable that + resolves to such. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return await self.protocol.send_request_async("initialize", params) + + def inlay_hint_resolve( + self, + params: types.InlayHint, + callback: Optional[Callable[[types.InlayHint], None]] = None, + ) -> Future[types.InlayHint]: + """Make a :lsp:`inlayHint/resolve` request. + + A request to resolve additional properties for an inlay hint. + The request's parameter is of type {@link InlayHint}, the response is + of type {@link InlayHint} or a Thenable that resolves to such. + + @since 3.17.0 + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return self.protocol.send_request("inlayHint/resolve", params, callback) + + async def inlay_hint_resolve_async( + self, + params: types.InlayHint, + ) -> types.InlayHint: + """Make a :lsp:`inlayHint/resolve` request. + + A request to resolve additional properties for an inlay hint. + The request's parameter is of type {@link InlayHint}, the response is + of type {@link InlayHint} or a Thenable that resolves to such. + + @since 3.17.0 + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return await self.protocol.send_request_async("inlayHint/resolve", params) + + def shutdown( + self, + params: None, + callback: Optional[Callable[[None], None]] = None, + ) -> Future[None]: + """Make a :lsp:`shutdown` request. + + A shutdown request is sent from the client to the server. + It is sent once when the client decides to shutdown the + server. The only notification that is sent after a shutdown request + is the exit event. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return self.protocol.send_request("shutdown", params, callback) + + async def shutdown_async( + self, + params: None, + ) -> None: + """Make a :lsp:`shutdown` request. + + A shutdown request is sent from the client to the server. + It is sent once when the client decides to shutdown the + server. The only notification that is sent after a shutdown request + is the exit event. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return await self.protocol.send_request_async("shutdown", params) + + def text_document_code_action( + self, + params: types.CodeActionParams, + callback: Optional[Callable[[Optional[Sequence[Union[types.Command, types.CodeAction]]]], None]] = None, + ) -> 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. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return self.protocol.send_request("textDocument/codeAction", params, callback) + + async def text_document_code_action_async( + self, + params: types.CodeActionParams, + ) -> 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. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return await self.protocol.send_request_async("textDocument/codeAction", params) + + def text_document_code_lens( + self, + params: types.CodeLensParams, + callback: Optional[Callable[[Optional[Sequence[types.CodeLens]]], None]] = None, + ) -> Future[Optional[Sequence[types.CodeLens]]]: + """Make a :lsp:`textDocument/codeLens` request. + + A request to provide code lens for the given text document. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return self.protocol.send_request("textDocument/codeLens", params, callback) + + async def text_document_code_lens_async( + self, + params: types.CodeLensParams, + ) -> Optional[Sequence[types.CodeLens]]: + """Make a :lsp:`textDocument/codeLens` request. + + A request to provide code lens for the given text document. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return await self.protocol.send_request_async("textDocument/codeLens", params) + + def text_document_color_presentation( + self, + params: types.ColorPresentationParams, + callback: Optional[Callable[[Sequence[types.ColorPresentation]], None]] = None, + ) -> Future[Sequence[types.ColorPresentation]]: + """Make a :lsp:`textDocument/colorPresentation` request. + + A request to list all presentation for a color. The request's + parameter is of type {@link ColorPresentationParams} the + response is of type {@link ColorInformation ColorInformation[]} or a Thenable + that resolves to such. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return self.protocol.send_request("textDocument/colorPresentation", params, callback) + + async def text_document_color_presentation_async( + self, + params: types.ColorPresentationParams, + ) -> Sequence[types.ColorPresentation]: + """Make a :lsp:`textDocument/colorPresentation` request. + + A request to list all presentation for a color. The request's + parameter is of type {@link ColorPresentationParams} the + response is of type {@link ColorInformation ColorInformation[]} or a Thenable + that resolves to such. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return await self.protocol.send_request_async("textDocument/colorPresentation", params) + + def text_document_completion( + self, + params: types.CompletionParams, + callback: Optional[Callable[[Union[Sequence[types.CompletionItem], types.CompletionList, None]], None]] = None, + ) -> 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 + parameter is of type {@link TextDocumentPosition} the response + is of type {@link CompletionItem CompletionItem[]} or {@link CompletionList} + or a Thenable that resolves to such. + + The request can delay the computation of the {@link CompletionItem.detail `detail`} + and {@link CompletionItem.documentation `documentation`} properties to the `completionItem/resolve` + request. However, properties that are needed for the initial sorting and filtering, like `sortText`, + `filterText`, `insertText`, and `textEdit`, must not be changed during resolve. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return self.protocol.send_request("textDocument/completion", params, callback) + + async def text_document_completion_async( + self, + params: types.CompletionParams, + ) -> 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 + parameter is of type {@link TextDocumentPosition} the response + is of type {@link CompletionItem CompletionItem[]} or {@link CompletionList} + or a Thenable that resolves to such. + + The request can delay the computation of the {@link CompletionItem.detail `detail`} + and {@link CompletionItem.documentation `documentation`} properties to the `completionItem/resolve` + request. However, properties that are needed for the initial sorting and filtering, like `sortText`, + `filterText`, `insertText`, and `textEdit`, must not be changed during resolve. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return await self.protocol.send_request_async("textDocument/completion", params) + + def text_document_declaration( + self, + params: types.DeclarationParams, + callback: Optional[Callable[[Union[types.Location, Sequence[types.Location], Sequence[types.LocationLink], None]], None]] = None, + ) -> 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 + document position. The request's parameter is of type {@link TextDocumentPositionParams} + the response is of type {@link Declaration} or a typed array of {@link DeclarationLink} + or a Thenable that resolves to such. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return self.protocol.send_request("textDocument/declaration", params, callback) + + async def text_document_declaration_async( + self, + params: types.DeclarationParams, + ) -> 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 + document position. The request's parameter is of type {@link TextDocumentPositionParams} + the response is of type {@link Declaration} or a typed array of {@link DeclarationLink} + or a Thenable that resolves to such. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return await self.protocol.send_request_async("textDocument/declaration", params) + + def text_document_definition( + self, + params: types.DefinitionParams, + callback: Optional[Callable[[Union[types.Location, Sequence[types.Location], Sequence[types.LocationLink], None]], None]] = None, + ) -> 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 + document position. The request's parameter is of type {@link TextDocumentPosition} + the response is of either type {@link Definition} or a typed array of + {@link DefinitionLink} or a Thenable that resolves to such. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return self.protocol.send_request("textDocument/definition", params, callback) + + async def text_document_definition_async( + self, + params: types.DefinitionParams, + ) -> 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 + document position. The request's parameter is of type {@link TextDocumentPosition} + the response is of either type {@link Definition} or a typed array of + {@link DefinitionLink} or a Thenable that resolves to such. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return await self.protocol.send_request_async("textDocument/definition", params) + + def text_document_diagnostic( + self, + params: types.DocumentDiagnosticParams, + callback: Optional[Callable[[Union[types.RelatedFullDocumentDiagnosticReport, types.RelatedUnchangedDocumentDiagnosticReport]], None]] = None, + ) -> Future[Union[types.RelatedFullDocumentDiagnosticReport, types.RelatedUnchangedDocumentDiagnosticReport]]: + """Make a :lsp:`textDocument/diagnostic` request. + + The document diagnostic request definition. + + @since 3.17.0 + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return self.protocol.send_request("textDocument/diagnostic", params, callback) + + async def text_document_diagnostic_async( + self, + params: types.DocumentDiagnosticParams, + ) -> Union[types.RelatedFullDocumentDiagnosticReport, types.RelatedUnchangedDocumentDiagnosticReport]: + """Make a :lsp:`textDocument/diagnostic` request. + + The document diagnostic request definition. + + @since 3.17.0 + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return await self.protocol.send_request_async("textDocument/diagnostic", params) + + def text_document_document_color( + self, + params: types.DocumentColorParams, + callback: Optional[Callable[[Sequence[types.ColorInformation]], None]] = None, + ) -> 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 + parameter is of type {@link DocumentColorParams} the + response is of type {@link ColorInformation ColorInformation[]} or a Thenable + that resolves to such. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return self.protocol.send_request("textDocument/documentColor", params, callback) + + async def text_document_document_color_async( + self, + params: types.DocumentColorParams, + ) -> 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 + parameter is of type {@link DocumentColorParams} the + response is of type {@link ColorInformation ColorInformation[]} or a Thenable + that resolves to such. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return await self.protocol.send_request_async("textDocument/documentColor", params) + + def text_document_document_highlight( + self, + params: types.DocumentHighlightParams, + callback: Optional[Callable[[Optional[Sequence[types.DocumentHighlight]]], None]] = None, + ) -> Future[Optional[Sequence[types.DocumentHighlight]]]: + """Make a :lsp:`textDocument/documentHighlight` request. + + Request to resolve a {@link DocumentHighlight} for a given + text document position. The request's parameter is of type {@link TextDocumentPosition} + the request response is an array of type {@link DocumentHighlight} + or a Thenable that resolves to such. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return self.protocol.send_request("textDocument/documentHighlight", params, callback) + + async def text_document_document_highlight_async( + self, + params: types.DocumentHighlightParams, + ) -> Optional[Sequence[types.DocumentHighlight]]: + """Make a :lsp:`textDocument/documentHighlight` request. + + Request to resolve a {@link DocumentHighlight} for a given + text document position. The request's parameter is of type {@link TextDocumentPosition} + the request response is an array of type {@link DocumentHighlight} + or a Thenable that resolves to such. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return await self.protocol.send_request_async("textDocument/documentHighlight", params) + + def text_document_document_link( + self, + params: types.DocumentLinkParams, + callback: Optional[Callable[[Optional[Sequence[types.DocumentLink]]], None]] = None, + ) -> Future[Optional[Sequence[types.DocumentLink]]]: + """Make a :lsp:`textDocument/documentLink` request. + + A request to provide document links + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return self.protocol.send_request("textDocument/documentLink", params, callback) + + async def text_document_document_link_async( + self, + params: types.DocumentLinkParams, + ) -> Optional[Sequence[types.DocumentLink]]: + """Make a :lsp:`textDocument/documentLink` request. + + A request to provide document links + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return await self.protocol.send_request_async("textDocument/documentLink", params) + + def text_document_document_symbol( + self, + params: types.DocumentSymbolParams, + callback: Optional[Callable[[Union[Sequence[types.SymbolInformation], Sequence[types.DocumentSymbol], None]], None]] = None, + ) -> 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 + parameter is of type {@link TextDocumentIdentifier} the + response is of type {@link SymbolInformation SymbolInformation[]} or a Thenable + that resolves to such. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return self.protocol.send_request("textDocument/documentSymbol", params, callback) + + async def text_document_document_symbol_async( + self, + params: types.DocumentSymbolParams, + ) -> 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 + parameter is of type {@link TextDocumentIdentifier} the + response is of type {@link SymbolInformation SymbolInformation[]} or a Thenable + that resolves to such. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return await self.protocol.send_request_async("textDocument/documentSymbol", params) + + def text_document_folding_range( + self, + params: types.FoldingRangeParams, + callback: Optional[Callable[[Optional[Sequence[types.FoldingRange]]], None]] = None, + ) -> Future[Optional[Sequence[types.FoldingRange]]]: + """Make a :lsp:`textDocument/foldingRange` request. + + A request to provide folding ranges in a document. The request's + parameter is of type {@link FoldingRangeParams}, the + response is of type {@link FoldingRangeList} or a Thenable + that resolves to such. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return self.protocol.send_request("textDocument/foldingRange", params, callback) + + async def text_document_folding_range_async( + self, + params: types.FoldingRangeParams, + ) -> Optional[Sequence[types.FoldingRange]]: + """Make a :lsp:`textDocument/foldingRange` request. + + A request to provide folding ranges in a document. The request's + parameter is of type {@link FoldingRangeParams}, the + response is of type {@link FoldingRangeList} or a Thenable + that resolves to such. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return await self.protocol.send_request_async("textDocument/foldingRange", params) + + def text_document_formatting( + self, + params: types.DocumentFormattingParams, + callback: Optional[Callable[[Optional[Sequence[types.TextEdit]]], None]] = None, + ) -> Future[Optional[Sequence[types.TextEdit]]]: + """Make a :lsp:`textDocument/formatting` request. + + A request to format a whole document. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return self.protocol.send_request("textDocument/formatting", params, callback) + + async def text_document_formatting_async( + self, + params: types.DocumentFormattingParams, + ) -> Optional[Sequence[types.TextEdit]]: + """Make a :lsp:`textDocument/formatting` request. + + A request to format a whole document. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return await self.protocol.send_request_async("textDocument/formatting", params) + + def text_document_hover( + self, + params: types.HoverParams, + callback: Optional[Callable[[Optional[types.Hover]], None]] = None, + ) -> Future[Optional[types.Hover]]: + """Make a :lsp:`textDocument/hover` request. + + Request to request hover information at a given text document position. The request's + parameter is of type {@link TextDocumentPosition} the response is of + type {@link Hover} or a Thenable that resolves to such. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return self.protocol.send_request("textDocument/hover", params, callback) + + async def text_document_hover_async( + self, + params: types.HoverParams, + ) -> Optional[types.Hover]: + """Make a :lsp:`textDocument/hover` request. + + Request to request hover information at a given text document position. The request's + parameter is of type {@link TextDocumentPosition} the response is of + type {@link Hover} or a Thenable that resolves to such. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return await self.protocol.send_request_async("textDocument/hover", params) + + def text_document_implementation( + self, + params: types.ImplementationParams, + callback: Optional[Callable[[Union[types.Location, Sequence[types.Location], Sequence[types.LocationLink], None]], None]] = None, + ) -> 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 + document position. The request's parameter is of type {@link TextDocumentPositionParams} + the response is of type {@link Definition} or a Thenable that resolves to such. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return self.protocol.send_request("textDocument/implementation", params, callback) + + async def text_document_implementation_async( + self, + params: types.ImplementationParams, + ) -> 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 + document position. The request's parameter is of type {@link TextDocumentPositionParams} + the response is of type {@link Definition} or a Thenable that resolves to such. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return await self.protocol.send_request_async("textDocument/implementation", params) + + def text_document_inlay_hint( + self, + params: types.InlayHintParams, + callback: Optional[Callable[[Optional[Sequence[types.InlayHint]]], None]] = None, + ) -> 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 + type {@link InlayHintsParams}, the response is of type + {@link InlayHint InlayHint[]} or a Thenable that resolves to such. + + @since 3.17.0 + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return self.protocol.send_request("textDocument/inlayHint", params, callback) + + async def text_document_inlay_hint_async( + self, + params: types.InlayHintParams, + ) -> 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 + type {@link InlayHintsParams}, the response is of type + {@link InlayHint InlayHint[]} or a Thenable that resolves to such. + + @since 3.17.0 + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return await self.protocol.send_request_async("textDocument/inlayHint", params) + + def text_document_inline_completion( + self, + params: types.InlineCompletionParams, + callback: Optional[Callable[[Union[types.InlineCompletionList, Sequence[types.InlineCompletionItem], None]], None]] = None, + ) -> 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 + type {@link InlineCompletionParams}, the response is of type + {@link InlineCompletion InlineCompletion[]} or a Thenable that resolves to such. + + @since 3.18.0 + @proposed + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return self.protocol.send_request("textDocument/inlineCompletion", params, callback) + + async def text_document_inline_completion_async( + self, + params: types.InlineCompletionParams, + ) -> 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 + type {@link InlineCompletionParams}, the response is of type + {@link InlineCompletion InlineCompletion[]} or a Thenable that resolves to such. + + @since 3.18.0 + @proposed + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return await self.protocol.send_request_async("textDocument/inlineCompletion", params) + + def text_document_inline_value( + self, + params: types.InlineValueParams, + callback: Optional[Callable[[Optional[Sequence[Union[types.InlineValueText, types.InlineValueVariableLookup, types.InlineValueEvaluatableExpression]]]], None]] = None, + ) -> 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 + type {@link InlineValueParams}, the response is of type + {@link InlineValue InlineValue[]} or a Thenable that resolves to such. + + @since 3.17.0 + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return self.protocol.send_request("textDocument/inlineValue", params, callback) + + async def text_document_inline_value_async( + self, + params: types.InlineValueParams, + ) -> 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 + type {@link InlineValueParams}, the response is of type + {@link InlineValue InlineValue[]} or a Thenable that resolves to such. + + @since 3.17.0 + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return await self.protocol.send_request_async("textDocument/inlineValue", params) + + def text_document_linked_editing_range( + self, + params: types.LinkedEditingRangeParams, + callback: Optional[Callable[[Optional[types.LinkedEditingRanges]], None]] = None, + ) -> Future[Optional[types.LinkedEditingRanges]]: + """Make a :lsp:`textDocument/linkedEditingRange` request. + + A request to provide ranges that can be edited together. + + @since 3.16.0 + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return self.protocol.send_request("textDocument/linkedEditingRange", params, callback) + + async def text_document_linked_editing_range_async( + self, + params: types.LinkedEditingRangeParams, + ) -> Optional[types.LinkedEditingRanges]: + """Make a :lsp:`textDocument/linkedEditingRange` request. + + A request to provide ranges that can be edited together. + + @since 3.16.0 + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return await self.protocol.send_request_async("textDocument/linkedEditingRange", params) + + def text_document_moniker( + self, + params: types.MonikerParams, + callback: Optional[Callable[[Optional[Sequence[types.Moniker]]], None]] = None, + ) -> 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. + The request parameter is of type {@link TextDocumentPositionParams}. + The response is of type {@link Moniker Moniker[]} or `null`. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return self.protocol.send_request("textDocument/moniker", params, callback) + + async def text_document_moniker_async( + self, + params: types.MonikerParams, + ) -> 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. + The request parameter is of type {@link TextDocumentPositionParams}. + The response is of type {@link Moniker Moniker[]} or `null`. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return await self.protocol.send_request_async("textDocument/moniker", params) + + def text_document_on_type_formatting( + self, + params: types.DocumentOnTypeFormattingParams, + callback: Optional[Callable[[Optional[Sequence[types.TextEdit]]], None]] = None, + ) -> Future[Optional[Sequence[types.TextEdit]]]: + """Make a :lsp:`textDocument/onTypeFormatting` request. + + A request to format a document on type. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return self.protocol.send_request("textDocument/onTypeFormatting", params, callback) + + async def text_document_on_type_formatting_async( + self, + params: types.DocumentOnTypeFormattingParams, + ) -> Optional[Sequence[types.TextEdit]]: + """Make a :lsp:`textDocument/onTypeFormatting` request. + + A request to format a document on type. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return await self.protocol.send_request_async("textDocument/onTypeFormatting", params) + + def text_document_prepare_call_hierarchy( + self, + params: types.CallHierarchyPrepareParams, + callback: Optional[Callable[[Optional[Sequence[types.CallHierarchyItem]]], None]] = None, + ) -> Future[Optional[Sequence[types.CallHierarchyItem]]]: + """Make a :lsp:`textDocument/prepareCallHierarchy` request. + + A request to result a `CallHierarchyItem` in a document at a given position. + Can be used as an input to an incoming or outgoing call hierarchy. + + @since 3.16.0 + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return self.protocol.send_request("textDocument/prepareCallHierarchy", params, callback) + + async def text_document_prepare_call_hierarchy_async( + self, + params: types.CallHierarchyPrepareParams, + ) -> Optional[Sequence[types.CallHierarchyItem]]: + """Make a :lsp:`textDocument/prepareCallHierarchy` request. + + A request to result a `CallHierarchyItem` in a document at a given position. + Can be used as an input to an incoming or outgoing call hierarchy. + + @since 3.16.0 + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return await self.protocol.send_request_async("textDocument/prepareCallHierarchy", params) + + def text_document_prepare_rename( + self, + params: types.PrepareRenameParams, + callback: Optional[Callable[[Union[types.Range, types.PrepareRenamePlaceholder, types.PrepareRenameDefaultBehavior, None]], None]] = None, + ) -> 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. + + @since 3.16 - support for default behavior + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return self.protocol.send_request("textDocument/prepareRename", params, callback) + + async def text_document_prepare_rename_async( + self, + params: types.PrepareRenameParams, + ) -> 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. + + @since 3.16 - support for default behavior + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return await self.protocol.send_request_async("textDocument/prepareRename", params) + + def text_document_prepare_type_hierarchy( + self, + params: types.TypeHierarchyPrepareParams, + callback: Optional[Callable[[Optional[Sequence[types.TypeHierarchyItem]]], None]] = None, + ) -> Future[Optional[Sequence[types.TypeHierarchyItem]]]: + """Make a :lsp:`textDocument/prepareTypeHierarchy` request. + + A request to result a `TypeHierarchyItem` in a document at a given position. + Can be used as an input to a subtypes or supertypes type hierarchy. + + @since 3.17.0 + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return self.protocol.send_request("textDocument/prepareTypeHierarchy", params, callback) + + async def text_document_prepare_type_hierarchy_async( + self, + params: types.TypeHierarchyPrepareParams, + ) -> Optional[Sequence[types.TypeHierarchyItem]]: + """Make a :lsp:`textDocument/prepareTypeHierarchy` request. + + A request to result a `TypeHierarchyItem` in a document at a given position. + Can be used as an input to a subtypes or supertypes type hierarchy. + + @since 3.17.0 + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return await self.protocol.send_request_async("textDocument/prepareTypeHierarchy", params) + + def text_document_ranges_formatting( + self, + params: types.DocumentRangesFormattingParams, + callback: Optional[Callable[[Optional[Sequence[types.TextEdit]]], None]] = None, + ) -> Future[Optional[Sequence[types.TextEdit]]]: + """Make a :lsp:`textDocument/rangesFormatting` request. + + A request to format ranges in a document. + + @since 3.18.0 + @proposed + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return self.protocol.send_request("textDocument/rangesFormatting", params, callback) + + async def text_document_ranges_formatting_async( + self, + params: types.DocumentRangesFormattingParams, + ) -> Optional[Sequence[types.TextEdit]]: + """Make a :lsp:`textDocument/rangesFormatting` request. + + A request to format ranges in a document. + + @since 3.18.0 + @proposed + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return await self.protocol.send_request_async("textDocument/rangesFormatting", params) + + def text_document_range_formatting( + self, + params: types.DocumentRangeFormattingParams, + callback: Optional[Callable[[Optional[Sequence[types.TextEdit]]], None]] = None, + ) -> Future[Optional[Sequence[types.TextEdit]]]: + """Make a :lsp:`textDocument/rangeFormatting` request. + + A request to format a range in a document. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return self.protocol.send_request("textDocument/rangeFormatting", params, callback) + + async def text_document_range_formatting_async( + self, + params: types.DocumentRangeFormattingParams, + ) -> Optional[Sequence[types.TextEdit]]: + """Make a :lsp:`textDocument/rangeFormatting` request. + + A request to format a range in a document. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return await self.protocol.send_request_async("textDocument/rangeFormatting", params) + + def text_document_references( + self, + params: types.ReferenceParams, + callback: Optional[Callable[[Optional[Sequence[types.Location]]], None]] = None, + ) -> Future[Optional[Sequence[types.Location]]]: + """Make a :lsp:`textDocument/references` request. + + A request to resolve project-wide references for the symbol denoted + by the given text document position. The request's parameter is of + type {@link ReferenceParams} the response is of type + {@link Location Location[]} or a Thenable that resolves to such. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return self.protocol.send_request("textDocument/references", params, callback) + + async def text_document_references_async( + self, + params: types.ReferenceParams, + ) -> Optional[Sequence[types.Location]]: + """Make a :lsp:`textDocument/references` request. + + A request to resolve project-wide references for the symbol denoted + by the given text document position. The request's parameter is of + type {@link ReferenceParams} the response is of type + {@link Location Location[]} or a Thenable that resolves to such. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return await self.protocol.send_request_async("textDocument/references", params) + + def text_document_rename( + self, + params: types.RenameParams, + callback: Optional[Callable[[Optional[types.WorkspaceEdit]], None]] = None, + ) -> Future[Optional[types.WorkspaceEdit]]: + """Make a :lsp:`textDocument/rename` request. + + A request to rename a symbol. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return self.protocol.send_request("textDocument/rename", params, callback) + + async def text_document_rename_async( + self, + params: types.RenameParams, + ) -> Optional[types.WorkspaceEdit]: + """Make a :lsp:`textDocument/rename` request. + + A request to rename a symbol. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return await self.protocol.send_request_async("textDocument/rename", params) + + def text_document_selection_range( + self, + params: types.SelectionRangeParams, + callback: Optional[Callable[[Optional[Sequence[types.SelectionRange]]], None]] = None, + ) -> Future[Optional[Sequence[types.SelectionRange]]]: + """Make a :lsp:`textDocument/selectionRange` request. + + A request to provide selection ranges in a document. The request's + parameter is of type {@link SelectionRangeParams}, the + response is of type {@link SelectionRange SelectionRange[]} or a Thenable + that resolves to such. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return self.protocol.send_request("textDocument/selectionRange", params, callback) + + async def text_document_selection_range_async( + self, + params: types.SelectionRangeParams, + ) -> Optional[Sequence[types.SelectionRange]]: + """Make a :lsp:`textDocument/selectionRange` request. + + A request to provide selection ranges in a document. The request's + parameter is of type {@link SelectionRangeParams}, the + response is of type {@link SelectionRange SelectionRange[]} or a Thenable + that resolves to such. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return await self.protocol.send_request_async("textDocument/selectionRange", params) + + def text_document_semantic_tokens_full( + self, + params: types.SemanticTokensParams, + callback: Optional[Callable[[Optional[types.SemanticTokens]], None]] = None, + ) -> Future[Optional[types.SemanticTokens]]: + """Make a :lsp:`textDocument/semanticTokens/full` request. + + @since 3.16.0 + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return self.protocol.send_request("textDocument/semanticTokens/full", params, callback) + + async def text_document_semantic_tokens_full_async( + self, + params: types.SemanticTokensParams, + ) -> Optional[types.SemanticTokens]: + """Make a :lsp:`textDocument/semanticTokens/full` request. + + @since 3.16.0 + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return await self.protocol.send_request_async("textDocument/semanticTokens/full", params) + + def text_document_semantic_tokens_full_delta( + self, + params: types.SemanticTokensDeltaParams, + callback: Optional[Callable[[Union[types.SemanticTokens, types.SemanticTokensDelta, None]], None]] = None, + ) -> Future[Union[types.SemanticTokens, types.SemanticTokensDelta, None]]: + """Make a :lsp:`textDocument/semanticTokens/full/delta` request. + + @since 3.16.0 + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return self.protocol.send_request("textDocument/semanticTokens/full/delta", params, callback) + + async def text_document_semantic_tokens_full_delta_async( + self, + params: types.SemanticTokensDeltaParams, + ) -> Union[types.SemanticTokens, types.SemanticTokensDelta, None]: + """Make a :lsp:`textDocument/semanticTokens/full/delta` request. + + @since 3.16.0 + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return await self.protocol.send_request_async("textDocument/semanticTokens/full/delta", params) + + def text_document_semantic_tokens_range( + self, + params: types.SemanticTokensRangeParams, + callback: Optional[Callable[[Optional[types.SemanticTokens]], None]] = None, + ) -> Future[Optional[types.SemanticTokens]]: + """Make a :lsp:`textDocument/semanticTokens/range` request. + + @since 3.16.0 + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return self.protocol.send_request("textDocument/semanticTokens/range", params, callback) + + async def text_document_semantic_tokens_range_async( + self, + params: types.SemanticTokensRangeParams, + ) -> Optional[types.SemanticTokens]: + """Make a :lsp:`textDocument/semanticTokens/range` request. + + @since 3.16.0 + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return await self.protocol.send_request_async("textDocument/semanticTokens/range", params) + + def text_document_signature_help( + self, + params: types.SignatureHelpParams, + callback: Optional[Callable[[Optional[types.SignatureHelp]], None]] = None, + ) -> Future[Optional[types.SignatureHelp]]: + """Make a :lsp:`textDocument/signatureHelp` request. + + + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return self.protocol.send_request("textDocument/signatureHelp", params, callback) + + async def text_document_signature_help_async( + self, + params: types.SignatureHelpParams, + ) -> Optional[types.SignatureHelp]: + """Make a :lsp:`textDocument/signatureHelp` request. + + + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return await self.protocol.send_request_async("textDocument/signatureHelp", params) + + 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[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 + document position. The request's parameter is of type {@link TextDocumentPositionParams} + the response is of type {@link Definition} or a Thenable that resolves to such. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return self.protocol.send_request("textDocument/typeDefinition", params, callback) + + async def text_document_type_definition_async( + self, + params: types.TypeDefinitionParams, + ) -> 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 + document position. The request's parameter is of type {@link TextDocumentPositionParams} + the response is of type {@link Definition} or a Thenable that resolves to such. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return await self.protocol.send_request_async("textDocument/typeDefinition", params) + + def text_document_will_save_wait_until( + self, + params: types.WillSaveTextDocumentParams, + callback: Optional[Callable[[Optional[Sequence[types.TextEdit]]], None]] = None, + ) -> 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 + the document is actually saved. The request can return an array of TextEdits + which will be applied to the text document before it is saved. Please note that + clients might drop results if computing the text edits took too long or if a + server constantly fails on this request. This is done to keep the save fast and + reliable. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return self.protocol.send_request("textDocument/willSaveWaitUntil", params, callback) + + async def text_document_will_save_wait_until_async( + self, + params: types.WillSaveTextDocumentParams, + ) -> Optional[Sequence[types.TextEdit]]: + """Make a :lsp:`textDocument/willSaveWaitUntil` request. + + A document will save request is sent from the client to the server before + the document is actually saved. The request can return an array of TextEdits + which will be applied to the text document before it is saved. Please note that + clients might drop results if computing the text edits took too long or if a + server constantly fails on this request. This is done to keep the save fast and + reliable. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return await self.protocol.send_request_async("textDocument/willSaveWaitUntil", params) + + def type_hierarchy_subtypes( + self, + params: types.TypeHierarchySubtypesParams, + callback: Optional[Callable[[Optional[Sequence[types.TypeHierarchyItem]]], None]] = None, + ) -> Future[Optional[Sequence[types.TypeHierarchyItem]]]: + """Make a :lsp:`typeHierarchy/subtypes` request. + + A request to resolve the subtypes for a given `TypeHierarchyItem`. + + @since 3.17.0 + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return self.protocol.send_request("typeHierarchy/subtypes", params, callback) + + async def type_hierarchy_subtypes_async( + self, + params: types.TypeHierarchySubtypesParams, + ) -> Optional[Sequence[types.TypeHierarchyItem]]: + """Make a :lsp:`typeHierarchy/subtypes` request. + + A request to resolve the subtypes for a given `TypeHierarchyItem`. + + @since 3.17.0 + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return await self.protocol.send_request_async("typeHierarchy/subtypes", params) + + def type_hierarchy_supertypes( + self, + params: types.TypeHierarchySupertypesParams, + callback: Optional[Callable[[Optional[Sequence[types.TypeHierarchyItem]]], None]] = None, + ) -> Future[Optional[Sequence[types.TypeHierarchyItem]]]: + """Make a :lsp:`typeHierarchy/supertypes` request. + + A request to resolve the supertypes for a given `TypeHierarchyItem`. + + @since 3.17.0 + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return self.protocol.send_request("typeHierarchy/supertypes", params, callback) + + async def type_hierarchy_supertypes_async( + self, + params: types.TypeHierarchySupertypesParams, + ) -> Optional[Sequence[types.TypeHierarchyItem]]: + """Make a :lsp:`typeHierarchy/supertypes` request. + + A request to resolve the supertypes for a given `TypeHierarchyItem`. + + @since 3.17.0 + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return await self.protocol.send_request_async("typeHierarchy/supertypes", params) + + def workspace_diagnostic( + self, + params: types.WorkspaceDiagnosticParams, + callback: Optional[Callable[[types.WorkspaceDiagnosticReport], None]] = None, + ) -> Future[types.WorkspaceDiagnosticReport]: + """Make a :lsp:`workspace/diagnostic` request. + + The workspace diagnostic request definition. + + @since 3.17.0 + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return self.protocol.send_request("workspace/diagnostic", params, callback) + + async def workspace_diagnostic_async( + self, + params: types.WorkspaceDiagnosticParams, + ) -> types.WorkspaceDiagnosticReport: + """Make a :lsp:`workspace/diagnostic` request. + + The workspace diagnostic request definition. + + @since 3.17.0 + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return await self.protocol.send_request_async("workspace/diagnostic", params) + + def workspace_execute_command( + self, + params: types.ExecuteCommandParams, + callback: Optional[Callable[[Optional[Any]], None]] = None, + ) -> 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 + a workspace edit which the client will apply to the workspace. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return self.protocol.send_request("workspace/executeCommand", params, callback) + + async def workspace_execute_command_async( + self, + params: types.ExecuteCommandParams, + ) -> 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 + a workspace edit which the client will apply to the workspace. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return await self.protocol.send_request_async("workspace/executeCommand", params) + + def workspace_symbol( + self, + params: types.WorkspaceSymbolParams, + callback: Optional[Callable[[Union[Sequence[types.SymbolInformation], Sequence[types.WorkspaceSymbol], None]], None]] = None, + ) -> 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 + by the {@link WorkspaceSymbolParams}. The response is + of type {@link SymbolInformation SymbolInformation[]} or a Thenable that + resolves to such. + + @since 3.17.0 - support for WorkspaceSymbol in the returned data. Clients + need to advertise support for WorkspaceSymbols via the client capability + `workspace.symbol.resolveSupport`. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return self.protocol.send_request("workspace/symbol", params, callback) + + async def workspace_symbol_async( + self, + params: types.WorkspaceSymbolParams, + ) -> 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 + by the {@link WorkspaceSymbolParams}. The response is + of type {@link SymbolInformation SymbolInformation[]} or a Thenable that + resolves to such. + + @since 3.17.0 - support for WorkspaceSymbol in the returned data. Clients + need to advertise support for WorkspaceSymbols via the client capability + `workspace.symbol.resolveSupport`. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return await self.protocol.send_request_async("workspace/symbol", params) + + def workspace_symbol_resolve( + self, + params: types.WorkspaceSymbol, + callback: Optional[Callable[[types.WorkspaceSymbol], None]] = None, + ) -> Future[types.WorkspaceSymbol]: + """Make a :lsp:`workspaceSymbol/resolve` request. + + A request to resolve the range inside the workspace + symbol's location. + + @since 3.17.0 + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return self.protocol.send_request("workspaceSymbol/resolve", params, callback) + + async def workspace_symbol_resolve_async( + self, + params: types.WorkspaceSymbol, + ) -> types.WorkspaceSymbol: + """Make a :lsp:`workspaceSymbol/resolve` request. + + A request to resolve the range inside the workspace + symbol's location. + + @since 3.17.0 + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return await self.protocol.send_request_async("workspaceSymbol/resolve", params) + + def workspace_text_document_content( + self, + params: types.TextDocumentContentParams, + callback: Optional[Callable[[types.TextDocumentContentResult], None]] = None, + ) -> Future[types.TextDocumentContentResult]: + """Make a :lsp:`workspace/textDocumentContent` request. + + The `workspace/textDocumentContent` request is sent from the client to the + server to request the content of a text document. + + @since 3.18.0 + @proposed + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return self.protocol.send_request("workspace/textDocumentContent", params, callback) + + async def workspace_text_document_content_async( + self, + params: types.TextDocumentContentParams, + ) -> types.TextDocumentContentResult: + """Make a :lsp:`workspace/textDocumentContent` request. + + The `workspace/textDocumentContent` request is sent from the client to the + server to request the content of a text document. + + @since 3.18.0 + @proposed + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return await self.protocol.send_request_async("workspace/textDocumentContent", params) + + def workspace_will_create_files( + self, + params: types.CreateFilesParams, + callback: Optional[Callable[[Optional[types.WorkspaceEdit]], None]] = None, + ) -> 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 + created as long as the creation is triggered from within the client. + + The request can return a `WorkspaceEdit` which will be applied to workspace before the + files are created. Hence the `WorkspaceEdit` can not manipulate the content of the file + to be created. + + @since 3.16.0 + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return self.protocol.send_request("workspace/willCreateFiles", params, callback) + + async def workspace_will_create_files_async( + self, + params: types.CreateFilesParams, + ) -> 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 + created as long as the creation is triggered from within the client. + + The request can return a `WorkspaceEdit` which will be applied to workspace before the + files are created. Hence the `WorkspaceEdit` can not manipulate the content of the file + to be created. + + @since 3.16.0 + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return await self.protocol.send_request_async("workspace/willCreateFiles", params) + + def workspace_will_delete_files( + self, + params: types.DeleteFilesParams, + callback: Optional[Callable[[Optional[types.WorkspaceEdit]], None]] = None, + ) -> Future[Optional[types.WorkspaceEdit]]: + """Make a :lsp:`workspace/willDeleteFiles` request. + + The did delete files notification is sent from the client to the server when + files were deleted from within the client. + + @since 3.16.0 + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return self.protocol.send_request("workspace/willDeleteFiles", params, callback) + + async def workspace_will_delete_files_async( + self, + params: types.DeleteFilesParams, + ) -> Optional[types.WorkspaceEdit]: + """Make a :lsp:`workspace/willDeleteFiles` request. + + The did delete files notification is sent from the client to the server when + files were deleted from within the client. + + @since 3.16.0 + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return await self.protocol.send_request_async("workspace/willDeleteFiles", params) + + def workspace_will_rename_files( + self, + params: types.RenameFilesParams, + callback: Optional[Callable[[Optional[types.WorkspaceEdit]], None]] = None, + ) -> 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 + renamed as long as the rename is triggered from within the client. + + @since 3.16.0 + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return self.protocol.send_request("workspace/willRenameFiles", params, callback) + + async def workspace_will_rename_files_async( + self, + params: types.RenameFilesParams, + ) -> 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 + renamed as long as the rename is triggered from within the client. + + @since 3.16.0 + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + return await self.protocol.send_request_async("workspace/willRenameFiles", params) + + def cancel_request(self, params: types.CancelParams) -> None: + """Send a :lsp:`$/cancelRequest` notification. + + + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + self.protocol.notify("$/cancelRequest", params) + + def exit(self, params: None) -> None: + """Send a :lsp:`exit` notification. + + The exit event is sent from the client to the server to + ask the server to exit its process. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + self.protocol.notify("exit", params) + + def initialized(self, params: types.InitializedParams) -> None: + """Send a :lsp:`initialized` notification. + + The initialized notification is sent from the client to the + server after the client is fully initialized and the server + is allowed to send requests from the server to the client. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + self.protocol.notify("initialized", params) + + def notebook_document_did_change(self, params: types.DidChangeNotebookDocumentParams) -> None: + """Send a :lsp:`notebookDocument/didChange` notification. + + + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + self.protocol.notify("notebookDocument/didChange", params) + + def notebook_document_did_close(self, params: types.DidCloseNotebookDocumentParams) -> None: + """Send a :lsp:`notebookDocument/didClose` notification. + + A notification sent when a notebook closes. + + @since 3.17.0 + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + self.protocol.notify("notebookDocument/didClose", params) + + def notebook_document_did_open(self, params: types.DidOpenNotebookDocumentParams) -> None: + """Send a :lsp:`notebookDocument/didOpen` notification. + + A notification sent when a notebook opens. + + @since 3.17.0 + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + self.protocol.notify("notebookDocument/didOpen", params) + + def notebook_document_did_save(self, params: types.DidSaveNotebookDocumentParams) -> None: + """Send a :lsp:`notebookDocument/didSave` notification. + + A notification sent when a notebook document is saved. + + @since 3.17.0 + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + self.protocol.notify("notebookDocument/didSave", params) + + def progress(self, params: types.ProgressParams) -> None: + """Send a :lsp:`$/progress` notification. + + + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + self.protocol.notify("$/progress", params) + + def set_trace(self, params: types.SetTraceParams) -> None: + """Send a :lsp:`$/setTrace` notification. + + + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + self.protocol.notify("$/setTrace", params) + + def text_document_did_change(self, params: types.DidChangeTextDocumentParams) -> None: + """Send a :lsp:`textDocument/didChange` notification. + + The document change notification is sent from the client to the server to signal + changes to a text document. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + self.protocol.notify("textDocument/didChange", params) + + def text_document_did_close(self, params: types.DidCloseTextDocumentParams) -> None: + """Send a :lsp:`textDocument/didClose` notification. + + The document close notification is sent from the client to the server when + the document got closed in the client. The document's truth now exists where + the document's uri points to (e.g. if the document's uri is a file uri the + truth now exists on disk). As with the open notification the close notification + is about managing the document's content. Receiving a close notification + doesn't mean that the document was open in an editor before. A close + notification requires a previous open notification to be sent. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + self.protocol.notify("textDocument/didClose", params) + + def text_document_did_open(self, params: types.DidOpenTextDocumentParams) -> None: + """Send a :lsp:`textDocument/didOpen` notification. + + The document open notification is sent from the client to the server to signal + newly opened text documents. The document's truth is now managed by the client + and the server must not try to read the document's truth using the document's + uri. Open in this sense means it is managed by the client. It doesn't necessarily + mean that its content is presented in an editor. An open notification must not + be sent more than once without a corresponding close notification send before. + This means open and close notification must be balanced and the max open count + is one. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + self.protocol.notify("textDocument/didOpen", params) + + def text_document_did_save(self, params: types.DidSaveTextDocumentParams) -> None: + """Send a :lsp:`textDocument/didSave` notification. + + The document save notification is sent from the client to the server when + the document got saved in the client. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + self.protocol.notify("textDocument/didSave", params) + + def text_document_will_save(self, params: types.WillSaveTextDocumentParams) -> None: + """Send a :lsp:`textDocument/willSave` notification. + + A document will save notification is sent from the client to the server before + the document is actually saved. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + self.protocol.notify("textDocument/willSave", params) + + def window_work_done_progress_cancel(self, params: types.WorkDoneProgressCancelParams) -> None: + """Send a :lsp:`window/workDoneProgress/cancel` notification. + + The `window/workDoneProgress/cancel` notification is sent from the client to the server to cancel a progress + initiated on the server side. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + self.protocol.notify("window/workDoneProgress/cancel", params) + + def workspace_did_change_configuration(self, params: types.DidChangeConfigurationParams) -> None: + """Send a :lsp:`workspace/didChangeConfiguration` notification. + + The configuration change notification is sent from the client to the server + when the client's configuration has changed. The notification contains + the changed configuration as defined by the language client. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + self.protocol.notify("workspace/didChangeConfiguration", params) + + def workspace_did_change_watched_files(self, params: types.DidChangeWatchedFilesParams) -> None: + """Send a :lsp:`workspace/didChangeWatchedFiles` notification. + + The watched files notification is sent from the client to the server when + the client detects changes to file watched by the language client. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + self.protocol.notify("workspace/didChangeWatchedFiles", params) + + def workspace_did_change_workspace_folders(self, params: types.DidChangeWorkspaceFoldersParams) -> None: + """Send a :lsp:`workspace/didChangeWorkspaceFolders` notification. + + The `workspace/didChangeWorkspaceFolders` notification is sent from the client to the server when the workspace + folder configuration changes. + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + self.protocol.notify("workspace/didChangeWorkspaceFolders", params) + + def workspace_did_create_files(self, params: types.CreateFilesParams) -> None: + """Send a :lsp:`workspace/didCreateFiles` notification. + + The did create files notification is sent from the client to the server when + files were created from within the client. + + @since 3.16.0 + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + self.protocol.notify("workspace/didCreateFiles", params) + + def workspace_did_delete_files(self, params: types.DeleteFilesParams) -> None: + """Send a :lsp:`workspace/didDeleteFiles` notification. + + The will delete files request is sent from the client to the server before files are actually + deleted as long as the deletion is triggered from within the client. + + @since 3.16.0 + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + self.protocol.notify("workspace/didDeleteFiles", params) + + def workspace_did_rename_files(self, params: types.RenameFilesParams) -> None: + """Send a :lsp:`workspace/didRenameFiles` notification. + + The did rename files notification is sent from the client to the server when + files were renamed from within the client. + + @since 3.16.0 + """ + if self.stopped: + raise RuntimeError("Client has been stopped.") + + self.protocol.notify("workspace/didRenameFiles", params) diff --git a/server/libs/pygls/lsp/_base_server.py b/server/libs/pygls/lsp/_base_server.py new file mode 100644 index 0000000..a686976 --- /dev/null +++ b/server/libs/pygls/lsp/_base_server.py @@ -0,0 +1,463 @@ +############################################################################ +# 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 lsprotocol import types +from pygls.protocol import LanguageServerProtocol +from pygls.protocol import default_converter +from pygls.server import JsonRPCServer +import typing + +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): + + protocol: LanguageServerProtocol + + def __init__( + self, + protocol_cls: type[LanguageServerProtocol] = LanguageServerProtocol, + converter_factory: Callable[[], Converter] = default_converter, + max_workers: int | None = None, + ): + super().__init__(protocol_cls, converter_factory, max_workers) + + def client_register_capability( + self, + params: types.RegistrationParams, + callback: Optional[Callable[[None], None]] = None, + ) -> 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 + handler on the client side. + """ + return self.protocol.send_request("client/registerCapability", params, callback) + + async def client_register_capability_async( + self, + params: types.RegistrationParams, + ) -> None: + """Make a :lsp:`client/registerCapability` request. + + The `client/registerCapability` request is sent from the server to the client to register a new capability + handler on the client side. + """ + return await self.protocol.send_request_async("client/registerCapability", params) + + def client_unregister_capability( + self, + params: types.UnregistrationParams, + callback: Optional[Callable[[None], None]] = None, + ) -> 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 + handler on the client side. + """ + return self.protocol.send_request("client/unregisterCapability", params, callback) + + async def client_unregister_capability_async( + self, + params: types.UnregistrationParams, + ) -> 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 + handler on the client side. + """ + return await self.protocol.send_request_async("client/unregisterCapability", params) + + def window_show_document( + self, + params: types.ShowDocumentParams, + callback: Optional[Callable[[types.ShowDocumentResult], None]] = None, + ) -> Future[types.ShowDocumentResult]: + """Make a :lsp:`window/showDocument` request. + + A request to show a document. This request might open an + external program depending on the value of the URI to open. + For example a request to open `https://code.visualstudio.com/` + will very likely open the URI in a WEB browser. + + @since 3.16.0 + """ + return self.protocol.send_request("window/showDocument", params, callback) + + async def window_show_document_async( + self, + params: types.ShowDocumentParams, + ) -> types.ShowDocumentResult: + """Make a :lsp:`window/showDocument` request. + + A request to show a document. This request might open an + external program depending on the value of the URI to open. + For example a request to open `https://code.visualstudio.com/` + will very likely open the URI in a WEB browser. + + @since 3.16.0 + """ + return await self.protocol.send_request_async("window/showDocument", params) + + def window_show_message_request( + self, + params: types.ShowMessageRequestParams, + callback: Optional[Callable[[Optional[types.MessageActionItem]], None]] = None, + ) -> 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 + and a set of options actions to the user. + """ + return self.protocol.send_request("window/showMessageRequest", params, callback) + + async def window_show_message_request_async( + self, + params: types.ShowMessageRequestParams, + ) -> 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 + and a set of options actions to the user. + """ + return await self.protocol.send_request_async("window/showMessageRequest", params) + + def window_work_done_progress_create( + self, + params: types.WorkDoneProgressCreateParams, + callback: Optional[Callable[[None], None]] = None, + ) -> 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 + reporting from the server. + """ + return self.protocol.send_request("window/workDoneProgress/create", params, callback) + + async def window_work_done_progress_create_async( + self, + params: types.WorkDoneProgressCreateParams, + ) -> None: + """Make a :lsp:`window/workDoneProgress/create` request. + + The `window/workDoneProgress/create` request is sent from the server to the client to initiate progress + reporting from the server. + """ + return await self.protocol.send_request_async("window/workDoneProgress/create", params) + + def workspace_apply_edit( + self, + params: types.ApplyWorkspaceEditParams, + callback: Optional[Callable[[types.ApplyWorkspaceEditResult], None]] = None, + ) -> Future[types.ApplyWorkspaceEditResult]: + """Make a :lsp:`workspace/applyEdit` request. + + A request sent from the server to the client to modified certain resources. + """ + return self.protocol.send_request("workspace/applyEdit", params, callback) + + async def workspace_apply_edit_async( + self, + params: types.ApplyWorkspaceEditParams, + ) -> types.ApplyWorkspaceEditResult: + """Make a :lsp:`workspace/applyEdit` request. + + A request sent from the server to the client to modified certain resources. + """ + return await self.protocol.send_request_async("workspace/applyEdit", params) + + def workspace_code_lens_refresh( + self, + params: None, + callback: Optional[Callable[[None], None]] = None, + ) -> Future[None]: + """Make a :lsp:`workspace/codeLens/refresh` request. + + A request to refresh all code actions + + @since 3.16.0 + """ + return self.protocol.send_request("workspace/codeLens/refresh", params, callback) + + async def workspace_code_lens_refresh_async( + self, + params: None, + ) -> None: + """Make a :lsp:`workspace/codeLens/refresh` request. + + A request to refresh all code actions + + @since 3.16.0 + """ + return await self.protocol.send_request_async("workspace/codeLens/refresh", params) + + def workspace_configuration( + self, + params: types.ConfigurationParams, + callback: Optional[Callable[[Sequence[Optional[Any]]], None]] = None, + ) -> 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 + configuration setting. + + This pull model replaces the old push model were the client signaled configuration change via an + event. If the server still needs to react to configuration changes (since the server caches the + result of `workspace/configuration` requests) the server should register for an empty configuration + change event and empty the cache if such an event is received. + """ + return self.protocol.send_request("workspace/configuration", params, callback) + + async def workspace_configuration_async( + self, + params: types.ConfigurationParams, + ) -> 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 + configuration setting. + + This pull model replaces the old push model were the client signaled configuration change via an + event. If the server still needs to react to configuration changes (since the server caches the + result of `workspace/configuration` requests) the server should register for an empty configuration + change event and empty the cache if such an event is received. + """ + return await self.protocol.send_request_async("workspace/configuration", params) + + def workspace_diagnostic_refresh( + self, + params: None, + callback: Optional[Callable[[None], None]] = None, + ) -> Future[None]: + """Make a :lsp:`workspace/diagnostic/refresh` request. + + The diagnostic refresh request definition. + + @since 3.17.0 + """ + return self.protocol.send_request("workspace/diagnostic/refresh", params, callback) + + async def workspace_diagnostic_refresh_async( + self, + params: None, + ) -> None: + """Make a :lsp:`workspace/diagnostic/refresh` request. + + The diagnostic refresh request definition. + + @since 3.17.0 + """ + return await self.protocol.send_request_async("workspace/diagnostic/refresh", params) + + def workspace_folding_range_refresh( + self, + params: None, + callback: Optional[Callable[[None], None]] = None, + ) -> Future[None]: + """Make a :lsp:`workspace/foldingRange/refresh` request. + + @since 3.18.0 + @proposed + """ + return self.protocol.send_request("workspace/foldingRange/refresh", params, callback) + + async def workspace_folding_range_refresh_async( + self, + params: None, + ) -> None: + """Make a :lsp:`workspace/foldingRange/refresh` request. + + @since 3.18.0 + @proposed + """ + return await self.protocol.send_request_async("workspace/foldingRange/refresh", params) + + def workspace_inlay_hint_refresh( + self, + params: None, + callback: Optional[Callable[[None], None]] = None, + ) -> Future[None]: + """Make a :lsp:`workspace/inlayHint/refresh` request. + + @since 3.17.0 + """ + return self.protocol.send_request("workspace/inlayHint/refresh", params, callback) + + async def workspace_inlay_hint_refresh_async( + self, + params: None, + ) -> None: + """Make a :lsp:`workspace/inlayHint/refresh` request. + + @since 3.17.0 + """ + return await self.protocol.send_request_async("workspace/inlayHint/refresh", params) + + def workspace_inline_value_refresh( + self, + params: None, + callback: Optional[Callable[[None], None]] = None, + ) -> Future[None]: + """Make a :lsp:`workspace/inlineValue/refresh` request. + + @since 3.17.0 + """ + return self.protocol.send_request("workspace/inlineValue/refresh", params, callback) + + async def workspace_inline_value_refresh_async( + self, + params: None, + ) -> None: + """Make a :lsp:`workspace/inlineValue/refresh` request. + + @since 3.17.0 + """ + return await self.protocol.send_request_async("workspace/inlineValue/refresh", params) + + def workspace_semantic_tokens_refresh( + self, + params: None, + callback: Optional[Callable[[None], None]] = None, + ) -> Future[None]: + """Make a :lsp:`workspace/semanticTokens/refresh` request. + + @since 3.16.0 + """ + return self.protocol.send_request("workspace/semanticTokens/refresh", params, callback) + + async def workspace_semantic_tokens_refresh_async( + self, + params: None, + ) -> None: + """Make a :lsp:`workspace/semanticTokens/refresh` request. + + @since 3.16.0 + """ + return await self.protocol.send_request_async("workspace/semanticTokens/refresh", params) + + def workspace_text_document_content_refresh( + self, + params: types.TextDocumentContentRefreshParams, + callback: Optional[Callable[[None], None]] = None, + ) -> Future[None]: + """Make a :lsp:`workspace/textDocumentContent/refresh` request. + + The `workspace/textDocumentContent` request is sent from the server to the client to refresh + the content of a specific text document. + + @since 3.18.0 + @proposed + """ + return self.protocol.send_request("workspace/textDocumentContent/refresh", params, callback) + + async def workspace_text_document_content_refresh_async( + self, + params: types.TextDocumentContentRefreshParams, + ) -> None: + """Make a :lsp:`workspace/textDocumentContent/refresh` request. + + The `workspace/textDocumentContent` request is sent from the server to the client to refresh + the content of a specific text document. + + @since 3.18.0 + @proposed + """ + return await self.protocol.send_request_async("workspace/textDocumentContent/refresh", params) + + def workspace_workspace_folders( + self, + params: None, + callback: Optional[Callable[[Optional[Sequence[types.WorkspaceFolder]]], None]] = None, + ) -> 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. + """ + return self.protocol.send_request("workspace/workspaceFolders", params, callback) + + async def workspace_workspace_folders_async( + self, + params: None, + ) -> 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. + """ + return await self.protocol.send_request_async("workspace/workspaceFolders", params) + + def cancel_request(self, params: types.CancelParams) -> None: + """Send a :lsp:`$/cancelRequest` notification. + + + """ + self.protocol.notify("$/cancelRequest", params) + + def log_trace(self, params: types.LogTraceParams) -> None: + """Send a :lsp:`$/logTrace` notification. + + + """ + self.protocol.notify("$/logTrace", params) + + def progress(self, params: types.ProgressParams) -> None: + """Send a :lsp:`$/progress` notification. + + + """ + self.protocol.notify("$/progress", params) + + def telemetry_event(self, params: typing.Optional[typing.Any]) -> None: + """Send a :lsp:`telemetry/event` notification. + + The telemetry event notification is sent from the server to the client to ask + the client to log telemetry data. + """ + self.protocol.notify("telemetry/event", params) + + def text_document_publish_diagnostics(self, params: types.PublishDiagnosticsParams) -> None: + """Send a :lsp:`textDocument/publishDiagnostics` notification. + + Diagnostics notification are sent from the server to the client to signal + results of validation runs. + """ + self.protocol.notify("textDocument/publishDiagnostics", params) + + def window_log_message(self, params: types.LogMessageParams) -> None: + """Send a :lsp:`window/logMessage` notification. + + The log message notification is sent from the server to the client to ask + the client to log a particular message. + """ + self.protocol.notify("window/logMessage", params) + + def window_show_message(self, params: types.ShowMessageParams) -> None: + """Send a :lsp:`window/showMessage` notification. + + The show message notification is sent from a server to a client to ask + the client to display a particular message in the user interface. + """ + self.protocol.notify("window/showMessage", params) diff --git a/server/libs/pygls/lsp/_capabilities.py b/server/libs/pygls/lsp/_capabilities.py new file mode 100644 index 0000000..9e92238 --- /dev/null +++ b/server/libs/pygls/lsp/_capabilities.py @@ -0,0 +1,1238 @@ +############################################################################ +# 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 Union + +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace'], default: None = None) -> types.WorkspaceClientCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace'], default: types.WorkspaceClientCapabilities) -> types.WorkspaceClientCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.apply_edit'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.apply_edit'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.workspace_edit'], default: None = None) -> types.WorkspaceEditClientCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.workspace_edit'], default: types.WorkspaceEditClientCapabilities) -> types.WorkspaceEditClientCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.workspace_edit.document_changes'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.workspace_edit.document_changes'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.workspace_edit.resource_operations'], default: None = None) -> Sequence[types.ResourceOperationKind] | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.workspace_edit.resource_operations'], default: Sequence[types.ResourceOperationKind]) -> Sequence[types.ResourceOperationKind]: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.workspace_edit.failure_handling'], default: None = None) -> types.FailureHandlingKind | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.workspace_edit.failure_handling'], default: types.FailureHandlingKind) -> types.FailureHandlingKind: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.workspace_edit.normalizes_line_endings'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.workspace_edit.normalizes_line_endings'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.workspace_edit.change_annotation_support'], default: None = None) -> types.ChangeAnnotationsSupportOptions | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.workspace_edit.change_annotation_support'], default: types.ChangeAnnotationsSupportOptions) -> types.ChangeAnnotationsSupportOptions: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.workspace_edit.change_annotation_support.groups_on_label'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.workspace_edit.change_annotation_support.groups_on_label'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.workspace_edit.metadata_support'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.workspace_edit.metadata_support'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.workspace_edit.snippet_edit_support'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.workspace_edit.snippet_edit_support'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.did_change_configuration'], default: None = None) -> types.DidChangeConfigurationClientCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.did_change_configuration'], default: types.DidChangeConfigurationClientCapabilities) -> types.DidChangeConfigurationClientCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.did_change_configuration.dynamic_registration'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.did_change_configuration.dynamic_registration'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.did_change_watched_files'], default: None = None) -> types.DidChangeWatchedFilesClientCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.did_change_watched_files'], default: types.DidChangeWatchedFilesClientCapabilities) -> types.DidChangeWatchedFilesClientCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.did_change_watched_files.dynamic_registration'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.did_change_watched_files.dynamic_registration'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.did_change_watched_files.relative_pattern_support'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.did_change_watched_files.relative_pattern_support'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.symbol'], default: None = None) -> types.WorkspaceSymbolClientCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.symbol'], default: types.WorkspaceSymbolClientCapabilities) -> types.WorkspaceSymbolClientCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.symbol.dynamic_registration'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.symbol.dynamic_registration'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.symbol.symbol_kind'], default: None = None) -> types.ClientSymbolKindOptions | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.symbol.symbol_kind'], default: types.ClientSymbolKindOptions) -> types.ClientSymbolKindOptions: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.symbol.symbol_kind.value_set'], default: None = None) -> Sequence[types.SymbolKind] | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.symbol.symbol_kind.value_set'], default: Sequence[types.SymbolKind]) -> Sequence[types.SymbolKind]: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.symbol.tag_support'], default: None = None) -> types.ClientSymbolTagOptions | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.symbol.tag_support'], default: types.ClientSymbolTagOptions) -> types.ClientSymbolTagOptions: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.symbol.tag_support.value_set'], default: None = None) -> Sequence[types.SymbolTag] | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.symbol.tag_support.value_set'], default: Sequence[types.SymbolTag]) -> Sequence[types.SymbolTag]: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.symbol.resolve_support'], default: None = None) -> types.ClientSymbolResolveOptions | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.symbol.resolve_support'], default: types.ClientSymbolResolveOptions) -> types.ClientSymbolResolveOptions: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.symbol.resolve_support.properties'], default: None = None) -> Sequence[str] | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.symbol.resolve_support.properties'], default: Sequence[str]) -> Sequence[str]: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.execute_command'], default: None = None) -> types.ExecuteCommandClientCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.execute_command'], default: types.ExecuteCommandClientCapabilities) -> types.ExecuteCommandClientCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.execute_command.dynamic_registration'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.execute_command.dynamic_registration'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.workspace_folders'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.workspace_folders'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.configuration'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.configuration'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.semantic_tokens'], default: None = None) -> types.SemanticTokensWorkspaceClientCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.semantic_tokens'], default: types.SemanticTokensWorkspaceClientCapabilities) -> types.SemanticTokensWorkspaceClientCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.semantic_tokens.refresh_support'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.semantic_tokens.refresh_support'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.code_lens'], default: None = None) -> types.CodeLensWorkspaceClientCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.code_lens'], default: types.CodeLensWorkspaceClientCapabilities) -> types.CodeLensWorkspaceClientCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.code_lens.refresh_support'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.code_lens.refresh_support'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.file_operations'], default: None = None) -> types.FileOperationClientCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.file_operations'], default: types.FileOperationClientCapabilities) -> types.FileOperationClientCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.file_operations.dynamic_registration'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.file_operations.dynamic_registration'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.file_operations.did_create'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.file_operations.did_create'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.file_operations.will_create'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.file_operations.will_create'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.file_operations.did_rename'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.file_operations.did_rename'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.file_operations.will_rename'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.file_operations.will_rename'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.file_operations.did_delete'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.file_operations.did_delete'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.file_operations.will_delete'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.file_operations.will_delete'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.inline_value'], default: None = None) -> types.InlineValueWorkspaceClientCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.inline_value'], default: types.InlineValueWorkspaceClientCapabilities) -> types.InlineValueWorkspaceClientCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.inline_value.refresh_support'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.inline_value.refresh_support'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.inlay_hint'], default: None = None) -> types.InlayHintWorkspaceClientCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.inlay_hint'], default: types.InlayHintWorkspaceClientCapabilities) -> types.InlayHintWorkspaceClientCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.inlay_hint.refresh_support'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.inlay_hint.refresh_support'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.diagnostics'], default: None = None) -> types.DiagnosticWorkspaceClientCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.diagnostics'], default: types.DiagnosticWorkspaceClientCapabilities) -> types.DiagnosticWorkspaceClientCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.diagnostics.refresh_support'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.diagnostics.refresh_support'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.folding_range'], default: None = None) -> types.FoldingRangeWorkspaceClientCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.folding_range'], default: types.FoldingRangeWorkspaceClientCapabilities) -> types.FoldingRangeWorkspaceClientCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.folding_range.refresh_support'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.folding_range.refresh_support'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.text_document_content'], default: None = None) -> types.TextDocumentContentClientCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.text_document_content'], default: types.TextDocumentContentClientCapabilities) -> types.TextDocumentContentClientCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.text_document_content.dynamic_registration'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['workspace.text_document_content.dynamic_registration'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document'], default: None = None) -> types.TextDocumentClientCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document'], default: types.TextDocumentClientCapabilities) -> types.TextDocumentClientCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.synchronization'], default: None = None) -> types.TextDocumentSyncClientCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.synchronization'], default: types.TextDocumentSyncClientCapabilities) -> types.TextDocumentSyncClientCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.synchronization.dynamic_registration'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.synchronization.dynamic_registration'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.synchronization.will_save'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.synchronization.will_save'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.synchronization.will_save_wait_until'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.synchronization.will_save_wait_until'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.synchronization.did_save'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.synchronization.did_save'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.filters'], default: None = None) -> types.TextDocumentFilterClientCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.filters'], default: types.TextDocumentFilterClientCapabilities) -> types.TextDocumentFilterClientCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.filters.relative_pattern_support'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.filters.relative_pattern_support'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion'], default: None = None) -> types.CompletionClientCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion'], default: types.CompletionClientCapabilities) -> types.CompletionClientCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.dynamic_registration'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.dynamic_registration'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_item'], default: None = None) -> types.ClientCompletionItemOptions | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_item'], default: types.ClientCompletionItemOptions) -> types.ClientCompletionItemOptions: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_item.snippet_support'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_item.snippet_support'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_item.commit_characters_support'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_item.commit_characters_support'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_item.documentation_format'], default: None = None) -> Sequence[types.MarkupKind] | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_item.documentation_format'], default: Sequence[types.MarkupKind]) -> Sequence[types.MarkupKind]: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_item.deprecated_support'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_item.deprecated_support'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_item.preselect_support'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_item.preselect_support'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_item.tag_support'], default: None = None) -> types.CompletionItemTagOptions | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_item.tag_support'], default: types.CompletionItemTagOptions) -> types.CompletionItemTagOptions: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_item.tag_support.value_set'], default: None = None) -> Sequence[types.CompletionItemTag] | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_item.tag_support.value_set'], default: Sequence[types.CompletionItemTag]) -> Sequence[types.CompletionItemTag]: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_item.insert_replace_support'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_item.insert_replace_support'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_item.resolve_support'], default: None = None) -> types.ClientCompletionItemResolveOptions | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_item.resolve_support'], default: types.ClientCompletionItemResolveOptions) -> types.ClientCompletionItemResolveOptions: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_item.resolve_support.properties'], default: None = None) -> Sequence[str] | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_item.resolve_support.properties'], default: Sequence[str]) -> Sequence[str]: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_item.insert_text_mode_support'], default: None = None) -> types.ClientCompletionItemInsertTextModeOptions | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_item.insert_text_mode_support'], default: types.ClientCompletionItemInsertTextModeOptions) -> types.ClientCompletionItemInsertTextModeOptions: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_item.insert_text_mode_support.value_set'], default: None = None) -> Sequence[types.InsertTextMode] | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_item.insert_text_mode_support.value_set'], default: Sequence[types.InsertTextMode]) -> Sequence[types.InsertTextMode]: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_item.label_details_support'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_item.label_details_support'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_item_kind'], default: None = None) -> types.ClientCompletionItemOptionsKind | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_item_kind'], default: types.ClientCompletionItemOptionsKind) -> types.ClientCompletionItemOptionsKind: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_item_kind.value_set'], default: None = None) -> Sequence[Union[types.CompletionItemKind, int]] | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_item_kind.value_set'], default: Sequence[Union[types.CompletionItemKind, int]]) -> Sequence[Union[types.CompletionItemKind, int]]: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.insert_text_mode'], default: None = None) -> types.InsertTextMode | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.insert_text_mode'], default: types.InsertTextMode) -> types.InsertTextMode: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.context_support'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.context_support'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_list'], default: None = None) -> types.CompletionListCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_list'], default: types.CompletionListCapabilities) -> types.CompletionListCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_list.item_defaults'], default: None = None) -> Sequence[str] | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_list.item_defaults'], default: Sequence[str]) -> Sequence[str]: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_list.apply_kind_support'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.completion.completion_list.apply_kind_support'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.hover'], default: None = None) -> types.HoverClientCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.hover'], default: types.HoverClientCapabilities) -> types.HoverClientCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.hover.dynamic_registration'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.hover.dynamic_registration'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.hover.content_format'], default: None = None) -> Sequence[types.MarkupKind] | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.hover.content_format'], default: Sequence[types.MarkupKind]) -> Sequence[types.MarkupKind]: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.signature_help'], default: None = None) -> types.SignatureHelpClientCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.signature_help'], default: types.SignatureHelpClientCapabilities) -> types.SignatureHelpClientCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.signature_help.dynamic_registration'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.signature_help.dynamic_registration'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.signature_help.signature_information'], default: None = None) -> types.ClientSignatureInformationOptions | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.signature_help.signature_information'], default: types.ClientSignatureInformationOptions) -> types.ClientSignatureInformationOptions: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.signature_help.signature_information.documentation_format'], default: None = None) -> Sequence[types.MarkupKind] | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.signature_help.signature_information.documentation_format'], default: Sequence[types.MarkupKind]) -> Sequence[types.MarkupKind]: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.signature_help.signature_information.parameter_information'], default: None = None) -> types.ClientSignatureParameterInformationOptions | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.signature_help.signature_information.parameter_information'], default: types.ClientSignatureParameterInformationOptions) -> types.ClientSignatureParameterInformationOptions: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.signature_help.signature_information.parameter_information.label_offset_support'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.signature_help.signature_information.parameter_information.label_offset_support'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.signature_help.signature_information.active_parameter_support'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.signature_help.signature_information.active_parameter_support'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.signature_help.signature_information.no_active_parameter_support'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.signature_help.signature_information.no_active_parameter_support'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.signature_help.context_support'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.signature_help.context_support'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.declaration'], default: None = None) -> types.DeclarationClientCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.declaration'], default: types.DeclarationClientCapabilities) -> types.DeclarationClientCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.declaration.dynamic_registration'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.declaration.dynamic_registration'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.declaration.link_support'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.declaration.link_support'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.definition'], default: None = None) -> types.DefinitionClientCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.definition'], default: types.DefinitionClientCapabilities) -> types.DefinitionClientCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.definition.dynamic_registration'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.definition.dynamic_registration'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.definition.link_support'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.definition.link_support'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.type_definition'], default: None = None) -> types.TypeDefinitionClientCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.type_definition'], default: types.TypeDefinitionClientCapabilities) -> types.TypeDefinitionClientCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.type_definition.dynamic_registration'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.type_definition.dynamic_registration'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.type_definition.link_support'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.type_definition.link_support'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.implementation'], default: None = None) -> types.ImplementationClientCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.implementation'], default: types.ImplementationClientCapabilities) -> types.ImplementationClientCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.implementation.dynamic_registration'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.implementation.dynamic_registration'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.implementation.link_support'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.implementation.link_support'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.references'], default: None = None) -> types.ReferenceClientCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.references'], default: types.ReferenceClientCapabilities) -> types.ReferenceClientCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.references.dynamic_registration'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.references.dynamic_registration'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.document_highlight'], default: None = None) -> types.DocumentHighlightClientCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.document_highlight'], default: types.DocumentHighlightClientCapabilities) -> types.DocumentHighlightClientCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.document_highlight.dynamic_registration'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.document_highlight.dynamic_registration'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.document_symbol'], default: None = None) -> types.DocumentSymbolClientCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.document_symbol'], default: types.DocumentSymbolClientCapabilities) -> types.DocumentSymbolClientCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.document_symbol.dynamic_registration'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.document_symbol.dynamic_registration'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.document_symbol.symbol_kind'], default: None = None) -> types.ClientSymbolKindOptions | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.document_symbol.symbol_kind'], default: types.ClientSymbolKindOptions) -> types.ClientSymbolKindOptions: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.document_symbol.symbol_kind.value_set'], default: None = None) -> Sequence[types.SymbolKind] | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.document_symbol.symbol_kind.value_set'], default: Sequence[types.SymbolKind]) -> Sequence[types.SymbolKind]: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.document_symbol.hierarchical_document_symbol_support'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.document_symbol.hierarchical_document_symbol_support'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.document_symbol.tag_support'], default: None = None) -> types.ClientSymbolTagOptions | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.document_symbol.tag_support'], default: types.ClientSymbolTagOptions) -> types.ClientSymbolTagOptions: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.document_symbol.tag_support.value_set'], default: None = None) -> Sequence[types.SymbolTag] | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.document_symbol.tag_support.value_set'], default: Sequence[types.SymbolTag]) -> Sequence[types.SymbolTag]: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.document_symbol.label_support'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.document_symbol.label_support'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.code_action'], default: None = None) -> types.CodeActionClientCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.code_action'], default: types.CodeActionClientCapabilities) -> types.CodeActionClientCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.code_action.dynamic_registration'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.code_action.dynamic_registration'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.code_action.code_action_literal_support'], default: None = None) -> types.ClientCodeActionLiteralOptions | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.code_action.code_action_literal_support'], default: types.ClientCodeActionLiteralOptions) -> types.ClientCodeActionLiteralOptions: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.code_action.code_action_literal_support.code_action_kind'], default: None = None) -> types.ClientCodeActionKindOptions | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.code_action.code_action_literal_support.code_action_kind'], default: types.ClientCodeActionKindOptions) -> types.ClientCodeActionKindOptions: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.code_action.code_action_literal_support.code_action_kind.value_set'], default: None = None) -> Sequence[Union[types.CodeActionKind, str]] | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.code_action.code_action_literal_support.code_action_kind.value_set'], default: Sequence[Union[types.CodeActionKind, str]]) -> Sequence[Union[types.CodeActionKind, str]]: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.code_action.is_preferred_support'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.code_action.is_preferred_support'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.code_action.disabled_support'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.code_action.disabled_support'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.code_action.data_support'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.code_action.data_support'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.code_action.resolve_support'], default: None = None) -> types.ClientCodeActionResolveOptions | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.code_action.resolve_support'], default: types.ClientCodeActionResolveOptions) -> types.ClientCodeActionResolveOptions: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.code_action.resolve_support.properties'], default: None = None) -> Sequence[str] | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.code_action.resolve_support.properties'], default: Sequence[str]) -> Sequence[str]: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.code_action.honors_change_annotations'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.code_action.honors_change_annotations'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.code_action.documentation_support'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.code_action.documentation_support'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.code_action.tag_support'], default: None = None) -> types.CodeActionTagOptions | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.code_action.tag_support'], default: types.CodeActionTagOptions) -> types.CodeActionTagOptions: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.code_action.tag_support.value_set'], default: None = None) -> Sequence[types.CodeActionTag] | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.code_action.tag_support.value_set'], default: Sequence[types.CodeActionTag]) -> Sequence[types.CodeActionTag]: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.code_lens'], default: None = None) -> types.CodeLensClientCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.code_lens'], default: types.CodeLensClientCapabilities) -> types.CodeLensClientCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.code_lens.dynamic_registration'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.code_lens.dynamic_registration'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.code_lens.resolve_support'], default: None = None) -> types.ClientCodeLensResolveOptions | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.code_lens.resolve_support'], default: types.ClientCodeLensResolveOptions) -> types.ClientCodeLensResolveOptions: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.code_lens.resolve_support.properties'], default: None = None) -> Sequence[str] | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.code_lens.resolve_support.properties'], default: Sequence[str]) -> Sequence[str]: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.document_link'], default: None = None) -> types.DocumentLinkClientCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.document_link'], default: types.DocumentLinkClientCapabilities) -> types.DocumentLinkClientCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.document_link.dynamic_registration'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.document_link.dynamic_registration'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.document_link.tooltip_support'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.document_link.tooltip_support'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.color_provider'], default: None = None) -> types.DocumentColorClientCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.color_provider'], default: types.DocumentColorClientCapabilities) -> types.DocumentColorClientCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.color_provider.dynamic_registration'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.color_provider.dynamic_registration'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.formatting'], default: None = None) -> types.DocumentFormattingClientCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.formatting'], default: types.DocumentFormattingClientCapabilities) -> types.DocumentFormattingClientCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.formatting.dynamic_registration'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.formatting.dynamic_registration'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.range_formatting'], default: None = None) -> types.DocumentRangeFormattingClientCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.range_formatting'], default: types.DocumentRangeFormattingClientCapabilities) -> types.DocumentRangeFormattingClientCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.range_formatting.dynamic_registration'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.range_formatting.dynamic_registration'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.range_formatting.ranges_support'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.range_formatting.ranges_support'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.on_type_formatting'], default: None = None) -> types.DocumentOnTypeFormattingClientCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.on_type_formatting'], default: types.DocumentOnTypeFormattingClientCapabilities) -> types.DocumentOnTypeFormattingClientCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.on_type_formatting.dynamic_registration'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.on_type_formatting.dynamic_registration'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.rename'], default: None = None) -> types.RenameClientCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.rename'], default: types.RenameClientCapabilities) -> types.RenameClientCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.rename.dynamic_registration'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.rename.dynamic_registration'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.rename.prepare_support'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.rename.prepare_support'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.rename.prepare_support_default_behavior'], default: None = None) -> types.PrepareSupportDefaultBehavior | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.rename.prepare_support_default_behavior'], default: types.PrepareSupportDefaultBehavior) -> types.PrepareSupportDefaultBehavior: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.rename.honors_change_annotations'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.rename.honors_change_annotations'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.folding_range'], default: None = None) -> types.FoldingRangeClientCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.folding_range'], default: types.FoldingRangeClientCapabilities) -> types.FoldingRangeClientCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.folding_range.dynamic_registration'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.folding_range.dynamic_registration'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.folding_range.range_limit'], default: None = None) -> int | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.folding_range.range_limit'], default: int) -> int: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.folding_range.line_folding_only'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.folding_range.line_folding_only'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.folding_range.folding_range_kind'], default: None = None) -> types.ClientFoldingRangeKindOptions | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.folding_range.folding_range_kind'], default: types.ClientFoldingRangeKindOptions) -> types.ClientFoldingRangeKindOptions: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.folding_range.folding_range_kind.value_set'], default: None = None) -> Sequence[Union[types.FoldingRangeKind, str]] | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.folding_range.folding_range_kind.value_set'], default: Sequence[Union[types.FoldingRangeKind, str]]) -> Sequence[Union[types.FoldingRangeKind, str]]: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.folding_range.folding_range'], default: None = None) -> types.ClientFoldingRangeOptions | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.folding_range.folding_range'], default: types.ClientFoldingRangeOptions) -> types.ClientFoldingRangeOptions: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.folding_range.folding_range.collapsed_text'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.folding_range.folding_range.collapsed_text'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.selection_range'], default: None = None) -> types.SelectionRangeClientCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.selection_range'], default: types.SelectionRangeClientCapabilities) -> types.SelectionRangeClientCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.selection_range.dynamic_registration'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.selection_range.dynamic_registration'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.publish_diagnostics'], default: None = None) -> types.PublishDiagnosticsClientCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.publish_diagnostics'], default: types.PublishDiagnosticsClientCapabilities) -> types.PublishDiagnosticsClientCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.publish_diagnostics.version_support'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.publish_diagnostics.version_support'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.publish_diagnostics.related_information'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.publish_diagnostics.related_information'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.publish_diagnostics.tag_support'], default: None = None) -> types.ClientDiagnosticsTagOptions | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.publish_diagnostics.tag_support'], default: types.ClientDiagnosticsTagOptions) -> types.ClientDiagnosticsTagOptions: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.publish_diagnostics.tag_support.value_set'], default: None = None) -> Sequence[types.DiagnosticTag] | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.publish_diagnostics.tag_support.value_set'], default: Sequence[types.DiagnosticTag]) -> Sequence[types.DiagnosticTag]: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.publish_diagnostics.code_description_support'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.publish_diagnostics.code_description_support'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.publish_diagnostics.data_support'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.publish_diagnostics.data_support'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.call_hierarchy'], default: None = None) -> types.CallHierarchyClientCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.call_hierarchy'], default: types.CallHierarchyClientCapabilities) -> types.CallHierarchyClientCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.call_hierarchy.dynamic_registration'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.call_hierarchy.dynamic_registration'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.semantic_tokens'], default: None = None) -> types.SemanticTokensClientCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.semantic_tokens'], default: types.SemanticTokensClientCapabilities) -> types.SemanticTokensClientCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.semantic_tokens.requests'], default: None = None) -> types.ClientSemanticTokensRequestOptions | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.semantic_tokens.requests'], default: types.ClientSemanticTokensRequestOptions) -> types.ClientSemanticTokensRequestOptions: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.semantic_tokens.requests.range'], default: None = None) -> Union[bool, Any, None] | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.semantic_tokens.requests.range'], default: Union[bool, Any, None]) -> Union[bool, Any, None]: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.semantic_tokens.requests.full'], default: None = None) -> Union[bool, types.ClientSemanticTokensRequestFullDelta, None] | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.semantic_tokens.requests.full'], default: Union[bool, types.ClientSemanticTokensRequestFullDelta, None]) -> Union[bool, types.ClientSemanticTokensRequestFullDelta, None]: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.semantic_tokens.token_types'], default: None = None) -> Sequence[str] | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.semantic_tokens.token_types'], default: Sequence[str]) -> Sequence[str]: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.semantic_tokens.token_modifiers'], default: None = None) -> Sequence[str] | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.semantic_tokens.token_modifiers'], default: Sequence[str]) -> Sequence[str]: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.semantic_tokens.formats'], default: None = None) -> Sequence[types.TokenFormat] | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.semantic_tokens.formats'], default: Sequence[types.TokenFormat]) -> Sequence[types.TokenFormat]: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.semantic_tokens.dynamic_registration'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.semantic_tokens.dynamic_registration'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.semantic_tokens.overlapping_token_support'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.semantic_tokens.overlapping_token_support'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.semantic_tokens.multiline_token_support'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.semantic_tokens.multiline_token_support'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.semantic_tokens.server_cancel_support'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.semantic_tokens.server_cancel_support'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.semantic_tokens.augments_syntax_tokens'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.semantic_tokens.augments_syntax_tokens'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.linked_editing_range'], default: None = None) -> types.LinkedEditingRangeClientCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.linked_editing_range'], default: types.LinkedEditingRangeClientCapabilities) -> types.LinkedEditingRangeClientCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.linked_editing_range.dynamic_registration'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.linked_editing_range.dynamic_registration'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.moniker'], default: None = None) -> types.MonikerClientCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.moniker'], default: types.MonikerClientCapabilities) -> types.MonikerClientCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.moniker.dynamic_registration'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.moniker.dynamic_registration'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.type_hierarchy'], default: None = None) -> types.TypeHierarchyClientCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.type_hierarchy'], default: types.TypeHierarchyClientCapabilities) -> types.TypeHierarchyClientCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.type_hierarchy.dynamic_registration'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.type_hierarchy.dynamic_registration'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.inline_value'], default: None = None) -> types.InlineValueClientCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.inline_value'], default: types.InlineValueClientCapabilities) -> types.InlineValueClientCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.inline_value.dynamic_registration'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.inline_value.dynamic_registration'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.inlay_hint'], default: None = None) -> types.InlayHintClientCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.inlay_hint'], default: types.InlayHintClientCapabilities) -> types.InlayHintClientCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.inlay_hint.dynamic_registration'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.inlay_hint.dynamic_registration'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.inlay_hint.resolve_support'], default: None = None) -> types.ClientInlayHintResolveOptions | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.inlay_hint.resolve_support'], default: types.ClientInlayHintResolveOptions) -> types.ClientInlayHintResolveOptions: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.inlay_hint.resolve_support.properties'], default: None = None) -> Sequence[str] | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.inlay_hint.resolve_support.properties'], default: Sequence[str]) -> Sequence[str]: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.diagnostic'], default: None = None) -> types.DiagnosticClientCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.diagnostic'], default: types.DiagnosticClientCapabilities) -> types.DiagnosticClientCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.diagnostic.dynamic_registration'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.diagnostic.dynamic_registration'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.diagnostic.related_document_support'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.diagnostic.related_document_support'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.diagnostic.related_information'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.diagnostic.related_information'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.diagnostic.tag_support'], default: None = None) -> types.ClientDiagnosticsTagOptions | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.diagnostic.tag_support'], default: types.ClientDiagnosticsTagOptions) -> types.ClientDiagnosticsTagOptions: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.diagnostic.tag_support.value_set'], default: None = None) -> Sequence[types.DiagnosticTag] | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.diagnostic.tag_support.value_set'], default: Sequence[types.DiagnosticTag]) -> Sequence[types.DiagnosticTag]: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.diagnostic.code_description_support'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.diagnostic.code_description_support'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.diagnostic.data_support'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.diagnostic.data_support'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.inline_completion'], default: None = None) -> types.InlineCompletionClientCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.inline_completion'], default: types.InlineCompletionClientCapabilities) -> types.InlineCompletionClientCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.inline_completion.dynamic_registration'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['text_document.inline_completion.dynamic_registration'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['notebook_document'], default: None = None) -> types.NotebookDocumentClientCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['notebook_document'], default: types.NotebookDocumentClientCapabilities) -> types.NotebookDocumentClientCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['notebook_document.synchronization'], default: None = None) -> types.NotebookDocumentSyncClientCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['notebook_document.synchronization'], default: types.NotebookDocumentSyncClientCapabilities) -> types.NotebookDocumentSyncClientCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['notebook_document.synchronization.dynamic_registration'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['notebook_document.synchronization.dynamic_registration'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['notebook_document.synchronization.execution_summary_support'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['notebook_document.synchronization.execution_summary_support'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['window'], default: None = None) -> types.WindowClientCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['window'], default: types.WindowClientCapabilities) -> types.WindowClientCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['window.work_done_progress'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['window.work_done_progress'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['window.show_message'], default: None = None) -> types.ShowMessageRequestClientCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['window.show_message'], default: types.ShowMessageRequestClientCapabilities) -> types.ShowMessageRequestClientCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['window.show_message.message_action_item'], default: None = None) -> types.ClientShowMessageActionItemOptions | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['window.show_message.message_action_item'], default: types.ClientShowMessageActionItemOptions) -> types.ClientShowMessageActionItemOptions: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['window.show_message.message_action_item.additional_properties_support'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['window.show_message.message_action_item.additional_properties_support'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['window.show_document'], default: None = None) -> types.ShowDocumentClientCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['window.show_document'], default: types.ShowDocumentClientCapabilities) -> types.ShowDocumentClientCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['window.show_document.support'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['window.show_document.support'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['general'], default: None = None) -> types.GeneralClientCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['general'], default: types.GeneralClientCapabilities) -> types.GeneralClientCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['general.stale_request_support'], default: None = None) -> types.StaleRequestSupportOptions | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['general.stale_request_support'], default: types.StaleRequestSupportOptions) -> types.StaleRequestSupportOptions: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['general.stale_request_support.cancel'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['general.stale_request_support.cancel'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['general.stale_request_support.retry_on_content_modified'], default: None = None) -> Sequence[str] | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['general.stale_request_support.retry_on_content_modified'], default: Sequence[str]) -> Sequence[str]: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['general.regular_expressions'], default: None = None) -> types.RegularExpressionsClientCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['general.regular_expressions'], default: types.RegularExpressionsClientCapabilities) -> types.RegularExpressionsClientCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['general.regular_expressions.engine'], default: None = None) -> str | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['general.regular_expressions.engine'], default: str) -> str: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['general.regular_expressions.version'], default: None = None) -> str | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['general.regular_expressions.version'], default: str) -> str: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['general.markdown'], default: None = None) -> types.MarkdownClientCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['general.markdown'], default: types.MarkdownClientCapabilities) -> types.MarkdownClientCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['general.markdown.parser'], default: None = None) -> str | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['general.markdown.parser'], default: str) -> str: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['general.markdown.version'], default: None = None) -> str | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['general.markdown.version'], default: str) -> str: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['general.markdown.allowed_tags'], default: None = None) -> Sequence[str] | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['general.markdown.allowed_tags'], default: Sequence[str]) -> Sequence[str]: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['general.position_encodings'], default: None = None) -> Sequence[Union[types.PositionEncodingKind, str]] | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['general.position_encodings'], default: Sequence[Union[types.PositionEncodingKind, str]]) -> Sequence[Union[types.PositionEncodingKind, str]]: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['experimental'], default: None = None) -> Any | None: ... +@typing.overload +def get_capability(capabilities: types.ClientCapabilities, field: Literal['experimental'], default: Any) -> Any: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['position_encoding'], default: None = None) -> Union[types.PositionEncodingKind, str, None] | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['position_encoding'], default: Union[types.PositionEncodingKind, str, None]) -> Union[types.PositionEncodingKind, str, None]: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['text_document_sync'], default: None = None) -> Union[types.TextDocumentSyncOptions, types.TextDocumentSyncKind, None] | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['text_document_sync'], default: Union[types.TextDocumentSyncOptions, types.TextDocumentSyncKind, None]) -> Union[types.TextDocumentSyncOptions, types.TextDocumentSyncKind, None]: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['notebook_document_sync'], default: None = None) -> Union[types.NotebookDocumentSyncOptions, types.NotebookDocumentSyncRegistrationOptions, None] | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['notebook_document_sync'], default: Union[types.NotebookDocumentSyncOptions, types.NotebookDocumentSyncRegistrationOptions, None]) -> Union[types.NotebookDocumentSyncOptions, types.NotebookDocumentSyncRegistrationOptions, None]: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['completion_provider'], default: None = None) -> types.CompletionOptions | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['completion_provider'], default: types.CompletionOptions) -> types.CompletionOptions: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['completion_provider.trigger_characters'], default: None = None) -> Sequence[str] | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['completion_provider.trigger_characters'], default: Sequence[str]) -> Sequence[str]: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['completion_provider.all_commit_characters'], default: None = None) -> Sequence[str] | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['completion_provider.all_commit_characters'], default: Sequence[str]) -> Sequence[str]: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['completion_provider.resolve_provider'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['completion_provider.resolve_provider'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['completion_provider.completion_item'], default: None = None) -> types.ServerCompletionItemOptions | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['completion_provider.completion_item'], default: types.ServerCompletionItemOptions) -> types.ServerCompletionItemOptions: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['completion_provider.completion_item.label_details_support'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['completion_provider.completion_item.label_details_support'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['completion_provider.work_done_progress'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['completion_provider.work_done_progress'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['hover_provider'], default: None = None) -> Union[bool, types.HoverOptions, None] | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['hover_provider'], default: Union[bool, types.HoverOptions, None]) -> Union[bool, types.HoverOptions, None]: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['signature_help_provider'], default: None = None) -> types.SignatureHelpOptions | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['signature_help_provider'], default: types.SignatureHelpOptions) -> types.SignatureHelpOptions: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['signature_help_provider.trigger_characters'], default: None = None) -> Sequence[str] | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['signature_help_provider.trigger_characters'], default: Sequence[str]) -> Sequence[str]: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['signature_help_provider.retrigger_characters'], default: None = None) -> Sequence[str] | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['signature_help_provider.retrigger_characters'], default: Sequence[str]) -> Sequence[str]: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['signature_help_provider.work_done_progress'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['signature_help_provider.work_done_progress'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['declaration_provider'], default: None = None) -> Union[bool, types.DeclarationOptions, types.DeclarationRegistrationOptions, None] | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['declaration_provider'], default: Union[bool, types.DeclarationOptions, types.DeclarationRegistrationOptions, None]) -> Union[bool, types.DeclarationOptions, types.DeclarationRegistrationOptions, None]: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['definition_provider'], default: None = None) -> Union[bool, types.DefinitionOptions, None] | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['definition_provider'], default: Union[bool, types.DefinitionOptions, None]) -> Union[bool, types.DefinitionOptions, None]: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['type_definition_provider'], default: None = None) -> Union[bool, types.TypeDefinitionOptions, types.TypeDefinitionRegistrationOptions, None] | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['type_definition_provider'], default: Union[bool, types.TypeDefinitionOptions, types.TypeDefinitionRegistrationOptions, None]) -> Union[bool, types.TypeDefinitionOptions, types.TypeDefinitionRegistrationOptions, None]: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['implementation_provider'], default: None = None) -> Union[bool, types.ImplementationOptions, types.ImplementationRegistrationOptions, None] | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['implementation_provider'], default: Union[bool, types.ImplementationOptions, types.ImplementationRegistrationOptions, None]) -> Union[bool, types.ImplementationOptions, types.ImplementationRegistrationOptions, None]: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['references_provider'], default: None = None) -> Union[bool, types.ReferenceOptions, None] | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['references_provider'], default: Union[bool, types.ReferenceOptions, None]) -> Union[bool, types.ReferenceOptions, None]: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['document_highlight_provider'], default: None = None) -> Union[bool, types.DocumentHighlightOptions, None] | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['document_highlight_provider'], default: Union[bool, types.DocumentHighlightOptions, None]) -> Union[bool, types.DocumentHighlightOptions, None]: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['document_symbol_provider'], default: None = None) -> Union[bool, types.DocumentSymbolOptions, None] | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['document_symbol_provider'], default: Union[bool, types.DocumentSymbolOptions, None]) -> Union[bool, types.DocumentSymbolOptions, None]: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['code_action_provider'], default: None = None) -> Union[bool, types.CodeActionOptions, None] | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['code_action_provider'], default: Union[bool, types.CodeActionOptions, None]) -> Union[bool, types.CodeActionOptions, None]: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['code_lens_provider'], default: None = None) -> types.CodeLensOptions | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['code_lens_provider'], default: types.CodeLensOptions) -> types.CodeLensOptions: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['code_lens_provider.resolve_provider'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['code_lens_provider.resolve_provider'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['code_lens_provider.work_done_progress'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['code_lens_provider.work_done_progress'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['document_link_provider'], default: None = None) -> types.DocumentLinkOptions | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['document_link_provider'], default: types.DocumentLinkOptions) -> types.DocumentLinkOptions: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['document_link_provider.resolve_provider'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['document_link_provider.resolve_provider'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['document_link_provider.work_done_progress'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['document_link_provider.work_done_progress'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['color_provider'], default: None = None) -> Union[bool, types.DocumentColorOptions, types.DocumentColorRegistrationOptions, None] | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['color_provider'], default: Union[bool, types.DocumentColorOptions, types.DocumentColorRegistrationOptions, None]) -> Union[bool, types.DocumentColorOptions, types.DocumentColorRegistrationOptions, None]: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace_symbol_provider'], default: None = None) -> Union[bool, types.WorkspaceSymbolOptions, None] | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace_symbol_provider'], default: Union[bool, types.WorkspaceSymbolOptions, None]) -> Union[bool, types.WorkspaceSymbolOptions, None]: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['document_formatting_provider'], default: None = None) -> Union[bool, types.DocumentFormattingOptions, None] | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['document_formatting_provider'], default: Union[bool, types.DocumentFormattingOptions, None]) -> Union[bool, types.DocumentFormattingOptions, None]: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['document_range_formatting_provider'], default: None = None) -> Union[bool, types.DocumentRangeFormattingOptions, None] | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['document_range_formatting_provider'], default: Union[bool, types.DocumentRangeFormattingOptions, None]) -> Union[bool, types.DocumentRangeFormattingOptions, None]: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['document_on_type_formatting_provider'], default: None = None) -> types.DocumentOnTypeFormattingOptions | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['document_on_type_formatting_provider'], default: types.DocumentOnTypeFormattingOptions) -> types.DocumentOnTypeFormattingOptions: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['document_on_type_formatting_provider.first_trigger_character'], default: None = None) -> str | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['document_on_type_formatting_provider.first_trigger_character'], default: str) -> str: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['document_on_type_formatting_provider.more_trigger_character'], default: None = None) -> Sequence[str] | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['document_on_type_formatting_provider.more_trigger_character'], default: Sequence[str]) -> Sequence[str]: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['rename_provider'], default: None = None) -> Union[bool, types.RenameOptions, None] | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['rename_provider'], default: Union[bool, types.RenameOptions, None]) -> Union[bool, types.RenameOptions, None]: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['folding_range_provider'], default: None = None) -> Union[bool, types.FoldingRangeOptions, types.FoldingRangeRegistrationOptions, None] | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['folding_range_provider'], default: Union[bool, types.FoldingRangeOptions, types.FoldingRangeRegistrationOptions, None]) -> Union[bool, types.FoldingRangeOptions, types.FoldingRangeRegistrationOptions, None]: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['selection_range_provider'], default: None = None) -> Union[bool, types.SelectionRangeOptions, types.SelectionRangeRegistrationOptions, None] | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['selection_range_provider'], default: Union[bool, types.SelectionRangeOptions, types.SelectionRangeRegistrationOptions, None]) -> Union[bool, types.SelectionRangeOptions, types.SelectionRangeRegistrationOptions, None]: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['execute_command_provider'], default: None = None) -> types.ExecuteCommandOptions | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['execute_command_provider'], default: types.ExecuteCommandOptions) -> types.ExecuteCommandOptions: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['execute_command_provider.commands'], default: None = None) -> Sequence[str] | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['execute_command_provider.commands'], default: Sequence[str]) -> Sequence[str]: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['execute_command_provider.work_done_progress'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['execute_command_provider.work_done_progress'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['call_hierarchy_provider'], default: None = None) -> Union[bool, types.CallHierarchyOptions, types.CallHierarchyRegistrationOptions, None] | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['call_hierarchy_provider'], default: Union[bool, types.CallHierarchyOptions, types.CallHierarchyRegistrationOptions, None]) -> Union[bool, types.CallHierarchyOptions, types.CallHierarchyRegistrationOptions, None]: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['linked_editing_range_provider'], default: None = None) -> Union[bool, types.LinkedEditingRangeOptions, types.LinkedEditingRangeRegistrationOptions, None] | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['linked_editing_range_provider'], default: Union[bool, types.LinkedEditingRangeOptions, types.LinkedEditingRangeRegistrationOptions, None]) -> Union[bool, types.LinkedEditingRangeOptions, types.LinkedEditingRangeRegistrationOptions, None]: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['semantic_tokens_provider'], default: None = None) -> Union[types.SemanticTokensOptions, types.SemanticTokensRegistrationOptions, None] | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['semantic_tokens_provider'], default: Union[types.SemanticTokensOptions, types.SemanticTokensRegistrationOptions, None]) -> Union[types.SemanticTokensOptions, types.SemanticTokensRegistrationOptions, None]: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['moniker_provider'], default: None = None) -> Union[bool, types.MonikerOptions, types.MonikerRegistrationOptions, None] | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['moniker_provider'], default: Union[bool, types.MonikerOptions, types.MonikerRegistrationOptions, None]) -> Union[bool, types.MonikerOptions, types.MonikerRegistrationOptions, None]: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['type_hierarchy_provider'], default: None = None) -> Union[bool, types.TypeHierarchyOptions, types.TypeHierarchyRegistrationOptions, None] | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['type_hierarchy_provider'], default: Union[bool, types.TypeHierarchyOptions, types.TypeHierarchyRegistrationOptions, None]) -> Union[bool, types.TypeHierarchyOptions, types.TypeHierarchyRegistrationOptions, None]: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['inline_value_provider'], default: None = None) -> Union[bool, types.InlineValueOptions, types.InlineValueRegistrationOptions, None] | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['inline_value_provider'], default: Union[bool, types.InlineValueOptions, types.InlineValueRegistrationOptions, None]) -> Union[bool, types.InlineValueOptions, types.InlineValueRegistrationOptions, None]: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['inlay_hint_provider'], default: None = None) -> Union[bool, types.InlayHintOptions, types.InlayHintRegistrationOptions, None] | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['inlay_hint_provider'], default: Union[bool, types.InlayHintOptions, types.InlayHintRegistrationOptions, None]) -> Union[bool, types.InlayHintOptions, types.InlayHintRegistrationOptions, None]: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['diagnostic_provider'], default: None = None) -> Union[types.DiagnosticOptions, types.DiagnosticRegistrationOptions, None] | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['diagnostic_provider'], default: Union[types.DiagnosticOptions, types.DiagnosticRegistrationOptions, None]) -> Union[types.DiagnosticOptions, types.DiagnosticRegistrationOptions, None]: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['inline_completion_provider'], default: None = None) -> Union[bool, types.InlineCompletionOptions, None] | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['inline_completion_provider'], default: Union[bool, types.InlineCompletionOptions, None]) -> Union[bool, types.InlineCompletionOptions, None]: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace'], default: None = None) -> types.WorkspaceOptions | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace'], default: types.WorkspaceOptions) -> types.WorkspaceOptions: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.workspace_folders'], default: None = None) -> types.WorkspaceFoldersServerCapabilities | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.workspace_folders'], default: types.WorkspaceFoldersServerCapabilities) -> types.WorkspaceFoldersServerCapabilities: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.workspace_folders.supported'], default: None = None) -> bool | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.workspace_folders.supported'], default: bool) -> bool: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.workspace_folders.change_notifications'], default: None = None) -> Union[str, bool, None] | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.workspace_folders.change_notifications'], default: Union[str, bool, None]) -> Union[str, bool, None]: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations'], default: None = None) -> types.FileOperationOptions | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations'], default: types.FileOperationOptions) -> types.FileOperationOptions: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.did_create'], default: None = None) -> types.FileOperationRegistrationOptions | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.did_create'], default: types.FileOperationRegistrationOptions) -> types.FileOperationRegistrationOptions: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.did_create.filters'], default: None = None) -> Sequence[types.FileOperationFilter] | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.did_create.filters'], default: Sequence[types.FileOperationFilter]) -> Sequence[types.FileOperationFilter]: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.will_create'], default: None = None) -> types.FileOperationRegistrationOptions | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.will_create'], default: types.FileOperationRegistrationOptions) -> types.FileOperationRegistrationOptions: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.will_create.filters'], default: None = None) -> Sequence[types.FileOperationFilter] | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.will_create.filters'], default: Sequence[types.FileOperationFilter]) -> Sequence[types.FileOperationFilter]: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.did_rename'], default: None = None) -> types.FileOperationRegistrationOptions | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.did_rename'], default: types.FileOperationRegistrationOptions) -> types.FileOperationRegistrationOptions: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.did_rename.filters'], default: None = None) -> Sequence[types.FileOperationFilter] | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.did_rename.filters'], default: Sequence[types.FileOperationFilter]) -> Sequence[types.FileOperationFilter]: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.will_rename'], default: None = None) -> types.FileOperationRegistrationOptions | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.will_rename'], default: types.FileOperationRegistrationOptions) -> types.FileOperationRegistrationOptions: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.will_rename.filters'], default: None = None) -> Sequence[types.FileOperationFilter] | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.will_rename.filters'], default: Sequence[types.FileOperationFilter]) -> Sequence[types.FileOperationFilter]: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.did_delete'], default: None = None) -> types.FileOperationRegistrationOptions | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.did_delete'], default: types.FileOperationRegistrationOptions) -> types.FileOperationRegistrationOptions: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.did_delete.filters'], default: None = None) -> Sequence[types.FileOperationFilter] | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.did_delete.filters'], default: Sequence[types.FileOperationFilter]) -> Sequence[types.FileOperationFilter]: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.will_delete'], default: None = None) -> types.FileOperationRegistrationOptions | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.will_delete'], default: types.FileOperationRegistrationOptions) -> types.FileOperationRegistrationOptions: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.will_delete.filters'], default: None = None) -> Sequence[types.FileOperationFilter] | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.file_operations.will_delete.filters'], default: Sequence[types.FileOperationFilter]) -> Sequence[types.FileOperationFilter]: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.text_document_content'], default: None = None) -> Union[types.TextDocumentContentOptions, types.TextDocumentContentRegistrationOptions, None] | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['workspace.text_document_content'], default: Union[types.TextDocumentContentOptions, types.TextDocumentContentRegistrationOptions, None]) -> Union[types.TextDocumentContentOptions, types.TextDocumentContentRegistrationOptions, None]: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['experimental'], default: None = None) -> Any | None: ... +@typing.overload +def get_capability(capabilities: types.ServerCapabilities, field: Literal['experimental'], default: Any) -> Any: ... +@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/server/libs/pygls/lsp/client.py b/server/libs/pygls/lsp/client.py index c877fdb..c100d34 100644 --- a/server/libs/pygls/lsp/client.py +++ b/server/libs/pygls/lsp/client.py @@ -1,1961 +1,6 @@ -# GENERATED FROM scripts/gen-client.py -- DO NOT EDIT -# flake8: noqa -from concurrent.futures import Future -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 List -from typing import Optional -from typing import Union +from ._base_client import BaseLanguageClient -class BaseLanguageClient(JsonRPCClient): - - def __init__( - self, - name: str, - version: str, - protocol_cls=LanguageServerProtocol, - converter_factory=default_converter, - **kwargs, - ): - self.name = name - self.version = version - super().__init__(protocol_cls, converter_factory, **kwargs) - - def call_hierarchy_incoming_calls( - self, - params: types.CallHierarchyIncomingCallsParams, - callback: Optional[Callable[[Optional[List[types.CallHierarchyIncomingCall]]], None]] = None, - ) -> Future: - """Make a :lsp:`callHierarchy/incomingCalls` request. - - A request to resolve the incoming calls for a given `CallHierarchyItem`. - - @since 3.16.0 - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return self.protocol.send_request("callHierarchy/incomingCalls", params, callback) - - async def call_hierarchy_incoming_calls_async( - self, - params: types.CallHierarchyIncomingCallsParams, - ) -> Optional[List[types.CallHierarchyIncomingCall]]: - """Make a :lsp:`callHierarchy/incomingCalls` request. - - A request to resolve the incoming calls for a given `CallHierarchyItem`. - - @since 3.16.0 - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return await self.protocol.send_request_async("callHierarchy/incomingCalls", params) - - def call_hierarchy_outgoing_calls( - self, - params: types.CallHierarchyOutgoingCallsParams, - callback: Optional[Callable[[Optional[List[types.CallHierarchyOutgoingCall]]], None]] = None, - ) -> Future: - """Make a :lsp:`callHierarchy/outgoingCalls` request. - - A request to resolve the outgoing calls for a given `CallHierarchyItem`. - - @since 3.16.0 - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return self.protocol.send_request("callHierarchy/outgoingCalls", params, callback) - - async def call_hierarchy_outgoing_calls_async( - self, - params: types.CallHierarchyOutgoingCallsParams, - ) -> Optional[List[types.CallHierarchyOutgoingCall]]: - """Make a :lsp:`callHierarchy/outgoingCalls` request. - - A request to resolve the outgoing calls for a given `CallHierarchyItem`. - - @since 3.16.0 - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return await self.protocol.send_request_async("callHierarchy/outgoingCalls", params) - - def code_action_resolve( - self, - params: types.CodeAction, - callback: Optional[Callable[[types.CodeAction], None]] = None, - ) -> Future: - """Make a :lsp:`codeAction/resolve` request. - - Request to resolve additional information for a given code action.The request's - parameter is of type {@link CodeAction} the response - is of type {@link CodeAction} or a Thenable that resolves to such. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return self.protocol.send_request("codeAction/resolve", params, callback) - - async def code_action_resolve_async( - self, - params: types.CodeAction, - ) -> types.CodeAction: - """Make a :lsp:`codeAction/resolve` request. - - Request to resolve additional information for a given code action.The request's - parameter is of type {@link CodeAction} the response - is of type {@link CodeAction} or a Thenable that resolves to such. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return await self.protocol.send_request_async("codeAction/resolve", params) - - def code_lens_resolve( - self, - params: types.CodeLens, - callback: Optional[Callable[[types.CodeLens], None]] = None, - ) -> Future: - """Make a :lsp:`codeLens/resolve` request. - - A request to resolve a command for a given code lens. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return self.protocol.send_request("codeLens/resolve", params, callback) - - async def code_lens_resolve_async( - self, - params: types.CodeLens, - ) -> types.CodeLens: - """Make a :lsp:`codeLens/resolve` request. - - A request to resolve a command for a given code lens. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return await self.protocol.send_request_async("codeLens/resolve", params) - - def completion_item_resolve( - self, - params: types.CompletionItem, - callback: Optional[Callable[[types.CompletionItem], None]] = None, - ) -> Future: - """Make a :lsp:`completionItem/resolve` request. - - Request to resolve additional information for a given completion item.The request's - parameter is of type {@link CompletionItem} the response - is of type {@link CompletionItem} or a Thenable that resolves to such. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return self.protocol.send_request("completionItem/resolve", params, callback) - - async def completion_item_resolve_async( - self, - params: types.CompletionItem, - ) -> types.CompletionItem: - """Make a :lsp:`completionItem/resolve` request. - - Request to resolve additional information for a given completion item.The request's - parameter is of type {@link CompletionItem} the response - is of type {@link CompletionItem} or a Thenable that resolves to such. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return await self.protocol.send_request_async("completionItem/resolve", params) - - def document_link_resolve( - self, - params: types.DocumentLink, - callback: Optional[Callable[[types.DocumentLink], None]] = None, - ) -> Future: - """Make a :lsp:`documentLink/resolve` request. - - Request to resolve additional information for a given document link. The request's - parameter is of type {@link DocumentLink} the response - is of type {@link DocumentLink} or a Thenable that resolves to such. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return self.protocol.send_request("documentLink/resolve", params, callback) - - async def document_link_resolve_async( - self, - params: types.DocumentLink, - ) -> types.DocumentLink: - """Make a :lsp:`documentLink/resolve` request. - - Request to resolve additional information for a given document link. The request's - parameter is of type {@link DocumentLink} the response - is of type {@link DocumentLink} or a Thenable that resolves to such. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return await self.protocol.send_request_async("documentLink/resolve", params) - - def initialize( - self, - params: types.InitializeParams, - callback: Optional[Callable[[types.InitializeResult], None]] = None, - ) -> Future: - """Make a :lsp:`initialize` request. - - The initialize request is sent from the client to the server. - It is sent once as the request after starting up the server. - The requests parameter is of type {@link InitializeParams} - the response if of type {@link InitializeResult} of a Thenable that - resolves to such. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return self.protocol.send_request("initialize", params, callback) - - async def initialize_async( - self, - params: types.InitializeParams, - ) -> types.InitializeResult: - """Make a :lsp:`initialize` request. - - The initialize request is sent from the client to the server. - It is sent once as the request after starting up the server. - The requests parameter is of type {@link InitializeParams} - the response if of type {@link InitializeResult} of a Thenable that - resolves to such. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return await self.protocol.send_request_async("initialize", params) - - def inlay_hint_resolve( - self, - params: types.InlayHint, - callback: Optional[Callable[[types.InlayHint], None]] = None, - ) -> Future: - """Make a :lsp:`inlayHint/resolve` request. - - A request to resolve additional properties for an inlay hint. - The request's parameter is of type {@link InlayHint}, the response is - of type {@link InlayHint} or a Thenable that resolves to such. - - @since 3.17.0 - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return self.protocol.send_request("inlayHint/resolve", params, callback) - - async def inlay_hint_resolve_async( - self, - params: types.InlayHint, - ) -> types.InlayHint: - """Make a :lsp:`inlayHint/resolve` request. - - A request to resolve additional properties for an inlay hint. - The request's parameter is of type {@link InlayHint}, the response is - of type {@link InlayHint} or a Thenable that resolves to such. - - @since 3.17.0 - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return await self.protocol.send_request_async("inlayHint/resolve", params) - - def shutdown( - self, - params: None, - callback: Optional[Callable[[None], None]] = None, - ) -> Future: - """Make a :lsp:`shutdown` request. - - A shutdown request is sent from the client to the server. - It is sent once when the client decides to shutdown the - server. The only notification that is sent after a shutdown request - is the exit event. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return self.protocol.send_request("shutdown", params, callback) - - async def shutdown_async( - self, - params: None, - ) -> None: - """Make a :lsp:`shutdown` request. - - A shutdown request is sent from the client to the server. - It is sent once when the client decides to shutdown the - server. The only notification that is sent after a shutdown request - is the exit event. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return await self.protocol.send_request_async("shutdown", params) - - def text_document_code_action( - self, - params: types.CodeActionParams, - callback: Optional[Callable[[Optional[List[Union[types.Command, types.CodeAction]]]], None]] = None, - ) -> Future: - """Make a :lsp:`textDocument/codeAction` request. - - A request to provide commands for the given text document and range. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return self.protocol.send_request("textDocument/codeAction", params, callback) - - async def text_document_code_action_async( - self, - params: types.CodeActionParams, - ) -> Optional[List[Union[types.Command, types.CodeAction]]]: - """Make a :lsp:`textDocument/codeAction` request. - - A request to provide commands for the given text document and range. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return await self.protocol.send_request_async("textDocument/codeAction", params) - - def text_document_code_lens( - self, - params: types.CodeLensParams, - callback: Optional[Callable[[Optional[List[types.CodeLens]]], None]] = None, - ) -> Future: - """Make a :lsp:`textDocument/codeLens` request. - - A request to provide code lens for the given text document. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return self.protocol.send_request("textDocument/codeLens", params, callback) - - async def text_document_code_lens_async( - self, - params: types.CodeLensParams, - ) -> Optional[List[types.CodeLens]]: - """Make a :lsp:`textDocument/codeLens` request. - - A request to provide code lens for the given text document. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return await self.protocol.send_request_async("textDocument/codeLens", params) - - def text_document_color_presentation( - self, - params: types.ColorPresentationParams, - callback: Optional[Callable[[List[types.ColorPresentation]], None]] = None, - ) -> Future: - """Make a :lsp:`textDocument/colorPresentation` request. - - A request to list all presentation for a color. The request's - parameter is of type {@link ColorPresentationParams} the - response is of type {@link ColorInformation ColorInformation[]} or a Thenable - that resolves to such. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return self.protocol.send_request("textDocument/colorPresentation", params, callback) - - async def text_document_color_presentation_async( - self, - params: types.ColorPresentationParams, - ) -> List[types.ColorPresentation]: - """Make a :lsp:`textDocument/colorPresentation` request. - - A request to list all presentation for a color. The request's - parameter is of type {@link ColorPresentationParams} the - response is of type {@link ColorInformation ColorInformation[]} or a Thenable - that resolves to such. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return await self.protocol.send_request_async("textDocument/colorPresentation", params) - - def text_document_completion( - self, - params: types.CompletionParams, - callback: Optional[Callable[[Union[List[types.CompletionItem], types.CompletionList, None]], None]] = None, - ) -> Future: - """Make a :lsp:`textDocument/completion` request. - - Request to request completion at a given text document position. The request's - parameter is of type {@link TextDocumentPosition} the response - is of type {@link CompletionItem CompletionItem[]} or {@link CompletionList} - or a Thenable that resolves to such. - - The request can delay the computation of the {@link CompletionItem.detail `detail`} - and {@link CompletionItem.documentation `documentation`} properties to the `completionItem/resolve` - request. However, properties that are needed for the initial sorting and filtering, like `sortText`, - `filterText`, `insertText`, and `textEdit`, must not be changed during resolve. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return self.protocol.send_request("textDocument/completion", params, callback) - - async def text_document_completion_async( - self, - params: types.CompletionParams, - ) -> Union[List[types.CompletionItem], types.CompletionList, None]: - """Make a :lsp:`textDocument/completion` request. - - Request to request completion at a given text document position. The request's - parameter is of type {@link TextDocumentPosition} the response - is of type {@link CompletionItem CompletionItem[]} or {@link CompletionList} - or a Thenable that resolves to such. - - The request can delay the computation of the {@link CompletionItem.detail `detail`} - and {@link CompletionItem.documentation `documentation`} properties to the `completionItem/resolve` - request. However, properties that are needed for the initial sorting and filtering, like `sortText`, - `filterText`, `insertText`, and `textEdit`, must not be changed during resolve. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return await self.protocol.send_request_async("textDocument/completion", params) - - def text_document_declaration( - self, - params: types.DeclarationParams, - callback: Optional[Callable[[Union[types.Location, List[types.Location], List[types.LocationLink], None]], None]] = None, - ) -> Future: - """Make a :lsp:`textDocument/declaration` request. - - A request to resolve the type definition locations of a symbol at a given text - document position. The request's parameter is of type {@link TextDocumentPositionParams} - the response is of type {@link Declaration} or a typed array of {@link DeclarationLink} - or a Thenable that resolves to such. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return self.protocol.send_request("textDocument/declaration", params, callback) - - async def text_document_declaration_async( - self, - params: types.DeclarationParams, - ) -> Union[types.Location, List[types.Location], List[types.LocationLink], None]: - """Make a :lsp:`textDocument/declaration` request. - - A request to resolve the type definition locations of a symbol at a given text - document position. The request's parameter is of type {@link TextDocumentPositionParams} - the response is of type {@link Declaration} or a typed array of {@link DeclarationLink} - or a Thenable that resolves to such. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return await self.protocol.send_request_async("textDocument/declaration", params) - - def text_document_definition( - self, - params: types.DefinitionParams, - callback: Optional[Callable[[Union[types.Location, List[types.Location], List[types.LocationLink], None]], None]] = None, - ) -> Future: - """Make a :lsp:`textDocument/definition` request. - - A request to resolve the definition location of a symbol at a given text - document position. The request's parameter is of type {@link TextDocumentPosition} - the response is of either type {@link Definition} or a typed array of - {@link DefinitionLink} or a Thenable that resolves to such. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return self.protocol.send_request("textDocument/definition", params, callback) - - async def text_document_definition_async( - self, - params: types.DefinitionParams, - ) -> Union[types.Location, List[types.Location], List[types.LocationLink], None]: - """Make a :lsp:`textDocument/definition` request. - - A request to resolve the definition location of a symbol at a given text - document position. The request's parameter is of type {@link TextDocumentPosition} - the response is of either type {@link Definition} or a typed array of - {@link DefinitionLink} or a Thenable that resolves to such. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return await self.protocol.send_request_async("textDocument/definition", params) - - def text_document_diagnostic( - self, - params: types.DocumentDiagnosticParams, - callback: Optional[Callable[[Union[types.RelatedFullDocumentDiagnosticReport, types.RelatedUnchangedDocumentDiagnosticReport]], None]] = None, - ) -> Future: - """Make a :lsp:`textDocument/diagnostic` request. - - The document diagnostic request definition. - - @since 3.17.0 - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return self.protocol.send_request("textDocument/diagnostic", params, callback) - - async def text_document_diagnostic_async( - self, - params: types.DocumentDiagnosticParams, - ) -> Union[types.RelatedFullDocumentDiagnosticReport, types.RelatedUnchangedDocumentDiagnosticReport]: - """Make a :lsp:`textDocument/diagnostic` request. - - The document diagnostic request definition. - - @since 3.17.0 - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return await self.protocol.send_request_async("textDocument/diagnostic", params) - - def text_document_document_color( - self, - params: types.DocumentColorParams, - callback: Optional[Callable[[List[types.ColorInformation]], None]] = None, - ) -> Future: - """Make a :lsp:`textDocument/documentColor` request. - - A request to list all color symbols found in a given text document. The request's - parameter is of type {@link DocumentColorParams} the - response is of type {@link ColorInformation ColorInformation[]} or a Thenable - that resolves to such. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return self.protocol.send_request("textDocument/documentColor", params, callback) - - async def text_document_document_color_async( - self, - params: types.DocumentColorParams, - ) -> List[types.ColorInformation]: - """Make a :lsp:`textDocument/documentColor` request. - - A request to list all color symbols found in a given text document. The request's - parameter is of type {@link DocumentColorParams} the - response is of type {@link ColorInformation ColorInformation[]} or a Thenable - that resolves to such. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return await self.protocol.send_request_async("textDocument/documentColor", params) - - def text_document_document_highlight( - self, - params: types.DocumentHighlightParams, - callback: Optional[Callable[[Optional[List[types.DocumentHighlight]]], None]] = None, - ) -> Future: - """Make a :lsp:`textDocument/documentHighlight` request. - - Request to resolve a {@link DocumentHighlight} for a given - text document position. The request's parameter is of type {@link TextDocumentPosition} - the request response is an array of type {@link DocumentHighlight} - or a Thenable that resolves to such. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return self.protocol.send_request("textDocument/documentHighlight", params, callback) - - async def text_document_document_highlight_async( - self, - params: types.DocumentHighlightParams, - ) -> Optional[List[types.DocumentHighlight]]: - """Make a :lsp:`textDocument/documentHighlight` request. - - Request to resolve a {@link DocumentHighlight} for a given - text document position. The request's parameter is of type {@link TextDocumentPosition} - the request response is an array of type {@link DocumentHighlight} - or a Thenable that resolves to such. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return await self.protocol.send_request_async("textDocument/documentHighlight", params) - - def text_document_document_link( - self, - params: types.DocumentLinkParams, - callback: Optional[Callable[[Optional[List[types.DocumentLink]]], None]] = None, - ) -> Future: - """Make a :lsp:`textDocument/documentLink` request. - - A request to provide document links - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return self.protocol.send_request("textDocument/documentLink", params, callback) - - async def text_document_document_link_async( - self, - params: types.DocumentLinkParams, - ) -> Optional[List[types.DocumentLink]]: - """Make a :lsp:`textDocument/documentLink` request. - - A request to provide document links - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return await self.protocol.send_request_async("textDocument/documentLink", params) - - def text_document_document_symbol( - self, - params: types.DocumentSymbolParams, - callback: Optional[Callable[[Union[List[types.SymbolInformation], List[types.DocumentSymbol], None]], None]] = None, - ) -> Future: - """Make a :lsp:`textDocument/documentSymbol` request. - - A request to list all symbols found in a given text document. The request's - parameter is of type {@link TextDocumentIdentifier} the - response is of type {@link SymbolInformation SymbolInformation[]} or a Thenable - that resolves to such. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return self.protocol.send_request("textDocument/documentSymbol", params, callback) - - async def text_document_document_symbol_async( - self, - params: types.DocumentSymbolParams, - ) -> Union[List[types.SymbolInformation], List[types.DocumentSymbol], None]: - """Make a :lsp:`textDocument/documentSymbol` request. - - A request to list all symbols found in a given text document. The request's - parameter is of type {@link TextDocumentIdentifier} the - response is of type {@link SymbolInformation SymbolInformation[]} or a Thenable - that resolves to such. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return await self.protocol.send_request_async("textDocument/documentSymbol", params) - - def text_document_folding_range( - self, - params: types.FoldingRangeParams, - callback: Optional[Callable[[Optional[List[types.FoldingRange]]], None]] = None, - ) -> Future: - """Make a :lsp:`textDocument/foldingRange` request. - - A request to provide folding ranges in a document. The request's - parameter is of type {@link FoldingRangeParams}, the - response is of type {@link FoldingRangeList} or a Thenable - that resolves to such. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return self.protocol.send_request("textDocument/foldingRange", params, callback) - - async def text_document_folding_range_async( - self, - params: types.FoldingRangeParams, - ) -> Optional[List[types.FoldingRange]]: - """Make a :lsp:`textDocument/foldingRange` request. - - A request to provide folding ranges in a document. The request's - parameter is of type {@link FoldingRangeParams}, the - response is of type {@link FoldingRangeList} or a Thenable - that resolves to such. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return await self.protocol.send_request_async("textDocument/foldingRange", params) - - def text_document_formatting( - self, - params: types.DocumentFormattingParams, - callback: Optional[Callable[[Optional[List[types.TextEdit]]], None]] = None, - ) -> Future: - """Make a :lsp:`textDocument/formatting` request. - - A request to format a whole document. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return self.protocol.send_request("textDocument/formatting", params, callback) - - async def text_document_formatting_async( - self, - params: types.DocumentFormattingParams, - ) -> Optional[List[types.TextEdit]]: - """Make a :lsp:`textDocument/formatting` request. - - A request to format a whole document. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return await self.protocol.send_request_async("textDocument/formatting", params) - - def text_document_hover( - self, - params: types.HoverParams, - callback: Optional[Callable[[Optional[types.Hover]], None]] = None, - ) -> Future: - """Make a :lsp:`textDocument/hover` request. - - Request to request hover information at a given text document position. The request's - parameter is of type {@link TextDocumentPosition} the response is of - type {@link Hover} or a Thenable that resolves to such. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return self.protocol.send_request("textDocument/hover", params, callback) - - async def text_document_hover_async( - self, - params: types.HoverParams, - ) -> Optional[types.Hover]: - """Make a :lsp:`textDocument/hover` request. - - Request to request hover information at a given text document position. The request's - parameter is of type {@link TextDocumentPosition} the response is of - type {@link Hover} or a Thenable that resolves to such. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return await self.protocol.send_request_async("textDocument/hover", params) - - def text_document_implementation( - self, - params: types.ImplementationParams, - callback: Optional[Callable[[Union[types.Location, List[types.Location], List[types.LocationLink], None]], None]] = None, - ) -> Future: - """Make a :lsp:`textDocument/implementation` request. - - A request to resolve the implementation locations of a symbol at a given text - document position. The request's parameter is of type {@link TextDocumentPositionParams} - the response is of type {@link Definition} or a Thenable that resolves to such. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return self.protocol.send_request("textDocument/implementation", params, callback) - - async def text_document_implementation_async( - self, - params: types.ImplementationParams, - ) -> Union[types.Location, List[types.Location], List[types.LocationLink], None]: - """Make a :lsp:`textDocument/implementation` request. - - A request to resolve the implementation locations of a symbol at a given text - document position. The request's parameter is of type {@link TextDocumentPositionParams} - the response is of type {@link Definition} or a Thenable that resolves to such. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return await self.protocol.send_request_async("textDocument/implementation", params) - - def text_document_inlay_hint( - self, - params: types.InlayHintParams, - callback: Optional[Callable[[Optional[List[types.InlayHint]]], None]] = None, - ) -> Future: - """Make a :lsp:`textDocument/inlayHint` request. - - A request to provide inlay hints in a document. The request's parameter is of - type {@link InlayHintsParams}, the response is of type - {@link InlayHint InlayHint[]} or a Thenable that resolves to such. - - @since 3.17.0 - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return self.protocol.send_request("textDocument/inlayHint", params, callback) - - async def text_document_inlay_hint_async( - self, - params: types.InlayHintParams, - ) -> Optional[List[types.InlayHint]]: - """Make a :lsp:`textDocument/inlayHint` request. - - A request to provide inlay hints in a document. The request's parameter is of - type {@link InlayHintsParams}, the response is of type - {@link InlayHint InlayHint[]} or a Thenable that resolves to such. - - @since 3.17.0 - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return await self.protocol.send_request_async("textDocument/inlayHint", params) - - def text_document_inline_completion( - self, - params: types.InlineCompletionParams, - callback: Optional[Callable[[Union[types.InlineCompletionList, List[types.InlineCompletionItem], None]], None]] = None, - ) -> Future: - """Make a :lsp:`textDocument/inlineCompletion` request. - - A request to provide inline completions in a document. The request's parameter is of - type {@link InlineCompletionParams}, the response is of type - {@link InlineCompletion InlineCompletion[]} or a Thenable that resolves to such. - - @since 3.18.0 - @proposed - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return self.protocol.send_request("textDocument/inlineCompletion", params, callback) - - async def text_document_inline_completion_async( - self, - params: types.InlineCompletionParams, - ) -> Union[types.InlineCompletionList, List[types.InlineCompletionItem], None]: - """Make a :lsp:`textDocument/inlineCompletion` request. - - A request to provide inline completions in a document. The request's parameter is of - type {@link InlineCompletionParams}, the response is of type - {@link InlineCompletion InlineCompletion[]} or a Thenable that resolves to such. - - @since 3.18.0 - @proposed - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return await self.protocol.send_request_async("textDocument/inlineCompletion", params) - - def text_document_inline_value( - self, - params: types.InlineValueParams, - callback: Optional[Callable[[Optional[List[Union[types.InlineValueText, types.InlineValueVariableLookup, types.InlineValueEvaluatableExpression]]]], None]] = None, - ) -> Future: - """Make a :lsp:`textDocument/inlineValue` request. - - A request to provide inline values in a document. The request's parameter is of - type {@link InlineValueParams}, the response is of type - {@link InlineValue InlineValue[]} or a Thenable that resolves to such. - - @since 3.17.0 - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return self.protocol.send_request("textDocument/inlineValue", params, callback) - - async def text_document_inline_value_async( - self, - params: types.InlineValueParams, - ) -> Optional[List[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 - type {@link InlineValueParams}, the response is of type - {@link InlineValue InlineValue[]} or a Thenable that resolves to such. - - @since 3.17.0 - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return await self.protocol.send_request_async("textDocument/inlineValue", params) - - def text_document_linked_editing_range( - self, - params: types.LinkedEditingRangeParams, - callback: Optional[Callable[[Optional[types.LinkedEditingRanges]], None]] = None, - ) -> Future: - """Make a :lsp:`textDocument/linkedEditingRange` request. - - A request to provide ranges that can be edited together. - - @since 3.16.0 - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return self.protocol.send_request("textDocument/linkedEditingRange", params, callback) - - async def text_document_linked_editing_range_async( - self, - params: types.LinkedEditingRangeParams, - ) -> Optional[types.LinkedEditingRanges]: - """Make a :lsp:`textDocument/linkedEditingRange` request. - - A request to provide ranges that can be edited together. - - @since 3.16.0 - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return await self.protocol.send_request_async("textDocument/linkedEditingRange", params) - - def text_document_moniker( - self, - params: types.MonikerParams, - callback: Optional[Callable[[Optional[List[types.Moniker]]], None]] = None, - ) -> Future: - """Make a :lsp:`textDocument/moniker` request. - - A request to get the moniker of a symbol at a given text document position. - The request parameter is of type {@link TextDocumentPositionParams}. - The response is of type {@link Moniker Moniker[]} or `null`. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return self.protocol.send_request("textDocument/moniker", params, callback) - - async def text_document_moniker_async( - self, - params: types.MonikerParams, - ) -> Optional[List[types.Moniker]]: - """Make a :lsp:`textDocument/moniker` request. - - A request to get the moniker of a symbol at a given text document position. - The request parameter is of type {@link TextDocumentPositionParams}. - The response is of type {@link Moniker Moniker[]} or `null`. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return await self.protocol.send_request_async("textDocument/moniker", params) - - def text_document_on_type_formatting( - self, - params: types.DocumentOnTypeFormattingParams, - callback: Optional[Callable[[Optional[List[types.TextEdit]]], None]] = None, - ) -> Future: - """Make a :lsp:`textDocument/onTypeFormatting` request. - - A request to format a document on type. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return self.protocol.send_request("textDocument/onTypeFormatting", params, callback) - - async def text_document_on_type_formatting_async( - self, - params: types.DocumentOnTypeFormattingParams, - ) -> Optional[List[types.TextEdit]]: - """Make a :lsp:`textDocument/onTypeFormatting` request. - - A request to format a document on type. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return await self.protocol.send_request_async("textDocument/onTypeFormatting", params) - - def text_document_prepare_call_hierarchy( - self, - params: types.CallHierarchyPrepareParams, - callback: Optional[Callable[[Optional[List[types.CallHierarchyItem]]], None]] = None, - ) -> Future: - """Make a :lsp:`textDocument/prepareCallHierarchy` request. - - A request to result a `CallHierarchyItem` in a document at a given position. - Can be used as an input to an incoming or outgoing call hierarchy. - - @since 3.16.0 - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return self.protocol.send_request("textDocument/prepareCallHierarchy", params, callback) - - async def text_document_prepare_call_hierarchy_async( - self, - params: types.CallHierarchyPrepareParams, - ) -> Optional[List[types.CallHierarchyItem]]: - """Make a :lsp:`textDocument/prepareCallHierarchy` request. - - A request to result a `CallHierarchyItem` in a document at a given position. - Can be used as an input to an incoming or outgoing call hierarchy. - - @since 3.16.0 - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return await self.protocol.send_request_async("textDocument/prepareCallHierarchy", params) - - def text_document_prepare_rename( - self, - params: types.PrepareRenameParams, - callback: Optional[Callable[[Union[types.Range, types.PrepareRenameResult_Type1, types.PrepareRenameResult_Type2, None]], None]] = None, - ) -> Future: - """Make a :lsp:`textDocument/prepareRename` request. - - A request to test and perform the setup necessary for a rename. - - @since 3.16 - support for default behavior - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return self.protocol.send_request("textDocument/prepareRename", params, callback) - - async def text_document_prepare_rename_async( - self, - params: types.PrepareRenameParams, - ) -> Union[types.Range, types.PrepareRenameResult_Type1, types.PrepareRenameResult_Type2, None]: - """Make a :lsp:`textDocument/prepareRename` request. - - A request to test and perform the setup necessary for a rename. - - @since 3.16 - support for default behavior - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return await self.protocol.send_request_async("textDocument/prepareRename", params) - - def text_document_prepare_type_hierarchy( - self, - params: types.TypeHierarchyPrepareParams, - callback: Optional[Callable[[Optional[List[types.TypeHierarchyItem]]], None]] = None, - ) -> Future: - """Make a :lsp:`textDocument/prepareTypeHierarchy` request. - - A request to result a `TypeHierarchyItem` in a document at a given position. - Can be used as an input to a subtypes or supertypes type hierarchy. - - @since 3.17.0 - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return self.protocol.send_request("textDocument/prepareTypeHierarchy", params, callback) - - async def text_document_prepare_type_hierarchy_async( - self, - params: types.TypeHierarchyPrepareParams, - ) -> Optional[List[types.TypeHierarchyItem]]: - """Make a :lsp:`textDocument/prepareTypeHierarchy` request. - - A request to result a `TypeHierarchyItem` in a document at a given position. - Can be used as an input to a subtypes or supertypes type hierarchy. - - @since 3.17.0 - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return await self.protocol.send_request_async("textDocument/prepareTypeHierarchy", params) - - def text_document_ranges_formatting( - self, - params: types.DocumentRangesFormattingParams, - callback: Optional[Callable[[Optional[List[types.TextEdit]]], None]] = None, - ) -> Future: - """Make a :lsp:`textDocument/rangesFormatting` request. - - A request to format ranges in a document. - - @since 3.18.0 - @proposed - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return self.protocol.send_request("textDocument/rangesFormatting", params, callback) - - async def text_document_ranges_formatting_async( - self, - params: types.DocumentRangesFormattingParams, - ) -> Optional[List[types.TextEdit]]: - """Make a :lsp:`textDocument/rangesFormatting` request. - - A request to format ranges in a document. - - @since 3.18.0 - @proposed - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return await self.protocol.send_request_async("textDocument/rangesFormatting", params) - - def text_document_range_formatting( - self, - params: types.DocumentRangeFormattingParams, - callback: Optional[Callable[[Optional[List[types.TextEdit]]], None]] = None, - ) -> Future: - """Make a :lsp:`textDocument/rangeFormatting` request. - - A request to format a range in a document. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return self.protocol.send_request("textDocument/rangeFormatting", params, callback) - - async def text_document_range_formatting_async( - self, - params: types.DocumentRangeFormattingParams, - ) -> Optional[List[types.TextEdit]]: - """Make a :lsp:`textDocument/rangeFormatting` request. - - A request to format a range in a document. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return await self.protocol.send_request_async("textDocument/rangeFormatting", params) - - def text_document_references( - self, - params: types.ReferenceParams, - callback: Optional[Callable[[Optional[List[types.Location]]], None]] = None, - ) -> Future: - """Make a :lsp:`textDocument/references` request. - - A request to resolve project-wide references for the symbol denoted - by the given text document position. The request's parameter is of - type {@link ReferenceParams} the response is of type - {@link Location Location[]} or a Thenable that resolves to such. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return self.protocol.send_request("textDocument/references", params, callback) - - async def text_document_references_async( - self, - params: types.ReferenceParams, - ) -> Optional[List[types.Location]]: - """Make a :lsp:`textDocument/references` request. - - A request to resolve project-wide references for the symbol denoted - by the given text document position. The request's parameter is of - type {@link ReferenceParams} the response is of type - {@link Location Location[]} or a Thenable that resolves to such. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return await self.protocol.send_request_async("textDocument/references", params) - - def text_document_rename( - self, - params: types.RenameParams, - callback: Optional[Callable[[Optional[types.WorkspaceEdit]], None]] = None, - ) -> Future: - """Make a :lsp:`textDocument/rename` request. - - A request to rename a symbol. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return self.protocol.send_request("textDocument/rename", params, callback) - - async def text_document_rename_async( - self, - params: types.RenameParams, - ) -> Optional[types.WorkspaceEdit]: - """Make a :lsp:`textDocument/rename` request. - - A request to rename a symbol. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return await self.protocol.send_request_async("textDocument/rename", params) - - def text_document_selection_range( - self, - params: types.SelectionRangeParams, - callback: Optional[Callable[[Optional[List[types.SelectionRange]]], None]] = None, - ) -> Future: - """Make a :lsp:`textDocument/selectionRange` request. - - A request to provide selection ranges in a document. The request's - parameter is of type {@link SelectionRangeParams}, the - response is of type {@link SelectionRange SelectionRange[]} or a Thenable - that resolves to such. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return self.protocol.send_request("textDocument/selectionRange", params, callback) - - async def text_document_selection_range_async( - self, - params: types.SelectionRangeParams, - ) -> Optional[List[types.SelectionRange]]: - """Make a :lsp:`textDocument/selectionRange` request. - - A request to provide selection ranges in a document. The request's - parameter is of type {@link SelectionRangeParams}, the - response is of type {@link SelectionRange SelectionRange[]} or a Thenable - that resolves to such. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return await self.protocol.send_request_async("textDocument/selectionRange", params) - - def text_document_semantic_tokens_full( - self, - params: types.SemanticTokensParams, - callback: Optional[Callable[[Optional[types.SemanticTokens]], None]] = None, - ) -> Future: - """Make a :lsp:`textDocument/semanticTokens/full` request. - - @since 3.16.0 - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return self.protocol.send_request("textDocument/semanticTokens/full", params, callback) - - async def text_document_semantic_tokens_full_async( - self, - params: types.SemanticTokensParams, - ) -> Optional[types.SemanticTokens]: - """Make a :lsp:`textDocument/semanticTokens/full` request. - - @since 3.16.0 - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return await self.protocol.send_request_async("textDocument/semanticTokens/full", params) - - def text_document_semantic_tokens_full_delta( - self, - params: types.SemanticTokensDeltaParams, - callback: Optional[Callable[[Union[types.SemanticTokens, types.SemanticTokensDelta, None]], None]] = None, - ) -> Future: - """Make a :lsp:`textDocument/semanticTokens/full/delta` request. - - @since 3.16.0 - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return self.protocol.send_request("textDocument/semanticTokens/full/delta", params, callback) - - async def text_document_semantic_tokens_full_delta_async( - self, - params: types.SemanticTokensDeltaParams, - ) -> Union[types.SemanticTokens, types.SemanticTokensDelta, None]: - """Make a :lsp:`textDocument/semanticTokens/full/delta` request. - - @since 3.16.0 - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return await self.protocol.send_request_async("textDocument/semanticTokens/full/delta", params) - - def text_document_semantic_tokens_range( - self, - params: types.SemanticTokensRangeParams, - callback: Optional[Callable[[Optional[types.SemanticTokens]], None]] = None, - ) -> Future: - """Make a :lsp:`textDocument/semanticTokens/range` request. - - @since 3.16.0 - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return self.protocol.send_request("textDocument/semanticTokens/range", params, callback) - - async def text_document_semantic_tokens_range_async( - self, - params: types.SemanticTokensRangeParams, - ) -> Optional[types.SemanticTokens]: - """Make a :lsp:`textDocument/semanticTokens/range` request. - - @since 3.16.0 - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return await self.protocol.send_request_async("textDocument/semanticTokens/range", params) - - def text_document_signature_help( - self, - params: types.SignatureHelpParams, - callback: Optional[Callable[[Optional[types.SignatureHelp]], None]] = None, - ) -> Future: - """Make a :lsp:`textDocument/signatureHelp` request. - - - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return self.protocol.send_request("textDocument/signatureHelp", params, callback) - - async def text_document_signature_help_async( - self, - params: types.SignatureHelpParams, - ) -> Optional[types.SignatureHelp]: - """Make a :lsp:`textDocument/signatureHelp` request. - - - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return await self.protocol.send_request_async("textDocument/signatureHelp", params) - - def text_document_type_definition( - self, - params: types.TypeDefinitionParams, - callback: Optional[Callable[[Union[types.Location, List[types.Location], List[types.LocationLink], None]], None]] = None, - ) -> Future: - """Make a :lsp:`textDocument/typeDefinition` request. - - A request to resolve the type definition locations of a symbol at a given text - document position. The request's parameter is of type {@link TextDocumentPositionParams} - the response is of type {@link Definition} or a Thenable that resolves to such. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return self.protocol.send_request("textDocument/typeDefinition", params, callback) - - async def text_document_type_definition_async( - self, - params: types.TypeDefinitionParams, - ) -> Union[types.Location, List[types.Location], List[types.LocationLink], None]: - """Make a :lsp:`textDocument/typeDefinition` request. - - A request to resolve the type definition locations of a symbol at a given text - document position. The request's parameter is of type {@link TextDocumentPositionParams} - the response is of type {@link Definition} or a Thenable that resolves to such. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return await self.protocol.send_request_async("textDocument/typeDefinition", params) - - def text_document_will_save_wait_until( - self, - params: types.WillSaveTextDocumentParams, - callback: Optional[Callable[[Optional[List[types.TextEdit]]], None]] = None, - ) -> Future: - """Make a :lsp:`textDocument/willSaveWaitUntil` request. - - A document will save request is sent from the client to the server before - the document is actually saved. The request can return an array of TextEdits - which will be applied to the text document before it is saved. Please note that - clients might drop results if computing the text edits took too long or if a - server constantly fails on this request. This is done to keep the save fast and - reliable. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return self.protocol.send_request("textDocument/willSaveWaitUntil", params, callback) - - async def text_document_will_save_wait_until_async( - self, - params: types.WillSaveTextDocumentParams, - ) -> Optional[List[types.TextEdit]]: - """Make a :lsp:`textDocument/willSaveWaitUntil` request. - - A document will save request is sent from the client to the server before - the document is actually saved. The request can return an array of TextEdits - which will be applied to the text document before it is saved. Please note that - clients might drop results if computing the text edits took too long or if a - server constantly fails on this request. This is done to keep the save fast and - reliable. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return await self.protocol.send_request_async("textDocument/willSaveWaitUntil", params) - - def type_hierarchy_subtypes( - self, - params: types.TypeHierarchySubtypesParams, - callback: Optional[Callable[[Optional[List[types.TypeHierarchyItem]]], None]] = None, - ) -> Future: - """Make a :lsp:`typeHierarchy/subtypes` request. - - A request to resolve the subtypes for a given `TypeHierarchyItem`. - - @since 3.17.0 - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return self.protocol.send_request("typeHierarchy/subtypes", params, callback) - - async def type_hierarchy_subtypes_async( - self, - params: types.TypeHierarchySubtypesParams, - ) -> Optional[List[types.TypeHierarchyItem]]: - """Make a :lsp:`typeHierarchy/subtypes` request. - - A request to resolve the subtypes for a given `TypeHierarchyItem`. - - @since 3.17.0 - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return await self.protocol.send_request_async("typeHierarchy/subtypes", params) - - def type_hierarchy_supertypes( - self, - params: types.TypeHierarchySupertypesParams, - callback: Optional[Callable[[Optional[List[types.TypeHierarchyItem]]], None]] = None, - ) -> Future: - """Make a :lsp:`typeHierarchy/supertypes` request. - - A request to resolve the supertypes for a given `TypeHierarchyItem`. - - @since 3.17.0 - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return self.protocol.send_request("typeHierarchy/supertypes", params, callback) - - async def type_hierarchy_supertypes_async( - self, - params: types.TypeHierarchySupertypesParams, - ) -> Optional[List[types.TypeHierarchyItem]]: - """Make a :lsp:`typeHierarchy/supertypes` request. - - A request to resolve the supertypes for a given `TypeHierarchyItem`. - - @since 3.17.0 - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return await self.protocol.send_request_async("typeHierarchy/supertypes", params) - - def workspace_diagnostic( - self, - params: types.WorkspaceDiagnosticParams, - callback: Optional[Callable[[types.WorkspaceDiagnosticReport], None]] = None, - ) -> Future: - """Make a :lsp:`workspace/diagnostic` request. - - The workspace diagnostic request definition. - - @since 3.17.0 - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return self.protocol.send_request("workspace/diagnostic", params, callback) - - async def workspace_diagnostic_async( - self, - params: types.WorkspaceDiagnosticParams, - ) -> types.WorkspaceDiagnosticReport: - """Make a :lsp:`workspace/diagnostic` request. - - The workspace diagnostic request definition. - - @since 3.17.0 - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return await self.protocol.send_request_async("workspace/diagnostic", params) - - def workspace_execute_command( - self, - params: types.ExecuteCommandParams, - callback: Optional[Callable[[Optional[Any]], None]] = None, - ) -> Future: - """Make a :lsp:`workspace/executeCommand` request. - - A request send from the client to the server to execute a command. The request might return - a workspace edit which the client will apply to the workspace. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return self.protocol.send_request("workspace/executeCommand", params, callback) - - async def workspace_execute_command_async( - self, - params: types.ExecuteCommandParams, - ) -> 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 - a workspace edit which the client will apply to the workspace. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return await self.protocol.send_request_async("workspace/executeCommand", params) - - def workspace_symbol( - self, - params: types.WorkspaceSymbolParams, - callback: Optional[Callable[[Union[List[types.SymbolInformation], List[types.WorkspaceSymbol], None]], None]] = None, - ) -> Future: - """Make a :lsp:`workspace/symbol` request. - - A request to list project-wide symbols matching the query string given - by the {@link WorkspaceSymbolParams}. The response is - of type {@link SymbolInformation SymbolInformation[]} or a Thenable that - resolves to such. - - @since 3.17.0 - support for WorkspaceSymbol in the returned data. Clients - need to advertise support for WorkspaceSymbols via the client capability - `workspace.symbol.resolveSupport`. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return self.protocol.send_request("workspace/symbol", params, callback) - - async def workspace_symbol_async( - self, - params: types.WorkspaceSymbolParams, - ) -> Union[List[types.SymbolInformation], List[types.WorkspaceSymbol], None]: - """Make a :lsp:`workspace/symbol` request. - - A request to list project-wide symbols matching the query string given - by the {@link WorkspaceSymbolParams}. The response is - of type {@link SymbolInformation SymbolInformation[]} or a Thenable that - resolves to such. - - @since 3.17.0 - support for WorkspaceSymbol in the returned data. Clients - need to advertise support for WorkspaceSymbols via the client capability - `workspace.symbol.resolveSupport`. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return await self.protocol.send_request_async("workspace/symbol", params) - - def workspace_symbol_resolve( - self, - params: types.WorkspaceSymbol, - callback: Optional[Callable[[types.WorkspaceSymbol], None]] = None, - ) -> Future: - """Make a :lsp:`workspaceSymbol/resolve` request. - - A request to resolve the range inside the workspace - symbol's location. - - @since 3.17.0 - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return self.protocol.send_request("workspaceSymbol/resolve", params, callback) - - async def workspace_symbol_resolve_async( - self, - params: types.WorkspaceSymbol, - ) -> types.WorkspaceSymbol: - """Make a :lsp:`workspaceSymbol/resolve` request. - - A request to resolve the range inside the workspace - symbol's location. - - @since 3.17.0 - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return await self.protocol.send_request_async("workspaceSymbol/resolve", params) - - def workspace_will_create_files( - self, - params: types.CreateFilesParams, - callback: Optional[Callable[[Optional[types.WorkspaceEdit]], None]] = None, - ) -> Future: - """Make a :lsp:`workspace/willCreateFiles` request. - - The will create files request is sent from the client to the server before files are actually - created as long as the creation is triggered from within the client. - - The request can return a `WorkspaceEdit` which will be applied to workspace before the - files are created. Hence the `WorkspaceEdit` can not manipulate the content of the file - to be created. - - @since 3.16.0 - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return self.protocol.send_request("workspace/willCreateFiles", params, callback) - - async def workspace_will_create_files_async( - self, - params: types.CreateFilesParams, - ) -> 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 - created as long as the creation is triggered from within the client. - - The request can return a `WorkspaceEdit` which will be applied to workspace before the - files are created. Hence the `WorkspaceEdit` can not manipulate the content of the file - to be created. - - @since 3.16.0 - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return await self.protocol.send_request_async("workspace/willCreateFiles", params) - - def workspace_will_delete_files( - self, - params: types.DeleteFilesParams, - callback: Optional[Callable[[Optional[types.WorkspaceEdit]], None]] = None, - ) -> Future: - """Make a :lsp:`workspace/willDeleteFiles` request. - - The did delete files notification is sent from the client to the server when - files were deleted from within the client. - - @since 3.16.0 - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return self.protocol.send_request("workspace/willDeleteFiles", params, callback) - - async def workspace_will_delete_files_async( - self, - params: types.DeleteFilesParams, - ) -> Optional[types.WorkspaceEdit]: - """Make a :lsp:`workspace/willDeleteFiles` request. - - The did delete files notification is sent from the client to the server when - files were deleted from within the client. - - @since 3.16.0 - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return await self.protocol.send_request_async("workspace/willDeleteFiles", params) - - def workspace_will_rename_files( - self, - params: types.RenameFilesParams, - callback: Optional[Callable[[Optional[types.WorkspaceEdit]], None]] = None, - ) -> Future: - """Make a :lsp:`workspace/willRenameFiles` request. - - The will rename files request is sent from the client to the server before files are actually - renamed as long as the rename is triggered from within the client. - - @since 3.16.0 - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return self.protocol.send_request("workspace/willRenameFiles", params, callback) - - async def workspace_will_rename_files_async( - self, - params: types.RenameFilesParams, - ) -> 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 - renamed as long as the rename is triggered from within the client. - - @since 3.16.0 - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - return await self.protocol.send_request_async("workspace/willRenameFiles", params) - - def cancel_request(self, params: types.CancelParams) -> None: - """Send a :lsp:`$/cancelRequest` notification. - - - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - self.protocol.notify("$/cancelRequest", params) - - def exit(self, params: None) -> None: - """Send a :lsp:`exit` notification. - - The exit event is sent from the client to the server to - ask the server to exit its process. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - self.protocol.notify("exit", params) - - def initialized(self, params: types.InitializedParams) -> None: - """Send a :lsp:`initialized` notification. - - The initialized notification is sent from the client to the - server after the client is fully initialized and the server - is allowed to send requests from the server to the client. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - self.protocol.notify("initialized", params) - - def notebook_document_did_change(self, params: types.DidChangeNotebookDocumentParams) -> None: - """Send a :lsp:`notebookDocument/didChange` notification. - - - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - self.protocol.notify("notebookDocument/didChange", params) - - def notebook_document_did_close(self, params: types.DidCloseNotebookDocumentParams) -> None: - """Send a :lsp:`notebookDocument/didClose` notification. - - A notification sent when a notebook closes. - - @since 3.17.0 - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - self.protocol.notify("notebookDocument/didClose", params) - - def notebook_document_did_open(self, params: types.DidOpenNotebookDocumentParams) -> None: - """Send a :lsp:`notebookDocument/didOpen` notification. - - A notification sent when a notebook opens. - - @since 3.17.0 - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - self.protocol.notify("notebookDocument/didOpen", params) - - def notebook_document_did_save(self, params: types.DidSaveNotebookDocumentParams) -> None: - """Send a :lsp:`notebookDocument/didSave` notification. - - A notification sent when a notebook document is saved. - - @since 3.17.0 - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - self.protocol.notify("notebookDocument/didSave", params) - - def progress(self, params: types.ProgressParams) -> None: - """Send a :lsp:`$/progress` notification. - - - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - self.protocol.notify("$/progress", params) - - def set_trace(self, params: types.SetTraceParams) -> None: - """Send a :lsp:`$/setTrace` notification. - - - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - self.protocol.notify("$/setTrace", params) - - def text_document_did_change(self, params: types.DidChangeTextDocumentParams) -> None: - """Send a :lsp:`textDocument/didChange` notification. - - The document change notification is sent from the client to the server to signal - changes to a text document. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - self.protocol.notify("textDocument/didChange", params) - - def text_document_did_close(self, params: types.DidCloseTextDocumentParams) -> None: - """Send a :lsp:`textDocument/didClose` notification. - - The document close notification is sent from the client to the server when - the document got closed in the client. The document's truth now exists where - the document's uri points to (e.g. if the document's uri is a file uri the - truth now exists on disk). As with the open notification the close notification - is about managing the document's content. Receiving a close notification - doesn't mean that the document was open in an editor before. A close - notification requires a previous open notification to be sent. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - self.protocol.notify("textDocument/didClose", params) - - def text_document_did_open(self, params: types.DidOpenTextDocumentParams) -> None: - """Send a :lsp:`textDocument/didOpen` notification. - - The document open notification is sent from the client to the server to signal - newly opened text documents. The document's truth is now managed by the client - and the server must not try to read the document's truth using the document's - uri. Open in this sense means it is managed by the client. It doesn't necessarily - mean that its content is presented in an editor. An open notification must not - be sent more than once without a corresponding close notification send before. - This means open and close notification must be balanced and the max open count - is one. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - self.protocol.notify("textDocument/didOpen", params) - - def text_document_did_save(self, params: types.DidSaveTextDocumentParams) -> None: - """Send a :lsp:`textDocument/didSave` notification. - - The document save notification is sent from the client to the server when - the document got saved in the client. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - self.protocol.notify("textDocument/didSave", params) - - def text_document_will_save(self, params: types.WillSaveTextDocumentParams) -> None: - """Send a :lsp:`textDocument/willSave` notification. - - A document will save notification is sent from the client to the server before - the document is actually saved. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - self.protocol.notify("textDocument/willSave", params) - - def window_work_done_progress_cancel(self, params: types.WorkDoneProgressCancelParams) -> None: - """Send a :lsp:`window/workDoneProgress/cancel` notification. - - The `window/workDoneProgress/cancel` notification is sent from the client to the server to cancel a progress - initiated on the server side. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - self.protocol.notify("window/workDoneProgress/cancel", params) - - def workspace_did_change_configuration(self, params: types.DidChangeConfigurationParams) -> None: - """Send a :lsp:`workspace/didChangeConfiguration` notification. - - The configuration change notification is sent from the client to the server - when the client's configuration has changed. The notification contains - the changed configuration as defined by the language client. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - self.protocol.notify("workspace/didChangeConfiguration", params) - - def workspace_did_change_watched_files(self, params: types.DidChangeWatchedFilesParams) -> None: - """Send a :lsp:`workspace/didChangeWatchedFiles` notification. - - The watched files notification is sent from the client to the server when - the client detects changes to file watched by the language client. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - self.protocol.notify("workspace/didChangeWatchedFiles", params) - - def workspace_did_change_workspace_folders(self, params: types.DidChangeWorkspaceFoldersParams) -> None: - """Send a :lsp:`workspace/didChangeWorkspaceFolders` notification. - - The `workspace/didChangeWorkspaceFolders` notification is sent from the client to the server when the workspace - folder configuration changes. - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - self.protocol.notify("workspace/didChangeWorkspaceFolders", params) - - def workspace_did_create_files(self, params: types.CreateFilesParams) -> None: - """Send a :lsp:`workspace/didCreateFiles` notification. - - The did create files notification is sent from the client to the server when - files were created from within the client. - - @since 3.16.0 - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - self.protocol.notify("workspace/didCreateFiles", params) - - def workspace_did_delete_files(self, params: types.DeleteFilesParams) -> None: - """Send a :lsp:`workspace/didDeleteFiles` notification. - - The will delete files request is sent from the client to the server before files are actually - deleted as long as the deletion is triggered from within the client. - - @since 3.16.0 - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - self.protocol.notify("workspace/didDeleteFiles", params) - - def workspace_did_rename_files(self, params: types.RenameFilesParams) -> None: - """Send a :lsp:`workspace/didRenameFiles` notification. - - The did rename files notification is sent from the client to the server when - files were renamed from within the client. - - @since 3.16.0 - """ - if self.stopped: - raise RuntimeError("Client has been stopped.") - - self.protocol.notify("workspace/didRenameFiles", params) +# Placeholder for when we add a real client +class LanguageClient(BaseLanguageClient): + """Language client.""" diff --git a/server/libs/pygls/lsp/server.py b/server/libs/pygls/lsp/server.py new file mode 100644 index 0000000..30692fb --- /dev/null +++ b/server/libs/pygls/lsp/server.py @@ -0,0 +1,126 @@ +from __future__ import annotations + +import typing + +from lsprotocol import types + +from pygls.exceptions import FeatureRequestError + +from ._base_server import BaseLanguageServer + +if typing.TYPE_CHECKING: + from typing import Callable + from typing import TypeVar + + from pygls.server import ServerErrors + from pygls.progress import Progress + from pygls.workspace import Workspace + + F = TypeVar("F", bound=Callable) + + +class LanguageServer(BaseLanguageServer): + """The default LanguageServer + + This class can be extended and it can be passed as a first argument to + registered commands/features. + + .. |ServerInfo| replace:: :class:`~lsprotocol.types.ServerInfo` + + Parameters + ---------- + name + Name of the server, used to populate |ServerInfo| which is sent to + the client during initialization + + version + Version of the server, used to populate |ServerInfo| which is sent to + the client during initialization + + protocol_cls + The :class:`~pygls.protocol.LanguageServerProtocol` class definition, or any + subclass of it. + + max_workers + Maximum number of workers for ``ThreadPool`` and ``ThreadPoolExecutor`` + + text_document_sync_kind + Text document synchronization method + + None + No synchronization + + :attr:`~lsprotocol.types.TextDocumentSyncKind.Full` + Send entire document text with each update + + :attr:`~lsprotocol.types.TextDocumentSyncKind.Incremental` + Send only the region of text that changed with each update + + notebook_document_sync + Advertise :lsp:`NotebookDocument` support to the client. + """ + + def __init__( + self, + name: str, + version: str, + text_document_sync_kind: types.TextDocumentSyncKind = types.TextDocumentSyncKind.Incremental, + notebook_document_sync: types.NotebookDocumentSyncOptions | None = None, + *args, + **kwargs, + ): + self.name = name + self.version = version + self._text_document_sync_kind = text_document_sync_kind + self._notebook_document_sync = notebook_document_sync + self.process_id: int | None = None + super().__init__(*args, **kwargs) + + @property + def client_capabilities(self) -> types.ClientCapabilities: + """The client's capabilities.""" + return self.protocol.client_capabilities + + @property + def server_capabilities(self) -> types.ServerCapabilities: + """The server's capabilities.""" + return self.protocol.server_capabilities + + @property + def workspace(self) -> Workspace: + """Returns in-memory workspace.""" + return self.protocol.workspace + + @property + def work_done_progress(self) -> Progress: + """Gets the object to manage client's progress bar.""" + return self.protocol.progress + + def report_server_error(self, error: Exception, source: ServerErrors): + """ + Sends error to the client for displaying. + + By default this function does not handle LSP request errors. This is because LSP requests + require direct responses and so already have a mechanism for including unexpected errors + in the response body. + + All other errors are "out of band" in the sense that the client isn't explicitly waiting + for them. For example diagnostics are returned as notifications, not responses to requests, + and so can seemingly be sent at random. Also for example consider JSON RPC serialization + and deserialization, if a payload cannot be parsed then the whole request/response cycle + cannot be completed and so one of these "out of band" error messages is sent. + + These "out of band" error messages are not a requirement of the LSP spec. Pygls simply + offers this behaviour as a recommended default. It is perfectly reasonble to override this + default. + """ + + if source == FeatureRequestError: + return + + self.window_show_message( + types.ShowMessageParams( + message=f"Error in server: {error}", + type=types.MessageType.Error, + ) + ) diff --git a/server/libs/pygls/protocol/__init__.py b/server/libs/pygls/protocol/__init__.py index 1a30b48..6c61e87 100644 --- a/server/libs/pygls/protocol/__init__.py +++ b/server/libs/pygls/protocol/__init__.py @@ -1,7 +1,6 @@ import json -from typing import Any - from collections import namedtuple +from typing import Any from lsprotocol import converters @@ -12,7 +11,6 @@ from pygls.protocol.json_rpc import ( JsonRPCResponseMessage, ) from pygls.protocol.language_server import LanguageServerProtocol, lsp_method -from pygls.protocol.lsp_meta import LSPMeta, call_user_feature def _dict_to_object(d: Any): @@ -68,8 +66,6 @@ __all__ = ( "JsonRPCRequestMessage", "JsonRPCResponseMessage", "JsonRPCNotification", - "LSPMeta", - "call_user_feature", "_dict_to_object", "_params_field_structure_hook", "_result_field_structure_hook", diff --git a/server/libs/pygls/protocol/json_rpc.py b/server/libs/pygls/protocol/json_rpc.py index 75a4b34..97fd6e9 100644 --- a/server/libs/pygls/protocol/json_rpc.py +++ b/server/libs/pygls/protocol/json_rpc.py @@ -15,54 +15,90 @@ # limitations under the License. # ############################################################################ from __future__ import annotations + import asyncio +import contextvars import enum +import inspect import json import logging -import re import sys -import uuid import traceback +import typing +import uuid from concurrent.futures import Future from functools import partial -from typing import ( - Any, - Dict, - List, - Optional, - Type, - Union, - TYPE_CHECKING, -) - -if TYPE_CHECKING: - from pygls.server import LanguageServer, WebSocketTransportAdapter - +from typing import Any, Callable, Protocol, Type, Union, runtime_checkable import attrs from cattrs.errors import ClassValidationError - from lsprotocol.types import ( CANCEL_REQUEST, EXIT, - WORKSPACE_EXECUTE_COMMAND, ResponseError, ResponseErrorMessage, ) from pygls.exceptions import ( + FeatureNotificationError, + FeatureRequestError, JsonRpcException, JsonRpcInternalError, JsonRpcInvalidParams, JsonRpcMethodNotFound, JsonRpcRequestCancelled, - FeatureNotificationError, - FeatureRequestError, ) from pygls.feature_manager import FeatureManager, is_thread_function +if typing.TYPE_CHECKING: + from collections.abc import Generator + + from cattrs import Converter + + from pygls.io_ import AsyncWriter, Writer + from pygls.server import JsonRPCServer + + MessageHandler = Union[Callable[[Any], Any],] + MessageCallback = Callable[[Future[Any]], None] + logger = logging.getLogger(__name__) +# cattrs needs access to this type definition so we cannot include it in the +# TYPE_CHECKING block above +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: @@ -81,7 +117,7 @@ class JsonRPCRequestMessage: Used as a fallback for unknown types. """ - id: Union[int, str] + id: MsgId method: str jsonrpc: str params: Any @@ -93,13 +129,13 @@ class JsonRPCResponseMessage: Used as a fallback for unknown types. """ - id: Union[int, str] + id: MsgId jsonrpc: str result: Any -class JsonRPCProtocol(asyncio.Protocol): - """Json RPC protocol implementation using on top of `asyncio.Protocol`. +class JsonRPCProtocol: + """Json RPC protocol implementation Specification of the protocol can be found here: https://www.jsonrpc.org/specification @@ -109,86 +145,156 @@ class JsonRPCProtocol(asyncio.Protocol): CHARSET = "utf-8" CONTENT_TYPE = "application/vscode-jsonrpc" - - MESSAGE_PATTERN = re.compile( - rb"^(?:[^\r\n]+\r\n)*" - + rb"Content-Length: (?P\d+)\r\n" - + rb"(?:[^\r\n]+\r\n)*\r\n" - + rb"(?P{.*)", - re.DOTALL, - ) - VERSION = "2.0" - def __init__(self, server: LanguageServer, converter): + def __init__(self, server: JsonRPCServer, converter: Converter): self._server = server self._converter = converter self._shutdown = False # Book keeping for in-flight requests - self._request_futures: Dict[str, Future[Any]] = {} - self._result_types: Dict[str, Any] = {} + self._ctx_msg_id: contextvars.ContextVar[MsgId | None] = contextvars.ContextVar( + "msg_id", default=None + ) + self._request_futures: dict[MsgId, Future[Any]] = {} + self._result_types: dict[MsgId, Any] = {} self.fm = FeatureManager(server, converter) - self.transport: Optional[ - Union[asyncio.WriteTransport, WebSocketTransportAdapter] - ] = None - self._message_buf: List[bytes] = [] - - self._send_only_body = False + self.writer: AsyncWriter | Writer | None = None + self._include_headers = False def __call__(self): return self - def _execute_notification(self, handler, *params): - """Executes notification message handler.""" - if asyncio.iscoroutinefunction(handler): - future = asyncio.ensure_future(handler(*params)) - future.add_done_callback(self._execute_notification_callback) - else: - if is_thread_function(handler): - self._server.thread_pool.apply_async(handler, (*params,)) - else: - handler(*params) + @property + def msg_id(self) -> MsgId | None: + """Returns the id of the current context (if it exists).""" + ctx = contextvars.copy_context() + return ctx.get(self._ctx_msg_id) - def _execute_notification_callback(self, future): - """Success callback used for coroutine notification message.""" - if future.exception(): - try: - raise future.exception() - except Exception: - error = JsonRpcInternalError.of(sys.exc_info()) - logger.exception('Exception occurred in notification: "%s"', error) + def _execute_handler( + self, + msg_id: MsgId, + handler: MessageHandler, + callback: MessageCallback, + args: tuple[Any, ...] | None = None, + kwargs: dict[str, Any] | None = None, + ): + """Execute the given message handler. - # Revisit. Client does not support response with msg_id = None - # https://stackoverflow.com/questions/31091376/json-rpc-2-0-allow-notifications-to-have-an-error-response - # self._send_response(None, error=error) + Parameters + ---------- + msg_id + The id of the message being handled - def _execute_request(self, msg_id, handler, params): - """Executes request message handler.""" + handler + The request handler to call + + callback + An optional callback function to call upon completion of the handler + + args + Positional arguments to pass to the handler + + kwargs + Keyword arguments to pass to the handler + """ + future: Future[Any] + args = args or tuple() + kwargs = kwargs or {} if asyncio.iscoroutinefunction(handler): - future = asyncio.ensure_future(handler(params)) + future = asyncio.ensure_future(handler(*args, **kwargs)) self._request_futures[msg_id] = future - future.add_done_callback(partial(self._execute_request_callback, msg_id)) + future.add_done_callback(callback) + + elif is_thread_function(handler): + future = self._server.thread_pool.submit(handler, *args, **kwargs) + self._request_futures[msg_id] = future + future.add_done_callback(callback) + + elif inspect.isgeneratorfunction(handler): + future = Future() + self._request_futures[msg_id] = future + future.add_done_callback(callback) + + try: + self._run_generator( + future=None, gen=handler(*args, **kwargs), result_future=future + ) + except Exception as exc: + future.set_exception(exc) + else: - # Can't be canceled - if is_thread_function(handler): - self._server.thread_pool.apply_async( - handler, - (params,), - callback=partial( - self._send_response, - msg_id, - ), - error_callback=partial(self._execute_request_err_callback, msg_id), - ) - else: - self._send_response(msg_id, handler(params)) + # While a future is not necessary for a synchronous function, it allows us to use a single + # pattern across all handler types + future = Future() + future.add_done_callback(callback) + + try: + result = handler(*args, **kwargs) + future.set_result(result) + except Exception as exc: + future.set_exception(exc) + + def _run_generator( + self, + future: Future[Any] | None, + *, + gen: Generator[Any, Any, Any], + result_future: Future[Any], + ): + """Run the next portion of the given generator. + + Generator handlers are designed to ``yield`` to other handlers that are executed + separately before their results are sent back into the generator allowing + execution to continue. + + Generator handlers are primarily used in the implementation of pygls' builtin + feature handlers. + + Parameters + ---------- + future + The future that contains the result of the previously executed handler, if any + + gen + The generator to run + + result_future + The future to send the final result to once the generator stops. + """ + + if result_future.cancelled(): + return + + try: + value = future.result() if future is not None else None + handler, args, kwargs = gen.send(value) + + self._execute_handler( + str(uuid.uuid4()), + handler, + args=args, + kwargs=kwargs, + callback=partial( + self._run_generator, gen=gen, result_future=result_future + ), + ) + except StopIteration as result: + result_future.set_result(result.value) + + except Exception as exc: + result_future.set_exception(exc) + + 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. + """ + self._request_futures.pop(msg_id, None) - def _execute_request_callback(self, msg_id, future): - """Success callback used for coroutine request message.""" try: if not future.cancelled(): self._send_response(msg_id, result=future.result()) @@ -199,30 +305,41 @@ class JsonRPCProtocol(asyncio.Protocol): f'Request with id "{msg_id}" is canceled' ).to_response_error(), ) - self._request_futures.pop(msg_id, None) + except JsonRpcException as exc: + logger.exception('Exception occurred for message "%s"', msg_id) + self._send_response(msg_id, error=exc.to_response_error()) + self._server._report_server_error(exc, FeatureRequestError) + except Exception: error = JsonRpcInternalError.of(sys.exc_info()) - logger.exception('Exception occurred for message "%s": %s', msg_id, error) + logger.exception('Exception occurred for message "%s"', msg_id) self._send_response(msg_id, error=error.to_response_error()) + self._server._report_server_error(error, FeatureRequestError) - def _execute_request_err_callback(self, msg_id, exc): - """Error callback used for coroutine request message.""" - exc_info = (type(exc), exc, None) - error = JsonRpcInternalError.of(exc_info) - logger.exception('Exception occurred for message "%s": %s', msg_id, error) - self._send_response(msg_id, error=error.to_response_error()) + def _check_handler_result(self, future: Future[Any]): + """Check the result of the future to see if an error occurred. - def _get_handler(self, feature_name): - """Returns builtin or used defined feature by name if exists.""" - try: - return self.fm.builtin_features[feature_name] - except KeyError: + Used when handling notification messages + """ + if not future.cancelled() and (exc := future.exception()) is not None: try: - return self.fm.features[feature_name] - except KeyError: - raise JsonRpcMethodNotFound.of(feature_name) + raise exc + except Exception: + error = JsonRpcInternalError.of(sys.exc_info()) + self._server._report_server_error(error, FeatureNotificationError) - def _handle_cancel_notification(self, msg_id): + 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: + return handler + + if (handler := self.fm.features.get(feature_name)) is not None: + return handler + + raise JsonRpcMethodNotFound.of(feature_name) + + def _handle_cancel_notification(self, msg_id: MsgId): """Handles a cancel notification from the client.""" future = self._request_futures.pop(msg_id, None) @@ -234,7 +351,7 @@ class JsonRPCProtocol(asyncio.Protocol): if future.cancel(): logger.info('Cancelled request with id "%s"', msg_id) - def _handle_notification(self, method_name, params): + def _handle_notification(self, method_name: str, params: Any): """Handles a notification from the client.""" if method_name == CANCEL_REQUEST: self._handle_cancel_notification(params.id) @@ -242,29 +359,45 @@ class JsonRPCProtocol(asyncio.Protocol): try: handler = self._get_handler(method_name) - self._execute_notification(handler, params) - except (KeyError, JsonRpcMethodNotFound): - logger.warning('Ignoring notification for unknown method "%s"', method_name) + self._execute_handler( + msg_id=str(uuid.uuid4()), + handler=handler, + args=(params,), + callback=self._check_handler_result, + ) + except JsonRpcMethodNotFound: + logger.warning("Ignoring notification for unknown method %r", method_name) except Exception as error: logger.exception( - 'Failed to handle notification "%s": %s', + "Failed to handle notification %r: %s", method_name, params, exc_info=True, ) self._server._report_server_error(error, FeatureNotificationError) - def _handle_request(self, msg_id, method_name, params): + def _handle_request(self, msg_id: MsgId, method_name: str, params: Any): """Handles a request from the client.""" try: handler = self._get_handler(method_name) - # workspace/executeCommand is a special case - if method_name == WORKSPACE_EXECUTE_COMMAND: - handler(params, msg_id) - else: - self._execute_request(msg_id, handler, params) + # Set the request id within the current context. + self._ctx_msg_id.set(msg_id) + self._execute_handler( + msg_id=msg_id, + handler=handler, + args=(params,), + callback=partial(self._send_handler_result, msg_id=msg_id), + ) + except JsonRpcMethodNotFound as error: + logger.warning( + "Failed to handle request %r, unknown method %r", + msg_id, + method_name, + ) + self._send_response(msg_id, None, error.to_response_error()) + self._server._report_server_error(error, FeatureRequestError) except JsonRpcException as error: logger.exception( "Failed to handle request %s %s %s", @@ -287,7 +420,12 @@ class JsonRPCProtocol(asyncio.Protocol): 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) @@ -302,7 +440,7 @@ class JsonRPCProtocol(asyncio.Protocol): 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__"): @@ -313,7 +451,7 @@ class JsonRPCProtocol(asyncio.Protocol): return data.__dict__ - def _deserialize_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: @@ -330,7 +468,8 @@ class JsonRPCProtocol(asyncio.Protocol): 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) @@ -347,7 +486,7 @@ class JsonRPCProtocol(asyncio.Protocol): logger.error("Unable to deserialize message\n%s", traceback.format_exc()) raise JsonRpcInternalError() from exc - def _procedure_handler(self, message): + def handle_message(self, message: RPCMessage): """Delegates message to handlers depending on message type.""" if message.jsonrpc != JsonRPCProtocol.VERSION: @@ -358,27 +497,31 @@ class JsonRPCProtocol(asyncio.Protocol): logger.warning("Server shutting down. No more requests!") return - if hasattr(message, "method"): - if hasattr(message, "id"): - logger.debug("Request message received.") - self._handle_request(message.id, message.method, message.params) - else: - logger.debug("Notification message received.") - self._handle_notification(message.method, message.params) - else: - if hasattr(message, "error"): - logger.debug("Error message received.") - self._handle_response(message.id, None, message.error) - else: - logger.debug("Response message received.") - self._handle_response(message.id, message.result) + # Run each handler within its own context. + ctx = contextvars.copy_context() - def _send_data(self, data): + 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: + logger.debug("Error message received.") + ctx.run(self._handle_response, message.id, None, message.error) + + def _send_data(self, data: Any): """Sends data to the client.""" if not data: return - if self.transport is None: + if self.writer is None: logger.error("Unable to send data, no available transport!") return @@ -386,31 +529,49 @@ class JsonRPCProtocol(asyncio.Protocol): body = json.dumps(data, default=self._serialize_message) logger.info("Sending data: %s", body) - if self._send_only_body: - # Mypy/Pyright seem to think `write()` wants `"bytes | bytearray | memoryview"` - # But runtime errors with anything but `str`. - self.transport.write(body) # type: ignore - return + if self._include_headers: + header = ( + f"Content-Length: {len(body)}\r\n" + f"Content-Type: {self.CONTENT_TYPE}; charset={self.CHARSET}\r\n\r\n" + ) + data = header + body + else: + data = body - header = ( - f"Content-Length: {len(body)}\r\n" - f"Content-Type: {self.CONTENT_TYPE}; charset={self.CHARSET}\r\n\r\n" - ).encode(self.CHARSET) + res = self.writer.write(data.encode(self.CHARSET)) + if inspect.isawaitable(res): + asyncio.ensure_future(res) - self.transport.write(header + body.encode(self.CHARSET)) + except BrokenPipeError: + logger.exception("Error sending data. BrokenPipeError", exc_info=True) + raise except Exception as error: logger.exception("Error sending data", exc_info=True) 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 - Args: - msg_id(str): Id from request - result(any): Result returned by handler - error(any): Error returned by handler + .. 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 + + error + The error to send in the event of a failure """ if error is not None: @@ -424,70 +585,51 @@ class JsonRPCProtocol(asyncio.Protocol): self._send_data(response) - def connection_lost(self, exc): - """Method from base class, called when connection is lost, in which case we - want to shutdown the server's process as well. - """ - logger.error("Connection to the client is lost! Shutting down the server.") - sys.exit(1) - - def connection_made( # type: ignore # see: https://github.com/python/typeshed/issues/3021 + def set_writer( self, - transport: asyncio.Transport, + writer: AsyncWriter | Writer, + include_headers: bool = True, ): - """Method from base class, called when connection is established""" - self.transport = transport + """Set the writer object to use when sending data - def data_received(self, data: bytes): - try: - self._data_received(data) - except Exception as error: - logger.exception("Error receiving data", exc_info=True) - self._server._report_server_error(error, JsonRpcInternalError) + Parameters + ---------- + writer + The writer object - def _data_received(self, data: bytes): - """Method from base class, called when server receives the data""" - logger.debug("Received %r", data) + include_headers + Flag indicating if headers like ``Content-Length`` should be included when + sending data. (Default ``True``) + """ + self.writer = writer + self._include_headers = include_headers - while len(data): - # Append the incoming chunk to the message buffer - self._message_buf.append(data) - - # Look for the body of the message - message = b"".join(self._message_buf) - found = JsonRPCProtocol.MESSAGE_PATTERN.fullmatch(message) - - body = found.group("body") if found else b"" - length = int(found.group("length")) if found else 1 - - if len(body) < length: - # Message is incomplete; bail until more data arrives - return - - # Message is complete; - # extract the body and any remaining data, - # and reset the buffer for the next message - body, data = body[:length], body[length:] - self._message_buf = [] - - # Parse the body - self._procedure_handler( - json.loads( - body.decode(self.CHARSET), object_hook=self._deserialize_message - ) - ) - - def get_message_type(self, method: str) -> Optional[Type]: + def get_message_type(self, method: str) -> Type[Any] | None: """Return the type definition of the message associated with the given method.""" return None - def get_result_type(self, method: str) -> Optional[Type]: + 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 @@ -497,15 +639,35 @@ class JsonRPCProtocol(asyncio.Protocol): 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 - Args: - method(str): The method name of the message to send - params(any): The payload of the message + Parameters + ---------- + method + The method name of the message to send - Returns: - Future that will be resolved once a response has been received + params + 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[Any] + A future that will resolve once a response has been received """ if msg_id is None: @@ -521,12 +683,12 @@ class JsonRPCProtocol(asyncio.Protocol): 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) @@ -539,22 +701,35 @@ class JsonRPCProtocol(asyncio.Protocol): 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. - 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 + 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. - Returns: - `asyncio.Future` that can be awaited + 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 + + msg_id + Send the request using the given id, if ``None``, an id will be automatically + generated + + Returns + ------- + `asyncio.Future` that can be awaited """ return asyncio.wrap_future( self.send_request(method, params=params, msg_id=msg_id) ) - - def thread(self): - """Decorator that mark function to execute it in a thread.""" - return self.fm.thread() diff --git a/server/libs/pygls/protocol/language_server.py b/server/libs/pygls/protocol/language_server.py index 42b1319..0a92701 100644 --- a/server/libs/pygls/protocol/language_server.py +++ b/server/libs/pygls/protocol/language_server.py @@ -15,88 +15,34 @@ # limitations under the License. # ############################################################################ from __future__ import annotations + import asyncio +import inspect import json import logging import sys -from concurrent.futures import Future +import typing from functools import lru_cache from itertools import zip_longest -from typing import ( - Callable, - List, - Optional, - Type, - TypeVar, - Union, -) +from lsprotocol import types from pygls.capabilities import ServerCapabilitiesBuilder -from pygls.lsp import ConfigCallbackType, ShowDocumentCallbackType -from lsprotocol.types import ( - CLIENT_REGISTER_CAPABILITY, - CLIENT_UNREGISTER_CAPABILITY, - EXIT, - INITIALIZE, - INITIALIZED, - METHOD_TO_TYPES, - NOTEBOOK_DOCUMENT_DID_CHANGE, - NOTEBOOK_DOCUMENT_DID_CLOSE, - NOTEBOOK_DOCUMENT_DID_OPEN, - LOG_TRACE, - SET_TRACE, - SHUTDOWN, - TEXT_DOCUMENT_DID_CHANGE, - TEXT_DOCUMENT_DID_CLOSE, - TEXT_DOCUMENT_DID_OPEN, - TEXT_DOCUMENT_PUBLISH_DIAGNOSTICS, - WINDOW_LOG_MESSAGE, - WINDOW_SHOW_DOCUMENT, - WINDOW_SHOW_MESSAGE, - WINDOW_WORK_DONE_PROGRESS_CANCEL, - WORKSPACE_APPLY_EDIT, - WORKSPACE_CONFIGURATION, - WORKSPACE_DID_CHANGE_WORKSPACE_FOLDERS, - WORKSPACE_EXECUTE_COMMAND, - WORKSPACE_SEMANTIC_TOKENS_REFRESH, -) -from lsprotocol.types import ( - ApplyWorkspaceEditParams, - Diagnostic, - DidChangeNotebookDocumentParams, - DidChangeTextDocumentParams, - DidChangeWorkspaceFoldersParams, - DidCloseNotebookDocumentParams, - DidCloseTextDocumentParams, - DidOpenNotebookDocumentParams, - DidOpenTextDocumentParams, - ExecuteCommandParams, - InitializeParams, - InitializeResult, - LogMessageParams, - LogTraceParams, - MessageType, - PublishDiagnosticsParams, - RegistrationParams, - SetTraceParams, - ShowDocumentParams, - ShowMessageParams, - TraceValues, - UnregistrationParams, - WorkspaceApplyEditResponse, - WorkspaceEdit, - InitializeResultServerInfoType, - WorkspaceConfigurationParams, - WorkDoneProgressCancelParams, -) +from pygls.constants import PARAM_LS +from pygls.exceptions import JsonRpcInvalidParams from pygls.protocol.json_rpc import JsonRPCProtocol -from pygls.protocol.lsp_meta import LSPMeta from pygls.uris import from_fs_path from pygls.workspace import Workspace +if typing.TYPE_CHECKING: + from collections.abc import Generator + from typing import Any, Callable, Optional, Type, TypeVar -F = TypeVar("F", bound=Callable) + from cattrs import Converter + + from pygls.lsp.server import LanguageServer + + F = TypeVar("F", bound=Callable) logger = logging.getLogger(__name__) @@ -109,7 +55,7 @@ def lsp_method(method_name: str) -> Callable[[F], F]: return decorator -class LanguageServerProtocol(JsonRPCProtocol, metaclass=LSPMeta): +class LanguageServerProtocol(JsonRPCProtocol): """A class that represents language server protocol. It contains implementations for generic LSP features. @@ -118,17 +64,19 @@ class LanguageServerProtocol(JsonRPCProtocol, metaclass=LSPMeta): workspace(Workspace): In memory workspace """ - def __init__(self, server, converter): + _server: LanguageServer + + def __init__(self, server: LanguageServer, converter: Converter): super().__init__(server, converter) self._workspace: Optional[Workspace] = None - self.trace = None + self.trace = types.TraceValue.Off from pygls.progress import Progress self.progress = Progress(self) - self.server_info = InitializeResultServerInfoType( + self.server_info = types.ServerInfo( name=server.name, version=server.version, ) @@ -155,40 +103,38 @@ class LanguageServerProtocol(JsonRPCProtocol, metaclass=LSPMeta): return self._workspace @lru_cache() - def get_message_type(self, method: str) -> Optional[Type]: + def get_message_type(self, method: str) -> Type[Any] | None: """Return LSP type definitions, as provided by `lsprotocol`""" - return METHOD_TO_TYPES.get(method, (None,))[0] + return types.METHOD_TO_TYPES.get(method, (None,))[0] @lru_cache() - def get_result_type(self, method: str) -> Optional[Type]: - return METHOD_TO_TYPES.get(method, (None, None))[1] + def get_result_type(self, method: str) -> Type[Any] | None: + return types.METHOD_TO_TYPES.get(method, (None, None))[1] - def apply_edit( - self, edit: WorkspaceEdit, label: Optional[str] = None - ) -> WorkspaceApplyEditResponse: - """Sends apply edit request to the client.""" - return self.send_request( - WORKSPACE_APPLY_EDIT, ApplyWorkspaceEditParams(edit=edit, label=label) - ) - - def apply_edit_async( - self, edit: WorkspaceEdit, label: Optional[str] = None - ) -> WorkspaceApplyEditResponse: - """Sends apply edit request to the client. Should be called with `await`""" - return self.send_request_async( - WORKSPACE_APPLY_EDIT, ApplyWorkspaceEditParams(edit=edit, label=label) - ) - - @lsp_method(EXIT) - def lsp_exit(self, *args) -> None: + @lsp_method(types.EXIT) + def lsp_exit(self, *args) -> Generator[Any, Any, None]: """Stops the server process.""" - if self.transport is not None: - self.transport.close() - sys.exit(0 if self._shutdown else 1) + # Ensure that the user handler is called first + if (user_handler := self.fm.features.get(types.EXIT)) is not None: + yield user_handler, args, None - @lsp_method(INITIALIZE) - def lsp_initialize(self, params: InitializeParams) -> InitializeResult: + returncode = 0 if self._shutdown else 1 + if self.writer is None: + sys.exit(returncode) + + res = self.writer.close() + if inspect.isawaitable(res): + # Only call sys.exit once the close task has completed. + fut = asyncio.ensure_future(res) + fut.add_done_callback(lambda t: sys.exit(returncode)) + else: + sys.exit(returncode) + + @lsp_method(types.INITIALIZE) + def lsp_initialize( + self, params: types.InitializeParams + ) -> Generator[Any, Any, types.InitializeResult]: """Method that initializes language server. It will compute and return server capabilities based on registered features. @@ -200,19 +146,9 @@ class LanguageServerProtocol(JsonRPCProtocol, metaclass=LSPMeta): text_document_sync_kind = self._server._text_document_sync_kind notebook_document_sync = self._server._notebook_document_sync - # Initialize server capabilities self.client_capabilities = params.capabilities - self.server_capabilities = ServerCapabilitiesBuilder( - self.client_capabilities, - set({**self.fm.features, **self.fm.builtin_features}.keys()), - self.fm.feature_options, - list(self.fm.commands.keys()), - text_document_sync_kind, - notebook_document_sync, - ).build() - logger.debug( - "Server capabilities: %s", - json.dumps(self.server_capabilities, default=self._serialize_message), + position_encoding = ServerCapabilitiesBuilder.choose_position_encoding( + self.client_capabilities ) root_path = params.root_path @@ -220,86 +156,144 @@ class LanguageServerProtocol(JsonRPCProtocol, metaclass=LSPMeta): if root_path is not None and root_uri is None: root_uri = from_fs_path(root_path) - # Initialize the workspace + # Initialize the workspace before yielding to the user's initialize handler workspace_folders = params.workspace_folders or [] self._workspace = Workspace( root_uri, text_document_sync_kind, workspace_folders, - self.server_capabilities.position_encoding, + position_encoding, ) - self.trace = TraceValues.Off + if (user_handler := self.fm.features.get(types.INITIALIZE)) is not None: + yield user_handler, (params,), None - return InitializeResult( + # Now that the user has had the opportunity to setup additional features, calculate + # the server's capabilities + self.server_capabilities = ServerCapabilitiesBuilder( + self.client_capabilities, + set({**self.fm.features, **self.fm.builtin_features}.keys()), + self.fm.feature_options, + list(self.fm.commands.keys()), + text_document_sync_kind, + notebook_document_sync, + position_encoding, + ).build() + logger.debug( + "Server capabilities: %s", + json.dumps(self.server_capabilities, default=self._serialize_message), + ) + + return types.InitializeResult( capabilities=self.server_capabilities, server_info=self.server_info, ) - @lsp_method(INITIALIZED) - def lsp_initialized(self, *args) -> None: + @lsp_method(types.INITIALIZED) + def lsp_initialized(self, *args): """Notification received when client and server are connected.""" - pass - @lsp_method(SHUTDOWN) - def lsp_shutdown(self, *args) -> None: + if (user_handler := self.fm.features.get(types.INITIALIZED)) is not None: + yield user_handler, args, None + + @lsp_method(types.SHUTDOWN) + def lsp_shutdown(self, *args) -> Generator[Any, Any, None]: """Request from client which asks server to shutdown.""" - for future in self._request_futures.values(): - future.cancel() + + if (user_handler := self.fm.features.get(types.SHUTDOWN)) is not None: + yield user_handler, args, None + + # Don't cancel the future for this request! + current_id = self.msg_id + + for msg_id, future in self._request_futures.items(): + if msg_id != current_id and not future.done(): + future.cancel() self._shutdown = True return None - @lsp_method(TEXT_DOCUMENT_DID_CHANGE) - def lsp_text_document__did_change( - self, params: DidChangeTextDocumentParams - ) -> None: + @lsp_method(types.TEXT_DOCUMENT_DID_CHANGE) + def lsp_text_document__did_change(self, params: types.DidChangeTextDocumentParams): """Updates document's content. (Incremental(from server capabilities); not configurable for now) """ for change in params.content_changes: self.workspace.update_text_document(params.text_document, change) - @lsp_method(TEXT_DOCUMENT_DID_CLOSE) - def lsp_text_document__did_close(self, params: DidCloseTextDocumentParams) -> None: + if ( + user_handler := self.fm.features.get(types.TEXT_DOCUMENT_DID_CHANGE) + ) is not None: + yield user_handler, (params,), None + + @lsp_method(types.TEXT_DOCUMENT_DID_CLOSE) + def lsp_text_document__did_close(self, params: types.DidCloseTextDocumentParams): """Removes document from workspace.""" self.workspace.remove_text_document(params.text_document.uri) - @lsp_method(TEXT_DOCUMENT_DID_OPEN) - def lsp_text_document__did_open(self, params: DidOpenTextDocumentParams) -> None: + if ( + user_handler := self.fm.features.get(types.TEXT_DOCUMENT_DID_CLOSE) + ) is not None: + yield user_handler, (params,), None + + @lsp_method(types.TEXT_DOCUMENT_DID_OPEN) + def lsp_text_document__did_open(self, params: types.DidOpenTextDocumentParams): """Puts document to the workspace.""" self.workspace.put_text_document(params.text_document) - @lsp_method(NOTEBOOK_DOCUMENT_DID_OPEN) + if ( + user_handler := self.fm.features.get(types.TEXT_DOCUMENT_DID_OPEN) + ) is not None: + yield user_handler, (params,), None + + @lsp_method(types.NOTEBOOK_DOCUMENT_DID_OPEN) def lsp_notebook_document__did_open( - self, params: DidOpenNotebookDocumentParams - ) -> None: + self, params: types.DidOpenNotebookDocumentParams + ): """Put a notebook document into the workspace""" self.workspace.put_notebook_document(params) - @lsp_method(NOTEBOOK_DOCUMENT_DID_CHANGE) + if ( + user_handler := self.fm.features.get(types.NOTEBOOK_DOCUMENT_DID_OPEN) + ) is not None: + yield user_handler, (params,), None + + @lsp_method(types.NOTEBOOK_DOCUMENT_DID_CHANGE) def lsp_notebook_document__did_change( - self, params: DidChangeNotebookDocumentParams - ) -> None: + self, params: types.DidChangeNotebookDocumentParams + ): """Update a notebook's contents""" self.workspace.update_notebook_document(params) - @lsp_method(NOTEBOOK_DOCUMENT_DID_CLOSE) + if ( + user_handler := self.fm.features.get(types.NOTEBOOK_DOCUMENT_DID_CHANGE) + ) is not None: + yield user_handler, (params,), None + + @lsp_method(types.NOTEBOOK_DOCUMENT_DID_CLOSE) def lsp_notebook_document__did_close( - self, params: DidCloseNotebookDocumentParams - ) -> None: + self, params: types.DidCloseNotebookDocumentParams + ): """Remove a notebook document from the workspace.""" self.workspace.remove_notebook_document(params) - @lsp_method(SET_TRACE) - def lsp_set_trace(self, params: SetTraceParams) -> None: + if ( + user_handler := self.fm.features.get(types.NOTEBOOK_DOCUMENT_DID_CLOSE) + ) is not None: + yield user_handler, (params,), None + + @lsp_method(types.SET_TRACE) + def lsp_set_trace(self, params: types.SetTraceParams) -> Generator[Any, Any, None]: """Changes server trace value.""" self.trace = params.value - @lsp_method(WORKSPACE_DID_CHANGE_WORKSPACE_FOLDERS) + if (user_handler := self.fm.features.get(types.SET_TRACE)) is not None: + yield user_handler, (params,), None + + @lsp_method(types.WORKSPACE_DID_CHANGE_WORKSPACE_FOLDERS) def lsp_workspace__did_change_workspace_folders( - self, params: DidChangeWorkspaceFoldersParams - ) -> None: + self, params: types.DidChangeWorkspaceFoldersParams + ): """Adds/Removes folders from the workspace.""" logger.info("Workspace folders changed: %s", params) @@ -312,18 +306,35 @@ class LanguageServerProtocol(JsonRPCProtocol, metaclass=LSPMeta): if f_remove: self.workspace.remove_folder(f_remove.uri) - @lsp_method(WORKSPACE_EXECUTE_COMMAND) - def lsp_workspace__execute_command( - self, params: ExecuteCommandParams, msg_id: str - ) -> None: - """Executes commands with passed arguments and returns a value.""" - cmd_handler = self.fm.commands[params.command] - self._execute_request(msg_id, cmd_handler, params.arguments) + if ( + user_handler := self.fm.features.get( + types.WORKSPACE_DID_CHANGE_WORKSPACE_FOLDERS + ) + ) is not None: + yield user_handler, (params,), None - @lsp_method(WINDOW_WORK_DONE_PROGRESS_CANCEL) - def lsp_work_done_progress_cancel( - self, params: WorkDoneProgressCancelParams - ) -> None: + @lsp_method(types.WORKSPACE_EXECUTE_COMMAND) + def lsp_workspace__execute_command( + self, params: types.ExecuteCommandParams + ) -> Generator[Any, Any, Any]: + """Executes commands with passed arguments and returns a value.""" + + if (handler := self.fm.commands.get(params.command, None)) is None: + raise JsonRpcInvalidParams.of( + ValueError(f"Command name {params.command!r} is not defined") + ) + + try: + args, kwargs = _prepare_command_arguments(handler, params, self._converter) + except Exception as exc: + raise JsonRpcInvalidParams.of(exc) + + # Call the user's command handler. + result = yield handler, args, kwargs + return result + + @lsp_method(types.WINDOW_WORK_DONE_PROGRESS_CANCEL) + def lsp_work_done_progress_cancel(self, params: types.WorkDoneProgressCancelParams): """Received a progress cancellation from client.""" future = self.progress.tokens.get(params.token) if future is None: @@ -333,237 +344,85 @@ class LanguageServerProtocol(JsonRPCProtocol, metaclass=LSPMeta): else: future.cancel() - def get_configuration( - self, - params: WorkspaceConfigurationParams, - callback: Optional[ConfigCallbackType] = None, - ) -> Future: - """Sends configuration request to the client. + if ( + user_handler := self.fm.features.get(types.WINDOW_WORK_DONE_PROGRESS_CANCEL) + ) is not None: + yield user_handler, (params,), None - Args: - params(WorkspaceConfigurationParams): WorkspaceConfigurationParams from lsp specs - callback(callable): Callabe which will be called after - response from the client is received - Returns: - concurrent.futures.Future object that will be resolved once a - response has been received - """ - return self.send_request(WORKSPACE_CONFIGURATION, params, callback) - def get_configuration_async( - self, params: WorkspaceConfigurationParams - ) -> asyncio.Future: - """Calls `get_configuration` method but designed to use with coroutines +def _prepare_command_arguments( + handler: Callable[..., Any], + params: types.ExecuteCommandParams, + converter: Converter, +) -> tuple[tuple[Any, ...], dict[str, Any]]: + """Prepare the arguments to pass to the command handler.""" - Args: - params(WorkspaceConfigurationParams): WorkspaceConfigurationParams from lsp specs - Returns: - asyncio.Future that can be awaited - """ - return asyncio.wrap_future(self.get_configuration(params)) + if params.arguments is None: + return tuple(), {} - def log_trace(self, message: str, verbose: Optional[str] = None) -> None: - """Sends trace notification to the client.""" - if self.trace == TraceValues.Off: - return + # Import this here to not introduce an import cycle at the module level + from pygls.lsp.server import LanguageServer - params = LogTraceParams(message=message) - if verbose and self.trace == TraceValues.Verbose: - params.verbose = verbose + param_vals = iter(params.arguments) + param_defs, annotations = _get_handler_params_annotations(handler) - self.notify(LOG_TRACE, params) + args: list[Any] = [] + kwargs: dict[str, Any] = {} - def _publish_diagnostics_deprecator( - self, - params_or_uri: Union[str, PublishDiagnosticsParams], - diagnostics: Optional[List[Diagnostic]], - version: Optional[int], - **kwargs, - ) -> PublishDiagnosticsParams: - if isinstance(params_or_uri, str): - message = "DEPRECATION: " - "`publish_diagnostics(" - "self, doc_uri: str, diagnostics: List[Diagnostic], version: Optional[int] = None)`" - "will be replaced with `publish_diagnostics(self, params: PublishDiagnosticsParams)`" - logging.warning(message) + # param_defs is an OrderedDict so *in theory* at least we don't have to + # worry about argument order. + found_ls = False + for idx, (name, param) in enumerate(param_defs.items()): + ptype = annotations.get(name, None) + + # We don't need to provide the injected server instance here. + # The @server.command decorator will have already handled it. + if idx == 0: + if name == PARAM_LS: + found_ls = True + continue + + if (ptype is not None) and issubclass(ptype, LanguageServer): + found_ls = True + continue + + if param.kind == inspect.Parameter.VAR_POSITIONAL: # i.e. *args + # consume the remaining values + args.extend(param_vals) - params = self._construct_publish_diagnostic_type( - params_or_uri, diagnostics, version, **kwargs - ) else: - params = params_or_uri - return params + try: + value = converter.structure(next(param_vals), ptype) + except StopIteration as exc: + raise TypeError( + f"Expected {len(param_defs) - found_ls} arguments, " + f"got {len(params.arguments)}" + ) from exc - def _construct_publish_diagnostic_type( - self, - uri: str, - diagnostics: Optional[List[Diagnostic]], - version: Optional[int], - **kwargs, - ) -> PublishDiagnosticsParams: - if diagnostics is None: - diagnostics = [] + args.append(value) - args = { - **{"uri": uri, "diagnostics": diagnostics, "version": version}, - **kwargs, - } - - params = PublishDiagnosticsParams(**args) # type:ignore - return params - - def publish_diagnostics( - self, - params_or_uri: Union[str, PublishDiagnosticsParams], - diagnostics: Optional[List[Diagnostic]] = None, - version: Optional[int] = None, - **kwargs, - ): - """Sends diagnostic notification to the client. - - .. deprecated:: 1.0.1 - - Passing ``(uri, diagnostics, version)`` as arguments is deprecated. - Pass an instance of :class:`~lsprotocol.types.PublishDiagnosticParams` - instead. - - Parameters - ---------- - params_or_uri - The :class:`~lsprotocol.types.PublishDiagnosticParams` to send to the client. - - diagnostics - *Deprecated*. The diagnostics to publish - - version - *Deprecated*: The version number - """ - params = self._publish_diagnostics_deprecator( - params_or_uri, diagnostics, version, **kwargs - ) - self.notify(TEXT_DOCUMENT_PUBLISH_DIAGNOSTICS, params) - - def register_capability( - self, params: RegistrationParams, callback: Optional[Callable[[], None]] = None - ) -> Future: - """Register a new capability on the client. - - Args: - params(RegistrationParams): RegistrationParams from lsp specs - callback(callable): Callabe which will be called after - response from the client is received - Returns: - concurrent.futures.Future object that will be resolved once a - response has been received - """ - return self.send_request(CLIENT_REGISTER_CAPABILITY, params, callback) - - def register_capability_async(self, params: RegistrationParams) -> asyncio.Future: - """Register a new capability on the client. - - Args: - params(RegistrationParams): RegistrationParams from lsp specs - - Returns: - asyncio.Future object that will be resolved once a - response has been received - """ - return asyncio.wrap_future(self.register_capability(params, None)) - - def semantic_tokens_refresh( - self, callback: Optional[Callable[[], None]] = None - ) -> Future: - """Requesting a refresh of all semantic tokens. - - Args: - callback(callable): Callabe which will be called after - response from the client is received - - Returns: - concurrent.futures.Future object that will be resolved once a - response has been received - """ - return self.send_request(WORKSPACE_SEMANTIC_TOKENS_REFRESH, callback=callback) - - def semantic_tokens_refresh_async(self) -> asyncio.Future: - """Requesting a refresh of all semantic tokens. - - Returns: - asyncio.Future object that will be resolved once a - response has been received - """ - return asyncio.wrap_future(self.semantic_tokens_refresh(None)) - - def show_document( - self, - params: ShowDocumentParams, - callback: Optional[ShowDocumentCallbackType] = None, - ) -> Future: - """Display a particular document in the user interface. - - Args: - params(ShowDocumentParams): ShowDocumentParams from lsp specs - callback(callable): Callabe which will be called after - response from the client is received - - Returns: - concurrent.futures.Future object that will be resolved once a - response has been received - """ - return self.send_request(WINDOW_SHOW_DOCUMENT, params, callback) - - def show_document_async(self, params: ShowDocumentParams) -> asyncio.Future: - """Display a particular document in the user interface. - - Args: - params(ShowDocumentParams): ShowDocumentParams from lsp specs - - Returns: - asyncio.Future object that will be resolved once a - response has been received - """ - return asyncio.wrap_future(self.show_document(params, None)) - - def show_message(self, message, msg_type=MessageType.Info): - """Sends message to the client to display message.""" - self.notify( - WINDOW_SHOW_MESSAGE, ShowMessageParams(type=msg_type, message=message) + # did we consume all the values? + if len(list(param_vals)) > 0: + raise TypeError( + f"Expected {len(param_defs) - found_ls} arguments, " + f"got {len(params.arguments)}" ) - def show_message_log(self, message, msg_type=MessageType.Log): - """Sends message to the client's output channel.""" - self.notify( - WINDOW_LOG_MESSAGE, LogMessageParams(type=msg_type, message=message) - ) + return tuple(args), kwargs - def unregister_capability( - self, - params: UnregistrationParams, - callback: Optional[Callable[[], None]] = None, - ) -> Future: - """Unregister a new capability on the client. - Args: - params(UnregistrationParams): UnregistrationParams from lsp specs - callback(callable): Callabe which will be called after - response from the client is received - Returns: - concurrent.futures.Future object that will be resolved once a - response has been received - """ - return self.send_request(CLIENT_UNREGISTER_CAPABILITY, params, callback) +def _get_handler_params_annotations(handler: Callable[..., Any]): + """Return the parameters and corresponding type annotations for the given handler + function.""" - def unregister_capability_async( - self, params: UnregistrationParams - ) -> asyncio.Future: - """Unregister a new capability on the client. + # If the user's handler requests the language server instance, the real function + # is wrapped inside whatever `functools.partial()` returns. + if hasattr(handler, "func"): + annotations = typing.get_type_hints(handler.func) + params = inspect.signature(handler.func).parameters - Args: - params(UnregistrationParams): UnregistrationParams from lsp specs - callback(callable): Callabe which will be called after - response from the client is received - Returns: - asyncio.Future object that will be resolved once a - response has been received - """ - return asyncio.wrap_future(self.unregister_capability(params, None)) + else: + annotations = typing.get_type_hints(handler) + params = inspect.signature(handler).parameters + + return params, annotations diff --git a/server/libs/pygls/protocol/lsp_meta.py b/server/libs/pygls/protocol/lsp_meta.py deleted file mode 100644 index 0dc52db..0000000 --- a/server/libs/pygls/protocol/lsp_meta.py +++ /dev/null @@ -1,51 +0,0 @@ -import functools -import logging -from pygls.constants import ATTR_FEATURE_TYPE -from pygls.feature_manager import assign_help_attrs - - -logger = logging.getLogger(__name__) - - -def call_user_feature(base_func, method_name): - """Wraps generic LSP features and calls user registered feature - immediately after it. - """ - - @functools.wraps(base_func) - def decorator(self, *args, **kwargs): - ret_val = base_func(self, *args, **kwargs) - - try: - user_func = self.fm.features[method_name] - self._execute_notification(user_func, *args, **kwargs) - except KeyError: - pass - except Exception: - logger.exception( - 'Failed to handle user defined notification "%s": %s', method_name, args - ) - - return ret_val - - return decorator - - -class LSPMeta(type): - """Wraps LSP built-in features (`lsp_` naming convention). - - Built-in features cannot be overridden but user defined features with - the same LSP name will be called after them. - """ - - def __new__(mcs, cls_name, cls_bases, cls): - for attr_name, attr_val in cls.items(): - if callable(attr_val) and hasattr(attr_val, "method_name"): - method_name = attr_val.method_name - wrapped = call_user_feature(attr_val, method_name) - assign_help_attrs(wrapped, method_name, ATTR_FEATURE_TYPE) - cls[attr_name] = wrapped - - logger.debug('Added decorator for lsp method: "%s"', attr_name) - - return super().__new__(mcs, cls_name, cls_bases, cls) diff --git a/server/libs/pygls/server.py b/server/libs/pygls/server.py index 7717b84..6c143a2 100644 --- a/server/libs/pygls/server.py +++ b/server/libs/pygls/server.py @@ -14,213 +14,66 @@ # See the License for the specific language governing permissions and # # limitations under the License. # ############################################################################ +from __future__ import annotations + import asyncio -import json import logging -import re import sys -from concurrent.futures import Future, ThreadPoolExecutor +import typing +from concurrent.futures import ThreadPoolExecutor from threading import Event -from typing import ( - Any, - Callable, - List, - Optional, - TextIO, - Type, - TypeVar, - Union, -) import cattrs -from pygls import IS_PYODIDE -from pygls.lsp import ConfigCallbackType, ShowDocumentCallbackType -from pygls.exceptions import ( - FeatureNotificationError, - JsonRpcInternalError, - PyglsError, - JsonRpcException, - FeatureRequestError, -) -from lsprotocol.types import ( - ClientCapabilities, - Diagnostic, - MessageType, - NotebookDocumentSyncOptions, - RegistrationParams, - ServerCapabilities, - ShowDocumentParams, - TextDocumentSyncKind, - UnregistrationParams, - WorkspaceApplyEditResponse, - WorkspaceEdit, - WorkspaceConfigurationParams, -) -from pygls.progress import Progress -from pygls.protocol import JsonRPCProtocol, LanguageServerProtocol, default_converter -from pygls.workspace import Workspace -if not IS_PYODIDE: - from multiprocessing.pool import ThreadPool +from pygls import IS_WASM +from pygls.exceptions import JsonRpcException, PyglsError +from pygls.io_ import StdinAsyncReader, StdoutWriter, run, run_async, run_websocket +from pygls.protocol import JsonRPCProtocol + +if typing.TYPE_CHECKING: + from typing import Any, BinaryIO, Callable, Optional, Type, TypeVar, Union + + from websockets.asyncio.server import Server as WSServer + from websockets.asyncio.server import ServerConnection + + F = TypeVar("F", bound=Callable) + ServerErrors = Union[type[PyglsError], type[JsonRpcException]] logger = logging.getLogger(__name__) -F = TypeVar("F", bound=Callable) -ServerErrors = Union[ - PyglsError, - JsonRpcException, - Type[JsonRpcInternalError], - Type[FeatureNotificationError], - Type[FeatureRequestError], -] - - -async def aio_readline(loop, executor, stop_event, rfile, proxy): - """Reads data from stdin in separate thread (asynchronously).""" - - CONTENT_LENGTH_PATTERN = re.compile(rb"^Content-Length: (\d+)\r\n$") - - # Initialize message buffer - message = [] - content_length = 0 - - while not stop_event.is_set() and not rfile.closed: - # Read a header line - header = await loop.run_in_executor(executor, rfile.readline) - if not header: - break - message.append(header) - - # Extract content length if possible - if not content_length: - match = CONTENT_LENGTH_PATTERN.fullmatch(header) - if match: - content_length = int(match.group(1)) - logger.debug("Content length: %s", content_length) - - # Check if all headers have been read (as indicated by an empty line \r\n) - if content_length and not header.strip(): - # Read body - body = await loop.run_in_executor(executor, rfile.read, content_length) - if not body: - break - message.append(body) - - # Pass message to language server protocol - proxy(b"".join(message)) - - # Reset the buffer - message = [] - content_length = 0 - - -class StdOutTransportAdapter: - """Protocol adapter which overrides write method. - - Write method sends data to stdout. - """ - - def __init__(self, rfile, wfile): - self.rfile = rfile - self.wfile = wfile - - def close(self): - self.rfile.close() - self.wfile.close() - - def write(self, data): - self.wfile.write(data) - self.wfile.flush() - - -class PyodideTransportAdapter: - """Protocol adapter which overrides write method. - - Write method sends data to stdout. - """ - - def __init__(self, wfile): - self.wfile = wfile - - def close(self): - self.wfile.close() - - def write(self, data): - self.wfile.write(data) - self.wfile.flush() - - -class WebSocketTransportAdapter: - """Protocol adapter which calls write method. - - Write method sends data via the WebSocket interface. - """ - - def __init__(self, ws, loop): - self._ws = ws - self._loop = loop - - def close(self) -> None: - """Stop the WebSocket server.""" - self._ws.close() - - def write(self, data: Any) -> None: - """Create a task to write specified data into a WebSocket.""" - asyncio.ensure_future(self._ws.send(data)) - - -class Server: +class JsonRPCServer: """Base server class Parameters ---------- protocol_cls - Protocol implementation that must be derive from :class:`~pygls.protocol.JsonRPCProtocol` + Protocol implementation that should derive from + :class:`~pygls.protocol.JsonRPCProtocol` converter_factory Factory function to use when constructing a cattrs converter. - loop - The asyncio event loop - max_workers - Maximum number of workers for `ThreadPool` and `ThreadPoolExecutor` + Maximum number of workers for `ThreadPoolExecutor` """ + protocol: JsonRPCProtocol + def __init__( self, protocol_cls: Type[JsonRPCProtocol], converter_factory: Callable[[], cattrs.Converter], - loop: Optional[asyncio.AbstractEventLoop] = None, - max_workers: int = 2, - sync_kind: TextDocumentSyncKind = TextDocumentSyncKind.Incremental, + max_workers: int | None = None, ): - if not issubclass(protocol_cls, asyncio.Protocol): - raise TypeError("Protocol class should be subclass of asyncio.Protocol") - self._max_workers = max_workers - self._server = None - self._stop_event: Optional[Event] = None - self._thread_pool: Optional[ThreadPool] = None - self._thread_pool_executor: Optional[ThreadPoolExecutor] = None + self._server: asyncio.Server | WSServer | None = None + self._stop_event: Event | None = None + self._thread_pool: ThreadPoolExecutor | None = None - if sync_kind is not None: - self.text_document_sync_kind = sync_kind - - if loop is None: - loop = asyncio.new_event_loop() - asyncio.set_event_loop(loop) - self._owns_loop = True - else: - self._owns_loop = False - - self.loop = loop - - # TODO: Will move this to `LanguageServer` soon - self.lsp = protocol_cls(self, converter_factory()) # type: ignore + self.protocol = protocol_cls(self, converter_factory()) def shutdown(self): """Shutdown server.""" @@ -230,38 +83,55 @@ class Server: self._stop_event.set() if self._thread_pool: - self._thread_pool.terminate() - self._thread_pool.join() - - if self._thread_pool_executor: - self._thread_pool_executor.shutdown() + self._thread_pool.shutdown() if self._server: self._server.close() - self.loop.run_until_complete(self._server.wait_closed()) - if self._owns_loop and not self.loop.is_closed(): - logger.info("Closing the event loop.") - self.loop.close() + def _report_server_error( + self, + error: Exception, + source: ServerErrors, + ): + # Prevent recursive error reporting + try: + self.report_server_error(error, source) + except Exception: + logger.warning("Failed to report error") - def start_io(self, stdin: Optional[TextIO] = None, stdout: Optional[TextIO] = None): - """Starts IO server.""" - logger.info("Starting IO server") + def report_server_error(self, error: Exception, source: ServerErrors): + """Default error reporter.""" + logger.error("%s", error) + + def start_io( + self, stdin: Optional[BinaryIO] = None, stdout: Optional[BinaryIO] = None + ): + """Starts an IO server.""" + + if IS_WASM: + self._start_io_sync(stdin, stdout) + else: + self._start_io_async(stdin, stdout) + + def _start_io_async( + self, stdin: Optional[BinaryIO] = None, stdout: Optional[BinaryIO] = None + ): + """Starts an asynchronous IO server.""" + logger.info("Starting async IO server") self._stop_event = Event() - transport = StdOutTransportAdapter( - stdin or sys.stdin.buffer, stdout or sys.stdout.buffer - ) - self.lsp.connection_made(transport) # type: ignore[arg-type] + reader = StdinAsyncReader(stdin or sys.stdin.buffer, self.thread_pool) + writer = StdoutWriter(stdout or sys.stdout.buffer) + self.protocol.set_writer(writer) try: - self.loop.run_until_complete( - aio_readline( - self.loop, - self.thread_pool_executor, - self._stop_event, - stdin or sys.stdin.buffer, - self.lsp.data_received, + asyncio.run( + run_async( + stop_event=self._stop_event, + reader=reader, + protocol=self.protocol, + logger=logger, + error_handler=self.report_server_error, ) ) except BrokenPipeError: @@ -271,169 +141,104 @@ class Server: finally: self.shutdown() - def start_pyodide(self): - logger.info("Starting Pyodide server") + def _start_io_sync( + self, stdin: Optional[BinaryIO] = None, stdout: Optional[BinaryIO] = None + ): + """Starts an synchronous IO server.""" + logger.info("Starting sync IO server") - # Note: We don't actually start anything running as the main event - # loop will be handled by the web platform. - transport = PyodideTransportAdapter(sys.stdout) - self.lsp.connection_made(transport) # type: ignore[arg-type] - self.lsp._send_only_body = True # Don't send headers within the payload + self._stop_event = Event() + writer = StdoutWriter(stdout or sys.stdout.buffer) + self.protocol.set_writer(writer) + + try: + asyncio.run( + run( + stop_event=self._stop_event, + reader=stdin or sys.stdin.buffer, + protocol=self.protocol, + logger=logger, + error_handler=self.report_server_error, + ) + ) + except BrokenPipeError: + logger.error("Connection to the client is lost! Shutting down the server.") + except (KeyboardInterrupt, SystemExit): + pass + finally: + self.shutdown() def start_tcp(self, host: str, port: int) -> None: """Starts TCP server.""" logger.info("Starting TCP server on %s:%s", host, port) - self._stop_event = Event() - self._server = self.loop.run_until_complete( # type: ignore[assignment] - self.loop.create_server(self.lsp, host, port) - ) - try: - self.loop.run_forever() - except (KeyboardInterrupt, SystemExit): - pass - finally: + self._stop_event = stop_event = Event() + + async def lsp_connection( + reader: asyncio.StreamReader, writer: asyncio.StreamWriter + ): + logger.debug("Connected to client") + self.protocol.set_writer(writer) # type: ignore + await run_async( + stop_event=stop_event, + reader=reader, + protocol=self.protocol, + logger=logger, + error_handler=self.report_server_error, + ) + logger.debug("Main loop finished") self.shutdown() + async def tcp_server(h: str, p: int): + self._server = await asyncio.start_server(lsp_connection, h, p) + + addrs = ", ".join(str(sock.getsockname()) for sock in self._server.sockets) + logger.info(f"Serving on {addrs}") + + async with self._server: + await self._server.serve_forever() + + try: + asyncio.run(tcp_server(host, port)) + except asyncio.CancelledError: + logger.debug("Server was cancelled") + def start_ws(self, host: str, port: int) -> None: """Starts WebSocket server.""" try: - from websockets.server import serve + from websockets.asyncio.server import serve except ImportError: - logger.error("Run `pip install pygls[ws]` to install `websockets`.") + logger.error( + "Run `pip install pygls[ws]` to install dependencies required for websockets." + ) sys.exit(1) logger.info("Starting WebSocket server on {}:{}".format(host, port)) + self._stop_event = stop_event = Event() - self._stop_event = Event() - self.lsp._send_only_body = True # Don't send headers within the payload - - async def connection_made(websocket, _): - """Handle new connection wrapped in the WebSocket.""" - self.lsp.transport = WebSocketTransportAdapter(websocket, self.loop) - async for message in websocket: - self.lsp._procedure_handler( - json.loads(message, object_hook=self.lsp._deserialize_message) - ) - - start_server = serve(connection_made, host, port, loop=self.loop) - self._server = start_server.ws_server # type: ignore[assignment] - self.loop.run_until_complete(start_server) - - try: - self.loop.run_forever() - except (KeyboardInterrupt, SystemExit): - pass - finally: - self._stop_event.set() + async def lsp_connection(websocket: ServerConnection): + await run_websocket( + stop_event=stop_event, + websocket=websocket, + protocol=self.protocol, + logger=logger, + error_handler=self.report_server_error, + ) self.shutdown() - if not IS_PYODIDE: + async def ws_server(h: str, p: int): + self._server = await serve(lsp_connection, host, port) - @property - def thread_pool(self) -> ThreadPool: - """Returns thread pool instance (lazy initialization).""" - if not self._thread_pool: - self._thread_pool = ThreadPool(processes=self._max_workers) + addrs = ", ".join(str(sock.getsockname()) for sock in self._server.sockets) + logger.info(f"Serving on {addrs}") - return self._thread_pool + async with self._server: + await self._server.serve_forever() - @property - def thread_pool_executor(self) -> ThreadPoolExecutor: - """Returns thread pool instance (lazy initialization).""" - if not self._thread_pool_executor: - self._thread_pool_executor = ThreadPoolExecutor( - max_workers=self._max_workers - ) - - return self._thread_pool_executor - - -class LanguageServer(Server): - """The default LanguageServer - - This class can be extended and it can be passed as a first argument to - registered commands/features. - - .. |ServerInfo| replace:: :class:`~lsprotocol.types.InitializeResultServerInfoType` - - Parameters - ---------- - name - Name of the server, used to populate |ServerInfo| which is sent to - the client during initialization - - version - Version of the server, used to populate |ServerInfo| which is sent to - the client during initialization - - protocol_cls - The :class:`~pygls.protocol.LanguageServerProtocol` class definition, or any - subclass of it. - - max_workers - Maximum number of workers for ``ThreadPool`` and ``ThreadPoolExecutor`` - - text_document_sync_kind - Text document synchronization method - - None - No synchronization - - :attr:`~lsprotocol.types.TextDocumentSyncKind.Full` - Send entire document text with each update - - :attr:`~lsprotocol.types.TextDocumentSyncKind.Incremental` - Send only the region of text that changed with each update - - notebook_document_sync - Advertise :lsp:`NotebookDocument` support to the client. - """ - - lsp: LanguageServerProtocol - - default_error_message = ( - "Unexpected error in LSP server, see server's logs for details" - ) - """ - The default error message sent to the user's editor when this server encounters an uncaught - exception. - """ - - def __init__( - self, - name: str, - version: str, - loop=None, - protocol_cls: Type[LanguageServerProtocol] = LanguageServerProtocol, - converter_factory=default_converter, - text_document_sync_kind: TextDocumentSyncKind = TextDocumentSyncKind.Incremental, - notebook_document_sync: Optional[NotebookDocumentSyncOptions] = None, - max_workers: int = 2, - ): - if not issubclass(protocol_cls, LanguageServerProtocol): - raise TypeError( - "Protocol class should be subclass of LanguageServerProtocol" - ) - - self.name = name - self.version = version - self._text_document_sync_kind = text_document_sync_kind - self._notebook_document_sync = notebook_document_sync - self.process_id: Optional[Union[int, None]] = None - super().__init__(protocol_cls, converter_factory, loop, max_workers) - - def apply_edit( - self, edit: WorkspaceEdit, label: Optional[str] = None - ) -> WorkspaceApplyEditResponse: - """Sends apply edit request to the client.""" - return self.lsp.apply_edit(edit, label) - - def apply_edit_async( - self, edit: WorkspaceEdit, label: Optional[str] = None - ) -> WorkspaceApplyEditResponse: - """Sends apply edit request to the client. Should be called with `await`""" - return self.lsp.apply_edit_async(edit, label) + try: + asyncio.run(ws_server(host, port)) + except asyncio.CancelledError: + logger.debug("Server was cancelled") def command(self, command_name: str) -> Callable[[F], F]: """Decorator used to register custom commands. @@ -446,17 +251,16 @@ class LanguageServer(Server): def my_cmd(ls, a, b, c): pass """ - return self.lsp.fm.command(command_name) + return self.protocol.fm.command(command_name) - @property - def client_capabilities(self) -> ClientCapabilities: - """The client's capabilities.""" - return self.lsp.client_capabilities + def thread(self) -> Callable[[F], F]: + """Decorator that mark function to execute it in a thread.""" + return self.protocol.fm.thread() def feature( self, feature_name: str, - options: Optional[Any] = None, + options: Any | None = None, ) -> Callable[[F], F]: """Decorator used to register LSP features. @@ -468,149 +272,12 @@ class LanguageServer(Server): def completions(ls, params: CompletionParams): return CompletionList(is_incomplete=False, items=[CompletionItem("Completion 1")]) """ - return self.lsp.fm.feature(feature_name, options) - - def get_configuration( - self, - params: WorkspaceConfigurationParams, - callback: Optional[ConfigCallbackType] = None, - ) -> Future: - """Gets the configuration settings from the client.""" - return self.lsp.get_configuration(params, callback) - - def get_configuration_async( - self, params: WorkspaceConfigurationParams - ) -> asyncio.Future: - """Gets the configuration settings from the client. Should be called with `await`""" - return self.lsp.get_configuration_async(params) - - def log_trace(self, message: str, verbose: Optional[str] = None) -> None: - """Sends trace notification to the client.""" - self.lsp.log_trace(message, verbose) + return self.protocol.fm.feature(feature_name, options) @property - def progress(self) -> Progress: - """Gets the object to manage client's progress bar.""" - return self.lsp.progress + def thread_pool(self) -> ThreadPoolExecutor: + """Returns thread pool instance (lazy initialization).""" + if not self._thread_pool: + self._thread_pool = ThreadPoolExecutor(max_workers=self._max_workers) - def publish_diagnostics( - self, - uri: str, - diagnostics: Optional[List[Diagnostic]] = None, - version: Optional[int] = None, - **kwargs - ): - """ - Sends diagnostic notification to the client. - """ - params = self.lsp._construct_publish_diagnostic_type( - uri, diagnostics, version, **kwargs - ) - self.lsp.publish_diagnostics(params, **kwargs) - - def register_capability( - self, params: RegistrationParams, callback: Optional[Callable[[], None]] = None - ) -> Future: - """Register a new capability on the client.""" - return self.lsp.register_capability(params, callback) - - def register_capability_async(self, params: RegistrationParams) -> asyncio.Future: - """Register a new capability on the client. Should be called with `await`""" - return self.lsp.register_capability_async(params) - - def semantic_tokens_refresh( - self, callback: Optional[Callable[[], None]] = None - ) -> Future: - """Request a refresh of all semantic tokens.""" - return self.lsp.semantic_tokens_refresh(callback) - - def semantic_tokens_refresh_async(self) -> asyncio.Future: - """Request a refresh of all semantic tokens. Should be called with `await`""" - return self.lsp.semantic_tokens_refresh_async() - - def send_notification(self, method: str, params: object = None) -> None: - """Sends notification to the client.""" - self.lsp.notify(method, params) - - @property - def server_capabilities(self) -> ServerCapabilities: - """Return server capabilities.""" - return self.lsp.server_capabilities - - def show_document( - self, - params: ShowDocumentParams, - callback: Optional[ShowDocumentCallbackType] = None, - ) -> Future: - """Display a particular document in the user interface.""" - return self.lsp.show_document(params, callback) - - def show_document_async(self, params: ShowDocumentParams) -> asyncio.Future: - """Display a particular document in the user interface. Should be called with `await`""" - return self.lsp.show_document_async(params) - - def show_message(self, message, msg_type=MessageType.Info) -> None: - """Sends message to the client to display message.""" - self.lsp.show_message(message, msg_type) - - def show_message_log(self, message, msg_type=MessageType.Log) -> None: - """Sends message to the client's output channel.""" - self.lsp.show_message_log(message, msg_type) - - def _report_server_error( - self, - error: Exception, - source: ServerErrors, - ): - # Prevent recursive error reporting - try: - self.report_server_error(error, source) - except Exception: - logger.warning("Failed to report error to client") - - def report_server_error(self, error: Exception, source: ServerErrors): - """ - Sends error to the client for displaying. - - By default this fucntion does not handle LSP request errors. This is because LSP requests - require direct responses and so already have a mechanism for including unexpected errors - in the response body. - - All other errors are "out of band" in the sense that the client isn't explicitly waiting - for them. For example diagnostics are returned as notifications, not responses to requests, - and so can seemingly be sent at random. Also for example consider JSON RPC serialization - and deserialization, if a payload cannot be parsed then the whole request/response cycle - cannot be completed and so one of these "out of band" error messages is sent. - - These "out of band" error messages are not a requirement of the LSP spec. Pygls simply - offers this behaviour as a recommended default. It is perfectly reasonble to override this - default. - """ - - if source == FeatureRequestError: - return - - self.show_message(self.default_error_message, msg_type=MessageType.Error) - - def thread(self) -> Callable[[F], F]: - """Decorator that mark function to execute it in a thread.""" - return self.lsp.thread() - - def unregister_capability( - self, - params: UnregistrationParams, - callback: Optional[Callable[[], None]] = None, - ) -> Future: - """Unregister a new capability on the client.""" - return self.lsp.unregister_capability(params, callback) - - def unregister_capability_async( - self, params: UnregistrationParams - ) -> asyncio.Future: - """Unregister a new capability on the client. Should be called with `await`""" - return self.lsp.unregister_capability_async(params) - - @property - def workspace(self) -> Workspace: - """Returns in-memory workspace.""" - return self.lsp.workspace + return self._thread_pool diff --git a/server/libs/pygls/uris.py b/server/libs/pygls/uris.py index 8c40f70..b0c34f1 100644 --- a/server/libs/pygls/uris.py +++ b/server/libs/pygls/uris.py @@ -21,6 +21,8 @@ A collection of URI utilities with logic built on the VSCode URI library. https://github.com/Microsoft/vscode-uri/blob/e59cab84f5df6265aed18ae5f43552d3eef13bb9/lib/index.ts """ +from __future__ import annotations + from typing import Optional, Tuple import re @@ -75,20 +77,22 @@ def from_fs_path(path: str): return None -def to_fs_path(uri: str): +def to_fs_path(uri: str) -> str | None: """ Returns the filesystem path of the given URI. Will handle UNC paths and normalize windows drive letters to lower-case. Also uses the platform specific path separator. Will *not* validate the path for invalid characters and semantics. - Will *not* look at the scheme of this URI. """ try: # scheme://netloc/path;parameters?query#fragment scheme, netloc, path, _, _, _ = urlparse(uri) - if netloc and path and scheme == "file": + if scheme != "file": + return None + + if netloc and path: # unc path: file://shares/c$/far/boo value = f"//{netloc}{path}" diff --git a/server/libs/pygls/workspace/__init__.py b/server/libs/pygls/workspace/__init__.py index 53e9b1f..73a56dc 100644 --- a/server/libs/pygls/workspace/__init__.py +++ b/server/libs/pygls/workspace/__init__.py @@ -1,97 +1,11 @@ -from typing import List -import warnings - -from lsprotocol import types - from .workspace import Workspace from .text_document import TextDocument -from .position_codec import PositionCodec - -# For backwards compatibility -Document = TextDocument - - -def utf16_unit_offset(chars: str): - warnings.warn( - "'utf16_unit_offset' has been deprecated, instead use " - "'PositionCodec.utf16_unit_offset' via 'workspace.position_codec' " - "or 'text_document.position_codec'", - DeprecationWarning, - stacklevel=2, - ) - _codec = PositionCodec() - return _codec.utf16_unit_offset(chars) - - -def utf16_num_units(chars: str): - warnings.warn( - "'utf16_num_units' has been deprecated, instead use " - "'PositionCodec.client_num_units' via 'workspace.position_codec' " - "or 'text_document.position_codec'", - DeprecationWarning, - stacklevel=2, - ) - _codec = PositionCodec() - return _codec.client_num_units(chars) - - -def position_from_utf16(lines: List[str], position: types.Position): - warnings.warn( - "'position_from_utf16' has been deprecated, instead use " - "'PositionCodec.position_from_client_units' via " - "'workspace.position_codec' or 'text_document.position_codec'", - DeprecationWarning, - stacklevel=2, - ) - _codec = PositionCodec() - return _codec.position_from_client_units(lines, position) - - -def position_to_utf16(lines: List[str], position: types.Position): - warnings.warn( - "'position_to_utf16' has been deprecated, instead use " - "'PositionCodec.position_to_client_units' via " - "'workspace.position_codec' or 'text_document.position_codec'", - DeprecationWarning, - stacklevel=2, - ) - _codec = PositionCodec() - return _codec.position_to_client_units(lines, position) - - -def range_from_utf16(lines: List[str], range: types.Range): - warnings.warn( - "'range_from_utf16' has been deprecated, instead use " - "'PositionCodec.range_from_client_units' via " - "'workspace.position_codec' or 'text_document.position_codec'", - DeprecationWarning, - stacklevel=2, - ) - _codec = PositionCodec() - return _codec.range_from_client_units(lines, range) - - -def range_to_utf16(lines: List[str], range: types.Range): - warnings.warn( - "'range_to_utf16' has been deprecated, instead use " - "'PositionCodec.range_to_client_units' via 'workspace.position_codec' " - "or 'text_document.position_codec'", - DeprecationWarning, - stacklevel=2, - ) - _codec = PositionCodec() - return _codec.range_to_client_units(lines, range) - +from .position_codec import PositionCodec, ServerTextPosition, ServerTextRange __all__ = ( "Workspace", "TextDocument", "PositionCodec", - "Document", - "utf16_unit_offset", - "utf16_num_units", - "position_from_utf16", - "position_to_utf16", - "range_from_utf16", - "range_to_utf16", + "ServerTextPosition", + "ServerTextRange", ) diff --git a/server/libs/pygls/workspace/position_codec.py b/server/libs/pygls/workspace/position_codec.py index b182c62..b8affc4 100644 --- a/server/libs/pygls/workspace/position_codec.py +++ b/server/libs/pygls/workspace/position_codec.py @@ -17,14 +17,113 @@ # limitations under the License. # ############################################################################ import logging -from typing import List, Optional, Union +from dataclasses import dataclass +from typing import Optional, Union, Sequence, Any from lsprotocol import types - log = logging.getLogger(__name__) +@dataclass(order=True) +class ServerTextPosition: + line: int + character: int + + def __repr__(self) -> str: + return f"{self.line}:{self.character}" + + +@dataclass +class ServerTextRange: + start: ServerTextPosition + end: ServerTextPosition + + def __repr__(self): + return f"{self.start}-{self.end}" + + def __contains__(self, position: Any) -> bool: + if not isinstance(position, ServerTextPosition): + raise TypeError("ServerTextRanges can only contain ServerTextPositions.") + return self.start <= position <= self.end + + def includes(self, inner: "ServerTextRange") -> bool: + """ + Returns whether `inner` is entirely contained within self, i.e. all + positions in `inner` are also in `self`. + """ + return self.start <= inner.start and inner.end <= self.end + + def overlaps(self, other: "ServerTextRange") -> bool: + """ + Returns whether `self` and `other` overlap, i.e. any positions exist that + are included in both self and other. + """ + return self.start <= other.end and other.start <= self.end + + +class UnitCounter: + def code_units_for_char(self, char: str) -> int: + """ + Get the number of code units used to encode the given single character. + """ + raise NotImplementedError + + def num_units(self, chars: str) -> int: + """ + Get the number of code units used to encode the given string. + """ + return sum(self.code_units_for_char(c) for c in chars) + + def column_from_utf32(self, line: str, column: int) -> int: + """ + Convert the codepoint index `column` into code units. + """ + return sum(self.code_units_for_char(c) for c in line[:column]) + + +class Utf32(UnitCounter): + def code_units_for_char(self, char: str) -> int: + return 1 + + def num_units(self, chars: str) -> int: + # We can avoid the loop needed for other encodings here + return len(chars) + + def column_from_utf32(self, line: str, column: int) -> int: + return column + + +def is_beyond_basic_multilingual_plane(char: str) -> bool: + return ord(char) > 0xFFFF + + +class Utf16(UnitCounter): + def code_units_for_char(self, char: str) -> int: + if is_beyond_basic_multilingual_plane(char): + return 2 + return 1 + + +class Utf8(UnitCounter): + def code_units_for_char(self, char: str) -> int: + codepoint = ord(char) + if codepoint < 0x80: + return 1 + if codepoint < 0x800: + return 2 + if codepoint < 0x10000: + return 3 + return 4 + + +impls: dict["str | types.PositionEncodingKind | None", UnitCounter] = { + types.PositionEncodingKind.Utf8: Utf8(), + types.PositionEncodingKind.Utf16: Utf16(), + types.PositionEncodingKind.Utf32: Utf32(), +} + + class PositionCodec: def __init__( self, @@ -33,39 +132,17 @@ class PositionCodec: ] = types.PositionEncodingKind.Utf16, ): self.encoding = encoding + self.impl = impls.get(encoding, Utf16()) - @classmethod - def is_char_beyond_multilingual_plane(cls, char: str) -> bool: - return ord(char) > 0xFFFF + def __repr__(self): + return f"<{self.__class__.__name__}, encoding {self.encoding}>" - def utf16_unit_offset(self, chars: str): - """ - Calculate the number of characters which need two utf-16 code units. - - Arguments: - chars (str): The string to count occurrences of utf-16 code units for. - """ - return sum(self.is_char_beyond_multilingual_plane(ch) for ch in chars) - - def client_num_units(self, chars: str): - """ - Calculate the length of `str` in client-supported UTF-[32|16|8] code units. - - Arguments: - chars (str): The string to return the length in UTF-[32|16|8] code units for. - """ - utf32_units = len(chars) - if self.encoding == types.PositionEncodingKind.Utf32: - return utf32_units - - if self.encoding == types.PositionEncodingKind.Utf8: - return utf32_units + (self.utf16_unit_offset(chars) * 2) - - return utf32_units + self.utf16_unit_offset(chars) + def client_num_units(self, string: str): + return self.impl.num_units(string) def position_from_client_units( - self, lines: List[str], position: types.Position - ) -> types.Position: + self, lines: Sequence[str], position: types.Position + ) -> ServerTextPosition: """ Convert the position.character from UTF-[32|16|8] code units to UTF-32. @@ -84,7 +161,7 @@ class PositionCodec: see: https://github.com/microsoft/language-server-protocol/issues/376 Arguments: - lines (list): + lines (sequence): The content of the document which the position refers to. position (Position): The line and character offset in UTF-[32|16|8] code units. @@ -93,59 +170,42 @@ class PositionCodec: The position with `character` being converted to UTF-32 code units. """ if len(lines) == 0: - return types.Position(0, 0) + return ServerTextPosition(0, 0) if position.line >= len(lines): - return types.Position(len(lines) - 1, self.client_num_units(lines[-1])) + return ServerTextPosition(len(lines) - 1, self.impl.num_units(lines[-1])) _line = lines[position.line] _line = _line.replace("\r\n", "\n") # TODO: it's a bit of a hack - _client_len = self.client_num_units(_line) - _utf32_len = len(_line) + _client_len = self.impl.num_units(_line) if _client_len == 0: - return types.Position(position.line, 0) + return ServerTextPosition(position.line, 0) - _client_end_of_line = self.client_num_units(_line) - if position.character > _client_end_of_line: - position.character = _client_end_of_line - 1 + if position.character > _client_len: + position.character = _client_len - 1 - _client_index = 0 + client_position = 0 utf32_index = 0 - while True: - _is_searching_queried_position = _client_index < position.character - _is_before_end_of_line = utf32_index < _utf32_len - _is_searching_for_position = ( - _is_searching_queried_position and _is_before_end_of_line - ) - if not _is_searching_for_position: + for c in _line: + if client_position >= position.character: break - - _current_char = _line[utf32_index] - _is_double_width = PositionCodec.is_char_beyond_multilingual_plane( - _current_char - ) - if _is_double_width: - if self.encoding == types.PositionEncodingKind.Utf32: - _client_index += 1 - if self.encoding == types.PositionEncodingKind.Utf8: - _client_index += 4 - _client_index += 2 - else: - _client_index += 1 + client_position += self.impl.code_units_for_char(c) utf32_index += 1 - position = types.Position(line=position.line, character=utf32_index) - return position + if client_position < position.character: + utf32_index = len(_line) + + return ServerTextPosition(line=position.line, character=utf32_index) def position_to_client_units( - self, lines: List[str], position: types.Position + self, lines: Sequence[str], position: "ServerTextPosition | types.Position" ) -> types.Position: """ Convert the position.character from its internal UTF-32 representation to client-supported UTF-[32|16|8] code units. Arguments: - lines (list): + lines (sequence): The content of the document which the position refers to. position (Position): The line and character offset in UTF-32 code units. @@ -154,9 +214,7 @@ class PositionCodec: The position with `character` being converted to UTF-[32|16|8] code units. """ try: - character = self.client_num_units( - lines[position.line][: position.character] - ) + character = self.impl.num_units(lines[position.line][: position.character]) return types.Position( line=position.line, character=character, @@ -165,13 +223,13 @@ class PositionCodec: return types.Position(line=len(lines), character=0) def range_from_client_units( - self, lines: List[str], range: types.Range - ) -> types.Range: + self, lines: Sequence[str], range: types.Range + ) -> ServerTextRange: """ Convert range.[start|end].character from UTF-[32|16|8] code units to UTF-32. Arguments: - lines (list): + lines (sequence): The content of the document which the range refers to. range (Range): The line and character offset in UTF-[32|16|8] code units. @@ -179,26 +237,25 @@ class PositionCodec: Returns: The range with `character` offsets being converted to UTF-32 code units. """ - range_new = types.Range( + return ServerTextRange( start=self.position_from_client_units(lines, range.start), end=self.position_from_client_units(lines, range.end), ) - return range_new def range_to_client_units( - self, lines: List[str], range: types.Range + self, lines: Sequence[str], range: "ServerTextRange | types.Range" ) -> types.Range: """ Convert range.[start|end].character from UTF-32 to UTF-[32|16|8] code units. Arguments: - lines (list): + lines (sequence): The content of the document which the range refers to. range (Range): - The line and character offset in code units. + The line and character offset in code points. Returns: - The range with `character` offsets being converted to UTF-[32|16|8] code units. + The range with `character` offsets converted to UTF-[32|16|8] code units. """ return types.Range( start=self.position_to_client_units(lines, range.start), diff --git a/server/libs/pygls/workspace/text_document.py b/server/libs/pygls/workspace/text_document.py index d62c6aa..7f90186 100644 --- a/server/libs/pygls/workspace/text_document.py +++ b/server/libs/pygls/workspace/text_document.py @@ -19,13 +19,14 @@ import io import logging import os +import pathlib import re -from typing import List, Optional, Pattern +from typing import Optional, Pattern, Sequence from lsprotocol import types -from pygls.uris import to_fs_path -from .position_codec import PositionCodec +from pygls.uris import urlparse, to_fs_path +from .position_codec import PositionCodec, ServerTextPosition, ServerTextRange # TODO: this is not the best e.g. we capture numbers RE_END_WORD = re.compile("^[A-Za-z_0-9]*") @@ -47,9 +48,10 @@ class TextDocument(object): ): self.uri = uri self.version = version - path = to_fs_path(uri) - if path is None: - raise Exception("`path` cannot be None") + + if (path := to_fs_path(uri)) is None: + _, _, path, *_ = urlparse(uri) + self.path = path self.language_id = language_id self.filename: Optional[str] = os.path.basename(self.path) @@ -73,7 +75,7 @@ class TextDocument(object): return self._position_codec def _apply_incremental_change( - self, change: types.TextDocumentContentChangeEvent_Type1 + self, change: types.TextDocumentContentChangePartial ) -> None: """Apply an ``Incremental`` text change to the document""" lines = self.lines @@ -142,7 +144,7 @@ class TextDocument(object): content update client requests in the pygls Python library. """ - if isinstance(change, types.TextDocumentContentChangeEvent_Type1): + if isinstance(change, types.TextDocumentContentChangePartial): if self._is_sync_kind_incremental: self._apply_incremental_change(change) return @@ -161,26 +163,101 @@ class TextDocument(object): self._apply_full_change(change) @property - def lines(self) -> List[str]: - return self.source.splitlines(True) + def lines(self) -> Sequence[str]: + return tuple(self.source.splitlines(True)) + + def offset_at_server_position(self, server_position: ServerTextPosition) -> int: + """ + Convert server_position to an index into self.source. + + The index is the number of code points preceding the client_position in self.source. + """ + row, col = server_position.line, server_position.character + return col + sum(len(line) for line in self.lines[:row]) def offset_at_position(self, client_position: types.Position) -> int: - """Return the character offset pointed at by the given client_position.""" + """ + Convert client_position to an index into self.source. + + The index is the number of code points preceding the client_position in self.source. + + Example in a code action request handler: + selected_string = document.source[ + document.offset_at_position(params.range.start) : document.offset_at_position(params.range.end) + ] + """ lines = self.lines server_position = self._position_codec.position_from_client_units( lines, client_position ) - row, col = server_position.line, server_position.character - return col + sum( - self._position_codec.client_num_units(line) for line in lines[:row] - ) + return self.offset_at_server_position(server_position) + + def server_position_at_offset(self, offset: int) -> ServerTextPosition: + """ + Convert a numeric character offset (index into self.source) into a line-column position. + """ + remaining_offset = offset + for lineno, line in enumerate(self.lines): + if remaining_offset < len(line): + return ServerTextPosition(lineno, remaining_offset) + remaining_offset -= len(line) + # The desired position is beyond the end of the last line. + return ServerTextPosition(lineno + 1, 0) + + def client_position_at_offset(self, offset: int) -> types.Position: + """ + Convert a numeric character offset (index into self.source) into a line-column position in client units. + """ + return self.position_to_client_units(self.server_position_at_offset(offset)) + + def range_from_client_units(self, range: types.Range) -> ServerTextRange: + """ + Convert a range from client units into code points, suitable for indexing into `self.lines`. + """ + return self.position_codec.range_from_client_units(self.lines, range) + + def position_from_client_units( + self, position: types.Position + ) -> ServerTextPosition: + """ + Convert a position from client units into code points, suitable for indexing into `self.lines`. + """ + return self.position_codec.position_from_client_units(self.lines, position) + + def range_to_client_units(self, range: ServerTextRange) -> types.Range: + """ + Convert a range from code points into client units, suitable for sending to the client. + """ + return self.position_codec.range_to_client_units(self.lines, range) + + def position_to_client_units(self, position: ServerTextPosition) -> types.Position: + """ + Convert a position from code points into client units, suitable for sending to the client. + """ + return self.position_codec.position_to_client_units(self.lines, position) + + def text_in_client_range(self, range: types.Range) -> str: + """ + Given a range in client units, return the text in this range in this document. + """ + return self.text_in_server_range(self.range_from_client_units(range)) + + def text_in_server_range(self, range: ServerTextRange) -> str: + """ + Given a range in server units, return the text in this range in this document. + """ + return self.source[ + self.offset_at_server_position( + range.start + ) : self.offset_at_server_position(range.end) + ] @property def source(self) -> str: - if self._source is None: - with io.open(self.path, "r", encoding="utf-8") as f: - return f.read() - return self._source + if self._source is None and self.path is not None: + return pathlib.Path(self.path).read_text(encoding="utf-8") + + return self._source or "" def word_at_position( self, diff --git a/server/libs/pygls/workspace/workspace.py b/server/libs/pygls/workspace/workspace.py index 405a798..4f16120 100644 --- a/server/libs/pygls/workspace/workspace.py +++ b/server/libs/pygls/workspace/workspace.py @@ -19,8 +19,8 @@ import copy import logging import os -import warnings -from typing import Dict, List, Optional, Union +from typing import Dict, Optional, Sequence, Union +from urllib.parse import unquote from lsprotocol import types from lsprotocol.types import ( @@ -40,7 +40,7 @@ class Workspace(object): self, root_uri: Optional[str], sync_kind: TextDocumentSyncKind = TextDocumentSyncKind.Incremental, - workspace_folders: Optional[List[WorkspaceFolder]] = None, + workspace_folders: Optional[Sequence[WorkspaceFolder]] = None, position_encoding: Optional[ Union[PositionEncodingKind, str] ] = PositionEncodingKind.Utf16, @@ -48,10 +48,7 @@ class Workspace(object): self._root_uri = root_uri if self._root_uri is not None: self._root_uri_scheme = uri_scheme(self._root_uri) - root_path = to_fs_path(self._root_uri) - if root_path is None: - raise Exception("Couldn't get `root_path` from `root_uri`") - self._root_path = root_path + self._root_path = to_fs_path(self._root_uri) else: self._root_path = None self._sync_kind = sync_kind @@ -94,17 +91,7 @@ class Workspace(object): ) def add_folder(self, folder: WorkspaceFolder): - self._folders[folder.uri] = folder - - @property - def documents(self): - warnings.warn( - "'workspace.documents' has been deprecated, use " - "'workspace.text_documents' instead", - DeprecationWarning, - stacklevel=2, - ) - return self.text_documents + self._folders[unquote(folder.uri)] = folder @property def notebook_documents(self): @@ -141,10 +128,10 @@ class Workspace(object): The requested notebook document if found, ``None`` otherwise. """ if notebook_uri is not None: - return self._notebook_documents.get(notebook_uri) + return self._notebook_documents.get(unquote(notebook_uri)) if cell_uri is not None: - notebook_uri = self._cell_in_notebook.get(cell_uri) + notebook_uri = self._cell_in_notebook.get(unquote(cell_uri)) if notebook_uri is None: return None @@ -159,18 +146,25 @@ class Workspace(object): See https://github.com/Microsoft/language-server-protocol/issues/177 """ - return self._text_documents.get(doc_uri) or self._create_text_document(doc_uri) + return self._text_documents.get(unquote(doc_uri)) or self._create_text_document( + doc_uri + ) def is_local(self): - return ( - self._root_uri_scheme == "" or self._root_uri_scheme == "file" - ) and os.path.exists(self._root_path) + + if self._root_uri_scheme not in {"", "file"}: + return False + + if (path := self._root_path) is None: + return False + + return os.path.exists(path) def put_notebook_document(self, params: types.DidOpenNotebookDocumentParams): notebook = params.notebook_document # Create a fresh instance to ensure our copy cannot be accidentally modified. - self._notebook_documents[notebook.uri] = copy.deepcopy(notebook) + self._notebook_documents[unquote(notebook.uri)] = copy.deepcopy(notebook) for cell_document in params.cell_text_documents: self.put_text_document(cell_document, notebook_uri=notebook.uri) @@ -193,7 +187,7 @@ class Workspace(object): """ doc_uri = text_document.uri - self._text_documents[doc_uri] = self._create_text_document( + self._text_documents[unquote(doc_uri)] = self._create_text_document( doc_uri, source=text_document.text, version=text_document.version, @@ -201,23 +195,23 @@ class Workspace(object): ) if notebook_uri: - self._cell_in_notebook[doc_uri] = notebook_uri + self._cell_in_notebook[unquote(doc_uri)] = unquote(notebook_uri) def remove_notebook_document(self, params: types.DidCloseNotebookDocumentParams): notebook_uri = params.notebook_document.uri - self._notebook_documents.pop(notebook_uri, None) + self._notebook_documents.pop(unquote(notebook_uri), None) for cell_document in params.cell_text_documents: self.remove_text_document(cell_document.uri) def remove_text_document(self, doc_uri: str): - self._text_documents.pop(doc_uri, None) - self._cell_in_notebook.pop(doc_uri, None) + self._text_documents.pop(unquote(doc_uri), None) + self._cell_in_notebook.pop(unquote(doc_uri), None) def remove_folder(self, folder_uri: str): - self._folders.pop(folder_uri, None) + self._folders.pop(unquote(folder_uri), None) try: - del self._folders[folder_uri] + del self._folders[unquote(folder_uri)] except KeyError: pass @@ -231,7 +225,7 @@ class Workspace(object): def update_notebook_document(self, params: types.DidChangeNotebookDocumentParams): uri = params.notebook_document.uri - notebook = self._notebook_documents[uri] + notebook = self._notebook_documents[unquote(uri)] notebook.version = params.notebook_document.version if params.change.metadata: @@ -283,41 +277,5 @@ class Workspace(object): change: types.TextDocumentContentChangeEvent, ): doc_uri = text_doc.uri - self._text_documents[doc_uri].apply_change(change) - self._text_documents[doc_uri].version = text_doc.version - - def get_document(self, *args, **kwargs): - warnings.warn( - "'workspace.get_document' has been deprecated, use " - "'workspace.get_text_document' instead", - DeprecationWarning, - stacklevel=2, - ) - return self.get_text_document(*args, **kwargs) - - def remove_document(self, *args, **kwargs): - warnings.warn( - "'workspace.remove_document' has been deprecated, use " - "'workspace.remove_text_document' instead", - DeprecationWarning, - stacklevel=2, - ) - return self.remove_text_document(*args, **kwargs) - - def put_document(self, *args, **kwargs): - warnings.warn( - "'workspace.put_document' has been deprecated, use " - "'workspace.put_text_document' instead", - DeprecationWarning, - stacklevel=2, - ) - return self.put_text_document(*args, **kwargs) - - def update_document(self, *args, **kwargs): - warnings.warn( - "'workspace.update_document' has been deprecated, use " - "'workspace.update_text_document' instead", - DeprecationWarning, - stacklevel=2, - ) - return self.update_text_document(*args, **kwargs) + self._text_documents[unquote(doc_uri)].apply_change(change) + self._text_documents[unquote(doc_uri)].version = text_doc.version diff --git a/server/libs/tclint-0.8.0.dist-info/INSTALLER b/server/libs/tclint-0.9.0.dist-info/INSTALLER similarity index 100% rename from server/libs/tclint-0.8.0.dist-info/INSTALLER rename to server/libs/tclint-0.9.0.dist-info/INSTALLER diff --git a/server/libs/tclint-0.8.0.dist-info/METADATA b/server/libs/tclint-0.9.0.dist-info/METADATA similarity index 99% rename from server/libs/tclint-0.8.0.dist-info/METADATA rename to server/libs/tclint-0.9.0.dist-info/METADATA index 2865849..a880889 100644 --- a/server/libs/tclint-0.8.0.dist-info/METADATA +++ b/server/libs/tclint-0.9.0.dist-info/METADATA @@ -1,6 +1,6 @@ Metadata-Version: 2.4 Name: tclint -Version: 0.8.0 +Version: 0.9.0 Summary: A CLI utility for linting and analyzing Tcl code. Author-email: Noah Moroze License: MIT License diff --git a/server/libs/tclint-0.8.0.dist-info/RECORD b/server/libs/tclint-0.9.0.dist-info/RECORD similarity index 59% rename from server/libs/tclint-0.8.0.dist-info/RECORD rename to server/libs/tclint-0.9.0.dist-info/RECORD index b96e4dc..54b09cf 100644 --- a/server/libs/tclint-0.8.0.dist-info/RECORD +++ b/server/libs/tclint-0.9.0.dist-info/RECORD @@ -1,17 +1,17 @@ bin/tclfmt.exe,sha256=5o9LOeyU_bfji3TOEQ2sDsjitSg-ZAQISI2LSX9MrCg,47104 bin/tclint.exe,sha256=0rGm-shW-XmBQ_KQkCJvGa9Qe1GCHvErXuL6C1D_kjc,47104 bin/tclsp.exe,sha256=K9fidz6r40fs43dAcfHVRE8RkH7W0dtQxX42EpMBp6I,47104 -tclint-0.8.0.dist-info/INSTALLER,sha256=5hhM4Q4mYTT9z6QB6PGpUAW81PGNFrYrdXMj4oM_6ak,2 -tclint-0.8.0.dist-info/METADATA,sha256=QiY1JEN7FiNRwRYDcqb2OqYucGyVl5ddIZIm1vC3WQ0,4015 -tclint-0.8.0.dist-info/RECORD,, -tclint-0.8.0.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -tclint-0.8.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91 -tclint-0.8.0.dist-info/entry_points.txt,sha256=K2vcacREnbnOEZvE7-QfzsmF9vazrD7HgM2WmTl_Wgs,161 -tclint-0.8.0.dist-info/licenses/LICENSE,sha256=PGii0wulXro34f25070gTG-JRGM-TAyXyKVObnNJU68,1055 -tclint-0.8.0.dist-info/top_level.txt,sha256=_cnnEELsoakzUgD9HHdivUoNbpKG9tUGznWvbGLmHQM,7 +tclint-0.9.0.dist-info/INSTALLER,sha256=5hhM4Q4mYTT9z6QB6PGpUAW81PGNFrYrdXMj4oM_6ak,2 +tclint-0.9.0.dist-info/METADATA,sha256=apRNFWLq_33SxthxLCUFZfaGZjz2AGucxFQYS7782u4,4015 +tclint-0.9.0.dist-info/RECORD,, +tclint-0.9.0.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +tclint-0.9.0.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91 +tclint-0.9.0.dist-info/entry_points.txt,sha256=K2vcacREnbnOEZvE7-QfzsmF9vazrD7HgM2WmTl_Wgs,161 +tclint-0.9.0.dist-info/licenses/LICENSE,sha256=PGii0wulXro34f25070gTG-JRGM-TAyXyKVObnNJU68,1055 +tclint-0.9.0.dist-info/top_level.txt,sha256=_cnnEELsoakzUgD9HHdivUoNbpKG9tUGznWvbGLmHQM,7 tclint/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 tclint/__main__.py,sha256=Bp_AE4xH3XNsUq3EHISWdLOFUbdvwnZ6YSf3F1NIqWU,65 -tclint/_version.py,sha256=Rttl-BDadtcW1QzGnNffCWA_Wc9mUKDMOBPZp--Mnsc,704 +tclint/_version.py,sha256=kSrltAJmP76cnQArqSQbTZHSYAIDCyFeWzh2SIC99Q4,520 tclint/checks.py,sha256=wr29RqWd8zuF9gy5YBWjkZs1WQ91pj9ipkfdsxVuDvg,7863 tclint/cli/resolver.py,sha256=kDvSvbQiqk_Dhd7zBkiUrSDkplr02uhdZ6k3CFj6geg,3750 tclint/cli/tclfmt.py,sha256=8_d7TGmV8gU6VfRhxjFxmlTDt1zBmKtk3016CvdnpXo,6949 @@ -19,16 +19,16 @@ tclint/cli/tclint.py,sha256=CTmchC3iL-dEM0paeRVEKJf79cEnUh7_QAQ7c17UAd0,4548 tclint/cli/tclsp.py,sha256=TvBA0K2_6CkRKgHXiTSFIDcNykOhH-qHOox7qQABMaY,18051 tclint/cli/utils.py,sha256=qa1tJ3St0uC9f4yAKCC4atglu8R3fZYVxu-KZ0dqTAo,1926 tclint/commands/__init__.py,sha256=u0zk3di692M1QSZGvOEM7ZYzKBB7r950ytAS8cxmEo0,113 -tclint/commands/builtin.py,sha256=XO0z4lX6rbEIpjZIEJ5-nGc0mX8a8VZxpAmOTCNIGSA,41587 -tclint/commands/checks.py,sha256=7SkderCq_M36XbOJbNw5ZDKt1XXlmT4ErAG4K8eY4-k,14133 +tclint/commands/builtin.py,sha256=WFgDdZzgTogALwbLAHgqt2fGOY1rX5Ukyzc4yCvvbQ4,41938 +tclint/commands/checks.py,sha256=TOgJ78ngCgkvOCBhHnbsz4Q67R9hWeQAdaNNNJ8L5KA,16757 tclint/commands/plugins.py,sha256=Q-FqS3h-D6m0lWzdMH5WFSEF19Ol2vTgPySb2ydCg5Q,5407 -tclint/commands/schema.py,sha256=nzgPuyQviWZYn1FZYzKs1kGixvIu0RF2GUoXzd3iaLg,1123 +tclint/commands/schema.py,sha256=_YEtPQfyV4UEO_CRPSYR6zGyB1wgJdfB32DmVNWCq9o,1150 tclint/comments.py,sha256=kCfSdnoSVofvNqs4zxnOrg45shlbVvu-e2hKia6EXhk,3047 tclint/config.py,sha256=d4QUS9XwZuBNGv9ggz0QpD7jbAXmWVBrenKzGjexx-E,15285 -tclint/format.py,sha256=YXX6HRy_AOhcBcJL3Ofo_lAdHtjPAGd0piiVTaGKZzg,21753 +tclint/format.py,sha256=5OgSEki7w7_w1HQ9rCiksTKDX2Ni41ZXTpA7hQ42k9M,23717 tclint/lexer.py,sha256=JnDcYCeT8wCGV1kqjXRVjQDUBw48lWBx_5g_4dt-JLc,6069 tclint/parser.py,sha256=sl7bkhKN253VpBALin8Bd5FtNxRfi5cEy7NFYtvzPpo,28822 tclint/plugins/expect.py,sha256=5fbrwJK3108w20Ib7pvfJhgVNpSW3FTAovlhbspDsIQ,1912 -tclint/symbol_table.py,sha256=vSbE5Cbgb-_ppdjsXOR4WBNqPQXxhf0k-pZMOFe5vU8,1557 -tclint/syntax_tree.py,sha256=kkMtbxUkD1EcLT2bXsV5foDF2W6zAYoxzu-dPZGnBbs,13033 +tclint/symbol_table.py,sha256=jqZli_len0f1nlSi7GF-u45FfK-GvBgXbluBYXCrzLY,1612 +tclint/syntax_tree.py,sha256=msFx3ihey1EtCzaYtZS3ge0cYOECITuHBhyKoUQp1js,13020 tclint/violations.py,sha256=q9y0j1btlMLhy1Pn6HP0u1347d7SF4t3ZVZpIxH3MVc,1232 diff --git a/server/libs/tclint-0.8.0.dist-info/REQUESTED b/server/libs/tclint-0.9.0.dist-info/REQUESTED similarity index 100% rename from server/libs/tclint-0.8.0.dist-info/REQUESTED rename to server/libs/tclint-0.9.0.dist-info/REQUESTED diff --git a/server/libs/tclint-0.8.0.dist-info/WHEEL b/server/libs/tclint-0.9.0.dist-info/WHEEL similarity index 65% rename from server/libs/tclint-0.8.0.dist-info/WHEEL rename to server/libs/tclint-0.9.0.dist-info/WHEEL index 14a883f..1d472b6 100644 --- a/server/libs/tclint-0.8.0.dist-info/WHEEL +++ b/server/libs/tclint-0.9.0.dist-info/WHEEL @@ -1,5 +1,5 @@ Wheel-Version: 1.0 -Generator: setuptools (82.0.1) +Generator: setuptools (83.0.0) Root-Is-Purelib: true Tag: py3-none-any diff --git a/server/libs/tclint-0.8.0.dist-info/entry_points.txt b/server/libs/tclint-0.9.0.dist-info/entry_points.txt similarity index 100% rename from server/libs/tclint-0.8.0.dist-info/entry_points.txt rename to server/libs/tclint-0.9.0.dist-info/entry_points.txt diff --git a/server/libs/tclint-0.8.0.dist-info/licenses/LICENSE b/server/libs/tclint-0.9.0.dist-info/licenses/LICENSE similarity index 100% rename from server/libs/tclint-0.8.0.dist-info/licenses/LICENSE rename to server/libs/tclint-0.9.0.dist-info/licenses/LICENSE diff --git a/server/libs/tclint-0.8.0.dist-info/top_level.txt b/server/libs/tclint-0.9.0.dist-info/top_level.txt similarity index 100% rename from server/libs/tclint-0.8.0.dist-info/top_level.txt rename to server/libs/tclint-0.9.0.dist-info/top_level.txt diff --git a/server/libs/tclint/_version.py b/server/libs/tclint/_version.py index c84591a..9d1ba18 100644 --- a/server/libs/tclint/_version.py +++ b/server/libs/tclint/_version.py @@ -1,5 +1,6 @@ -# file generated by setuptools-scm +# file generated by vcs-versioning # don't change, don't track in version control +from __future__ import annotations __all__ = [ "__version__", @@ -10,25 +11,14 @@ __all__ = [ "commit_id", ] -TYPE_CHECKING = False -if TYPE_CHECKING: - from typing import Tuple - from typing import Union - - VERSION_TUPLE = Tuple[Union[int, str], ...] - COMMIT_ID = Union[str, None] -else: - VERSION_TUPLE = object - COMMIT_ID = object - version: str __version__: str -__version_tuple__: VERSION_TUPLE -version_tuple: VERSION_TUPLE -commit_id: COMMIT_ID -__commit_id__: COMMIT_ID +__version_tuple__: tuple[int | str, ...] +version_tuple: tuple[int | str, ...] +commit_id: str | None +__commit_id__: str | None -__version__ = version = '0.8.0' -__version_tuple__ = version_tuple = (0, 8, 0) +__version__ = version = '0.9.0' +__version_tuple__ = version_tuple = (0, 9, 0) __commit_id__ = commit_id = None diff --git a/server/libs/tclint/commands/builtin.py b/server/libs/tclint/commands/builtin.py index 79824d7..0147e0f 100644 --- a/server/libs/tclint/commands/builtin.py +++ b/server/libs/tclint/commands/builtin.py @@ -573,7 +573,16 @@ def _package_ifneeded(args, parser): def _proc(args, parser): - if len(args) != 3: + required_args = ["name", "args", "body"] + if len(args) < len(required_args): + missing_args = ", ".join(required_args[len(args) :]) + raise CommandArgError( + "missing required" + f" argument{'s' if len(args) < len(required_args) - 1 else ''} for proc:" + f" {missing_args}" + ) + + if len(args) > len(required_args): raise CommandArgError(f"wrong # of args to proc: got {len(args)}, expected 3") # Parse args as list, then iterate over each item to parse arg specifier lists and diff --git a/server/libs/tclint/commands/checks.py b/server/libs/tclint/commands/checks.py index d2b61ba..55f21a8 100644 --- a/server/libs/tclint/commands/checks.py +++ b/server/libs/tclint/commands/checks.py @@ -2,7 +2,8 @@ from __future__ import annotations -from collections.abc import Callable +from collections.abc import Callable, Iterable +from difflib import get_close_matches from typing import TYPE_CHECKING, Optional from tclint.syntax_tree import ArgExpansion, BareWord, BracedWord, Node, QuotedWord @@ -18,6 +19,33 @@ class CommandArgError(Exception): pass +def get_suggestion(value: str | None, candidates: Iterable[str]) -> Optional[str]: + if value is None: + return None + + unique_candidates = sorted({candidate for candidate in candidates if candidate}) + if value in unique_candidates: + unique_candidates.remove(value) + + if not unique_candidates: + return None + + cutoff = 0.85 if len(value) <= 3 else 0.75 + matches = get_close_matches(value, unique_candidates, n=1, cutoff=cutoff) + if not matches: + return None + + return matches[0] + + +def _did_you_mean_suffix(value: str | None, candidates: Iterable[str]) -> str: + suggestion = get_suggestion(value, candidates) + if suggestion is None: + return "" + + return f"; did you mean {suggestion}?" + + def arg_count(args: list[Node], parser: Parser) -> tuple[int, bool]: """Returns the number of arguments in args, taking {*} into account. @@ -83,6 +111,9 @@ def check_count(command, min=None, max=None): def eval(args: list[Node], parser: Parser, command: str) -> list[Node]: + if len(args) == 1: + return [parser.parse_script(args[0])] + if len(args) > 1 and any(isinstance(arg, (QuotedWord, BracedWord)) for arg in args): # Slightly odd restriction, but our syntax tree doesn't have a great way # to handle this case. We require each command argument to correspond to @@ -174,10 +205,19 @@ def check_arg_spec( mapping = map_positionals(positionals, arg_spec["positionals"], command) args = list(args) for arg_i, map_to_spec in zip(positional_args, mapping): + arg = args[arg_i] + if _positional_has_type("script", arg_spec, map_to_spec): - args[arg_i] = parser.parse_script(args[arg_i]) + args[arg_i] = parser.parse_script(arg) elif _positional_has_type("expression", arg_spec, map_to_spec): - args[arg_i] = parser.parse_expression(args[arg_i]) + args[arg_i] = parser.parse_expression(arg) + elif len(map_to_spec) == 1: + positional_spec = arg_spec["positionals"][map_to_spec[0]] + _validate_value( + arg, + positional_spec["value"], + f"{command} {positional_spec['name']}", + ) return args @@ -201,12 +241,18 @@ def dispatch_subcommands( if "" in spec: return check_command(command, args, parser, spec[""]) + valid_subcommands = [name for name in spec.keys() if name != ""] + if subcommand is not None: msg = f"invalid subcommand for {command}: got {subcommand}" + suggestion = _did_you_mean_suffix(subcommand, valid_subcommands) else: msg = f"no subcommand provided for {command}" + suggestion = "" - raise CommandArgError(f"{msg}, expected one of {', '.join(spec.keys())}") + raise CommandArgError( + f"{msg}, expected one of {', '.join(valid_subcommands)}{suggestion}" + ) def map_switches( @@ -250,17 +296,23 @@ def map_switches( continue if contents in switches: - if contents in mapped and not switches[contents]["repeated"]: + switch_spec = switches[contents] + + if contents in mapped and not switch_spec["repeated"]: raise CommandArgError( f"duplicate argument for {command_name}: {contents}" ) - if switches[contents]["value"]: + if switch_spec["value"]: arg_i += 1 if arg_i > len(args): + expected = _switch_value_description(switch_spec) raise CommandArgError( - f"invalid arguments for {command_name}: expected value after" - f" {contents}" + f"invalid arguments for {command_name}: expected" + f" {expected} after {contents}" ) + _validate_value( + args[arg_i - 1], switch_spec["value"], f"{command_name} {contents}" + ) mapped.add(contents) continue @@ -281,11 +333,52 @@ def map_switches( f" {', '.join(prefix_matches)}" ) - raise CommandArgError(f"unrecognized argument for {command_name}: {contents}") + raise CommandArgError( + f"unrecognized argument for {command_name}: {contents}" + f"{_did_you_mean_suffix(contents, switches.keys())}" + ) return mapped, positional_args +def _switch_value_description(switch_spec: dict) -> str: + metavar = switch_spec.get("metavar") + if metavar is not None: + return metavar + + value_spec = switch_spec.get("value") + if value_spec is None: + return "value" + + value_type = value_spec.get("type") + if value_type == "int": + return "int value" + + return "value" + + +def _validate_value(arg: Node, value_spec: dict | None, context: str) -> None: + if value_spec is None: + return + + contents = arg.contents + if contents is None: + return + + value_type = value_spec.get("type") + if value_type in {"any", "variadic", "script", "expression"}: + return + + if value_type == "int": + try: + int(contents, 0) + return + except ValueError as error: + raise CommandArgError( + f"invalid value for {context}: got {contents}, expected {value_type}" + ) from error + + def map_positionals( args: list[Node], spec: list[dict], command_name: str ) -> list[list[int]]: diff --git a/server/libs/tclint/commands/schema.py b/server/libs/tclint/commands/schema.py index c807f45..ca57254 100644 --- a/server/libs/tclint/commands/schema.py +++ b/server/libs/tclint/commands/schema.py @@ -2,6 +2,15 @@ from collections.abc import Callable from voluptuous import Optional, Or, Schema, Self +_switch_value = Or({"type": "any"}, {"type": "int"}, None) +_positional_value = Or( + {"type": "any"}, + {"type": "int"}, + {"type": "variadic"}, + {"type": "script"}, + {"type": "expression"}, +) + # Need to define this as a Schema with required=True to ensure that this requirement # persists through the Or in the main schema definition. _command_args = Schema( @@ -10,19 +19,14 @@ _command_args = Schema( { "name": str, "required": bool, - "value": Or( - {"type": "any"}, - {"type": "variadic"}, - {"type": "script"}, - {"type": "expression"}, - ), + "value": _positional_value, } ], Optional("switches", default={}): { Optional(str): { "required": bool, "repeated": bool, - "value": Or({"type": "any"}, None), + "value": _switch_value, Optional("metavar"): str, } }, diff --git a/server/libs/tclint/format.py b/server/libs/tclint/format.py index ee4d668..2bb4545 100644 --- a/server/libs/tclint/format.py +++ b/server/libs/tclint/format.py @@ -69,13 +69,15 @@ class Formatter: assert len(debug_char) == 1 if space is None: space = self.opts.indent + elif isinstance(space, int): + space = space * " " if self.opts.debug_whitespace: # Enable this to return a string of debug_char. return len(space) * debug_char return space def get_spaces_in_braces(self, space: tuple[int, int]): - spaces_in_braces = self.space("A", " ") if self.opts.spaces_in_braces else "" + spaces_in_braces = self.space("A", 1) if self.opts.spaces_in_braces else "" if not self.opts.balanced_spaces_in_braces: # No balancing. return spaces_in_braces @@ -88,7 +90,7 @@ class Formatter: if space[0] != -1 and space[1] == -1: # we've got empty braces. Keep "{}" and "{ }" as is, but normalize # more than one space to a single space. - return min(space[0], 1) * self.space("B", " ") + return min(space[0], 1) * self.space("B", 1) # Normalize more than one space to a single space. before = min(space[0], 1) @@ -101,7 +103,7 @@ class Formatter: # Check that we have a balanced expression. assert before == after # Keep either "{1}" or "{ 1 }". - return before * self.space("C", " ") + return before * self.space("C", 1) def _brace(self, lines: list[str], space: tuple[int, int]) -> list[str]: """Format content between braces. @@ -307,6 +309,10 @@ class Formatter: def format_script(self, script: Script, should_indent=True) -> list[str]: lines = self.format_script_contents(script) + if not script.braced: + # Script came from a non-braced word argument (e.g. plugin called + # parse_script on a BareWord). Don't wrap in braces. + return lines if script.pos[0] == script.end_pos[0]: space_before = -1 space_after = -1 @@ -327,7 +333,7 @@ class Formatter: and isinstance(script.children[0], Comment) and script.pos[0] == script.children[0].pos[0] ): - open_brace += self.space("D", " ") + lines[0] + open_brace += self.space("D", 1) + lines[0] lines = lines[1:] if should_indent: @@ -353,14 +359,26 @@ class Formatter: child_lines = self.format(child) if last_line == child.pos[0]: - formatted[-1] += self.space("F", " ") - if self.opts.emacs and child_lines[0][-1] == "\\": - base_indent = (len(formatted[-1])) * self.space("G", " ") - else: - base_indent = "" + formatted[-1] += self.space("F", 1) + base_indent = "" + if self.opts.emacs: + if child_lines[0][-1] == "\\": + base_indent = (len(formatted[-1])) * self.space("G", 1) + elif (isinstance(child, BracedExpression)) and child_lines[ + -1 + ] == "}": + child_lines[1:-1] = self._indent( + child_lines[1:-1], self.space("V", len(formatted[-1])) + ) + elif (isinstance(child, BracedExpression)) and child_lines[-1][ + -1 + ] == "}": + child_lines[1:] = self._indent( + child_lines[1:], self.space("W", len(formatted[-1])) + ) formatted[-1] += child_lines[0] else: - formatted[-1] += self.space("H", " ") + "\\" + formatted[-1] += self.space("H", 1) + "\\" formatted.append(self.space("I") + child_lines[0]) hanging_indent = True @@ -383,13 +401,19 @@ class Formatter: formatted = [] contents = self.format_script_contents(command_sub) if len(command_sub.children) > 1 and len(contents) > 1: - formatted.append("[") - formatted.extend(self._indent(contents, self.space("K"))) - formatted.append("]") + if self.opts.emacs and command_sub.pos[0] == command_sub.children[0].pos[0]: + formatted = contents + formatted[0] = "[" + formatted[0] + formatted[-1] = formatted[-1] + "]" + formatted[1:] = self._indent(formatted[1:], self.space("U", 1)) + else: + formatted.append("[") + formatted.extend(self._indent(contents, self.space("K"))) + formatted.append("]") else: formatted.append("[" + contents[0]) if self.opts.emacs: - indent = self.space("L", " ") + indent = self.space("L", 1) else: indent = "" formatted.extend(self._indent(contents[1:], indent)) @@ -460,7 +484,7 @@ class Formatter: for child in list_node.children: if last_line is not None: if last_line == child.pos[0]: - contents[-1] += self.space("M", " ") + contents[-1] += self.space("M", 1) else: newlines = child.pos[0] - last_line newlines = min(newlines, 3) @@ -516,6 +540,29 @@ class Formatter: space_after = expr.end_pos[1] - expr.children[-1].end_pos[1] - 1 return self._brace(formatted, (space_before, space_after)) + if self.opts.emacs: + pre = [] + post = [] + indent_first = 0 + indent_last = len(formatted) + if expr.pos[0] == expr.children[0].pos[0]: + formatted[0] = "{" + formatted[0] + indent_first = 1 + else: + pre = ["{"] + if expr.end_pos[0] == expr.children[-1].end_pos[0]: + formatted[-1] = formatted[-1] + "}" + else: + post = ["}"] + formatted = ( + pre + + formatted[0:indent_first] + + self._indent(formatted[indent_first:indent_last], self.space("X", 1)) + + formatted[indent_last:] + + post + ) + return formatted + return ["{"] + self._indent(formatted, self.space("P")) + ["}"] def format_paren_expression(self, expr) -> list[str]: @@ -556,7 +603,7 @@ class Formatter: if last.end_pos[0] != next.pos[0]: formatted.extend(lines) else: - formatted[-1] += self.space("R", " ") + formatted[-1] += self.space("R", 1) formatted[-1] += lines[0] formatted.extend(lines[1:]) last = next @@ -585,7 +632,7 @@ class Formatter: formatted.extend(lines) else: if i > 0: - formatted[-1] += self.space("S", " ") + formatted[-1] += self.space("S", 1) formatted[-1] += lines[0] formatted.extend(lines[1:]) last = child diff --git a/server/libs/tclint/symbol_table.py b/server/libs/tclint/symbol_table.py index 414b8a6..d41564d 100644 --- a/server/libs/tclint/symbol_table.py +++ b/server/libs/tclint/symbol_table.py @@ -13,6 +13,9 @@ class SymbolTable: def add_proc_definition(self, command: Command) -> None: """Add definition of procedure""" # command holds the "proc" keyword, so the proc name is 1st argument + if len(command.args) == 0: + return + proc_name_node = command.args[0] proc_name = proc_name_node.contents if not proc_name: diff --git a/server/libs/tclint/syntax_tree.py b/server/libs/tclint/syntax_tree.py index cc11a27..e8577e0 100644 --- a/server/libs/tclint/syntax_tree.py +++ b/server/libs/tclint/syntax_tree.py @@ -253,7 +253,7 @@ class Node: class Script(Node): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - # hack for spaces-in-braces check + # Used by formatter. self.braced = False def accept(self, visitor, recurse=False): diff --git a/server/libs/typing_extensions-4.15.0.dist-info/RECORD b/server/libs/typing_extensions-4.15.0.dist-info/RECORD deleted file mode 100644 index ec54c2e..0000000 --- a/server/libs/typing_extensions-4.15.0.dist-info/RECORD +++ /dev/null @@ -1,7 +0,0 @@ -typing_extensions-4.15.0.dist-info/INSTALLER,sha256=5hhM4Q4mYTT9z6QB6PGpUAW81PGNFrYrdXMj4oM_6ak,2 -typing_extensions-4.15.0.dist-info/METADATA,sha256=wTg3j-jxiTSsmd4GBTXFPsbBOu7WXpTDJkHafuMZKnI,3259 -typing_extensions-4.15.0.dist-info/RECORD,, -typing_extensions-4.15.0.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -typing_extensions-4.15.0.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82 -typing_extensions-4.15.0.dist-info/licenses/LICENSE,sha256=Oy-B_iHRgcSZxZolbI4ZaEVdZonSaaqFNzv7avQdo78,13936 -typing_extensions.py,sha256=Qz0R0XDTok0usGXrwb_oSM6n49fOaFZ6tSvqLUwvftg,160429 diff --git a/server/libs/typing_extensions-4.15.0.dist-info/INSTALLER b/server/libs/typing_extensions-4.16.0.dist-info/INSTALLER similarity index 100% rename from server/libs/typing_extensions-4.15.0.dist-info/INSTALLER rename to server/libs/typing_extensions-4.16.0.dist-info/INSTALLER diff --git a/server/libs/typing_extensions-4.15.0.dist-info/METADATA b/server/libs/typing_extensions-4.16.0.dist-info/METADATA similarity index 97% rename from server/libs/typing_extensions-4.15.0.dist-info/METADATA rename to server/libs/typing_extensions-4.16.0.dist-info/METADATA index b09cb50..97fd818 100644 --- a/server/libs/typing_extensions-4.15.0.dist-info/METADATA +++ b/server/libs/typing_extensions-4.16.0.dist-info/METADATA @@ -1,6 +1,6 @@ Metadata-Version: 2.4 Name: typing_extensions -Version: 4.15.0 +Version: 4.16.0 Summary: Backported and Experimental Type Hints for Python 3.9+ Keywords: annotations,backport,checker,checking,function,hinting,hints,type,typechecking,typehinting,typehints,typing Author-email: "Guido van Rossum, Jukka Lehtosalo, Łukasz Langa, Michael Lee" @@ -19,6 +19,7 @@ Classifier: Programming Language :: Python :: 3.11 Classifier: Programming Language :: Python :: 3.12 Classifier: Programming Language :: Python :: 3.13 Classifier: Programming Language :: Python :: 3.14 +Classifier: Programming Language :: Python :: 3.15 Classifier: Topic :: Software Development License-File: LICENSE Project-URL: Bug Tracker, https://github.com/python/typing_extensions/issues diff --git a/server/libs/typing_extensions-4.16.0.dist-info/RECORD b/server/libs/typing_extensions-4.16.0.dist-info/RECORD new file mode 100644 index 0000000..4c1a0f0 --- /dev/null +++ b/server/libs/typing_extensions-4.16.0.dist-info/RECORD @@ -0,0 +1,7 @@ +typing_extensions-4.16.0.dist-info/INSTALLER,sha256=5hhM4Q4mYTT9z6QB6PGpUAW81PGNFrYrdXMj4oM_6ak,2 +typing_extensions-4.16.0.dist-info/METADATA,sha256=sFCEyh1Qh5hlF42f_5-r6rYb37HzYb-96VQh_8j5vkY,3310 +typing_extensions-4.16.0.dist-info/RECORD,, +typing_extensions-4.16.0.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +typing_extensions-4.16.0.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82 +typing_extensions-4.16.0.dist-info/licenses/LICENSE,sha256=Oy-B_iHRgcSZxZolbI4ZaEVdZonSaaqFNzv7avQdo78,13936 +typing_extensions.py,sha256=QEDKGh7L7gDROFwSqTCE0cW9RvC3dPB-WufpHE9V5pY,165012 diff --git a/server/libs/typing_extensions-4.15.0.dist-info/REQUESTED b/server/libs/typing_extensions-4.16.0.dist-info/REQUESTED similarity index 100% rename from server/libs/typing_extensions-4.15.0.dist-info/REQUESTED rename to server/libs/typing_extensions-4.16.0.dist-info/REQUESTED diff --git a/server/libs/lsprotocol-2023.0.1.dist-info/WHEEL b/server/libs/typing_extensions-4.16.0.dist-info/WHEEL similarity index 71% rename from server/libs/lsprotocol-2023.0.1.dist-info/WHEEL rename to server/libs/typing_extensions-4.16.0.dist-info/WHEEL index 3b5e64b..d8b9936 100644 --- a/server/libs/lsprotocol-2023.0.1.dist-info/WHEEL +++ b/server/libs/typing_extensions-4.16.0.dist-info/WHEEL @@ -1,4 +1,4 @@ Wheel-Version: 1.0 -Generator: flit 3.9.0 +Generator: flit 3.12.0 Root-Is-Purelib: true Tag: py3-none-any diff --git a/server/libs/typing_extensions-4.15.0.dist-info/licenses/LICENSE b/server/libs/typing_extensions-4.16.0.dist-info/licenses/LICENSE similarity index 100% rename from server/libs/typing_extensions-4.15.0.dist-info/licenses/LICENSE rename to server/libs/typing_extensions-4.16.0.dist-info/licenses/LICENSE diff --git a/server/libs/typing_extensions.py b/server/libs/typing_extensions.py index 77f33e1..ced7837 100644 --- a/server/libs/typing_extensions.py +++ b/server/libs/typing_extensions.py @@ -91,6 +91,7 @@ __all__ = [ 'overload', 'override', 'Protocol', + 'sentinel', 'Sentinel', 'reveal_type', 'runtime', @@ -148,7 +149,6 @@ __all__ = [ 'ValuesView', 'cast', 'no_type_check', - 'no_type_check_decorator', ] # for backward compatibility @@ -160,18 +160,122 @@ _PEP_696_IMPLEMENTED = sys.version_info >= (3, 13, 0, "beta") # Added with bpo-45166 to 3.10.1+ and some 3.9 versions _FORWARD_REF_HAS_CLASS = "__forward_is_class__" in typing.ForwardRef.__slots__ + +def _caller(depth=1, default='__main__'): + try: + return sys._getframemodulename(depth + 1) or default + except AttributeError: # For platforms without _getframemodulename() + pass + try: + return sys._getframe(depth + 1).f_globals.get('__name__', default) + except (AttributeError, ValueError): # For platforms without _getframe() + pass + return None + + +# Placeholder for sentinel methods, because sentinels can not have their own sentinels +_sentinel_placeholder = object() + +if hasattr(builtins, "sentinel"): # 3.15+ + sentinel = builtins.sentinel +else: + class sentinel: + """Create a unique sentinel object. + + *name* should be the name of the variable to which the return value + shall be assigned. + """ + + def __init__( + self, + __name: str = _sentinel_placeholder, + __repr: typing.Optional[str] = _sentinel_placeholder, + /, + *, + repr: typing.Optional[str] = None, + name: str = _sentinel_placeholder, + ) -> None: + if name is not _sentinel_placeholder: + warnings.warn( + "Passing 'name' as a keyword argument is deprecated; " + "pass it positionally instead.", + DeprecationWarning, + stacklevel=2, + ) + __name = name + if __name is _sentinel_placeholder: + raise TypeError("First parameter 'name' is required") + if __repr is not _sentinel_placeholder: + warnings.warn( + "Passing 'repr' as a positional argument is deprecated; " + "pass it by keyword instead.", + DeprecationWarning, + stacklevel=2, + ) + repr = __repr + + self._name = __name + self._repr = repr if repr is not None else __name + + # For pickling as a singleton: + self.__module__ = _caller() + + def __init_subclass__(cls): + warnings.warn( + "Subclassing sentinel is deprecated " + "and will be disallowed in Python 3.15", + DeprecationWarning, + stacklevel=2, + ) + super().__init_subclass__() + + def __setattr__(self, attr: str, value: object) -> None: + if attr not in {"_name", "_repr", "__module__"}: + warnings.warn( + f"Setting attribute {attr!r} on sentinel objects is deprecated " + "and will be disallowed in Python 3.15.", + DeprecationWarning, + stacklevel=2, + ) + super().__setattr__(attr, value) + + @property + def __name__(self) -> str: + return self._name + + @__name__.setter + def __name__(self, value: str) -> None: + self._name = value + + def __repr__(self) -> str: + return self._repr + + if sys.version_info < (3, 11): + # The presence of this method convinces typing._type_check + # that Sentinels are types. + def __call__(self, *args, **kwargs): + raise TypeError(f"{type(self).__name__!r} object is not callable") + + # Breakpoint: https://github.com/python/cpython/pull/21515 + if sys.version_info >= (3, 10): + def __or__(self, other): + return typing.Union[self, other] + + def __ror__(self, other): + return typing.Union[other, self] + + def __reduce__(self) -> str: + """Reduce this sentinel to a singleton.""" + return self.__name__ # Module is taken from the __module__ attribute + +Sentinel = sentinel + +_marker = sentinel("sentinel") + + # The functions below are modified copies of typing internal helpers. # They are needed by _ProtocolMeta and they provide support for PEP 646. - -class _Sentinel: - def __repr__(self): - return "" - - -_marker = _Sentinel() - - # Breakpoint: https://github.com/python/cpython/pull/27342 if sys.version_info >= (3, 10): def _should_collect_from_parameters(t): @@ -524,7 +628,9 @@ else: class _SpecialGenericAlias(typing._SpecialGenericAlias, _root=True): - def __init__(self, origin, nparams, *, inst=True, name=None, defaults=()): + def __init__(self, origin, nparams, *, defaults, inst=True, name=None): + assert nparams > 0, "`nparams` must be a positive integer" + assert defaults, "Must always specify a non-empty sequence for `defaults`" super().__init__(origin, nparams, inst=inst, name=name) self._defaults = defaults @@ -542,20 +648,14 @@ else: msg = "Parameters to generic types must be types." params = tuple(typing._type_check(p, msg) for p in params) if ( - self._defaults - and len(params) < self._nparams + len(params) < self._nparams and len(params) + len(self._defaults) >= self._nparams ): params = (*params, *self._defaults[len(params) - self._nparams:]) actual_len = len(params) if actual_len != self._nparams: - if self._defaults: - expected = f"at least {self._nparams - len(self._defaults)}" - else: - expected = str(self._nparams) - if not self._nparams: - raise TypeError(f"{self} is not a generic class") + expected = f"at least {self._nparams - len(self._defaults)}" raise TypeError( f"Too {'many' if actual_len > self._nparams else 'few'}" f" arguments for {self};" @@ -587,10 +687,13 @@ else: _PROTO_ALLOWLIST = { 'collections.abc': [ 'Callable', 'Awaitable', 'Iterable', 'Iterator', 'AsyncIterable', - 'Hashable', 'Sized', 'Container', 'Collection', 'Reversible', 'Buffer', + 'AsyncIterator', 'Hashable', 'Sized', 'Container', 'Collection', + 'Reversible', 'Buffer', ], 'contextlib': ['AbstractContextManager', 'AbstractAsyncContextManager'], + 'io': ['Reader', 'Writer'], 'typing_extensions': ['Buffer'], + 'os': ['PathLike'], } @@ -612,22 +715,12 @@ def _get_protocol_attrs(cls): return attrs -def _caller(depth=1, default='__main__'): - try: - return sys._getframemodulename(depth + 1) or default - except AttributeError: # For platforms without _getframemodulename() - pass - try: - return sys._getframe(depth + 1).f_globals.get('__name__', default) - except (AttributeError, ValueError): # For platforms without _getframe() - pass - return None - - # `__match_args__` attribute was removed from protocol members in 3.13, # we want to backport this change to older Python versions. -# Breakpoint: https://github.com/python/cpython/pull/110683 -if sys.version_info >= (3, 13): +# 3.14 additionally added `io.Reader`, `io.Writer` and `os.PathLike` to +# the list of allowed protocol allowlist. +# https://github.com/python/cpython/issues/127647 +if sys.version_info >= (3, 14): Protocol = typing.Protocol else: def _allow_reckless_class_checks(depth=2): @@ -1038,10 +1131,10 @@ if _NEEDS_SINGLETONMETA: # Update this to something like >=3.13.0b1 if and when -# PEP 728 is implemented in CPython -_PEP_728_IMPLEMENTED = False +# PEP 764 is implemented in CPython +_PEP_764_IMPLEMENTED = False -if _PEP_728_IMPLEMENTED: +if _PEP_764_IMPLEMENTED: # The standard library TypedDict in Python 3.9.0/1 does not honour the "total" # keyword with old-style TypedDict(). See https://bugs.python.org/issue42059 # The standard library TypedDict below Python 3.11 does not store runtime @@ -1051,7 +1144,8 @@ if _PEP_728_IMPLEMENTED: # to enable better runtime introspection. # On 3.13 we deprecate some odd ways of creating TypedDicts. # Also on 3.13, PEP 705 adds the ReadOnly[] qualifier. - # PEP 728 (still pending) makes more changes. + # PEP 728 (Python 3.15+) adds the `extra_items` and `closed` keywords. + # PEP 764 (still pending) allows the `TypedDict` special form to be subscripted. TypedDict = typing.TypedDict _TypedDictMeta = typing._TypedDictMeta is_typeddict = typing.is_typeddict @@ -1155,8 +1249,14 @@ else: if sys.version_info <= (3, 14): annotations.update(base_dict.get('__annotations__', {})) - required_keys.update(base_dict.get('__required_keys__', ())) - optional_keys.update(base_dict.get('__optional_keys__', ())) + base_required = base_dict.get('__required_keys__', set()) + required_keys |= base_required + optional_keys -= base_required + + base_optional = base_dict.get('__optional_keys__', set()) + required_keys -= base_optional + optional_keys |= base_optional + readonly_keys.update(base_dict.get('__readonly_keys__', ())) mutable_keys.update(base_dict.get('__mutable_keys__', ())) @@ -1184,13 +1284,19 @@ else: qualifiers = set(_get_typeddict_qualifiers(annotation_type)) if Required in qualifiers: - required_keys.add(annotation_key) + is_required = True elif NotRequired in qualifiers: - optional_keys.add(annotation_key) - elif total: + is_required = False + else: + is_required = total + + if is_required: required_keys.add(annotation_key) + optional_keys.discard(annotation_key) else: optional_keys.add(annotation_key) + required_keys.discard(annotation_key) + if ReadOnly in qualifiers: mutable_keys.discard(annotation_key) readonly_keys.add(annotation_key) @@ -1798,7 +1904,7 @@ elif hasattr(typing, 'ParamSpec'): paramspec = typing.ParamSpec(name, bound=bound, covariant=covariant, contravariant=contravariant) - paramspec.__infer_variance__ = infer_variance + paramspec.__infer_variance__ = bool(infer_variance) _set_default(paramspec, default) _set_module(paramspec) @@ -1894,10 +2000,7 @@ else: self.__covariant__ = bool(covariant) self.__contravariant__ = bool(contravariant) self.__infer_variance__ = bool(infer_variance) - if bound: - self.__bound__ = typing._type_check(bound, 'Bound must be a type.') - else: - self.__bound__ = None + self.__bound__ = bound _DefaultMixin.__init__(self, default) # for pickling: @@ -1929,6 +2032,9 @@ else: def __call__(self, *args, **kwargs): pass + def __init_subclass__(cls) -> None: + raise TypeError(f"type '{__name__}.ParamSpec' is not an acceptable base type") + # 3.9 if not hasattr(typing, 'Concatenate'): @@ -1956,7 +2062,9 @@ if not hasattr(typing, 'Concatenate'): __class__ = typing._GenericAlias def __init__(self, origin, args): - super().__init__(args) + # Cannot use `super().__init__` here because of the `__class__` assignment + # in the class body (https://github.com/python/typing_extensions/issues/661) + list.__init__(self, args) self.__origin__ = origin self.__args__ = args @@ -2259,10 +2367,10 @@ else: return typing._GenericAlias(self, (item,)) -# 3.14+? +# 3.15+? if hasattr(typing, 'TypeForm'): TypeForm = typing.TypeForm -# <=3.13 +# <=3.14 else: class _TypeFormForm(_ExtensionsSpecialForm, _root=True): # TypeForm(X) is equivalent to X but indicates to the type checker @@ -2515,7 +2623,10 @@ else: # <=3.11 def __getitem__(self, args): if self.__typing_is_unpacked_typevartuple__: return args - return super().__getitem__(args) + # Cannot use `super().__getitem__` here because of the `__class__` assignment + # in the class body on Python <=3.11 + # (https://github.com/python/typing_extensions/issues/661) + return typing._GenericAlias.__getitem__(self, args) @_UnpackSpecialForm def Unpack(self, parameters): @@ -2537,20 +2648,33 @@ def _unpack_args(*args): return newargs -if _PEP_696_IMPLEMENTED: +if sys.version_info >= (3, 15): from typing import TypeVarTuple elif hasattr(typing, "TypeVarTuple"): # 3.11+ - # Add default parameter - PEP 696 + # Add default parameter - PEP 696 and bound/variance parameters class TypeVarTuple(metaclass=_TypeVarLikeMeta): """Type variable tuple.""" _backported_typevarlike = typing.TypeVarTuple - def __new__(cls, name, *, default=NoDefault): - tvt = typing.TypeVarTuple(name) - _set_default(tvt, default) + def __new__(cls, name, *, bound=None, + covariant=False, contravariant=False, + infer_variance=False, default=NoDefault): + + if _PEP_696_IMPLEMENTED: + # can pass default argument + tvt = typing.TypeVarTuple(name, default=default) + else: + tvt = typing.TypeVarTuple(name) + _set_default(tvt, default) + + tvt.__bound__ = bound + tvt.__covariant__ = bool(covariant) + tvt.__contravariant__ = bool(contravariant) + tvt.__infer_variance__ = bool(infer_variance) + _set_module(tvt) def _typevartuple_prepare_subst(alias, args): @@ -2655,8 +2779,13 @@ else: # <=3.10 def __iter__(self): yield self.__unpacked__ - def __init__(self, name, *, default=NoDefault): + def __init__(self, name, *, bound=None, covariant=False, contravariant=False, + infer_variance=False, default=NoDefault): self.__name__ = name + self.__covariant__ = bool(covariant) + self.__contravariant__ = bool(contravariant) + self.__infer_variance__ = bool(infer_variance) + self.__bound__ = bound _DefaultMixin.__init__(self, default) # for pickling: @@ -2667,7 +2796,15 @@ else: # <=3.10 self.__unpacked__ = Unpack[self] def __repr__(self): - return self.__name__ + if self.__infer_variance__: + prefix = '' + elif self.__covariant__: + prefix = '+' + elif self.__contravariant__: + prefix = '-' + else: + prefix = '~' + return prefix + self.__name__ def __hash__(self): return object.__hash__(self) @@ -2873,9 +3010,9 @@ else: # <=3.11 return arg -# Python 3.13.3+ contains a fix for the wrapped __new__ -# Breakpoint: https://github.com/python/cpython/pull/132160 -if sys.version_info >= (3, 13, 3): +# Python 3.13.8+ and 3.14.1+ contain a fix for the wrapped __init_subclass__ +# Breakpoint: https://github.com/python/cpython/pull/138210 +if ((3, 13, 8) <= sys.version_info < (3, 14)) or sys.version_info >= (3, 14, 1): deprecated = warnings.deprecated else: _T = typing.TypeVar("_T") @@ -2968,33 +3105,32 @@ else: arg.__new__ = staticmethod(__new__) - original_init_subclass = arg.__init_subclass__ - # We need slightly different behavior if __init_subclass__ - # is a bound method (likely if it was implemented in Python) - if isinstance(original_init_subclass, MethodType): - original_init_subclass = original_init_subclass.__func__ + if "__init_subclass__" in arg.__dict__: + # __init_subclass__ is directly present on the decorated class. + # Synthesize a wrapper that calls this method directly. + original_init_subclass = arg.__init_subclass__ + # We need slightly different behavior if __init_subclass__ + # is a bound method (likely if it was implemented in Python). + # Otherwise, it likely means it's a builtin such as + # object's implementation of __init_subclass__. + if isinstance(original_init_subclass, MethodType): + original_init_subclass = original_init_subclass.__func__ @functools.wraps(original_init_subclass) def __init_subclass__(*args, **kwargs): warnings.warn(msg, category=category, stacklevel=stacklevel + 1) return original_init_subclass(*args, **kwargs) - - arg.__init_subclass__ = classmethod(__init_subclass__) - # Or otherwise, which likely means it's a builtin such as - # object's implementation of __init_subclass__. else: - @functools.wraps(original_init_subclass) - def __init_subclass__(*args, **kwargs): + def __init_subclass__(cls, *args, **kwargs): warnings.warn(msg, category=category, stacklevel=stacklevel + 1) - return original_init_subclass(*args, **kwargs) + return super(arg, cls).__init_subclass__(*args, **kwargs) - arg.__init_subclass__ = __init_subclass__ + arg.__init_subclass__ = classmethod(__init_subclass__) arg.__deprecated__ = __new__.__deprecated__ = msg __init_subclass__.__deprecated__ = msg return arg elif callable(arg): - import asyncio.coroutines import functools import inspect @@ -3003,11 +3139,13 @@ else: warnings.warn(msg, category=category, stacklevel=stacklevel + 1) return arg(*args, **kwargs) - if asyncio.coroutines.iscoroutinefunction(arg): + if inspect.iscoroutinefunction(arg): # Breakpoint: https://github.com/python/cpython/pull/99247 if sys.version_info >= (3, 12): wrapper = inspect.markcoroutinefunction(wrapper) else: + import asyncio.coroutines + wrapper._is_coroutine = asyncio.coroutines._is_coroutine arg.__deprecated__ = wrapper.__deprecated__ = msg @@ -3579,14 +3717,14 @@ else: return typing.Union[other, self] -# Breakpoint: https://github.com/python/cpython/pull/124795 -if sys.version_info >= (3, 14): +# Breakpoint: https://github.com/python/cpython/pull/149172 +if sys.version_info >= (3, 15): TypeAliasType = typing.TypeAliasType -# <=3.13 +# <=3.14 else: # Breakpoint: https://github.com/python/cpython/pull/103764 if sys.version_info >= (3, 12): - # 3.12-3.13 + # 3.12-3.14 def _is_unionable(obj): """Corresponds to is_unionable() in unionobject.c in CPython.""" return obj is None or isinstance(obj, ( @@ -3699,7 +3837,7 @@ else: self.__name__ = name def __setattr__(self, name: str, value: object, /) -> None: - if hasattr(self, "__name__"): + if hasattr(self, "__name__") and name != "__module__": self._raise_attribute_error(name) super().__setattr__(name, value) @@ -3710,7 +3848,7 @@ else: # Match the Python 3.12 error messages exactly if name == "__name__": raise AttributeError("readonly attribute") - elif name in {"__value__", "__type_params__", "__parameters__", "__module__"}: + elif name in {"__value__", "__type_params__", "__parameters__"}: raise AttributeError( f"attribute '{name}' of 'typing.TypeAliasType' objects " "is not writable" @@ -3829,8 +3967,8 @@ else: >>> class P(Protocol): ... def a(self) -> str: ... ... b: int - >>> get_protocol_members(P) - frozenset({'a', 'b'}) + >>> get_protocol_members(P) == frozenset({'a', 'b'}) + True Raise a TypeError for arguments that are not Protocols. """ @@ -4207,44 +4345,6 @@ else: ) -class Sentinel: - """Create a unique sentinel object. - - *name* should be the name of the variable to which the return value shall be assigned. - - *repr*, if supplied, will be used for the repr of the sentinel object. - If not provided, "" will be used. - """ - - def __init__( - self, - name: str, - repr: typing.Optional[str] = None, - ): - self._name = name - self._repr = repr if repr is not None else f'<{name}>' - - def __repr__(self): - return self._repr - - if sys.version_info < (3, 11): - # The presence of this method convinces typing._type_check - # that Sentinels are types. - def __call__(self, *args, **kwargs): - raise TypeError(f"{type(self).__name__!r} object is not callable") - - # Breakpoint: https://github.com/python/cpython/pull/21515 - if sys.version_info >= (3, 10): - def __or__(self, other): - return typing.Union[self, other] - - def __ror__(self, other): - return typing.Union[other, self] - - def __getstate__(self): - raise TypeError(f"Cannot pickle {type(self).__name__!r} object") - - if sys.version_info >= (3, 14, 0, "beta"): type_repr = annotationlib.type_repr else: @@ -4302,11 +4402,16 @@ _typing_names = [ "ValuesView", "cast", "no_type_check", - "no_type_check_decorator", # This is private, but it was defined by typing_extensions for a long time # and some users rely on it. "_AnnotatedAlias", ] + +# Breakpoint: https://github.com/python/cpython/pull/133602 +if sys.version_info < (3, 15, 0): + _typing_names.append("no_type_check_decorator") + __all__.append("no_type_check_decorator") + globals().update( {name: getattr(typing, name) for name in _typing_names if hasattr(typing, name)} ) diff --git a/server/noxfile.py b/server/noxfile.py index 7895f0b..87a29c4 100644 --- a/server/noxfile.py +++ b/server/noxfile.py @@ -8,7 +8,6 @@ import pathlib import sys import tomllib import urllib.request as url_lib -from typing import List import nox # pylint: disable=import-error @@ -17,7 +16,7 @@ import nox # pylint: disable=import-error nox.options.default_venv_backend = "uv" -def _read_dependencies() -> List[str]: +def _read_dependencies() -> list[str]: """Read project dependencies from pyproject.toml.""" pyproject = tomllib.loads(pathlib.Path("pyproject.toml").read_text()) return list(pyproject.get("project", {}).get("dependencies", [])) @@ -33,16 +32,18 @@ def _install_bundle(session: nox.Session) -> None: "./libs", "--no-cache-dir", "--upgrade", + "--overrides", + "./uv-overrides.txt", *deps, external=True, ) -def _check_files(names: List[str]) -> None: +def _check_files(names: list[str]) -> None: root_dir = pathlib.Path(__file__).parent for name in names: file_path = root_dir / name - lines: List[str] = file_path.read_text().splitlines() + lines: list[str] = file_path.read_text().splitlines() if any(line for line in lines if line.startswith("# TODO:")): raise Exception(f"Please update {os.fspath(file_path)}.") @@ -101,7 +102,17 @@ def setup(session: nox.Session) -> None: def tests(session: nox.Session) -> None: """Runs all the tests for the extension.""" deps = _read_dependencies() - session.run("uv", "pip", "install", "--python", sys.executable, *deps, external=True) + session.run( + "uv", + "pip", + "install", + "--python", + sys.executable, + "--overrides", + "./uv-overrides.txt", + *deps, + external=True, + ) session.run("uv", "pip", "install", "--python", sys.executable, "pytest", external=True) session.run("pytest", "tests/python_tests") @@ -110,7 +121,17 @@ def tests(session: nox.Session) -> None: def lint(session: nox.Session) -> None: """Runs linter and formatter checks on python files.""" deps = _read_dependencies() - session.run("uv", "pip", "install", "--python", sys.executable, *deps, external=True) + session.run( + "uv", + "pip", + "install", + "--python", + sys.executable, + "--overrides", + "./uv-overrides.txt", + *deps, + external=True, + ) session.run( "uv", "pip", @@ -161,7 +182,12 @@ def _update_uv_lock(session: nox.Session) -> None: @nox.session() -def update_packages(session: nox.Session) -> None: - """Update Python and npm packages.""" +def update_python_packages(session: nox.Session) -> None: + """Update Python packages.""" _update_uv_lock(session) + + +@nox.session() +def update_npm_packages(session: nox.Session) -> None: + """Update npm packages.""" _update_npm_packages(session) diff --git a/server/pyproject.toml b/server/pyproject.toml index a5d7b62..c45370a 100644 --- a/server/pyproject.toml +++ b/server/pyproject.toml @@ -2,14 +2,21 @@ name = "nx-post-support-server" version = "0.1.0" description = "Python language server for NX Postprocessor Support" -requires-python = ">=3.8" +requires-python = ">=3.12" dependencies = [ # Upper bounds guard against breaking API changes in bundled deps. The code - # is written against tclint 0.8.x (see tools/semantic_tokens.py); pin it so a + # is written against tclint 0.9.x (see tools/semantic_tokens.py); pin it so a # re-bundle can't silently pull an incompatible major/minor. - "pygls>=1.3,<2", + "pygls>=2.0,<3", "packaging>=24,<27", - "tclint>=0.8,<0.9", + "tclint>=0.9,<1.0", +] + +[tool.uv] +override-dependencies = [ + # tclint only uses pygls in its tclsp CLI, which this project does not use. + # The language server itself is migrated independently to pygls 2.x. + "pygls>=2.0,<3", ] [dependency-groups] diff --git a/server/src/lsp_server.py b/server/src/lsp_server.py index 34f87dd..a58c49d 100644 --- a/server/src/lsp_server.py +++ b/server/src/lsp_server.py @@ -42,7 +42,7 @@ import lsp_jsonrpc as jsonrpc import lsprotocol.types as lsp from common.load_data import standard_items from lsp_tclserver import TclLanguageServer -from pygls import uris, workspace +from pygls import uris from pygls.workspace.text_document import TextDocument from tools.folding_ranges import build_folding_ranges from tools.inlay_hint import ( @@ -575,7 +575,7 @@ def prepare_rename(params: lsp.PrepareRenameParams): indexes, definitions, occurrence, identity = context if not _is_renamable(identity, indexes, definitions): return None - return lsp.PrepareRenameResult_Type1( + return lsp.PrepareRenamePlaceholder( range=occurrence.range, placeholder=occurrence.placeholder ) @@ -822,7 +822,7 @@ def _get_settings_by_path(file_path: pathlib.Path): return setting_values[0] -def _get_document_key(document: workspace.Document): +def _get_document_key(document: TextDocument): if WORKSPACE_SETTINGS: document_workspace = pathlib.Path(document.path) workspaces = {s["workspaceFS"] for s in WORKSPACE_SETTINGS.values()} @@ -836,7 +836,7 @@ def _get_document_key(document: workspace.Document): return None -def _get_settings_by_document(document: workspace.Document | None): +def _get_settings_by_document(document: TextDocument | None): if document is None or document.path is None: return list(WORKSPACE_SETTINGS.values())[0] @@ -860,25 +860,33 @@ def _get_settings_by_document(document: workspace.Document | None): def log_to_output( message: str, msg_type: lsp.MessageType = lsp.MessageType.Log ) -> None: - LSP_SERVER.show_message_log(message, msg_type) + LSP_SERVER.window_log_message( + lsp.LogMessageParams(message=message, type=msg_type) + ) def log_error(message: str) -> None: - LSP_SERVER.show_message_log(message, lsp.MessageType.Error) + log_to_output(message, lsp.MessageType.Error) if os.getenv("LS_SHOW_NOTIFICATION", "off") in ["onError", "onWarning", "always"]: - LSP_SERVER.show_message(message, lsp.MessageType.Error) + LSP_SERVER.window_show_message( + lsp.ShowMessageParams(message=message, type=lsp.MessageType.Error) + ) def log_warning(message: str) -> None: - LSP_SERVER.show_message_log(message, lsp.MessageType.Warning) + log_to_output(message, lsp.MessageType.Warning) if os.getenv("LS_SHOW_NOTIFICATION", "off") in ["onWarning", "always"]: - LSP_SERVER.show_message(message, lsp.MessageType.Warning) + LSP_SERVER.window_show_message( + lsp.ShowMessageParams(message=message, type=lsp.MessageType.Warning) + ) def log_always(message: str) -> None: - LSP_SERVER.show_message_log(message, lsp.MessageType.Info) + log_to_output(message, lsp.MessageType.Info) if os.getenv("LS_SHOW_NOTIFICATION", "off") in ["always"]: - LSP_SERVER.show_message(message, lsp.MessageType.Info) + LSP_SERVER.window_show_message( + lsp.ShowMessageParams(message=message, type=lsp.MessageType.Info) + ) # ***************************************************** diff --git a/server/src/lsp_tclserver.py b/server/src/lsp_tclserver.py index e98e294..544bc0a 100644 --- a/server/src/lsp_tclserver.py +++ b/server/src/lsp_tclserver.py @@ -6,7 +6,8 @@ from typing import List, Optional, Tuple import lsprotocol.types as lsp from plugins.poco_plugin import commands -from pygls import server, uris +from pygls import uris +from pygls.lsp.server import LanguageServer from pygls.workspace.text_document import TextDocument from tclint.format import FormatterOpts from tclint.lexer import TclSyntaxError @@ -23,7 +24,7 @@ DIAGNOSTIC_SOURCE = "nx-post-support" LOGGER = logging.getLogger(__name__) -class TclLanguageServer(server.LanguageServer): +class TclLanguageServer(LanguageServer): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.parser = parser.CustomParser() diff --git a/server/tests/python_tests/conftest.py b/server/tests/python_tests/conftest.py new file mode 100644 index 0000000..937364d --- /dev/null +++ b/server/tests/python_tests/conftest.py @@ -0,0 +1,26 @@ +"""Shared pytest setup for the language server.""" + +import sys +from pathlib import Path + +import pytest + +THIS_DIR = Path(__file__).parent +SRC_DIR = THIS_DIR.parent.parent / "src" +if str(SRC_DIR) not in sys.path: + sys.path.insert(0, str(SRC_DIR)) + +import lsprotocol.types as lsp # type: ignore # noqa: E402 +from lsp_server import LSP_SERVER # type: ignore # noqa: E402 +from pygls.workspace import Workspace # noqa: E402 + + +@pytest.fixture(scope="session", autouse=True) +def initialize_test_workspace() -> None: + """Provide the workspace that pygls 2 creates during LSP initialization.""" + LSP_SERVER.protocol._workspace = Workspace( # pylint: disable=protected-access + root_uri=None, + sync_kind=lsp.TextDocumentSyncKind.Incremental, + workspace_folders=[], + position_encoding=lsp.PositionEncodingKind.Utf16, + ) diff --git a/server/tests/python_tests/test_document_symbols.py b/server/tests/python_tests/test_document_symbols.py index c2eb66f..d56ff03 100644 --- a/server/tests/python_tests/test_document_symbols.py +++ b/server/tests/python_tests/test_document_symbols.py @@ -53,10 +53,11 @@ def test_document_symbols_namespace_proc_set_hierarchy(tmp_path: Path): assert "top_var" in top_names assert "top_proc" in top_names - # Check that proc add has no children (we're not extracting params as children here) + # Procedure parameters are not emitted as children, but local variables are. add = next(c for c in ns.children if c.name == "add") assert add.kind == lsp.SymbolKind.Function - assert add.children == [] + assert add.children is not None + assert {child.name for child in add.children} == {"sum"} def test_buffer_edit_events_are_symbols_with_type_and_name(tmp_path: Path): diff --git a/server/uv-overrides.txt b/server/uv-overrides.txt new file mode 100644 index 0000000..cdd66e7 --- /dev/null +++ b/server/uv-overrides.txt @@ -0,0 +1,3 @@ +# tclint only uses pygls in its unused tclsp CLI. The project language server +# uses pygls 2.x directly, so override tclint's pygls==1.3.1 dependency. +pygls>=2.0,<3 diff --git a/server/uv.lock b/server/uv.lock index d5f5d88..88bb3b8 100644 --- a/server/uv.lock +++ b/server/uv.lock @@ -1,91 +1,39 @@ version = 1 revision = 3 -requires-python = ">=3.8" +requires-python = ">=3.12" resolution-markers = [ - "python_full_version >= '3.10'", - "python_full_version == '3.9.*'", - "python_full_version < '3.9'", + "python_full_version >= '3.15'", + "python_full_version < '3.15'", ] +[manifest] +overrides = [{ name = "pygls", specifier = ">=2.0,<3" }] + [[package]] name = "argcomplete" -version = "3.6.3" +version = "3.7.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/38/61/0b9ae6399dd4a58d8c1b1dc5a27d6f2808023d0b5dd3104bb99f45a33ff6/argcomplete-3.6.3.tar.gz", hash = "sha256:62e8ed4fd6a45864acc8235409461b72c9a28ee785a2011cc5eb78318786c89c", size = 73754, upload-time = "2025-10-20T03:33:34.741Z" } +sdist = { url = "https://files.pythonhosted.org/packages/87/6f/5a73f04007ca950701765949209f068da628bd11f9c2da287278ce91e0ee/argcomplete-3.7.2.tar.gz", hash = "sha256:aad8b69a0b9969edb62db0d1752354c0d50717b10e0cbb00e2a958381b9fc6b9", size = 74473, upload-time = "2026-08-06T04:53:21.662Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/74/f5/9373290775639cb67a2fce7f629a1c240dce9f12fe927bc32b2736e16dfc/argcomplete-3.6.3-py3-none-any.whl", hash = "sha256:f5007b3a600ccac5d25bbce33089211dfd49eab4a7718da3f10e3082525a92ce", size = 43846, upload-time = "2025-10-20T03:33:33.021Z" }, -] - -[[package]] -name = "attrs" -version = "25.3.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.9'", -] -sdist = { url = "https://files.pythonhosted.org/packages/5a/b0/1367933a8532ee6ff8d63537de4f1177af4bff9f3e829baf7331f595bb24/attrs-25.3.0.tar.gz", hash = "sha256:75d7cefc7fb576747b2c81b4442d4d4a1ce0900973527c011d1030fd3bf4af1b", size = 812032, upload-time = "2025-03-13T11:10:22.779Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/77/06/bb80f5f86020c4551da315d78b3ab75e8228f89f0162f2c3a819e407941a/attrs-25.3.0-py3-none-any.whl", hash = "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3", size = 63815, upload-time = "2025-03-13T11:10:21.14Z" }, + { url = "https://files.pythonhosted.org/packages/46/bd/551ee6af426af84ca33e02622be722925c196608e9127d731ef17c47f06e/argcomplete-3.7.2-py3-none-any.whl", hash = "sha256:6029205678bdd9c1c728a155f5f9ecf5812393f969eef58807641a2bc2aa5b19", size = 43294, upload-time = "2026-08-06T04:53:20.246Z" }, ] [[package]] name = "attrs" version = "26.1.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.10'", - "python_full_version == '3.9.*'", -] sdist = { url = "https://files.pythonhosted.org/packages/9a/8e/82a0fe20a541c03148528be8cac2408564a6c9a0cc7e9171802bc1d26985/attrs-26.1.0.tar.gz", hash = "sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32", size = 952055, upload-time = "2026-03-19T14:22:25.026Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/64/b4/17d4b0b2a2dc85a6df63d1157e028ed19f90d4cd97c36717afef2bc2f395/attrs-26.1.0-py3-none-any.whl", hash = "sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309", size = 67548, upload-time = "2026-03-19T14:22:23.645Z" }, ] -[[package]] -name = "cattrs" -version = "24.1.3" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.9'", -] -dependencies = [ - { name = "attrs", version = "25.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, - { name = "exceptiongroup", marker = "python_full_version < '3.9'" }, - { name = "typing-extensions", version = "4.13.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/29/7b/da4aa2f95afb2f28010453d03d6eedf018f9e085bd001f039e15731aba89/cattrs-24.1.3.tar.gz", hash = "sha256:981a6ef05875b5bb0c7fb68885546186d306f10f0f6718fe9b96c226e68821ff", size = 426684, upload-time = "2025-03-25T15:01:00.325Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/3c/ee/d68a3de23867a9156bab7e0a22fb9a0305067ee639032a22982cf7f725e7/cattrs-24.1.3-py3-none-any.whl", hash = "sha256:adf957dddd26840f27ffbd060a6c4dd3b2192c5b7c2c0525ef1bd8131d8a83f5", size = 66462, upload-time = "2025-03-25T15:00:58.663Z" }, -] - -[[package]] -name = "cattrs" -version = "25.3.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version == '3.9.*'", -] -dependencies = [ - { name = "attrs", version = "26.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.9.*'" }, - { name = "exceptiongroup", marker = "python_full_version == '3.9.*'" }, - { name = "typing-extensions", version = "4.15.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.9.*'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/6e/00/2432bb2d445b39b5407f0a90e01b9a271475eea7caf913d7a86bcb956385/cattrs-25.3.0.tar.gz", hash = "sha256:1ac88d9e5eda10436c4517e390a4142d88638fe682c436c93db7ce4a277b884a", size = 509321, upload-time = "2025-10-07T12:26:08.737Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d8/2b/a40e1488fdfa02d3f9a653a61a5935ea08b3c2225ee818db6a76c7ba9695/cattrs-25.3.0-py3-none-any.whl", hash = "sha256:9896e84e0a5bf723bc7b4b68f4481785367ce07a8a02e7e9ee6eb2819bc306ff", size = 70738, upload-time = "2025-10-07T12:26:06.603Z" }, -] - [[package]] name = "cattrs" version = "26.1.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.10'", -] dependencies = [ - { name = "attrs", version = "26.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, - { name = "exceptiongroup", marker = "python_full_version == '3.10.*'" }, - { name = "typing-extensions", version = "4.15.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "attrs" }, + { name = "typing-extensions" }, ] sdist = { url = "https://files.pythonhosted.org/packages/a0/ec/ba18945e7d6e55a58364d9fb2e46049c1c2998b3d805f19b703f14e81057/cattrs-26.1.0.tar.gz", hash = "sha256:fa239e0f0ec0715ba34852ce813986dfed1e12117e209b816ab87401271cdd40", size = 495672, upload-time = "2026-02-18T22:15:19.406Z" } wheels = [ @@ -103,36 +51,26 @@ wheels = [ [[package]] name = "colorlog" -version = "6.10.1" +version = "6.12.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/a2/61/f083b5ac52e505dfc1c624eafbf8c7589a0d7f32daa398d2e7590efa5fda/colorlog-6.10.1.tar.gz", hash = "sha256:eb4ae5cb65fe7fec7773c2306061a8e63e02efc2c72eba9d27b0fa23c94f1321", size = 17162, upload-time = "2025-10-16T16:14:11.978Z" } +sdist = { url = "https://files.pythonhosted.org/packages/8c/55/ba79756cb90c8d69d599d57785398ac87bba7b19c80e87f4e8a562197c93/colorlog-6.12.0.tar.gz", hash = "sha256:2a7924c1dadf18b22a0eb8b06d1c7b01d5341707ec1641eb6fcc4fde0c3e8e5f", size = 18151, upload-time = "2026-07-23T13:40:40.71Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/6d/c1/e419ef3723a074172b68aaa89c9f3de486ed4c2399e2dbd8113a4fdcaf9e/colorlog-6.10.1-py3-none-any.whl", hash = "sha256:2d7e8348291948af66122cff006c9f8da6255d224e7cf8e37d8de2df3bad8c9c", size = 11743, upload-time = "2025-10-16T16:14:10.512Z" }, -] - -[[package]] -name = "contextlib2" -version = "21.6.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/c7/13/37ea7805ae3057992e96ecb1cffa2fa35c2ef4498543b846f90dd2348d8f/contextlib2-21.6.0.tar.gz", hash = "sha256:ab1e2bfe1d01d968e1b7e8d9023bc51ef3509bba217bb730cee3827e1ee82869", size = 43795, upload-time = "2021-06-27T06:54:40.841Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/76/56/6d6872f79d14c0cb02f1646cbb4592eef935857c0951a105874b7b62a0c3/contextlib2-21.6.0-py2.py3-none-any.whl", hash = "sha256:3fbdb64466afd23abaf6c977627b75b6139a5a3e8ce38405c5b413aed7a0471f", size = 13277, upload-time = "2021-06-27T06:54:20.972Z" }, + { url = "https://files.pythonhosted.org/packages/d4/19/0b6647bf5e331521e55d2b63bfbdc210bd9cd605189273f03614a05f702d/colorlog-6.12.0-py3-none-any.whl", hash = "sha256:30d392604e9110045a2c2aeefc27d7a017abbab63f3a8aee594eac0801df784e", size = 12239, upload-time = "2026-07-23T13:40:39.562Z" }, ] [[package]] name = "dependency-groups" -version = "1.3.1" +version = "1.3.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "packaging" }, - { name = "tomli", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/62/55/f054de99871e7beb81935dea8a10b90cd5ce42122b1c3081d5282fdb3621/dependency_groups-1.3.1.tar.gz", hash = "sha256:78078301090517fd938c19f64a53ce98c32834dfe0dee6b88004a569a6adfefd", size = 10093, upload-time = "2025-05-02T00:34:29.452Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b5/16/65e61d8e837e0d70a99a0d4dd76e2af53357c3a03ed1db8ad9b5786d7f25/dependency_groups-1.3.2.tar.gz", hash = "sha256:c81831f43828dbc3987ee247eb198241a0152b8e7ceab10977cc3808eb388ac7", size = 13309, upload-time = "2026-08-22T02:43:30.137Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/99/c7/d1ec24fb280caa5a79b6b950db565dab30210a66259d17d5bb2b3a9f878d/dependency_groups-1.3.1-py3-none-any.whl", hash = "sha256:51aeaa0dfad72430fcfb7bcdbefbd75f3792e5919563077f30bc0d73f4493030", size = 8664, upload-time = "2025-05-02T00:34:27.085Z" }, + { url = "https://files.pythonhosted.org/packages/a1/e4/da5f2f176050efcfb9222a76a3e81c41f69f775be8e563b76ca4292a134f/dependency_groups-1.3.2-py3-none-any.whl", hash = "sha256:8c337f7b92445823b0d0ea507f611390c58dcd2112be00aebcd738a2ca7a1c64", size = 9802, upload-time = "2026-08-22T02:43:28.853Z" }, ] [[package]] @@ -144,89 +82,22 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/02/08/9c41fb51ab5b43eb21674aff13df270e8ba6c4b29c8624e328dc7a9482af/distlib-0.4.3-py2.py3-none-any.whl", hash = "sha256:4b0ce306c966eb73bc3a7b6abad017c556dadd92c44701562cd528ac7fde4d5b", size = 470628, upload-time = "2026-06-12T08:04:50.506Z" }, ] -[[package]] -name = "exceptiongroup" -version = "1.3.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "typing-extensions", version = "4.13.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, - { name = "typing-extensions", version = "4.15.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9' and python_full_version < '3.13'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740, upload-time = "2025-11-21T23:01:53.443Z" }, -] - [[package]] name = "filelock" -version = "3.16.1" +version = "3.32.5" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.9'", -] -sdist = { url = "https://files.pythonhosted.org/packages/9d/db/3ef5bb276dae18d6ec2124224403d1d67bccdbefc17af4cc8f553e341ab1/filelock-3.16.1.tar.gz", hash = "sha256:c249fbfcd5db47e5e2d6d62198e565475ee65e4831e2561c8e313fa7eb961435", size = 18037, upload-time = "2024-09-17T19:02:01.779Z" } +sdist = { url = "https://files.pythonhosted.org/packages/0a/a0/50c2c0ce5e74d7721bbb1b19a26ebd339aac5878553a6e35308c2f31f935/filelock-3.32.5.tar.gz", hash = "sha256:f6a6a28f743f9b95ce19db5abe0f376f75eb56517dff21e1a4751e2657d3e83d", size = 222838, upload-time = "2026-08-31T18:56:34.729Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b9/f8/feced7779d755758a52d1f6635d990b8d98dc0a29fa568bbe0625f18fdf3/filelock-3.16.1-py3-none-any.whl", hash = "sha256:2082e5703d51fbf98ea75855d9d5527e33d8ff23099bec374a134febee6946b0", size = 16163, upload-time = "2024-09-17T19:02:00.268Z" }, -] - -[[package]] -name = "filelock" -version = "3.19.1" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version == '3.9.*'", -] -sdist = { url = "https://files.pythonhosted.org/packages/40/bb/0ab3e58d22305b6f5440629d20683af28959bf793d98d11950e305c1c326/filelock-3.19.1.tar.gz", hash = "sha256:66eda1888b0171c998b35be2bcc0f6d75c388a7ce20c3f3f37aa8e96c2dddf58", size = 17687, upload-time = "2025-08-14T16:56:03.016Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/42/14/42b2651a2f46b022ccd948bca9f2d5af0fd8929c4eec235b8d6d844fbe67/filelock-3.19.1-py3-none-any.whl", hash = "sha256:d38e30481def20772f5baf097c122c3babc4fcdb7e14e57049eb9d88c6dc017d", size = 15988, upload-time = "2025-08-14T16:56:01.633Z" }, -] - -[[package]] -name = "filelock" -version = "3.29.4" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.10'", -] -sdist = { url = "https://files.pythonhosted.org/packages/e6/dc/be6cbe99670cd6e4ad387123647cb08e0c32975e223f82551e914c5568a6/filelock-3.29.4.tar.gz", hash = "sha256:10cdb3656fc44541cdf30652a93fb10ec6b05325620eb316bd26893e4201538a", size = 63028, upload-time = "2026-06-13T16:12:00.744Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/13/37/a065dc3bd6e49423a6532c642ca7378d3f467b1ef44c2800c937af7f9739/filelock-3.29.4-py3-none-any.whl", hash = "sha256:dac1648087d5115554850d113e7dd8c83ab2d38e3435dde2d4f163847e57b767", size = 42757, upload-time = "2026-06-13T16:11:59.582Z" }, + { url = "https://files.pythonhosted.org/packages/36/d2/b70a31e13d04456d28493f31d2aa087e99eeb2767ef0293b2625727ccb8c/filelock-3.32.5-py3-none-any.whl", hash = "sha256:142cd9fa77a872c5e78c62329a0d15278fadc686eb89e760017968961a4fd6b2", size = 100003, upload-time = "2026-08-31T18:56:33.078Z" }, ] [[package]] name = "humanize" -version = "4.10.0" +version = "4.16.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.9'", -] -sdist = { url = "https://files.pythonhosted.org/packages/5d/b1/c8f05d5dc8f64030d8cc71e91307c1daadf6ec0d70bcd6eabdfd9b6f153f/humanize-4.10.0.tar.gz", hash = "sha256:06b6eb0293e4b85e8d385397c5868926820db32b9b654b932f57fa41c23c9978", size = 79192, upload-time = "2024-07-08T10:31:04.945Z" } +sdist = { url = "https://files.pythonhosted.org/packages/0a/ea/13a1ef3c12d12662905801495283530251918b70d62d368f1d2e0272c70d/humanize-4.16.0.tar.gz", hash = "sha256:7dc2244a2f84a4bfb1d36c37bac80cd78e35cdc5c119206d87b018e1445f3a3f", size = 89515, upload-time = "2026-06-30T16:17:29.859Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/8f/49/a29c79bea335e52fb512a43faf84998c184c87fef82c65f568f8c56f2642/humanize-4.10.0-py3-none-any.whl", hash = "sha256:39e7ccb96923e732b5c2e27aeaa3b10a8dfeeba3eb965ba7b74a3eb0e30040a6", size = 126957, upload-time = "2024-07-08T10:31:02.751Z" }, -] - -[[package]] -name = "humanize" -version = "4.13.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version == '3.9.*'", -] -sdist = { url = "https://files.pythonhosted.org/packages/98/1d/3062fcc89ee05a715c0b9bfe6490c00c576314f27ffee3a704122c6fd259/humanize-4.13.0.tar.gz", hash = "sha256:78f79e68f76f0b04d711c4e55d32bebef5be387148862cb1ef83d2b58e7935a0", size = 81884, upload-time = "2025-08-25T09:39:20.04Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/1e/c7/316e7ca04d26695ef0635dc81683d628350810eb8e9b2299fc08ba49f366/humanize-4.13.0-py3-none-any.whl", hash = "sha256:b810820b31891813b1673e8fec7f1ed3312061eab2f26e3fa192c393d11ed25f", size = 128869, upload-time = "2025-08-25T09:39:18.54Z" }, -] - -[[package]] -name = "humanize" -version = "4.15.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.10'", -] -sdist = { url = "https://files.pythonhosted.org/packages/ba/66/a3921783d54be8a6870ac4ccffcd15c4dc0dd7fcce51c6d63b8c63935276/humanize-4.15.0.tar.gz", hash = "sha256:1dd098483eb1c7ee8e32eb2e99ad1910baefa4b75c3aff3a82f4d78688993b10", size = 83599, upload-time = "2025-12-20T20:16:13.19Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/c5/7b/bca5613a0c3b542420cf92bd5e5fb8ebd5435ce1011a091f66bb7693285e/humanize-4.15.0-py3-none-any.whl", hash = "sha256:b1186eb9f5a9749cd9cb8565aee77919dd7c8d076161cf44d70e59e3301e1769", size = 132203, upload-time = "2025-12-20T20:16:11.67Z" }, + { url = "https://files.pythonhosted.org/packages/b0/aa/0b7365d30fed43e7a3449aba1fe20a0a7174d9cf13e282af4e69ac825441/humanize-4.16.0-py3-none-any.whl", hash = "sha256:353eb2f34c09d098b2880eee8bef21832eae6d174f48c5762fff7e5fcb74d01d", size = 137209, upload-time = "2026-06-30T16:17:28.36Z" }, ] [[package]] @@ -234,9 +105,7 @@ name = "importlib-metadata" version = "6.8.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "zipp", version = "3.20.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, - { name = "zipp", version = "3.23.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.9.*'" }, - { name = "zipp", version = "4.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "zipp" }, ] sdist = { url = "https://files.pythonhosted.org/packages/33/44/ae06b446b8d8263d712a211e959212083a5eda2bf36d57ca7415e03f6f36/importlib_metadata-6.8.0.tar.gz", hash = "sha256:dbace7892d8c0c4ac1ad096662232f831d4e64f4c4545bd53016a3e9d4654743", size = 53494, upload-time = "2023-07-07T16:16:03.091Z" } wheels = [ @@ -245,64 +114,35 @@ wheels = [ [[package]] name = "lsprotocol" -version = "2023.0.1" +version = "2025.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "attrs", version = "25.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, - { name = "attrs", version = "26.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, - { name = "cattrs", version = "24.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, - { name = "cattrs", version = "25.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.9.*'" }, - { name = "cattrs", version = "26.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "attrs" }, + { name = "cattrs" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/9d/f6/6e80484ec078d0b50699ceb1833597b792a6c695f90c645fbaf54b947e6f/lsprotocol-2023.0.1.tar.gz", hash = "sha256:cc5c15130d2403c18b734304339e51242d3018a05c4f7d0f198ad6e0cd21861d", size = 69434, upload-time = "2024-01-09T17:21:12.625Z" } +sdist = { url = "https://files.pythonhosted.org/packages/e9/26/67b84e6ec1402f0e6764ef3d2a0aaf9a79522cc1d37738f4e5bb0b21521a/lsprotocol-2025.0.0.tar.gz", hash = "sha256:e879da2b9301e82cfc3e60d805630487ac2f7ab17492f4f5ba5aaba94fe56c29", size = 74896, upload-time = "2025-06-17T21:30:18.156Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/8d/37/2351e48cb3309673492d3a8c59d407b75fb6630e560eb27ecd4da03adc9a/lsprotocol-2023.0.1-py3-none-any.whl", hash = "sha256:c75223c9e4af2f24272b14c6375787438279369236cd568f596d4951052a60f2", size = 70826, upload-time = "2024-01-09T17:21:14.491Z" }, + { url = "https://files.pythonhosted.org/packages/7b/f0/92f2d609d6642b5f30cb50a885d2bf1483301c69d5786286500d15651ef2/lsprotocol-2025.0.0-py3-none-any.whl", hash = "sha256:f9d78f25221f2a60eaa4a96d3b4ffae011b107537facee61d3da3313880995c7", size = 76250, upload-time = "2025-06-17T21:30:19.455Z" }, ] [[package]] name = "nox" -version = "2026.2.9" +version = "2026.8.17" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.9'", -] dependencies = [ - { name = "argcomplete", marker = "python_full_version < '3.9'" }, - { name = "attrs", version = "25.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, - { name = "colorlog", marker = "python_full_version < '3.9'" }, - { name = "dependency-groups", marker = "python_full_version < '3.9'" }, - { name = "humanize", version = "4.10.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, - { name = "packaging", marker = "python_full_version < '3.9'" }, - { name = "tomli", marker = "python_full_version < '3.9'" }, - { name = "virtualenv", version = "21.4.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "argcomplete" }, + { name = "attrs" }, + { name = "colorlog" }, + { name = "dependency-groups" }, + { name = "humanize" }, + { name = "packaging" }, + { name = "platformdirs" }, + { name = "python-discovery" }, + { name = "virtualenv" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/6e/8e/55a9679b31f1efc48facedd2448eb53c7f1e647fb592aa1403c9dd7a4590/nox-2026.2.9.tar.gz", hash = "sha256:1bc8a202ee8cd69be7aaada63b2a7019126899a06fc930a7aee75585bf8ee41b", size = 4031165, upload-time = "2026-02-10T04:38:58.878Z" } +sdist = { url = "https://files.pythonhosted.org/packages/be/65/4cef8ae8f6dbcb5753b202e46791277f1ea0b4a0650d1a6cb940c468b143/nox-2026.8.17.tar.gz", hash = "sha256:8d9c69c9b996a59db1eb2c6968deaebc2edbc55317d205981bbc4a37351d3f2e", size = 4076047, upload-time = "2026-08-18T03:09:57.078Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/8d/58/0d5e5a044f1868bdc45f38afdc2d90ff9867ce398b4e8fa9e666bfc9bfba/nox-2026.2.9-py3-none-any.whl", hash = "sha256:1b7143bc8ecdf25f2353201326152c5303ae4ae56ca097b1fb6179ad75164c47", size = 74615, upload-time = "2026-02-10T04:38:57.266Z" }, -] - -[[package]] -name = "nox" -version = "2026.4.10" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.10'", - "python_full_version == '3.9.*'", -] -dependencies = [ - { name = "argcomplete", marker = "python_full_version >= '3.9'" }, - { name = "attrs", version = "26.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, - { name = "colorlog", marker = "python_full_version >= '3.9'" }, - { name = "dependency-groups", marker = "python_full_version >= '3.9'" }, - { name = "humanize", version = "4.13.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.9.*'" }, - { name = "humanize", version = "4.15.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, - { name = "packaging", marker = "python_full_version >= '3.9'" }, - { name = "tomli", marker = "python_full_version >= '3.9' and python_full_version < '3.11'" }, - { name = "virtualenv", version = "21.5.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/e7/6b/e672c862a43cfca704d32359221fa3780226daa1e5db5dfc401bcc8be9c9/nox-2026.4.10.tar.gz", hash = "sha256:2d0af5374f3f37a295428c927d1b04a8182aa01762897d172446dda2f1ce9692", size = 4034839, upload-time = "2026-04-10T17:42:42.209Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/7f/95/4df134a100b5a9a12378d5301b934366686ef6fbdaffcd21211d5654970e/nox-2026.4.10-py3-none-any.whl", hash = "sha256:082c117627590d9b90aa21f86df89b310b07c5842539524203bcb3c719f116c1", size = 75536, upload-time = "2026-04-10T17:42:40.664Z" }, + { url = "https://files.pythonhosted.org/packages/81/71/e0829a0500646070e98bc4442afa2917bfe5b6f1289511d8de853ae86497/nox-2026.8.17-py3-none-any.whl", hash = "sha256:a96a5286007cbc0d1eb1930e85738668f6722adba1ffaa48287296a96963086e", size = 94839, upload-time = "2026-08-18T03:09:55.684Z" }, ] [[package]] @@ -310,30 +150,33 @@ name = "nx-post-support-server" version = "0.1.0" source = { editable = "." } dependencies = [ - { name = "nox", version = "2026.2.9", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, - { name = "nox", version = "2026.4.10", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, - { name = "packaging" }, - { name = "pygls" }, - { name = "tclint", version = "0.4.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, - { name = "tclint", version = "0.7.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.9.*'" }, - { name = "tclint", version = "0.8.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, -] - -[package.metadata] -requires-dist = [ - { name = "nox", specifier = ">=2026.2.9" }, { name = "packaging" }, { name = "pygls" }, { name = "tclint" }, ] +[package.dev-dependencies] +dev = [ + { name = "nox" }, +] + +[package.metadata] +requires-dist = [ + { name = "packaging", specifier = ">=24,<27" }, + { name = "pygls", specifier = ">=2.0,<3" }, + { name = "tclint", specifier = ">=0.9,<1.0" }, +] + +[package.metadata.requires-dev] +dev = [{ name = "nox", specifier = ">=2026.2.9" }] + [[package]] name = "packaging" -version = "26.2" +version = "26.3" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d7/f1/e7a6dd94a8d4a5626c03e4e99c87f241ba9e350cd9e6d75123f992427270/packaging-26.2.tar.gz", hash = "sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661", size = 228134, upload-time = "2026-04-24T20:15:23.917Z" } +sdist = { url = "https://files.pythonhosted.org/packages/7d/fa/3944b40b07da9ce895c0e6303a5ab7d53da063554f534556b134a54d6093/packaging-26.3.tar.gz", hash = "sha256:94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79", size = 313412, upload-time = "2026-08-04T18:15:28.737Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/df/b2/87e62e8c3e2f4b32e5fe99e0b86d576da1312593b39f47d8ceef365e95ed/packaging-26.2-py3-none-any.whl", hash = "sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e", size = 100195, upload-time = "2026-04-24T20:15:22.081Z" }, + { url = "https://files.pythonhosted.org/packages/63/34/ba1c580383c9eada3711951fef0795c80b829a078d72188184bcab9dd527/packaging-26.3-py3-none-any.whl", hash = "sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c", size = 129956, upload-time = "2026-08-04T18:15:27.159Z" }, ] [[package]] @@ -347,38 +190,11 @@ wheels = [ [[package]] name = "platformdirs" -version = "4.3.6" +version = "4.11.7" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.9'", -] -sdist = { url = "https://files.pythonhosted.org/packages/13/fc/128cc9cb8f03208bdbf93d3aa862e16d376844a14f9a0ce5cf4507372de4/platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907", size = 21302, upload-time = "2024-09-17T19:06:50.688Z" } +sdist = { url = "https://files.pythonhosted.org/packages/69/b7/802a56eca9f2fac455b8bab5375a2647b0f0e14a2cd63ef077de3c4a7658/platformdirs-4.11.7.tar.gz", hash = "sha256:4f41487eeeeeb07f3a6625e61d9bc0ae6809f92d3386dbd74392fbb76108104d", size = 35127, upload-time = "2026-09-01T13:35:10.502Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/3c/a6/bc1012356d8ece4d66dd75c4b9fc6c1f6650ddd5991e421177d9f8f671be/platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb", size = 18439, upload-time = "2024-09-17T19:06:49.212Z" }, -] - -[[package]] -name = "platformdirs" -version = "4.4.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version == '3.9.*'", -] -sdist = { url = "https://files.pythonhosted.org/packages/23/e8/21db9c9987b0e728855bd57bff6984f67952bea55d6f75e055c46b5383e8/platformdirs-4.4.0.tar.gz", hash = "sha256:ca753cf4d81dc309bc67b0ea38fd15dc97bc30ce419a7f58d13eb3bf14c4febf", size = 21634, upload-time = "2025-08-26T14:32:04.268Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/40/4b/2028861e724d3bd36227adfa20d3fd24c3fc6d52032f4a93c133be5d17ce/platformdirs-4.4.0-py3-none-any.whl", hash = "sha256:abd01743f24e5287cd7a5db3752faf1a2d65353f38ec26d98e25a6db65958c85", size = 18654, upload-time = "2025-08-26T14:32:02.735Z" }, -] - -[[package]] -name = "platformdirs" -version = "4.10.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.10'", -] -sdist = { url = "https://files.pythonhosted.org/packages/d7/47/e4501f49c178ae1d9f4a75073fda4204f52647993f075a9db4d14930e0c5/platformdirs-4.10.0.tar.gz", hash = "sha256:31e761a6a0ca04faf7353ea759bdba55652be214725111e5aac52dfa29d4bef7", size = 31224, upload-time = "2026-05-28T03:32:53.587Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/81/e6/cd9575ac904136b3cbf7aa7ee819ef86eedb7274e46f230e94ea4342e729/platformdirs-4.10.0-py3-none-any.whl", hash = "sha256:fb516cdb12eb0d857d0cd85a7c57cea4d060bee4578d6cf5a14dfdf8cbf8784a", size = 22743, upload-time = "2026-05-28T03:32:52.175Z" }, + { url = "https://files.pythonhosted.org/packages/27/6e/80993e10a0482f630cef528635789233224f36b1ffd11592aa15d13ff9ce/platformdirs-4.11.7-py3-none-any.whl", hash = "sha256:8a02cb259042c79d1cd0450facc2fe6dc9d303ae7901afbe33bf8ea0b188cef6", size = 23938, upload-time = "2026-09-01T13:35:09.02Z" }, ] [[package]] @@ -392,180 +208,68 @@ wheels = [ [[package]] name = "pygls" -version = "1.3.1" +version = "2.1.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "cattrs", version = "24.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, - { name = "cattrs", version = "25.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.9.*'" }, - { name = "cattrs", version = "26.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "attrs" }, + { name = "cattrs" }, { name = "lsprotocol" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/86/b9/41d173dad9eaa9db9c785a85671fc3d68961f08d67706dc2e79011e10b5c/pygls-1.3.1.tar.gz", hash = "sha256:140edceefa0da0e9b3c533547c892a42a7d2fd9217ae848c330c53d266a55018", size = 45527, upload-time = "2024-03-26T18:44:25.679Z" } +sdist = { url = "https://files.pythonhosted.org/packages/da/2e/7bbe061d175c0baddde8fc9edb908a4c31ba5d9165b8c68e3439c3a9f138/pygls-2.1.1.tar.gz", hash = "sha256:1da03ba9053201bb337dcdd8d121df70feb2a91e1a0dcc74de5da79755b1a201", size = 55091, upload-time = "2026-03-25T11:19:10.541Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/11/19/b74a10dd24548e96e8c80226cbacb28b021bc3a168a7d2709fb0d0185348/pygls-1.3.1-py3-none-any.whl", hash = "sha256:6e00f11efc56321bdeb6eac04f6d86131f654c7d49124344a9ebb968da3dd91e", size = 56031, upload-time = "2024-03-26T18:44:24.249Z" }, + { url = "https://files.pythonhosted.org/packages/fd/1a/208293b6c350f5abea6941d5606080d4a492644052504f5312e5de30a902/pygls-2.1.1-py3-none-any.whl", hash = "sha256:510a6dea2476177230c7d851125e5948efdf3fdb9ebfd8543fc434972f8faed4", size = 68975, upload-time = "2026-03-25T11:19:11.374Z" }, ] [[package]] name = "python-discovery" -version = "1.4.2" +version = "1.6.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "filelock", version = "3.16.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, - { name = "filelock", version = "3.19.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.9.*'" }, - { name = "filelock", version = "3.29.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, - { name = "platformdirs", version = "4.3.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, - { name = "platformdirs", version = "4.4.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.9.*'" }, - { name = "platformdirs", version = "4.10.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "filelock" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/0b/1a/cbbaf13b730abb0a16b964d984e19f2fe520c21a4dc664051359a3f5a9e7/python_discovery-1.4.2.tar.gz", hash = "sha256:8f3746c4b4968d22afbb97d36e1a0e5b66e6c0f297290f2e95f05b9b8bf18690", size = 70277, upload-time = "2026-06-11T16:10:42.383Z" } +sdist = { url = "https://files.pythonhosted.org/packages/91/96/0f93e27c9f60a650838f2118159aa115fd5732c0716247917b7ba7ede665/python_discovery-1.6.0.tar.gz", hash = "sha256:6393b4eae1be8b2182670635e7baff89ac21cb9f8e86fd1ff40c7b1144febb4c", size = 82849, upload-time = "2026-08-28T17:30:02.366Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/1a/82/a70006589557f267f15bd384c0642ad49f0d97b690c3a05b166b9dcbad3b/python_discovery-1.4.2-py3-none-any.whl", hash = "sha256:475803f53b7b2ed6e490e27373f9d8340f7d2eebf9acdaf645d7d714c97bb500", size = 33886, upload-time = "2026-06-11T16:10:41.192Z" }, -] - -[[package]] -name = "schema" -version = "0.7.5" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "contextlib2", marker = "python_full_version < '3.9'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/4e/e8/01e1b46d9e04cdaee91c9c736d9117304df53361a191144c8eccda7f0ee9/schema-0.7.5.tar.gz", hash = "sha256:f06717112c61895cabc4707752b88716e8420a8819d71404501e114f91043197", size = 48173, upload-time = "2021-12-01T20:49:24.038Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/0d/93/ca8aa5a772efd69043d0a745172d92bee027caa7565c7f774a2f44b91207/schema-0.7.5-py2.py3-none-any.whl", hash = "sha256:f3ffdeeada09ec34bf40d7d79996d9f7175db93b7a5065de0faa7f41083c1e6c", size = 17603, upload-time = "2021-12-01T20:49:21.252Z" }, + { url = "https://files.pythonhosted.org/packages/43/5e/21abf578182fb15006a57faf3711a1e659e29d600d19b6e557eae908c81d/python_discovery-1.6.0-py3-none-any.whl", hash = "sha256:d4e244cf17b8b29819ed78003d55fbacf86eda23425b075454fff9271b79377a", size = 38451, upload-time = "2026-08-28T17:30:01.236Z" }, ] [[package]] name = "tclint" -version = "0.4.2" +version = "0.9.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.9'", -] dependencies = [ - { name = "importlib-metadata", marker = "python_full_version < '3.9'" }, - { name = "pathspec", marker = "python_full_version < '3.9'" }, - { name = "ply", marker = "python_full_version < '3.9'" }, - { name = "schema", marker = "python_full_version < '3.9'" }, - { name = "tomli", marker = "python_full_version < '3.9'" }, + { name = "importlib-metadata" }, + { name = "pathspec" }, + { name = "ply" }, + { name = "pygls" }, + { name = "voluptuous" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c0/88/1c7a191cd487f73ead49f447ec7963866ef093e47382d51cc54b60e89c6d/tclint-0.4.2.tar.gz", hash = "sha256:27dc43f6804a560f0813bd0bca3b617369f9909e9db8d609906660b367ef1583", size = 70559, upload-time = "2024-10-08T02:45:28.603Z" } +sdist = { url = "https://files.pythonhosted.org/packages/85/d8/ebee2778ef596bb6038381299142923f7dbd8e021f2d5711b201a56a5c13/tclint-0.9.0.tar.gz", hash = "sha256:15517ecb8193e3fd72b657459b633853ba9a60c2124b421c95f613914b89654b", size = 100435, upload-time = "2026-08-01T20:42:44.686Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/cc/b5/51832e9a286e65a17a4846ab4d634a6eee44692874cf298bf82c807e5495/tclint-0.4.2-py3-none-any.whl", hash = "sha256:9be008df348ad9558e07f21bc02e3b385be4444c448f4aed982ef6be40698309", size = 52481, upload-time = "2024-10-08T02:45:27.508Z" }, -] - -[[package]] -name = "tclint" -version = "0.7.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version == '3.9.*'", -] -dependencies = [ - { name = "importlib-metadata", marker = "python_full_version == '3.9.*'" }, - { name = "pathspec", marker = "python_full_version == '3.9.*'" }, - { name = "ply", marker = "python_full_version == '3.9.*'" }, - { name = "pygls", marker = "python_full_version == '3.9.*'" }, - { name = "tomli", marker = "python_full_version == '3.9.*'" }, - { name = "voluptuous", marker = "python_full_version == '3.9.*'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/84/57/bac53151cc404c8fd5b15c69943cde772b404cd740ee576d5a7ca12732d1/tclint-0.7.0.tar.gz", hash = "sha256:bd605b11d44708e1537b902e63d7dd1d05f2d85c2c99a36854b157606eac1e8a", size = 90458, upload-time = "2025-12-21T22:35:27.041Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/44/72/1465bedba4f2ea4ae501eaa9f8e06d31e62627f053c88c58544c50ec4ac5/tclint-0.7.0-py3-none-any.whl", hash = "sha256:58b54bf333a96ef4b4eac3bde23da997a64a4414a4cdec8e5e0a9fbafb6dcd25", size = 53945, upload-time = "2025-12-21T22:35:25.436Z" }, -] - -[[package]] -name = "tclint" -version = "0.8.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.10'", -] -dependencies = [ - { name = "importlib-metadata", marker = "python_full_version >= '3.10'" }, - { name = "pathspec", marker = "python_full_version >= '3.10'" }, - { name = "ply", marker = "python_full_version >= '3.10'" }, - { name = "pygls", marker = "python_full_version >= '3.10'" }, - { name = "tomli", marker = "python_full_version == '3.10.*'" }, - { name = "voluptuous", marker = "python_full_version >= '3.10'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/3f/4e/9ec785aa3f9473bcbd56bb858a46749db94baee2c1df603c458bfe189b51/tclint-0.8.0.tar.gz", hash = "sha256:0a0fff0dd4610859a85c06bd347c8ffb46e9bed79cdd34662738a518acc43c0c", size = 97995, upload-time = "2026-03-24T01:54:41.49Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/8a/cc/781a8bf0ec24ebe8850f9aee7101c9177e90f98b3400c9ceaa1f5421b0d5/tclint-0.8.0-py3-none-any.whl", hash = "sha256:0fff3ec0878bc870005bf4cbcd4529e2764d2adfa602532f86f456e49df2c002", size = 57012, upload-time = "2026-03-24T01:54:40.186Z" }, -] - -[[package]] -name = "tomli" -version = "2.0.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/35/b9/de2a5c0144d7d75a57ff355c0c24054f965b2dc3036456ae03a51ea6264b/tomli-2.0.2.tar.gz", hash = "sha256:d46d457a85337051c36524bc5349dd91b1877838e2979ac5ced3e710ed8a60ed", size = 16096, upload-time = "2024-10-02T10:46:13.208Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/cf/db/ce8eda256fa131af12e0a76d481711abe4681b6923c27efb9a255c9e4594/tomli-2.0.2-py3-none-any.whl", hash = "sha256:2ebe24485c53d303f690b0ec092806a085f07af5a5aa1464f3931eec36caaa38", size = 13237, upload-time = "2024-10-02T10:46:11.806Z" }, + { url = "https://files.pythonhosted.org/packages/46/d6/d1cf5cad5bb11d79546785972f04f6cb51e4415f25eba8957d405c1f8148/tclint-0.9.0-py3-none-any.whl", hash = "sha256:e4f0eb6b263161190a502184425fdd3ab046d09112da8089ddb767e7de198583", size = 58021, upload-time = "2026-08-01T20:42:43.418Z" }, ] [[package]] name = "typing-extensions" -version = "4.13.2" +version = "4.16.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.9'", -] -sdist = { url = "https://files.pythonhosted.org/packages/f6/37/23083fcd6e35492953e8d2aaaa68b860eb422b34627b13f2ce3eb6106061/typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef", size = 106967, upload-time = "2025-04-10T14:19:05.416Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f6/cc/6253133b5bb138fc3306cebfbda2c520f545d36b5be2c7255cc528bb45d6/typing_extensions-4.16.0.tar.gz", hash = "sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5", size = 113555, upload-time = "2026-07-02T08:40:05.92Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/8b/54/b1ae86c0973cc6f0210b53d508ca3641fb6d0c56823f288d108bc7ab3cc8/typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c", size = 45806, upload-time = "2025-04-10T14:19:03.967Z" }, -] - -[[package]] -name = "typing-extensions" -version = "4.15.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.10'", - "python_full_version == '3.9.*'", -] -sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" }, + { url = "https://files.pythonhosted.org/packages/49/d3/b8441a820a491ddfc024b0b0cf0393375b75ea13866d9c66727e54c2fc80/typing_extensions-4.16.0-py3-none-any.whl", hash = "sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8", size = 45571, upload-time = "2026-07-02T08:40:04.659Z" }, ] [[package]] name = "virtualenv" -version = "21.4.3" +version = "21.7.8" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.9'", -] dependencies = [ - { name = "distlib", marker = "python_full_version < '3.9'" }, - { name = "filelock", version = "3.16.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, - { name = "platformdirs", version = "4.3.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, - { name = "python-discovery", marker = "python_full_version < '3.9'" }, - { name = "typing-extensions", version = "4.13.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "distlib" }, + { name = "filelock" }, + { name = "platformdirs" }, + { name = "python-discovery" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/4b/50/7564c805bb8966d9771caaba8a143fa5e57c848ce4e7fdf2d55a1feb2ead/virtualenv-21.4.3.tar.gz", hash = "sha256:938ff0fd3f4e0f0d3a025f67a3d2f25e3c3aabbcd5857ea6170619138d72d141", size = 7644454, upload-time = "2026-06-11T16:47:04.843Z" } +sdist = { url = "https://files.pythonhosted.org/packages/08/1c/69faa2e6a83484e2a8227bce5cfaa183941c5720f99c48f204931d286b07/virtualenv-21.7.8.tar.gz", hash = "sha256:1dc49c790072a9072cb1803f9bd62aa69cd583077cada32390f75505cdc64c9b", size = 5347580, upload-time = "2026-09-01T13:36:13.894Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a2/8d/84b0d07c6b5f685f85ddf6c87a59d3a8a895a3dfd89e759666fabe951b94/virtualenv-21.4.3-py3-none-any.whl", hash = "sha256:75f4127d4067397c64f38579ce918fec6bf9ca2cd4f48685e82952cc3c035840", size = 7625544, upload-time = "2026-06-11T16:47:01.78Z" }, -] - -[[package]] -name = "virtualenv" -version = "21.5.1" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.10'", - "python_full_version == '3.9.*'", -] -dependencies = [ - { name = "distlib", marker = "python_full_version >= '3.9'" }, - { name = "filelock", version = "3.19.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.9.*'" }, - { name = "filelock", version = "3.29.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, - { name = "platformdirs", version = "4.4.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.9.*'" }, - { name = "platformdirs", version = "4.10.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, - { name = "python-discovery", marker = "python_full_version >= '3.9'" }, - { name = "typing-extensions", version = "4.15.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9' and python_full_version < '3.11'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/f1/a5/81f987504738e6defeed61ec1c47e2aefab3c35d8eeb87e1b3f38cf28254/virtualenv-21.5.1.tar.gz", hash = "sha256:dca3bf98275a59c652b69d68e73433e597d977c2da9198882479d1a7188009c8", size = 4578798, upload-time = "2026-06-16T16:23:58.603Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/2c/02/3623e6169bed617ed1e2d372f7c69f92ec28d54c4dfc997055c8578ec148/virtualenv-21.5.1-py3-none-any.whl", hash = "sha256:55aa670b67bbfb991b03fda39bd3276d92c419d702376e98c5df1c9989a26783", size = 4558820, upload-time = "2026-06-16T16:23:56.963Z" }, + { url = "https://files.pythonhosted.org/packages/9f/34/88d507d4a4030fa559788de9c690a214f9a4053aa1d91cfb60e9b36127c2/virtualenv-21.7.8-py3-none-any.whl", hash = "sha256:3040eb3cbf5d32b10ffd57d167e6a162237ad82ba7d8cf1400a1efed593d85ac", size = 5324617, upload-time = "2026-09-01T13:36:11.248Z" }, ] [[package]] @@ -577,37 +281,10 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/db/a8/8f9cc6749331186e6a513bfe3745454f81d25f6e34c6024f88f80c71ed28/voluptuous-0.15.2-py3-none-any.whl", hash = "sha256:016348bc7788a9af9520b1764ebd4de0df41fe2138ebe9e06fa036bf86a65566", size = 31349, upload-time = "2024-07-02T19:09:58.125Z" }, ] -[[package]] -name = "zipp" -version = "3.20.2" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.9'", -] -sdist = { url = "https://files.pythonhosted.org/packages/54/bf/5c0000c44ebc80123ecbdddba1f5dcd94a5ada602a9c225d84b5aaa55e86/zipp-3.20.2.tar.gz", hash = "sha256:bc9eb26f4506fda01b81bcde0ca78103b6e62f991b381fec825435c836edbc29", size = 24199, upload-time = "2024-09-13T13:44:16.101Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/62/8b/5ba542fa83c90e09eac972fc9baca7a88e7e7ca4b221a89251954019308b/zipp-3.20.2-py3-none-any.whl", hash = "sha256:a817ac80d6cf4b23bf7f2828b7cabf326f15a001bea8b1f9b49631780ba28350", size = 9200, upload-time = "2024-09-13T13:44:14.38Z" }, -] - -[[package]] -name = "zipp" -version = "3.23.1" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version == '3.9.*'", -] -sdist = { url = "https://files.pythonhosted.org/packages/30/21/093488dfc7cc8964ded15ab726fad40f25fd3d788fd741cc1c5a17d78ee8/zipp-3.23.1.tar.gz", hash = "sha256:32120e378d32cd9714ad503c1d024619063ec28aad2248dc6672ad13edfa5110", size = 25965, upload-time = "2026-04-13T23:21:46.6Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/08/8a/0861bec20485572fbddf3dfba2910e38fe249796cb73ecdeb74e07eeb8d3/zipp-3.23.1-py3-none-any.whl", hash = "sha256:0b3596c50a5c700c9cb40ba8d86d9f2cc4807e9bedb06bcdf7fac85633e444dc", size = 10378, upload-time = "2026-04-13T23:21:45.386Z" }, -] - [[package]] name = "zipp" version = "4.1.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.10'", -] sdist = { url = "https://files.pythonhosted.org/packages/b9/d8/eab98a517c14134c0b2eb4e2387bc5f457334293ec5d2dd3857ec2966802/zipp-4.1.0.tar.gz", hash = "sha256:4cb57381f544315db7688e976e922a2b18cdb513d21cc194eb42232ba2a3e602", size = 26214, upload-time = "2026-05-18T20:08:57.967Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/3a/13/547360d81e6d88d58492968ffda9f9542854f11310ee556fef14260cc886/zipp-4.1.0-py3-none-any.whl", hash = "sha256:25ad4e16390cd314347dd8f1de67a2ac538ae658ed4ab9db16029c07c188e97f", size = 10238, upload-time = "2026-05-18T20:08:57.045Z" }, diff --git a/test/file.cdl b/test/file.cdl index e98a153..884d1aa 100644 --- a/test/file.cdl +++ b/test/file.cdl @@ -1,4 +1,5 @@ -MACHINE +MACHINE Default + EVENT dummy_event_start { UI_LABEL "------------SAMSON UDES------------" diff --git a/test/test.tcl b/test/test.tcl index bfb0ed7..f4f8826 100644 --- a/test/test.tcl +++ b/test/test.tcl @@ -68,6 +68,13 @@ proc SERVICE_ask_ude_tool {pos ude_name tool_name} { return 0 } +proc MOM_dummy_event_start {} { + global mom_new_item + global mom_new_item_end + + #Put your UDE Handler Tcl here +} + #_________________________________________________________________________________________________ # # Ask UDE Info for the Operation @@ -116,4 +123,4 @@ LIB_GE_command_buffer_edit_replace MOM_end_of_program_LIB END_OF_PROGRAM @END_OF } EndOfProgramRewind -SERVICE_remove_file "test" \ No newline at end of file +SERVICE_remove_file "test" -- 2.54.0