aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Leake2015-08-26 16:43:29 -0500
committerStephen Leake2015-08-26 16:58:57 -0500
commit64fbdc9825ad98ebbc8c021442c1f3c3ba0fd1b1 (patch)
treeb72f6a944fd02cf945b04060d921799f56085a85
parent2e8750c76940a712f0be93667c042c8987d919d4 (diff)
downloademacs-64fbdc9825ad98ebbc8c021442c1f3c3ba0fd1b1.tar.gz
emacs-64fbdc9825ad98ebbc8c021442c1f3c3ba0fd1b1.zip
Add mode local overrides to xref-find-definitions
* lisp/cedet/mode-local.el (xref-mode-local--override-present, xref-mode-local-overload): New; add mode local overrides to xref-find-definitions. * test/automated/elisp-mode-tests.el: Add mode local override tests. (xref-elisp-test-run): Handle indented defuns. (xref-elisp-generic-*): Improve doc strings. * lisp/progmodes/elisp-mode.el (elisp-xref-find-def-functions): New. (elisp--xref-find-definitions): Use it.
-rw-r--r--etc/NEWS7
-rw-r--r--lisp/cedet/mode-local.el98
-rw-r--r--lisp/progmodes/elisp-mode.el302
-rw-r--r--test/automated/elisp-mode-tests.el116
4 files changed, 367 insertions, 156 deletions
diff --git a/etc/NEWS b/etc/NEWS
index cf0804d791e..bfcce3692d0 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -88,9 +88,10 @@ command line when `initial-buffer-choice' is non-nil.
88 88
89* Changes in Emacs 25.1 89* Changes in Emacs 25.1
90 90
91** `describe-function' now displays information about mode local 91** `xref-find-definitions' and `describe-function' now display
92 overrides (defined by cedet/mode-local.el 92 information about mode local overrides (defined by
93 `define-overloadable-function' and `define-mode-local-overrides'. 93 cedet/mode-local.el `define-overloadable-function' and
94 `define-mode-local-overrides').
94 95
95** New `display-buffer' action function `display-buffer-use-some-frame' 96** New `display-buffer' action function `display-buffer-use-some-frame'
96This displays the buffer in an existing frame other than the current 97This displays the buffer in an existing frame other than the current
diff --git a/lisp/cedet/mode-local.el b/lisp/cedet/mode-local.el
index ce30a985a79..9ee875022f8 100644
--- a/lisp/cedet/mode-local.el
+++ b/lisp/cedet/mode-local.el
@@ -48,6 +48,13 @@
48 48
49(eval-when-compile (require 'cl)) 49(eval-when-compile (require 'cl))
50 50
51(require 'find-func)
52;; For find-function-regexp-alist. It is tempting to replace this
53;; ‘require‘ by (defvar find-function-regexp-alist) and
54;; with-eval-after-load, but model-local.el is typically loaded when a
55;; semantic autoload is invoked, and something in semantic loads
56;; find-func.el before mode-local.el, so the eval-after-load is lost.
57
51;;; Misc utilities 58;;; Misc utilities
52;; 59;;
53(defun mode-local-map-file-buffers (function &optional predicate buffers) 60(defun mode-local-map-file-buffers (function &optional predicate buffers)
@@ -649,6 +656,97 @@ SYMBOL is a function that can be overridden."
649 656
650(add-hook 'help-fns-describe-function-functions 'describe-mode-local-overload) 657(add-hook 'help-fns-describe-function-functions 'describe-mode-local-overload)
651 658
659(declare-function xref-item-location "xref" (xref))
660
661(defun xref-mode-local--override-present (sym xrefs)
662 "Return non-nil if SYM is in XREFS."
663 (let (result)
664 (while (and (null result)
665 xrefs)
666 (when (equal sym (car (xref-elisp-location-symbol (xref-item-location (pop xrefs)))))
667 (setq result t)))
668 result))
669
670(defun xref-mode-local-overload (symbol)
671 "For ‘elisp-xref-find-def-functions’; add overloads for SYMBOL."
672 ;; Current buffer is the buffer where xref-find-definitions was invoked.
673 (when (get symbol 'mode-local-overload)
674 (let* ((symbol-file (find-lisp-object-file-name symbol (symbol-function symbol)))
675 (default (intern-soft (format "%s-default" (symbol-name symbol))))
676 (default-file (when default (find-lisp-object-file-name default (symbol-function default))))
677 modes
678 xrefs)
679
680 (mapatoms
681 (lambda (sym) (when (get sym 'mode-local-symbol-table) (push sym modes)))
682 obarray)
683
684 ;; mode-local-overrides are inherited from parent modes; we
685 ;; don't want to list the same function twice. So order ‘modes’
686 ;; with parents first, and check for duplicates.
687
688 (setq modes
689 (sort modes
690 (lambda (a b)
691 (not (equal b (get a 'mode-local-parent)))))) ;; a is not a child, or not a child of b
692
693 (dolist (mode modes)
694 (let* ((major-mode mode)
695 (override (fetch-overload symbol))
696 (override-file (when override (find-lisp-object-file-name override (symbol-function override)))))
697
698 (when (and override override-file)
699 (let ((meta-name (cons override major-mode))
700 ;; For the declaration:
701 ;;
702 ;;(define-mode-local-override xref-elisp-foo c-mode
703 ;;
704 ;; The override symbol name is
705 ;; "xref-elisp-foo-c-mode". The summary should match
706 ;; the declaration, so strip the mode from the
707 ;; symbol name.
708 (summary (format elisp--xref-format-extra
709 'define-mode-local-override
710 (substring (symbol-name override) 0 (- (1+ (length (symbol-name major-mode)))))
711 major-mode)))
712
713 (unless (xref-mode-local--override-present override xrefs)
714 (push (elisp--xref-make-xref
715 'define-mode-local-override meta-name override-file summary)
716 xrefs))))))
717
718 ;; %s-default is interned whether it is a separate function or
719 ;; not, so we have to check that here.
720 (when (and (functionp default) default-file)
721 (push (elisp--xref-make-xref nil default default-file) xrefs))
722
723 (when symbol-file
724 (push (elisp--xref-make-xref 'define-overloadable-function symbol symbol-file) xrefs))
725
726 xrefs)))
727
728(add-hook 'elisp-xref-find-def-functions 'xref-mode-local-overload)
729
730(defconst xref-mode-local-find-overloadable-regexp
731 "(\\(\\(define-overloadable-function\\)\\|\\(define-overload\\)\\) +%s"
732 "Regexp used by ‘xref-find-definitions’ when searching for a
733 mode-local overloadable function definition.")
734
735(defun xref-mode-local-find-override (meta-name)
736 "Function used by ‘xref-find-definitions’ when searching for an
737 override of a mode-local overloadable function.
738META-NAME is a cons (OVERLOADABLE-SYMBOL . MAJOR-MODE)."
739 (let* ((override (car meta-name))
740 (mode (cdr meta-name))
741 (regexp (format "(define-mode-local-override +%s +%s"
742 (substring (symbol-name override) 0 (- (1+ (length (symbol-name mode)))))
743 mode)))
744 (re-search-forward regexp nil t)
745 ))
746
747(add-to-list 'find-function-regexp-alist '(define-overloadable-function . xref-mode-local-find-overloadable-regexp))
748(add-to-list 'find-function-regexp-alist (cons 'define-mode-local-override #'xref-mode-local-find-override))
749
652;; Help for mode-local bindings. 750;; Help for mode-local bindings.
653(defun mode-local-print-binding (symbol) 751(defun mode-local-print-binding (symbol)
654 "Print the SYMBOL binding." 752 "Print the SYMBOL binding."
diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el
index a96fca15cc2..e76728d0461 100644
--- a/lisp/progmodes/elisp-mode.el
+++ b/lisp/progmodes/elisp-mode.el
@@ -620,7 +620,7 @@ It can be quoted, or be inside a quoted form."
620 (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)
621 str)) 621 str))
622 622
623(defvar find-feature-regexp) 623(defvar find-feature-regexp);; in find-func.el
624 624
625(defun elisp--xref-make-xref (type symbol file &optional summary) 625(defun elisp--xref-make-xref (type symbol file &optional summary)
626 "Return an xref for TYPE SYMBOL in FILE. 626 "Return an xref for TYPE SYMBOL in FILE.
@@ -631,149 +631,167 @@ otherwise build the summary from TYPE and SYMBOL."
631 (format elisp--xref-format (or type 'defun) symbol)) 631 (format elisp--xref-format (or type 'defun) symbol))
632 (xref-make-elisp-location symbol type file))) 632 (xref-make-elisp-location symbol type file)))
633 633
634(defvar elisp-xref-find-def-functions nil
635 "List of functions to be run from ‘elisp--xref-find-definitions’ to add additional xrefs.
636Called with one arg; the symbol whose definition is desired.
637Each function should return a list of xrefs, or nil; the first
638non-nil result supercedes the xrefs produced by
639‘elisp--xref-find-definitions’.")
640
641;; FIXME: name should be singular; match xref-find-definition
634(defun elisp--xref-find-definitions (symbol) 642(defun elisp--xref-find-definitions (symbol)
635 ;; The file name is not known when `symbol' is defined via interactive eval. 643 ;; The file name is not known when `symbol' is defined via interactive eval.
636 (let (xrefs) 644 (let (xrefs temp)
637 ;; alphabetical by result type symbol 645
638 646 (let ((temp elisp-xref-find-def-functions))
639 ;; FIXME: advised function; list of advice functions 647 (while (and (null xrefs)
640 648 temp)
641 ;; FIXME: aliased variable 649 (setq xrefs (append xrefs (funcall (pop temp) symbol)))))
642 650
643 (when (and (symbolp symbol) 651 (unless xrefs
644 (symbol-function symbol) 652 ;; alphabetical by result type symbol
645 (symbolp (symbol-function symbol))) 653
646 ;; aliased function 654 ;; FIXME: advised function; list of advice functions
647 (let* ((alias-symbol symbol) 655
648 (alias-file (symbol-file alias-symbol)) 656 ;; FIXME: aliased variable
649 (real-symbol (symbol-function symbol)) 657
650 (real-file (find-lisp-object-file-name real-symbol 'defun))) 658 (when (and (symbolp symbol)
651 659 (symbol-function symbol)
652 (when real-file 660 (symbolp (symbol-function symbol)))
653 (push (elisp--xref-make-xref nil real-symbol real-file) xrefs)) 661 ;; aliased function
654 662 (let* ((alias-symbol symbol)
655 (when alias-file 663 (alias-file (symbol-file alias-symbol))
656 (push (elisp--xref-make-xref 'defalias alias-symbol alias-file) xrefs)))) 664 (real-symbol (symbol-function symbol))
657 665 (real-file (find-lisp-object-file-name real-symbol 'defun)))
658 (when (facep symbol) 666
659 (let ((file (find-lisp-object-file-name symbol 'defface))) 667 (when real-file
660 (when file 668 (push (elisp--xref-make-xref nil real-symbol real-file) xrefs))
661 (push (elisp--xref-make-xref 'defface symbol file) xrefs)))) 669
662 670 (when alias-file
663 (when (fboundp symbol) 671 (push (elisp--xref-make-xref 'defalias alias-symbol alias-file) xrefs))))
664 (let ((file (find-lisp-object-file-name symbol (symbol-function symbol))) 672
665 generic doc) 673 (when (facep symbol)
666 (when file 674 (let ((file (find-lisp-object-file-name symbol 'defface)))
667 (cond 675 (when file
668 ((eq file 'C-source) 676 (push (elisp--xref-make-xref 'defface symbol file) xrefs))))
669 ;; First call to find-lisp-object-file-name for an object 677
670 ;; defined in C; the doc strings from the C source have 678 (when (fboundp symbol)
671 ;; not been loaded yet. Second call will return "src/*.c" 679 (let ((file (find-lisp-object-file-name symbol (symbol-function symbol)))
672 ;; in file; handled by 't' case below. 680 generic doc)
673 (push (elisp--xref-make-xref nil symbol (help-C-file-name (symbol-function symbol) 'subr)) xrefs)) 681 (when file
674 682 (cond
675 ((and (setq doc (documentation symbol t)) 683 ((eq file 'C-source)
676 ;; This doc string is defined in cl-macs.el cl-defstruct 684 ;; First call to find-lisp-object-file-name for an object
677 (string-match "Constructor for objects of type `\\(.*\\)'" doc)) 685 ;; defined in C; the doc strings from the C source have
678 ;; `symbol' is a name for the default constructor created by 686 ;; not been loaded yet. Second call will return "src/*.c"
679 ;; cl-defstruct, so return the location of the cl-defstruct. 687 ;; in file; handled by 't' case below.
680 (let* ((type-name (match-string 1 doc)) 688 (push (elisp--xref-make-xref nil symbol (help-C-file-name (symbol-function symbol) 'subr)) xrefs))
681 (type-symbol (intern type-name)) 689
682 (file (find-lisp-object-file-name type-symbol 'define-type)) 690 ((and (setq doc (documentation symbol t))
683 (summary (format elisp--xref-format-extra 691 ;; This doc string is defined in cl-macs.el cl-defstruct
684 'cl-defstruct 692 (string-match "Constructor for objects of type `\\(.*\\)'" doc))
685 (concat "(" type-name) 693 ;; `symbol' is a name for the default constructor created by
686 (concat "(:constructor " (symbol-name symbol) "))")))) 694 ;; cl-defstruct, so return the location of the cl-defstruct.
687 (push (elisp--xref-make-xref 'define-type type-symbol file summary) xrefs) 695 (let* ((type-name (match-string 1 doc))
688 )) 696 (type-symbol (intern type-name))
689 697 (file (find-lisp-object-file-name type-symbol 'define-type))
690 ((setq generic (cl--generic symbol)) 698 (summary (format elisp--xref-format-extra
691 ;; A generic function. If there is a default method, it 699 'cl-defstruct
692 ;; will appear in the method table, with no 700 (concat "(" type-name)
693 ;; specializers. 701 (concat "(:constructor " (symbol-name symbol) "))"))))
694 ;; 702 (push (elisp--xref-make-xref 'define-type type-symbol file summary) xrefs)
695 ;; If the default method is declared by the cl-defgeneric 703 ))
696 ;; declaration, it will have the same location as the 704
697 ;; cl-defgeneric, so we want to exclude it from the 705 ((setq generic (cl--generic symbol))
698 ;; result. In this case, it will have a null doc 706 ;; FIXME: move this to elisp-xref-find-def-functions, in cl-generic.el
699 ;; string. User declarations of default methods may also 707
700 ;; have null doc strings, but we hope that is 708 ;; A generic function. If there is a default method, it
701 ;; rare. Perhaps this heuristic will discourage that. 709 ;; will appear in the method table, with no
702 (dolist (method (cl--generic-method-table generic)) 710 ;; specializers.
703 (let* ((info (cl--generic-method-info method));; qual-string combined-args doconly 711 ;;
704 (specializers (cl--generic-method-specializers method)) 712 ;; If the default method is declared by the cl-defgeneric
705 (met-name (cons symbol specializers)) 713 ;; declaration, it will have the same location as the
706 (file (find-lisp-object-file-name met-name 'cl-defmethod))) 714 ;; cl-defgeneric, so we want to exclude it from the
707 (when (and file 715 ;; result. In this case, it will have a null doc
708 (or specializers ;; default method has null specializers 716 ;; string. User declarations of default methods may also
709 (nth 2 info))) ;; assuming only co-located default has null doc string 717 ;; have null doc strings, but we hope that is
710 (if specializers 718 ;; rare. Perhaps this heuristic will discourage that.
711 (let ((summary (format elisp--xref-format-extra 'cl-defmethod symbol (nth 1 info)))) 719 (dolist (method (cl--generic-method-table generic))
712 (push (elisp--xref-make-xref 'cl-defmethod met-name file summary) xrefs)) 720 (let* ((info (cl--generic-method-info method));; qual-string combined-args doconly
713 721 (specializers (cl--generic-method-specializers method))
714 (let ((summary (format elisp--xref-format-extra 'cl-defmethod symbol "()"))) 722 (met-name (cons symbol specializers))
715 (push (elisp--xref-make-xref 'cl-defmethod met-name file summary) xrefs)))) 723 (file (find-lisp-object-file-name met-name 'cl-defmethod)))
716 )) 724 (when (and file
717 725 (or specializers ;; default method has null specializers
718 (if (and (setq doc (documentation symbol t)) 726 (nth 2 info))) ;; assuming only co-located default has null doc string
719 ;; This doc string is created somewhere in 727 (if specializers
720 ;; cl--generic-make-function for an implicit 728 (let ((summary (format elisp--xref-format-extra 'cl-defmethod symbol (nth 1 info))))
721 ;; defgeneric. 729 (push (elisp--xref-make-xref 'cl-defmethod met-name file summary) xrefs))
722 (string-match "\n\n(fn ARG &rest ARGS)" doc)) 730
723 ;; This symbol is an implicitly defined defgeneric, so 731 (let ((summary (format elisp--xref-format-extra 'cl-defmethod symbol "()")))
724 ;; don't return it. 732 (push (elisp--xref-make-xref 'cl-defmethod met-name file summary) xrefs))))
725 nil 733 ))
726 (push (elisp--xref-make-xref 'cl-defgeneric symbol file) xrefs)) 734
727 ) 735 (if (and (setq doc (documentation symbol t))
728 736 ;; This doc string is created somewhere in
729 (t 737 ;; cl--generic-make-function for an implicit
730 (push (elisp--xref-make-xref nil symbol file) xrefs)) 738 ;; defgeneric.
731 )))) 739 (string-match "\n\n(fn ARG &rest ARGS)" doc))
732 740 ;; This symbol is an implicitly defined defgeneric, so
733 (when (boundp symbol) 741 ;; don't return it.
734 ;; A variable 742 nil
735 (let ((file (find-lisp-object-file-name symbol 'defvar))) 743 (push (elisp--xref-make-xref 'cl-defgeneric symbol file) xrefs))
736 (when file 744 )
737 (cond 745
738 ((eq file 'C-source) 746 (t
739 ;; The doc strings from the C source have not been loaded 747 (push (elisp--xref-make-xref nil symbol file) xrefs))
740 ;; yet; help-C-file-name does that. Second call will 748 ))))
741 ;; return "src/*.c" in file; handled below. 749
742 (push (elisp--xref-make-xref 'defvar symbol (help-C-file-name symbol 'var)) xrefs)) 750 (when (boundp symbol)
743 751 ;; A variable
744 ((string= "src/" (substring file 0 4)) 752 (let ((file (find-lisp-object-file-name symbol 'defvar)))
745 ;; The variable is defined in a C source file; don't check 753 (when file
746 ;; for define-minor-mode. 754 (cond
747 (push (elisp--xref-make-xref 'defvar symbol file) xrefs)) 755 ((eq file 'C-source)
748 756 ;; The doc strings from the C source have not been loaded
749 ((memq symbol minor-mode-list) 757 ;; yet; help-C-file-name does that. Second call will
750 ;; The symbol is a minor mode. These should be defined by 758 ;; return "src/*.c" in file; handled below.
751 ;; "define-minor-mode", which means the variable and the 759 (push (elisp--xref-make-xref 'defvar symbol (help-C-file-name symbol 'var)) xrefs))
752 ;; function are declared in the same place. So we return only 760
753 ;; the function, arbitrarily. 761 ((string= "src/" (substring file 0 4))
754 ;; 762 ;; The variable is defined in a C source file; don't check
755 ;; There is an exception, when the variable is defined in C 763 ;; for define-minor-mode.
756 ;; code, as for abbrev-mode. 764 (push (elisp--xref-make-xref 'defvar symbol file) xrefs))
757 ;; 765
758 ;; IMPROVEME: If the user is searching for the identifier at 766 ((memq symbol minor-mode-list)
759 ;; point, we can determine whether it is a variable or 767 ;; The symbol is a minor mode. These should be defined by
760 ;; function by looking at the source code near point. 768 ;; "define-minor-mode", which means the variable and the
761 ;; 769 ;; function are declared in the same place. So we return only
762 ;; IMPROVEME: The user may actually be asking "do any 770 ;; the function, arbitrarily.
763 ;; variables by this name exist"; we need a way to specify 771 ;;
764 ;; that. 772 ;; There is an exception, when the variable is defined in C
765 nil) 773 ;; code, as for abbrev-mode.
766 774 ;;
767 (t 775 ;; IMPROVEME: If the user is searching for the identifier at
768 (push (elisp--xref-make-xref 'defvar symbol file) xrefs)) 776 ;; point, we can determine whether it is a variable or
769 777 ;; function by looking at the source code near point.
770 )))) 778 ;;
771 779 ;; IMPROVEME: The user may actually be asking "do any
772 (when (featurep symbol) 780 ;; variables by this name exist"; we need a way to specify
773 (let ((file (ignore-errors 781 ;; that.
774 (find-library-name (symbol-name symbol))))) 782 nil)
775 (when file 783
776 (push (elisp--xref-make-xref 'feature symbol file) xrefs)))) 784 (t
785 (push (elisp--xref-make-xref 'defvar symbol file) xrefs))
786
787 ))))
788
789 (when (featurep symbol)
790 (let ((file (ignore-errors
791 (find-library-name (symbol-name symbol)))))
792 (when file
793 (push (elisp--xref-make-xref 'feature symbol file) xrefs))))
794 );; 'unless xrefs'
777 795
778 xrefs)) 796 xrefs))
779 797
diff --git a/test/automated/elisp-mode-tests.el b/test/automated/elisp-mode-tests.el
index 64b3f665a03..ec01477984c 100644
--- a/test/automated/elisp-mode-tests.el
+++ b/test/automated/elisp-mode-tests.el
@@ -186,6 +186,7 @@
186 (or (when (consp expected) (car expected)) expected))) 186 (or (when (consp expected) (car expected)) expected)))
187 187
188 (xref--goto-location (xref-item-location xref)) 188 (xref--goto-location (xref-item-location xref))
189 (back-to-indentation)
189 (should (looking-at (or (when (consp expected) (cdr expected)) 190 (should (looking-at (or (when (consp expected) (cdr expected))
190 (xref-elisp-test-descr-to-target expected))))) 191 (xref-elisp-test-descr-to-target expected)))))
191 )) 192 ))
@@ -258,50 +259,55 @@ to (xref-elisp-test-descr-to-target xref)."
258 slot-1) 259 slot-1)
259 260
260(cl-defgeneric xref-elisp-generic-no-methods () 261(cl-defgeneric xref-elisp-generic-no-methods ()
261 "doc string no-methods" 262 "doc string generic no-methods"
262 ;; No default implementation, no methods, but fboundp is true for 263 ;; No default implementation, no methods, but fboundp is true for
263 ;; this symbol; it calls cl-no-applicable-method 264 ;; this symbol; it calls cl-no-applicable-method
264 ) 265 )
265 266
267;; WORKAROUND: ‘this’ is unused, and the byte compiler complains, so
268;; it should be spelled ‘_this’. But for some unknown reason, that
269;; causes the batch mode test to fail; the symbol shows up as
270;; ‘this’. It passes in interactive tests, so I haven't been able to
271;; track down the problem.
266(cl-defmethod xref-elisp-generic-no-default ((this xref-elisp-root-type)) 272(cl-defmethod xref-elisp-generic-no-default ((this xref-elisp-root-type))
267 "doc string no-default xref-elisp-root-type" 273 "doc string generic no-default xref-elisp-root-type"
268 "non-default for no-default") 274 "non-default for no-default")
269 275
270;; defgeneric after defmethod in file to ensure the fallback search 276;; defgeneric after defmethod in file to ensure the fallback search
271;; method of just looking for the function name will fail. 277;; method of just looking for the function name will fail.
272(cl-defgeneric xref-elisp-generic-no-default () 278(cl-defgeneric xref-elisp-generic-no-default ()
273 "doc string no-default generic" 279 "doc string generic no-default generic"
274 ;; No default implementation; this function calls the cl-generic 280 ;; No default implementation; this function calls the cl-generic
275 ;; dispatching code. 281 ;; dispatching code.
276 ) 282 )
277 283
278(cl-defgeneric xref-elisp-generic-co-located-default () 284(cl-defgeneric xref-elisp-generic-co-located-default ()
279 "doc string co-located-default generic" 285 "doc string generic co-located-default"
280 "co-located default") 286 "co-located default")
281 287
282(cl-defmethod xref-elisp-generic-co-located-default ((this xref-elisp-root-type)) 288(cl-defmethod xref-elisp-generic-co-located-default ((this xref-elisp-root-type))
283 "doc string co-located-default xref-elisp-root-type" 289 "doc string generic co-located-default xref-elisp-root-type"
284 "non-default for co-located-default") 290 "non-default for co-located-default")
285 291
286(cl-defgeneric xref-elisp-generic-separate-default () 292(cl-defgeneric xref-elisp-generic-separate-default ()
287 "doc string separate-default generic" 293 "doc string generic separate-default"
288 ;; default implementation provided separately 294 ;; default implementation provided separately
289 ) 295 )
290 296
291(cl-defmethod xref-elisp-generic-separate-default () 297(cl-defmethod xref-elisp-generic-separate-default ()
292 "doc string separate-default default" 298 "doc string generic separate-default default"
293 "separate default") 299 "separate default")
294 300
295(cl-defmethod xref-elisp-generic-separate-default ((this xref-elisp-root-type)) 301(cl-defmethod xref-elisp-generic-separate-default ((this xref-elisp-root-type))
296 "doc string separate-default xref-elisp-root-type" 302 "doc string generic separate-default xref-elisp-root-type"
297 "non-default for separate-default") 303 "non-default for separate-default")
298 304
299(cl-defmethod xref-elisp-generic-implicit-generic () 305(cl-defmethod xref-elisp-generic-implicit-generic ()
300 "doc string implicit-generic default" 306 "doc string generic implicit-generic default"
301 "default for implicit generic") 307 "default for implicit generic")
302 308
303(cl-defmethod xref-elisp-generic-implicit-generic ((this xref-elisp-root-type)) 309(cl-defmethod xref-elisp-generic-implicit-generic ((this xref-elisp-root-type))
304 "doc string implicit-generic xref-elisp-root-type" 310 "doc string generic implicit-generic xref-elisp-root-type"
305 "non-default for implicit generic") 311 "non-default for implicit generic")
306 312
307 313
@@ -351,7 +357,6 @@ to (xref-elisp-test-descr-to-target xref)."
351 (xref-make-elisp-location 357 (xref-make-elisp-location
352 '(xref-elisp-generic-separate-default) 'cl-defmethod 358 '(xref-elisp-generic-separate-default) 'cl-defmethod
353 (expand-file-name "elisp-mode-tests.el" emacs-test-dir))) 359 (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)))" 360 (xref-make "(cl-defmethod xref-elisp-generic-separate-default ((this xref-elisp-root-type)))"
356 (xref-make-elisp-location 361 (xref-make-elisp-location
357 '(xref-elisp-generic-separate-default xref-elisp-root-type) 'cl-defmethod 362 '(xref-elisp-generic-separate-default xref-elisp-root-type) 'cl-defmethod
@@ -410,6 +415,95 @@ to (xref-elisp-test-descr-to-target xref)."
410 (elisp--xref-find-definitions (eval '(cl-defgeneric stephe-leake-cl-defgeneric ()))) 415 (elisp--xref-find-definitions (eval '(cl-defgeneric stephe-leake-cl-defgeneric ())))
411 nil) 416 nil)
412 417
418;; Define some mode-local overloadable/overridden functions for xref to find
419(require 'mode-local)
420
421(define-overloadable-function xref-elisp-overloadable-no-methods ()
422 "doc string overloadable no-methods")
423
424(define-overloadable-function xref-elisp-overloadable-no-default ()
425 "doc string overloadable no-default")
426
427;; FIXME: byte compiler complains about unused lexical arguments
428;; generated by this macro.
429(define-mode-local-override xref-elisp-overloadable-no-default c-mode
430 (start end &optional nonterminal depth returnonerror)
431 "doc string overloadable no-default c-mode."
432 "result overloadable no-default c-mode.")
433
434(define-overloadable-function xref-elisp-overloadable-co-located-default ()
435 "doc string overloadable co-located-default"
436 "result overloadable co-located-default.")
437
438(define-mode-local-override xref-elisp-overloadable-co-located-default c-mode
439 (start end &optional nonterminal depth returnonerror)
440 "doc string overloadable co-located-default c-mode."
441 "result overloadable co-located-default c-mode.")
442
443(define-overloadable-function xref-elisp-overloadable-separate-default ()
444 "doc string overloadable separate-default.")
445
446(defun xref-elisp-overloadable-separate-default-default ()
447 "doc string overloadable separate-default default"
448 "result overloadable separate-default.")
449
450(define-mode-local-override xref-elisp-overloadable-separate-default c-mode
451 (start end &optional nonterminal depth returnonerror)
452 "doc string overloadable separate-default c-mode."
453 "result overloadable separate-default c-mode.")
454
455(xref-elisp-deftest find-defs-define-overload-no-methods
456 (elisp--xref-find-definitions 'xref-elisp-overloadable-no-methods)
457 (list
458 (xref-make "(define-overloadable-function xref-elisp-overloadable-no-methods)"
459 (xref-make-elisp-location
460 'xref-elisp-overloadable-no-methods 'define-overloadable-function
461 (expand-file-name "elisp-mode-tests.el" emacs-test-dir)))
462 ))
463
464(xref-elisp-deftest find-defs-define-overload-no-default
465 (elisp--xref-find-definitions 'xref-elisp-overloadable-no-default)
466 (list
467 (xref-make "(define-overloadable-function xref-elisp-overloadable-no-default)"
468 (xref-make-elisp-location
469 'xref-elisp-overloadable-no-default 'define-overloadable-function
470 (expand-file-name "elisp-mode-tests.el" emacs-test-dir)))
471 (xref-make "(define-mode-local-override xref-elisp-overloadable-no-default c-mode)"
472 (xref-make-elisp-location
473 '(xref-elisp-overloadable-no-default-c-mode . c-mode) 'define-mode-local-override
474 (expand-file-name "elisp-mode-tests.el" emacs-test-dir)))
475 ))
476
477(xref-elisp-deftest find-defs-define-overload-co-located-default
478 (elisp--xref-find-definitions 'xref-elisp-overloadable-co-located-default)
479 (list
480 (xref-make "(define-overloadable-function xref-elisp-overloadable-co-located-default)"
481 (xref-make-elisp-location
482 'xref-elisp-overloadable-co-located-default 'define-overloadable-function
483 (expand-file-name "elisp-mode-tests.el" emacs-test-dir)))
484 (xref-make "(define-mode-local-override xref-elisp-overloadable-co-located-default c-mode)"
485 (xref-make-elisp-location
486 '(xref-elisp-overloadable-co-located-default-c-mode . c-mode) 'define-mode-local-override
487 (expand-file-name "elisp-mode-tests.el" emacs-test-dir)))
488 ))
489
490(xref-elisp-deftest find-defs-define-overload-separate-default
491 (elisp--xref-find-definitions 'xref-elisp-overloadable-separate-default)
492 (list
493 (xref-make "(define-overloadable-function xref-elisp-overloadable-separate-default)"
494 (xref-make-elisp-location
495 'xref-elisp-overloadable-separate-default 'define-overloadable-function
496 (expand-file-name "elisp-mode-tests.el" emacs-test-dir)))
497 (xref-make "(defun xref-elisp-overloadable-separate-default-default)"
498 (xref-make-elisp-location
499 'xref-elisp-overloadable-separate-default-default nil
500 (expand-file-name "elisp-mode-tests.el" emacs-test-dir)))
501 (xref-make "(define-mode-local-override xref-elisp-overloadable-separate-default c-mode)"
502 (xref-make-elisp-location
503 '(xref-elisp-overloadable-separate-default-c-mode . c-mode) 'define-mode-local-override
504 (expand-file-name "elisp-mode-tests.el" emacs-test-dir)))
505 ))
506
413(xref-elisp-deftest find-defs-defun-el 507(xref-elisp-deftest find-defs-defun-el
414 (elisp--xref-find-definitions 'xref-find-definitions) 508 (elisp--xref-find-definitions 'xref-find-definitions)
415 (list 509 (list