From ae17daca850766d06e9812c3367c93d8dd789f15 Mon Sep 17 00:00:00 2001 From: Niels Thykier Date: Sat, 6 Apr 2024 11:35:20 +0000 Subject: [PATCH] fix: respect client's preferred encoding when possible Previously, `pygls` would always use `UTF-16` except when the client tried to hide the fact that it supports `UTF-16` (which the LSP spec requires it to do in all cases). Now, `pygls` will choose the editor's preferred encoding. When it is `UTF-32`, `pygls` saves a bit of computation in most position codec related operations (`X_to_client_units` + `client_num_units` are faster, `X_from_client_units` is about the same), which is great. When it is `UTF-16` or `UTF-8`, the computational load is about the same. Closes: #445 --- pygls/capabilities.py | 23 +++++++++++++---------- tests/test_feature_manager.py | 13 +++++++++++++ 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/pygls/capabilities.py b/pygls/capabilities.py index 975e5e24..44a6d2ed 100644 --- a/pygls/capabilities.py +++ b/pygls/capabilities.py @@ -24,6 +24,14 @@ logger = logging.getLogger(__name__) T = TypeVar("T") +_SUPPORTED_ENCODINGS = frozenset( + [ + types.PositionEncodingKind.Utf8, + types.PositionEncodingKind.Utf16, + types.PositionEncodingKind.Utf32, + ] +) + def get_capability( client_capabilities: types.ClientCapabilities, field: str, default: Any = None @@ -401,16 +409,11 @@ def _with_position_encodings(self): 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 + # We match client preference where this an overlap between its and our supported encodings. + for encoding in encodings: + if encoding in _SUPPORTED_ENCODINGS: + self.server_cap.position_encoding = encoding + return self logger.warning(f"Unknown `PositionEncoding`s: {encodings}") diff --git a/tests/test_feature_manager.py b/tests/test_feature_manager.py index f69f12a3..744fcdb1 100644 --- a/tests/test_feature_manager.py +++ b/tests/test_feature_manager.py @@ -240,6 +240,19 @@ def server_capabilities(**kwargs): ] ) ), + server_capabilities(position_encoding=lsp.PositionEncodingKind.Utf8), + ), + ( + lsp.INITIALIZE, + None, + lsp.ClientCapabilities( + general=lsp.GeneralClientCapabilities( + position_encodings=[ + lsp.PositionEncodingKind.Utf32, + lsp.PositionEncodingKind.Utf8, + ] + ) + ), server_capabilities(position_encoding=lsp.PositionEncodingKind.Utf32), ), (