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

From: Eli Zaretskii <[email-masked]>
Date: Thu, 22 May 2025 14:31:22 +0300

> Date: Sun, 18 May 2025 21:37:19 -0400
> From:  Troy Brown via "Bug reports for GNU Emacs,
>  the Swiss army knife of text editors" <[email-masked]>
> 
> For this issue, you can just load the Ada source into Fundamental
> mode.  The problem doesn't appear to be with the major mode, but
> instead with the etags backend for xref not fully supporting the Ada
> tags generated by etags.  The following source file can be used to
> reproduce the problem (named hello_world.adb):
> 
> --8<---------------cut here---------------start------------->8---
> with Ada.Text_IO; use Ada.Text_IO;
> 
> procedure Hello_World is
>    procedure Display_Message is
>    begin
>       Put_Line ("Hello, World!");
>    end Display_Message;
> begin  -- Hello_World
>    Display_Message;
> end Hello_World;
> --8<---------------cut here---------------end--------------->8---
> 
> 1. Generate TAGS: etags *.adb
> 2. emacs -Q hello_world.adb
> 3. Place point over Display_Message on line 9
> 4. M-x xref-find-definitions
> 5. Select TAGS file previously generated
> 6. Message buffer contains "No definitions found for: Display_Message"
> 
> Digging into this, it appears the reason the definition is not found
> is because of the `etags-xref-find-definitions-tag-order`, or more
> specifically, that `tag-exact-match-p` contained in that list does not
> account for the suffix appended by etags for Ada tags.  According to
> the the Emacs manual [(info "(emacs) Tag Syntax")], Ada tags will
> contain a "/b", "/f", "/k", "/p", "/s" or "/t" suffix to distinguish
> the type of tag.  This can be observed by looking at the contents of
> the generated TAGS file.  When invoking `xref-find-definitions`, the
> symbol at point (i.e., "Display_Message" in this example) will not
> exactly match the tag found in the TAGS file (i.e.,
> "Display_Message/p"), thus the observed "No definitions found"
> message.

Thanks for the analysis.  Out of curiosity: do you happen to know the
reasons why Ada tags have these suffixes?  It seems to be Ada-only
feature, so I wonder what's it about?

> I assume this is just an oversight that `xref-find-definitions` does
> not work out of the box with Ada tags.

Yes.

> The older `M-x find-tag` will work as expected, as well as other
> functions which don't expect an exact match (i.e., `M-x
> xref-find-apropos`).  However, It's surprising that
> `xref-find-definitions` does not work out of the box with the output
> that etags generates.

Xref intentionally switched to exact matches, so as to avoid the extra
step for the user to select one of the possible inexact matches.  But
doing that with Ada needs special handling, due to this idiosyncrasy
of Ada tags.

> It's unclear to me how special handling like this should be handled in
> the etags xref backend.

I can propose the patch below instead.  Could you please see if it
solves your problems with Ada tags?

diff --git a/lisp/progmodes/etags.el b/lisp/progmodes/etags.el
index 42057a3..f14d915 100644
--- a/lisp/progmodes/etags.el
+++ b/lisp/progmodes/etags.el
@@ -1649,7 +1649,10 @@ tag-exact-match-p
   (or (and (eq (char-after (point)) ?\001)
 	   (eq (char-after (- (point) (length tag) 1)) ?\177))
       ;; We are not on the explicit tag name, but perhaps it follows.
-      (looking-at (concat "[^\177\n]*\177" (regexp-quote tag) "\001"))))
+      (looking-at (concat "[^\177\n]*\177"
+                          (regexp-quote tag)
+                          ;; The optional "/x" part is for Ada tags.
+                          "\\(/[fpsbtk]\\)?\001"))))
 
 ;; t if point is at a tag line that has an implicit name.
 ;; point should be just after a string that matches TAG.