1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2025-12-10 00:00:39 -08:00

Help find-function find methods defined inside macros

* doc/lispref/functions.texi (Finding Definitions): Document the
expanded definition-finding extension mechanism.
* etc/NEWS: Briefly describe the new feature.
* lisp/emacs-lisp/cl-generic.el
(cl--generic-find-defgeneric-regexp): Use defconst now that we
no longer have purespace.
(cl--generic-search-method-make-form-matcher): New function.
* lisp/emacs-lisp/find-func.el (find-function-regexp-alist)
(find-function-search-for-symbol): Parse out the new
factory function.
(find-function--search-by-expanding-macros): Try using it when
searching for definitions by expanding macros.
This commit is contained in:
Daniel Colascione 2025-03-27 16:04:51 -04:00
parent 59fd8c26be
commit 364c3dbc12
4 changed files with 83 additions and 28 deletions

View file

@ -144,6 +144,16 @@ Instead of regexp variable, types can be mapped to functions as well,
in which case the function is called with one argument (the object
we're looking for) and it should search for it.
A value can also be a cons (REGEX . EXPANDED-FORM-MATCHER-FACTORY).
REGEX is as above; EXPANDED-FORM-MATCHER-FACTORY is a function of one
argument, the same as we'd pass to a REGEX function, that returns
another function of one argument that returns true if we're looking at a
macroexpanded form that defines what we're looking for. If you want to
use EXPANDED-FORM-MATCHER-FACTORY exclusively, you can set REGEX to a
never-match regex and force the fallback to
EXPANDED-FORM-MATCHER-FACTORY. The buffer to search is current during
the call to EXPANDED-FORM-MATCHER-FACTORY.
Symbols can have their own version of this alist on
the property `find-function-type-alist'.
See the function `find-function-update-type-alist'.")
@ -434,7 +444,13 @@ The search is done in the source for library LIBRARY."
(regexp-symbol
(or (and (symbolp symbol)
(alist-get type (get symbol 'find-function-type-alist)))
(alist-get type find-function-regexp-alist))))
(alist-get type find-function-regexp-alist)))
(form-matcher-factory
(and (functionp (cdr-safe regexp-symbol))
(cdr regexp-symbol)))
(regexp-symbol (if form-matcher-factory
(car regexp-symbol)
regexp-symbol)))
(with-current-buffer (find-file-noselect filename)
(let ((regexp (if (functionp regexp-symbol) regexp-symbol
(format (symbol-value regexp-symbol)
@ -474,7 +490,8 @@ The search is done in the source for library LIBRARY."
;; expands macros until it finds the symbol.
(cons (current-buffer)
(find-function--search-by-expanding-macros
(current-buffer) symbol type))))))))))
(current-buffer) symbol type
form-matcher-factory))))))))))
;;;###autoload
(defun find-function-update-type-alist (symbol type variable)
@ -506,19 +523,13 @@ Return t if any PRED returns t."
(find-function--any-subform-p left-child pred)
(find-function--any-subform-p right-child pred))))))
(defun find-function--search-by-expanding-macros (buf symbol type)
(defun find-function--search-by-expanding-macros
(buf symbol type matcher-factory)
"Expand macros in BUF to search for the definition of SYMBOL of TYPE."
(catch 'found
(with-current-buffer buf
(save-excursion
(goto-char (point-min))
(condition-case nil
(while t
(let ((form (read (current-buffer)))
(expected-symbol-p
(lambda (form)
(cond
((null type)
(with-current-buffer buf
(when-let* ((expected-symbol-p
(cond ((null type)
(lambda (form)
;; Check if a given form is a `defalias' to
;; SYM, the function name we are searching
;; for. All functions in Emacs Lisp
@ -526,20 +537,28 @@ Return t if any PRED returns t."
;; after several steps of macroexpansion.
(and (eq (car-safe form) 'defalias)
(equal (car-safe (cdr form))
`(quote ,symbol))))
((eq type 'defvar)
`(quote ,symbol)))))
((eq type 'defvar)
(lambda (form)
;; Variables generated by macros ultimately
;; expand to `defvar'.
(and (eq (car-safe form) 'defvar)
(eq (car-safe (cdr form)) symbol)))
(t nil)))))
(eq (car-safe (cdr form)) symbol))))
(matcher-factory
(funcall matcher-factory symbol)))))
(catch 'found
(save-excursion
(goto-char (point-min))
(condition-case nil
(while t
(when (find-function--any-subform-p
(find-function--try-macroexpand form)
(find-function--try-macroexpand
(read (current-buffer)))
expected-symbol-p)
;; We want to return the location at the beginning
;; of the macro, so move back one sexp.
(throw 'found (progn (backward-sexp) (point))))))
(end-of-file nil))))))
(throw 'found (progn (backward-sexp) (point)))))
(end-of-file nil)))))))
(defun find-function-library (function &optional lisp-only verbose)
"Return the pair (ORIG-FUNCTION . LIBRARY) for FUNCTION.