]> git.eshelyaron.com Git - emacs.git/commitdiff
* lisp/subr.el (define-symbol-prop): New function
authorStefan Monnier <monnier@iro.umontreal.ca>
Fri, 28 Jul 2017 16:02:01 +0000 (12:02 -0400)
committerStefan Monnier <monnier@iro.umontreal.ca>
Fri, 28 Jul 2017 16:02:01 +0000 (12:02 -0400)
(symbol-file): Make it find symbol property definitions.

* lisp/emacs-lisp/pcase.el (pcase-defmacro):
* lisp/emacs-lisp/ert.el (ert-set-test): Use it instead of `put'.
(ert-describe-test): Adjust call to symbol-file accordingly.

etc/NEWS
lisp/emacs-lisp/ert.el
lisp/emacs-lisp/pcase.el
lisp/loadhist.el
lisp/subr.el
test/lisp/emacs-lisp/ert-tests.el

index 2b7c93fda10f656d98f1cd0b8cf7c87212ae1b02..ef4c125ab1651a45f83ad01bc238dc019976b80e 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1175,6 +1175,8 @@ break.
 \f
 * Lisp Changes in Emacs 26.1
 
+** New function `define-symbol-prop'.
+
 +++
 ** New optional argument TESTFN in 'alist-get', 'map-elt' and 'map-put'.
 
index 5186199cfce5c92516734a2ae2c52154803c4adb..d7bd331c11b3ed04e81739dbccb0eb3cde7207f4 100644 (file)
@@ -135,16 +135,9 @@ Emacs bug 6581 at URL `http://debbugs.gnu.org/cgi/bugreport.cgi?bug=6581'."
     ;; Note that nil is still a valid value for the `name' slot in
     ;; ert-test objects.  It designates an anonymous test.
     (error "Attempt to define a test named nil"))
