Skip to content

Commit

Permalink
fix: code actions on save not fixing issues if saving quickly
Browse files Browse the repository at this point in the history
  • Loading branch information
rchl committed Oct 30, 2024
1 parent de767d1 commit 87b33b4
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 @@ -130,6 +130,8 @@ def request_factory(sb: SessionBufferProtocol) -> Request | None:
if diag_sb == sb:
diagnostics = diags
break
# Pull for diagnostics to ensure that server computes them before receiving code action request.
sb.do_document_diagnostic_async(view)
params = text_document_code_action_params(view, region, diagnostics, matching_kinds, manual=False)
return Request.codeAction(params, view)

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 87b33b4

Please sign in to comment.