aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Gutov2014-12-27 16:06:37 +0200
committerDmitry Gutov2014-12-27 16:07:31 +0200
commit6d14e0d361cfb3589874fe1b559e30b4fd3eb284 (patch)
treed358b0ef77e8e814113d274df1596c2489634d70
parent09d2e8477aa64308447395a0f01cfe5414619811 (diff)
downloademacs-6d14e0d361cfb3589874fe1b559e30b4fd3eb284.tar.gz
emacs-6d14e0d361cfb3589874fe1b559e30b4fd3eb284.zip
elisp-xref-find: Don't create buffers eagerly
* lisp/emacs-lisp/find-func.el (find-function-library): New function, extracted from `find-function-noselect'. * lisp/progmodes/elisp-mode.el (elisp--identifier-location): Fold back into `elisp--company-location'. (elisp--identifier-completion-table): Rename to `elisp--identifier-completion-table', and do not include just any symbols with a property list. (elisp-completion-at-point): Revert the 2014-12-25 change. (elisp--xref-identifier-file): New function. (elisp--xref-find-definitions): Use it. * lisp/progmodes/xref.el (xref-elisp-location): New class. (xref-make-elisp-location): New function. (xref-location-marker): New implementation.
-rw-r--r--lisp/ChangeLog20
-rw-r--r--lisp/emacs-lisp/find-func.el59
-rw-r--r--lisp/progmodes/elisp-mode.el90
-rw-r--r--lisp/progmodes/xref.el25
4 files changed, 129 insertions, 65 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 5a42e506d35..5829ec2fae5 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,23 @@
12014-12-27 Dmitry Gutov <dgutov@yandex.ru>
2
3 elisp-xref-find: Don't create buffers eagerly.
4
5 * progmodes/elisp-mode.el (elisp--identifier-location): Fold back
6 into `elisp--company-location'.
7 (elisp--identifier-completion-table): Rename to
8 `elisp--identifier-completion-table', and do not include just any
9 symbols with a property list.
10 (elisp-completion-at-point): Revert the 2014-12-25 change.
11 (elisp--xref-identifier-file): New function.
12 (elisp--xref-find-definitions): Use it.
13
14 * emacs-lisp/find-func.el (find-function-library): New function,
15 extracted from `find-function-noselect'.
16
17 * progmodes/xref.el (xref-elisp-location): New class.
18 (xref-make-elisp-location): New function.
19 (xref-location-marker): New implementation.
20
12014-12-27 Juri Linkov <juri@linkov.net> 212014-12-27 Juri Linkov <juri@linkov.net>
2 22
3 * minibuffer.el (minibuffer-completion-help): 23 * minibuffer.el (minibuffer-completion-help):
diff --git a/lisp/emacs-lisp/find-func.el b/lisp/emacs-lisp/find-func.el
index c372117b104..e1586a96716 100644
--- a/lisp/emacs-lisp/find-func.el
+++ b/lisp/emacs-lisp/find-func.el
@@ -311,6 +311,39 @@ The search is done in the source for library LIBRARY."
311 (cons (current-buffer) (point))) 311 (cons (current-buffer) (point)))
312 (cons (current-buffer) nil)))))))) 312 (cons (current-buffer) nil))))))))
313 313
314(defun find-function-library (function &optional lisp-only verbose)
315 "Return the library FUNCTION is defined in.
316
317If FUNCTION is a built-in function and LISP-ONLY is non-nil,
318signal an error.
319
320If VERBOSE is non-nil, and FUNCTION is an alias, display a
321message about the whole chain of aliases."
322 (let ((def (symbol-function (find-function-advised-original function)))
323 aliases)
324 ;; FIXME for completeness, it might be nice to print something like:
325 ;; foo (which is advised), which is an alias for bar (which is advised).
326 (while (symbolp def)
327 (or (eq def function)
328 (not verbose)
329 (if aliases
330 (setq aliases (concat aliases
331 (format ", which is an alias for `%s'"
332 (symbol-name def))))
333 (setq aliases (format "`%s' is an alias for `%s'"
334 function (symbol-name def)))))
335 (setq function (symbol-function (find-function-advised-original function))
336 def (symbol-function (find-function-advised-original function))))
337 (if aliases
338 (message "%s" aliases))
339 (cond
340 ((autoloadp def) (nth 1 def))
341 ((subrp def)
342 (if lisp-only
343 (error "%s is a built-in function" function))
344 (help-C-file-name def 'subr))
345 ((symbol-file function 'defun)))))
346
314;;;###autoload 347;;;###autoload
315(defun find-function-noselect (function &optional lisp-only) 348(defun find-function-noselect (function &optional lisp-only)
316 "Return a pair (BUFFER . POINT) pointing to the definition of FUNCTION. 349 "Return a pair (BUFFER . POINT) pointing to the definition of FUNCTION.
@@ -329,30 +362,8 @@ searched for in `find-function-source-path' if non-nil, otherwise
329in `load-path'." 362in `load-path'."
330 (if (not function) 363 (if (not function)
331 (error "You didn't specify a function")) 364 (error "You didn't specify a function"))
332 (let ((def (symbol-function (find-function-advised-original function))) 365 (let ((library (find-function-library function lisp-only t)))
333 aliases) 366 (find-function-search-for-symbol function nil library)))
334 ;; FIXME for completeness, it might be nice to print something like:
335 ;; foo (which is advised), which is an alias for bar (which is advised).
336 (while (symbolp def)
337 (or (eq def function)
338 (if aliases
339 (setq aliases (concat aliases
340 (format ", which is an alias for `%s'"
341 (symbol-name def))))
342 (setq aliases (format "`%s' is an alias for `%s'"
343 function (symbol-name def)))))
344 (setq function (symbol-function (find-function-advised-original function))
345 def (symbol-function (find-function-advised-original function))))
346 (if aliases
347 (message "%s" aliases))
348 (let ((library
349 (cond ((autoloadp def) (nth 1 def))
350 ((subrp def)
351 (if lisp-only
352 (error "%s is a built-in function" function))
353 (help-C-file-name def 'subr))
354 ((symbol-file function 'defun)))))
355 (find-function-search-for-symbol function nil library))))
356 367
357(defun find-function-read (&optional type) 368(defun find-function-read (&optional type)
358 "Read and return an interned symbol, defaulting to the one near point. 369 "Read and return an interned symbol, defaulting to the one near point.
diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el
index ef619f0899a..347560a484e 100644
--- a/lisp/progmodes/elisp-mode.el
+++ b/lisp/progmodes/elisp-mode.el
@@ -418,40 +418,19 @@ It can be quoted, or be inside a quoted form."
418 (match-string 0 doc)))) 418 (match-string 0 doc))))
419 419
420(declare-function find-library-name "find-func" (library)) 420(declare-function find-library-name "find-func" (library))
421 421(declare-function find-function-library "find-func" (function &optional l-o v))
422(defvar elisp--identifier-types '(defun defvar feature defface))
423
424(defun elisp--identifier-location (type sym)
425 (pcase (cons type sym)
426 (`(defun . ,(pred fboundp))
427 (find-definition-noselect sym nil))
428 (`(defvar . ,(pred boundp))
429 (find-definition-noselect sym 'defvar))
430 (`(defface . ,(pred facep))
431 (find-definition-noselect sym 'defface))
432 (`(feature . ,(pred featurep))
433 (require 'find-func)
434 (cons (find-file-noselect (find-library-name
435 (symbol-name sym)))
436 1))))
437 422
438(defun elisp--company-location (str) 423(defun elisp--company-location (str)
439 (catch 'res 424 (let ((sym (intern-soft str)))
440 (let ((sym (intern-soft str))) 425 (cond
441 (when sym 426 ((fboundp sym) (find-definition-noselect sym nil))
442 (dolist (type elisp--identifier-types) 427 ((boundp sym) (find-definition-noselect sym 'defvar))
443 (let ((loc (elisp--identifier-location type sym))) 428 ((featurep sym)
444 (and loc (throw 'res loc)))))))) 429 (require 'find-func)
445 430 (cons (find-file-noselect (find-library-name
446(defvar elisp--identifier-completion-table 431 (symbol-name sym)))
447 (apply-partially #'completion-table-with-predicate 432 0))
448 obarray 433 ((facep sym) (find-definition-noselect sym 'defface)))))
449 (lambda (sym)
450 (or (boundp sym)
451 (fboundp sym)
452 (featurep sym)
453 (symbol-plist sym)))
454 'strict))
455 434
456(defun elisp-completion-at-point () 435(defun elisp-completion-at-point ()
457 "Function used for `completion-at-point-functions' in `emacs-lisp-mode'." 436 "Function used for `completion-at-point-functions' in `emacs-lisp-mode'."
@@ -493,8 +472,13 @@ It can be quoted, or be inside a quoted form."
493 :company-docsig #'elisp--company-doc-string 472 :company-docsig #'elisp--company-doc-string
494 :company-location #'elisp--company-location)) 473 :company-location #'elisp--company-location))
495 ((elisp--form-quoted-p beg) 474 ((elisp--form-quoted-p beg)
496 ;; Don't include all symbols (bug#16646). 475 (list nil obarray
497 (list nil elisp--identifier-completion-table 476 ;; Don't include all symbols (bug#16646).
477 :predicate (lambda (sym)
478 (or (boundp sym)
479 (fboundp sym)
480 (featurep sym)
481 (symbol-plist sym)))
498 :annotation-function 482 :annotation-function
499 (lambda (str) (if (fboundp (intern-soft str)) " <f>")) 483 (lambda (str) (if (fboundp (intern-soft str)) " <f>"))
500 :company-doc-buffer #'elisp--company-doc-buffer 484 :company-doc-buffer #'elisp--company-doc-buffer
@@ -572,11 +556,12 @@ It can be quoted, or be inside a quoted form."
572 556
573;;; Xref backend 557;;; Xref backend
574 558
575(declare-function xref-make-buffer-location "xref" (buffer position)) 559(declare-function xref-make-elisp-location "xref" (symbol type file))
576(declare-function xref-make-bogus-location "xref" (message)) 560(declare-function xref-make-bogus-location "xref" (message))
577(declare-function xref-make "xref" (description location)) 561(declare-function xref-make "xref" (description location))
578 562
579(defun elisp-xref-find (action id) 563(defun elisp-xref-find (action id)
564 (require 'find-func)
580 (pcase action 565 (pcase action
581 (`definitions 566 (`definitions
582 (let ((sym (intern-soft id))) 567 (let ((sym (intern-soft id)))
@@ -585,16 +570,29 @@ It can be quoted, or be inside a quoted form."
585 (`apropos 570 (`apropos
586 (elisp--xref-find-apropos id)))) 571 (elisp--xref-find-apropos id))))
587 572
573(defun elisp--xref-identifier-file (type sym)
574 (pcase type
575 (`defun (when (fboundp sym)
576 (find-function-library sym)))
577 (`defvar (when (boundp sym)
578 (or (symbol-file sym 'defvar)
579 (help-C-file-name sym 'var))))
580 (`feature (when (featurep sym)
581 (find-library-name (symbol-name sym))))
582 (`defface (when (facep sym)
583 (symbol-file sym 'defface)))))
584
588(defun elisp--xref-find-definitions (symbol) 585(defun elisp--xref-find-definitions (symbol)
589 (save-excursion 586 (save-excursion
590 (let (lst) 587 (let (lst)
591 (dolist (type elisp--identifier-types) 588 (dolist (type '(feature defface defvar defun))
592 (let ((loc 589 (let ((loc
593 (condition-case err 590 (condition-case err
594 (let ((buf-pos (elisp--identifier-location type symbol))) 591 (let ((file (elisp--xref-identifier-file type symbol)))
595 (when buf-pos 592 (when file
596 (xref-make-buffer-location (car buf-pos) 593 (when (string-match-p "\\.elc\\'" file)
597 (or (cdr buf-pos) 1)))) 594 (setq file (substring file 0 -1)))
595 (xref-make-elisp-location symbol type file)))
598 (error 596 (error
599 (xref-make-bogus-location (error-message-string err)))))) 597 (xref-make-bogus-location (error-message-string err))))))
600 (when loc 598 (when loc
@@ -611,8 +609,18 @@ It can be quoted, or be inside a quoted form."
611 (push (elisp--xref-find-definitions sym) lst)) 609 (push (elisp--xref-find-definitions sym) lst))
612 (nreverse lst)))) 610 (nreverse lst))))
613 611
612(defvar elisp--xref-identifier-completion-table
613 (apply-partially #'completion-table-with-predicate
614 obarray
615 (lambda (sym)
616 (or (boundp sym)
617 (fboundp sym)
618 (featurep sym)
619 (facep sym)))
620 'strict))
621
614(defun elisp--xref-identifier-completion-table () 622(defun elisp--xref-identifier-completion-table ()
615 elisp--identifier-completion-table) 623 elisp--xref-identifier-completion-table)
616 624
617;;; Elisp Interaction mode 625;;; Elisp Interaction mode
618 626
diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el
index 21c0d6aa6a4..8221aebd871 100644
--- a/lisp/progmodes/xref.el
+++ b/lisp/progmodes/xref.el
@@ -136,6 +136,31 @@ actual location is not known.")
136 136
137(defmethod xref-location-group ((_ xref-bogus-location)) "(No location)") 137(defmethod xref-location-group ((_ xref-bogus-location)) "(No location)")
138 138
139;; This should be in elisp-mode.el, but it's preloaded, and we can't
140;; preload defclass and defmethod (at least, not yet).
141(defclass xref-elisp-location (xref-location)
142 ((symbol :type symbol :initarg :symbol)
143 (type :type symbol :initarg :type)
144 (file :type string :initarg :file
145 :reader xref-location-group))
146 :documentation "Location of an Emacs Lisp symbol definition.")
147
148(defun xref-make-elisp-location (symbol type file)
149 (make-instance 'xref-elisp-location :symbol symbol :type type :file file))
150
151(defmethod xref-location-marker ((l xref-elisp-location))
152 (with-slots (symbol type file) l
153 (let ((buffer-point
154 (pcase type
155 (`defun (find-function-search-for-symbol symbol nil file))
156 ((or `defvar `defface)
157 (find-function-search-for-symbol symbol type file))
158 (`feature
159 (cons (find-file-noselect file) 1)))))
160 (with-current-buffer (car buffer-point)
161 (goto-char (or (cdr buffer-point) (point-min)))
162 (point-marker)))))
163
139 164
140;;; Cross-reference 165;;; Cross-reference
141 166