xref-find-by-kind 2daeb3ca35f: xref-read-identifier: Avoid wrapping identifier predicates for elisp
Dmitry Gutov <[email protected]>
| Newsgroups | gmane.emacs.diffs |
|---|---|
| Message-ID | <[email protected]> |
branch: xref-find-by-kind commit 2daeb3ca35fb7c09b09cfea29c58070829b3a60a Author: Dmitry Gutov <[email protected]> Commit: Dmitry Gutov <[email protected]> xref-read-identifier: Avoid wrapping identifier predicates for elisp * lisp/progmodes/elisp-mode.el (xref-backend-xref-kinds): Use 'defun' as the kind symbol for functions, so we're able to distinguish nil values, making the "&optional kind" argument possible. (xref-backend-identifier-completion-predicate): Return either the previous default predicate (extracted from the completion table) or the predicate appropriate to KIND. Return functions symbols where possible rather than a big lambda with cl-ecase inside. Both changes in theory improve performance; not measured. (xref-backend-identifier-completion-table): Just return obarray. * lisp/progmodes/xref.el (xref-backend-identifier-completion-predicate): Rename from 'xref-backend-identifier-kind-predicate' and make KIND optional. (xref-read-identifier): Accept KIND instead of opaque PREDICATE, call the new generic function. (xref-find-by-kind): Move that call from here, remove outdated commentary. --- lisp/progmodes/elisp-mode.el | 61 +++++++++++++++++++++----------------------- lisp/progmodes/xref.el | 22 ++++++++-------- 2 files changed, 41 insertions(+), 42 deletions(-) diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el index c303aefa75b..449683a6231 100644 --- a/lisp/progmodes/elisp-mode.el +++ b/lisp/progmodes/elisp-mode.el @@ -1666,7 +1666,7 @@ namespace but with lower confidence." xrefs)) (cl-defmethod xref-backend-xref-kinds ((_backend (eql 'elisp))) - '((:kind nil :name "function" :key ?f) + '((:kind defun :name "function" :key ?f) (:kind defvar :name "variable" :key ?v) (:kind cl-defgeneric :name "generic function" :key ?g) (:kind cl-defmethod :name "generic method" :key ?m) @@ -1683,7 +1683,7 @@ namespace but with lower confidence." (let* ((defs (elisp--xref-find-definitions sym))) (cl-loop for d in defs for def-kind = (xref-elisp-location-type (xref-item-location d)) - when (if kind + when (if (not (eq kind 'defun)) (eq def-kind kind) (memq def-kind '( nil cl-defgeneric cl-defmethod define-type defalias))) @@ -1699,38 +1699,35 @@ namespace but with lower confidence." (push (elisp--xref-find-definitions sym) lst)) (nreverse lst)))) -(defvar elisp--xref-identifier-completion-table - (apply-partially #'completion-table-with-predicate - obarray - (lambda (sym) - (or (boundp sym) - (fboundp sym) - (featurep sym) - (facep sym))) - 'strict)) - (cl-defmethod xref-backend-identifier-completion-table ((_backend (eql 'elisp))) - elisp--xref-identifier-completion-table) - -(cl-defmethod xref-backend-identifier-kind-predicate ((_backend (eql 'elisp)) kind) - (lambda (identifier) - (let ((sym (intern-soft identifier))) - (cl-ecase kind - ((nil) (fboundp sym)) - (defvar (boundp sym)) - (cl-defgeneric (cl--generic sym)) - (cl-defmethod (and (cl--generic sym) - (cl--generic-method-table (cl--generic sym)))) - (define-type (and (functionp sym) - (let ((doc (documentation sym t))) - (and doc - (string-search "Constructor for objects of type" doc))))) - (defalias (and (symbolp sym) - (symbol-function sym) - (symbolp (symbol-function sym)))) - (defface (facep sym)) - (feature (featurep sym)))))) + obarray) + +(cl-defmethod xref-backend-identifier-completion-predicate ((_backend (eql 'elisp)) + &optional kind) + (if (not kind) + (lambda (sym) + (or (boundp sym) + (fboundp sym) + (featurep sym) + (facep sym))) + (cl-ecase kind + (defun #'fboundp) + (defvar #'boundp) + (cl-defgeneric #'cl--generic) + (cl-defmethod + (lambda (sym) + (and (cl--generic sym) + (cl--generic-method-table (cl--generic sym))))) + (define-type + (lambda (sym) + (and (functionp sym) + (let ((doc (documentation sym t))) + (and doc + (string-search "Constructor for objects of type" doc)))))) + (defalias #'function-alias-p) + (defface #'facep) + (feature #'featurep)))) (cl-defstruct (xref-elisp-location (:constructor xref-make-elisp-location (symbol type file))) diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el index 8b404c16e2c..5496c5498a1 100644 --- a/lisp/progmodes/xref.el +++ b/lisp/progmodes/xref.el @@ -312,8 +312,12 @@ recognize and then delegate the work to an external process." "Return the completion table for identifiers." nil) -(cl-defgeneric xref-backend-identifier-kind-predicate (_backend _kind) - "Return the completion predicate for identifiers based on KIND." +(cl-defgeneric xref-backend-identifier-completion-predicate (_backend + &optional _kind) + "Return the predicate for identifier completion. +The argument KIND will be provided when the caller intends to narrow +down the search. The backend can use it to narrow down to only +identifiers that have xrefs belonging to KIND." nil) (cl-defgeneric xref-backend-identifier-completion-ignore-case (_backend) @@ -1701,14 +1705,16 @@ The meanings of both arguments are the same as documented in (not (memq command (cdr xref-prompt-for-identifier))) (memq command xref-prompt-for-identifier)))) -(defun xref-read-identifier (prompt &optional predicate) +(defun xref-read-identifier (prompt &optional kind) "Return the identifier at point or read it from the minibuffer. Reads and returns the identifier to use as input for the command being executed now. If the current command should prompt, as defined in `xref-prompt-for-identifier', it uses the result of `xref-backend-identifier-at-point'. Otherwise, it reads with completion -from `xref-backend-identifier-completion-table'." +from the table returned by `xref-backend-identifier-completion-table', +together with `xref-backend-identifier-completion-predicate'. +The argument KIND is passed on to the latter function." (let* ((backend (xref-find-backend)) (def (xref-backend-identifier-at-point backend)) (completion-ignore-case @@ -1730,7 +1736,7 @@ from `xref-backend-identifier-completion-table'." def) prompt)) (xref-backend-identifier-completion-table backend) - predicate + (xref-backend-identifier-completion-predicate backend kind) nil nil 'xref--read-identifier-history def t))) (if (equal id "") @@ -1842,14 +1848,10 @@ When called programmatically, KIND should be one of supported symbols." (kind (plist-get desc :kind))) (unless desc (user-error "Have to choose the kind")) (list - ;; For completeness, we can also add a specialized - ;; "identifier completion table for kind". But - ;; probably only the elisp backend would have it. (xref-read-identifier (format-message (or (plist-get desc :prompt-format) "Find %s") (plist-get desc :name)) - (xref-backend-identifier-kind-predicate (xref-find-backend) - kind)) + kind) kind))) (let ((kind-desc (cl-find kind (xref-backend-xref-kinds (xref-find-backend)) :key (lambda (desc) (plist-get desc :kind)))))