summaryrefslogtreecommitdiff
path: root/lisp/emacs-lisp/cl-generic.el
diff options
context:
space:
mode:
authorStefan Monnier <monnier@iro.umontreal.ca>2015-07-07 02:14:16 -0400
committerStefan Monnier <monnier@iro.umontreal.ca>2015-07-07 02:14:16 -0400
commit59b5723c9b613f14cd60cd3239cfdbc0d2343b18 (patch)
tree923edc0b04619ab41af69078d8cd9e3f86df5038 /lisp/emacs-lisp/cl-generic.el
parent287bce988895b104c33d53faacfffd91d8d8e0f1 (diff)
downloademacs-59b5723c9b613f14cd60cd3239cfdbc0d2343b18.tar.gz
emacs-59b5723c9b613f14cd60cd3239cfdbc0d2343b18.tar.bz2
emacs-59b5723c9b613f14cd60cd3239cfdbc0d2343b18.zip
Add online-help support to describe types
* lisp/help-fns.el (describe-symbol-backends): Move to help-mode.el. (describe-symbol): Improve the selection of default. * lisp/help-mode.el: Require cl-lib. (describe-symbol-backends): Move from help-fns.el. (help-make-xrefs): Use it. * lisp/emacs-lisp/cl-extra.el (describe-symbol-backends): Add entry for types. (cl--typedef-regexp): New const. (find-function-regexp-alist): Add entry for types. (cl-help-type, cl-type-definition): New buttons. (cl-find-class): New function. (cl-describe-type): New command. (cl--describe-class, cl--describe-class-slot) (cl--describe-class-slots): New functions, moved from eieio-opt.el. * lisp/emacs-lisp/cl-generic.el (cl--generic-method-documentation) (cl--generic-all-functions, cl--generic-specializers-apply-to-type-p): New functions. Moved from eieio-opt.el. (cl--generic-class-parents): New function, extracted from cl--generic-struct-specializers. (cl--generic-struct-specializers): Use it. * lisp/emacs-lisp/cl-macs.el (cl-defstruct): Use pcase-dolist. Improve constructor's docstrings. (cl-struct-unknown-slot): New error. (cl-struct-slot-offset): Use it. * lisp/emacs-lisp/cl-preloaded.el (cl-struct-define): Record the type definition in current-load-list. * lisp/emacs-lisp/eieio-core.el (eieio--known-slot-names): New var. (eieio--add-new-slot): Set it. (eieio-defclass-internal): Use new name for current-load-list. (eieio-oref): Add compiler-macro to warn about unknown slots. * lisp/emacs-lisp/eieio.el (defclass): Update eieio--known-slot-names as compile-time as well. Improve constructor docstrings. * lisp/emacs-lisp/eieio-opt.el (eieio-help-class) (eieio--help-print-slot, eieio-help-class-slots): Move to cl-extra.el. (eieio-class-def): Remove button. (eieio-help-constructor): Use new name for load-history element. (eieio--specializers-apply-to-class-p, eieio-all-generic-functions) (eieio-method-documentation): Move to cl-generic.el. (eieio-display-method-list): Use new names. * lisp/emacs-lisp/lisp-mode.el (lisp-imenu-generic-expression): Add "define-linline". (lisp-fdefs): Remove "defsubst". (el-fdefs): Add "defsubst", "cl-defsubst", and "define-linline". * lisp/emacs-lisp/macroexp.el (macroexp--warned): New var. (macroexp--warn-and-return): Use it to avoid inf-loops. Add `compile-only' argument.
Diffstat (limited to 'lisp/emacs-lisp/cl-generic.el')
-rw-r--r--lisp/emacs-lisp/cl-generic.el71
1 files changed, 62 insertions, 9 deletions
diff --git a/lisp/emacs-lisp/cl-generic.el b/lisp/emacs-lisp/cl-generic.el
index 5923e4db996..a3bb7c3ad7b 100644
--- a/lisp/emacs-lisp/cl-generic.el
+++ b/lisp/emacs-lisp/cl-generic.el
@@ -95,6 +95,7 @@
;; usually be simplified, or even completely skipped.
(eval-when-compile (require 'cl-lib))
+(eval-when-compile (require 'cl-macs)) ;For cl--find-class.
(eval-when-compile (require 'pcase))
(cl-defstruct (cl--generic-generalizer
@@ -883,6 +884,55 @@ Can only be used from within the lexical body of a primary or around method."
(insert (substitute-command-keys "’.\n"))))
(insert "\n" (or (nth 2 info) "Undocumented") "\n\n")))))))
+(defun cl--generic-specializers-apply-to-type-p (specializers type)
+ "Return non-nil if a method with SPECIALIZERS applies to TYPE."
+ (let ((applies nil))
+ (dolist (specializer specializers)
+ (if (memq (car-safe specializer) '(subclass eieio--static))
+ (setq specializer (nth 1 specializer)))
+ ;; Don't include the methods that are "too generic", such as those
+ ;; applying to `eieio-default-superclass'.
+ (and (not (memq specializer '(t eieio-default-superclass)))
+ (or (equal type specializer)
+ (when (symbolp specializer)
+ (let ((sclass (cl--find-class specializer))
+ (tclass (cl--find-class type)))
+ (when (and sclass tclass)
+ (member specializer (cl--generic-class-parents tclass))))))
+ (setq applies t)))
+ applies))
+
+(defun cl--generic-all-functions (&optional type)
+ "Return a list of all generic functions.
+Optional TYPE argument returns only those functions that contain
+methods for TYPE."
+ (let ((l nil))
+ (mapatoms
+ (lambda (symbol)
+ (let ((generic (and (fboundp symbol) (cl--generic symbol))))
+ (and generic
+ (catch 'found
+ (if (null type) (throw 'found t))
+ (dolist (method (cl--generic-method-table generic))
+ (if (cl--generic-specializers-apply-to-type-p
+ (cl--generic-method-specializers method) type)
+ (throw 'found t))))
+ (push symbol l)))))
+ l))
+
+(defun cl--generic-method-documentation (function type)
+ "Return info for all methods of FUNCTION (a symbol) applicable to TYPE.
+The value returned is a list of elements of the form
+\(QUALIFIERS ARGS DOC)."
+ (let ((generic (cl--generic function))
+ (docs ()))
+ (when generic
+ (dolist (method (cl--generic-method-table generic))
+ (when (cl--generic-specializers-apply-to-type-p
+ (cl--generic-method-specializers method) type)
+ (push (cl--generic-method-info method) docs))))
+ docs))
+
;;; Support for (head <val>) specializers.
;; For both the `eql' and the `head' specializers, the dispatch
@@ -958,19 +1008,22 @@ Can only be used from within the lexical body of a primary or around method."
(if (eq (symbol-function tag) :quick-object-witness-check)
tag))))
+(defun cl--generic-class-parents (class)
+ (let ((parents ())
+ (classes (list class)))
+ ;; BFS precedence. FIXME: Use a topological sort.
+ (while (let ((class (pop classes)))
+ (cl-pushnew (cl--class-name class) parents)
+ (setq classes
+ (append classes
+ (cl--class-parents class)))))
+ (nreverse parents)))
+
(defun cl--generic-struct-specializers (tag)
(and (symbolp tag) (boundp tag)
(let ((class (symbol-value tag)))
(when (cl-typep class 'cl-structure-class)
- (let ((types ())
- (classes (list class)))
- ;; BFS precedence.
- (while (let ((class (pop classes)))
- (push (cl--class-name class) types)
- (setq classes
- (append classes
- (cl--class-parents class)))))
- (nreverse types))))))
+ (cl--generic-class-parents class)))))
(defconst cl--generic-struct-generalizer
(cl-generic-make-generalizer