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

From: Theodor Thornhill <[email-masked]>
Date: Tue, 14 Sep 2021 14:22:42 +0200

On 14 September 2021 13:34:42 CEST, "João Távora" <[email-masked]> wrote:
>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...)
>

Great.

>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?
>

Yeah. For any edit in any file, _all_ diagnostics for everything gets re-sent.  I've made the assumption earlier that everything is to be flushed every time. 

>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.
>

Thank you! I'll follow up on this tonight if time permits :)

>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'.
>
>
>