diff --git a/plugin/code_lens.py b/plugin/code_lens.py index cfdc1591c..90ab41e7e 100644 --- a/plugin/code_lens.py +++ b/plugin/code_lens.py @@ -1,5 +1,5 @@ -from .core.protocol import CodeLens, Range -from .core.typing import List, Tuple, Dict, Iterable, Generator +from .core.protocol import CodeLens, Error, Range +from .core.typing import List, Tuple, Dict, Iterable, Generator, Union from .core.registry import LspTextCommand from .core.registry import windows from .core.views import make_command_link @@ -15,6 +15,7 @@ class CodeLensData: 'region', 'session_name', 'annotation', + 'is_resolve_error', ) def __init__(self, data: CodeLens, view: sublime.View, session_name: str) -> None: @@ -23,13 +24,14 @@ def __init__(self, data: CodeLens, view: sublime.View, session_name: str) -> Non self.session_name = session_name self.annotation = '...' self.resolve_annotation() + self.is_resolve_error = False def __repr__(self) -> str: return 'CodeLensData(resolved={0}, region={1!r})'.format(self.is_resolved(), self.region) def is_resolved(self) -> bool: """A code lens is considered resolved if the inner data contains the 'command' key.""" - return 'command' in self.data + return 'command' in self.data or self.is_resolve_error def to_lsp(self) -> CodeLens: copy = self.data.copy() @@ -55,9 +57,13 @@ def resolve_annotation(self) -> None: else: self.annotation = '...' - def resolve(self, view: sublime.View, code_lens: CodeLens) -> None: - self.data = code_lens - self.region = range_to_region(Range.from_lsp(code_lens['range']), view) + def resolve(self, view: sublime.View, code_lens_or_error: Union[CodeLens, Error]) -> None: + if isinstance(code_lens_or_error, Error): + self.is_resolve_error = True + self.annotation = html_escape(str(code_lens_or_error)) + return + self.data = code_lens_or_error + self.region = range_to_region(Range.from_lsp(code_lens_or_error['range']), view) self.resolve_annotation() diff --git a/plugin/session_view.py b/plugin/session_view.py index 63e03c8db..ebdd620e0 100644 --- a/plugin/session_view.py +++ b/plugin/session_view.py @@ -78,6 +78,9 @@ def __del__(self) -> None: self.view.erase_regions(self.diagnostics_key(severity, False)) self.view.erase_regions(self.diagnostics_key(severity, True)) + def _is_listener_alive(self) -> bool: + return bool(self.listener()) + def _clear_auto_complete_triggers(self, settings: sublime.Settings) -> None: '''Remove all of our modifications to the view's "auto_complete_triggers"''' triggers = settings.get(self.AC_TRIGGERS_KEY) @@ -295,7 +298,7 @@ def start_code_lenses_async(self) -> None: self.session.send_request_async(Request("textDocument/codeLens", params, self.view), self._on_code_lenses_async) def _on_code_lenses_async(self, response: Optional[List[CodeLens]]) -> None: - if not isinstance(response, list): + if not self._is_listener_alive() or not isinstance(response, list): return self._code_lenses.handle_response(self.session.config.name, response) self.resolve_visible_code_lenses_async() @@ -306,16 +309,19 @@ def resolve_visible_code_lenses_async(self) -> None: return if self._code_lenses.is_empty(): return - promises = [] # type: List[Promise[None]] - for code_lens in self._code_lenses.unresolved_visible_code_lenses(self.view.visible_region()): - callback = functools.partial(code_lens.resolve, self.view) - promise = self.session.send_request_task( - Request("codeLens/resolve", code_lens.data, self.view) - ).then(callback) - promises.append(promise) + promises = [Promise.resolve(None)] # type: List[Promise[None]] + if self.session.get_capability('codeLensProvider.resolveProvider'): + for code_lens in self._code_lenses.unresolved_visible_code_lenses(self.view.visible_region()): + request = Request("codeLens/resolve", code_lens.data, self.view) + callback = functools.partial(code_lens.resolve, self.view) + promise = self.session.send_request_task(request).then(callback) + promises.append(promise) mode = userprefs().show_code_lens - render = functools.partial(self._code_lenses.render, mode) - Promise.all(promises).then(lambda _: sublime.set_timeout(render)) + Promise.all(promises).then(lambda _: self._on_code_lenses_resolved_async(mode)) + + def _on_code_lenses_resolved_async(self, mode: str) -> None: + if self._is_listener_alive(): + sublime.set_timeout(lambda: self._code_lenses.render(mode)) 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)