diff options
| author | João Távora | 2026-01-30 12:35:14 +0000 |
|---|---|---|
| committer | João Távora | 2026-01-30 12:55:32 +0000 |
| commit | d0daaead22f37df587113281ebdfd0d4c94636cf (patch) | |
| tree | 4417750878ec4635d881dbf9b13581142bdec2c4 | |
| parent | 705c0e3729bf53db9e84ae7c8b932ebc3b2da934 (diff) | |
| download | emacs-d0daaead22f37df587113281ebdfd0d4c94636cf.tar.gz emacs-d0daaead22f37df587113281ebdfd0d4c94636cf.zip | |
Eglot: recall diagnostics froms unopened files on session start
This is exclusively for the benefit of rust-analyzer, which
sends publishDiagnostics for all project files upfront, and
never republishes them on 'didOpen'.
See https://github.com/joaotavora/eglot/issues/1531.
* lisp/progmodes/eglot.el (eglot--flymake-handle-push): Simplify.
Don't flymake-list-only-diagnostics here.
Save original diagnostic in flymake-list-only-diagnostics setting.
(eglot--on-shutdown): Cleanup flymake-list-only-diagnostics.
(eglot--flymake-report-push+pulled): Hack in data from
flymake-list-only-diagnostics.
| -rw-r--r-- | lisp/progmodes/eglot.el | 33 |
1 files changed, 24 insertions, 9 deletions
diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index 251b4e58e38..28ee14c67cb 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el | |||
| @@ -1438,6 +1438,12 @@ PRESERVE-BUFFERS as in `eglot-shutdown', which see." | |||
| 1438 | (maphash (lambda (f s) | 1438 | (maphash (lambda (f s) |
| 1439 | (when (eq s server) (remhash f eglot--servers-by-xrefed-file))) | 1439 | (when (eq s server) (remhash f eglot--servers-by-xrefed-file))) |
| 1440 | eglot--servers-by-xrefed-file) | 1440 | eglot--servers-by-xrefed-file) |
| 1441 | ;; Cleanup entries in 'flymake-list-only-diagnostics' | ||
| 1442 | (setq flymake-list-only-diagnostics | ||
| 1443 | (cl-delete-if | ||
| 1444 | (lambda (x) (eq server | ||
| 1445 | (get-text-property 0 'eglot--server (car x)))) | ||
| 1446 | flymake-list-only-diagnostics)) | ||
| 1441 | (cond ((eglot--shutdown-requested server) | 1447 | (cond ((eglot--shutdown-requested server) |
| 1442 | t) | 1448 | t) |
| 1443 | ((not (eglot--inhibit-autoreconnect server)) | 1449 | ((not (eglot--inhibit-autoreconnect server)) |
| @@ -3422,11 +3428,8 @@ object. The originator of this \"push\" is usually either regular | |||
| 3422 | (with-current-buffer buffer | 3428 | (with-current-buffer buffer |
| 3423 | (if (and version (/= version eglot--docver)) | 3429 | (if (and version (/= version eglot--docver)) |
| 3424 | (cl-return-from eglot--flymake-handle-push)) | 3430 | (cl-return-from eglot--flymake-handle-push)) |
| 3425 | (setq | 3431 | ;; if no explicit version received, assume it's current. |
| 3426 | ;; if no explicit version received, assume it's current. | 3432 | (setq version eglot--docver) |
| 3427 | version eglot--docver | ||
| 3428 | flymake-list-only-diagnostics | ||
| 3429 | (assoc-delete-all path flymake-list-only-diagnostics)) | ||
| 3430 | (funcall then diagnostics)) | 3433 | (funcall then diagnostics)) |
| 3431 | (cl-loop | 3434 | (cl-loop |
| 3432 | for diag-spec across diagnostics | 3435 | for diag-spec across diagnostics |
| @@ -3437,12 +3440,13 @@ object. The originator of this \"push\" is usually either regular | |||
| 3437 | (flymake-make-diagnostic | 3440 | (flymake-make-diagnostic |
| 3438 | path (cons line char) nil | 3441 | path (cons line char) nil |
| 3439 | (eglot--flymake-diag-type severity) | 3442 | (eglot--flymake-diag-type severity) |
| 3440 | (list source code message)))) | 3443 | (list source code message) |
| 3444 | `((eglot-lsp-diag . ,diag-spec))))) | ||
| 3441 | into diags | 3445 | into diags |
| 3442 | finally | 3446 | finally |
| 3443 | (setq flymake-list-only-diagnostics | 3447 | (setf (alist-get (propertize path 'eglot--server server) |
| 3444 | (assoc-delete-all path flymake-list-only-diagnostics)) | 3448 | flymake-list-only-diagnostics nil nil #'equal) |
| 3445 | (push (cons path diags) flymake-list-only-diagnostics)))) | 3449 | diags)))) |
| 3446 | 3450 | ||
| 3447 | (cl-defun eglot--flymake-pull (&aux (server (eglot--current-server-or-lose)) | 3451 | (cl-defun eglot--flymake-pull (&aux (server (eglot--current-server-or-lose)) |
| 3448 | (origin (current-buffer))) | 3452 | (origin (current-buffer))) |
| @@ -3506,6 +3510,17 @@ MODE is like `eglot--flymake-report-1'." | |||
| 3506 | (pushed-outdated-p (and pushed-docver (< pushed-docver eglot--docver)))) | 3510 | (pushed-outdated-p (and pushed-docver (< pushed-docver eglot--docver)))) |
| 3507 | "Push previously collected diagnostics to `eglot--flymake-report-fn'. | 3511 | "Push previously collected diagnostics to `eglot--flymake-report-fn'. |
| 3508 | If KEEP, knowingly push a dummy do-nothing update." | 3512 | If KEEP, knowingly push a dummy do-nothing update." |
| 3513 | ;; Maybe hack in diagnostics we previously may have saved in | ||
| 3514 | ;; `flymake-list-only-diagnostics', pushed for this file before it was | ||
| 3515 | ;; visited (github#1531). | ||
| 3516 | (when-let* ((hack (and (<= eglot--docver 0) | ||
| 3517 | (null eglot--pushed-diagnostics) | ||
| 3518 | (cdr (assoc (buffer-file-name) | ||
| 3519 | flymake-list-only-diagnostics))))) | ||
| 3520 | (cl-loop | ||
| 3521 | for x in hack | ||
| 3522 | collect (alist-get 'eglot-lsp-diag (flymake-diagnostic-data x)) into res | ||
| 3523 | finally (setq eglot--pushed-diagnostics `(,(vconcat res) ,eglot--docver)))) | ||
| 3509 | (eglot--widening | 3524 | (eglot--widening |
| 3510 | (if (and (null eglot--pulled-diagnostics) pushed-outdated-p) | 3525 | (if (and (null eglot--pulled-diagnostics) pushed-outdated-p) |
| 3511 | ;; Here, we don't have anything interesting to give to Flymake. | 3526 | ;; Here, we don't have anything interesting to give to Flymake. |