Subject: Re: bug#50244: 28.0.50; Support project-wide diagnostics reports in flymake.el

From: João Távora <[email-masked]>
Date: Tue, 14 Sep 2021 12:34:42 +0100

Hi Theodor,

I've now pushed this to master, so I'm marking the bug done.  But we
can keep discussing the Eglot patch here (or in another bug, or in
Eglot's tracker, as you prefer...)

Theodor Thornhill <[email-masked]> writes:

>>Thanks.  I think I'll try rust-analyzer as I've been meaning to anyway.
>>Perhaps make it the default Rust server for Eglot.
> Absolutely, the community seems to have moved on.

Actually I did still try with `rls` since that was most handy and it
also provides diagnostics for other files on startup.  So I tested it
with rls and got decent results (see Eglot patch).

> By the way- these list only diagnostics do in fact happen on each
> keystroke in the mentioned servers.  Not just on the first load.
> Would this mean the foreign variant is more correct to use?

Yes, it would, indeed.  I don't know if _every_ server operates like
that, though.  But doesn't matter.  Are you saying that in your server,
making a modification to any file always brings in diagnostics for all
other files, too?

Anyway, I've tested a bit with Eglot and flymake-list-only-diagnostics
and it seems to do the right thing (mostly).  I attach the Eglot patch
which you can use as starting point.

diff --git a/eglot.el b/eglot.el
index 7ebc422..d036a75 100644
--- a/eglot.el
+++ b/eglot.el
@@ -1386,6 +1386,11 @@ Doubles as an indicator of snippet support."
       (font-lock-ensure)
       (string-trim (filter-buffer-substring (point-min) (point-max))))))
 
+(defun eglot--diag-type (severity)
+  (cond ((<= severity 1) 'eglot-error)
+        ((= severity 2)  'eglot-warning)
+        (t               'eglot-note)))
+
 (define-obsolete-variable-alias 'eglot-ignored-server-capabilites
   'eglot-ignored-server-capabilities "1.8")
 
@@ -1788,8 +1793,7 @@ COMMAND is a symbol naming the command."
                      diag-spec
                    (setq message (concat source ": " message))
                    (pcase-let
-                       ((sev severity)
-                        (`(,beg . ,end) (eglot--range-region range)))
+                       ((`(,beg . ,end) (eglot--range-region range)))
                      ;; Fallback to `flymake-diag-region' if server
                      ;; botched the range
                      (when (= beg end)
@@ -1808,16 +1812,26 @@ COMMAND is a symbol naming the command."
                                 (point-at-eol
                                  (1+ (plist-get (plist-get range :end) :line)))))))
                      (eglot--make-diag (current-buffer) beg end
-                                       (cond ((<= sev 1) 'eglot-error)
-                                             ((= sev 2)  'eglot-warning)
-                                             (t          'eglot-note))
+                                       (eglot--diag-type severity)
                                        message `((eglot-lsp-diag . ,diag-spec)))))
          into diags
          finally (cond (eglot--current-flymake-report-fn
                         (eglot--report-to-flymake diags))
                        (t
                         (setq eglot--unreported-diagnostics (cons t diags))))))
-    (jsonrpc--debug server "Diagnostics received for unvisited %s" uri)))
+    (cl-loop
+     with path = (expand-file-name (eglot--uri-to-path uri))
+     for diag-spec across diagnostics
+     collect (eglot--dbind ((Diagnostic) message severity source) diag-spec
+               (setq message (concat source ": " message))
+               (eglot--make-diag path (cons 1 1) nil ; cons 1 1 bcs lazy...
+                                 (eglot--diag-type severity)
+                                 message))
+     into diags
+     finally
+     (setq flymake-list-only-diagnostics
+           (assoc-delete-all path flymake-list-only-diagnostics #'string=))
+     (push (cons path diags) flymake-list-only-diagnostics))))
 
 (cl-defun eglot--register-unregister (server things how)
   "Helper for `registerCapability'.