Skip to content

Commit 4eb9ad3

Browse files
committed
add some LSP 3.17 declarations, move InlineValueProvider completely to the language server
1 parent 9de28ed commit 4eb9ad3

File tree

40 files changed

+652
-164
lines changed

40 files changed

+652
-164
lines changed

robotcode/jsonrpc2/protocol.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -456,7 +456,11 @@ def inner(d: Dict[Any, Any]) -> JsonRPCMessage:
456456

457457
def _handle_body(self, body: bytes, charset: str) -> None:
458458
try:
459-
self._handle_messages(self._generate_json_rpc_messages_from_dict(json.loads(body.decode(charset))))
459+
b = body.decode(charset)
460+
461+
self._data_logger.trace(lambda: f"JSON Received: {b}")
462+
463+
self._handle_messages(self._generate_json_rpc_messages_from_dict(json.loads(b)))
460464
except (asyncio.CancelledError, SystemExit, KeyboardInterrupt):
461465
raise
462466
except BaseException as e:
@@ -519,7 +523,7 @@ def send_message(self, message: JsonRPCMessage) -> None:
519523
if self.write_transport is not None:
520524
msg = header + body
521525

522-
self._data_logger.trace(lambda: f"JSON Message: {msg.decode()}")
526+
self._data_logger.trace(lambda: f"JSON send: {msg.decode()}")
523527

524528
if self._loop:
525529
self._loop.call_soon_threadsafe(self.write_transport.write, msg)

robotcode/language_server/common/lsp_types.py

Lines changed: 129 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,30 @@
1313
ProgressToken = Union[str, int]
1414

1515

16+
class ErrorCodes:
17+
PARSE_ERROR = -32700
18+
INVALID_REQUEST = -32600
19+
METHOD_NOT_FOUND = -32601
20+
INVALID_PARAMS = -32602
21+
INTERNAL_ERROR = -32603
22+
SERVER_ERROR_START = -32000
23+
SERVER_ERROR_END = -32099
24+
25+
JSON_RPC_RESERVED_ERROR_RANGE_START = -32099
26+
27+
SERVER_NOT_INITIALIZED = -32002
28+
UNKNOWN_ERROR = -32001
29+
30+
JSON_RPC_RESERVED_ERROR_RANGE_END = -32000
31+
32+
LSP_RESERVED_ERROR_RANGE_START = -32899
33+
REQUEST_FAILED = -32803
34+
SERVER_CANCELLED = -32802
35+
CONTENT_MODIFIED = -32801
36+
REQUEST_CANCELLED = -32800
37+
LSP_RESERVED_ERROR_RANGE_END = -32800
38+
39+
1640
@dataclass(repr=False)
1741
class Model:
1842
@classmethod
@@ -485,11 +509,32 @@ class PublishDiagnosticsClientCapabilities(Model):
485509
data_support: Optional[bool] = None
486510

487511

512+
class FoldingRangeKind(Enum):
513+
COMMENT = "comment"
514+
IMPORTS = "imports"
515+
REGION = "region"
516+
517+
def __repr__(self) -> str: # pragma: no cover
518+
return super().__str__()
519+
520+
521+
@dataclass(repr=False)
522+
class FoldingRangeClientCapabilitiesFoldingRangeKind(Model):
523+
value_set: Optional[List[FoldingRangeKind]]
524+
525+
526+
@dataclass(repr=False)
527+
class FoldingRangeClientCapabilitiesFoldingRange(Model):
528+
collapsed_text: Optional[bool] = None
529+
530+
488531
@dataclass(repr=False)
489532
class FoldingRangeClientCapabilities(Model):
490533
dynamic_registration: Optional[bool] = None
491534
range_limit: Optional[int] = None
492535
line_folding_only: Optional[bool] = None
536+
folding_range_kind: Optional[FoldingRangeClientCapabilitiesFoldingRangeKind] = None
537+
folding_range: Optional[FoldingRangeClientCapabilitiesFoldingRange] = None
493538

494539

