emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: a property "definition-type" would help find macro-defined tests


From: Stephen Gildea
Subject: Re: a property "definition-type" would help find macro-defined tests
Date: Thu, 09 Jan 2025 20:47:28 -0800

I have made the changes requested and one other:

 - added a NEWS entry

 - find-function-search-for-symbol doc string additions
   trimmed of detail that is available from the manual.

 - in the manual, added an index entry for the new property,
   definition-type, and for all the existing properties that
   did not have index entries (which was most of them).

 - in the code example, put each top-level form in @group.

 - new in this version of the patch: added a cross reference
   from where Coding Conventions discusses how to write macros
   that define functions.


diff --git a/etc/NEWS b/etc/NEWS
index 37e5669b139..50928cd9264 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1137,6 +1137,13 @@ It offers a more concise way to create a completion 
table with metadata.
 +++
 ** 'all-completions' and 'unintern' no longer support old calling conventions.
 
++++
+** New property 'definition-type' used by find-function and friends.
+Macros that define an object in a way 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.
+
 
 * Changes in Emacs 31.1 on Non-Free Operating Systems
 
diff --git a/lisp/emacs-lisp/find-func.el b/lisp/emacs-lisp/find-func.el
index 0837b37023e..643b6aba2a6 100644
--- a/lisp/emacs-lisp/find-func.el
+++ b/lisp/emacs-lisp/find-func.el
@@ -400,9 +400,12 @@ find-function-search-for-symbol
 Visit the library in a buffer, and return a cons cell (BUFFER . POSITION),
 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,
-and it is interpreted via `find-function-regexp-alist'.
+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'.
+
 The search is done in the source for library LIBRARY."
   (if (null library)
       (error "Don't know where `%s' is defined" symbol))
