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""" -
{scope_list}