Improve "find definition" in *Help* buffers
* lisp/emacs-lisp/find-func.el (find-function-search-for-symbol): If our regexp algorithm could not find a location for the symbol definition, resort to find-function--search-by-expanding-macros. * test/lisp/emacs-lisp/find-func-tests.el: Add a automatic test for a function and variable generated by a macro. * etc/NEWS: Advertise the improved functionality (bug#45443).
This commit is contained in:
parent
0f790464d5
commit
80420faf49
3 changed files with 80 additions and 1 deletions
6
etc/NEWS
6
etc/NEWS
|
@ -114,6 +114,12 @@ choosing a group, or clicking a button in the "*Help*" buffers when
|
|||
looking at the doc string of a function that belongs to one of these
|
||||
groups.
|
||||
|
||||
---
|
||||
** Improved "find definition" feature of *Help* buffers.
|
||||
Now clicking on the link to find the definition of functions generated
|
||||
by 'cl-defstruct', or variables generated by 'define-derived-mode',
|
||||
for example, will go to the exact place where they are defined.
|
||||
|
||||
** New variable 'redisplay-skip-initial-frame' to enable batch redisplay tests.
|
||||
Setting it to nil forces the redisplay to do its job even in the
|
||||
initial frame used in batch mode.
|
||||
|
|
|
@ -389,7 +389,70 @@ The search is done in the source for library LIBRARY."
|
|||
(progn
|
||||
(beginning-of-line)
|
||||
(cons (current-buffer) (point)))
|
||||
(cons (current-buffer) nil)))))))))
|
||||
;; If the regexp search didn't find the location of
|
||||
;; the symbol (for example, because it is generated by
|
||||
;; a macro), try a slightly more expensive search that
|
||||
;; expands macros until it finds the symbol.
|
||||
(cons (current-buffer)
|
||||
(find-function--search-by-expanding-macros
|
||||
(current-buffer) symbol type))))))))))
|
||||
|
||||
(defun find-function--try-macroexpand (form)
|
||||
"Try to macroexpand FORM in full or partially.
|
||||
This is a best-effort operation in which if macroexpansion fails,
|
||||
this function returns FORM as is."
|
||||
(ignore-errors
|
||||
(or
|
||||
(macroexpand-all form)
|
||||
(macroexpand-1 form)
|
||||
form)))
|
||||
|
||||
(defun find-function--any-subform-p (form pred)
|
||||
"Walk FORM and apply PRED to its subexpressions.
|
||||
Return t if any PRED returns t."
|
||||
(cond
|
||||
((not (consp form)) nil)
|
||||
((funcall pred form) t)
|
||||
(t
|
||||
(cl-destructuring-bind (left-child . right-child) form
|
||||
(or
|
||||
(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)
|
||||
"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)
|
||||
;; Check if a given form is a `defalias' to
|
||||
;; SYM, the function name we are searching
|
||||
;; for. All functions in Emacs Lisp
|
||||
;; ultimately expand to a `defalias' form
|
||||
;; after several steps of macroexpansion.
|
||||
(and (eq (car-safe form) 'defalias)
|
||||
(equal (car-safe (cdr form))
|
||||
`(quote ,symbol))))
|
||||
((eq type 'defvar)
|
||||
;; Variables generated by macros ultimately
|
||||
;; expand to `defvar'.
|
||||
(and (eq (car-safe form) 'defvar)
|
||||
(eq (car-safe (cdr form)) symbol)))
|
||||
(t nil)))))
|
||||
(when (find-function--any-subform-p
|
||||
(find-function--try-macroexpand form)
|
||||
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))))))
|
||||
|
||||
(defun find-function-library (function &optional lisp-only verbose)
|
||||
"Return the pair (ORIG-FUNCTION . LIBRARY) for FUNCTION.
|
||||
|
|
|
@ -43,5 +43,15 @@
|
|||
(concat data-directory (kbd "n x / TAB RET"))
|
||||
(read-library-name)))))
|
||||
|
||||
;; Avoid a byte-compilation warning that may confuse people reading
|
||||
;; the result of the following test.
|
||||
(declare-function compilation--message->loc nil "compile")
|
||||
|
||||
(ert-deftest find-func-tests--locate-macro-generated-symbols () ;bug#45443
|
||||
(should (cdr (find-function-search-for-symbol
|
||||
#'compilation--message->loc nil "compile")))
|
||||
(should (cdr (find-function-search-for-symbol
|
||||
'c-mode-hook 'defvar "cc-mode"))))
|
||||
|
||||
(provide 'find-func-tests)
|
||||
;;; find-func-tests.el ends here
|
||||
|
|
Loading…
Add table
Reference in a new issue