@@ -410,6 +413,8 @@ find-function-search-for-symbol
   ;; that defines something else.
   (while (and (symbolp symbol) (get symbol 'definition-name))
     (setq symbol (get symbol 'definition-name)))
+  (setq type (or (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)
diff --git a/doc/lispref/symbols.texi b/doc/lispref/symbols.texi
index 24b4e892024..7990e2a8f75 100644
--- a/doc/lispref/symbols.texi
+++ b/doc/lispref/symbols.texi
@@ -510,35 +510,54 @@ Standard Properties
 
 @table @code
 @item :advertised-binding
+@cindex @code{:advertised-binding} property
 This property value specifies the preferred key binding, when showing
 documentation, for the named function.  @xref{Keys in Documentation}.
 
 @item char-table-extra-slots
+@cindex @code{char-table-extra-slots} property
 The value, if non-@code{nil}, specifies the number of extra slots in
 the named char-table type.  @xref{Char-Tables}.
 
 @item customized-face
+@cindex @code{customized-face} property
 @itemx face-defface-spec
+@cindex @code{face-defface-spec} property
 @itemx saved-face
+@cindex @code{saved-face} property
 @itemx theme-face
+@cindex @code{theme-face} property
 These properties are used to record a face's standard, saved,
 customized, and themed face specs.  Do not set them directly; they are
 managed by @code{defface} and related functions.  @xref{Defining
 Faces}.
 
 @item customized-value
+@cindex @code{customized-value} property
 @itemx saved-value
+@cindex @code{saved-value} property
 @itemx standard-value
+@cindex @code{standard-value} property
 @itemx theme-value
+@cindex @code{theme-value} property
 These properties are used to record a customizable variable's standard
 value, saved value, customized-but-unsaved value, and themed values.
 Do not set them directly; they are managed by @code{defcustom} and
 related functions.  @xref{Variable Definitions}.
 
 @item definition-name
-This property is used to 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.  For example, a @code{define-derived-mode}
+@cindex @code{definition-name} property
+@itemx definition-type
+@cindex @code{definition-type} property
+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.
+The Emacs Help commands such as @kbd{C-h f} (@pxref{Help,,,
+emacs, The GNU Emacs Manual}) use these properties to show the definition
+of a symbol via a button in the @file{*Help*} buffer where the
+symbol's documentation is shown.
+
+For example, a @code{define-derived-mode}
 (@pxref{Derived Modes}) might define a mode-specific function or a
 variable implicitly; or your Lisp program might generate a run-time
 call to @code{defun} to define a function (@pxref{Defining
@@ -547,43 +566,101 @@ Standard Properties
 be found by textual search and whose code defines the original symbol.
 In the example with @code{define-derived-mode}, the value of this
 property of the functions and variables it defines should be the mode
-symbol.  The Emacs Help commands such as @kbd{C-h f} (@pxref{Help,,,
-emacs, The GNU Emacs Manual}) use this property to show the definition
-of a symbol via a button in the @file{*Help*} buffer where the
-symbol's documentation is shown.
+symbol.
+
+In some cases, the definition cannot be found by looking for the
+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}
+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:
+
+@example
+@group
+(defmacro define-foo-test (data)
+  "Define a test of the foo system using DATA."
+  (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 " ...)
+        ...))))
+@end group
+@end example
+
+@example
+@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
+@end example
+
+@example
+@group
+(with-eval-after-load "find-func"
+  (add-to-list
+   'find-function-regexp-alist
+   '(foo-test-type . foo-find-test-def-function)))
+@end group
+@end example
 
 @item disabled
+@cindex @code{disabled} property
 If the value is non-@code{nil}, the named function is disabled as a
 command.  @xref{Disabling Commands}.
 
 @item face-documentation
+@cindex @code{face-documentation} property
 The value stores the documentation string of the named face.  This is
 set automatically by @code{defface}.  @xref{Defining Faces}.
 
 @item history-length
+@cindex @code{history-length} property
 The value, if non-@code{nil}, specifies the maximum minibuffer history
 length for the named history list variable.  @xref{Minibuffer
 History}.
 
 @item interactive-form
+@cindex @code{interactive-form} property
 The value is an interactive form for the named function.  Normally,
 you should not set this directly; use the @code{interactive} special
 form instead.  @xref{Interactive Call}.
 
 @item menu-enable
+@cindex @code{menu-enable} property
 The value is an expression for determining whether the named menu item
 should be enabled in menus.  @xref{Simple Menu Items}.
 
 @item mode-class
+@cindex @code{mode-class} property
 If the value is @code{special}, the named major mode is special.
 @xref{Major Mode Conventions}.
 
 @item permanent-local
+@cindex @code{permanent-local} property
 If the value is non-@code{nil}, the named variable is a buffer-local
 variable whose value should not be reset when changing major modes.
 @xref{Creating Buffer-Local}.
 
 @item permanent-local-hook
+@cindex @code{permanent-local-hook} property
 If the value is non-@code{nil}, the named function should not be
 deleted from the local value of a hook variable when changing major
 modes.  @xref{Setting Hooks}.
@@ -597,18 +674,22 @@ Standard Properties
 Storage}).
 
 @item risky-local-variable
+@cindex @code{risky-local-variable} property
 If the value is non-@code{nil}, the named variable is considered risky
 as a file-local variable.  @xref{File Local Variables}.
 
 @item safe-function
+@cindex @code{safe-function} property
 If the value is non-@code{nil}, the named function is considered
 generally safe for evaluation.  @xref{Function Safety}.
 
 @item safe-local-eval-function
+@cindex @code{safe-local-eval-function} property
 If the value is non-@code{nil}, the named function is safe to call in
 file-local evaluation forms.  @xref{File Local Variables}.
 
 @item safe-local-variable
+@cindex @code{safe-local-variable} property
 The value specifies a function for determining safe file-local values
 for the named variable.  @xref{File Local Variables}.  Since this
 value is consulted when loading files, the function should be
@@ -631,11 +712,13 @@ Standard Properties
 useful for functions where doing so is likely to be a mistake.
 
 @item undo-inhibit-region
+@cindex @code{undo-inhibit-region} property
 If non-@code{nil}, the named function prevents the @code{undo} operation
 from being restricted to the active region, if @code{undo} is invoked
 immediately after the function.  @xref{Undo}.
 
 @item variable-documentation
+@cindex @code{variable-documentation} property
 If non-@code{nil}, this specifies the named variable's documentation
 string.  This is set automatically by @code{defvar} and related
 functions.  @xref{Defining Faces}.
diff --git a/doc/lispref/functions.texi b/doc/lispref/functions.texi
index c659ecaf3f8..8e183e7382b 100644
--- a/doc/lispref/functions.texi
+++ b/doc/lispref/functions.texi
@@ -752,9 +752,9 @@ Defining Functions
 buffer a button to jump to the function's definition, might be unable
 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 which
+@code{defun}.  You can make the job of finding the code that
 generates such functions easier by using the @code{definition-name}
-property, @pxref{Standard Properties}.
+or @code{definition-type} property, @pxref{Standard Properties}.
 
 @cindex override existing functions
 @cindex redefine existing functions
diff --git a/doc/lispref/tips.texi b/doc/lispref/tips.texi
index d48921a0bf8..ea2850cd2f5 100644
--- a/doc/lispref/tips.texi
+++ b/doc/lispref/tips.texi
@@ -226,6 +226,10 @@ Coding Conventions
 defined as the first argument.  That will help various tools find the
 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} (@pxref{Standard
+Properties}) on the name.
 
 @item
 In some other systems there is a convention of choosing variable names
diff --git a/doc/misc/ert.texi b/doc/misc/ert.texi
index 9e60647f3ba..c8aac971ec7 100644
--- a/doc/misc/ert.texi
+++ b/doc/misc/ert.texi
@@ -518,9 +518,14 @@ How to Write Tests
 with @code{eval-defun} or @code{compile-defun}, or you can save the
 file and load it, optionally byte-compiling it first.
 
-Just like @code{find-function} is only able to find where a function
-was defined if the function was loaded from a file, ERT is only able
-to find where a test was defined if the test was loaded from a file.
+Just like @code{find-function} is able to find where a function was
+defined only if the function was loaded from a file, ERT is able to
+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.
+@xref{Standard Properties,,,elisp, GNU Emacs Lisp Reference Manual}.
 
 
 @menu

reply via email to

[Prev in Thread] Current Thread [Next in Thread]