diff --git a/plugin/core/constants.py b/plugin/core/constants.py index be59b9ebb..9c6345d0c 100644 --- a/plugin/core/constants.py +++ b/plugin/core/constants.py @@ -44,6 +44,8 @@ class RequestFlags(IntFlag): """ textDocument/documentColor """ INLAY_HINT = 2 """ textDocument/inlayHint """ + SEMANTIC_TOKENS = 4 + """ textDocument/semanticTokens """ class RegionKey(StrEnum): diff --git a/plugin/core/sessions.py b/plugin/core/sessions.py index 384b35dd1..32771f3bb 100644 --- a/plugin/core/sessions.py +++ b/plugin/core/sessions.py @@ -2166,7 +2166,10 @@ def m_workspace_semanticTokens_refresh(self, params: None, request_id: Any) -> N self.send_response(Response(request_id, None)) visible_session_views, not_visible_session_views = self.session_views_by_visibility() for sv in visible_session_views: - sv.session_buffer.do_semantic_tokens_async(sv.view) + if sv.get_request_flags() & RequestFlags.SEMANTIC_TOKENS: + sv.session_buffer.do_semantic_tokens_async(sv.view) + else: + sv.session_buffer.set_semantic_tokens_pending_refresh() for sv in not_visible_session_views: sv.session_buffer.set_semantic_tokens_pending_refresh() diff --git a/plugin/documents.py b/plugin/documents.py index 49d09ab0f..5e53cdccb 100644 --- a/plugin/documents.py +++ b/plugin/documents.py @@ -264,6 +264,13 @@ def on_session_initialized_async(self, session: Session) -> None: for sb in self.session_buffers_async('inlayHintProvider'): if sb.session != session: sb.remove_all_inlay_hints() + if request_flags & RequestFlags.SEMANTIC_TOKENS: + for sb in self.session_buffers_async('semanticTokensProvider'): + if sb.session != session: + sb.clear_semantic_tokens_async() + if request_id := sb.semantic_tokens.pending_response: + sb.session.cancel_request_async(request_id) + sb.semantic_tokens.pending_response = None def on_session_shutdown_async(self, session: Session) -> None: if removed_session := self._session_views.pop(session.config.name, None): @@ -356,6 +363,8 @@ def get_request_flags(self, session: Session) -> RequestFlags: request_flags |= RequestFlags.DOCUMENT_COLOR if session == self.session_async('inlayHintProvider', 0): request_flags |= RequestFlags.INLAY_HINT + if session == self.session_async('semanticTokensProvider', 0): + request_flags |= RequestFlags.SEMANTIC_TOKENS return request_flags # --- Callbacks from Sublime Text ---------------------------------------------------------------------------------- @@ -394,7 +403,9 @@ def on_activated_async(self) -> None: if sb.document_diagnostic_needs_refresh: sb.set_document_diagnostic_pending_refresh(needs_refresh=False) sb.do_document_diagnostic_async(self.view, self.view.change_count()) - if sb.semantic_tokens.needs_refresh: + if sb.semantic_tokens.needs_refresh \ + and (session_view := sb.session.session_view_for_view_async(self.view)) \ + and session_view.get_request_flags() & RequestFlags.SEMANTIC_TOKENS: sb.set_semantic_tokens_pending_refresh(needs_refresh=False) sb.do_semantic_tokens_async(self.view) if sb.inlay_hints_needs_refresh \ diff --git a/plugin/semantic_highlighting.py b/plugin/semantic_highlighting.py index e63cc9e43..12c03a653 100644 --- a/plugin/semantic_highlighting.py +++ b/plugin/semantic_highlighting.py @@ -5,7 +5,7 @@ import sublime import os -SemanticTokensInfo = List[Tuple[str, str, str]] +SemanticTokensInfo = Tuple[str, str, str] POPUP_CSS = ''' @@ -79,25 +79,22 @@ def run(self, _: sublime.Edit) -> None: semantic_info ) - def _get_semantic_info(self, point: int) -> SemanticTokensInfo: - info: SemanticTokensInfo = [] - for session in self.sessions('semanticTokensProvider'): + def _get_semantic_info(self, point: int) -> SemanticTokensInfo | None: + if session := self.best_session('semanticTokensProvider', 0): for sv in session.session_views_async(): if self.view == sv.view: for token in sv.session_buffer.get_semantic_tokens(): if token.region.contains(point) and point < token.region.end(): token_modifiers = ', '.join(token.modifiers) if token.modifiers else '-' - info.append((token.type, token_modifiers, session.config.name)) - break + return (token.type, token_modifiers, session.config.name) break - return info def _render_with_plain_string_stackframes( self, scope: str, scope_list: str, stack: list[str], - semantic_info: SemanticTokensInfo, + semantic_info: SemanticTokensInfo | None, ) -> None: backtrace = '' digits_len = 1 @@ -118,7 +115,7 @@ def _render_with_fancy_stackframes( scope: str, scope_list: str, stack: list[Any], - semantic_info: SemanticTokensInfo, + semantic_info: SemanticTokensInfo | None, ) -> None: backtrace = '' digits_len = 1 @@ -154,13 +151,16 @@ def _show_popup( scope: str, scope_list: str, backtrace: str, - semantic_info: SemanticTokensInfo, + semantic_info: SemanticTokensInfo | None, on_navigate: Callable[[str], None] ) -> None: - semantic_info_html = '' - for info in semantic_info: - semantic_info_html += f""" -
Type: {info[0]}, Modifiers: {info[1]} {info[2]}
+ semantic_token_html = '' + if semantic_info: + semantic_token_html = f""" +
+

Semantic Token {semantic_info[2]}

+
Type: {semantic_info[0]}
+
Modifiers: {semantic_info[1]}
""" css = POPUP_CSS % digits_len html = f""" @@ -172,9 +172,7 @@ def _show_popup(

{scope_list}

Context Backtrace

{backtrace} -
-

Semantic Tokens

- {semantic_info_html or '-'} + {semantic_token_html} """ self.view.show_popup(html, max_width=512, max_height=512, on_navigate=on_navigate) diff --git a/plugin/session_buffer.py b/plugin/session_buffer.py index fc9079fab..805d5ddce 100644 --- a/plugin/session_buffer.py +++ b/plugin/session_buffer.py @@ -196,7 +196,8 @@ def _check_did_open(self, view: sublime.View) -> None: if request_flags & RequestFlags.DOCUMENT_COLOR: self._do_color_boxes_async(view, version) self.do_document_diagnostic_async(view, version) - self.do_semantic_tokens_async(view, view.size() > HUGE_FILE_SIZE) + if request_flags & RequestFlags.SEMANTIC_TOKENS: + self.do_semantic_tokens_async(view, view.size() > HUGE_FILE_SIZE) if request_flags & RequestFlags.INLAY_HINT: self.do_inlay_hints_async(view) self.do_code_lenses_async(view) @@ -406,7 +407,8 @@ def _on_after_change_async(self, view: sublime.View, version: int, suppress_requ self.session.has_capability('diagnosticProvider.workspaceDiagnostics'): self._workspace_diagnostics_debouncer_async.debounce( self.session.do_workspace_diagnostics_async, timeout_ms=WORKSPACE_DIAGNOSTICS_TIMEOUT) - self.do_semantic_tokens_async(view) + if request_flags & RequestFlags.SEMANTIC_TOKENS: + self.do_semantic_tokens_async(view) if userprefs().link_highlight_style in ("underline", "none"): self._do_document_link_async(view, version) if request_flags & RequestFlags.INLAY_HINT: