diff options
| author | Stephen Leake | 2015-08-13 12:54:39 -0500 |
|---|---|---|
| committer | Stephen Leake | 2015-08-13 13:16:47 -0500 |
| commit | 0382fd42c6979bbedc9230b789503258a5e963eb (patch) | |
| tree | 989b157edeb659f5e0b2b3e8b884ec143dcbe3fd | |
| parent | 9c13a81a9e1aa74901cd958d7adb3ca71966dbef (diff) | |
| download | emacs-0382fd42c6979bbedc9230b789503258a5e963eb.tar.gz emacs-0382fd42c6979bbedc9230b789503258a5e963eb.zip | |
xref-find-definitions: Exclude more generic function items.
* lisp/emacs-lisp/cl-generic.el (cl--generic-search-method): Add doc string.
(cl--generic-find-defgeneric-regexp): New.
(find-function-regexp-alist): Add it.
* lisp/emacs-lisp/find-func.el (find-feature-regexp): Move here from
elisp-mode.el, change to search for ";;; Code:"
(find-alias-regexp): Move here from elisp-mode.el, cleaned up.
(find-function-regexp-alist): Add them.
* lisp/progmodes/elisp-mode.el:
(elisp--xref-format, elisp--xref-format-extra): Change back to defvar due
to bug#21237.
(elisp--xref-find-definitions): Exclude co-located default methods for
generic functions. Also exclude implicitly declared defgeneric.
(elisp--xref-find-definitions): Handle C source properly. Exclude minor
mode variables defined by 'define-minor-mode'.
* test/automated/elisp-mode-tests.el: Declare generic functions, add
tests for them.
(xref-elisp-test-run): Fix bug.
(emacs-test-dir): Improve initial value.
(find-defs-defun-defvar-el): Don't expect defvar.
(find-defs-feature-el): Match change to find-feature-regexp.
| -rw-r--r-- | lisp/emacs-lisp/cl-generic.el | 8 | ||||
| -rw-r--r-- | lisp/emacs-lisp/find-func.el | 26 | ||||
| -rw-r--r-- | lisp/progmodes/elisp-mode.el | 115 | ||||
| -rw-r--r-- | test/automated/elisp-mode-tests.el | 170 |
4 files changed, 264 insertions, 55 deletions
diff --git a/lisp/emacs-lisp/cl-generic.el b/lisp/emacs-lisp/cl-generic.el index 63cd9108410..a138697a18b 100644 --- a/lisp/emacs-lisp/cl-generic.el +++ b/lisp/emacs-lisp/cl-generic.el | |||
| @@ -791,6 +791,8 @@ Can only be used from within the lexical body of a primary or around method." | |||
| 791 | ;;; Add support for describe-function | 791 | ;;; Add support for describe-function |
| 792 | 792 | ||
| 793 | (defun cl--generic-search-method (met-name) | 793 | (defun cl--generic-search-method (met-name) |
| 794 | "For `find-function-regexp-alist'. Searches for a cl-defmethod. | ||
| 795 | MET-NAME is a cons (SYMBOL . SPECIALIZERS)." | ||
| 794 | (let ((base-re (concat "(\\(?:cl-\\)?defmethod[ \t]+" | 796 | (let ((base-re (concat "(\\(?:cl-\\)?defmethod[ \t]+" |
| 795 | (regexp-quote (format "%s" (car met-name))) | 797 | (regexp-quote (format "%s" (car met-name))) |
| 796 | "\\_>"))) | 798 | "\\_>"))) |
| @@ -806,11 +808,15 @@ Can only be used from within the lexical body of a primary or around method." | |||
| 806 | nil t) | 808 | nil t) |
| 807 | (re-search-forward base-re nil t)))) | 809 | (re-search-forward base-re nil t)))) |
| 808 | 810 | ||
| 811 | ;; WORKAROUND: This can't be a defconst due to bug#21237. | ||
| 812 | (defvar cl--generic-find-defgeneric-regexp "(\\(?:cl-\\)?defgeneric[ \t]+%s\\>") | ||
| 809 | 813 | ||
| 810 | (with-eval-after-load 'find-func | 814 | (with-eval-after-load 'find-func |
| 811 | (defvar find-function-regexp-alist) | 815 | (defvar find-function-regexp-alist) |
| 812 | (add-to-list 'find-function-regexp-alist | 816 | (add-to-list 'find-function-regexp-alist |
| 813 | `(cl-defmethod . ,#'cl--generic-search-method))) | 817 | `(cl-defmethod . ,#'cl--generic-search-method)) |
| 818 | (add-to-list 'find-function-regexp-alist | ||
| 819 | `(cl-defgeneric . cl--generic-find-defgeneric-regexp))) | ||
| 814 | 820 | ||
| 815 | (defun cl--generic-method-info (method) | 821 | (defun cl--generic-method-info (method) |
| 816 | (let* ((specializers (cl--generic-method-specializers method)) | 822 | (let* ((specializers (cl--generic-method-specializers method)) |
diff --git a/lisp/emacs-lisp/find-func.el b/lisp/emacs-lisp/find-func.el index cd23cd77f4a..4dc0596de66 100644 --- a/lisp/emacs-lisp/find-func.el +++ b/lisp/emacs-lisp/find-func.el | |||
| @@ -100,10 +100,34 @@ Please send improvements and fixes to the maintainer." | |||
| 100 | :group 'find-function | 100 | :group 'find-function |
| 101 | :version "22.1") | 101 | :version "22.1") |
| 102 | 102 | ||
| 103 | (defcustom find-feature-regexp | ||
| 104 | (concat ";;; Code:") | ||
| 105 | "The regexp used by `xref-find-definitions' when searching for a feature definition. | ||
| 106 | Note it must contain a `%s' at the place where `format' | ||
| 107 | should insert the feature name." | ||
| 108 | ;; We search for ";;; Code" rather than (feature '%s) because the | ||
| 109 | ;; former is near the start of the code, and the latter is very | ||
| 110 | ;; uninteresting. If the regexp is not found, just goes to | ||
| 111 | ;; (point-min), which is acceptable in this case. | ||
| 112 | :type 'regexp | ||
| 113 | :group 'xref | ||
| 114 | :version "25.0") | ||
| 115 | |||
| 116 | (defcustom find-alias-regexp | ||
| 117 | "(defalias +'%s" | ||
| 118 | "The regexp used by `xref-find-definitions' to search for an alias definition. | ||
| 119 | Note it must contain a `%s' at the place where `format' | ||
| 120 | should insert the feature name." | ||
| 121 | :type 'regexp | ||
| 122 | :group 'xref | ||
| 123 | :version "25.0") | ||
| 124 | |||
| 103 | (defvar find-function-regexp-alist | 125 | (defvar find-function-regexp-alist |
| 104 | '((nil . find-function-regexp) | 126 | '((nil . find-function-regexp) |
| 105 | (defvar . find-variable-regexp) | 127 | (defvar . find-variable-regexp) |
| 106 | (defface . find-face-regexp)) | 128 | (defface . find-face-regexp) |
| 129 | (feature . find-feature-regexp) | ||
| 130 | (defalias . find-alias-regexp)) | ||
| 107 | "Alist mapping definition types into regexp variables. | 131 | "Alist mapping definition types into regexp variables. |
| 108 | Each regexp variable's value should actually be a format string | 132 | Each regexp variable's value should actually be a format string |
| 109 | to be used to substitute the desired symbol name into the regexp. | 133 | to be used to substitute the desired symbol name into the regexp. |
diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el index 7ac5a5cb778..81314574672 100644 --- a/lisp/progmodes/elisp-mode.el +++ b/lisp/progmodes/elisp-mode.el | |||
| @@ -604,40 +604,23 @@ It can be quoted, or be inside a quoted form." | |||
| 604 | (`apropos | 604 | (`apropos |
| 605 | (elisp--xref-find-apropos id)))) | 605 | (elisp--xref-find-apropos id)))) |
| 606 | 606 | ||
| 607 | (defconst elisp--xref-format | 607 | ;; WORKAROUND: This is nominally a constant, but the text properities |
| 608 | ;; are not preserved thru dump if use defconst. See bug#21237 | ||
| 609 | (defvar elisp--xref-format | ||
| 608 | (let ((str "(%s %s)")) | 610 | (let ((str "(%s %s)")) |
| 609 | (put-text-property 1 3 'face 'font-lock-keyword-face str) | 611 | (put-text-property 1 3 'face 'font-lock-keyword-face str) |
| 610 | (put-text-property 4 6 'face 'font-lock-function-name-face str) | 612 | (put-text-property 4 6 'face 'font-lock-function-name-face str) |
| 611 | str)) | 613 | str)) |
| 612 | 614 | ||
| 613 | (defconst elisp--xref-format-extra | 615 | ;; WORKAROUND: This is nominally a constant, but the text properities |
| 616 | ;; are not preserved thru dump if use defconst. See bug#21237 | ||
| 617 | (defvar elisp--xref-format-extra | ||
| 614 | (let ((str "(%s %s %s)")) | 618 | (let ((str "(%s %s %s)")) |
| 615 | (put-text-property 1 3 'face 'font-lock-keyword-face str) | 619 | (put-text-property 1 3 'face 'font-lock-keyword-face str) |
| 616 | (put-text-property 4 6 'face 'font-lock-function-name-face str) | 620 | (put-text-property 4 6 'face 'font-lock-function-name-face str) |
| 617 | str)) | 621 | str)) |
| 618 | 622 | ||
| 619 | (defcustom find-feature-regexp | 623 | (defvar find-feature-regexp) |
| 620 | (concat "(provide +'%s)") | ||
| 621 | "The regexp used by `xref-find-definitions' to search for a feature definition. | ||
| 622 | Note it must contain a `%s' at the place where `format' | ||
| 623 | should insert the feature name." | ||
| 624 | :type 'regexp | ||
| 625 | :group 'xref | ||
| 626 | :version "25.0") | ||
| 627 | |||
| 628 | (defcustom find-alias-regexp | ||
| 629 | "(\\(defalias +'\\|def\\(const\\|face\\) +\\)%s" | ||
| 630 | "The regexp used by `xref-find-definitions' to search for an alias definition. | ||
| 631 | Note it must contain a `%s' at the place where `format' | ||
| 632 | should insert the feature name." | ||
| 633 | :type 'regexp | ||
| 634 | :group 'xref | ||
| 635 | :version "25.0") | ||
| 636 | |||
| 637 | (with-eval-after-load 'find-func | ||
| 638 | (defvar find-function-regexp-alist) | ||
| 639 | (add-to-list 'find-function-regexp-alist (cons 'feature 'find-feature-regexp)) | ||
| 640 | (add-to-list 'find-function-regexp-alist (cons 'defalias 'find-alias-regexp))) | ||
| 641 | 624 | ||
| 642 | (defun elisp--xref-make-xref (type symbol file &optional summary) | 625 | (defun elisp--xref-make-xref (type symbol file &optional summary) |
| 643 | "Return an xref for TYPE SYMBOL in FILE. | 626 | "Return an xref for TYPE SYMBOL in FILE. |
| @@ -683,9 +666,10 @@ otherwise build the summary from TYPE and SYMBOL." | |||
| 683 | (when file | 666 | (when file |
| 684 | (cond | 667 | (cond |
| 685 | ((eq file 'C-source) | 668 | ((eq file 'C-source) |
| 686 | ;; First call to find-lisp-object-file-name (for this | 669 | ;; First call to find-lisp-object-file-name for an object |
| 687 | ;; symbol?); C-source has not been cached yet. | 670 | ;; defined in C; the doc strings from the C source have |
| 688 | ;; Second call will return "src/*.c" in file; handled by 't' case below. | 671 | ;; not been loaded yet. Second call will return "src/*.c" |
| 672 | ;; in file; handled by 't' case below. | ||
| 689 | (push (elisp--xref-make-xref nil symbol (help-C-file-name (symbol-function symbol) 'subr)) xrefs)) | 673 | (push (elisp--xref-make-xref nil symbol (help-C-file-name (symbol-function symbol) 'subr)) xrefs)) |
| 690 | 674 | ||
| 691 | ((and (setq doc (documentation symbol t)) | 675 | ((and (setq doc (documentation symbol t)) |
| @@ -704,17 +688,42 @@ otherwise build the summary from TYPE and SYMBOL." | |||
| 704 | )) | 688 | )) |
| 705 | 689 | ||
| 706 | ((setq generic (cl--generic symbol)) | 690 | ((setq generic (cl--generic symbol)) |
| 691 | ;; A generic function. If there is a default method, it | ||
| 692 | ;; will appear in the method table, with no | ||
| 693 | ;; specializers. | ||
| 694 | ;; | ||
| 695 | ;; If the default method is declared by the cl-defgeneric | ||
| 696 | ;; declaration, it will have the same location as teh | ||
| 697 | ;; cl-defgeneric, so we want to exclude it from the | ||
| 698 | ;; result. In this case, it will have a null doc | ||
| 699 | ;; string. User declarations of default methods may also | ||
| 700 | ;; have null doc strings, but we hope that is | ||
| 701 | ;; rare. Perhaps this hueristic will discourage that. | ||
| 707 | (dolist (method (cl--generic-method-table generic)) | 702 | (dolist (method (cl--generic-method-table generic)) |
| 708 | (let* ((info (cl--generic-method-info method)) | 703 | (let* ((info (cl--generic-method-info method));; qual-string combined-args doconly |
| 709 | (met-name (cons symbol (cl--generic-method-specializers method))) | 704 | (specializers (cl--generic-method-specializers method)) |
| 710 | (descr (format elisp--xref-format-extra 'cl-defmethod symbol (nth 1 info))) | 705 | (met-name (cons symbol specializers)) |
| 711 | (file (find-lisp-object-file-name met-name 'cl-defmethod))) | 706 | (file (find-lisp-object-file-name met-name 'cl-defmethod))) |
| 712 | (when file | 707 | (when (and file |
| 713 | (push (elisp--xref-make-xref 'cl-defmethod met-name file descr) xrefs)) | 708 | (or specializers ;; default method has null specializers |
| 709 | (nth 2 info))) ;; assuming only co-located default has null doc string | ||
| 710 | (if specializers | ||
| 711 | (let ((summary (format elisp--xref-format-extra 'cl-defmethod symbol (nth 1 info)))) | ||
| 712 | (push (elisp--xref-make-xref 'cl-defmethod met-name file summary) xrefs)) | ||
| 713 | |||
| 714 | (let ((summary (format elisp--xref-format-extra 'cl-defmethod symbol "()"))) | ||
| 715 | (push (elisp--xref-make-xref 'cl-defmethod met-name file summary) xrefs)))) | ||
| 714 | )) | 716 | )) |
| 715 | 717 | ||
| 716 | (let ((descr (format elisp--xref-format 'cl-defgeneric symbol))) | 718 | (if (and (setq doc (documentation symbol t)) |
| 717 | (push (elisp--xref-make-xref nil symbol file descr) xrefs)) | 719 | ;; This doc string is created somewhere in |
| 720 | ;; cl--generic-make-function for an implicit | ||
| 721 | ;; defgeneric. | ||
| 722 | (string-match "\n\n(fn ARG &rest ARGS)" doc)) | ||
| 723 | ;; This symbol is an implicitly defined defgeneric, so | ||
| 724 | ;; don't return it. | ||
| 725 | nil | ||
| 726 | (push (elisp--xref-make-xref 'cl-defgeneric symbol file) xrefs)) | ||
| 718 | ) | 727 | ) |
| 719 | 728 | ||
| 720 | (t | 729 | (t |
| @@ -722,11 +731,43 @@ otherwise build the summary from TYPE and SYMBOL." | |||
| 722 | )))) | 731 | )))) |
| 723 | 732 | ||
| 724 | (when (boundp symbol) | 733 | (when (boundp symbol) |
| 734 | ;; A variable | ||
| 725 | (let ((file (find-lisp-object-file-name symbol 'defvar))) | 735 | (let ((file (find-lisp-object-file-name symbol 'defvar))) |
| 726 | (when file | 736 | (when file |
| 727 | (when (eq file 'C-source) | 737 | (cond |
| 728 | (setq file (help-C-file-name symbol 'var))) | 738 | ((eq file 'C-source) |
| 729 | (push (elisp--xref-make-xref 'defvar symbol file) xrefs)))) | 739 | ;; The doc strings from the C source have not been loaded |
| 740 | ;; yet; help-C-file-name does that. Second call will | ||
| 741 | ;; return "src/*.c" in file; handled below. | ||
| 742 | (push (elisp--xref-make-xref 'defvar symbol (help-C-file-name symbol 'var)) xrefs)) | ||
| 743 | |||
| 744 | ((string= "src/" (substring file 0 4)) | ||
| 745 | ;; The variable is defined in a C source file; don't check | ||
| 746 | ;; for define-minor-mode. | ||
| 747 | (push (elisp--xref-make-xref 'defvar symbol file) xrefs)) | ||
| 748 | |||
| 749 | ((memq symbol minor-mode-list) | ||
| 750 | ;; The symbol is a minor mode. These should be defined by | ||
| 751 | ;; "define-minor-mode", which means the variable and the | ||
| 752 | ;; function are declared in the same place. So we return only | ||
| 753 | ;; the function, arbitrarily. | ||
| 754 | ;; | ||
| 755 | ;; There is an exception, when the variable is defined in C | ||
| 756 | ;; code, as for abbrev-mode. | ||
| 757 | ;; | ||
| 758 | ;; IMPROVEME: If the user is searching for the identifier at | ||
| 759 | ;; point, we can determine whether it is a variable or | ||
| 760 | ;; function by looking at the source code near point. | ||
| 761 | ;; | ||
| 762 | ;; IMPROVEME: The user may actually be asking "do any | ||
| 763 | ;; variables by this name exist"; we need a way to specify | ||
| 764 | ;; that. | ||
| 765 | nil) | ||
| 766 | |||
| 767 | (t | ||
| 768 | (push (elisp--xref-make-xref 'defvar symbol file) xrefs)) | ||
| 769 | |||
| 770 | )))) | ||
| 730 | 771 | ||
| 731 | (when (featurep symbol) | 772 | (when (featurep symbol) |
| 732 | (let ((file (ignore-errors | 773 | (let ((file (ignore-errors |
diff --git a/test/automated/elisp-mode-tests.el b/test/automated/elisp-mode-tests.el index 9b4014a8a55..47212e919c6 100644 --- a/test/automated/elisp-mode-tests.el +++ b/test/automated/elisp-mode-tests.el | |||
| @@ -177,8 +177,8 @@ | |||
| 177 | 177 | ||
| 178 | 178 | ||
| 179 | (defun xref-elisp-test-run (xrefs expecteds) | 179 | (defun xref-elisp-test-run (xrefs expecteds) |
| 180 | (should (= (length xrefs) (length expecteds))) | ||
| 180 | (while xrefs | 181 | (while xrefs |
| 181 | (should (= (length xrefs) (length expecteds))) | ||
| 182 | (let ((xref (pop xrefs)) | 182 | (let ((xref (pop xrefs)) |
| 183 | (expected (pop expecteds))) | 183 | (expected (pop expecteds))) |
| 184 | 184 | ||
| @@ -204,8 +204,9 @@ to (xref-elisp-test-descr-to-target xref)." | |||
| 204 | 204 | ||
| 205 | ;; When tests are run from the Makefile, 'default-directory' is $HOME, | 205 | ;; When tests are run from the Makefile, 'default-directory' is $HOME, |
| 206 | ;; so we must provide this dir to expand-file-name in the expected | 206 | ;; so we must provide this dir to expand-file-name in the expected |
| 207 | ;; results. The Makefile sets EMACS_TEST_DIRECTORY. | 207 | ;; results. This also allows running these tests from other |
| 208 | (defconst emacs-test-dir (getenv "EMACS_TEST_DIRECTORY")) | 208 | ;; directories. |
| 209 | (defconst emacs-test-dir (file-name-directory (or load-file-name (buffer-file-name)))) | ||
| 209 | 210 | ||
| 210 | ;; alphabetical by test name | 211 | ;; alphabetical by test name |
| 211 | 212 | ||
| @@ -244,12 +245,144 @@ to (xref-elisp-test-descr-to-target xref)." | |||
| 244 | 245 | ||
| 245 | ;; FIXME: defconst | 246 | ;; FIXME: defconst |
| 246 | 247 | ||
| 248 | ;; FIXME: eieio defclass | ||
| 249 | |||
| 250 | ;; Possible ways of defining the default method implementation for a | ||
| 251 | ;; generic function. We declare these here, so we know we cover all | ||
| 252 | ;; cases, and we don't rely on other code not changing. | ||
| 253 | ;; | ||
| 254 | ;; When the generic and default method are declared in the same place, | ||
| 255 | ;; elisp--xref-find-definitions only returns one. | ||
| 256 | |||
| 257 | (cl-defstruct (xref-elisp-root-type) | ||
| 258 | slot-1) | ||
| 259 | |||
| 260 | (cl-defgeneric xref-elisp-generic-no-methods () | ||
| 261 | "doc string no-methods" | ||
| 262 | ;; No default implementation, no methods, but fboundp is true for | ||
| 263 | ;; this symbol; it calls cl-no-applicable-method | ||
| 264 | ) | ||
| 265 | |||
| 266 | (cl-defmethod xref-elisp-generic-no-default ((this xref-elisp-root-type)) | ||
| 267 | "doc string no-default xref-elisp-root-type" | ||
| 268 | "non-default for no-default") | ||
| 269 | |||
| 270 | ;; defgeneric after defmethod in file to ensure the fallback search | ||
| 271 | ;; method of just looking for the function name will fail. | ||
| 272 | (cl-defgeneric xref-elisp-generic-no-default () | ||
| 273 | "doc string no-default generic" | ||
| 274 | ;; No default implementation; this function calls the cl-generic | ||
| 275 | ;; dispatching code. | ||
| 276 | ) | ||
| 277 | |||
| 278 | (cl-defgeneric xref-elisp-generic-co-located-default () | ||
| 279 | "doc string co-located-default generic" | ||
| 280 | "co-located default") | ||
| 281 | |||
| 282 | (cl-defmethod xref-elisp-generic-co-located-default ((this xref-elisp-root-type)) | ||
| 283 | "doc string co-located-default xref-elisp-root-type" | ||
| 284 | "non-default for co-located-default") | ||
| 285 | |||
| 286 | (cl-defgeneric xref-elisp-generic-separate-default () | ||
| 287 | "doc string separate-default generic" | ||
| 288 | ;; default implementation provided separately | ||
| 289 | ) | ||
| 290 | |||
| 291 | (cl-defmethod xref-elisp-generic-separate-default () | ||
| 292 | "doc string separate-default default" | ||
| 293 | "separate default") | ||
| 294 | |||
| 295 | (cl-defmethod xref-elisp-generic-separate-default ((this xref-elisp-root-type)) | ||
| 296 | "doc string separate-default xref-elisp-root-type" | ||
| 297 | "non-default for separate-default") | ||
| 298 | |||
| 299 | (cl-defmethod xref-elisp-generic-implicit-generic () | ||
| 300 | "doc string implict-generic default" | ||
| 301 | "default for implicit generic") | ||
| 302 | |||
| 303 | (cl-defmethod xref-elisp-generic-implicit-generic ((this xref-elisp-root-type)) | ||
| 304 | "doc string implict-generic xref-elisp-root-type" | ||
| 305 | "non-default for implicit generic") | ||
| 306 | |||
| 307 | |||
| 308 | (xref-elisp-deftest find-defs-defgeneric-no-methods | ||
| 309 | (elisp--xref-find-definitions 'xref-elisp-generic-no-methods) | ||
| 310 | (list | ||
| 311 | (xref-make "(cl-defgeneric xref-elisp-generic-no-methods)" | ||
| 312 | (xref-make-elisp-location | ||
| 313 | 'xref-elisp-generic-no-methods 'cl-defgeneric | ||
| 314 | (expand-file-name "elisp-mode-tests.el" emacs-test-dir))) | ||
| 315 | )) | ||
| 316 | |||
| 317 | (xref-elisp-deftest find-defs-defgeneric-no-default | ||
| 318 | (elisp--xref-find-definitions 'xref-elisp-generic-no-default) | ||
| 319 | (list | ||
| 320 | (xref-make "(cl-defgeneric xref-elisp-generic-no-default)" | ||
| 321 | (xref-make-elisp-location | ||
| 322 | 'xref-elisp-generic-no-default 'cl-defgeneric | ||
| 323 | (expand-file-name "elisp-mode-tests.el" emacs-test-dir))) | ||
| 324 | (xref-make "(cl-defmethod xref-elisp-generic-no-default ((this xref-elisp-root-type)))" | ||
| 325 | (xref-make-elisp-location | ||
| 326 | '(xref-elisp-generic-no-default xref-elisp-root-type) 'cl-defmethod | ||
| 327 | (expand-file-name "elisp-mode-tests.el" emacs-test-dir))) | ||
| 328 | )) | ||
| 329 | |||
| 330 | (xref-elisp-deftest find-defs-defgeneric-co-located-default | ||
| 331 | (elisp--xref-find-definitions 'xref-elisp-generic-co-located-default) | ||
| 332 | (list | ||
| 333 | (xref-make "(cl-defgeneric xref-elisp-generic-co-located-default)" | ||
| 334 | (xref-make-elisp-location | ||
| 335 | 'xref-elisp-generic-co-located-default 'cl-defgeneric | ||
| 336 | (expand-file-name "elisp-mode-tests.el" emacs-test-dir))) | ||
| 337 | (xref-make "(cl-defmethod xref-elisp-generic-co-located-default ((this xref-elisp-root-type)))" | ||
| 338 | (xref-make-elisp-location | ||
| 339 | '(xref-elisp-generic-co-located-default xref-elisp-root-type) 'cl-defmethod | ||
| 340 | (expand-file-name "elisp-mode-tests.el" emacs-test-dir))) | ||
| 341 | )) | ||
| 342 | |||
| 343 | (xref-elisp-deftest find-defs-defgeneric-separate-default | ||
| 344 | (elisp--xref-find-definitions 'xref-elisp-generic-separate-default) | ||
| 345 | (list | ||
| 346 | (xref-make "(cl-defgeneric xref-elisp-generic-separate-default)" | ||
| 347 | (xref-make-elisp-location | ||
| 348 | 'xref-elisp-generic-separate-default 'cl-defgeneric | ||
| 349 | (expand-file-name "elisp-mode-tests.el" emacs-test-dir))) | ||
| 350 | (xref-make "(cl-defmethod xref-elisp-generic-separate-default ())" | ||
| 351 | (xref-make-elisp-location | ||
| 352 | '(xref-elisp-generic-separate-default) 'cl-defmethod | ||
| 353 | (expand-file-name "elisp-mode-tests.el" emacs-test-dir))) | ||
| 354 | |||
| 355 | (xref-make "(cl-defmethod xref-elisp-generic-separate-default ((this xref-elisp-root-type)))" | ||
| 356 | (xref-make-elisp-location | ||
| 357 | '(xref-elisp-generic-separate-default xref-elisp-root-type) 'cl-defmethod | ||
| 358 | (expand-file-name "elisp-mode-tests.el" emacs-test-dir))) | ||
| 359 | )) | ||
| 360 | |||
| 361 | (xref-elisp-deftest find-defs-defgeneric-implicit-generic | ||
| 362 | (elisp--xref-find-definitions 'xref-elisp-generic-implicit-generic) | ||
| 363 | (list | ||
| 364 | (xref-make "(cl-defmethod xref-elisp-generic-implicit-generic ())" | ||
| 365 | (xref-make-elisp-location | ||
| 366 | '(xref-elisp-generic-implicit-generic) 'cl-defmethod | ||
| 367 | (expand-file-name "elisp-mode-tests.el" emacs-test-dir))) | ||
| 368 | (xref-make "(cl-defmethod xref-elisp-generic-implicit-generic ((this xref-elisp-root-type)))" | ||
| 369 | (xref-make-elisp-location | ||
| 370 | '(xref-elisp-generic-implicit-generic xref-elisp-root-type) 'cl-defmethod | ||
| 371 | (expand-file-name "elisp-mode-tests.el" emacs-test-dir))) | ||
| 372 | )) | ||
| 373 | |||
| 374 | ;; Test that we handle more than one method | ||
| 375 | |||
| 376 | ;; When run from the Makefile, etags is not loaded at compile time, | ||
| 377 | ;; but it is by the time this test is run. interactively; don't fail | ||
| 378 | ;; for that. | ||
| 379 | (require 'etags) | ||
| 247 | (xref-elisp-deftest find-defs-defgeneric-el | 380 | (xref-elisp-deftest find-defs-defgeneric-el |
| 248 | (elisp--xref-find-definitions 'xref-location-marker) | 381 | (elisp--xref-find-definitions 'xref-location-marker) |
| 249 | (list | 382 | (list |
| 250 | (xref-make "(cl-defgeneric xref-location-marker)" | 383 | (xref-make "(cl-defgeneric xref-location-marker)" |
| 251 | (xref-make-elisp-location | 384 | (xref-make-elisp-location |
| 252 | 'xref-location-marker nil | 385 | 'xref-location-marker 'cl-defgeneric |
| 253 | (expand-file-name "../../lisp/progmodes/xref.el" emacs-test-dir))) | 386 | (expand-file-name "../../lisp/progmodes/xref.el" emacs-test-dir))) |
| 254 | (xref-make "(cl-defmethod xref-location-marker ((l xref-elisp-location)))" | 387 | (xref-make "(cl-defmethod xref-location-marker ((l xref-elisp-location)))" |
| 255 | (xref-make-elisp-location | 388 | (xref-make-elisp-location |
| @@ -267,7 +400,10 @@ to (xref-elisp-test-descr-to-target xref)." | |||
| 267 | (xref-make-elisp-location | 400 | (xref-make-elisp-location |
| 268 | '(xref-location-marker xref-bogus-location) 'cl-defmethod | 401 | '(xref-location-marker xref-bogus-location) 'cl-defmethod |
| 269 | (expand-file-name "../../lisp/progmodes/xref.el" emacs-test-dir))) | 402 | (expand-file-name "../../lisp/progmodes/xref.el" emacs-test-dir))) |
| 270 | ;; etags is not loaded at test time | 403 | (xref-make "(cl-defmethod xref-location-marker ((l xref-etags-location)))" |
| 404 | (xref-make-elisp-location | ||
| 405 | '(xref-location-marker xref-etags-location) 'cl-defmethod | ||
| 406 | (expand-file-name "../../lisp/progmodes/etags.el" emacs-test-dir))) | ||
| 271 | )) | 407 | )) |
| 272 | 408 | ||
| 273 | (xref-elisp-deftest find-defs-defgeneric-eval | 409 | (xref-elisp-deftest find-defs-defgeneric-eval |
| @@ -318,20 +454,19 @@ to (xref-elisp-test-descr-to-target xref)." | |||
| 318 | ) | 454 | ) |
| 319 | 455 | ||
| 320 | ;; Source for both variable and defun is "(define-minor-mode | 456 | ;; Source for both variable and defun is "(define-minor-mode |
| 321 | ;; compilation-minor-mode". There is no way to tell that from the | 457 | ;; compilation-minor-mode". There is no way to tell that directly from |
| 322 | ;; symbol. find-function-regexp-alist uses find-function-regexp for | 458 | ;; the symbol, but we can use (memq sym minor-mode-list) to detect |
| 323 | ;; this, but that matches too many things for use in this test. | 459 | ;; that the symbol is a minor mode. See `elisp--xref-find-definitions' |
| 460 | ;; for more comments. | ||
| 461 | ;; | ||
| 462 | ;; IMPROVEME: return defvar instead of defun if source near starting | ||
| 463 | ;; point indicates the user is searching for a varible, not a | ||
| 464 | ;; function. | ||
| 324 | (require 'compile) ;; not loaded by default at test time | 465 | (require 'compile) ;; not loaded by default at test time |
| 325 | (xref-elisp-deftest find-defs-defun-defvar-el | 466 | (xref-elisp-deftest find-defs-defun-defvar-el |
| 326 | (elisp--xref-find-definitions 'compilation-minor-mode) | 467 | (elisp--xref-find-definitions 'compilation-minor-mode) |
| 327 | (list | 468 | (list |
| 328 | (cons | 469 | (cons |
| 329 | (xref-make "(defvar compilation-minor-mode)" | ||
| 330 | (xref-make-elisp-location | ||
| 331 | 'compilation-minor-mode 'defvar | ||
| 332 | (expand-file-name "../../lisp/progmodes/compile.el" emacs-test-dir))) | ||
| 333 | "(define-minor-mode compilation-minor-mode") | ||
| 334 | (cons | ||
| 335 | (xref-make "(defun compilation-minor-mode)" | 470 | (xref-make "(defun compilation-minor-mode)" |
| 336 | (xref-make-elisp-location | 471 | (xref-make-elisp-location |
| 337 | 'compilation-minor-mode nil | 472 | 'compilation-minor-mode nil |
| @@ -382,10 +517,13 @@ to (xref-elisp-test-descr-to-target xref)." | |||
| 382 | (xref-elisp-deftest find-defs-feature-el | 517 | (xref-elisp-deftest find-defs-feature-el |
| 383 | (elisp--xref-find-definitions 'xref) | 518 | (elisp--xref-find-definitions 'xref) |
| 384 | (list | 519 | (list |
| 385 | (xref-make "(feature xref)" | 520 | (cons |
| 521 | (xref-make "(feature xref)" | ||
| 386 | (xref-make-elisp-location | 522 | (xref-make-elisp-location |
| 387 | 'xref 'feature | 523 | 'xref 'feature |
| 388 | (expand-file-name "../../lisp/progmodes/xref.el" emacs-test-dir))))) | 524 | (expand-file-name "../../lisp/progmodes/xref.el" emacs-test-dir))) |
| 525 | ";;; Code:") | ||
| 526 | )) | ||
| 389 | 527 | ||
| 390 | (xref-elisp-deftest find-defs-feature-eval | 528 | (xref-elisp-deftest find-defs-feature-eval |
| 391 | (elisp--xref-find-definitions (eval '(provide 'stephe-leake-feature))) | 529 | (elisp--xref-find-definitions (eval '(provide 'stephe-leake-feature))) |