495540
@dataclass(repr=False)
@@ -533,6 +578,8 @@ class SemanticTokensClientCapabilities(Model):
533578
formats: List[TokenFormat]
534579
overlapping_token_support: Optional[bool] = None
535580
multiline_token_support: Optional[bool] = None
581+
server_cancel_support: Optional[bool] = None
582+
augments_syntax_tokens: Optional[bool] = None
536583
dynamic_registration: Optional[bool] = None
537584

538585

@@ -541,6 +588,22 @@ class MonikerClientCapabilities(Model):
541588
dynamic_registration: Optional[bool] = None
542589

543590

591+
@dataclass(repr=False)
592+
class InlayHintClientCapabilitiesResolveSupport(Model):
593+
properties: List[str]
594+
595+
596+
@dataclass(repr=False)
597+
class InlayHintClientCapabilities(Model):
598+
dynamic_registration: Optional[bool] = None
599+
resolve_support: Optional[InlayHintClientCapabilitiesResolveSupport] = None
600+
601+
602+
@dataclass(repr=False)
603+
class InlineValueClientCapabilities(Model):
604+
dynamic_registration: Optional[bool] = None
605+
606+
544607
@dataclass(repr=False)
545608
class TextDocumentClientCapabilities(Model):
546609
synchronization: Optional[TextDocumentSyncClientCapabilities] = None
@@ -569,6 +632,10 @@ class TextDocumentClientCapabilities(Model):
569632
call_hierarchy: Optional[CallHierarchyClientCapabilities] = None
570633
semantic_tokens: Optional[SemanticTokensClientCapabilities] = None
571634
moniker: Optional[MonikerClientCapabilities] = None
635+
# TODO typeHierarchy?: TypeHierarchyClientCapabilities;
636+
inline_value: Optional[InlineValueClientCapabilities] = None
637+
inlay_hint: Optional[InlayHintClientCapabilities] = None
638+
# TODO diagnostic?: DiagnosticClientCapabilities;
572639

573640

574641
@dataclass(repr=False)
@@ -596,6 +663,7 @@ class RegularExpressionsClientCapabilities(Model):
596663
class MarkdownClientCapabilities(Model):
597664
parser: str
598665
version: Optional[str] = None
666+
allowed_tags: Optional[List[str]] = None
599667

600668

