Subject: Re: bug#78459: flymake related locations (ancillary diagnostics)

From: Spencer Baugh <[email-masked]>
Date: Tue, 20 May 2025 14:56:14 -0400

Mattias Engdegård <[email-masked]> writes:
> Flymake does not seem to have a way to attach related locations to a
> diagnostic. These are 'info' or 'note'-level messages that follow an
> error or warning and point out locations of interest, such as
> definitions or conflicting code. Current, they become independent
> diagnostics with no connection to the main message.
>
> This is unfortunate, because:
>
> * As interfaces typically sort diagnostics by location, these messages often become detached from their context. The text is usually not meant to be read in isolation, only as part of a single warning or error. Example:
>
> myprog.q:98: error: variable 'zurk' is assigned an integer here
> myprog.q:12: note: declared with type string here
>
> When messages are sorted these come in the wrong order, possibly separated with several unrelated messages in-between.
>
> * Since these info-messages make little sense on their own, it might
> be useful to hide them (from the table of diagnostics and in-code
> annotations) until the user selects their parent warning or
> error. That also cuts down on colliding squiggly underlines or
> whatever is used to mark locations in the code buffer.

Yes, I agree that this is an important issue and that this should be
fixed.

> * The LSP protocol has explicit provisions for ancillary messages ('relatedInformation') but Flymake cannot make use of it without some additional hacks.

As do many other flymake backends.  I believe gcc for example can
generate errors which indicate multiple locations, e.g. when there's a
mismatch in type between two declaration sites.  (And, of relevance to
my site, the Dune build system has support for emitting "additional
error locations" associated with a diagnostic, but currently flymake
cannot use this.)

BTW, another feature this would enable is cycling between the locations
associated with a given error.  When an error is due to a mismatch
between two declarations, e.g., an auxiliary location might be in
another file and it might be useful to be able to jump to that location
and jump back.

> There are various ways to fix this. For example:
>
> A. Keep a list of auxiliary diagnostics in the diagnostic object. This seems easiest to work with and what I would suggest. It also corresponds directly to LSP, if I understand it right.
>
> B. Tag all diagnostics that belong together in a group. This is what Flycheck does and would make interoperability easier, but doesn't say which diagnostic is the main one and in what order the auxiliary diagnostics should come.

I also much prefer A.

Maybe the easiest thing to do would be to create individual diagnostic
objects for each auxiliary diagnostic, and have a backend report all of
them as individual diagnostics just as it would today - but to
additionally have a list in the "primary" diagnostic which has a
reference to each "auxiliary" diagnostic.  Then the flymake UI could
decide how to render these.  That's just my initial thought though.

Adding Joao to Cc, since he may have comments about how Eglot could make
use of this, and if there's any issues we're overlooking.