Skip to content

Commit

Permalink
Solve Flymake diagnostics synchronization problems
Browse files Browse the repository at this point in the history
A diagnostics-lazy server is one who doesn't re-report already
reported diagnostics when it received textDocument/didSave.

Such is the case of Clangd, for example.  Before this change, saving
an Eglot/Clang-managed buffer with some diagnostics caused the Flymake
indicator to display Wait[0 0] until some change was actually done to
the buffer.

That is because Flymake, by default, wants diagnostics on buffer save,
per flymake-start-on-save-buffer.  But it doesn't work to simply turn
that off.  That's because if one types something and quickly saves,
and the LSP diagnostics do come in after the save (for some reason,
like server latency), then Flymake sometimes doesn't request any
diagnostics at all.

The reason for the Flymake behaviour wasn't investigated, but that
wasn't a very good solution either

Rather this change makes it so that when such a Flymake request comes
in, it always gets served immediately with the latest information.
The latest information is now always stored in eglot--diagnostics,
with eglot--unreported-diagnotics being removed.  The up-to-date list
is reported to Flymake whenever it requests it.  It is updated
whenever the LSP server decides to.

* eglot.el (eglot--last-reported-diagnostics): Delete.
(eglot--unreported-diagnostics): Delete.
(eglot--diagnostics): New variable..
(eglot--maybe-activate-editing-mode): Use eglot--diagnostics.
(eglot-handle-notification): Set eglot--diaggnostics.
(eglot-flymake-backend): Read eglot--diagnostics. Always report.
(eglot--report-to-flymake): Set eglot--diagnostics.
  • Loading branch information
joaotavora committed Apr 6, 2022
1 parent 000598a commit 2c34dae
Showing 1 changed file with 6 additions and 8 deletions.
14 changes: 6 additions & 8 deletions eglot.el
Original file line number Diff line number Diff line change
Expand Up @@ -1701,8 +1701,8 @@ Use `eglot-managed-p' to determine if current buffer is managed.")
(or (eglot-current-server)
(jsonrpc-error "No current JSON-RPC connection")))

(defvar-local eglot--unreported-diagnostics nil
"Unreported Flymake diagnostics for this buffer.")
(defvar-local eglot--diagnostics nil
"Flymake diagnostics for this buffer.")

(defvar revert-buffer-preserve-modes)
(defun eglot--after-revert-hook ()
Expand All @@ -1717,7 +1717,7 @@ If it is activated, also signal textDocument/didOpen."
;; Called when `revert-buffer-in-progress-p' is t but
;; `revert-buffer-preserve-modes' is nil.
(when (and buffer-file-name (eglot-current-server))
(setq eglot--unreported-diagnostics `(:just-opened . nil))
(setq eglot--diagnostics nil)
(eglot--managed-mode)
(eglot--signal-textDocument/didOpen))))

Expand Down Expand Up @@ -1995,7 +1995,7 @@ COMMAND is a symbol naming the command."
finally (cond (eglot--current-flymake-report-fn
(eglot--report-to-flymake diags))
(t
(setq eglot--unreported-diagnostics (cons t diags))))))
(setq eglot--diagnostics diags)))))
(cl-loop
with path = (expand-file-name (eglot--uri-to-path uri))
for diag-spec across diagnostics
Expand Down Expand Up @@ -2305,9 +2305,7 @@ may be called multiple times (respecting the protocol of
`flymake-backend-functions')."
(cond (eglot--managed-mode
(setq eglot--current-flymake-report-fn report-fn)
;; Report anything unreported
(when eglot--unreported-diagnostics
(eglot--report-to-flymake (cdr eglot--unreported-diagnostics))))
(eglot--report-to-flymake eglot--diagnostics))
(t
(funcall report-fn nil))))

Expand All @@ -2322,7 +2320,7 @@ may be called multiple times (respecting the protocol of
;; keyword forces flymake to delete
;; them (github#159).
:region (cons (point-min) (point-max))))
(setq eglot--unreported-diagnostics nil))
(setq eglot--diagnostics diags))

(defun eglot-xref-backend () "EGLOT xref backend." 'eglot)

Expand Down

0 comments on commit 2c34dae

Please sign in to comment.