601669
@dataclass(repr=False)
@@ -609,6 +677,11 @@ class ClientCapabilitiesWorkspaceFileOperationsWorkspaceClientCapabilities(Model
609677
will_delete: Optional[bool] = None
610678

611679

680+
@dataclass(repr=False)
681+
class InlineValueWorkspaceClientCapabilities(Model):
682+
refresh_support: Optional[bool] = None
683+
684+
612685
@dataclass(repr=False)
613686
class ClientCapabilitiesWorkspace(Model):
614687
apply_edit: Optional[bool] = None
@@ -622,6 +695,7 @@ class ClientCapabilitiesWorkspace(Model):
622695
semantic_tokens: Optional[SemanticTokensWorkspaceClientCapabilities] = None
623696
code_lens: Optional[CodeLensWorkspaceClientCapabilities] = None
624697
file_operations: Optional[ClientCapabilitiesWorkspaceFileOperationsWorkspaceClientCapabilities] = None
698+
inline_value: Optional[InlineValueWorkspaceClientCapabilities] = None
625699

626700

627701
@dataclass(repr=False)
@@ -972,6 +1046,16 @@ class RenameRegistrationOptions(TextDocumentRegistrationOptions, RenameOptions,
9721046
pass
9731047

9741048

1049+
@dataclass(repr=False)
1050+
class InlineValueOptions(WorkDoneProgressOptions):
1051+
pass
1052+
1053+
1054+
@dataclass(repr=False)
1055+
class InlineValueRegistrationOptions(InlineValueOptions, TextDocumentRegistrationOptions, StaticRegistrationOptions):
1056+
pass
1057+
1058+
9751059
@dataclass(repr=False)
9761060
class ServerCapabilities(Model):
9771061
text_document_sync: Union[TextDocumentSyncOptions, TextDocumentSyncKind, None] = None
@@ -1001,6 +1085,9 @@ class ServerCapabilities(Model):
10011085
# TODO call_hierarchy_provider: Union[boolean, CallHierarchyOptions, CallHierarchyRegistrationOptions, None] = None
10021086
semantic_tokens_provider: Union[SemanticTokensOptions, SemanticTokensRegistrationOptions, None] = None
10031087
# TODO moniker_provider: Union[bool, MonikerOptions, MonikerRegistrationOptions, None] = None
1088+
1089+
# TODO typeHierarchyProvider?: boolean | TypeHierarchyOptions | TypeHierarchyRegistrationOptions;
1090+
inline_value_provider: Union[bool, InlineValueOptions, InlineValueRegistrationOptions, None] = None
10041091
workspace_symbol_provider: Union[bool, WorkspaceSymbolOptions, None] = None
10051092
workspace: Optional[ServerCapabilitiesWorkspace] = None
10061093
experimental: Optional[Any] = None
@@ -1333,22 +1420,14 @@ class FoldingRangeParams(WorkDoneProgressParams, _FoldingRangeParams):
13331420
pass
13341421

13351422

1336-
class FoldingRangeKind(Enum):
1337-
Comment = "comment"
1338-
Imports = "imports"
1339-
Region = "region"
1340-
1341-
def __repr__(self) -> str: # pragma: no cover
1342-
return super().__str__()
1343-
1344-
13451423
@dataclass(repr=False)
13461424
class FoldingRange(Model):
13471425
start_line: int
13481426
end_line: int
13491427
start_character: Optional[int] = None
13501428
end_character: Optional[int] = None
13511429
kind: Union[FoldingRangeKind, str, None] = None
1430+
collapsed_text: Optional[str] = None
13521431

13531432

13541433
@dataclass(repr=False)
@@ -2014,3 +2093,44 @@ class PrepareRenameResultWithDefaultBehavior(Model):
20142093

20152094

20162095
PrepareRenameResult = Union[Range, PrepareRenameResultWithPlaceHolder, PrepareRenameResultWithDefaultBehavior]
2096+
2097+
2098+
@dataclass(repr=False)
2099+
class InlineValueContext(Model):
2100+
# TODO: this differs from definition in the LSP 3.17 spec
2101+
stopped_location: Union[Range, List[Position]]
2102+
frame_id: Optional[int] = None
2103+
2104+
2105+
@dataclass(repr=False)
2106+
class _InlineValueParams(Model):
2107+
text_document: TextDocumentIdentifier
2108+
range: Range
2109+
context: InlineValueContext
2110+
2111+
2112+
@dataclass(repr=False)
2113+
class InlineValueParams(WorkDoneProgressParams, _InlineValueParams):
2114+
pass
2115+
2116+
2117+
@dataclass(repr=False)
2118+
class InlineValueText(Model):
2119+
range: Range
2120+
text: str
2121+
2122+
2123+
@dataclass(repr=False)
2124+
class InlineValueVariableLookup(Model):
2125+
range: Range
2126+
variable_name: Optional[str]
2127+
case_sensitive_lookup: bool
2128+
2129+
2130+
@dataclass(repr=False)
2131+
class InlineValueEvaluatableExpression(Model):
2132+
range: Range
2133+
expression: Optional[str]
2134+
2135+
2136+
InlineValue = Union[InlineValueText, InlineValueVariableLookup, InlineValueEvaluatableExpression]
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
from __future__ import annotations
2+
3+
from asyncio import CancelledError
4+
from typing import TYPE_CHECKING, Any, List, Optional, Union
5+
6+
from ....jsonrpc2.protocol import rpc_method
7+
from ....utils.async_tools import async_tasking_event
8+
from ....utils.logging import LoggingDescriptor
9+
from ..decorators import HasLanguageId, language_id_filter
10+
from ..has_extend_capabilities import HasExtendCapabilities
11+
from ..lsp_types import (
12+
DocumentFilter,
13+
DocumentSelector,
14+
InlineValue,
15+
InlineValueContext,
16+
InlineValueParams,
17+
InlineValueRegistrationOptions,
18+
Position,
19+
Range,
20+
ServerCapabilities,
21+
TextDocumentIdentifier,
22+
)
23+
from ..text_document import TextDocument
24+
25+
if TYPE_CHECKING:
26+
from ..protocol import LanguageServerProtocol # pragma: no cover
27+
28+
from .protocol_part import LanguageServerProtocolPart
29+
30+
31+
class InlineValueProtocolPart(LanguageServerProtocolPart, HasExtendCapabilities):
32+
33+
_logger = LoggingDescriptor()
34+
35+
def __init__(self, parent: LanguageServerProtocol) -> None:
36+
super().__init__(parent)
37+
38+
@async_tasking_event
39+
async def collect(
40+
sender, document: TextDocument, range: Range, context: InlineValueContext # pragma: no cover, NOSONAR
41+
) -> Optional[List[InlineValue]]:
42+
...
43+
44+
def extend_capabilities(self, capabilities: ServerCapabilities) -> None:
45+
if len(self.collect):
46+
document_filters: DocumentSelector = []
47+
for e in self.collect:
48+
if isinstance(e, HasLanguageId):
49+
document_filters.append(DocumentFilter(language=e.__language_id__))
50+
capabilities.inline_value_provider = InlineValueRegistrationOptions(
51+
work_done_progress=True, document_selector=document_filters if document_filters else None
52+
)
53+
54+
@rpc_method(name="textDocument/inlineValue", param_type=InlineValueParams)
55+
async def _text_document_inline_value(
56+
self,
57+
text_document: TextDocumentIdentifier,
58+
range: Union[Range, List[Position]],
59+
context: InlineValueContext,
60+
*args: Any,
61+
**kwargs: Any,
62+
) -> Optional[List[InlineValue]]:
63+
64+
results: List[InlineValue] = []
65+
document = await self.parent.documents.get(text_document.uri)
66+
if document is None:
67+
return None
68+
69+
if isinstance(context.stopped_location, list): # TODO this is a hack, fix it
70+
context.stopped_location = Range(*context.stopped_location)
71+
72+
for result in await self.collect(self, document, range, context, callback_filter=language_id_filter(document)):
73+
if isinstance(result, BaseException):
74+
if not isinstance(result, CancelledError):
75+
self._logger.exception(result, exc_info=result)
76+
else:
77+
if result is not None:
78+
results += result
79+
80+
if len(results) == 0:
81+
return None
82+
83+
return results
84+
85+
async def refresh(self) -> None:
86+
if (
87+
self.parent.client_capabilities
88+
and self.parent.client_capabilities.workspace
89+
and self.parent.client_capabilities.workspace.inline_value
90+
and self.parent.client_capabilities.workspace.inline_value.refresh_support
91+
):
92+
await self.parent.send_request_async("workspace/inlineValue/refresh")

robotcode/language_server/common/protocol.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
from .parts.formatting import FormattingProtocolPart
5050
from .parts.hover import HoverProtocolPart
5151
from .parts.implementation import ImplementationProtocolPart
52+
from .parts.inline_value import InlineValueProtocolPart
5253
from .parts.linked_editing_ranges import LinkedEditingRangeProtocolPart
5354
from .parts.references import ReferencesProtocolPart
5455
from .parts.rename import RenameProtocolPart
@@ -88,6 +89,7 @@ class LanguageServerProtocol(JsonRPCProtocol):
8889
linked_editing_range = ProtocolPartDescriptor(LinkedEditingRangeProtocolPart)
8990
selection_range = ProtocolPartDescriptor(SelectionRangeProtocolPart)
9091
rename = ProtocolPartDescriptor(RenameProtocolPart)
92+
inline_value = ProtocolPartDescriptor(InlineValueProtocolPart)
9193

9294
name: Optional[str] = None
9395
short_name: Optional[str] = None

0 commit comments

Comments
 (0)