aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Monnier2015-01-16 22:52:15 -0500
committerStefan Monnier2015-01-16 22:52:15 -0500
commit24b7f77581c7eefe484db6cbbd661c04460c66aa (patch)
tree59bf6bdfba55d0f5aeb73a755e2420ce19ac7c3a
parenta2cd6d90d20408a6265c8615697dbff94df3f098 (diff)
downloademacs-24b7f77581c7eefe484db6cbbd661c04460c66aa.tar.gz
emacs-24b7f77581c7eefe484db6cbbd661c04460c66aa.zip
Improve handling of doc-strings and describe-function for cl-generic
* lisp/help-fns.el (find-lisp-object-file-name): Accept any `type' as long as it's a symbol. (help-fns-short-filename): New function. (describe-function-1): Use it. Use autoload-do-load. * lisp/help-mode.el (help-function-def): Add optional arg `type'. * lisp/emacs-lisp/cl-generic.el (cl-generic-ensure-function): It's OK to override an autoload. (cl-generic-current-method-specializers): Replace dyn-bind variable with a lexically-scoped macro. (cl--generic-lambda): Update accordingly. (cl-generic-define-method): Record manually in the load-history with type `cl-defmethod'. (cl--generic-get-dispatcher): Minor optimization. (cl--generic-search-method): New function. (find-function-regexp-alist): Add entry for `cl-defmethod' type. (cl--generic-search-method): Add hyperlinks for methods. Merge the specializers and the function's arguments. * lisp/emacs-lisp/eieio-core.el (eieio--defalias): Move to eieio-generic.el. (eieio-defclass-autoload): Don't record the superclasses any more. (eieio-defclass-internal): Reuse the old class object if it was just an autoload stub. (eieio--class-precedence-list): Load the class if it's autoloaded. * lisp/emacs-lisp/eieio-generic.el (eieio--defalias): Move from eieio-core. (eieio--defgeneric-init-form): Don't throw away a previous docstring. (eieio--method-optimize-primary): Don't mess with the docstring. (defgeneric): Keep the `args' in the docstring. (defmethod): Don't use the method's docstring for the generic function's docstring. * lisp/emacs-lisp/find-func.el: Use lexical-binding. (find-function-regexp): Don't rule out `defgeneric'. (find-function-regexp-alist): Document new possibility of including a function instead of a regexp. (find-function-search-for-symbol): Implement that new possibility. (find-function-library): Don't assume that `function' is a symbol. (find-function-do-it): Remove unused var `orig-buf'. * test/automated/cl-generic-tests.el (cl-generic-test-8-after/before): Rename from cl-generic-test-7-after/before. (cl--generic-test-advice): New function. (cl-generic-test-9-advice): New test. * test/automated/eieio-test-methodinvoke.el (eieio-test-cl-generic-1): Reset eieio-test--1.
-rw-r--r--lisp/ChangeLog45
-rw-r--r--lisp/emacs-lisp/cl-generic.el117
-rw-r--r--lisp/emacs-lisp/eieio-core.el89
-rw-r--r--lisp/emacs-lisp/eieio-generic.el51
-rw-r--r--lisp/emacs-lisp/find-func.el68
-rw-r--r--lisp/help-fns.el26
-rw-r--r--lisp/help-mode.el4
-rw-r--r--test/ChangeLog10
-rw-r--r--test/automated/cl-generic-tests.el15
-rw-r--r--test/automated/eieio-test-methodinvoke.el1
10 files changed, 269 insertions, 157 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index f78714b3217..01de483a607 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,48 @@
12015-01-17 Stefan Monnier <monnier@iro.umontreal.ca>
2
3 Improve handling of doc-strings and describe-function for cl-generic.
4
5 * help-mode.el (help-function-def): Add optional arg `type'.
6
7 * help-fns.el (find-lisp-object-file-name): Accept any `type' as long
8 as it's a symbol.
9 (help-fns-short-filename): New function.
10 (describe-function-1): Use it. Use autoload-do-load.
11
12 * emacs-lisp/find-func.el: Use lexical-binding.
13 (find-function-regexp): Don't rule out `defgeneric'.
14 (find-function-regexp-alist): Document new possibility of including
15 a function instead of a regexp.
16 (find-function-search-for-symbol): Implement that new possibility.
17 (find-function-library): Don't assume that `function' is a symbol.
18 (find-function-do-it): Remove unused var `orig-buf'.
19
20 * emacs-lisp/eieio-generic.el (eieio--defalias): Move from eieio-core.
21 (eieio--defgeneric-init-form): Don't throw away a previous docstring.
22 (eieio--method-optimize-primary): Don't mess with the docstring.
23 (defgeneric): Keep the `args' in the docstring.
24 (defmethod): Don't use the method's docstring for the generic
25 function's docstring.
26
27 * emacs-lisp/eieio-core.el (eieio--defalias): Move to eieio-generic.el.
28 (eieio-defclass-autoload): Don't record the superclasses any more.
29 (eieio-defclass-internal): Reuse the old class object if it was just an
30 autoload stub.
31 (eieio--class-precedence-list): Load the class if it's autoloaded.
32
33 * emacs-lisp/cl-generic.el (cl-generic-ensure-function): It's OK to
34 override an autoload.
35 (cl-generic-current-method-specializers): Replace dyn-bind variable
36 with a lexically-scoped macro.
37 (cl--generic-lambda): Update accordingly.
38 (cl-generic-define-method): Record manually in the load-history with
39 type `cl-defmethod'.
40 (cl--generic-get-dispatcher): Minor optimization.
41 (cl--generic-search-method): New function.
42 (find-function-regexp-alist): Add entry for `cl-defmethod' type.
43 (cl--generic-search-method): Add hyperlinks for methods. Merge the
44 specializers and the function's arguments.
45
12015-01-16 Artur Malabarba <bruce.connor.am@gmail.com> 462015-01-16 Artur Malabarba <bruce.connor.am@gmail.com>
2 47
3 * emacs-lisp/package.el (package--read-pkg-desc): New 48 * emacs-lisp/package.el (package--read-pkg-desc): New
diff --git a/lisp/emacs-lisp/cl-generic.el b/lisp/emacs-lisp/cl-generic.el
index 21688bef18a..ae0f129bb23 100644
--- a/lisp/emacs-lisp/cl-generic.el
+++ b/lisp/emacs-lisp/cl-generic.el
@@ -107,6 +107,7 @@ They should be sorted from most specific to least specific.")
107 (symbolp (symbol-function name))) 107 (symbolp (symbol-function name)))
108 (setq name (symbol-function name))) 108 (setq name (symbol-function name)))
109 (unless (or (not (fboundp name)) 109 (unless (or (not (fboundp name))
110 (autoloadp (symbol-function name))
110 (and (functionp name) generic)) 111 (and (functionp name) generic))
111 (error "%s is already defined as something else than a generic function" 112 (error "%s is already defined as something else than a generic function"
112 origname)) 113 origname))
@@ -153,7 +154,7 @@ via (:documentation DOCSTRING)."
153 code)) 154 code))
154 (defalias ',name 155 (defalias ',name
155 (cl-generic-define ',name ',args ',options-and-methods) 156 (cl-generic-define ',name ',args ',options-and-methods)
156 ,doc)))) 157 ,(help-add-fundoc-usage doc args)))))
157 158
158(defun cl--generic-mandatory-args (args) 159(defun cl--generic-mandatory-args (args)
159 (let ((res ())) 160 (let ((res ()))
@@ -176,15 +177,10 @@ via (:documentation DOCSTRING)."
176 (setf (cl--generic-method-table generic) nil) 177 (setf (cl--generic-method-table generic) nil)
177 (cl--generic-make-function generic))) 178 (cl--generic-make-function generic)))
178 179
179(defvar cl-generic-current-method-specializers nil 180(defmacro cl-generic-current-method-specializers ()
180 ;; This is let-bound during macro-expansion of method bodies, so that those 181 "List of (VAR . TYPE) where TYPE is var's specializer.
181 ;; bodies can be optimized knowing that the specializers have matched. 182This macro can only be used within the lexical scope of a cl-generic method."
182 ;; FIXME: This presumes the formal arguments aren't modified via `setq' and 183 (error "cl-generic-current-method-specializers used outside of a method"))
183 ;; aren't shadowed either ;-(
184 ;; FIXME: This might leak outside the scope of the method if, during
185 ;; macroexpansion of the method, something causes some other macroexpansion
186 ;; (e.g. an autoload).
187 "List of (VAR . TYPE) where TYPE is var's specializer.")
188 184
189(eval-and-compile ;Needed while compiling the cl-defmethod calls below! 185(eval-and-compile ;Needed while compiling the cl-defmethod calls below!
190 (defun cl--generic-fgrep (vars sexp) ;Copied from pcase.el. 186 (defun cl--generic-fgrep (vars sexp) ;Copied from pcase.el.
@@ -199,27 +195,29 @@ via (:documentation DOCSTRING)."
199 (defun cl--generic-lambda (args body with-cnm) 195 (defun cl--generic-lambda (args body with-cnm)
200 "Make the lambda expression for a method with ARGS and BODY." 196 "Make the lambda expression for a method with ARGS and BODY."
201 (let ((plain-args ()) 197 (let ((plain-args ())
202 (cl-generic-current-method-specializers nil) 198 (specializers nil)
203 (doc-string (if (stringp (car-safe body)) (pop body))) 199 (doc-string (if (stringp (car-safe body)) (pop body)))
204 (mandatory t)) 200 (mandatory t))
205 (dolist (arg args) 201 (dolist (arg args)
206 (push (pcase arg 202 (push (pcase arg
207 ((or '&optional '&rest '&key) (setq mandatory nil) arg) 203 ((or '&optional '&rest '&key) (setq mandatory nil) arg)
208 ((and `(,name . ,type) (guard mandatory)) 204 ((and `(,name . ,type) (guard mandatory))
209 (push (cons name (car type)) 205 (push (cons name (car type)) specializers)
210 cl-generic-current-method-specializers)
211 name) 206 name)
212 (_ arg)) 207 (_ arg))
213 plain-args)) 208 plain-args))
214 (setq plain-args (nreverse plain-args)) 209 (setq plain-args (nreverse plain-args))
215 (let ((fun `(cl-function (lambda ,plain-args 210 (let ((fun `(cl-function (lambda ,plain-args
216 ,@(if doc-string (list doc-string)) 211 ,@(if doc-string (list doc-string))
217 ,@body)))) 212 ,@body)))
213 (macroenv (cons `(cl-generic-current-method-specializers
214 . ,(lambda () specializers))
215 macroexpand-all-environment)))
218 (if (not with-cnm) 216 (if (not with-cnm)
219 (cons nil fun) 217 (cons nil (macroexpand-all fun macroenv))
220 ;; First macroexpand away the cl-function stuff (e.g. &key and 218 ;; First macroexpand away the cl-function stuff (e.g. &key and
221 ;; destructuring args, `declare' and whatnot). 219 ;; destructuring args, `declare' and whatnot).
222 (pcase (macroexpand fun macroexpand-all-environment) 220 (pcase (macroexpand fun macroenv)
223 (`#'(lambda ,args . ,body) 221 (`#'(lambda ,args . ,body)
224 (require 'cl-lib) ;Needed to expand `cl-flet'. 222 (require 'cl-lib) ;Needed to expand `cl-flet'.
225 (let* ((doc-string (and doc-string (stringp (car body)) 223 (let* ((doc-string (and doc-string (stringp (car body))
@@ -228,7 +226,7 @@ via (:documentation DOCSTRING)."
228 (nbody (macroexpand-all 226 (nbody (macroexpand-all
229 `(cl-flet ((cl-call-next-method ,cnm)) 227 `(cl-flet ((cl-call-next-method ,cnm))
230 ,@body) 228 ,@body)
231 macroexpand-all-environment)) 229 macroenv))
232 ;; FIXME: Rather than `grep' after the fact, the 230 ;; FIXME: Rather than `grep' after the fact, the
233 ;; macroexpansion should directly set some flag when cnm 231 ;; macroexpansion should directly set some flag when cnm
234 ;; is used. 232 ;; is used.
@@ -309,8 +307,13 @@ which case this method will be invoked when the argument is `eql' to VAL.
309 (setf (cl--generic-method-table generic) 307 (setf (cl--generic-method-table generic)
310 (cons `(,key ,uses-cnm . ,function) mt))) 308 (cons `(,key ,uses-cnm . ,function) mt)))
311 ;; For aliases, cl--generic-name gives us the actual name. 309 ;; For aliases, cl--generic-name gives us the actual name.
312 (defalias (cl--generic-name generic) 310 (let ((gfun (cl--generic-make-function generic))
313 (cl--generic-make-function generic)))) 311 ;; Prevent `defalias' from recording this as the definition site of
312 ;; the generic function.
313 current-load-list)
314 (defalias (cl--generic-name generic) gfun))
315 (cl-pushnew `(cl-defmethod . (,(cl--generic-name generic) . ,specializers))
316 current-load-list :test #'equal)))
314 317
315(defmacro cl--generic-with-memoization (place &rest code) 318(defmacro cl--generic-with-memoization (place &rest code)
316 (declare (indent 1) (debug t)) 319 (declare (indent 1) (debug t))
@@ -327,6 +330,14 @@ which case this method will be invoked when the argument is `eql' to VAL.
327 (cl--generic-with-memoization 330 (cl--generic-with-memoization
328 (gethash (cons dispatch-arg tagcodes) cl--generic-dispatchers) 331 (gethash (cons dispatch-arg tagcodes) cl--generic-dispatchers)
329 (let ((lexical-binding t) 332 (let ((lexical-binding t)
333 (tag-exp `(or ,@(mapcar #'cdr
334 ;; Minor optimization: since this tag-exp is
335 ;; only used to lookup the method-cache, it
336 ;; doesn't matter if the default value is some
337 ;; constant or nil.
338 (if (macroexp-const-p (car (last tagcodes)))
339 (butlast tagcodes)
340 tagcodes))))
330 (extraargs ())) 341 (extraargs ()))
331 (dotimes (_ dispatch-arg) 342 (dotimes (_ dispatch-arg)
332 (push (make-symbol "arg") extraargs)) 343 (push (make-symbol "arg") extraargs))
@@ -335,7 +346,7 @@ which case this method will be invoked when the argument is `eql' to VAL.
335 (let ((method-cache (make-hash-table :test #'eql))) 346 (let ((method-cache (make-hash-table :test #'eql)))
336 (lambda (,@extraargs arg &rest args) 347 (lambda (,@extraargs arg &rest args)
337 (apply (cl--generic-with-memoization 348 (apply (cl--generic-with-memoization
338 (gethash (or ,@(mapcar #'cdr tagcodes)) method-cache) 349 (gethash ,tag-exp method-cache)
339 (cl--generic-cache-miss 350 (cl--generic-cache-miss
340 generic ',dispatch-arg dispatches-left 351 generic ',dispatch-arg dispatches-left
341 (list ,@(mapcar #'cdr tagcodes)))) 352 (list ,@(mapcar #'cdr tagcodes))))
@@ -456,31 +467,63 @@ Can only be used from within the lexical body of a primary or around method."
456 467
457;;; Add support for describe-function 468;;; Add support for describe-function
458 469
459(add-hook 'help-fns-describe-function-functions 'cl--generic-describe) 470(defun cl--generic-search-method (met-name)
471 (let ((base-re (concat "(\\(?:cl-\\)?defmethod[ \t]+"
472 (regexp-quote (format "%s\\_>" (car met-name))))))
473 (or
474 (re-search-forward
475 (concat base-re "[^&\"\n]*"
476 (mapconcat (lambda (specializer)
477 (regexp-quote
478 (format "%S" (if (consp specializer)
479 (nth 1 specializer) specializer))))
480 (remq t (cdr met-name))
481 "[ \t\n]*)[^&\"\n]*"))
482 nil t)
483 (re-search-forward base-re nil t))))
484
485
486(with-eval-after-load 'find-func
487 (defvar find-function-regexp-alist)
488 (add-to-list 'find-function-regexp-alist
489 `(cl-defmethod . ,#'cl--generic-search-method)))
490
491(add-hook 'help-fns-describe-function-functions #'cl--generic-describe)
460(defun cl--generic-describe (function) 492(defun cl--generic-describe (function)
461 ;; FIXME: Fix up the main "in `<file>'" hyperlink, and add such hyperlinks
462 ;; for each method.
463 (let ((generic (if (symbolp function) (cl--generic function)))) 493 (let ((generic (if (symbolp function) (cl--generic function))))
464 (when generic 494 (when generic
495 (require 'help-mode) ;Needed for `help-function-def' button!
465 (save-excursion 496 (save-excursion
466 (insert "\n\nThis is a generic function.\n\n") 497 (insert "\n\nThis is a generic function.\n\n")
467 (insert (propertize "Implementations:\n\n" 'face 'bold)) 498 (insert (propertize "Implementations:\n\n" 'face 'bold))
468 ;; Loop over fanciful generics 499 ;; Loop over fanciful generics
469 (pcase-dolist (`((,type . ,qualifier) . ,method) 500 (pcase-dolist (`((,specializers . ,qualifier) ,uses-cnm . ,method)
470 (cl--generic-method-table generic)) 501 (cl--generic-method-table generic))
471 (insert "`") 502 (let* ((args (help-function-arglist method 'names))
472 (if (symbolp type) 503 (docstring (documentation method))
473 ;; FIXME: Add support for cl-structs in help-variable. 504 (doconly (if docstring
474 (help-insert-xref-button (symbol-name type) 505 (let ((split (help-split-fundoc docstring nil)))
475 'help-variable type) 506 (if split (cdr split) docstring))))
476 (insert (format "%S" type))) 507 (combined-args ()))
477 (insert (format "' %S %S\n" 508 (if uses-cnm (setq args (cdr args)))
478 (car qualifier) 509 (dolist (specializer specializers)
479 (let ((args (help-function-arglist method))) 510 (let ((arg (if (eq '&rest (car args))
480 ;; Drop cl--generic-next arg if present. 511 (intern (format "arg%d" (length combined-args)))
481 (if (memq (car qualifier) '(:after :before)) 512 (pop args))))
482 args (cdr args))))) 513 (push (if (eq specializer t) arg (list arg specializer))
483 (insert (or (documentation method) "Undocumented") "\n\n")))))) 514 combined-args)))
515 (setq combined-args (append (nreverse combined-args) args))
516 ;; FIXME: Add hyperlinks for the types as well.
517 (insert (format "%S %S" qualifier combined-args))
518 (let* ((met-name (cons function specializers))
519 (file (find-lisp-object-file-name met-name 'cl-defmethod)))
520 (when file
521 (insert " in `")
522 (help-insert-xref-button (help-fns-short-filename file)
523 'help-function-def met-name file
524 'cl-defmethod)
525 (insert "'.\n")))
526 (insert "\n" (or doconly "Undocumented") "\n\n")))))))
484 527
485;;; Support for (eql <val>) specializers. 528;;; Support for (eql <val>) specializers.
486 529
diff --git a/lisp/emacs-lisp/eieio-core.el b/lisp/emacs-lisp/eieio-core.el
index bfa922bade6..e526a41e871 100644
--- a/lisp/emacs-lisp/eieio-core.el
+++ b/lisp/emacs-lisp/eieio-core.el
@@ -34,19 +34,6 @@
34(require 'cl-lib) 34(require 'cl-lib)
35(require 'pcase) 35(require 'pcase)
36 36
37(put 'eieio--defalias 'byte-hunk-handler
38 #'byte-compile-file-form-defalias) ;;(get 'defalias 'byte-hunk-handler)
39(defun eieio--defalias (name body)
40 "Like `defalias', but with less side-effects.
41More specifically, it has no side-effects at all when the new function
42definition is the same (`eq') as the old one."
43 (while (and (fboundp name) (symbolp (symbol-function name)))
44 ;; Follow aliases, so methods applied to obsolete aliases still work.
45 (setq name (symbol-function name)))
46 (unless (and (fboundp name)
47 (eq (symbol-function name) body))
48 (defalias name body)))
49
50;;; 37;;;
51;; A few functions that are better in the official EIEIO src, but 38;; A few functions that are better in the official EIEIO src, but
52;; used from the core. 39;; used from the core.
@@ -292,7 +279,7 @@ Abstract classes cannot be instantiated."
292 279
293;; We autoload this because it's used in `make-autoload'. 280;; We autoload this because it's used in `make-autoload'.
294;;;###autoload 281;;;###autoload
295(defun eieio-defclass-autoload (cname superclasses filename doc) 282(defun eieio-defclass-autoload (cname _superclasses filename doc)
296 "Create autoload symbols for the EIEIO class CNAME. 283 "Create autoload symbols for the EIEIO class CNAME.
297SUPERCLASSES are the superclasses that CNAME inherits from. 284SUPERCLASSES are the superclasses that CNAME inherits from.
298DOC is the docstring for CNAME. 285DOC is the docstring for CNAME.
@@ -301,58 +288,35 @@ SUPERCLASSES as children.
301It creates an autoload function for CNAME's constructor." 288It creates an autoload function for CNAME's constructor."
302 ;; Assume we've already debugged inputs. 289 ;; Assume we've already debugged inputs.
303 290
291 ;; We used to store the list of superclasses in the `parent' slot (as a list
292 ;; of class names). But now this slot holds a list of class objects, and
293 ;; those parents may not exist yet, so the corresponding class objects may
294 ;; simply not exist yet. So instead we just don't store the list of parents
295 ;; here in eieio-defclass-autoload at all, since it seems that they're just
296 ;; not needed before the class is actually loaded.
304 (let* ((oldc (when (class-p cname) (eieio--class-v cname))) 297 (let* ((oldc (when (class-p cname) (eieio--class-v cname)))
305 (newc (eieio--class-make cname)) 298 (newc (eieio--class-make cname))
306 ) 299 )
307 (if oldc 300 (if oldc
308 nil ;; Do nothing if we already have this class. 301 nil ;; Do nothing if we already have this class.
309 302
310 (let ((clear-parent nil)) 303 ;; turn this into a usable self-pointing symbol
311 ;; No parents? 304 (when eieio-backward-compatibility
312 (when (not superclasses) 305 (set cname cname)
313 (setq superclasses '(eieio-default-superclass) 306 (make-obsolete-variable cname (format "use '%s instead" cname) "25.1"))
314 clear-parent t)
315 )
316
317 ;; Hook our new class into the existing structures so we can
318 ;; autoload it later.
319 (dolist (SC superclasses)
320
321
322 ;; TODO - If we create an autoload that is in the map, that
323 ;; map needs to be cleared!
324
325
326 ;; Save the child in the parent.
327 (cl-pushnew cname (if (class-p SC)
328 (eieio--class-children (eieio--class-v SC))
329 ;; Parent doesn't exist yet.
330 (gethash SC eieio-defclass-autoload-map)))
331 307
332 ;; Save parent in child. 308 ;; Store the new class vector definition into the symbol. We need to
333 (push (eieio--class-v SC) (eieio--class-parent newc))) 309 ;; do this first so that we can call defmethod for the accessor.
310 ;; The vector will be updated by the following while loop and will not
311 ;; need to be stored a second time.
312 (setf (eieio--class-v cname) newc)
334 313
335 ;; turn this into a usable self-pointing symbol 314 ;; Create an autoload on top of our constructor function.
336 (when eieio-backward-compatibility 315 (autoload cname filename doc nil nil)
337 (set cname cname) 316 (autoload (intern (format "%s-p" cname)) filename "" nil nil)
338 (make-obsolete-variable cname (format "use '%s instead" cname) "25.1")) 317 (when eieio-backward-compatibility
339 318 (autoload (intern (format "%s-child-p" cname)) filename "" nil nil)
340 ;; Store the new class vector definition into the symbol. We need to 319 (autoload (intern (format "%s-list-p" cname)) filename "" nil nil)))))
341 ;; do this first so that we can call defmethod for the accessor.
342 ;; The vector will be updated by the following while loop and will not
343 ;; need to be stored a second time.
344 (setf (eieio--class-v cname) newc)
345
346 ;; Clear the parent
347 (if clear-parent (setf (eieio--class-parent newc) nil))
348
349 ;; Create an autoload on top of our constructor function.
350 (autoload cname filename doc nil nil)
351 (autoload (intern (concat (symbol-name cname) "-p")) filename "" nil nil)
352 (autoload (intern (concat (symbol-name cname) "-child-p")) filename "" nil nil)
353 (autoload (intern (concat (symbol-name cname) "-list-p")) filename "" nil nil)
354
355 ))))
356 320
357(defsubst eieio-class-un-autoload (cname) 321(defsubst eieio-class-un-autoload (cname)
358 "If class CNAME is in an autoload state, load its file." 322 "If class CNAME is in an autoload state, load its file."
@@ -378,8 +342,13 @@ See `defclass' for more information."
378 (setq eieio-hook nil) 342 (setq eieio-hook nil)
379 343
380 (let* ((pname superclasses) 344 (let* ((pname superclasses)
381 (newc (eieio--class-make cname))
382 (oldc (when (class-p cname) (eieio--class-v cname))) 345 (oldc (when (class-p cname) (eieio--class-v cname)))
346 (newc (if (and oldc (not (eieio--class-default-object-cache oldc)))
347 ;; The oldc class is a stub setup by eieio-defclass-autoload.
348 ;; Reuse it instead of creating a new one, so that existing
349 ;; references are still valid.
350 oldc
351 (eieio--class-make cname)))
383 (groups nil) ;; list of groups id'd from slots 352 (groups nil) ;; list of groups id'd from slots
384 (clearparent nil)) 353 (clearparent nil))
385 354
@@ -1284,6 +1253,8 @@ The order, in which the parents are returned depends on the
1284method invocation orders of the involved classes." 1253method invocation orders of the involved classes."
1285 (if (or (null class) (eq class eieio-default-superclass)) 1254 (if (or (null class) (eq class eieio-default-superclass))
1286 nil 1255 nil
1256 (unless (eieio--class-default-object-cache class)
1257 (eieio-class-un-autoload (eieio--class-symbol class)))
1287 (cl-case (eieio--class-method-invocation-order class) 1258 (cl-case (eieio--class-method-invocation-order class)
1288 (:depth-first 1259 (:depth-first
1289 (eieio--class-precedence-dfs class)) 1260 (eieio--class-precedence-dfs class))
diff --git a/lisp/emacs-lisp/eieio-generic.el b/lisp/emacs-lisp/eieio-generic.el
index 0e90074660e..4045c038033 100644
--- a/lisp/emacs-lisp/eieio-generic.el
+++ b/lisp/emacs-lisp/eieio-generic.el
@@ -33,6 +33,19 @@
33(require 'eieio-core) 33(require 'eieio-core)
34(declare-function child-of-class-p "eieio") 34(declare-function child-of-class-p "eieio")
35 35
36(put 'eieio--defalias 'byte-hunk-handler
37 #'byte-compile-file-form-defalias) ;;(get 'defalias 'byte-hunk-handler)
38(defun eieio--defalias (name body)
39 "Like `defalias', but with less side-effects.
40More specifically, it has no side-effects at all when the new function
41definition is the same (`eq') as the old one."
42 (while (and (fboundp name) (symbolp (symbol-function name)))
43 ;; Follow aliases, so methods applied to obsolete aliases still work.
44 (setq name (symbol-function name)))
45 (unless (and (fboundp name)
46 (eq (symbol-function name) body))
47 (defalias name body)))
48
36(defconst eieio--method-static 0 "Index into :static tag on a method.") 49(defconst eieio--method-static 0 "Index into :static tag on a method.")
37(defconst eieio--method-before 1 "Index into :before tag on a method.") 50(defconst eieio--method-before 1 "Index into :before tag on a method.")
38(defconst eieio--method-primary 2 "Index into :primary tag on a method.") 51(defconst eieio--method-primary 2 "Index into :primary tag on a method.")
@@ -101,7 +114,7 @@ Methods with only primary implementations are executed in an optimized way."
101 ;; Make sure the method tables are installed. 114 ;; Make sure the method tables are installed.
102 (eieio--mt-install method) 115 (eieio--mt-install method)
103 ;; Construct the actual body of this function. 116 ;; Construct the actual body of this function.
104 (put method 'function-documentation doc-string) 117 (if doc-string (put method 'function-documentation doc-string))
105 (eieio--defgeneric-form method)) 118 (eieio--defgeneric-form method))
106 ((generic-p method) (symbol-function method)) ;Leave it as-is. 119 ((generic-p method) (symbol-function method)) ;Leave it as-is.
107 (t (error "You cannot create a generic/method over an existing symbol: %s" 120 (t (error "You cannot create a generic/method over an existing symbol: %s"
@@ -177,20 +190,18 @@ but remove reference to all implementations of METHOD."
177 ;; 190 ;;
178 ;; If this method, after this setup, only has primary methods, then 191 ;; If this method, after this setup, only has primary methods, then
179 ;; we can setup the generic that way. 192 ;; we can setup the generic that way.
180 (let ((doc-string (documentation method 'raw))) 193 ;; Use `defalias' so as to interact properly with nadvice.el.
181 (put method 'function-documentation doc-string) 194 (defalias method
182 ;; Use `defalias' so as to interact properly with nadvice.el. 195 (if (eieio--generic-primary-only-p method)
183 (defalias method 196 ;; If there is only one primary method, then we can go one more
184 (if (eieio--generic-primary-only-p method) 197 ;; optimization step.
185 ;; If there is only one primary method, then we can go one more 198 (if (eieio--generic-primary-only-one-p method)
186 ;; optimization step. 199 (let* ((M (get method 'eieio-method-tree))
187 (if (eieio--generic-primary-only-one-p method) 200 (entry (car (aref M eieio--method-primary))))
188 (let* ((M (get method 'eieio-method-tree)) 201 (eieio--defgeneric-form-primary-only-one
189 (entry (car (aref M eieio--method-primary)))) 202 method (car entry) (cdr entry)))
190 (eieio--defgeneric-form-primary-only-one 203 (eieio--defgeneric-form-primary-only method))
191 method (car entry) (cdr entry))) 204 (eieio--defgeneric-form method)))))
192 (eieio--defgeneric-form-primary-only method))
193 (eieio--defgeneric-form method))))))
194 205
195(defun eieio--defmethod (method kind argclass code) 206(defun eieio--defmethod (method kind argclass code)
196 "Work part of the `defmethod' macro defining METHOD with ARGS." 207 "Work part of the `defmethod' macro defining METHOD with ARGS."
@@ -627,7 +638,7 @@ is memorized for faster future use."
627 638
628;;; CLOS methods and generics 639;;; CLOS methods and generics
629;; 640;;
630(defmacro defgeneric (method _args &optional doc-string) 641(defmacro defgeneric (method args &optional doc-string)
631 "Create a generic function METHOD. 642 "Create a generic function METHOD.
632DOC-STRING is the base documentation for this class. A generic 643DOC-STRING is the base documentation for this class. A generic
633function has no body, as its purpose is to decide which method body 644function has no body, as its purpose is to decide which method body
@@ -637,7 +648,9 @@ currently ignored. You can use `defgeneric' to apply specialized
637top level documentation to a method." 648top level documentation to a method."
638 (declare (doc-string 3)) 649 (declare (doc-string 3))
639 `(eieio--defalias ',method 650 `(eieio--defalias ',method
640 (eieio--defgeneric-init-form ',method ,doc-string))) 651 (eieio--defgeneric-init-form
652 ',method
653 ,(if doc-string (help-add-fundoc-usage doc-string args)))))
641 654
642(defmacro defmethod (method &rest args) 655(defmacro defmethod (method &rest args)
643 "Create a new METHOD through `defgeneric' with ARGS. 656 "Create a new METHOD through `defgeneric' with ARGS.
@@ -684,9 +697,7 @@ Summary:
684 (code `(lambda ,fargs ,@(cdr args)))) 697 (code `(lambda ,fargs ,@(cdr args))))
685 `(progn 698 `(progn
686 ;; Make sure there is a generic and the byte-compiler sees it. 699 ;; Make sure there is a generic and the byte-compiler sees it.
687 (defgeneric ,method ,args 700 (defgeneric ,method ,args)
688 ,(or (documentation code)
689 (format "Generically created method `%s'." method)))
690 (eieio--defmethod ',method ',key ',class #',code)))) 701 (eieio--defmethod ',method ',key ',class #',code))))
691 702
692 703
diff --git a/lisp/emacs-lisp/find-func.el b/lisp/emacs-lisp/find-func.el
index cc7b06c35b1..6c9c798bc16 100644
--- a/lisp/emacs-lisp/find-func.el
+++ b/lisp/emacs-lisp/find-func.el
@@ -1,4 +1,4 @@
1;;; find-func.el --- find the definition of the Emacs Lisp function near point 1;;; find-func.el --- find the definition of the Emacs Lisp function near point -*- lexical-binding:t -*-
2 2
3;; Copyright (C) 1997, 1999, 2001-2015 Free Software Foundation, Inc. 3;; Copyright (C) 1997, 1999, 2001-2015 Free Software Foundation, Inc.
4 4
@@ -59,7 +59,7 @@
59 (concat 59 (concat
60 "^\\s-*(\\(def\\(ine-skeleton\\|ine-generic-mode\\|ine-derived-mode\\|\ 60 "^\\s-*(\\(def\\(ine-skeleton\\|ine-generic-mode\\|ine-derived-mode\\|\
61ine\\(?:-global\\)?-minor-mode\\|ine-compilation-mode\\|un-cvs-mode\\|\ 61ine\\(?:-global\\)?-minor-mode\\|ine-compilation-mode\\|un-cvs-mode\\|\
62foo\\|[^icfgv]\\(\\w\\|\\s_\\)+\\*?\\)\\|easy-mmode-define-[a-z-]+\\|easy-menu-define\\|\ 62foo\\|\\(?:[^icfv]\\|g[^r]\\)\\(\\w\\|\\s_\\)+\\*?\\)\\|easy-mmode-define-[a-z-]+\\|easy-menu-define\\|\
63menu-bar-make-toggle\\)" 63menu-bar-make-toggle\\)"
64 find-function-space-re 64 find-function-space-re
65 "\\('\\|\(quote \\)?%s\\(\\s-\\|$\\|\(\\|\)\\)") 65 "\\('\\|\(quote \\)?%s\\(\\s-\\|$\\|\(\\|\)\\)")
@@ -106,7 +106,10 @@ Please send improvements and fixes to the maintainer."
106 (defface . find-face-regexp)) 106 (defface . find-face-regexp))
107 "Alist mapping definition types into regexp variables. 107 "Alist mapping definition types into regexp variables.
108Each regexp variable's value should actually be a format string 108Each regexp variable's value should actually be a format string
109to be used to substitute the desired symbol name into the regexp.") 109to be used to substitute the desired symbol name into the regexp.
110Instead of regexp variable, types can be mapped to functions as well,
111in which case the function is called with one argument (the object
112we're looking for) and it should search for it.")
110(put 'find-function-regexp-alist 'risky-local-variable t) 113(put 'find-function-regexp-alist 'risky-local-variable t)
111 114
112(defcustom find-function-source-path nil 115(defcustom find-function-source-path nil
@@ -282,30 +285,33 @@ The search is done in the source for library LIBRARY."
282 (let* ((filename (find-library-name library)) 285 (let* ((filename (find-library-name library))
283 (regexp-symbol (cdr (assq type find-function-regexp-alist)))) 286 (regexp-symbol (cdr (assq type find-function-regexp-alist))))
284 (with-current-buffer (find-file-noselect filename) 287 (with-current-buffer (find-file-noselect filename)
285 (let ((regexp (format (symbol-value regexp-symbol) 288 (let ((regexp (if (functionp regexp-symbol) regexp-symbol
286 ;; Entry for ` (backquote) macro in loaddefs.el, 289 (format (symbol-value regexp-symbol)
287 ;; (defalias (quote \`)..., has a \ but 290 ;; Entry for ` (backquote) macro in loaddefs.el,
288 ;; (symbol-name symbol) doesn't. Add an 291 ;; (defalias (quote \`)..., has a \ but
289 ;; optional \ to catch this. 292 ;; (symbol-name symbol) doesn't. Add an
290 (concat "\\\\?" 293 ;; optional \ to catch this.
291 (regexp-quote (symbol-name symbol))))) 294 (concat "\\\\?"
295 (regexp-quote (symbol-name symbol))))))
292 (case-fold-search)) 296 (case-fold-search))
293 (with-syntax-table emacs-lisp-mode-syntax-table 297 (with-syntax-table emacs-lisp-mode-syntax-table
294 (goto-char (point-min)) 298 (goto-char (point-min))
295 (if (or (re-search-forward regexp nil t) 299 (if (if (functionp regexp)
296 ;; `regexp' matches definitions using known forms like 300 (funcall regexp symbol)
297 ;; `defun', or `defvar'. But some functions/variables 301 (or (re-search-forward regexp nil t)
298 ;; are defined using special macros (or functions), so 302 ;; `regexp' matches definitions using known forms like
299 ;; if `regexp' can't find the definition, we look for 303 ;; `defun', or `defvar'. But some functions/variables
300 ;; something of the form "(SOMETHING <symbol> ...)". 304 ;; are defined using special macros (or functions), so
301 ;; This fails to distinguish function definitions from 305 ;; if `regexp' can't find the definition, we look for
302 ;; variable declarations (or even uses thereof), but is 306 ;; something of the form "(SOMETHING <symbol> ...)".
303 ;; a good pragmatic fallback. 307 ;; This fails to distinguish function definitions from
304 (re-search-forward 308 ;; variable declarations (or even uses thereof), but is
305 (concat "^([^ ]+" find-function-space-re "['(]?" 309 ;; a good pragmatic fallback.
306 (regexp-quote (symbol-name symbol)) 310 (re-search-forward
307 "\\_>") 311 (concat "^([^ ]+" find-function-space-re "['(]?"
308 nil t)) 312 (regexp-quote (symbol-name symbol))
313 "\\_>")
314 nil t)))
309 (progn 315 (progn
310 (beginning-of-line) 316 (beginning-of-line)
311 (cons (current-buffer) (point))) 317 (cons (current-buffer) (point)))
@@ -324,18 +330,19 @@ signal an error.
324 330
325If VERBOSE is non-nil, and FUNCTION is an alias, display a 331If VERBOSE is non-nil, and FUNCTION is an alias, display a
326message about the whole chain of aliases." 332message about the whole chain of aliases."
327 (let ((def (symbol-function (find-function-advised-original function))) 333 (let ((def (if (symbolp function)
334 (symbol-function (find-function-advised-original function))))
328 aliases) 335 aliases)
329 ;; FIXME for completeness, it might be nice to print something like: 336 ;; FIXME for completeness, it might be nice to print something like:
330 ;; foo (which is advised), which is an alias for bar (which is advised). 337 ;; foo (which is advised), which is an alias for bar (which is advised).
331 (while (symbolp def) 338 (while (and def (symbolp def))
332 (or (eq def function) 339 (or (eq def function)
333 (not verbose) 340 (not verbose)
334 (if aliases 341 (setq aliases (if aliases
335 (setq aliases (concat aliases 342 (concat aliases
336 (format ", which is an alias for `%s'" 343 (format ", which is an alias for `%s'"
337 (symbol-name def)))) 344 (symbol-name def)))
338 (setq aliases (format "`%s' is an alias for `%s'" 345 (format "`%s' is an alias for `%s'"
339 function (symbol-name def))))) 346 function (symbol-name def)))))
340 (setq function (symbol-function (find-function-advised-original function)) 347 (setq function (symbol-function (find-function-advised-original function))
341 def (symbol-function (find-function-advised-original function)))) 348 def (symbol-function (find-function-advised-original function))))
@@ -408,7 +415,6 @@ See also `find-function-after-hook'.
408 415
409Set mark before moving, if the buffer already existed." 416Set mark before moving, if the buffer already existed."
410 (let* ((orig-point (point)) 417 (let* ((orig-point (point))
411 (orig-buf (window-buffer))
412 (orig-buffers (buffer-list)) 418 (orig-buffers (buffer-list))
413 (buffer-point (save-excursion 419 (buffer-point (save-excursion
414 (find-definition-noselect symbol type))) 420 (find-definition-noselect symbol type)))
diff --git a/lisp/help-fns.el b/lisp/help-fns.el
index 10c040a246c..c0d63935035 100644
--- a/lisp/help-fns.el
+++ b/lisp/help-fns.el
@@ -183,8 +183,7 @@ OBJECT should be a symbol associated with a function, variable, or face;
183 alternatively, it can be a function definition. 183 alternatively, it can be a function definition.
184If TYPE is `defvar', search for a variable definition. 184If TYPE is `defvar', search for a variable definition.
185If TYPE is `defface', search for a face definition. 185If TYPE is `defface', search for a face definition.
186If TYPE is the value returned by `symbol-function' for a function symbol, 186If TYPE is not a symbol, search for a function definition.
187 search for a function definition.
188 187
189The return value is the absolute name of a readable file where OBJECT is 188The return value is the absolute name of a readable file where OBJECT is
190defined. If several such files exist, preference is given to a file 189defined. If several such files exist, preference is given to a file
@@ -194,9 +193,10 @@ suitable file is found, return nil."
194 (let* ((autoloaded (autoloadp type)) 193 (let* ((autoloaded (autoloadp type))
195 (file-name (or (and autoloaded (nth 1 type)) 194 (file-name (or (and autoloaded (nth 1 type))
196 (symbol-file 195 (symbol-file
197 object (if (memq type (list 'defvar 'defface)) 196 ;; FIXME: Why do we have this weird "If TYPE is the
198 type 197 ;; value returned by `symbol-function' for a function
199 'defun))))) 198 ;; symbol" exception?
199 object (or (if (symbolp type) type) 'defun)))))
200 (cond 200 (cond
201 (autoloaded 201 (autoloaded
202 ;; An autoloaded function: Locate the file since `symbol-function' 202 ;; An autoloaded function: Locate the file since `symbol-function'
@@ -452,6 +452,18 @@ FILE is the file where FUNCTION was probably defined."
452 (t ".")) 452 (t "."))
453 "\n"))))) 453 "\n")))))
454 454
455(defun help-fns-short-filename (filename)
456 (let* ((abbrev (abbreviate-file-name filename))
457 (short abbrev))
458 (dolist (dir load-path)
459 (let ((rel (file-relative-name filename dir)))
460 (if (< (length rel) (length short))
461 (setq short rel)))
462 (let ((rel (file-relative-name abbrev dir)))
463 (if (< (length rel) (length short))
464 (setq short rel))))
465 short))
466
455;;;###autoload 467;;;###autoload
456(defun describe-function-1 (function) 468(defun describe-function-1 (function)
457 (let* ((advised (and (symbolp function) 469 (let* ((advised (and (symbolp function)
@@ -543,7 +555,7 @@ FILE is the file where FUNCTION was probably defined."
543 ;; but that's completely wrong when the user used load-file. 555 ;; but that's completely wrong when the user used load-file.
544 (princ (if (eq file-name 'C-source) 556 (princ (if (eq file-name 'C-source)
545 "C source code" 557 "C source code"
546 (file-name-nondirectory file-name))) 558 (help-fns-short-filename file-name)))
547 (princ "'") 559 (princ "'")
548 ;; Make a hyperlink to the library. 560 ;; Make a hyperlink to the library.
549 (with-current-buffer standard-output 561 (with-current-buffer standard-output
@@ -564,7 +576,7 @@ FILE is the file where FUNCTION was probably defined."
564 help-enable-auto-load 576 help-enable-auto-load
565 (string-match "\\([^\\]=\\|[^=]\\|\\`\\)\\\\[[{<]" 577 (string-match "\\([^\\]=\\|[^=]\\|\\`\\)\\\\[[{<]"
566 doc-raw) 578 doc-raw)
567 (load (cadr real-def) t)) 579 (autoload-do-load real-def))
568 (substitute-command-keys doc-raw)))) 580 (substitute-command-keys doc-raw))))
569 581
570 (help-fns--key-bindings function) 582 (help-fns--key-bindings function)
diff --git a/lisp/help-mode.el b/lisp/help-mode.el
index dd2030706b2..c62ddc3dcd0 100644
--- a/lisp/help-mode.el
+++ b/lisp/help-mode.el
@@ -191,7 +191,7 @@ The format is (FUNCTION ARGS...).")
191 191
192(define-button-type 'help-function-def 192(define-button-type 'help-function-def
193 :supertype 'help-xref 193 :supertype 'help-xref
194 'help-function (lambda (fun file) 194 'help-function (lambda (fun file &optional type)
195 (require 'find-func) 195 (require 'find-func)
196 (when (eq file 'C-source) 196 (when (eq file 'C-source)
197 (setq file 197 (setq file
@@ -199,7 +199,7 @@ The format is (FUNCTION ARGS...).")
199 ;; Don't use find-function-noselect because it follows 199 ;; Don't use find-function-noselect because it follows
200 ;; aliases (which fails for built-in functions). 200 ;; aliases (which fails for built-in functions).
201 (let ((location 201 (let ((location
202 (find-function-search-for-symbol fun nil file))) 202 (find-function-search-for-symbol fun type file)))
203 (pop-to-buffer (car location)) 203 (pop-to-buffer (car location))
204 (if (cdr location) 204 (if (cdr location)
205 (goto-char (cdr location)) 205 (goto-char (cdr location))
diff --git a/test/ChangeLog b/test/ChangeLog
index 8ed02ee341b..c40407f496b 100644
--- a/test/ChangeLog
+++ b/test/ChangeLog
@@ -1,3 +1,13 @@
12015-01-17 Stefan Monnier <monnier@iro.umontreal.ca>
2
3 * automated/eieio-test-methodinvoke.el (eieio-test-cl-generic-1): Reset
4 eieio-test--1.
5
6 * automated/cl-generic-tests.el (cl-generic-test-8-after/before):
7 Rename from cl-generic-test-7-after/before.
8 (cl--generic-test-advice): New function.
9 (cl-generic-test-9-advice): New test.
10
12015-01-16 Jorgen Schaefer <contact@jorgenschaefer.de> 112015-01-16 Jorgen Schaefer <contact@jorgenschaefer.de>
2 12
3 * automated/package-test.el (package-test-install-prioritized): 13 * automated/package-test.el (package-test-install-prioritized):
diff --git a/test/automated/cl-generic-tests.el b/test/automated/cl-generic-tests.el
index 57b17b145e8..46397fb7f51 100644
--- a/test/automated/cl-generic-tests.el
+++ b/test/automated/cl-generic-tests.el
@@ -129,7 +129,7 @@
129 (cons "x&y-int" (cl-call-next-method))) 129 (cons "x&y-int" (cl-call-next-method)))
130 (should (equal (cl--generic-1 1 2) '("x&y-int" "y-int" "x-int" 1 2)))) 130 (should (equal (cl--generic-1 1 2) '("x&y-int" "y-int" "x-int" 1 2))))
131 131
132(ert-deftest cl-generic-test-7-after/before () 132(ert-deftest cl-generic-test-8-after/before ()
133 (let ((log ())) 133 (let ((log ()))
134 (cl-defgeneric cl--generic-1 (x y)) 134 (cl-defgeneric cl--generic-1 (x y))
135 (cl-defmethod cl--generic-1 ((_x t) y) (cons y log)) 135 (cl-defmethod cl--generic-1 ((_x t) y) (cons y log))
@@ -142,5 +142,18 @@
142 (should (equal (cl--generic-1 4 6) '("quatre" 6 (:before 4)))) 142 (should (equal (cl--generic-1 4 6) '("quatre" 6 (:before 4))))
143 (should (equal log '((:after 4) (:before 4)))))) 143 (should (equal log '((:after 4) (:before 4))))))
144 144
145(defun cl--generic-test-advice (&rest args) (cons "advice" (apply args)))
146
147(ert-deftest cl-generic-test-9-advice ()
148 (cl-defgeneric cl--generic-1 (x y) "My doc.")
149 (cl-defmethod cl--generic-1 (x y) (list x y))
150 (advice-add 'cl--generic-1 :around #'cl--generic-test-advice)
151 (should (equal (cl--generic-1 4 5) '("advice" 4 5)))
152 (cl-defmethod cl--generic-1 ((_x integer) _y)
153 (cons "integer" (cl-call-next-method)))
154 (should (equal (cl--generic-1 4 5) '("advice" "integer" 4 5)))
155 (advice-remove 'cl--generic-1 #'cl--generic-test-advice)
156 (should (equal (cl--generic-1 4 5) '("integer" 4 5))))
157
145(provide 'cl-generic-tests) 158(provide 'cl-generic-tests)
146;;; cl-generic-tests.el ends here 159;;; cl-generic-tests.el ends here
diff --git a/test/automated/eieio-test-methodinvoke.el b/test/automated/eieio-test-methodinvoke.el
index 6362fc5a8d9..1c3d9c34708 100644
--- a/test/automated/eieio-test-methodinvoke.el
+++ b/test/automated/eieio-test-methodinvoke.el
@@ -384,6 +384,7 @@
384(cl-defgeneric eieio-test--1 (x y)) 384(cl-defgeneric eieio-test--1 (x y))
385 385
386(ert-deftest eieio-test-cl-generic-1 () 386(ert-deftest eieio-test-cl-generic-1 ()
387 (cl-defgeneric eieio-test--1 (x y))
387 (cl-defmethod eieio-test--1 (x y) (list x y)) 388 (cl-defmethod eieio-test--1 (x y) (list x y))
388 (cl-defmethod eieio-test--1 ((_x CNM-0) y) 389 (cl-defmethod eieio-test--1 ((_x CNM-0) y)
389 (cons "CNM-0" (cl-call-next-method 7 y))) 390 (cons "CNM-0" (cl-call-next-method 7 y)))