From a9cf8b76ed95c75515f2da5f765043d86ab08541 Mon Sep 17 00:00:00 2001 From: Predrag Nikolic Date: Thu, 11 Aug 2022 14:45:33 +0200 Subject: [PATCH 01/65] add inlay hints Co-authored-by: jwortmann --- plugin/core/protocol.py | 35 ++++++++++++++++++++++++ plugin/core/sessions.py | 12 +++++++++ plugin/inlay_hint.py | 57 ++++++++++++++++++++++++++++++++++++++++ plugin/session_buffer.py | 26 +++++++++++++++++- plugin/session_view.py | 8 ++++++ 5 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 plugin/inlay_hint.py diff --git a/plugin/core/protocol.py b/plugin/core/protocol.py index ec5827026..f2455e8de 100644 --- a/plugin/core/protocol.py +++ b/plugin/core/protocol.py @@ -334,6 +334,37 @@ class SemanticTokenModifiers: 'watchers': List[FileSystemWatcher], }, total=True) +InlayHintParams = TypedDict('InlayHintParams', { + 'textDocument': TextDocumentIdentifier, + 'range': RangeLsp, +}, total=True) + +InlayHintLabelPart = TypedDict('InlayHintLabelPart', { + 'value': str, + 'tooltip': Union[str, MarkupContent], + 'location': Location, + 'command': Command +}, total=False) + + +class InlayHintKind: + Type = 1 + Parameter = 1 + + +InlayHint = TypedDict('InlayHint', { + 'position': Position, + 'label': Union[str, List[InlayHintLabelPart]], + 'kind': Optional[int], + 'textEdits': Optional[List[TextEdit]], + 'tooltip': Optional[Union[str, MarkupContent]], + 'paddingLeft': Optional[bool], + 'paddingRight': Optional[bool], + 'data': Optional[Any] +}, total=True) + +InlayHintResponse = Union[List[InlayHint], None] + WatchKind = int WatchKindCreate = 1 WatchKindChange = 2 @@ -422,6 +453,10 @@ def resolveCompletionItem(cls, params: CompletionItem, view: sublime.View) -> 'R def resolveDocumentLink(cls, params: DocumentLink, view: sublime.View) -> 'Request': return Request("documentLink/resolve", params, view) + @classmethod + def inlayHint(cls, params: InlayHintParams, view: sublime.View) -> 'Request': + return Request('textDocument/inlayHint', params, view) + @classmethod def shutdown(cls) -> 'Request': return Request("shutdown") diff --git a/plugin/core/sessions.py b/plugin/core/sessions.py index cca3c8710..72fd85684 100644 --- a/plugin/core/sessions.py +++ b/plugin/core/sessions.py @@ -351,6 +351,12 @@ def get_initialize_params(variables: Dict[str, str], workspace_folders: List[Wor "codeLens": { "dynamicRegistration": True }, + "inlayHint": { + "dynamicRegistration": True, + "resolveSupport": { + "properties": [] + } + }, "semanticTokens": { "dynamicRegistration": True, "requests": { @@ -393,6 +399,9 @@ def get_initialize_params(variables: Dict[str, str], workspace_folders: List[Wor "codeLens": { "refreshSupport": True }, + "inlayHint": { + "refreshSupport": True + }, "semanticTokens": { "refreshSupport": True } @@ -489,6 +498,9 @@ def get_resolved_code_lenses_for_region(self, region: sublime.Region) -> Generat def start_code_lenses_async(self) -> None: ... + def present_inlay_hints_async(self, phantoms: List[sublime.Phantom]) -> None: + ... + class SessionBufferProtocol(Protocol): diff --git a/plugin/inlay_hint.py b/plugin/inlay_hint.py new file mode 100644 index 000000000..ffa66bfb8 --- /dev/null +++ b/plugin/inlay_hint.py @@ -0,0 +1,57 @@ +from .core.protocol import InlayHintLabelPart, MarkupContent, Point, InlayHint +from .core.typing import List, Optional, Union +from .core.views import FORMAT_MARKUP_CONTENT, point_to_offset, minihtml +import html +import sublime + +INLAY_HINT_HTML = """ + + +
+ {label} +
+ +""" + + +def format_inlay_hint_tooltip(view: sublime.View, tooltip: Optional[Union[str, MarkupContent]]) -> str: + if isinstance(tooltip, str): + return html.escape(tooltip) + elif isinstance(tooltip, dict): # MarkupContent + return minihtml(view, tooltip, allowed_formats=FORMAT_MARKUP_CONTENT) + else: + return "" + + +def format_inlay_hint_label(view: sublime.View, label: Union[str, List[InlayHintLabelPart]]) -> str: + if isinstance(label, str): + return html.escape(label) + else: + return "".join("
{value}
".format( + tooltip=format_inlay_hint_tooltip(view, label_part.get("tooltip")), + value=label_part.get("value") + ) for label_part in label) + + +def inlay_hint_to_phantom(view: sublime.View, inlay_hint: InlayHint) -> sublime.Phantom: + region = sublime.Region(point_to_offset(Point.from_lsp(inlay_hint["position"]), view)) + tooltip = format_inlay_hint_tooltip(view, inlay_hint.get("tooltip")) + label = format_inlay_hint_label(view, inlay_hint["label"]) + margin_left = "0.6rem" if inlay_hint.get("paddingLeft", False) else "0" + margin_right = "0.6rem" if inlay_hint.get("paddingRight", False) else "0" + content = INLAY_HINT_HTML.format( + margin_left=margin_left, + margin_right=margin_right, + tooltip=tooltip, + label=label) + return sublime.Phantom(region, content, sublime.LAYOUT_INLINE) diff --git a/plugin/session_buffer.py b/plugin/session_buffer.py index 023d274c6..54bcb09b5 100644 --- a/plugin/session_buffer.py +++ b/plugin/session_buffer.py @@ -2,6 +2,8 @@ from .core.protocol import DiagnosticSeverity from .core.protocol import DocumentLink from .core.protocol import DocumentUri +from .core.protocol import InlayHintParams +from .core.protocol import InlayHintResponse from .core.protocol import Range from .core.protocol import Request from .core.protocol import TextDocumentSyncKindFull @@ -28,6 +30,7 @@ from .core.views import region_to_range from .core.views import text_document_identifier from .core.views import will_save +from .inlay_hint import inlay_hint_to_phantom from .semantic_highlighting import SemanticToken from weakref import WeakSet import sublime @@ -143,6 +146,7 @@ def _check_did_open(self, view: sublime.View) -> None: self.opened = True self._do_color_boxes_async(view, view.change_count()) self.do_semantic_tokens_async(view) + self.do_inlay_hints_async(view) if userprefs().link_highlight_style in ("underline", "none"): self._do_document_link_async(view, view.change_count()) self.session.notify_plugin_on_session_buffer_change(self) @@ -288,6 +292,7 @@ def purge_changes_async(self, view: sublime.View) -> None: self.do_semantic_tokens_async(view) if userprefs().link_highlight_style in ("underline", "none"): self._do_document_link_async(view, version) + self.do_inlay_hints_async(view) self.session.notify_plugin_on_session_buffer_change(self) def on_pre_save_async(self, view: sublime.View) -> None: @@ -611,7 +616,26 @@ def set_semantic_tokens_pending_refresh(self, needs_refresh: bool = True) -> Non def get_semantic_tokens(self) -> List[SemanticToken]: return self.semantic_tokens.tokens - # ------------------------------------------------------------------------------------------------------------------ + def do_inlay_hints_async(self, view: sublime.View) -> None: + if not self.session.has_capability("inlayHintProvider"): + return + params = { + "textDocument": text_document_identifier(view), + # "range": region_to_range(view, view.visible_region()).to_lsp() + "range": region_to_range(view, sublime.Region(0, view.size())).to_lsp() + } # type: InlayHintParams + + request = Request.inlayHint(params, view) + self.session.send_request_async(request, self._on_inlay_hints_async) + + def _on_inlay_hints_async(self, response: InlayHintResponse) -> None: + if response: + view = self.some_view() + if not view: + return + phantoms = [inlay_hint_to_phantom(view, inlay_hint) for inlay_hint in response] + for sv in self.session_views: + sublime.set_timeout(lambda: sv.present_inlay_hints_async(phantoms)) def __str__(self) -> str: return '{}:{}:{}'.format(self.session.config.name, self.id, self.get_uri()) diff --git a/plugin/session_view.py b/plugin/session_view.py index 48f5c5b36..819d148d7 100644 --- a/plugin/session_view.py +++ b/plugin/session_view.py @@ -45,6 +45,7 @@ def __init__(self, listener: AbstractViewListener, session: Session, uri: Docume self._listener = ref(listener) self.progress = {} # type: Dict[int, ViewProgressReporter] self._code_lenses = CodeLensView(self._view) + self._inlay_hints_phantom_set = sublime.PhantomSet(self._view, "lsp_inlay_hints") settings = self._view.settings() buffer_id = self._view.buffer_id() key = (id(session), buffer_id) @@ -379,5 +380,12 @@ def _on_code_lenses_resolved_async(self, mode: str) -> None: def get_resolved_code_lenses_for_region(self, region: sublime.Region) -> Generator[CodeLens, None, None]: yield from self._code_lenses.get_resolved_code_lenses_for_region(region) + # --- textDocument/inlayHint --------------------------------------------------------------------------------------- + + def present_inlay_hints_async(self, phantoms: List[sublime.Phantom]) -> None: + self._inlay_hints_phantom_set.update(phantoms) + + # ------------------------------------------------------------------------------------------------------------------ + def __str__(self) -> str: return '{}:{}'.format(self.session.config.name, self.view.id()) From e5b8147282ebd94b21d24260a5cf7fc2c5675c9e Mon Sep 17 00:00:00 2001 From: Predrag Nikolic Date: Thu, 11 Aug 2022 15:04:29 +0200 Subject: [PATCH 02/65] use system font family for inlay hints --- plugin/inlay_hint.py | 1 + 1 file changed, 1 insertion(+) diff --git a/plugin/inlay_hint.py b/plugin/inlay_hint.py index ffa66bfb8..0db249e92 100644 --- a/plugin/inlay_hint.py +++ b/plugin/inlay_hint.py @@ -15,6 +15,7 @@ margin-right: {margin_right}; padding: 0.05em 4px; font-size: 0.9em; + font-family: system; }}
From 375ff3a6fa796ee7d3b3952d6e84ff9d8dcf428c Mon Sep 17 00:00:00 2001 From: Predrag Nikolic Date: Fri, 12 Aug 2022 11:17:44 +0200 Subject: [PATCH 03/65] handle inlay hint text edits --- boot.py | 1 + plugin/core/protocol.py | 4 ++++ plugin/formatting.py | 10 +++++----- plugin/inlay_hint.py | 36 +++++++++++++++++++++++++++++++----- plugin/session_buffer.py | 2 +- 5 files changed, 42 insertions(+), 11 deletions(-) diff --git a/boot.py b/boot.py index f2057e1b1..5a5ec050d 100644 --- a/boot.py +++ b/boot.py @@ -48,6 +48,7 @@ from .plugin.goto import LspSymbolTypeDefinitionCommand from .plugin.goto_diagnostic import LspGotoDiagnosticCommand from .plugin.hover import LspHoverCommand +from .plugin.inlay_hint import LspInlayHintClickCommand from .plugin.panels import LspShowDiagnosticsPanelCommand from .plugin.panels import LspToggleServerPanelCommand from .plugin.references import LspSymbolReferencesCommand diff --git a/plugin/core/protocol.py b/plugin/core/protocol.py index f2455e8de..29ef2b204 100644 --- a/plugin/core/protocol.py +++ b/plugin/core/protocol.py @@ -457,6 +457,10 @@ def resolveDocumentLink(cls, params: DocumentLink, view: sublime.View) -> 'Reque def inlayHint(cls, params: InlayHintParams, view: sublime.View) -> 'Request': return Request('textDocument/inlayHint', params, view) + @classmethod + def resolveInlayHint(cls, params: InlayHint, view: sublime.View) -> 'Request': + return Request('inlayHint/resolve', params, view) + @classmethod def shutdown(cls) -> 'Request': return Request("shutdown") diff --git a/plugin/formatting.py b/plugin/formatting.py index b8a2c8371..18473b42f 100644 --- a/plugin/formatting.py +++ b/plugin/formatting.py @@ -31,7 +31,7 @@ def format_document(text_command: LspTextCommand) -> Promise[FormatResponse]: return Promise.resolve(None) -def apply_response_to_view(response: Optional[List[TextEdit]], view: sublime.View) -> None: +def apply_text_edits_to_view(response: Optional[List[TextEdit]], view: sublime.View) -> None: edits = list(parse_text_edit(change) for change in response) if response else [] view.run_command('lsp_apply_document_edit', {'changes': edits}) @@ -66,7 +66,7 @@ def _will_save_wait_until_async(self, session: Session) -> None: def _on_response(self, response: Any) -> None: if response and not self._cancelled: - apply_response_to_view(response, self._task_runner.view) + apply_text_edits_to_view(response, self._task_runner.view) sublime.set_timeout_async(self._handle_next_session_async) @@ -85,7 +85,7 @@ def run_async(self) -> None: def _on_response(self, response: FormatResponse) -> None: if response and not isinstance(response, Error) and not self._cancelled: - apply_response_to_view(response, self._task_runner.view) + apply_text_edits_to_view(response, self._task_runner.view) sublime.set_timeout_async(self._on_complete) @@ -105,7 +105,7 @@ def run(self, edit: sublime.Edit, event: Optional[dict] = None) -> None: def on_result(self, result: FormatResponse) -> None: if result and not isinstance(result, Error): - apply_response_to_view(result, self.view) + apply_text_edits_to_view(result, self.view) class LspFormatDocumentRangeCommand(LspTextCommand): @@ -125,4 +125,4 @@ def run(self, edit: sublime.Edit, event: Optional[dict] = None) -> None: selection = first_selection_region(self.view) if session and selection is not None: req = text_document_range_formatting(self.view, selection) - session.send_request(req, lambda response: apply_response_to_view(response, self.view)) + session.send_request(req, lambda response: apply_text_edits_to_view(response, self.view)) diff --git a/plugin/inlay_hint.py b/plugin/inlay_hint.py index 0db249e92..d30b14c90 100644 --- a/plugin/inlay_hint.py +++ b/plugin/inlay_hint.py @@ -1,14 +1,33 @@ -from .core.protocol import InlayHintLabelPart, MarkupContent, Point, InlayHint +from .core.protocol import InlayHintLabelPart, MarkupContent, Point, InlayHint, Request +from .core.registry import LspTextCommand from .core.typing import List, Optional, Union from .core.views import FORMAT_MARKUP_CONTENT, point_to_offset, minihtml +from .formatting import apply_text_edits_to_view import html import sublime + +class LspInlayHintClickCommand(LspTextCommand): + capability = 'inlayHintProvider' + + def run(self, _edit: sublime.Edit, session_name: str, inlay_hint: InlayHint, event: Optional[dict] = None) -> None: + session = self.session_by_name(session_name, 'inlayHintProvider.resolveProvider') + if session: + request = Request.resolveInlayHint(inlay_hint, self.view) + session.send_request_async(request, self.handle) + return + self.handle(inlay_hint) + + def handle(self, inlay_hint: InlayHint) -> None: + text_edits = inlay_hint.get('textEdits') + if text_edits: + apply_text_edits_to_view(text_edits, self.view) + + INLAY_HINT_HTML = """
- {label} + {label}
""" @@ -44,15 +68,17 @@ def format_inlay_hint_label(view: sublime.View, label: Union[str, List[InlayHint ) for label_part in label) -def inlay_hint_to_phantom(view: sublime.View, inlay_hint: InlayHint) -> sublime.Phantom: +def inlay_hint_to_phantom(view: sublime.View, inlay_hint: InlayHint, session_name: str) -> sublime.Phantom: region = sublime.Region(point_to_offset(Point.from_lsp(inlay_hint["position"]), view)) tooltip = format_inlay_hint_tooltip(view, inlay_hint.get("tooltip")) label = format_inlay_hint_label(view, inlay_hint["label"]) margin_left = "0.6rem" if inlay_hint.get("paddingLeft", False) else "0" margin_right = "0.6rem" if inlay_hint.get("paddingRight", False) else "0" + command = sublime.command_url('lsp_inlay_hint_click', {'session_name': session_name, 'inlay_hint': inlay_hint}) content = INLAY_HINT_HTML.format( margin_left=margin_left, margin_right=margin_right, tooltip=tooltip, - label=label) + label=label, + command=command) return sublime.Phantom(region, content, sublime.LAYOUT_INLINE) diff --git a/plugin/session_buffer.py b/plugin/session_buffer.py index 54bcb09b5..79a87ccf2 100644 --- a/plugin/session_buffer.py +++ b/plugin/session_buffer.py @@ -633,7 +633,7 @@ def _on_inlay_hints_async(self, response: InlayHintResponse) -> None: view = self.some_view() if not view: return - phantoms = [inlay_hint_to_phantom(view, inlay_hint) for inlay_hint in response] + phantoms = [inlay_hint_to_phantom(view, inlay_hint, self.session.config.name) for inlay_hint in response] for sv in self.session_views: sublime.set_timeout(lambda: sv.present_inlay_hints_async(phantoms)) From 48a65f2b687ca3046bfa0c80c9a18e08ac4d6a12 Mon Sep 17 00:00:00 2001 From: Predrag Nikolic Date: Fri, 12 Aug 2022 11:41:09 +0200 Subject: [PATCH 04/65] handle inlay hint commands --- plugin/inlay_hint.py | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/plugin/inlay_hint.py b/plugin/inlay_hint.py index d30b14c90..19164e50c 100644 --- a/plugin/inlay_hint.py +++ b/plugin/inlay_hint.py @@ -14,15 +14,34 @@ def run(self, _edit: sublime.Edit, session_name: str, inlay_hint: InlayHint, eve session = self.session_by_name(session_name, 'inlayHintProvider.resolveProvider') if session: request = Request.resolveInlayHint(inlay_hint, self.view) - session.send_request_async(request, self.handle) + session.send_request_async(request, lambda response: self.handle(session_name, response)) return - self.handle(inlay_hint) + self.handle(session_name, inlay_hint) - def handle(self, inlay_hint: InlayHint) -> None: + def handle(self, session_name: str, inlay_hint: InlayHint) -> None: + self.handle_inlay_hint_text_edits(inlay_hint) + self.handle_inlay_hint_command(session_name, inlay_hint) + + def handle_inlay_hint_text_edits(self, inlay_hint: InlayHint) -> None: text_edits = inlay_hint.get('textEdits') if text_edits: apply_text_edits_to_view(text_edits, self.view) + def handle_inlay_hint_command(self, session_name: str, inlay_hint: InlayHint) -> None: + label_parts = inlay_hint.get('label') + if not isinstance(label_parts, list): + return + for label_part in label_parts: + command = label_part.get('command') + if not command: + continue + args = { + "session_name": session_name, + "command_name": command["command"], + "command_args": command["arguments"] + } + self.view.run_command("lsp_execute", args) + INLAY_HINT_HTML = """ From 0ba49069a2f76d745a25a2fe12ac886cd29c7863 Mon Sep 17 00:00:00 2001 From: Predrag Nikolic Date: Fri, 12 Aug 2022 11:41:55 +0200 Subject: [PATCH 05/65] mark unused event with _ --- plugin/inlay_hint.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/inlay_hint.py b/plugin/inlay_hint.py index 19164e50c..98c7eea40 100644 --- a/plugin/inlay_hint.py +++ b/plugin/inlay_hint.py @@ -10,7 +10,7 @@ class LspInlayHintClickCommand(LspTextCommand): capability = 'inlayHintProvider' - def run(self, _edit: sublime.Edit, session_name: str, inlay_hint: InlayHint, event: Optional[dict] = None) -> None: + def run(self, _edit: sublime.Edit, session_name: str, inlay_hint: InlayHint, _event: Optional[dict] = None) -> None: session = self.session_by_name(session_name, 'inlayHintProvider.resolveProvider') if session: request = Request.resolveInlayHint(inlay_hint, self.view) From 4e4338685c7dc2aa1d4012dcb07b8240dcdd1b36 Mon Sep 17 00:00:00 2001 From: Predrag Nikolic Date: Fri, 12 Aug 2022 11:47:48 +0200 Subject: [PATCH 06/65] add resolvable properties --- plugin/core/sessions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/core/sessions.py b/plugin/core/sessions.py index 72fd85684..71e43e38c 100644 --- a/plugin/core/sessions.py +++ b/plugin/core/sessions.py @@ -354,7 +354,7 @@ def get_initialize_params(variables: Dict[str, str], workspace_folders: List[Wor "inlayHint": { "dynamicRegistration": True, "resolveSupport": { - "properties": [] + "properties": ["textEdits", "label.command"] # not sure if I can just put "command" because the command is nested in the label } }, "semanticTokens": { From 7b691d2e9f9ac5859897522d014158a042f44bc0 Mon Sep 17 00:00:00 2001 From: Predrag Nikolic Date: Fri, 12 Aug 2022 12:02:34 +0200 Subject: [PATCH 07/65] fix pyflake --- plugin/core/sessions.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugin/core/sessions.py b/plugin/core/sessions.py index 71e43e38c..895feba4a 100644 --- a/plugin/core/sessions.py +++ b/plugin/core/sessions.py @@ -354,7 +354,8 @@ def get_initialize_params(variables: Dict[str, str], workspace_folders: List[Wor "inlayHint": { "dynamicRegistration": True, "resolveSupport": { - "properties": ["textEdits", "label.command"] # not sure if I can just put "command" because the command is nested in the label + # not sure if I can just put "command" because the command is nested in the label + "properties": ["textEdits", "label.command"] } }, "semanticTokens": { From 90fb030b8ded26a9881dd7154a59e3967309a222 Mon Sep 17 00:00:00 2001 From: Predrag Nikolic Date: Fri, 12 Aug 2022 12:03:09 +0200 Subject: [PATCH 08/65] use command instead of label.command --- plugin/core/sessions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/core/sessions.py b/plugin/core/sessions.py index 895feba4a..bf0fdd6ca 100644 --- a/plugin/core/sessions.py +++ b/plugin/core/sessions.py @@ -355,7 +355,7 @@ def get_initialize_params(variables: Dict[str, str], workspace_folders: List[Wor "dynamicRegistration": True, "resolveSupport": { # not sure if I can just put "command" because the command is nested in the label - "properties": ["textEdits", "label.command"] + "properties": ["textEdits", "command"] } }, "semanticTokens": { From 21fb6e04e515a4ce341cf4d7b28ec331f33f6151 Mon Sep 17 00:00:00 2001 From: Predrag Nikolic Date: Fri, 12 Aug 2022 12:35:32 +0200 Subject: [PATCH 09/65] add show_inlay_hints setting, and ability to toggle that setting through a keybinding or the command palette with LSP: Toggle Inlay Hints --- Default.sublime-commands | 4 ++++ Default.sublime-keymap | 14 ++++++++++++++ LSP.sublime-settings | 3 +++ boot.py | 1 + plugin/core/types.py | 2 ++ plugin/inlay_hint.py | 10 ++++++++++ plugin/session_buffer.py | 2 ++ sublime-package.json | 7 ++++++- 8 files changed, 42 insertions(+), 1 deletion(-) diff --git a/Default.sublime-commands b/Default.sublime-commands index bd9c22766..c83f2b59e 100644 --- a/Default.sublime-commands +++ b/Default.sublime-commands @@ -126,5 +126,9 @@ { "caption": "LSP: Find References", "command": "lsp_symbol_references" + }, + { + "caption": "LSP: Toggle Inlay Hints", + "command": "lsp_toggle_inlay_hints" } ] diff --git a/Default.sublime-keymap b/Default.sublime-keymap index 6e4298d3a..620ca977e 100644 --- a/Default.sublime-keymap +++ b/Default.sublime-keymap @@ -389,6 +389,20 @@ // } // ] // }, + // Toggle inlay hints. + // { + // "command": "lsp_toggle_inlay_hints", + // "keys": [ + // "UNBOUND" + // ], + // "context": [ + // { + // "key": "lsp.session_with_capability", + // "operator": "equal", + // "operand": "inlayHintProvider" + // } + // ] + // }, // Internal key-binding { "keys": [ diff --git a/LSP.sublime-settings b/LSP.sublime-settings index 9cecd3af9..f2c95fc84 100644 --- a/LSP.sublime-settings +++ b/LSP.sublime-settings @@ -134,6 +134,9 @@ // "phantom" - show a phantom on the top when code actions are available "show_code_lens": "annotation", + // Show inlay hints + "show_inlay_hints": true, + // Show code actions in hover popup if available "show_code_actions_in_hover": true, diff --git a/boot.py b/boot.py index 5a5ec050d..b6d9bf426 100644 --- a/boot.py +++ b/boot.py @@ -49,6 +49,7 @@ from .plugin.goto_diagnostic import LspGotoDiagnosticCommand from .plugin.hover import LspHoverCommand from .plugin.inlay_hint import LspInlayHintClickCommand +from .plugin.inlay_hint import LspToggleInlayHintsCommand from .plugin.panels import LspShowDiagnosticsPanelCommand from .plugin.panels import LspToggleServerPanelCommand from .plugin.references import LspSymbolReferencesCommand diff --git a/plugin/core/types.py b/plugin/core/types.py index 85d352167..aa43d8bec 100644 --- a/plugin/core/types.py +++ b/plugin/core/types.py @@ -206,6 +206,7 @@ class Settings: semantic_highlighting = None # type: bool show_code_actions = None # type: str show_code_lens = None # type: str + show_inlay_hints = None # type: bool show_code_actions_in_hover = None # type: bool show_diagnostics_count_in_view_status = None # type: bool show_multiline_diagnostics_highlights = None # type: bool @@ -243,6 +244,7 @@ def r(name: str, default: Union[bool, int, str, list, dict]) -> None: r("semantic_highlighting", False) r("show_code_actions", "annotation") r("show_code_lens", "annotation") + r("show_inlay_hints", True) r("show_code_actions_in_hover", True) r("show_diagnostics_count_in_view_status", False) r("show_diagnostics_in_view_status", True) diff --git a/plugin/inlay_hint.py b/plugin/inlay_hint.py index 98c7eea40..e61a82d80 100644 --- a/plugin/inlay_hint.py +++ b/plugin/inlay_hint.py @@ -7,6 +7,16 @@ import sublime +class LspToggleInlayHintsCommand(LspTextCommand): + capability = 'inlayHintProvider' + + def run(self, _edit: sublime.Edit, _event: Optional[dict] = None) -> None: + settings = sublime.load_settings("LSP.sublime-settings") + show_inlay_hints = settings.get("show_inlay_hints", False) + settings.set("show_inlay_hints", not show_inlay_hints) + sublime.save_settings("LSP.sublime-settings") + + class LspInlayHintClickCommand(LspTextCommand): capability = 'inlayHintProvider' diff --git a/plugin/session_buffer.py b/plugin/session_buffer.py index 79a87ccf2..dce1557d9 100644 --- a/plugin/session_buffer.py +++ b/plugin/session_buffer.py @@ -617,6 +617,8 @@ def get_semantic_tokens(self) -> List[SemanticToken]: return self.semantic_tokens.tokens def do_inlay_hints_async(self, view: sublime.View) -> None: + if not userprefs().show_inlay_hints: + return if not self.session.has_capability("inlayHintProvider"): return params = { diff --git a/sublime-package.json b/sublime-package.json index 73927b458..bc2b7469d 100644 --- a/sublime-package.json +++ b/sublime-package.json @@ -508,7 +508,12 @@ "$ref": "sublime://settings/LSP#/definitions/ClientConfig" }, "markdownDescription": "**DO NOT MODIFY THIS SETTING!** Use `\"clients\"` to override settings instead!", - } + }, + "show_inlay_hints": { + "type": "boolean", + "default": true, + "markdownDescription": "Show inlay hints." + }, }, "additionalProperties": false } From ea953eb6cfffc5df0cd615bfa94f96776381bef5 Mon Sep 17 00:00:00 2001 From: Predrag Nikolic Date: Fri, 12 Aug 2022 12:40:38 +0200 Subject: [PATCH 10/65] haha cannot name event "_event" --- plugin/inlay_hint.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/inlay_hint.py b/plugin/inlay_hint.py index e61a82d80..3d47deba3 100644 --- a/plugin/inlay_hint.py +++ b/plugin/inlay_hint.py @@ -20,7 +20,7 @@ def run(self, _edit: sublime.Edit, _event: Optional[dict] = None) -> None: class LspInlayHintClickCommand(LspTextCommand): capability = 'inlayHintProvider' - def run(self, _edit: sublime.Edit, session_name: str, inlay_hint: InlayHint, _event: Optional[dict] = None) -> None: + def run(self, _edit: sublime.Edit, session_name: str, inlay_hint: InlayHint, event: Optional[dict] = None) -> None: session = self.session_by_name(session_name, 'inlayHintProvider.resolveProvider') if session: request = Request.resolveInlayHint(inlay_hint, self.view) From 83b152ef8fedb5586671c55ccd12fb9e087b02da Mon Sep 17 00:00:00 2001 From: Predrag Nikolic Date: Fri, 12 Aug 2022 12:50:29 +0200 Subject: [PATCH 11/65] fix use monospace instead of system --- plugin/inlay_hint.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/inlay_hint.py b/plugin/inlay_hint.py index 3d47deba3..b90e21220 100644 --- a/plugin/inlay_hint.py +++ b/plugin/inlay_hint.py @@ -63,7 +63,7 @@ def handle_inlay_hint_command(self, session_name: str, inlay_hint: InlayHint) -> margin-right: {margin_right}; padding: 0.05em 4px; font-size: 0.9em; - font-family: system; + font-family: monospace; }} .inlay-hint a {{ From a8f30ed7e17f27344a6a544caec571057ca19195 Mon Sep 17 00:00:00 2001 From: Predrag Nikolic Date: Fri, 12 Aug 2022 13:22:07 +0200 Subject: [PATCH 12/65] implement workspace/inlayHint/refresh haven't tested this --- plugin/core/sessions.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/plugin/core/sessions.py b/plugin/core/sessions.py index 196d35d0d..68ade180a 100644 --- a/plugin/core/sessions.py +++ b/plugin/core/sessions.py @@ -555,6 +555,9 @@ def set_semantic_tokens_pending_refresh(self, needs_refresh: bool = True) -> Non def get_semantic_tokens(self) -> List[Any]: ... + def do_inlay_hints_async(self, view: sublime.View) -> None: + ... + class AbstractViewListener(metaclass=ABCMeta): @@ -1635,6 +1638,12 @@ def m_workspace_semanticTokens_refresh(self, params: Any, request_id: Any) -> No else: sv.session_buffer.set_semantic_tokens_pending_refresh() + def m_workspace_inlayHint_refresh(self, params: None, request_id: Any) -> None: + """handles the workspace/inlayHint/refresh request""" + for sv in self.session_views_async(): + sv.session_buffer.do_inlay_hints_async(sv.view) + self.send_response(Response(request_id, None)) + def m_textDocument_publishDiagnostics(self, params: Any) -> None: """handles the textDocument/publishDiagnostics notification""" uri = params["uri"] From fcb6ec5165c3d7ef41a43b404541e09846a7ed91 Mon Sep 17 00:00:00 2001 From: Predrag Nikolic Date: Fri, 12 Aug 2022 13:36:24 +0200 Subject: [PATCH 13/65] run inlay hints when focusing the view to re-fetch the newest inlay hints to avoid showing stale inlay hints. --- plugin/documents.py | 1 + 1 file changed, 1 insertion(+) diff --git a/plugin/documents.py b/plugin/documents.py index f3d8fd78a..89fd9d9d4 100644 --- a/plugin/documents.py +++ b/plugin/documents.py @@ -342,6 +342,7 @@ def on_activated_async(self) -> None: if sb.semantic_tokens.needs_refresh: sb.semantic_tokens.needs_refresh = False sb.do_semantic_tokens_async(self.view) + sb.do_inlay_hints_async(self.view) def on_selection_modified_async(self) -> None: different, current_region = self._update_stored_region_async() From 730e47d1d2843f03b1eb9741108590ac78e07574 Mon Sep 17 00:00:00 2001 From: Predrag Nikolic Date: Fri, 12 Aug 2022 14:32:11 +0200 Subject: [PATCH 14/65] remove phantom when they are clicked if they have textEdits In order to follow the spec more precisly /** * ... * * *Note* that edits are expected to change the document so that the inlay * hint (or its nearest variant) is now part of the document and the inlay * hint itself is **now obsolete**. * * ... */ textEdits?: TextEdit[]; Phantoms have an id but we cannot rely on that field because it is none at the time of creating the Phantom. It is creted only when the phantom_set is created. Instead attach a custom lsp_uuid field on the phantom --- plugin/core/sessions.py | 3 +++ plugin/inlay_hint.py | 40 +++++++++++++++++++++++++--------------- plugin/session_view.py | 10 ++++++++++ 3 files changed, 38 insertions(+), 15 deletions(-) diff --git a/plugin/core/sessions.py b/plugin/core/sessions.py index 68ade180a..d4f8e1e7e 100644 --- a/plugin/core/sessions.py +++ b/plugin/core/sessions.py @@ -500,6 +500,9 @@ def start_code_lenses_async(self) -> None: def present_inlay_hints_async(self, phantoms: List[sublime.Phantom]) -> None: ... + def remove_inlay_hint_phantom(self, phantom_uuid: str) -> None: + ... + class SessionBufferProtocol(Protocol): diff --git a/plugin/inlay_hint.py b/plugin/inlay_hint.py index b90e21220..96c86f967 100644 --- a/plugin/inlay_hint.py +++ b/plugin/inlay_hint.py @@ -1,10 +1,12 @@ from .core.protocol import InlayHintLabelPart, MarkupContent, Point, InlayHint, Request from .core.registry import LspTextCommand +from .core.sessions import Session from .core.typing import List, Optional, Union from .core.views import FORMAT_MARKUP_CONTENT, point_to_offset, minihtml from .formatting import apply_text_edits_to_view import html import sublime +import uuid class LspToggleInlayHintsCommand(LspTextCommand): @@ -20,24 +22,29 @@ def run(self, _edit: sublime.Edit, _event: Optional[dict] = None) -> None: class LspInlayHintClickCommand(LspTextCommand): capability = 'inlayHintProvider' - def run(self, _edit: sublime.Edit, session_name: str, inlay_hint: InlayHint, event: Optional[dict] = None) -> None: - session = self.session_by_name(session_name, 'inlayHintProvider.resolveProvider') - if session: + def run(self, _edit: sublime.Edit, session_name: str, inlay_hint: InlayHint, phantom_uuid: str, event: Optional[dict] = None) -> None: + session = self.session_by_name(session_name, 'inlayHintProvider') + if not session: + return + if session.has_capability('inlayHintProvider.resolveProvider'): request = Request.resolveInlayHint(inlay_hint, self.view) - session.send_request_async(request, lambda response: self.handle(session_name, response)) + session.send_request_async(request, lambda response: self.handle(session, response, phantom_uuid)) return - self.handle(session_name, inlay_hint) + self.handle(session, inlay_hint, phantom_uuid) - def handle(self, session_name: str, inlay_hint: InlayHint) -> None: - self.handle_inlay_hint_text_edits(inlay_hint) - self.handle_inlay_hint_command(session_name, inlay_hint) + def handle(self, session: Session, inlay_hint: InlayHint, phantom_uuid: str) -> None: + self.handle_inlay_hint_text_edits(session, inlay_hint, phantom_uuid) + self.handle_inlay_hint_command(session, inlay_hint) - def handle_inlay_hint_text_edits(self, inlay_hint: InlayHint) -> None: + def handle_inlay_hint_text_edits(self, session: Session, inlay_hint: InlayHint, phantom_uuid: str) -> None: text_edits = inlay_hint.get('textEdits') - if text_edits: - apply_text_edits_to_view(text_edits, self.view) + if not text_edits: + return + for sv in session.session_views_async(): + sv.remove_inlay_hint_phantom(phantom_uuid) + apply_text_edits_to_view(text_edits, self.view) - def handle_inlay_hint_command(self, session_name: str, inlay_hint: InlayHint) -> None: + def handle_inlay_hint_command(self, session: Session, inlay_hint: InlayHint) -> None: label_parts = inlay_hint.get('label') if not isinstance(label_parts, list): return @@ -46,7 +53,7 @@ def handle_inlay_hint_command(self, session_name: str, inlay_hint: InlayHint) -> if not command: continue args = { - "session_name": session_name, + "session_name": session.config.name, "command_name": command["command"], "command_args": command["arguments"] } @@ -103,11 +110,14 @@ def inlay_hint_to_phantom(view: sublime.View, inlay_hint: InlayHint, session_nam label = format_inlay_hint_label(view, inlay_hint["label"]) margin_left = "0.6rem" if inlay_hint.get("paddingLeft", False) else "0" margin_right = "0.6rem" if inlay_hint.get("paddingRight", False) else "0" - command = sublime.command_url('lsp_inlay_hint_click', {'session_name': session_name, 'inlay_hint': inlay_hint}) + phantom_uuid = str(uuid.uuid4()) + command = sublime.command_url('lsp_inlay_hint_click', {'session_name': session_name, 'inlay_hint': inlay_hint, 'phantom_uuid': phantom_uuid}) content = INLAY_HINT_HTML.format( margin_left=margin_left, margin_right=margin_right, tooltip=tooltip, label=label, command=command) - return sublime.Phantom(region, content, sublime.LAYOUT_INLINE) + p = sublime.Phantom(region, content, sublime.LAYOUT_INLINE) + setattr(p, 'lsp_uuid', phantom_uuid) + return p diff --git a/plugin/session_view.py b/plugin/session_view.py index 819d148d7..a8991e655 100644 --- a/plugin/session_view.py +++ b/plugin/session_view.py @@ -385,6 +385,16 @@ def get_resolved_code_lenses_for_region(self, region: sublime.Region) -> Generat def present_inlay_hints_async(self, phantoms: List[sublime.Phantom]) -> None: self._inlay_hints_phantom_set.update(phantoms) + def remove_inlay_hint_phantom(self, phantom_uuid: str) -> None: + for p in self._inlay_hints_phantom_set.phantoms: + print(getattr(p, 'lsp_uuid')) + + new_phantoms = list(filter( + lambda p: getattr(p, 'lsp_uuid') != phantom_uuid, + self._inlay_hints_phantom_set.phantoms) + ) + self._inlay_hints_phantom_set.update(new_phantoms) + # ------------------------------------------------------------------------------------------------------------------ def __str__(self) -> str: From f6932b88f005b7c2aacc06de41982a3681cf660d Mon Sep 17 00:00:00 2001 From: Predrag Nikolic Date: Fri, 12 Aug 2022 14:56:33 +0200 Subject: [PATCH 15/65] make mypy and pyflake happy --- plugin/inlay_hint.py | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/plugin/inlay_hint.py b/plugin/inlay_hint.py index 96c86f967..eac287958 100644 --- a/plugin/inlay_hint.py +++ b/plugin/inlay_hint.py @@ -1,6 +1,5 @@ from .core.protocol import InlayHintLabelPart, MarkupContent, Point, InlayHint, Request from .core.registry import LspTextCommand -from .core.sessions import Session from .core.typing import List, Optional, Union from .core.views import FORMAT_MARKUP_CONTENT, point_to_offset, minihtml from .formatting import apply_text_edits_to_view @@ -22,21 +21,23 @@ def run(self, _edit: sublime.Edit, _event: Optional[dict] = None) -> None: class LspInlayHintClickCommand(LspTextCommand): capability = 'inlayHintProvider' - def run(self, _edit: sublime.Edit, session_name: str, inlay_hint: InlayHint, phantom_uuid: str, event: Optional[dict] = None) -> None: + def run(self, _edit: sublime.Edit, session_name: str, inlay_hint: InlayHint, phantom_uuid: str, + event: Optional[dict] = None) -> None: session = self.session_by_name(session_name, 'inlayHintProvider') - if not session: - return - if session.has_capability('inlayHintProvider.resolveProvider'): + if session and session.has_capability('inlayHintProvider.resolveProvider'): request = Request.resolveInlayHint(inlay_hint, self.view) - session.send_request_async(request, lambda response: self.handle(session, response, phantom_uuid)) + session.send_request_async(request, lambda response: self.handle(session_name, response, phantom_uuid)) return - self.handle(session, inlay_hint, phantom_uuid) + self.handle(session_name, inlay_hint, phantom_uuid) - def handle(self, session: Session, inlay_hint: InlayHint, phantom_uuid: str) -> None: - self.handle_inlay_hint_text_edits(session, inlay_hint, phantom_uuid) - self.handle_inlay_hint_command(session, inlay_hint) + def handle(self, session_name: str, inlay_hint: InlayHint, phantom_uuid: str) -> None: + self.handle_inlay_hint_text_edits(session_name, inlay_hint, phantom_uuid) + self.handle_inlay_hint_command(session_name, inlay_hint) - def handle_inlay_hint_text_edits(self, session: Session, inlay_hint: InlayHint, phantom_uuid: str) -> None: + def handle_inlay_hint_text_edits(self, session_name: str, inlay_hint: InlayHint, phantom_uuid: str) -> None: + session = self.session_by_name(session_name, 'inlayHintProvider') + if not session: + return text_edits = inlay_hint.get('textEdits') if not text_edits: return @@ -44,7 +45,7 @@ def handle_inlay_hint_text_edits(self, session: Session, inlay_hint: InlayHint, sv.remove_inlay_hint_phantom(phantom_uuid) apply_text_edits_to_view(text_edits, self.view) - def handle_inlay_hint_command(self, session: Session, inlay_hint: InlayHint) -> None: + def handle_inlay_hint_command(self, session_name: str, inlay_hint: InlayHint) -> None: label_parts = inlay_hint.get('label') if not isinstance(label_parts, list): return @@ -53,7 +54,7 @@ def handle_inlay_hint_command(self, session: Session, inlay_hint: InlayHint) -> if not command: continue args = { - "session_name": session.config.name, + "session_name": session_name, "command_name": command["command"], "command_args": command["arguments"] } @@ -111,7 +112,11 @@ def inlay_hint_to_phantom(view: sublime.View, inlay_hint: InlayHint, session_nam margin_left = "0.6rem" if inlay_hint.get("paddingLeft", False) else "0" margin_right = "0.6rem" if inlay_hint.get("paddingRight", False) else "0" phantom_uuid = str(uuid.uuid4()) - command = sublime.command_url('lsp_inlay_hint_click', {'session_name': session_name, 'inlay_hint': inlay_hint, 'phantom_uuid': phantom_uuid}) + command = sublime.command_url('lsp_inlay_hint_click', { + 'session_name': session_name, + 'inlay_hint': inlay_hint, + 'phantom_uuid': phantom_uuid + }) content = INLAY_HINT_HTML.format( margin_left=margin_left, margin_right=margin_right, From e1979d8f5d2ea01bb38dc4ee0876b523a4f41abf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D1=80=D0=B5=D0=B4=D1=80=D0=B0=D0=B3=20=D0=9D=D0=B8?= =?UTF-8?q?=D0=BA=D0=BE=D0=BB=D0=B8=D1=9B?= Date: Fri, 12 Aug 2022 18:18:40 +0200 Subject: [PATCH 16/65] use label.command instead of command --- plugin/core/sessions.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/plugin/core/sessions.py b/plugin/core/sessions.py index d4f8e1e7e..589352be4 100644 --- a/plugin/core/sessions.py +++ b/plugin/core/sessions.py @@ -352,8 +352,7 @@ def get_initialize_params(variables: Dict[str, str], workspace_folders: List[Wor "inlayHint": { "dynamicRegistration": True, "resolveSupport": { - # not sure if I can just put "command" because the command is nested in the label - "properties": ["textEdits", "command"] + "properties": ["textEdits", "label.command"] } }, "semanticTokens": { From e9dd64c64236ebb84b23537671a99b9bdd916f25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D1=80=D0=B5=D0=B4=D1=80=D0=B0=D0=B3=20=D0=9D=D0=B8?= =?UTF-8?q?=D0=BA=D0=BE=D0=BB=D0=B8=D1=9B?= Date: Fri, 12 Aug 2022 18:42:54 +0200 Subject: [PATCH 17/65] replace LspToggleInlayHintsCommand with LspToggleSettingCommand --- Default.sublime-commands | 5 ++++- Default.sublime-keymap | 3 ++- boot.py | 2 +- plugin/configuration.py | 14 ++++++++++++++ plugin/inlay_hint.py | 10 ---------- 5 files changed, 21 insertions(+), 13 deletions(-) diff --git a/Default.sublime-commands b/Default.sublime-commands index c83f2b59e..a338d23d4 100644 --- a/Default.sublime-commands +++ b/Default.sublime-commands @@ -129,6 +129,9 @@ }, { "caption": "LSP: Toggle Inlay Hints", - "command": "lsp_toggle_inlay_hints" + "command": "lsp_toggle_setting", + "args": { + "setting": "show_inlay_hints" + } } ] diff --git a/Default.sublime-keymap b/Default.sublime-keymap index 620ca977e..d194690db 100644 --- a/Default.sublime-keymap +++ b/Default.sublime-keymap @@ -391,7 +391,8 @@ // }, // Toggle inlay hints. // { - // "command": "lsp_toggle_inlay_hints", + // "command": "lsp_toggle_setting", + // "args": {"setting": "show_inlay_hints"}, // "keys": [ // "UNBOUND" // ], diff --git a/boot.py b/boot.py index b6d9bf426..582e06ef9 100644 --- a/boot.py +++ b/boot.py @@ -11,6 +11,7 @@ from .plugin.configuration import LspDisableLanguageServerInProjectCommand from .plugin.configuration import LspEnableLanguageServerGloballyCommand from .plugin.configuration import LspEnableLanguageServerInProjectCommand +from .plugin.configuration import LspToggleSettingCommand from .plugin.core.collections import DottedDict from .plugin.core.css import load as load_css from .plugin.core.logging import exception_log @@ -49,7 +50,6 @@ from .plugin.goto_diagnostic import LspGotoDiagnosticCommand from .plugin.hover import LspHoverCommand from .plugin.inlay_hint import LspInlayHintClickCommand -from .plugin.inlay_hint import LspToggleInlayHintsCommand from .plugin.panels import LspShowDiagnosticsPanelCommand from .plugin.panels import LspToggleServerPanelCommand from .plugin.references import LspSymbolReferencesCommand diff --git a/plugin/configuration.py b/plugin/configuration.py index ec2c8031d..3807065c3 100644 --- a/plugin/configuration.py +++ b/plugin/configuration.py @@ -64,3 +64,17 @@ def _on_done(self, index: int) -> None: config_name = self._items[index] wm = windows.lookup(self.window) sublime.set_timeout_async(lambda: wm.disable_config_async(config_name)) + + +class LspToggleSettingCommand(sublime_plugin.WindowCommand): + def run(self, setting: str) -> None: + settings = sublime.load_settings("LSP.sublime-settings") + setting_value = settings.get(setting) + if not isinstance(setting_value, bool): + self.window.status_message("Expected a boolean for setting '{setting}', but received value: '{value}'".format( + setting=setting, + value=setting_value + )) + return + settings.set(setting, not setting_value) + sublime.save_settings("LSP.sublime-settings") diff --git a/plugin/inlay_hint.py b/plugin/inlay_hint.py index eac287958..468b484aa 100644 --- a/plugin/inlay_hint.py +++ b/plugin/inlay_hint.py @@ -8,16 +8,6 @@ import uuid -class LspToggleInlayHintsCommand(LspTextCommand): - capability = 'inlayHintProvider' - - def run(self, _edit: sublime.Edit, _event: Optional[dict] = None) -> None: - settings = sublime.load_settings("LSP.sublime-settings") - show_inlay_hints = settings.get("show_inlay_hints", False) - settings.set("show_inlay_hints", not show_inlay_hints) - sublime.save_settings("LSP.sublime-settings") - - class LspInlayHintClickCommand(LspTextCommand): capability = 'inlayHintProvider' From 6e5f09c511ce80c6ccfa8790e644c81dd73d979b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D1=80=D0=B5=D0=B4=D1=80=D0=B0=D0=B3=20=D0=9D=D0=B8?= =?UTF-8?q?=D0=BA=D0=BE=D0=BB=D0=B8=D1=9B?= Date: Sat, 13 Aug 2022 21:47:04 +0200 Subject: [PATCH 18/65] Revert "replace LspToggleInlayHintsCommand with LspToggleSettingCommand" This reverts commit e9dd64c64236ebb84b23537671a99b9bdd916f25. --- Default.sublime-commands | 5 +---- Default.sublime-keymap | 3 +-- boot.py | 2 +- plugin/configuration.py | 14 -------------- plugin/inlay_hint.py | 10 ++++++++++ 5 files changed, 13 insertions(+), 21 deletions(-) diff --git a/Default.sublime-commands b/Default.sublime-commands index a338d23d4..c83f2b59e 100644 --- a/Default.sublime-commands +++ b/Default.sublime-commands @@ -129,9 +129,6 @@ }, { "caption": "LSP: Toggle Inlay Hints", - "command": "lsp_toggle_setting", - "args": { - "setting": "show_inlay_hints" - } + "command": "lsp_toggle_inlay_hints" } ] diff --git a/Default.sublime-keymap b/Default.sublime-keymap index d194690db..620ca977e 100644 --- a/Default.sublime-keymap +++ b/Default.sublime-keymap @@ -391,8 +391,7 @@ // }, // Toggle inlay hints. // { - // "command": "lsp_toggle_setting", - // "args": {"setting": "show_inlay_hints"}, + // "command": "lsp_toggle_inlay_hints", // "keys": [ // "UNBOUND" // ], diff --git a/boot.py b/boot.py index 582e06ef9..b6d9bf426 100644 --- a/boot.py +++ b/boot.py @@ -11,7 +11,6 @@ from .plugin.configuration import LspDisableLanguageServerInProjectCommand from .plugin.configuration import LspEnableLanguageServerGloballyCommand from .plugin.configuration import LspEnableLanguageServerInProjectCommand -from .plugin.configuration import LspToggleSettingCommand from .plugin.core.collections import DottedDict from .plugin.core.css import load as load_css from .plugin.core.logging import exception_log @@ -50,6 +49,7 @@ from .plugin.goto_diagnostic import LspGotoDiagnosticCommand from .plugin.hover import LspHoverCommand from .plugin.inlay_hint import LspInlayHintClickCommand +from .plugin.inlay_hint import LspToggleInlayHintsCommand from .plugin.panels import LspShowDiagnosticsPanelCommand from .plugin.panels import LspToggleServerPanelCommand from .plugin.references import LspSymbolReferencesCommand diff --git a/plugin/configuration.py b/plugin/configuration.py index 3807065c3..ec2c8031d 100644 --- a/plugin/configuration.py +++ b/plugin/configuration.py @@ -64,17 +64,3 @@ def _on_done(self, index: int) -> None: config_name = self._items[index] wm = windows.lookup(self.window) sublime.set_timeout_async(lambda: wm.disable_config_async(config_name)) - - -class LspToggleSettingCommand(sublime_plugin.WindowCommand): - def run(self, setting: str) -> None: - settings = sublime.load_settings("LSP.sublime-settings") - setting_value = settings.get(setting) - if not isinstance(setting_value, bool): - self.window.status_message("Expected a boolean for setting '{setting}', but received value: '{value}'".format( - setting=setting, - value=setting_value - )) - return - settings.set(setting, not setting_value) - sublime.save_settings("LSP.sublime-settings") diff --git a/plugin/inlay_hint.py b/plugin/inlay_hint.py index 468b484aa..eac287958 100644 --- a/plugin/inlay_hint.py +++ b/plugin/inlay_hint.py @@ -8,6 +8,16 @@ import uuid +class LspToggleInlayHintsCommand(LspTextCommand): + capability = 'inlayHintProvider' + + def run(self, _edit: sublime.Edit, _event: Optional[dict] = None) -> None: + settings = sublime.load_settings("LSP.sublime-settings") + show_inlay_hints = settings.get("show_inlay_hints", False) + settings.set("show_inlay_hints", not show_inlay_hints) + sublime.save_settings("LSP.sublime-settings") + + class LspInlayHintClickCommand(LspTextCommand): capability = 'inlayHintProvider' From 16d1b32a8c018f041df6a2930bb7f86461285f21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D1=80=D0=B5=D0=B4=D1=80=D0=B0=D0=B3=20=D0=9D=D0=B8?= =?UTF-8?q?=D0=BA=D0=BE=D0=BB=D0=B8=D1=9B?= Date: Sat, 13 Aug 2022 23:22:06 +0200 Subject: [PATCH 19/65] Do not re-initialize server when toggling inlay hints --- plugin/core/sessions.py | 3 +++ plugin/core/types.py | 7 ++++++- plugin/inlay_hint.py | 10 ++++++---- plugin/session_buffer.py | 6 +++++- plugin/session_view.py | 5 +++++ 5 files changed, 25 insertions(+), 6 deletions(-) diff --git a/plugin/core/sessions.py b/plugin/core/sessions.py index 589352be4..53e000a20 100644 --- a/plugin/core/sessions.py +++ b/plugin/core/sessions.py @@ -502,6 +502,9 @@ def present_inlay_hints_async(self, phantoms: List[sublime.Phantom]) -> None: def remove_inlay_hint_phantom(self, phantom_uuid: str) -> None: ... + def remove_all_inlay_hints(self) -> None: + ... + class SessionBufferProtocol(Protocol): diff --git a/plugin/core/types.py b/plugin/core/types.py index aa43d8bec..616c575c2 100644 --- a/plugin/core/types.py +++ b/plugin/core/types.py @@ -33,6 +33,11 @@ }, total=False) +class TemporarySettings: + """ Changing TemporarySettings will not cause server re-initialization. """ + SHOW_INLAY_HINTS = False # type: bool + + def basescope2languageid(base_scope: str) -> str: # This the connection between Language IDs and ST selectors. base_scope_map = sublime.load_settings("language-ids.sublime-settings") @@ -219,9 +224,9 @@ class Settings: def __init__(self, s: sublime.Settings) -> None: self.update(s) + TemporarySettings.SHOW_INLAY_HINTS = self.show_inlay_hints def update(self, s: sublime.Settings) -> None: - def r(name: str, default: Union[bool, int, str, list, dict]) -> None: val = s.get(name) setattr(self, name, val if isinstance(val, default.__class__) else default) diff --git a/plugin/inlay_hint.py b/plugin/inlay_hint.py index eac287958..6d7d70ef4 100644 --- a/plugin/inlay_hint.py +++ b/plugin/inlay_hint.py @@ -6,16 +6,18 @@ import html import sublime import uuid +from .core.types import TemporarySettings class LspToggleInlayHintsCommand(LspTextCommand): capability = 'inlayHintProvider' def run(self, _edit: sublime.Edit, _event: Optional[dict] = None) -> None: - settings = sublime.load_settings("LSP.sublime-settings") - show_inlay_hints = settings.get("show_inlay_hints", False) - settings.set("show_inlay_hints", not show_inlay_hints) - sublime.save_settings("LSP.sublime-settings") + sessions = self.sessions('inlayHintProvider') + TemporarySettings.SHOW_INLAY_HINTS = not TemporarySettings.SHOW_INLAY_HINTS + for session in sessions: + for sv in session.session_views_async(): + sv.session_buffer.do_inlay_hints_async(sv.view) class LspInlayHintClickCommand(LspTextCommand): diff --git a/plugin/session_buffer.py b/plugin/session_buffer.py index dce1557d9..9e6f71b7e 100644 --- a/plugin/session_buffer.py +++ b/plugin/session_buffer.py @@ -31,6 +31,7 @@ from .core.views import text_document_identifier from .core.views import will_save from .inlay_hint import inlay_hint_to_phantom +from .core.types import TemporarySettings from .semantic_highlighting import SemanticToken from weakref import WeakSet import sublime @@ -617,7 +618,10 @@ def get_semantic_tokens(self) -> List[SemanticToken]: return self.semantic_tokens.tokens def do_inlay_hints_async(self, view: sublime.View) -> None: - if not userprefs().show_inlay_hints: + if not TemporarySettings.SHOW_INLAY_HINTS: + # remove inlay hints + for sv in self.session_views: + sv.remove_all_inlay_hints() return if not self.session.has_capability("inlayHintProvider"): return diff --git a/plugin/session_view.py b/plugin/session_view.py index a8991e655..7b59372a8 100644 --- a/plugin/session_view.py +++ b/plugin/session_view.py @@ -395,6 +395,11 @@ def remove_inlay_hint_phantom(self, phantom_uuid: str) -> None: ) self._inlay_hints_phantom_set.update(new_phantoms) + def remove_all_inlay_hints(self) -> None: + if not self._inlay_hints_phantom_set.phantoms: + return + self._inlay_hints_phantom_set.update([]) + # ------------------------------------------------------------------------------------------------------------------ def __str__(self) -> str: From d24924126fc4be0b9c74552cffa3ad16eaa397f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D1=80=D0=B5=D0=B4=D1=80=D0=B0=D0=B3=20=D0=9D=D0=B8?= =?UTF-8?q?=D0=BA=D0=BE=D0=BB=D0=B8=D1=9B?= Date: Sat, 13 Aug 2022 23:27:46 +0200 Subject: [PATCH 20/65] remove handeling inlay hints commands in this PR I believe that I didn't implement correctly handling of label.commands, so I will remove them. Mosly because I am itrating of label_parts and triggering commands for each label_part, but I think I shul run only one command from the clicked label part. --- plugin/core/sessions.py | 2 +- plugin/inlay_hint.py | 16 ---------------- 2 files changed, 1 insertion(+), 17 deletions(-) diff --git a/plugin/core/sessions.py b/plugin/core/sessions.py index 53e000a20..e954a83f7 100644 --- a/plugin/core/sessions.py +++ b/plugin/core/sessions.py @@ -352,7 +352,7 @@ def get_initialize_params(variables: Dict[str, str], workspace_folders: List[Wor "inlayHint": { "dynamicRegistration": True, "resolveSupport": { - "properties": ["textEdits", "label.command"] + "properties": ["textEdits"] } }, "semanticTokens": { diff --git a/plugin/inlay_hint.py b/plugin/inlay_hint.py index 6d7d70ef4..03143fa9c 100644 --- a/plugin/inlay_hint.py +++ b/plugin/inlay_hint.py @@ -34,7 +34,6 @@ def run(self, _edit: sublime.Edit, session_name: str, inlay_hint: InlayHint, pha def handle(self, session_name: str, inlay_hint: InlayHint, phantom_uuid: str) -> None: self.handle_inlay_hint_text_edits(session_name, inlay_hint, phantom_uuid) - self.handle_inlay_hint_command(session_name, inlay_hint) def handle_inlay_hint_text_edits(self, session_name: str, inlay_hint: InlayHint, phantom_uuid: str) -> None: session = self.session_by_name(session_name, 'inlayHintProvider') @@ -47,21 +46,6 @@ def handle_inlay_hint_text_edits(self, session_name: str, inlay_hint: InlayHint, sv.remove_inlay_hint_phantom(phantom_uuid) apply_text_edits_to_view(text_edits, self.view) - def handle_inlay_hint_command(self, session_name: str, inlay_hint: InlayHint) -> None: - label_parts = inlay_hint.get('label') - if not isinstance(label_parts, list): - return - for label_part in label_parts: - command = label_part.get('command') - if not command: - continue - args = { - "session_name": session_name, - "command_name": command["command"], - "command_args": command["arguments"] - } - self.view.run_command("lsp_execute", args) - INLAY_HINT_HTML = """ From c5a6469b52df53eaf5a4afbccef135c9565c6503 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D1=80=D0=B5=D0=B4=D1=80=D0=B0=D0=B3=20=D0=9D=D0=B8?= =?UTF-8?q?=D0=BA=D0=BE=D0=BB=D0=B8=D1=9B?= Date: Sat, 13 Aug 2022 23:53:01 +0200 Subject: [PATCH 21/65] only make inlay hints that have text edits clickable or the one who do not have text edits but support resolving(this is still not perfect but a better behavior) --- boot.py | 2 +- plugin/inlay_hint.py | 91 ++++++++++++++++++++++------------------ plugin/session_buffer.py | 2 +- 3 files changed, 53 insertions(+), 42 deletions(-) diff --git a/boot.py b/boot.py index b6d9bf426..ba2124d21 100644 --- a/boot.py +++ b/boot.py @@ -48,7 +48,7 @@ from .plugin.goto import LspSymbolTypeDefinitionCommand from .plugin.goto_diagnostic import LspGotoDiagnosticCommand from .plugin.hover import LspHoverCommand -from .plugin.inlay_hint import LspInlayHintClickCommand +from .plugin.inlay_hint import LspInlayHintApplyTextEditsCommand from .plugin.inlay_hint import LspToggleInlayHintsCommand from .plugin.panels import LspShowDiagnosticsPanelCommand from .plugin.panels import LspToggleServerPanelCommand diff --git a/plugin/inlay_hint.py b/plugin/inlay_hint.py index 03143fa9c..c3be27029 100644 --- a/plugin/inlay_hint.py +++ b/plugin/inlay_hint.py @@ -1,3 +1,4 @@ +from .core.sessions import Session from .core.protocol import InlayHintLabelPart, MarkupContent, Point, InlayHint, Request from .core.registry import LspTextCommand from .core.typing import List, Optional, Union @@ -20,7 +21,7 @@ def run(self, _edit: sublime.Edit, _event: Optional[dict] = None) -> None: sv.session_buffer.do_inlay_hints_async(sv.view) -class LspInlayHintClickCommand(LspTextCommand): +class LspInlayHintApplyTextEditsCommand(LspTextCommand): capability = 'inlayHintProvider' def run(self, _edit: sublime.Edit, session_name: str, inlay_hint: InlayHint, phantom_uuid: str, @@ -47,29 +48,53 @@ def handle_inlay_hint_text_edits(self, session_name: str, inlay_hint: InlayHint, apply_text_edits_to_view(text_edits, self.view) -INLAY_HINT_HTML = """ - - -
- {label} -
- -""" +def get_inlay_hint_html(view: sublime.View, inlay_hint: InlayHint, session: Session, phantom_uuid: str) -> str: + tooltip = format_inlay_hint_tooltip(view, inlay_hint.get("tooltip")) + label = format_inlay_hint_label(view, inlay_hint["label"]) + margin_left = "0.6rem" if inlay_hint.get("paddingLeft", False) else "0" + margin_right = "0.6rem" if inlay_hint.get("paddingRight", False) else "0" + html = """ + + +
+ """.format( + margin_left=margin_left, + margin_right=margin_right, + tooltip=tooltip + ) + can_resolve_inlay_hint = session.has_capability('inlayHintProvider.resolveProvider') + apply_text_edits_command = sublime.command_url('lsp_inlay_hint_apply_text_edits', { + 'session_name': session.config.name, + 'inlay_hint': inlay_hint, + 'phantom_uuid': phantom_uuid + }) + can_apply_text_edits = inlay_hint.get('textEdits') or (not inlay_hint.get('textEdits') and can_resolve_inlay_hint) + if can_apply_text_edits: + html += ''.format(apply_text_edits_command=apply_text_edits_command) + html += label + if can_apply_text_edits: + html += '' + html += """ +
+ + """ + return html def format_inlay_hint_tooltip(view: sublime.View, tooltip: Optional[Union[str, MarkupContent]]) -> str: @@ -91,24 +116,10 @@ def format_inlay_hint_label(view: sublime.View, label: Union[str, List[InlayHint ) for label_part in label) -def inlay_hint_to_phantom(view: sublime.View, inlay_hint: InlayHint, session_name: str) -> sublime.Phantom: +def inlay_hint_to_phantom(view: sublime.View, inlay_hint: InlayHint, session: Session) -> sublime.Phantom: region = sublime.Region(point_to_offset(Point.from_lsp(inlay_hint["position"]), view)) - tooltip = format_inlay_hint_tooltip(view, inlay_hint.get("tooltip")) - label = format_inlay_hint_label(view, inlay_hint["label"]) - margin_left = "0.6rem" if inlay_hint.get("paddingLeft", False) else "0" - margin_right = "0.6rem" if inlay_hint.get("paddingRight", False) else "0" phantom_uuid = str(uuid.uuid4()) - command = sublime.command_url('lsp_inlay_hint_click', { - 'session_name': session_name, - 'inlay_hint': inlay_hint, - 'phantom_uuid': phantom_uuid - }) - content = INLAY_HINT_HTML.format( - margin_left=margin_left, - margin_right=margin_right, - tooltip=tooltip, - label=label, - command=command) + content = get_inlay_hint_html(view, inlay_hint, session, phantom_uuid) p = sublime.Phantom(region, content, sublime.LAYOUT_INLINE) setattr(p, 'lsp_uuid', phantom_uuid) return p diff --git a/plugin/session_buffer.py b/plugin/session_buffer.py index 9e6f71b7e..d85faa67b 100644 --- a/plugin/session_buffer.py +++ b/plugin/session_buffer.py @@ -639,7 +639,7 @@ def _on_inlay_hints_async(self, response: InlayHintResponse) -> None: view = self.some_view() if not view: return - phantoms = [inlay_hint_to_phantom(view, inlay_hint, self.session.config.name) for inlay_hint in response] + phantoms = [inlay_hint_to_phantom(view, inlay_hint, self.session) for inlay_hint in response] for sv in self.session_views: sublime.set_timeout(lambda: sv.present_inlay_hints_async(phantoms)) From d833b4cd170a0d49bd7e36f8ce6a5e4f0c2e654e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D1=80=D0=B5=D0=B4=D1=80=D0=B0=D0=B3=20=D0=9D=D0=B8?= =?UTF-8?q?=D0=BA=D0=BE=D0=BB=D0=B8=D1=9B?= Date: Sun, 14 Aug 2022 00:09:41 +0200 Subject: [PATCH 22/65] use the user font_face for the inlay-hint phantom font-family --- plugin/inlay_hint.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/plugin/inlay_hint.py b/plugin/inlay_hint.py index c3be27029..c241c2d43 100644 --- a/plugin/inlay_hint.py +++ b/plugin/inlay_hint.py @@ -53,6 +53,7 @@ def get_inlay_hint_html(view: sublime.View, inlay_hint: InlayHint, session: Sess label = format_inlay_hint_label(view, inlay_hint["label"]) margin_left = "0.6rem" if inlay_hint.get("paddingLeft", False) else "0" margin_right = "0.6rem" if inlay_hint.get("paddingRight", False) else "0" + font = view.settings().get('font_face') or "monospace" html = """
+ {label} +
+ """.format( margin_left=margin_left, margin_right=margin_right, tooltip=tooltip, - font=font + font=font, + label=label ) - can_resolve_inlay_hint = session.has_capability('inlayHintProvider.resolveProvider') - apply_text_edits_command = sublime.command_url('lsp_inlay_hint_apply_text_edits', { - 'session_name': session.config.name, - 'inlay_hint': inlay_hint, - 'phantom_uuid': phantom_uuid - }) - can_apply_text_edits = inlay_hint.get('textEdits') or (not inlay_hint.get('textEdits') and can_resolve_inlay_hint) - if can_apply_text_edits: - html += ''.format(apply_text_edits_command=apply_text_edits_command) - html += label - if can_apply_text_edits: - html += '' - html += """ -
- - """ return html @@ -108,14 +118,43 @@ def format_inlay_hint_tooltip(view: sublime.View, tooltip: Optional[Union[str, M return "" -def format_inlay_hint_label(view: sublime.View, label: Union[str, List[InlayHintLabelPart]]) -> str: +def format_inlay_hint_label(view: sublime.View, inlay_hint: InlayHint, session: Session, phantom_uuid: str) -> str: + result = "" + can_resolve_inlay_hint = session.has_capability('inlayHintProvider.resolveProvider') + label = inlay_hint['label'] + is_clickable = bool(inlay_hint.get('textEdits')) or can_resolve_inlay_hint if isinstance(label, str): - return html.escape(label) - else: - return "".join("
{value}
".format( + inlay_hint_click_command = sublime.command_url('lsp_inlay_hint_click', { + 'session_name': session.config.name, + 'inlay_hint': inlay_hint, + 'phantom_uuid': phantom_uuid + }) + if is_clickable: + result += ''.format(command=inlay_hint_click_command) + result += html.escape(label) + if is_clickable: + result += "" + return result + + for label_part in label: + value = "" + inlay_hint_click_command = sublime.command_url('lsp_inlay_hint_click', { + 'session_name': session.config.name, + 'inlay_hint': inlay_hint, + 'phantom_uuid': phantom_uuid, + 'label_part': label_part + }) + is_clickable = is_clickable or bool(label_part.get('command')) + if is_clickable: + value += ''.format(command=inlay_hint_click_command) + value += html.escape(label_part.get('value') or "") + if is_clickable: + value += "" + result += "
{value}
".format( tooltip=format_inlay_hint_tooltip(view, label_part.get("tooltip")), - value=label_part.get("value") - ) for label_part in label) + value=value + ) + return result def inlay_hint_to_phantom(view: sublime.View, inlay_hint: InlayHint, session: Session) -> sublime.Phantom: From 3d3d6b1b10b7158f9debad9758b6df539a34e7fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D1=80=D0=B5=D0=B4=D1=80=D0=B0=D0=B3=20=D0=9D=D0=B8?= =?UTF-8?q?=D0=BA=D0=BE=D0=BB=D0=B8=D1=9B?= Date: Sun, 14 Aug 2022 15:49:21 +0200 Subject: [PATCH 24/65] Update plugin/core/protocol.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Rafał Chłodnicki --- plugin/core/protocol.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/core/protocol.py b/plugin/core/protocol.py index 8127ce691..5b1956ff2 100644 --- a/plugin/core/protocol.py +++ b/plugin/core/protocol.py @@ -379,7 +379,7 @@ class SemanticTokenModifiers: class InlayHintKind: Type = 1 - Parameter = 1 + Parameter = 2 InlayHint = TypedDict('InlayHint', { From 595471f99bfb223f87f48701bf0fdf39899b5425 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D1=80=D0=B5=D0=B4=D1=80=D0=B0=D0=B3=20=D0=9D=D0=B8?= =?UTF-8?q?=D0=BA=D0=BE=D0=BB=D0=B8=D1=9B?= Date: Sun, 14 Aug 2022 15:52:10 +0200 Subject: [PATCH 25/65] sort imports --- plugin/inlay_hint.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugin/inlay_hint.py b/plugin/inlay_hint.py index 4e1811b03..9c7d68d84 100644 --- a/plugin/inlay_hint.py +++ b/plugin/inlay_hint.py @@ -1,13 +1,13 @@ -from .core.sessions import Session from .core.protocol import InlayHintLabelPart, MarkupContent, Point, InlayHint, Request from .core.registry import LspTextCommand +from .core.sessions import Session +from .core.types import TemporarySettings from .core.typing import Optional, Union from .core.views import FORMAT_MARKUP_CONTENT, point_to_offset, minihtml from .formatting import apply_text_edits_to_view import html import sublime import uuid -from .core.types import TemporarySettings class LspToggleInlayHintsCommand(LspTextCommand): From c88bbd23f45580fd4648181fdfbfc442cafe8656 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D1=80=D0=B5=D0=B4=D1=80=D0=B0=D0=B3=20=D0=9D=D0=B8?= =?UTF-8?q?=D0=BA=D0=BE=D0=BB=D0=B8=D1=9B?= Date: Sun, 14 Aug 2022 15:53:00 +0200 Subject: [PATCH 26/65] remove debug code --- plugin/session_view.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/plugin/session_view.py b/plugin/session_view.py index 7b59372a8..d8f061f63 100644 --- a/plugin/session_view.py +++ b/plugin/session_view.py @@ -386,9 +386,6 @@ def present_inlay_hints_async(self, phantoms: List[sublime.Phantom]) -> None: self._inlay_hints_phantom_set.update(phantoms) def remove_inlay_hint_phantom(self, phantom_uuid: str) -> None: - for p in self._inlay_hints_phantom_set.phantoms: - print(getattr(p, 'lsp_uuid')) - new_phantoms = list(filter( lambda p: getattr(p, 'lsp_uuid') != phantom_uuid, self._inlay_hints_phantom_set.phantoms) From f2528b4aea45b9320a8a5af27e362085b6dfb1d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D1=80=D0=B5=D0=B4=D1=80=D0=B0=D0=B3=20=D0=9D=D0=B8?= =?UTF-8?q?=D0=BA=D0=BE=D0=BB=D0=B8=D1=9B?= Date: Sun, 14 Aug 2022 15:54:23 +0200 Subject: [PATCH 27/65] sort imports --- plugin/session_buffer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/session_buffer.py b/plugin/session_buffer.py index d85faa67b..04a3e64d7 100644 --- a/plugin/session_buffer.py +++ b/plugin/session_buffer.py @@ -15,6 +15,7 @@ from .core.types import debounced from .core.types import Debouncer from .core.types import FEATURES_TIMEOUT +from .core.types import TemporarySettings from .core.typing import Any, Callable, Iterable, Optional, List, Set, Dict, Tuple from .core.views import DIAGNOSTIC_SEVERITY from .core.views import diagnostic_severity @@ -31,7 +32,6 @@ from .core.views import text_document_identifier from .core.views import will_save from .inlay_hint import inlay_hint_to_phantom -from .core.types import TemporarySettings from .semantic_highlighting import SemanticToken from weakref import WeakSet import sublime From 113fbb9a47b858268c0306df7f0d41bf74f810a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D1=80=D0=B5=D0=B4=D1=80=D0=B0=D0=B3=20=D0=9D=D0=B8?= =?UTF-8?q?=D0=BA=D0=BE=D0=BB=D0=B8=D1=9B?= Date: Sun, 14 Aug 2022 16:02:13 +0200 Subject: [PATCH 28/65] remove check as a guard for potential preformace bennefit or for not so performant code :) --- plugin/session_view.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugin/session_view.py b/plugin/session_view.py index d8f061f63..4b126fadf 100644 --- a/plugin/session_view.py +++ b/plugin/session_view.py @@ -393,8 +393,6 @@ def remove_inlay_hint_phantom(self, phantom_uuid: str) -> None: self._inlay_hints_phantom_set.update(new_phantoms) def remove_all_inlay_hints(self) -> None: - if not self._inlay_hints_phantom_set.phantoms: - return self._inlay_hints_phantom_set.update([]) # ------------------------------------------------------------------------------------------------------------------ From ae1734498a40d47ce90926c5672f2fcc4063dbf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D1=80=D0=B5=D0=B4=D1=80=D0=B0=D0=B3=20=D0=9D=D0=B8?= =?UTF-8?q?=D0=BA=D0=BE=D0=BB=D0=B8=D1=9B?= Date: Sun, 14 Aug 2022 16:05:30 +0200 Subject: [PATCH 29/65] Update plugin/session_buffer.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Rafał Chłodnicki --- plugin/session_buffer.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/plugin/session_buffer.py b/plugin/session_buffer.py index 04a3e64d7..4b35c8229 100644 --- a/plugin/session_buffer.py +++ b/plugin/session_buffer.py @@ -627,12 +627,11 @@ def do_inlay_hints_async(self, view: sublime.View) -> None: return params = { "textDocument": text_document_identifier(view), - # "range": region_to_range(view, view.visible_region()).to_lsp() - "range": region_to_range(view, sublime.Region(0, view.size())).to_lsp() + params = { + "textDocument": text_document_identifier(view), + "range": entire_content_range(view).to_lsp() } # type: InlayHintParams - - request = Request.inlayHint(params, view) - self.session.send_request_async(request, self._on_inlay_hints_async) + self.session.send_request_async(Request.inlayHint(params, view), self._on_inlay_hints_async) def _on_inlay_hints_async(self, response: InlayHintResponse) -> None: if response: From 0566c0f1c18fd4842a1a65085dd9aa4258f70d71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D1=80=D0=B5=D0=B4=D1=80=D0=B0=D0=B3=20=D0=9D=D0=B8?= =?UTF-8?q?=D0=BA=D0=BE=D0=BB=D0=B8=D1=9B?= Date: Sun, 14 Aug 2022 16:07:33 +0200 Subject: [PATCH 30/65] add import --- plugin/session_buffer.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/plugin/session_buffer.py b/plugin/session_buffer.py index 4b35c8229..19234b418 100644 --- a/plugin/session_buffer.py +++ b/plugin/session_buffer.py @@ -25,6 +25,7 @@ from .core.views import did_save from .core.views import document_color_params from .core.views import DOCUMENT_LINK_FLAGS +from .core.views import entire_content_range from .core.views import lsp_color_to_phantom from .core.views import MissingUriError from .core.views import range_to_region @@ -625,8 +626,6 @@ def do_inlay_hints_async(self, view: sublime.View) -> None: return if not self.session.has_capability("inlayHintProvider"): return - params = { - "textDocument": text_document_identifier(view), params = { "textDocument": text_document_identifier(view), "range": entire_content_range(view).to_lsp() From 0014a4dba07432baa76d257412ccef2c3e74debb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D1=80=D0=B5=D0=B4=D1=80=D0=B0=D0=B3=20=D0=9D=D0=B8?= =?UTF-8?q?=D0=BA=D0=BE=D0=BB=D0=B8=D1=9B?= Date: Sun, 14 Aug 2022 16:10:39 +0200 Subject: [PATCH 31/65] remove params in m_workspace_inlayHint_refresh --- plugin/core/sessions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/core/sessions.py b/plugin/core/sessions.py index 53e000a20..7775c45a0 100644 --- a/plugin/core/sessions.py +++ b/plugin/core/sessions.py @@ -1643,7 +1643,7 @@ def m_workspace_semanticTokens_refresh(self, params: Any, request_id: Any) -> No else: sv.session_buffer.set_semantic_tokens_pending_refresh() - def m_workspace_inlayHint_refresh(self, params: None, request_id: Any) -> None: + def m_workspace_inlayHint_refresh(self, request_id: Any) -> None: """handles the workspace/inlayHint/refresh request""" for sv in self.session_views_async(): sv.session_buffer.do_inlay_hints_async(sv.view) From fcf72129ac8b4c4bea7e69b01726ad6003f4b944 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D1=80=D0=B5=D0=B4=D1=80=D0=B0=D0=B3=20=D0=9D=D0=B8?= =?UTF-8?q?=D0=BA=D0=BE=D0=BB=D0=B8=D1=9B?= Date: Sun, 14 Aug 2022 16:12:50 +0200 Subject: [PATCH 32/65] rename SHOW_INLAY_HINTS to show_inlay_hints --- plugin/core/types.py | 4 ++-- plugin/inlay_hint.py | 2 +- plugin/session_buffer.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/plugin/core/types.py b/plugin/core/types.py index 616c575c2..73ad2bcd4 100644 --- a/plugin/core/types.py +++ b/plugin/core/types.py @@ -35,7 +35,7 @@ class TemporarySettings: """ Changing TemporarySettings will not cause server re-initialization. """ - SHOW_INLAY_HINTS = False # type: bool + show_inlay_hints = False # type: bool def basescope2languageid(base_scope: str) -> str: @@ -224,7 +224,7 @@ class Settings: def __init__(self, s: sublime.Settings) -> None: self.update(s) - TemporarySettings.SHOW_INLAY_HINTS = self.show_inlay_hints + TemporarySettings.show_inlay_hints = self.show_inlay_hints def update(self, s: sublime.Settings) -> None: def r(name: str, default: Union[bool, int, str, list, dict]) -> None: diff --git a/plugin/inlay_hint.py b/plugin/inlay_hint.py index 9c7d68d84..70fc25ce0 100644 --- a/plugin/inlay_hint.py +++ b/plugin/inlay_hint.py @@ -15,7 +15,7 @@ class LspToggleInlayHintsCommand(LspTextCommand): def run(self, _edit: sublime.Edit, _event: Optional[dict] = None) -> None: sessions = self.sessions('inlayHintProvider') - TemporarySettings.SHOW_INLAY_HINTS = not TemporarySettings.SHOW_INLAY_HINTS + TemporarySettings.show_inlay_hints = not TemporarySettings.show_inlay_hints for session in sessions: for sv in session.session_views_async(): sv.session_buffer.do_inlay_hints_async(sv.view) diff --git a/plugin/session_buffer.py b/plugin/session_buffer.py index 19234b418..f67b33f4d 100644 --- a/plugin/session_buffer.py +++ b/plugin/session_buffer.py @@ -619,7 +619,7 @@ def get_semantic_tokens(self) -> List[SemanticToken]: return self.semantic_tokens.tokens def do_inlay_hints_async(self, view: sublime.View) -> None: - if not TemporarySettings.SHOW_INLAY_HINTS: + if not TemporarySettings.show_inlay_hints: # remove inlay hints for sv in self.session_views: sv.remove_all_inlay_hints() From f4e38fa8db01e4f4487e1303c43b08638be44fd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D1=80=D0=B5=D0=B4=D1=80=D0=B0=D0=B3=20=D0=9D=D0=B8?= =?UTF-8?q?=D0=BA=D0=BE=D0=BB=D0=B8=D1=9B?= Date: Sun, 14 Aug 2022 16:18:10 +0200 Subject: [PATCH 33/65] remove inlay hints on_before_remove --- plugin/session_view.py | 1 + 1 file changed, 1 insertion(+) diff --git a/plugin/session_view.py b/plugin/session_view.py index 4b126fadf..fb391f66e 100644 --- a/plugin/session_view.py +++ b/plugin/session_view.py @@ -82,6 +82,7 @@ def on_before_remove(self) -> None: self.view.erase_regions(self.diagnostics_key(severity, True)) self.view.erase_regions("lsp_document_link") self.session_buffer.remove_session_view(self) + self.remove_all_inlay_hints() @property def session(self) -> Session: From 719bbbc9a1c4990edf9a569b4620eb1d2ab8e74a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D1=80=D0=B5=D0=B4=D1=80=D0=B0=D0=B3=20=D0=9D=D0=B8?= =?UTF-8?q?=D0=BA=D0=BE=D0=BB=D0=B8=D1=9B?= Date: Sun, 14 Aug 2022 16:18:20 +0200 Subject: [PATCH 34/65] Revert "remove params in m_workspace_inlayHint_refresh" This reverts commit 0014a4dba07432baa76d257412ccef2c3e74debb. --- plugin/core/sessions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/core/sessions.py b/plugin/core/sessions.py index 7775c45a0..53e000a20 100644 --- a/plugin/core/sessions.py +++ b/plugin/core/sessions.py @@ -1643,7 +1643,7 @@ def m_workspace_semanticTokens_refresh(self, params: Any, request_id: Any) -> No else: sv.session_buffer.set_semantic_tokens_pending_refresh() - def m_workspace_inlayHint_refresh(self, request_id: Any) -> None: + def m_workspace_inlayHint_refresh(self, params: None, request_id: Any) -> None: """handles the workspace/inlayHint/refresh request""" for sv in self.session_views_async(): sv.session_buffer.do_inlay_hints_async(sv.view) From ad6814e729692d16a191a5808ce2c5e8f03b5a0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D1=80=D0=B5=D0=B4=D1=80=D0=B0=D0=B3=20=D0=9D=D0=B8?= =?UTF-8?q?=D0=BA=D0=BE=D0=BB=D0=B8=D1=9B?= Date: Sun, 14 Aug 2022 16:22:49 +0200 Subject: [PATCH 35/65] drop LspToggleInlayHintsCommand to not block the PR --- boot.py | 1 - plugin/core/types.py | 6 ------ plugin/inlay_hint.py | 12 ------------ plugin/session_buffer.py | 6 +----- 4 files changed, 1 insertion(+), 24 deletions(-) diff --git a/boot.py b/boot.py index b6d9bf426..5a5ec050d 100644 --- a/boot.py +++ b/boot.py @@ -49,7 +49,6 @@ from .plugin.goto_diagnostic import LspGotoDiagnosticCommand from .plugin.hover import LspHoverCommand from .plugin.inlay_hint import LspInlayHintClickCommand -from .plugin.inlay_hint import LspToggleInlayHintsCommand from .plugin.panels import LspShowDiagnosticsPanelCommand from .plugin.panels import LspToggleServerPanelCommand from .plugin.references import LspSymbolReferencesCommand diff --git a/plugin/core/types.py b/plugin/core/types.py index 73ad2bcd4..c724f7d8c 100644 --- a/plugin/core/types.py +++ b/plugin/core/types.py @@ -33,11 +33,6 @@ }, total=False) -class TemporarySettings: - """ Changing TemporarySettings will not cause server re-initialization. """ - show_inlay_hints = False # type: bool - - def basescope2languageid(base_scope: str) -> str: # This the connection between Language IDs and ST selectors. base_scope_map = sublime.load_settings("language-ids.sublime-settings") @@ -224,7 +219,6 @@ class Settings: def __init__(self, s: sublime.Settings) -> None: self.update(s) - TemporarySettings.show_inlay_hints = self.show_inlay_hints def update(self, s: sublime.Settings) -> None: def r(name: str, default: Union[bool, int, str, list, dict]) -> None: diff --git a/plugin/inlay_hint.py b/plugin/inlay_hint.py index 70fc25ce0..608250e6e 100644 --- a/plugin/inlay_hint.py +++ b/plugin/inlay_hint.py @@ -1,7 +1,6 @@ from .core.protocol import InlayHintLabelPart, MarkupContent, Point, InlayHint, Request from .core.registry import LspTextCommand from .core.sessions import Session -from .core.types import TemporarySettings from .core.typing import Optional, Union from .core.views import FORMAT_MARKUP_CONTENT, point_to_offset, minihtml from .formatting import apply_text_edits_to_view @@ -10,17 +9,6 @@ import uuid -class LspToggleInlayHintsCommand(LspTextCommand): - capability = 'inlayHintProvider' - - def run(self, _edit: sublime.Edit, _event: Optional[dict] = None) -> None: - sessions = self.sessions('inlayHintProvider') - TemporarySettings.show_inlay_hints = not TemporarySettings.show_inlay_hints - for session in sessions: - for sv in session.session_views_async(): - sv.session_buffer.do_inlay_hints_async(sv.view) - - class LspInlayHintClickCommand(LspTextCommand): capability = 'inlayHintProvider' diff --git a/plugin/session_buffer.py b/plugin/session_buffer.py index f67b33f4d..35c6e1384 100644 --- a/plugin/session_buffer.py +++ b/plugin/session_buffer.py @@ -15,7 +15,6 @@ from .core.types import debounced from .core.types import Debouncer from .core.types import FEATURES_TIMEOUT -from .core.types import TemporarySettings from .core.typing import Any, Callable, Iterable, Optional, List, Set, Dict, Tuple from .core.views import DIAGNOSTIC_SEVERITY from .core.views import diagnostic_severity @@ -619,10 +618,7 @@ def get_semantic_tokens(self) -> List[SemanticToken]: return self.semantic_tokens.tokens def do_inlay_hints_async(self, view: sublime.View) -> None: - if not TemporarySettings.show_inlay_hints: - # remove inlay hints - for sv in self.session_views: - sv.remove_all_inlay_hints() + if not userprefs().show_inlay_hints: return if not self.session.has_capability("inlayHintProvider"): return From b67dd54175265c65f75657874513bef0f037917f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D1=80=D0=B5=D0=B4=D1=80=D0=B0=D0=B3=20=D0=9D=D0=B8?= =?UTF-8?q?=D0=BA=D0=BE=D0=BB=D0=B8=D1=9B?= Date: Sun, 14 Aug 2022 16:25:34 +0200 Subject: [PATCH 36/65] drop commands for lsp_toggle_inlay_hints --- Default.sublime-commands | 4 ---- Default.sublime-keymap | 14 -------------- 2 files changed, 18 deletions(-) diff --git a/Default.sublime-commands b/Default.sublime-commands index c83f2b59e..bd9c22766 100644 --- a/Default.sublime-commands +++ b/Default.sublime-commands @@ -126,9 +126,5 @@ { "caption": "LSP: Find References", "command": "lsp_symbol_references" - }, - { - "caption": "LSP: Toggle Inlay Hints", - "command": "lsp_toggle_inlay_hints" } ] diff --git a/Default.sublime-keymap b/Default.sublime-keymap index 620ca977e..6e4298d3a 100644 --- a/Default.sublime-keymap +++ b/Default.sublime-keymap @@ -389,20 +389,6 @@ // } // ] // }, - // Toggle inlay hints. - // { - // "command": "lsp_toggle_inlay_hints", - // "keys": [ - // "UNBOUND" - // ], - // "context": [ - // { - // "key": "lsp.session_with_capability", - // "operator": "equal", - // "operand": "inlayHintProvider" - // } - // ] - // }, // Internal key-binding { "keys": [ From 77c6bfb53b40a153fad63891fd3bb377e91caaf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D1=80=D0=B5=D0=B4=D1=80=D0=B0=D0=B3=20=D0=9D=D0=B8?= =?UTF-8?q?=D0=BA=D0=BE=D0=BB=D0=B8=D1=9B?= Date: Mon, 15 Aug 2022 10:36:27 +0200 Subject: [PATCH 37/65] document that location is not supported --- plugin/inlay_hint.py | 1 + 1 file changed, 1 insertion(+) diff --git a/plugin/inlay_hint.py b/plugin/inlay_hint.py index 608250e6e..1c0339b03 100644 --- a/plugin/inlay_hint.py +++ b/plugin/inlay_hint.py @@ -138,6 +138,7 @@ def format_inlay_hint_label(view: sublime.View, inlay_hint: InlayHint, session: value += html.escape(label_part.get('value') or "") if is_clickable: value += "" + # InlayHintLabelPart.location is not supported result += "
{value}
".format( tooltip=format_inlay_hint_tooltip(view, label_part.get("tooltip")), value=value From 75bda3973c4992e7e0bbb957a331debdf05eb686 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D1=80=D0=B5=D0=B4=D1=80=D0=B0=D0=B3=20=D0=9D=D0=B8?= =?UTF-8?q?=D0=BA=D0=BE=D0=BB=D0=B8=D1=9B?= Date: Mon, 15 Aug 2022 10:37:10 +0200 Subject: [PATCH 38/65] remove elif for an if --- plugin/inlay_hint.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/plugin/inlay_hint.py b/plugin/inlay_hint.py index 1c0339b03..fe066dcdc 100644 --- a/plugin/inlay_hint.py +++ b/plugin/inlay_hint.py @@ -100,10 +100,9 @@ def get_inlay_hint_html(view: sublime.View, inlay_hint: InlayHint, session: Sess def format_inlay_hint_tooltip(view: sublime.View, tooltip: Optional[Union[str, MarkupContent]]) -> str: if isinstance(tooltip, str): return html.escape(tooltip) - elif isinstance(tooltip, dict): # MarkupContent + if isinstance(tooltip, dict): # MarkupContent return minihtml(view, tooltip, allowed_formats=FORMAT_MARKUP_CONTENT) - else: - return "" + return "" def format_inlay_hint_label(view: sublime.View, inlay_hint: InlayHint, session: Session, phantom_uuid: str) -> str: From d7c7b0b2fdfab9405894059b628d35423e030a33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D1=80=D0=B5=D0=B4=D1=80=D0=B0=D0=B3=20=D0=9D=D0=B8?= =?UTF-8?q?=D0=BA=D0=BE=D0=BB=D0=B8=D1=9B?= Date: Mon, 15 Aug 2022 10:44:48 +0200 Subject: [PATCH 39/65] be more descriptive about the setting description --- LSP.sublime-settings | 2 +- sublime-package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/LSP.sublime-settings b/LSP.sublime-settings index f2c95fc84..c2eedbe41 100644 --- a/LSP.sublime-settings +++ b/LSP.sublime-settings @@ -134,7 +134,7 @@ // "phantom" - show a phantom on the top when code actions are available "show_code_lens": "annotation", - // Show inlay hints + // Show inlay hints that interleave with the code. "show_inlay_hints": true, // Show code actions in hover popup if available diff --git a/sublime-package.json b/sublime-package.json index bc2b7469d..559403d95 100644 --- a/sublime-package.json +++ b/sublime-package.json @@ -512,7 +512,7 @@ "show_inlay_hints": { "type": "boolean", "default": true, - "markdownDescription": "Show inlay hints." + "markdownDescription": "Show inlay hints that interleave with the code." }, }, "additionalProperties": false From f07cc30b1186ec732dc2fe3c226588a618ab5625 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D1=80=D0=B5=D0=B4=D1=80=D0=B0=D0=B3=20=D0=9D=D0=B8?= =?UTF-8?q?=D0=BA=D0=BE=D0=BB=D0=B8=D1=9B?= Date: Mon, 15 Aug 2022 10:45:41 +0200 Subject: [PATCH 40/65] use inline comments instead of docs comments --- plugin/inlay_hint.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/plugin/inlay_hint.py b/plugin/inlay_hint.py index fe066dcdc..0c341b5b0 100644 --- a/plugin/inlay_hint.py +++ b/plugin/inlay_hint.py @@ -14,11 +14,9 @@ class LspInlayHintClickCommand(LspTextCommand): def run(self, _edit: sublime.Edit, session_name: str, inlay_hint: InlayHint, phantom_uuid: str, event: Optional[dict] = None, label_part: Optional[InlayHintLabelPart] = None) -> None: - """ - Insert textEdits for the given inlay hint. - If a InlayHintLabelPart was clicked, label_part will be passed as an argument to the LspInlayHintClickCommand - and InlayHintLabelPart.command will be executed. - """ + # Insert textEdits for the given inlay hint. + # If a InlayHintLabelPart was clicked, label_part will be passed as an argument to the LspInlayHintClickCommand + # and InlayHintLabelPart.command will be executed. session = self.session_by_name(session_name, 'inlayHintProvider') if session and session.has_capability('inlayHintProvider.resolveProvider'): request = Request.resolveInlayHint(inlay_hint, self.view) From d370af964cfb1ec8594ebeec457e3ec328f30028 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D1=80=D0=B5=D0=B4=D1=80=D0=B0=D0=B3=20=D0=9D=D0=B8?= =?UTF-8?q?=D0=BA=D0=BE=D0=BB=D0=B8=D1=9B?= Date: Mon, 15 Aug 2022 13:02:48 +0200 Subject: [PATCH 41/65] strip html tags for tooltips --- plugin/core/strip_html.py | 29 +++++++++++++++++++++++++++++ plugin/inlay_hint.py | 19 +++++++++++-------- tests/test_strip_html.py | 9 +++++++++ 3 files changed, 49 insertions(+), 8 deletions(-) create mode 100644 plugin/core/strip_html.py create mode 100644 tests/test_strip_html.py diff --git a/plugin/core/strip_html.py b/plugin/core/strip_html.py new file mode 100644 index 000000000..51a6960e4 --- /dev/null +++ b/plugin/core/strip_html.py @@ -0,0 +1,29 @@ +from html.parser import HTMLParser +from .types import List + + +class MLRemover(HTMLParser): + def __init__(self) -> None: + self.reset() + self.strict = False + self.convert_charrefs = True + self.fed = [] # type: List[str] + + def handle_data(self, data: str) -> None: + self.fed.append(data) + + def handle_entityref(self, name: str) -> None: + self.fed.append('&{name};'.format(name=name)) + + def handle_charref(self, name: str) -> None: + self.fed.append('&#{name};'.format(name=name)) + + def get_data(self) -> str: + return ''.join(self.fed) + + +def strip_html(value: str) -> str: + remover = MLRemover() + remover.feed(value) + remover.close() + return remover.get_data() diff --git a/plugin/inlay_hint.py b/plugin/inlay_hint.py index 0c341b5b0..631086c32 100644 --- a/plugin/inlay_hint.py +++ b/plugin/inlay_hint.py @@ -1,8 +1,9 @@ +from .core.strip_html import strip_html from .core.protocol import InlayHintLabelPart, MarkupContent, Point, InlayHint, Request from .core.registry import LspTextCommand from .core.sessions import Session from .core.typing import Optional, Union -from .core.views import FORMAT_MARKUP_CONTENT, point_to_offset, minihtml +from .core.views import point_to_offset from .formatting import apply_text_edits_to_view import html import sublime @@ -57,8 +58,8 @@ def handle_inlay_hint_command(self, session_name: str, label_part: Optional[Inla def get_inlay_hint_html(view: sublime.View, inlay_hint: InlayHint, session: Session, phantom_uuid: str) -> str: - tooltip = format_inlay_hint_tooltip(view, inlay_hint.get("tooltip")) - label = format_inlay_hint_label(view, inlay_hint, session, phantom_uuid) + tooltip = format_inlay_hint_tooltip(inlay_hint.get("tooltip")) + label = format_inlay_hint_label(inlay_hint, session, phantom_uuid) margin_left = "0.6rem" if inlay_hint.get("paddingLeft", False) else "0" margin_right = "0.6rem" if inlay_hint.get("paddingRight", False) else "0" font = view.settings().get('font_face') or "monospace" @@ -95,15 +96,17 @@ def get_inlay_hint_html(view: sublime.View, inlay_hint: InlayHint, session: Sess return html -def format_inlay_hint_tooltip(view: sublime.View, tooltip: Optional[Union[str, MarkupContent]]) -> str: +def format_inlay_hint_tooltip(tooltip: Optional[Union[str, MarkupContent]]) -> str: if isinstance(tooltip, str): - return html.escape(tooltip) + # Sublime Text doesn't support HTML for tooltips + # so we strip the HTML tags from the tooltip + return strip_html(tooltip) if isinstance(tooltip, dict): # MarkupContent - return minihtml(view, tooltip, allowed_formats=FORMAT_MARKUP_CONTENT) + return strip_html(tooltip.get('value') or "") return "" -def format_inlay_hint_label(view: sublime.View, inlay_hint: InlayHint, session: Session, phantom_uuid: str) -> str: +def format_inlay_hint_label(inlay_hint: InlayHint, session: Session, phantom_uuid: str) -> str: result = "" can_resolve_inlay_hint = session.has_capability('inlayHintProvider.resolveProvider') label = inlay_hint['label'] @@ -137,7 +140,7 @@ def format_inlay_hint_label(view: sublime.View, inlay_hint: InlayHint, session: value += "" # InlayHintLabelPart.location is not supported result += "
{value}
".format( - tooltip=format_inlay_hint_tooltip(view, label_part.get("tooltip")), + tooltip=format_inlay_hint_tooltip(label_part.get("tooltip")), value=value ) return result diff --git a/tests/test_strip_html.py b/tests/test_strip_html.py new file mode 100644 index 000000000..9f02de04f --- /dev/null +++ b/tests/test_strip_html.py @@ -0,0 +1,9 @@ +import unittest +from LSP.plugin.core.strip_html import strip_html + + +class StripHtmlTest(unittest.TestCase): + def test_strip_html(self): + result = strip_html("

Hello world!

") + expected = "Hello world!" + self.assertEqual(result, expected) From ea1e4f2d150f076b3f8083c97cd6c96f03b33e2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D1=80=D0=B5=D0=B4=D1=80=D0=B0=D0=B3=20=D0=9D=D0=B8?= =?UTF-8?q?=D0=BA=D0=BE=D0=BB=D0=B8=D1=9B?= Date: Mon, 15 Aug 2022 13:19:13 +0200 Subject: [PATCH 42/65] use total=False for types and mark not required fields with comment --- plugin/core/protocol.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/plugin/core/protocol.py b/plugin/core/protocol.py index 5b1956ff2..15293d512 100644 --- a/plugin/core/protocol.py +++ b/plugin/core/protocol.py @@ -371,10 +371,10 @@ class SemanticTokenModifiers: InlayHintLabelPart = TypedDict('InlayHintLabelPart', { 'value': str, - 'tooltip': Union[str, MarkupContent], - 'location': Location, - 'command': Command -}, total=True) + 'tooltip': Union[str, MarkupContent], # NotRequired + 'location': Location, # NotRequired + 'command': Command # NotRequired +}, total=False) class InlayHintKind: @@ -385,13 +385,13 @@ class InlayHintKind: InlayHint = TypedDict('InlayHint', { 'position': Position, 'label': Union[str, List[InlayHintLabelPart]], - 'kind': Optional[int], - 'textEdits': Optional[List[TextEdit]], - 'tooltip': Optional[Union[str, MarkupContent]], - 'paddingLeft': Optional[bool], - 'paddingRight': Optional[bool], - 'data': Optional[Any] -}, total=True) + 'kind': int, # NotRequired + 'textEdits': List[TextEdit], # NotRequired + 'tooltip': Union[str, MarkupContent], # NotRequired + 'paddingLeft': bool, + 'paddingRight': bool, # NotRequired + 'data': Any # NotRequired +}, total=False) InlayHintResponse = Union[List[InlayHint], None] From 8ae76303ec36dc397da7459e2fce0f00b40e076f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D1=80=D0=B5=D0=B4=D1=80=D0=B0=D0=B3=20=D0=9D=D0=B8?= =?UTF-8?q?=D0=BA=D0=BE=D0=BB=D0=B8=D1=9B?= Date: Mon, 15 Aug 2022 13:20:17 +0200 Subject: [PATCH 43/65] add not required for paddingLeft --- plugin/core/protocol.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/core/protocol.py b/plugin/core/protocol.py index 15293d512..984ed77e4 100644 --- a/plugin/core/protocol.py +++ b/plugin/core/protocol.py @@ -388,7 +388,7 @@ class InlayHintKind: 'kind': int, # NotRequired 'textEdits': List[TextEdit], # NotRequired 'tooltip': Union[str, MarkupContent], # NotRequired - 'paddingLeft': bool, + 'paddingLeft': bool, # NotRequired 'paddingRight': bool, # NotRequired 'data': Any # NotRequired }, total=False) From 405de836adc11bef2b95b478d7b60ab6a8da67d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D1=80=D0=B5=D0=B4=D1=80=D0=B0=D0=B3=20=D0=9D=D0=B8?= =?UTF-8?q?=D0=BA=D0=BE=D0=BB=D0=B8=D1=9B?= Date: Mon, 15 Aug 2022 13:22:49 +0200 Subject: [PATCH 44/65] rename handle_inlay_hint_command to handle_label_part_command --- plugin/inlay_hint.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugin/inlay_hint.py b/plugin/inlay_hint.py index 631086c32..7af217b3e 100644 --- a/plugin/inlay_hint.py +++ b/plugin/inlay_hint.py @@ -30,7 +30,7 @@ def run(self, _edit: sublime.Edit, session_name: str, inlay_hint: InlayHint, pha def handle(self, session_name: str, inlay_hint: InlayHint, phantom_uuid: str, label_part: Optional[InlayHintLabelPart] = None) -> None: self.handle_inlay_hint_text_edits(session_name, inlay_hint, phantom_uuid) - self.handle_inlay_hint_command(session_name, label_part) + self.handle_label_part_command(session_name, label_part) def handle_inlay_hint_text_edits(self, session_name: str, inlay_hint: InlayHint, phantom_uuid: str) -> None: session = self.session_by_name(session_name, 'inlayHintProvider') @@ -43,7 +43,7 @@ def handle_inlay_hint_text_edits(self, session_name: str, inlay_hint: InlayHint, sv.remove_inlay_hint_phantom(phantom_uuid) apply_text_edits_to_view(text_edits, self.view) - def handle_inlay_hint_command(self, session_name: str, label_part: Optional[InlayHintLabelPart] = None) -> None: + def handle_label_part_command(self, session_name: str, label_part: Optional[InlayHintLabelPart] = None) -> None: if not label_part: return command = label_part.get('command') From 3779a1345fc2ec8a511608e9daedd6ae15bc20de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D1=80=D0=B5=D0=B4=D1=80=D0=B0=D0=B3=20=D0=9D=D0=B8?= =?UTF-8?q?=D0=BA=D0=BE=D0=BB=D0=B8=D1=9B?= Date: Mon, 15 Aug 2022 19:01:10 +0200 Subject: [PATCH 45/65] remove html parser, instead show plain markdown from server --- plugin/core/strip_html.py | 29 ----------------------------- plugin/inlay_hint.py | 5 ++--- tests/test_strip_html.py | 9 --------- 3 files changed, 2 insertions(+), 41 deletions(-) delete mode 100644 plugin/core/strip_html.py delete mode 100644 tests/test_strip_html.py diff --git a/plugin/core/strip_html.py b/plugin/core/strip_html.py deleted file mode 100644 index 51a6960e4..000000000 --- a/plugin/core/strip_html.py +++ /dev/null @@ -1,29 +0,0 @@ -from html.parser import HTMLParser -from .types import List - - -class MLRemover(HTMLParser): - def __init__(self) -> None: - self.reset() - self.strict = False - self.convert_charrefs = True - self.fed = [] # type: List[str] - - def handle_data(self, data: str) -> None: - self.fed.append(data) - - def handle_entityref(self, name: str) -> None: - self.fed.append('&{name};'.format(name=name)) - - def handle_charref(self, name: str) -> None: - self.fed.append('&#{name};'.format(name=name)) - - def get_data(self) -> str: - return ''.join(self.fed) - - -def strip_html(value: str) -> str: - remover = MLRemover() - remover.feed(value) - remover.close() - return remover.get_data() diff --git a/plugin/inlay_hint.py b/plugin/inlay_hint.py index 7af217b3e..5f8ea4fa0 100644 --- a/plugin/inlay_hint.py +++ b/plugin/inlay_hint.py @@ -1,4 +1,3 @@ -from .core.strip_html import strip_html from .core.protocol import InlayHintLabelPart, MarkupContent, Point, InlayHint, Request from .core.registry import LspTextCommand from .core.sessions import Session @@ -100,9 +99,9 @@ def format_inlay_hint_tooltip(tooltip: Optional[Union[str, MarkupContent]]) -> s if isinstance(tooltip, str): # Sublime Text doesn't support HTML for tooltips # so we strip the HTML tags from the tooltip - return strip_html(tooltip) + return tooltip if isinstance(tooltip, dict): # MarkupContent - return strip_html(tooltip.get('value') or "") + return tooltip.get('value') or "" return "" diff --git a/tests/test_strip_html.py b/tests/test_strip_html.py deleted file mode 100644 index 9f02de04f..000000000 --- a/tests/test_strip_html.py +++ /dev/null @@ -1,9 +0,0 @@ -import unittest -from LSP.plugin.core.strip_html import strip_html - - -class StripHtmlTest(unittest.TestCase): - def test_strip_html(self): - result = strip_html("

Hello world!

") - expected = "Hello world!" - self.assertEqual(result, expected) From f57aceecc9ce2c088dff05f96b892376fa6f3ff6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D1=80=D0=B5=D0=B4=D1=80=D0=B0=D0=B3=20=D0=9D=D0=B8?= =?UTF-8?q?=D0=BA=D0=BE=D0=BB=D0=B8=D1=9B?= Date: Mon, 15 Aug 2022 19:13:18 +0200 Subject: [PATCH 46/65] move phantom set from session view to session buffer to avoid potential edgecase of showing duplicate phantoms I managed to create an edge case like that by dragging a view outside of the project and bringing it back to project. that caused duplicate phanotoms... To not worry about that just move the phantom set to the session buffer --- plugin/core/sessions.py | 18 +++++++++--------- plugin/inlay_hint.py | 4 ++-- plugin/session_buffer.py | 18 ++++++++++++++++-- plugin/session_view.py | 17 ----------------- 4 files changed, 27 insertions(+), 30 deletions(-) diff --git a/plugin/core/sessions.py b/plugin/core/sessions.py index 53e000a20..8ca03f580 100644 --- a/plugin/core/sessions.py +++ b/plugin/core/sessions.py @@ -496,15 +496,6 @@ def get_resolved_code_lenses_for_region(self, region: sublime.Region) -> Generat def start_code_lenses_async(self) -> None: ... - def present_inlay_hints_async(self, phantoms: List[sublime.Phantom]) -> None: - ... - - def remove_inlay_hint_phantom(self, phantom_uuid: str) -> None: - ... - - def remove_all_inlay_hints(self) -> None: - ... - class SessionBufferProtocol(Protocol): @@ -563,6 +554,15 @@ def get_semantic_tokens(self) -> List[Any]: def do_inlay_hints_async(self, view: sublime.View) -> None: ... + def present_inlay_hints_async(self, phantoms: List[sublime.Phantom]) -> None: + ... + + def remove_inlay_hint_phantom(self, phantom_uuid: str) -> None: + ... + + def remove_all_inlay_hints(self) -> None: + ... + class AbstractViewListener(metaclass=ABCMeta): diff --git a/plugin/inlay_hint.py b/plugin/inlay_hint.py index 5f8ea4fa0..7ed943df8 100644 --- a/plugin/inlay_hint.py +++ b/plugin/inlay_hint.py @@ -38,8 +38,8 @@ def handle_inlay_hint_text_edits(self, session_name: str, inlay_hint: InlayHint, text_edits = inlay_hint.get('textEdits') if not text_edits: return - for sv in session.session_views_async(): - sv.remove_inlay_hint_phantom(phantom_uuid) + for sb in session.session_buffers_async(): + sb.remove_inlay_hint_phantom(phantom_uuid) apply_text_edits_to_view(text_edits, self.view) def handle_label_part_command(self, session_name: str, label_part: Optional[InlayHintLabelPart] = None) -> None: diff --git a/plugin/session_buffer.py b/plugin/session_buffer.py index 35c6e1384..2913d32e8 100644 --- a/plugin/session_buffer.py +++ b/plugin/session_buffer.py @@ -116,6 +116,7 @@ def __init__(self, session_view: SessionViewProtocol, buffer_id: int, uri: Docum self._last_semantic_region_key = 0 self._check_did_open(view) self._session.register_session_buffer_async(self) + self._inlay_hints_phantom_set = sublime.PhantomSet(view, "lsp_inlay_hints") def __del__(self) -> None: mgr = self.session.manager() @@ -186,6 +187,7 @@ def add_session_view(self, sv: SessionViewProtocol) -> None: def remove_session_view(self, sv: SessionViewProtocol) -> None: self._clear_semantic_token_regions(sv.view) + self.remove_all_inlay_hints() self.session_views.remove(sv) def register_capability_async( @@ -634,8 +636,20 @@ def _on_inlay_hints_async(self, response: InlayHintResponse) -> None: if not view: return phantoms = [inlay_hint_to_phantom(view, inlay_hint, self.session) for inlay_hint in response] - for sv in self.session_views: - sublime.set_timeout(lambda: sv.present_inlay_hints_async(phantoms)) + sublime.set_timeout(lambda: self.present_inlay_hints_async(phantoms)) + + def present_inlay_hints_async(self, phantoms: List[sublime.Phantom]) -> None: + self._inlay_hints_phantom_set.update(phantoms) + + def remove_inlay_hint_phantom(self, phantom_uuid: str) -> None: + new_phantoms = list(filter( + lambda p: getattr(p, 'lsp_uuid') != phantom_uuid, + self._inlay_hints_phantom_set.phantoms) + ) + self._inlay_hints_phantom_set.update(new_phantoms) + + def remove_all_inlay_hints(self) -> None: + self._inlay_hints_phantom_set.update([]) def __str__(self) -> str: return '{}:{}:{}'.format(self.session.config.name, self.id, self.get_uri()) diff --git a/plugin/session_view.py b/plugin/session_view.py index fb391f66e..8138625a8 100644 --- a/plugin/session_view.py +++ b/plugin/session_view.py @@ -45,7 +45,6 @@ def __init__(self, listener: AbstractViewListener, session: Session, uri: Docume self._listener = ref(listener) self.progress = {} # type: Dict[int, ViewProgressReporter] self._code_lenses = CodeLensView(self._view) - self._inlay_hints_phantom_set = sublime.PhantomSet(self._view, "lsp_inlay_hints") settings = self._view.settings() buffer_id = self._view.buffer_id() key = (id(session), buffer_id) @@ -82,7 +81,6 @@ def on_before_remove(self) -> None: self.view.erase_regions(self.diagnostics_key(severity, True)) self.view.erase_regions("lsp_document_link") self.session_buffer.remove_session_view(self) - self.remove_all_inlay_hints() @property def session(self) -> Session: @@ -381,21 +379,6 @@ def _on_code_lenses_resolved_async(self, mode: str) -> None: def get_resolved_code_lenses_for_region(self, region: sublime.Region) -> Generator[CodeLens, None, None]: yield from self._code_lenses.get_resolved_code_lenses_for_region(region) - # --- textDocument/inlayHint --------------------------------------------------------------------------------------- - - def present_inlay_hints_async(self, phantoms: List[sublime.Phantom]) -> None: - self._inlay_hints_phantom_set.update(phantoms) - - def remove_inlay_hint_phantom(self, phantom_uuid: str) -> None: - new_phantoms = list(filter( - lambda p: getattr(p, 'lsp_uuid') != phantom_uuid, - self._inlay_hints_phantom_set.phantoms) - ) - self._inlay_hints_phantom_set.update(new_phantoms) - - def remove_all_inlay_hints(self) -> None: - self._inlay_hints_phantom_set.update([]) - # ------------------------------------------------------------------------------------------------------------------ def __str__(self) -> str: From ffb02801294685394ca3659b54accee5177a5e2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D1=80=D0=B5=D0=B4=D1=80=D0=B0=D0=B3=20=D0=9D=D0=B8?= =?UTF-8?q?=D0=BA=D0=BE=D0=BB=D0=B8=D1=9B?= Date: Mon, 15 Aug 2022 19:20:50 +0200 Subject: [PATCH 47/65] use a more descriptive sentence for the show_inlay_hints setting --- LSP.sublime-settings | 2 +- sublime-package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/LSP.sublime-settings b/LSP.sublime-settings index c2eedbe41..a2cbff4ab 100644 --- a/LSP.sublime-settings +++ b/LSP.sublime-settings @@ -134,7 +134,7 @@ // "phantom" - show a phantom on the top when code actions are available "show_code_lens": "annotation", - // Show inlay hints that interleave with the code. + // Inlay hints are short annotations within the code, which show variable types or parameter names. "show_inlay_hints": true, // Show code actions in hover popup if available diff --git a/sublime-package.json b/sublime-package.json index 559403d95..f95d7589c 100644 --- a/sublime-package.json +++ b/sublime-package.json @@ -512,7 +512,7 @@ "show_inlay_hints": { "type": "boolean", "default": true, - "markdownDescription": "Show inlay hints that interleave with the code." + "markdownDescription": "Inlay hints are short annotations within the code, which show variable types or parameter names." }, }, "additionalProperties": false From 8269fbf8fe35692bf0da5eb0ab7f531d46303b95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D1=80=D0=B5=D0=B4=D1=80=D0=B0=D0=B3=20=D0=9D=D0=B8?= =?UTF-8?q?=D0=BA=D0=BE=D0=BB=D0=B8=D1=9B?= Date: Mon, 15 Aug 2022 19:52:42 +0200 Subject: [PATCH 48/65] use type: ignore :( --- plugin/inlay_hint.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/plugin/inlay_hint.py b/plugin/inlay_hint.py index 7ed943df8..b7e45c579 100644 --- a/plugin/inlay_hint.py +++ b/plugin/inlay_hint.py @@ -108,7 +108,7 @@ def format_inlay_hint_tooltip(tooltip: Optional[Union[str, MarkupContent]]) -> s def format_inlay_hint_label(inlay_hint: InlayHint, session: Session, phantom_uuid: str) -> str: result = "" can_resolve_inlay_hint = session.has_capability('inlayHintProvider.resolveProvider') - label = inlay_hint['label'] + label = inlay_hint['label'] # type: ignore is_clickable = bool(inlay_hint.get('textEdits')) or can_resolve_inlay_hint if isinstance(label, str): inlay_hint_click_command = sublime.command_url('lsp_inlay_hint_click', { @@ -146,7 +146,8 @@ def format_inlay_hint_label(inlay_hint: InlayHint, session: Session, phantom_uui def inlay_hint_to_phantom(view: sublime.View, inlay_hint: InlayHint, session: Session) -> sublime.Phantom: - region = sublime.Region(point_to_offset(Point.from_lsp(inlay_hint["position"]), view)) + position = inlay_hint["position"] # type: ignore + region = sublime.Region(point_to_offset(Point.from_lsp(position), view)) phantom_uuid = str(uuid.uuid4()) content = get_inlay_hint_html(view, inlay_hint, session, phantom_uuid) p = sublime.Phantom(region, content, sublime.LAYOUT_INLINE) From b5370ec03b03228ada772ed5f70d9ed21f323089 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D1=80=D0=B5=D0=B4=D1=80=D0=B0=D0=B3=20=D0=9D=D0=B8?= =?UTF-8?q?=D0=BA=D0=BE=D0=BB=D0=B8=D1=9B?= Date: Mon, 15 Aug 2022 20:01:42 +0200 Subject: [PATCH 49/65] remove unecessary line comment --- plugin/session_view.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugin/session_view.py b/plugin/session_view.py index 8138625a8..48f5c5b36 100644 --- a/plugin/session_view.py +++ b/plugin/session_view.py @@ -379,7 +379,5 @@ def _on_code_lenses_resolved_async(self, mode: str) -> None: def get_resolved_code_lenses_for_region(self, region: sublime.Region) -> Generator[CodeLens, None, None]: yield from self._code_lenses.get_resolved_code_lenses_for_region(region) - # ------------------------------------------------------------------------------------------------------------------ - def __str__(self) -> str: return '{}:{}'.format(self.session.config.name, self.view.id()) From 99fdf69fd8f235e3b6ca0499c08ceac24eb676ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D1=80=D0=B5=D0=B4=D1=80=D0=B0=D0=B3=20=D0=9D=D0=B8?= =?UTF-8?q?=D0=BA=D0=BE=D0=BB=D0=B8=D1=9B?= Date: Mon, 15 Aug 2022 20:02:49 +0200 Subject: [PATCH 50/65] be consistent add textDocument/inlayHint comment line --- plugin/session_buffer.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugin/session_buffer.py b/plugin/session_buffer.py index 2913d32e8..c2da1136c 100644 --- a/plugin/session_buffer.py +++ b/plugin/session_buffer.py @@ -619,6 +619,8 @@ def set_semantic_tokens_pending_refresh(self, needs_refresh: bool = True) -> Non def get_semantic_tokens(self) -> List[SemanticToken]: return self.semantic_tokens.tokens + # --- textDocument/inlayHint ---------------------------------------------------------------------------------- + def do_inlay_hints_async(self, view: sublime.View) -> None: if not userprefs().show_inlay_hints: return From 3fb30271a31d24beea868004dee0841eb6f9ed1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D1=80=D0=B5=D0=B4=D1=80=D0=B0=D0=B3=20=D0=9D=D0=B8?= =?UTF-8?q?=D0=BA=D0=BE=D0=BB=D0=B8=D1=9B?= Date: Mon, 15 Aug 2022 20:03:53 +0200 Subject: [PATCH 51/65] revert back the line that was accidentaly deleted when migrating the from session view to session buffer --- plugin/session_buffer.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugin/session_buffer.py b/plugin/session_buffer.py index c2da1136c..86d6ad71c 100644 --- a/plugin/session_buffer.py +++ b/plugin/session_buffer.py @@ -653,5 +653,7 @@ def remove_inlay_hint_phantom(self, phantom_uuid: str) -> None: def remove_all_inlay_hints(self) -> None: self._inlay_hints_phantom_set.update([]) + # ------------------------------------------------------------------------------------------------------------------ + def __str__(self) -> str: return '{}:{}:{}'.format(self.session.config.name, self.id, self.get_uri()) From 56f4f6e004ce8b50909a954ddaaaffb0f7a5aea7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D1=80=D0=B5=D0=B4=D1=80=D0=B0=D0=B3=20=D0=9D=D0=B8?= =?UTF-8?q?=D0=BA=D0=BE=D0=BB=D0=B8=D1=9B?= Date: Mon, 15 Aug 2022 23:09:14 +0200 Subject: [PATCH 52/65] remove all inlay hints on_before_remove --- plugin/session_buffer.py | 1 - plugin/session_view.py | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/session_buffer.py b/plugin/session_buffer.py index 86d6ad71c..00d2b3013 100644 --- a/plugin/session_buffer.py +++ b/plugin/session_buffer.py @@ -187,7 +187,6 @@ def add_session_view(self, sv: SessionViewProtocol) -> None: def remove_session_view(self, sv: SessionViewProtocol) -> None: self._clear_semantic_token_regions(sv.view) - self.remove_all_inlay_hints() self.session_views.remove(sv) def register_capability_async( diff --git a/plugin/session_view.py b/plugin/session_view.py index 48f5c5b36..84c27ef32 100644 --- a/plugin/session_view.py +++ b/plugin/session_view.py @@ -80,6 +80,7 @@ def on_before_remove(self) -> None: self.view.erase_regions(self.diagnostics_key(severity, False)) self.view.erase_regions(self.diagnostics_key(severity, True)) self.view.erase_regions("lsp_document_link") + self.session_buffer.remove_all_inlay_hints() self.session_buffer.remove_session_view(self) @property From 37857bbd0133656dfdf4155ae9600119e325a6b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D1=80=D0=B5=D0=B4=D1=80=D0=B0=D0=B3=20=D0=9D=D0=B8?= =?UTF-8?q?=D0=BA=D0=BE=D0=BB=D0=B8=D1=9B?= Date: Mon, 15 Aug 2022 23:10:28 +0200 Subject: [PATCH 53/65] rename present_inlay_hints_async to present_inlay_hints --- plugin/session_buffer.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugin/session_buffer.py b/plugin/session_buffer.py index 00d2b3013..107fe1083 100644 --- a/plugin/session_buffer.py +++ b/plugin/session_buffer.py @@ -637,9 +637,9 @@ def _on_inlay_hints_async(self, response: InlayHintResponse) -> None: if not view: return phantoms = [inlay_hint_to_phantom(view, inlay_hint, self.session) for inlay_hint in response] - sublime.set_timeout(lambda: self.present_inlay_hints_async(phantoms)) + sublime.set_timeout(lambda: self.present_inlay_hints(phantoms)) - def present_inlay_hints_async(self, phantoms: List[sublime.Phantom]) -> None: + def present_inlay_hints(self, phantoms: List[sublime.Phantom]) -> None: self._inlay_hints_phantom_set.update(phantoms) def remove_inlay_hint_phantom(self, phantom_uuid: str) -> None: From 9992e23375db3e911a1500f7191ba9a4c7154893 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D1=80=D0=B5=D0=B4=D1=80=D0=B0=D0=B3=20=D0=9D=D0=B8?= =?UTF-8?q?=D0=BA=D0=BE=D0=BB=D0=B8=D1=9B?= Date: Mon, 15 Aug 2022 23:11:46 +0200 Subject: [PATCH 54/65] handle None response --- plugin/session_buffer.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugin/session_buffer.py b/plugin/session_buffer.py index 107fe1083..da828e231 100644 --- a/plugin/session_buffer.py +++ b/plugin/session_buffer.py @@ -638,6 +638,8 @@ def _on_inlay_hints_async(self, response: InlayHintResponse) -> None: return phantoms = [inlay_hint_to_phantom(view, inlay_hint, self.session) for inlay_hint in response] sublime.set_timeout(lambda: self.present_inlay_hints(phantoms)) + else: + sublime.set_timeout(lambda: self.remove_all_inlay_hints()) def present_inlay_hints(self, phantoms: List[sublime.Phantom]) -> None: self._inlay_hints_phantom_set.update(phantoms) From f38e620b6286ff1d3862c2b9011856a794a6f787 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D1=80=D0=B5=D0=B4=D1=80=D0=B0=D0=B3=20=D0=9D=D0=B8?= =?UTF-8?q?=D0=BA=D0=BE=D0=BB=D0=B8=D1=9B?= Date: Mon, 15 Aug 2022 23:12:47 +0200 Subject: [PATCH 55/65] move self._inlay_hints_phantom_set before self._check_did_open(view) --- plugin/session_buffer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/session_buffer.py b/plugin/session_buffer.py index da828e231..1339e7180 100644 --- a/plugin/session_buffer.py +++ b/plugin/session_buffer.py @@ -114,9 +114,9 @@ def __init__(self, session_view: SessionViewProtocol, buffer_id: int, uri: Docum self.semantic_tokens = SemanticTokensData() self._semantic_region_keys = {} # type: Dict[str, int] self._last_semantic_region_key = 0 + self._inlay_hints_phantom_set = sublime.PhantomSet(view, "lsp_inlay_hints") self._check_did_open(view) self._session.register_session_buffer_async(self) - self._inlay_hints_phantom_set = sublime.PhantomSet(view, "lsp_inlay_hints") def __del__(self) -> None: mgr = self.session.manager() From b54f24c8dcb00ed05683e61d0b13a14816e75a13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D1=80=D0=B5=D0=B4=D1=80=D0=B0=D0=B3=20=D0=9D=D0=B8?= =?UTF-8?q?=D0=BA=D0=BE=D0=BB=D0=B8=D1=9B?= Date: Mon, 15 Aug 2022 23:13:48 +0200 Subject: [PATCH 56/65] move command's in the respected if is_clickable block --- plugin/inlay_hint.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/plugin/inlay_hint.py b/plugin/inlay_hint.py index b7e45c579..689126466 100644 --- a/plugin/inlay_hint.py +++ b/plugin/inlay_hint.py @@ -111,12 +111,12 @@ def format_inlay_hint_label(inlay_hint: InlayHint, session: Session, phantom_uui label = inlay_hint['label'] # type: ignore is_clickable = bool(inlay_hint.get('textEdits')) or can_resolve_inlay_hint if isinstance(label, str): - inlay_hint_click_command = sublime.command_url('lsp_inlay_hint_click', { - 'session_name': session.config.name, - 'inlay_hint': inlay_hint, - 'phantom_uuid': phantom_uuid - }) if is_clickable: + inlay_hint_click_command = sublime.command_url('lsp_inlay_hint_click', { + 'session_name': session.config.name, + 'inlay_hint': inlay_hint, + 'phantom_uuid': phantom_uuid + }) result += ''.format(command=inlay_hint_click_command) result += html.escape(label) if is_clickable: @@ -125,14 +125,14 @@ def format_inlay_hint_label(inlay_hint: InlayHint, session: Session, phantom_uui for label_part in label: value = "" - inlay_hint_click_command = sublime.command_url('lsp_inlay_hint_click', { - 'session_name': session.config.name, - 'inlay_hint': inlay_hint, - 'phantom_uuid': phantom_uuid, - 'label_part': label_part - }) is_clickable = is_clickable or bool(label_part.get('command')) if is_clickable: + inlay_hint_click_command = sublime.command_url('lsp_inlay_hint_click', { + 'session_name': session.config.name, + 'inlay_hint': inlay_hint, + 'phantom_uuid': phantom_uuid, + 'label_part': label_part + }) value += ''.format(command=inlay_hint_click_command) value += html.escape(label_part.get('value') or "") if is_clickable: From e80903ec38240ad3328a0fa94970782ff580ed9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D1=80=D0=B5=D0=B4=D1=80=D0=B0=D0=B3=20=D0=9D=D0=B8?= =?UTF-8?q?=D0=BA=D0=BE=D0=BB=D0=B8=D1=9B?= Date: Mon, 15 Aug 2022 23:16:36 +0200 Subject: [PATCH 57/65] remove present_inlay_hints_async from interface --- plugin/core/sessions.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/plugin/core/sessions.py b/plugin/core/sessions.py index 8ca03f580..dddf27aae 100644 --- a/plugin/core/sessions.py +++ b/plugin/core/sessions.py @@ -554,9 +554,6 @@ def get_semantic_tokens(self) -> List[Any]: def do_inlay_hints_async(self, view: sublime.View) -> None: ... - def present_inlay_hints_async(self, phantoms: List[sublime.Phantom]) -> None: - ... - def remove_inlay_hint_phantom(self, phantom_uuid: str) -> None: ... From cd5b94632ef472bb8d61cade5d307669609c9cc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D1=80=D0=B5=D0=B4=D1=80=D0=B0=D0=B3=20=D0=9D=D0=B8?= =?UTF-8?q?=D0=BA=D0=BE=D0=BB=D0=B8=D1=9B?= Date: Mon, 15 Aug 2022 23:17:14 +0200 Subject: [PATCH 58/65] remove unrelevant comment --- plugin/inlay_hint.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugin/inlay_hint.py b/plugin/inlay_hint.py index 689126466..3faf97bef 100644 --- a/plugin/inlay_hint.py +++ b/plugin/inlay_hint.py @@ -97,8 +97,6 @@ def get_inlay_hint_html(view: sublime.View, inlay_hint: InlayHint, session: Sess def format_inlay_hint_tooltip(tooltip: Optional[Union[str, MarkupContent]]) -> str: if isinstance(tooltip, str): - # Sublime Text doesn't support HTML for tooltips - # so we strip the HTML tags from the tooltip return tooltip if isinstance(tooltip, dict): # MarkupContent return tooltip.get('value') or "" From e63422e8e70de6b8f7cc9b1326d6c9626cfa4bf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D1=80=D0=B5=D0=B4=D1=80=D0=B0=D0=B3=20=D0=9D=D0=B8?= =?UTF-8?q?=D0=BA=D0=BE=D0=BB=D0=B8=D1=9B?= Date: Mon, 15 Aug 2022 23:18:30 +0200 Subject: [PATCH 59/65] move inlay_hint_to_phantom before get_inlay_hint_html --- plugin/inlay_hint.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/plugin/inlay_hint.py b/plugin/inlay_hint.py index 3faf97bef..a35140d03 100644 --- a/plugin/inlay_hint.py +++ b/plugin/inlay_hint.py @@ -56,6 +56,16 @@ def handle_label_part_command(self, session_name: str, label_part: Optional[Inla self.view.run_command("lsp_execute", args) +def inlay_hint_to_phantom(view: sublime.View, inlay_hint: InlayHint, session: Session) -> sublime.Phantom: + position = inlay_hint["position"] # type: ignore + region = sublime.Region(point_to_offset(Point.from_lsp(position), view)) + phantom_uuid = str(uuid.uuid4()) + content = get_inlay_hint_html(view, inlay_hint, session, phantom_uuid) + p = sublime.Phantom(region, content, sublime.LAYOUT_INLINE) + setattr(p, 'lsp_uuid', phantom_uuid) + return p + + def get_inlay_hint_html(view: sublime.View, inlay_hint: InlayHint, session: Session, phantom_uuid: str) -> str: tooltip = format_inlay_hint_tooltip(inlay_hint.get("tooltip")) label = format_inlay_hint_label(inlay_hint, session, phantom_uuid) @@ -141,13 +151,3 @@ def format_inlay_hint_label(inlay_hint: InlayHint, session: Session, phantom_uui value=value ) return result - - -def inlay_hint_to_phantom(view: sublime.View, inlay_hint: InlayHint, session: Session) -> sublime.Phantom: - position = inlay_hint["position"] # type: ignore - region = sublime.Region(point_to_offset(Point.from_lsp(position), view)) - phantom_uuid = str(uuid.uuid4()) - content = get_inlay_hint_html(view, inlay_hint, session, phantom_uuid) - p = sublime.Phantom(region, content, sublime.LAYOUT_INLINE) - setattr(p, 'lsp_uuid', phantom_uuid) - return p From 3823e3b7c69b2cf9d7ec29321f38d0fe426d49a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D1=80=D0=B5=D0=B4=D1=80=D0=B0=D0=B3=20=D0=9D=D0=B8?= =?UTF-8?q?=D0=BA=D0=BE=D0=BB=D0=B8=D1=9B?= Date: Mon, 15 Aug 2022 23:23:22 +0200 Subject: [PATCH 60/65] Revert "remove all inlay hints on_before_remove" This reverts commit 56f4f6e004ce8b50909a954ddaaaffb0f7a5aea7. --- plugin/session_buffer.py | 1 + plugin/session_view.py | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/session_buffer.py b/plugin/session_buffer.py index 1339e7180..d06827f16 100644 --- a/plugin/session_buffer.py +++ b/plugin/session_buffer.py @@ -187,6 +187,7 @@ def add_session_view(self, sv: SessionViewProtocol) -> None: def remove_session_view(self, sv: SessionViewProtocol) -> None: self._clear_semantic_token_regions(sv.view) + self.remove_all_inlay_hints() self.session_views.remove(sv) def register_capability_async( diff --git a/plugin/session_view.py b/plugin/session_view.py index 84c27ef32..48f5c5b36 100644 --- a/plugin/session_view.py +++ b/plugin/session_view.py @@ -80,7 +80,6 @@ def on_before_remove(self) -> None: self.view.erase_regions(self.diagnostics_key(severity, False)) self.view.erase_regions(self.diagnostics_key(severity, True)) self.view.erase_regions("lsp_document_link") - self.session_buffer.remove_all_inlay_hints() self.session_buffer.remove_session_view(self) @property From 2523ed8743e7184a93ec1e511fffc65475acbca3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D1=80=D0=B5=D0=B4=D1=80=D0=B0=D0=B3=20=D0=9D=D0=B8?= =?UTF-8?q?=D0=BA=D0=BE=D0=BB=D0=B8=D1=9B?= Date: Mon, 15 Aug 2022 23:29:43 +0200 Subject: [PATCH 61/65] remove inlay hints if there are no session_views --- plugin/session_buffer.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugin/session_buffer.py b/plugin/session_buffer.py index d06827f16..d96d620ee 100644 --- a/plugin/session_buffer.py +++ b/plugin/session_buffer.py @@ -187,8 +187,9 @@ def add_session_view(self, sv: SessionViewProtocol) -> None: def remove_session_view(self, sv: SessionViewProtocol) -> None: self._clear_semantic_token_regions(sv.view) - self.remove_all_inlay_hints() self.session_views.remove(sv) + if len(self.session_views) == 0: + self.remove_all_inlay_hints() def register_capability_async( self, From 9f22d31b9e9368387e8243b9779a9d6841812d6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D1=80=D0=B5=D0=B4=D1=80=D0=B0=D0=B3=20=D0=9D=D0=B8?= =?UTF-8?q?=D0=BA=D0=BE=D0=BB=D0=B8=D1=9B?= Date: Mon, 15 Aug 2022 23:30:48 +0200 Subject: [PATCH 62/65] now the remove_all_inlay_hints can go away --- plugin/core/sessions.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/plugin/core/sessions.py b/plugin/core/sessions.py index dddf27aae..85e86874f 100644 --- a/plugin/core/sessions.py +++ b/plugin/core/sessions.py @@ -557,9 +557,6 @@ def do_inlay_hints_async(self, view: sublime.View) -> None: def remove_inlay_hint_phantom(self, phantom_uuid: str) -> None: ... - def remove_all_inlay_hints(self) -> None: - ... - class AbstractViewListener(metaclass=ABCMeta): From 53beedc92a4eeb0bccbe3ccd9bbd3376979d295f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D1=80=D0=B5=D0=B4=D1=80=D0=B0=D0=B3=20=D0=9D=D0=B8?= =?UTF-8?q?=D0=BA=D0=BE=D0=BB=D0=B8=D1=9B?= Date: Sat, 20 Aug 2022 14:42:57 +0200 Subject: [PATCH 63/65] remove margin from phantoms even if inlay hints have paddingLeft or paddingRight --- plugin/inlay_hint.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/plugin/inlay_hint.py b/plugin/inlay_hint.py index a35140d03..17505da09 100644 --- a/plugin/inlay_hint.py +++ b/plugin/inlay_hint.py @@ -69,8 +69,6 @@ def inlay_hint_to_phantom(view: sublime.View, inlay_hint: InlayHint, session: Se def get_inlay_hint_html(view: sublime.View, inlay_hint: InlayHint, session: Session, phantom_uuid: str) -> str: tooltip = format_inlay_hint_tooltip(inlay_hint.get("tooltip")) label = format_inlay_hint_label(inlay_hint, session, phantom_uuid) - margin_left = "0.6rem" if inlay_hint.get("paddingLeft", False) else "0" - margin_right = "0.6rem" if inlay_hint.get("paddingRight", False) else "0" font = view.settings().get('font_face') or "monospace" html = """ @@ -79,8 +77,6 @@ def get_inlay_hint_html(view: sublime.View, inlay_hint: InlayHint, session: Sess color: color(var(--foreground) alpha(0.6)); background-color: color(var(--foreground) alpha(0.08)); border-radius: 4px; - margin-left: {margin_left}; - margin-right: {margin_right}; padding: 0.05em 4px; font-size: 0.9em; font-family: {font}; @@ -96,8 +92,6 @@ def get_inlay_hint_html(view: sublime.View, inlay_hint: InlayHint, session: Sess """.format( - margin_left=margin_left, - margin_right=margin_right, tooltip=tooltip, font=font, label=label From 653f9bee0c9c90a31fafbcebe922093f57afcb2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D1=80=D0=B5=D0=B4=D1=80=D0=B0=D0=B3=20=D0=9D=D0=B8?= =?UTF-8?q?=D0=BA=D0=BE=D0=BB=D0=B8=D1=9B?= Date: Sat, 20 Aug 2022 16:22:41 +0200 Subject: [PATCH 64/65] change default value to false --- LSP.sublime-settings | 2 +- plugin/core/types.py | 2 +- sublime-package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/LSP.sublime-settings b/LSP.sublime-settings index a2cbff4ab..0e4c478ec 100644 --- a/LSP.sublime-settings +++ b/LSP.sublime-settings @@ -135,7 +135,7 @@ "show_code_lens": "annotation", // Inlay hints are short annotations within the code, which show variable types or parameter names. - "show_inlay_hints": true, + "show_inlay_hints": false, // Show code actions in hover popup if available "show_code_actions_in_hover": true, diff --git a/plugin/core/types.py b/plugin/core/types.py index c724f7d8c..ddfb128cd 100644 --- a/plugin/core/types.py +++ b/plugin/core/types.py @@ -243,7 +243,7 @@ def r(name: str, default: Union[bool, int, str, list, dict]) -> None: r("semantic_highlighting", False) r("show_code_actions", "annotation") r("show_code_lens", "annotation") - r("show_inlay_hints", True) + r("show_inlay_hints", False) r("show_code_actions_in_hover", True) r("show_diagnostics_count_in_view_status", False) r("show_diagnostics_in_view_status", True) diff --git a/sublime-package.json b/sublime-package.json index f95d7589c..eb5858358 100644 --- a/sublime-package.json +++ b/sublime-package.json @@ -511,7 +511,7 @@ }, "show_inlay_hints": { "type": "boolean", - "default": true, + "default": false, "markdownDescription": "Inlay hints are short annotations within the code, which show variable types or parameter names." }, }, From 804f1c0a4c195b8bd0c7798389184c87a0a32050 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D1=80=D0=B5=D0=B4=D1=80=D0=B0=D0=B3=20=D0=9D=D0=B8?= =?UTF-8?q?=D0=BA=D0=BE=D0=BB=D0=B8=D1=9B?= Date: Sat, 20 Aug 2022 16:24:51 +0200 Subject: [PATCH 65/65] be more explicit about the setting description --- LSP.sublime-settings | 2 +- sublime-package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/LSP.sublime-settings b/LSP.sublime-settings index 0e4c478ec..20040c51b 100644 --- a/LSP.sublime-settings +++ b/LSP.sublime-settings @@ -134,7 +134,7 @@ // "phantom" - show a phantom on the top when code actions are available "show_code_lens": "annotation", - // Inlay hints are short annotations within the code, which show variable types or parameter names. + // Show inlay hints in the editor. Inlay hints are short annotations within the code, which show variable types or parameter names. "show_inlay_hints": false, // Show code actions in hover popup if available diff --git a/sublime-package.json b/sublime-package.json index eb5858358..4a7ce5692 100644 --- a/sublime-package.json +++ b/sublime-package.json @@ -512,7 +512,7 @@ "show_inlay_hints": { "type": "boolean", "default": false, - "markdownDescription": "Inlay hints are short annotations within the code, which show variable types or parameter names." + "markdownDescription": "Show inlay hints in the editor. Inlay hints are short annotations within the code, which show variable types or parameter names." }, }, "additionalProperties": false