Subject: bug#78489: 30.1.50; Using etags, Ada and xref-find-definitions doesn't find definitions

From: Troy Brown <[email-masked]>
Date: Sun, 22 Jun 2025 18:35:02 -0400

On Sat, Jun 7, 2025 at 5:27 AM Eli Zaretskii <[email-masked]> wrote:
>
> > From: Stefan Monnier <[email-masked]>
> > Cc: [email-masked],  [email-masked]
> > Date: Sun, 01 Jun 2025 18:19:31 -0400
> >
> > > Seems to do the job, thanks.  Maybe Troy could try this for a while
> > > and report back.
> >
> > Yes, I'd like to hear confirmation that it fixes the concrete case that
> > Troy was interested in.
>
> Troy, please try the patch and tell us if it fixes the problem.

While I think using an exit-function technically solves the problem of
preventing the suffix from being added into the buffer, I don't think
it is the ideal solution and is likely to lead to confusion.
Furthermore, it doesn't address friction elsewhere.  Stefan's comments
in the patch hint at using a modified completion table and
annotation-function instead of using an exit-function, which I agree
is the better solution.

One nice thing about displaying the tag suffix as an annotation,
rather than leaving it as part of the candidate in the completion
table, is that there is a separate `completions-annotation` face used.
Thus, when it's displayed in the *Completions* buffer, it is
de-emphasised (at least with the Emacs default face configuration
where it's shadowed and italicized) from the actual candidate text.
Keeping it as part of the candidate makes it truly appear that it is
part of the candidate itself, rather than annotation.

Furthermore, only using an exit-function is likely to lead to
confusion for functionality outside of the "*Completions*" buffer.
Consider `completion-preview-mode`.  When a preview is overlaid on the
buffer, and only an exit-function is used, the tag suffix is also
displayed as part of this overlay.  Again this adds to the confusion
making the user think it is part of the completion, rather than
something which will be removed upon insertion.  This doesn't even
consider third party UIs, such as `company-mode`, `corfu-mode`, etc.
but I see this behavior being confusing there as well.

Something which I think that should be noted is that legacy ada-mode
used `gnatfind` and `gnatxref` for completion and cross-referencing,
but those tools were deprecated and finally removed in GCC 12...I
suspect due to the rise of LSP and the Ada Language Server.
Therefore, I think it's likely that people have not been relying on
Ada etags support in Emacs for a very long time.  This is further
evidenced by the fact that the etags `completion-at-point` support has
been broken for Ada tags for a long time and only now is being
discovered.  As a result, it's my belief that trying to preserve the
display of the Ada tag suffix as part of the completion process is
likely to hinder comprehension rather than add any amount of clarity.

The tag suffix could be considered an implementation detail of TAGS,
which I think is only useful for xref, to help jump to the desired
location.  I don't think it is helpful for completion, other than to
add embellishments to the UI (via annotation-function, company-kind,
etc).

For the above reasons, this is why I decided not to use the
exit-function in the example I previously provided, and instead used a
combination of modifying the completion table as well as the addition
of the annotation-function.  Furthermore, those unfamiliar with the
Ada etags suffix are likely to still be confused even if it were to be
turned into an annotation (since they likely haven't read the portion
of the Emacs manual describing those suffixes).  This is also why I
decided not to use the original suffix text in my example with an
annotation function and instead made the annotation more descriptive.

I believe to properly fix this, the suffix needs to be separated from
the candidate text (via a modified completion table).  I don't think
it's necessary to add an annotation-function to restore the suffix,
but I think the suffix information should at least be preserved
non-visually (e.g., text property on the candidate) so it's available
for use by annotation-function, company-kind, etc.