-  (put symbol 'ert--test definition)
-  ;; Register in load-history, so `symbol-file' can find us, and so
-  ;; unload-feature can unload our tests.
-  (cl-pushnew `(ert-deftest . ,symbol) current-load-list :test #'equal)
+  (define-symbol-prop symbol 'ert--test definition)
   definition)
 
-(cl-defmethod loadhist-unload-element ((x (head ert-deftest)))
-  (let ((name (cdr x)))
-    (put name 'ert--test nil)))
-
 (defun ert-make-test-unbound (symbol)
   "Make SYMBOL name no test.  Return SYMBOL."
   (cl-remprop symbol 'ert--test)
@@ -2539,7 +2532,7 @@ To be used in the ERT results buffer."
           (insert (if test-name (format "%S" test-name) "<anonymous test>"))
           (insert " is a test")
           (let ((file-name (and test-name
-                                (symbol-file test-name 'ert-deftest))))
+                                (symbol-file test-name 'ert--test))))
             (when file-name
               (insert (format-message " defined in `%s'"
                                       (file-name-nondirectory file-name)))
index b40161104d21eac97dd917c5a377e8c0945e8fa7..253b60e75348537679bb2c47a17d4442a32413ce 100644 (file)
@@ -418,8 +418,8 @@ to this macro."
     (when decl (setq body (remove decl body)))
     `(progn
        (defun ,fsym ,args ,@body)
-       (put ',fsym 'edebug-form-spec ',(cadr (assq 'debug decl)))
-       (put ',name 'pcase-macroexpander #',fsym))))
+       (define-symbol-prop ',fsym 'edebug-form-spec ',(cadr (assq 'debug decl)))
+       (define-symbol-prop ',name 'pcase-macroexpander #',fsym))))
 
 (defun pcase--match (val upat)
   "Build a MATCH structure, hoisting all `or's and `and's outside."
index b83d023ccf8de22e3928276db0740dd080f06fec..18c30f781f0cfb72a7ad40f29a33daf4f1b8daad 100644 (file)
@@ -221,6 +221,11 @@ restore a previous autoload if possible.")
     ;; Remove the struct.
     (setf (cl--find-class name) nil)))
 
+(cl-defmethod loadhist-unload-element ((x (head define-symbol-props)))
+  (pcase-dolist (`(,symbol . ,props) (cdr x))
+    (dolist (prop props)
+      (put symbol prop nil))))
+
 ;;;###autoload
 (defun unload-feature (feature &optional force)
   "Unload the library that provided FEATURE.
index 90a78cf68a08551b5ffac3b13399f77b283da3cc..b3f9f902349924d7539a6fdbec27bf4e20ade61e 100644 (file)
@@ -1999,6 +1999,25 @@ If TOGGLE has a `:menu-tag', that is used for the menu item's label."
 ;;   "Return the name of the file from which AUTOLOAD will be loaded.
 ;; \n\(fn AUTOLOAD)")
 
+(defun define-symbol-prop (symbol prop val)
+  "Define the property PROP of SYMBOL to be VAL.
+This is to `put' what `defalias' is to `fset'."
+  ;; Can't use `cl-pushnew' here (nor `push' on (cdr foo)).
+  ;; (cl-pushnew symbol (alist-get prop
+  ;;                               (alist-get 'define-symbol-props
+  ;;                                          current-load-list)))
+  (let ((sps (assq 'define-symbol-props current-load-list)))
+    (unless sps
+      (setq sps (list 'define-symbol-props))
+      (push sps current-load-list))
+    (let ((ps (assq prop sps)))
+      (unless ps
+        (setq ps (list prop))
+        (setcdr sps (cons ps (cdr sps))))
+      (unless (member symbol (cdr ps))
+        (setcdr ps (cons symbol (cdr ps))))))
+  (put symbol prop val))
+
 (defun symbol-file (symbol &optional type)
   "Return the name of the file that defined SYMBOL.
 The value is normally an absolute file name.  It can also be nil,
@@ -2008,28 +2027,30 @@ file name without extension.
 
 If TYPE is nil, then any kind of definition is acceptable.  If
 TYPE is `defun', `defvar', or `defface', that specifies function
-definition, variable definition, or face definition only."
+definition, variable definition, or face definition only.
+Otherwise TYPE is assumed to be a symbol property."
   (if (and (or (null type) (eq type 'defun))
           (symbolp symbol)
           (autoloadp (symbol-function symbol)))
       (nth 1 (symbol-function symbol))
-    (let ((files load-history)
-         file match)
-      (while files
-       (if (if type
-               (if (eq type 'defvar)
-                   ;; Variables are present just as their names.
-                   (member symbol (cdr (car files)))
-                 ;; Other types are represented as (TYPE . NAME).
-                 (member (cons type symbol) (cdr (car files))))
-             ;; We accept all types, so look for variable def
-             ;; and then for any other kind.
-             (or (member symbol (cdr (car files)))
-                 (and (setq match (rassq symbol (cdr (car files))))
-                      (not (eq 'require (car match))))))
-           (setq file (car (car files)) files nil))
-       (setq files (cdr files)))
-      file)))
+    (catch 'found
+      (pcase-dolist (`(,file . ,elems) load-history)
+       (when (if type
+                 (if (eq type 'defvar)
+                     ;; Variables are present just as their names.
+                     (member symbol elems)
+                   ;; Many other types are represented as (TYPE . NAME).
+                   (or (member (cons type symbol) elems)
+                        (memq symbol (alist-get type
+                                                (alist-get 'define-symbol-props
+                                                           elems)))))
+               ;; We accept all types, so look for variable def
+               ;; and then for any other kind.
+               (or (member symbol elems)
+                    (let ((match (rassq symbol elems)))
+                     (and match
+                          (not (eq 'require (car match)))))))
+          (throw 'found file))))))
 
 (defun locate-library (library &optional nosuffix path interactive-call)
   "Show the precise file name of Emacs library LIBRARY.
index 317838b250f730d299565ebf04c1d66ee67a0540..57463ad932dac160863d22818ef500073b6abe9d 100644 (file)
@@ -352,7 +352,7 @@ This macro is used to test if macroexpansion in `should' works."
   (let ((abc (ert-get-test 'ert-test-abc)))
     (should (equal (ert-test-tags abc) '(bar)))
     (should (equal (ert-test-documentation abc) "foo")))
-  (should (equal (symbol-file 'ert-test-deftest 'ert-deftest)
+  (should (equal (symbol-file 'ert-test-deftest 'ert--test)
                  (symbol-file 'ert-test--which-file 'defun)))
 
   (ert-deftest ert-test-def () :expected-result ':passed)