From 59b5723c9b613f14cd60cd3239cfdbc0d2343b18 Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Tue, 7 Jul 2015 02:14:16 -0400 Subject: 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. --- lisp/emacs-lisp/cl-generic.el | 71 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 62 insertions(+), 9 deletions(-) (limited to 'lisp/emacs-lisp/cl-generic.el') 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 ) 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 -- cgit v1.2.3