Skip to content

Commit

Permalink
fix: code actions on save not fixing issues if saving quickly (#2540)
Browse files Browse the repository at this point in the history
  • Loading branch information
rchl authored Nov 2, 2024
1 parent 2b3a48c commit 04827c7
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 19 deletions.
2 changes: 2 additions & 0 deletions plugin/code_actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,8 @@ def on_response(
session = sb.session
request = request_factory(sb)
if request:
# Pull for diagnostics to ensure that server computes them before receiving code action request.
sb.do_document_diagnostic_async(listener.view)
response_handler = partial(on_response, sb)
task: Promise[list[CodeActionOrCommand] | None] = session.send_request_task(request)
tasks.append(task.then(response_handler))
Expand Down
49 changes: 30 additions & 19 deletions plugin/session_buffer.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,15 @@ def update(self, version: int, changes: Iterable[sublime.TextChange]) -> None:
self.changes.extend(changes)


class PendingDocumentDiagnosticRequest:

__slots__ = ('version', 'request_id')

def __init__(self, version: int, request_id: int) -> None:
self.version = version
self.request_id = request_id


class SemanticTokensData:

__slots__ = (
Expand Down Expand Up @@ -122,7 +131,7 @@ def __init__(self, session_view: SessionViewProtocol, buffer_id: int, uri: Docum
self.diagnostics_flags = 0
self._diagnostics_are_visible = False
self.document_diagnostic_needs_refresh = False
self._document_diagnostic_pending_response: int | None = None
self._document_diagnostic_pending_request: PendingDocumentDiagnosticRequest | None = None
self._last_synced_version = 0
self._last_text_change_time = 0.0
self._diagnostics_debouncer_async = DebouncerNonThreadSafe(async_thread=True)
Expand Down Expand Up @@ -471,30 +480,32 @@ def update_document_link(self, new_link: DocumentLink) -> None:

def do_document_diagnostic_async(self, view: sublime.View, version: int | None = None) -> None:
mgr = self.session.manager()
if not mgr:
if not mgr or not self.has_capability("diagnosticProvider"):
return
if mgr.should_ignore_diagnostics(self._last_known_uri, self.session.config):
return
if version is None:
version = view.change_count()
if self.has_capability("diagnosticProvider"):
if self._document_diagnostic_pending_response:
self.session.cancel_request(self._document_diagnostic_pending_response)
params: DocumentDiagnosticParams = {'textDocument': text_document_identifier(view)}
identifier = self.get_capability("diagnosticProvider.identifier")
if identifier:
params['identifier'] = identifier
result_id = self.session.diagnostics_result_ids.get(self._last_known_uri)
if result_id is not None:
params['previousResultId'] = result_id
self._document_diagnostic_pending_response = self.session.send_request_async(
Request.documentDiagnostic(params, view),
partial(self._on_document_diagnostic_async, version),
partial(self._on_document_diagnostic_error_async, version)
)
if self._document_diagnostic_pending_request:
if self._document_diagnostic_pending_request.version == version:
return
self.session.cancel_request(self._document_diagnostic_pending_request.request_id)
params: DocumentDiagnosticParams = {'textDocument': text_document_identifier(view)}
identifier = self.get_capability("diagnosticProvider.identifier")
if identifier:
params['identifier'] = identifier
result_id = self.session.diagnostics_result_ids.get(self._last_known_uri)
if result_id is not None:
params['previousResultId'] = result_id
request_id = self.session.send_request_async(
Request.documentDiagnostic(params, view),
partial(self._on_document_diagnostic_async, version),
partial(self._on_document_diagnostic_error_async, version)
)
self._document_diagnostic_pending_request = PendingDocumentDiagnosticRequest(version, request_id)

def _on_document_diagnostic_async(self, version: int, response: DocumentDiagnosticReport) -> None:
self._document_diagnostic_pending_response = None
self._document_diagnostic_pending_request = None
self._if_view_unchanged(self._apply_document_diagnostic_async, version)(response)

def _apply_document_diagnostic_async(
Expand All @@ -511,7 +522,7 @@ def _apply_document_diagnostic_async(
None, cast(DocumentDiagnosticReport, diagnostic_report))

def _on_document_diagnostic_error_async(self, version: int, error: ResponseError) -> None:
self._document_diagnostic_pending_response = None
self._document_diagnostic_pending_request = None
if error['code'] == LSPErrorCodes.ServerCancelled:
data = error.get('data')
if is_diagnostic_server_cancellation_data(data) and data['retriggerRequest']:
Expand Down

0 comments on commit 04827c7

Please sign in to comment.