Property definition-type becomes find-function-type-alist

lisp/emacs-lisp/find-func.el (find-function-search-for-symbol): Use
symbol property 'find-function-type-alist' instead of 'definition-type'
(find-function-update-type-alist): New convenience function.
* doc/lispref/symbols.texi (Standard Properties): Update example to use
'find-function-type-alist' and 'find-function-update-type-alist'
* doc/lispref/functions.texi (Defining Functions):
* doc/lispref/tips.texi (Coding Conventions):
* doc/misc/ert.texi (How to Write Tests):
* etc/NEWS: Change reference to 'definition-type' to name
'find-function-type-alist' instead
This commit is contained in:
Stephen Gildea 2025-01-16 15:33:12 -08:00
parent dace7fa2ab
commit 863fd1c276
6 changed files with 48 additions and 41 deletions

View file

@ -754,7 +754,7 @@ to find the source code because generating a function dynamically
usually looks very different from the usual static calls to
@code{defun}. You can make the job of finding the code that
generates such functions easier by using the @code{definition-name}
or @code{definition-type} property, @pxref{Standard Properties}.
or @code{find-function-type-alist} property, @pxref{Standard Properties}.
@cindex override existing functions
@cindex redefine existing functions

View file

@ -536,9 +536,9 @@ Do not set them directly; they are managed by @code{defcustom} and
related functions. @xref{Variable Definitions}.
@cindex @code{definition-name} (symbol property)
@cindex @code{definition-type} (symbol property)
@cindex @code{find-function-type-alist} (symbol property)
@item definition-name
@itemx definition-type
@itemx find-function-type-alist
These properties help find the definition of a symbol in the source
code when it might be hard to find the definition by textual search
of the source file.
@ -563,16 +563,19 @@ definition of another symbol. For example, a test file might use a
macro to generate calls to @code{ert-deftest}
(@pxref{,,,ert, ERT: Emacs Lisp Regression Testing}) where the code
is boiler plate and only varying data need to be passed in.
In such cases, the @code{definition-type} property of the symbol can
be a symbol that has an entry in @code{find-function-regexp-alist}
In such cases, the @code{find-function-type-alist} property of the
symbol can be an alist that augments @code{find-function-regexp-alist}
telling how to find the definition of symbols of this type.
In the example of a macro defining calls to @code{ert-deftest},
the macro could put the property @code{definition-type} on each
test defined. The file defining the macro would also define a
definition-finding function or regexp and add it to
@code{find-function-regexp-alist} after that variable is loaded.
Here is an example using a function to find the definition:
the macro could put the property @code{find-function-type-alist} on each
test defined, associating @code{ert--test} (the internal type of ERT
tests) with the name of a regexp or function that can find the correct
macro call. The file defining the macro would also have to provide that
definition-finding function or regexp.
Here is an example using a function to find the definition.
The example updates the property using convenience function
@code{find-function-update-type-alist}.
@example
@group
@ -581,29 +584,19 @@ Here is an example using a function to find the definition:
(declare (debug (&rest sexp)))
(let ((test-name (intern (concat ...))))
`(progn
(put ',test-name 'definition-type 'foo-test-type)
(ert-deftest ,test-name ()
,(concat "Test foo with " ...)
...))))
(find-function-update-type-alist
',test-name 'ert--test 'foo-find-test-def-function)
(ert-deftest ,test-name ()
,(concat "Test foo with " ...)
...))))
@end group
@group
(defun foo-find-test-def-function (test-name)
"Search for the `define-foo-test' call defining TEST-NAME.
Return non-nil if the definition is found."
(save-match-data
(let ((regexp ...))
(save-restriction
(widen)
(goto-char (point-min))
(re-search-forward regexp nil t)))))
@end group
@group
(with-eval-after-load "find-func"
(add-to-list
'find-function-regexp-alist
'(foo-test-type . foo-find-test-def-function)))
(let ((regexp ...))
(re-search-forward regexp nil t)))
@end group
@end example

View file

@ -228,7 +228,7 @@ definition automatically. Avoid constructing the names in the macro
itself, since that would confuse these tools.
If your macro cannot be written in this style, the macro can still
help these tools find the defining call by putting the property
@code{definition-name} or @code{definition-type} on the name.
@code{definition-name} or @code{find-function-type-alist} on the name.
@xref{Standard Properties}.
@item

View file

@ -524,7 +524,7 @@ find where a test was defined only if the test was loaded from a file.
If the test definition is generated by a macro, the macro may want to
help ERT find the defining call to the macro by putting the property
@code{definition-type} on the test name.
@code{find-function-type-alist} on the test name.
@xref{Standard Properties,,,elisp, GNU Emacs Lisp Reference Manual}.

View file

@ -1175,11 +1175,14 @@ It offers a more concise way to create a completion table with metadata.
** 'all-completions' and 'unintern' no longer support old calling conventions.
+++
** New symbol property 'definition-type' used by 'find-function' and friends.
** New symbol property 'find-function-type-alist' used by 'find-function' etc.
Macros that define an object in a way that makes the object's name and
the macro call site defining the object hard to associate can put the
property 'definition-type' on the object's name to provide instructions
for finding the definition.
the macro call site defining the object hard to associate can add an
entry to the property 'find-function-type-alist' on the object's name to
provide instructions for finding the definition.
New convenience function 'find-function-update-type-alist' offers a
concise way to update a symbol's 'find-function-type-alist' property.
* Changes in Emacs 31.1 on Non-Free Operating Systems

View file

@ -152,7 +152,11 @@ Each regexp variable's value should actually be a format string
to be used to substitute the desired symbol name into the regexp.
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.")
we're looking for) and it should search for it.
Symbols can have their own version of this alist on
the property `find-function-type-alist'.
See the function `find-function-update-type-alist'.")
(put 'find-function-regexp-alist 'risky-local-variable t)
(define-obsolete-variable-alias 'find-function-source-path
@ -402,9 +406,9 @@ or just (BUFFER . nil) if the definition can't be found in the file.
If TYPE is nil, look for a function definition,
otherwise, TYPE specifies the kind of definition.
If SYMBOL has a property `definition-type',
the property value is used instead of TYPE.
TYPE is interpreted via `find-function-regexp-alist'.
TYPE is looked up in SYMBOL's property `find-function-type-alist'
(which can be maintained with `find-function-update-type-alist')
or the variable `find-function-regexp-alist'.
The search is done in the source for library LIBRARY."
(if (null library)
@ -413,9 +417,6 @@ The search is done in the source for library LIBRARY."
;; that defines something else.
(while (and (symbolp symbol) (get symbol 'definition-name))
(setq symbol (get symbol 'definition-name)))
(setq type (or (and (symbolp symbol)
(get symbol 'definition-type))
type))
(if (string-match "\\`src/\\(.*\\.\\(c\\|m\\)\\)\\'" library)
(find-function-C-source symbol (match-string 1 library) type)
(when (string-match "\\.el\\(c\\)\\'" library)
@ -425,7 +426,10 @@ The search is done in the source for library LIBRARY."
(when (string-match "\\.emacs\\(.el\\)\\'" library)
(setq library (substring library 0 (match-beginning 1))))
(let* ((filename (find-library-name library))
(regexp-symbol (cdr (assq type find-function-regexp-alist))))
(regexp-symbol
(or (and (symbolp symbol)
(alist-get type (get symbol 'find-function-type-alist)))
(alist-get type find-function-regexp-alist))))
(with-current-buffer (find-file-noselect filename)
(let ((regexp (if (functionp regexp-symbol) regexp-symbol
(format (symbol-value regexp-symbol)
@ -467,6 +471,13 @@ The search is done in the source for library LIBRARY."
(find-function--search-by-expanding-macros
(current-buffer) symbol type))))))))))
;;;###autoload
(defun find-function-update-type-alist (symbol type variable)
"Update SYMBOL property `find-function-type-alist' with (TYPE . VARIABLE).
Property `find-function-type-alist' is a symbol-specific version
of variable `find-function-regexp-alist' and has the same format."
(setf (alist-get type (get symbol 'find-function-type-alist)) variable))
(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,