Subject: Re: bug#69462: 29.2.50; describe-function should support finding references

From: Dmitry Gutov <[email-masked]>
Date: Sat, 28 Sep 2024 02:01:30 +0300

Hi!

On 28/02/2024 19:31, Spencer Baugh wrote:
> 
> In emacs-lisp-mode in an Emacs git checkout, M-? (xref-find-references)
> nicely searches the load path for references to a symbol.
> 
> It would be neat if this feature could be accessed from
> describe-function and describe-variable as well, perhaps by just hitting
> M-? in the help buffer.
> 
> The feature may need to be redesigned somewhat, since it's currently
> dependent on being run from a project; to use it from a
> describe-function help buffer, we'd want to only search the load-path.

Reusing the Elisp backend seems the easiest approach.

Caveats:

* You need to press RET after M-? like anywhere else (unless 
xref-prompt-for-identifier is customized).
* A bit hackish change in 'xref-backend-definitions'.

Pros:

* Both M-? and M-. work on anything that looks like symbol in the help 
buffer, quoted or not - though there will be false positives like usual.
* Can be similarly added to cl-describe-type.

diff --git a/lisp/help-fns.el b/lisp/help-fns.el
index e1daa8977f0..ac424a9d028 100644
--- a/lisp/help-fns.el
+++ b/lisp/help-fns.el
@@ -262,6 +262,11 @@ help-fns--describe-function-or-command-prompt
                   fn))
     (list fn)))
 
+(defun help-fns--setup-xref-backend ()
+  (add-hook 'xref-backend-functions #'elisp--xref-backend nil t)
+  (setq-local project-vc-external-roots-function #'elisp-load-path-roots)
+  (setq-local semantic-symref-filepattern-alist '((help-mode "*.el"))))
+
 ;;;###autoload
 (defun describe-function (function)
   "Display the full documentation of FUNCTION (a symbol).
@@ -287,6 +292,7 @@ describe-function
 
     (save-excursion
       (with-help-window (help-buffer)
+        (help-fns--setup-xref-backend)
         (if (get function 'reader-construct)
             (princ function)
           (prin1 function))
@@ -1348,6 +1354,8 @@ describe-variable
 	      (prin1 variable)
 	      (setq file-name (find-lisp-object-file-name variable 'defvar))
 
+              (help-fns--setup-xref-backend)
+
 	      (princ (if file-name
 		         (progn
 		           (princ (format-message
diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el
index 63bd685af91..2f931daedc7 100644
--- a/lisp/progmodes/elisp-mode.el
+++ b/lisp/progmodes/elisp-mode.el
@@ -1049,7 +1049,9 @@ xref-backend-definitions
   (let ((sym (intern-soft identifier)))
     (when sym
       (let* ((pos (get-text-property 0 'pos identifier))
-             (namespace (if pos
+             (namespace (if (and pos
+                                 ;; Reusing it in Help Mode.
+                                 (derived-mode-p 'emacs-lisp-mode))
                             (elisp--xref-infer-namespace pos)
                           'any))
              (defs (elisp--xref-find-definitions sym)))