Skip to content

Commit

Permalink
feat: accept PositionEncoding client capability
Browse files Browse the repository at this point in the history
This commit is only for supporting sending preferred position encoding
from the client during startup. Even though this commit introduces the
server's ability to choose from the client's list of supported position
encodings, it doesn't actually support any other encoding from the
existing UTF-16.
  • Loading branch information
tombh committed Sep 24, 2023
1 parent 09ea48a commit d719b17
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 0 deletions.
31 changes: 31 additions & 0 deletions pygls/capabilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
############################################################################
from functools import reduce
from typing import Any, Dict, List, Set, Union
import logging

from lsprotocol.types import (
INLAY_HINT_RESOLVE,
Expand Down Expand Up @@ -64,6 +65,7 @@
WORKSPACE_WILL_DELETE_FILES,
WORKSPACE_WILL_RENAME_FILES,
InlayHintOptions,
PositionEncodingKind,
)
from lsprotocol.types import (
ClientCapabilities,
Expand All @@ -86,6 +88,8 @@
WorkspaceFoldersServerCapabilities,
)

logger = logging.getLogger(__name__)


def get_capability(
client_capabilities: ClientCapabilities, field: str, default: Any = None
Expand Down Expand Up @@ -429,6 +433,32 @@ def _with_inline_value_provider(self):
self.server_cap.inline_value_provider = value
return self

def _with_position_encodings(self):
self.server_cap.position_encoding = PositionEncodingKind.Utf16

general = self.client_capabilities.general
if general is None:
return self

encodings = general.position_encodings
if encodings is None:
return self

if PositionEncodingKind.Utf16 in encodings:
return self

if PositionEncodingKind.Utf32 in encodings:
self.server_cap.position_encoding = PositionEncodingKind.Utf32
return self

if PositionEncodingKind.Utf8 in encodings:
self.server_cap.position_encoding = PositionEncodingKind.Utf8
return self

logger.warning(f"Unknown `PositionEncoding`s: {encodings}")

return self

def _build(self):
return self.server_cap

Expand Down Expand Up @@ -467,5 +497,6 @@ def build(self):
._with_workspace_capabilities()
._with_diagnostic_provider()
._with_inline_value_provider()
._with_position_encodings()
._build()
)
5 changes: 5 additions & 0 deletions pygls/protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
WORKSPACE_DID_CHANGE_WORKSPACE_FOLDERS,
WORKSPACE_EXECUTE_COMMAND,
WORKSPACE_SEMANTIC_TOKENS_REFRESH,
PositionEncodingKind,
)
from lsprotocol.types import (
ApplyWorkspaceEditParams,
Expand Down Expand Up @@ -214,6 +215,10 @@ def default_converter():

converter.register_structure_hook(JsonRPCNotification, _params_field_structure_hook)

converter.register_structure_hook(
Union[PositionEncodingKind, str, None], lambda obj, _: obj
)

return converter


Expand Down
26 changes: 26 additions & 0 deletions tests/test_feature_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,12 +215,38 @@ def server_capabilities(**kwargs):
file_operations=lsp.FileOperationOptions(),
)

if "position_encoding" not in kwargs:
kwargs["position_encoding"] = lsp.PositionEncodingKind.Utf16

return lsp.ServerCapabilities(**kwargs)


@pytest.mark.parametrize(
"method, options, capabilities, expected",
[
(
lsp.INITIALIZE,
None,
lsp.ClientCapabilities(
general=lsp.GeneralClientCapabilities(
position_encodings=[lsp.PositionEncodingKind.Utf8]
)
),
server_capabilities(position_encoding=lsp.PositionEncodingKind.Utf8),
),
(
lsp.INITIALIZE,
None,
lsp.ClientCapabilities(
general=lsp.GeneralClientCapabilities(
position_encodings=[
lsp.PositionEncodingKind.Utf8,
lsp.PositionEncodingKind.Utf32,
]
)
),
server_capabilities(position_encoding=lsp.PositionEncodingKind.Utf32),
),
(
lsp.TEXT_DOCUMENT_DID_SAVE,
lsp.SaveOptions(include_text=True),
Expand Down

0 comments on commit d719b17

Please sign in to comment.