From 64fbdc9825ad98ebbc8c021442c1f3c3ba0fd1b1 Mon Sep 17 00:00:00 2001 From: Stephen Leake Date: Wed, 26 Aug 2015 16:43:29 -0500 Subject: [PATCH] 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. --- etc/NEWS | 7 +- lisp/cedet/mode-local.el | 98 ++++++++++ lisp/progmodes/elisp-mode.el | 302 +++++++++++++++-------------- test/automated/elisp-mode-tests.el | 116 +++++++++-- 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. * Changes in Emacs 25.1 -** `describe-function' now displays information about mode local - overrides (defined by cedet/mode-local.el - `define-overloadable-function' and `define-mode-local-overrides'. +** `xref-find-definitions' and `describe-function' now display + information about mode local overrides (defined by + cedet/mode-local.el `define-overloadable-function' and + `define-mode-local-overrides'). ** New `display-buffer' action function `display-buffer-use-some-frame' This 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 @@ (eval-when-compile (require 'cl)) +(require 'find-func) +;; For find-function-regexp-alist. It is tempting to replace this +;; ‘require‘ by (defvar find-function-regexp-alist) and +;; with-eval-after-load, but model-local.el is typically loaded when a +;; semantic autoload is invoked, and something in semantic loads +;; find-func.el before mode-local.el, so the eval-after-load is lost. + ;;; Misc utilities ;; (defun mode-local-map-file-buffers (function &optional predicate buffers) @@ -649,6 +656,97 @@ SYMBOL is a function that can be overridden." (add-hook 'help-fns-describe-function-functions 'describe-mode-local-overload) +(declare-function xref-item-location "xref" (xref)) + +(defun xref-mode-local--override-present (sym xrefs) + "Return non-nil if SYM is in XREFS." + (let (result) + (while (and (null result) + xrefs) + (when (equal sym (car (xref-elisp-location-symbol (xref-item-location (pop xrefs))))) + (setq result t))) + result)) + +(defun xref-mode-local-overload (symbol) + "For ‘elisp-xref-find-def-functions’; add overloads for SYMBOL." + ;; Current buffer is the buffer where xref-find-definitions was invoked. + (when (get symbol 'mode-local-overload) + (let* ((symbol-file (find-lisp-object-file-name symbol (symbol-function symbol))) + (default (intern-soft (format "%s-default" (symbol-name symbol)))) + (default-file (when default (find-lisp-object-file-name default (symbol-function default)))) + modes + xrefs) + + (mapatoms + (lambda (sym) (when (get sym 'mode-local-symbol-table) (push sym modes))) + obarray) + + ;; mode-local-overrides are inherited from parent modes; we + ;; don't want to list the same function twice. So order ‘modes’ + ;; with parents first, and check for duplicates. + + (setq modes + (sort modes + (lambda (a b) + (not (equal b (get a 'mode-local-parent)))))) ;; a is not a child, or not a child of b + + (dolist (mode modes) + (let* ((major-mode mode) + (override (fetch-overload symbol)) + (override-file (when override (find-lisp-object-file-name override (symbol-function override))))) + + (when (and override override-file) + (let ((meta-name (cons override major-mode)) + ;; For the declaration: + ;; + ;;(define-mode-local-override xref-elisp-foo c-mode + ;; + ;; The override symbol name is + ;; "xref-elisp-foo-c-mode". The summary should match + ;; the declaration, so strip the mode from the + ;; symbol name. + (summary (format elisp--xref-format-extra + 'define-mode-local-override + (substring (symbol-name override) 0 (- (1+ (length (symbol-name major-mode))))) + major-mode))) + + (unless (xref-mode-local--override-present override xrefs) + (push (elisp--xref-make-xref + 'define-mode-local-override meta-name override-file summary) + xrefs)))))) + + ;; %s-default is interned whether it is a separate function or + ;; not, so we have to check that here. + (when (and (functionp default) default-file) + (push (elisp--xref-make-xref nil default default-file) xrefs)) + + (when symbol-file + (push (elisp--xref-make-xref 'define-overloadable-function symbol symbol-file) xrefs)) + + xrefs))) + +(add-hook 'elisp-xref-find-def-functions 'xref-mode-local-overload) + +(defconst xref-mode-local-find-overloadable-regexp + "(\\(\\(define-overloadable-function\\)\\|\\(define-overload\\)\\) +%s" + "Regexp used by ‘xref-find-definitions’ when searching for a + mode-local overloadable function definition.") + +(defun xref-mode-local-find-override (meta-name) + "Function used by ‘xref-find-definitions’ when searching for an + override of a mode-local overloadable function. +META-NAME is a cons (OVERLOADABLE-SYMBOL . MAJOR-MODE)." + (let* ((override (car meta-name)) + (mode (cdr meta-name)) + (regexp (format "(define-mode-local-override +%s +%s" + (substring (symbol-name override) 0 (- (1+ (length (symbol-name mode))))) + mode))) + (re-search-forward regexp nil t) + )) + +(add-to-list 'find-function-regexp-alist '(define-overloadable-function . xref-mode-local-find-overloadable-regexp)) +(add-to-list 'find-function-regexp-alist (cons 'define-mode-local-override #'xref-mode-local-find-override)) + ;; Help for mode-local bindings. (defun mode-local-print-binding (symbol) "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." (put-text-property 4 6 'face 'font-lock-function-name-face str) str)) -(defvar find-feature-regexp) +(defvar find-feature-regexp);; in find-func.el (defun elisp--xref-make-xref (type symbol file &optional summary) "Return an xref for TYPE SYMBOL in FILE. @@ -631,149 +631,167 @@ otherwise build the summary from TYPE and SYMBOL." (format elisp--xref-format (or type 'defun) symbol)) (xref-make-elisp-location symbol type file))) +(defvar elisp-xref-find-def-functions nil + "List of functions to be run from ‘elisp--xref-find-definitions’ to add additional xrefs. +Called with one arg; the symbol whose definition is desired. +Each function should return a list of xrefs, or nil; the first +non-nil result supercedes the xrefs produced by +‘elisp--xref-find-definitions’.") + +;; FIXME: name should be singular; match xref-find-definition (defun elisp--xref-find-definitions (symbol) ;; The file name is not known when `symbol' is defined via interactive eval. - (let (xrefs) - ;; alphabetical by result type symbol - - ;; FIXME: advised function; list of advice functions - - ;; FIXME: aliased variable - - (when (and (symbolp symbol) - (symbol-function symbol) - (symbolp (symbol-function symbol))) - ;; aliased function - (let* ((alias-symbol symbol) - (alias-file (symbol-file alias-symbol)) - (real-symbol (symbol-function symbol)) - (real-file (find-lisp-object-file-name real-symbol 'defun))) - - (when real-file - (push (elisp--xref-make-xref nil real-symbol real-file) xrefs)) - - (when alias-file - (push (elisp--xref-make-xref 'defalias alias-symbol alias-file) xrefs)))) - - (when (facep symbol) - (let ((file (find-lisp-object-file-name symbol 'defface))) - (when file - (push (elisp--xref-make-xref 'defface symbol file) xrefs)))) - - (when (fboundp symbol) - (let ((file (find-lisp-object-file-name symbol (symbol-function symbol))) - generic doc) - (when file - (cond - ((eq file 'C-source) - ;; First call to find-lisp-object-file-name for an object - ;; defined in C; the doc strings from the C source have - ;; not been loaded yet. Second call will return "src/*.c" - ;; in file; handled by 't' case below. - (push (elisp--xref-make-xref nil symbol (help-C-file-name (symbol-function symbol) 'subr)) xrefs)) - - ((and (setq doc (documentation symbol t)) - ;; This doc string is defined in cl-macs.el cl-defstruct - (string-match "Constructor for objects of type `\\(.*\\)'" doc)) - ;; `symbol' is a name for the default constructor created by - ;; cl-defstruct, so return the location of the cl-defstruct. - (let* ((type-name (match-string 1 doc)) - (type-symbol (intern type-name)) - (file (find-lisp-object-file-name type-symbol 'define-type)) - (summary (format elisp--xref-format-extra - 'cl-defstruct - (concat "(" type-name) - (concat "(:constructor " (symbol-name symbol) "))")))) - (push (elisp--xref-make-xref 'define-type type-symbol file summary) xrefs) - )) - - ((setq generic (cl--generic symbol)) - ;; A generic function. If there is a default method, it - ;; will appear in the method table, with no - ;; specializers. - ;; - ;; If the default method is declared by the cl-defgeneric - ;; declaration, it will have the same location as the - ;; cl-defgeneric, so we want to exclude it from the - ;; result. In this case, it will have a null doc - ;; string. User declarations of default methods may also - ;; have null doc strings, but we hope that is - ;; rare. Perhaps this heuristic will discourage that. - (dolist (method (cl--generic-method-table generic)) - (let* ((info (cl--generic-method-info method));; qual-string combined-args doconly - (specializers (cl--generic-method-specializers method)) - (met-name (cons symbol specializers)) - (file (find-lisp-object-file-name met-name 'cl-defmethod))) - (when (and file - (or specializers ;; default method has null specializers - (nth 2 info))) ;; assuming only co-located default has null doc string - (if specializers - (let ((summary (format elisp--xref-format-extra 'cl-defmethod symbol (nth 1 info)))) - (push (elisp--xref-make-xref 'cl-defmethod met-name file summary) xrefs)) - - (let ((summary (format elisp--xref-format-extra 'cl-defmethod symbol "()"))) - (push (elisp--xref-make-xref 'cl-defmethod met-name file summary) xrefs)))) - )) - - (if (and (setq doc (documentation symbol t)) - ;; This doc string is created somewhere in - ;; cl--generic-make-function for an implicit - ;; defgeneric. - (string-match "\n\n(fn ARG &rest ARGS)" doc)) - ;; This symbol is an implicitly defined defgeneric, so - ;; don't return it. - nil - (push (elisp--xref-make-xref 'cl-defgeneric symbol file) xrefs)) - ) - - (t - (push (elisp--xref-make-xref nil symbol file) xrefs)) - )))) - - (when (boundp symbol) - ;; A variable - (let ((file (find-lisp-object-file-name symbol 'defvar))) - (when file - (cond - ((eq file 'C-source) - ;; The doc strings from the C source have not been loaded - ;; yet; help-C-file-name does that. Second call will - ;; return "src/*.c" in file; handled below. - (push (elisp--xref-make-xref 'defvar symbol (help-C-file-name symbol 'var)) xrefs)) - - ((string= "src/" (substring file 0 4)) - ;; The variable is defined in a C source file; don't check - ;; for define-minor-mode. - (push (elisp--xref-make-xref 'defvar symbol file) xrefs)) - - ((memq symbol minor-mode-list) - ;; The symbol is a minor mode. These should be defined by - ;; "define-minor-mode", which means the variable and the - ;; function are declared in the same place. So we return only - ;; the function, arbitrarily. - ;; - ;; There is an exception, when the variable is defined in C - ;; code, as for abbrev-mode. - ;; - ;; IMPROVEME: If the user is searching for the identifier at - ;; point, we can determine whether it is a variable or - ;; function by looking at the source code near point. - ;; - ;; IMPROVEME: The user may actually be asking "do any - ;; variables by this name exist"; we need a way to specify - ;; that. - nil) - - (t - (push (elisp--xref-make-xref 'defvar symbol file) xrefs)) - - )))) - - (when (featurep symbol) - (let ((file (ignore-errors - (find-library-name (symbol-name symbol))))) - (when file - (push (elisp--xref-make-xref 'feature symbol file) xrefs)))) + (let (xrefs temp) + + (let ((temp elisp-xref-find-def-functions)) + (while (and (null xrefs) + temp) + (setq xrefs (append xrefs (funcall (pop temp) symbol))))) + + (unless xrefs + ;; alphabetical by result type symbol + + ;; FIXME: advised function; list of advice functions + + ;; FIXME: aliased variable + + (when (and (symbolp symbol) + (symbol-function symbol) + (symbolp (symbol-function symbol))) + ;; aliased function + (let* ((alias-symbol symbol) + (alias-file (symbol-file alias-symbol)) + (real-symbol (symbol-function symbol)) + (real-file (find-lisp-object-file-name real-symbol 'defun))) + + (when real-file + (push (elisp--xref-make-xref nil real-symbol real-file) xrefs)) + + (when alias-file + (push (elisp--xref-make-xref 'defalias alias-symbol alias-file) xrefs)))) + + (when (facep symbol) + (let ((file (find-lisp-object-file-name symbol 'defface))) + (when file + (push (elisp--xref-make-xref 'defface symbol file) xrefs)))) + + (when (fboundp symbol) + (let ((file (find-lisp-object-file-name symbol (symbol-function symbol))) + generic doc) + (when file + (cond + ((eq file 'C-source) + ;; First call to find-lisp-object-file-name for an object + ;; defined in C; the doc strings from the C source have + ;; not been loaded yet. Second call will return "src/*.c" + ;; in file; handled by 't' case below. + (push (elisp--xref-make-xref nil symbol (help-C-file-name (symbol-function symbol) 'subr)) xrefs)) + + ((and (setq doc (documentation symbol t)) + ;; This doc string is defined in cl-macs.el cl-defstruct + (string-match "Constructor for objects of type `\\(.*\\)'" doc)) + ;; `symbol' is a name for the default constructor created by + ;; cl-defstruct, so return the location of the cl-defstruct. + (let* ((type-name (match-string 1 doc)) + (type-symbol (intern type-name)) + (file (find-lisp-object-file-name type-symbol 'define-type)) + (summary (format elisp--xref-format-extra + 'cl-defstruct + (concat "(" type-name) + (concat "(:constructor " (symbol-name symbol) "))")))) + (push (elisp--xref-make-xref 'define-type type-symbol file summary) xrefs) + )) + + ((setq generic (cl--generic symbol)) + ;; FIXME: move this to elisp-xref-find-def-functions, in cl-generic.el + + ;; A generic function. If there is a default method, it + ;; will appear in the method table, with no + ;; specializers. + ;; + ;; If the default method is declared by the cl-defgeneric + ;; declaration, it will have the same location as the + ;; cl-defgeneric, so we want to exclude it from the + ;; result. In this case, it will have a null doc + ;; string. User declarations of default methods may also + ;; have null doc strings, but we hope that is + ;; rare. Perhaps this heuristic will discourage that. + (dolist (method (cl--generic-method-table generic)) + (let* ((info (cl--generic-method-info method));; qual-string combined-args doconly + (specializers (cl--generic-method-specializers method)) + (met-name (cons symbol specializers)) + (file (find-lisp-object-file-name met-name 'cl-defmethod))) + (when (and file + (or specializers ;; default method has null specializers + (nth 2 info))) ;; assuming only co-located default has null doc string + (if specializers + (let ((summary (format elisp--xref-format-extra 'cl-defmethod symbol (nth 1 info)))) + (push (elisp--xref-make-xref 'cl-defmethod met-name file summary) xrefs)) + + (let ((summary (format elisp--xref-format-extra 'cl-defmethod symbol "()"))) + (push (elisp--xref-make-xref 'cl-defmethod met-name file summary) xrefs)))) + )) + + (if (and (setq doc (documentation symbol t)) + ;; This doc string is created somewhere in + ;; cl--generic-make-function for an implicit + ;; defgeneric. + (string-match "\n\n(fn ARG &rest ARGS)" doc)) + ;; This symbol is an implicitly defined defgeneric, so + ;; don't return it. + nil + (push (elisp--xref-make-xref 'cl-defgeneric symbol file) xrefs)) + ) + + (t + (push (elisp--xref-make-xref nil symbol file) xrefs)) + )))) + + (when (boundp symbol) + ;; A variable + (let ((file (find-lisp-object-file-name symbol 'defvar))) + (when file + (cond + ((eq file 'C-source) + ;; The doc strings from the C source have not been loaded + ;; yet; help-C-file-name does that. Second call will + ;; return "src/*.c" in file; handled below. + (push (elisp--xref-make-xref 'defvar symbol (help-C-file-name symbol 'var)) xrefs)) + + ((string= "src/" (substring file 0 4)) + ;; The variable is defined in a C source file; don't check + ;; for define-minor-mode. + (push (elisp--xref-make-xref 'defvar symbol file) xrefs)) + + ((memq symbol minor-mode-list) + ;; The symbol is a minor mode. These should be defined by + ;; "define-minor-mode", which means the variable and the + ;; function are declared in the same place. So we return only + ;; the function, arbitrarily. + ;; + ;; There is an exception, when the variable is defined in C + ;; code, as for abbrev-mode. + ;; + ;; IMPROVEME: If the user is searching for the identifier at + ;; point, we can determine whether it is a variable or + ;; function by looking at the source code near point. + ;; + ;; IMPROVEME: The user may actually be asking "do any + ;; variables by this name exist"; we need a way to specify + ;; that. + nil) + + (t + (push (elisp--xref-make-xref 'defvar symbol file) xrefs)) + + )))) + + (when (featurep symbol) + (let ((file (ignore-errors + (find-library-name (symbol-name symbol))))) + (when file + (push (elisp--xref-make-xref 'feature symbol file) xrefs)))) + );; 'unless xrefs' xrefs)) 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 @@ (or (when (consp expected) (car expected)) expected))) (xref--goto-location (xref-item-location xref)) + (back-to-indentation) (should (looking-at (or (when (consp expected) (cdr expected)) (xref-elisp-test-descr-to-target expected))))) )) @@ -258,50 +259,55 @@ to (xref-elisp-test-descr-to-target xref)." slot-1) (cl-defgeneric xref-elisp-generic-no-methods () - "doc string no-methods" + "doc string generic no-methods" ;; No default implementation, no methods, but fboundp is true for ;; this symbol; it calls cl-no-applicable-method ) +;; WORKAROUND: ‘this’ is unused, and the byte compiler complains, so +;; it should be spelled ‘_this’. But for some unknown reason, that +;; causes the batch mode test to fail; the symbol shows up as +;; ‘this’. It passes in interactive tests, so I haven't been able to +;; track down the problem. (cl-defmethod xref-elisp-generic-no-default ((this xref-elisp-root-type)) - "doc string no-default xref-elisp-root-type" + "doc string generic no-default xref-elisp-root-type" "non-default for no-default") ;; defgeneric after defmethod in file to ensure the fallback search ;; method of just looking for the function name will fail. (cl-defgeneric xref-elisp-generic-no-default () - "doc string no-default generic" + "doc string generic no-default generic" ;; No default implementation; this function calls the cl-generic ;; dispatching code. ) (cl-defgeneric xref-elisp-generic-co-located-default () - "doc string co-located-default generic" + "doc string generic co-located-default" "co-located default") (cl-defmethod xref-elisp-generic-co-located-default ((this xref-elisp-root-type)) - "doc string co-located-default xref-elisp-root-type" + "doc string generic co-located-default xref-elisp-root-type" "non-default for co-located-default") (cl-defgeneric xref-elisp-generic-separate-default () - "doc string separate-default generic" + "doc string generic separate-default" ;; default implementation provided separately ) (cl-defmethod xref-elisp-generic-separate-default () - "doc string separate-default default" + "doc string generic separate-default default" "separate default") (cl-defmethod xref-elisp-generic-separate-default ((this xref-elisp-root-type)) - "doc string separate-default xref-elisp-root-type" + "doc string generic separate-default xref-elisp-root-type" "non-default for separate-default") (cl-defmethod xref-elisp-generic-implicit-generic () - "doc string implicit-generic default" + "doc string generic implicit-generic default" "default for implicit generic") (cl-defmethod xref-elisp-generic-implicit-generic ((this xref-elisp-root-type)) - "doc string implicit-generic xref-elisp-root-type" + "doc string generic implicit-generic xref-elisp-root-type" "non-default for implicit generic") @@ -351,7 +357,6 @@ to (xref-elisp-test-descr-to-target xref)." (xref-make-elisp-location '(xref-elisp-generic-separate-default) 'cl-defmethod (expand-file-name "elisp-mode-tests.el" emacs-test-dir))) - (xref-make "(cl-defmethod xref-elisp-generic-separate-default ((this xref-elisp-root-type)))" (xref-make-elisp-location '(xref-elisp-generic-separate-default xref-elisp-root-type) 'cl-defmethod @@ -410,6 +415,95 @@ to (xref-elisp-test-descr-to-target xref)." (elisp--xref-find-definitions (eval '(cl-defgeneric stephe-leake-cl-defgeneric ()))) nil) +;; Define some mode-local overloadable/overridden functions for xref to find +(require 'mode-local) + +(define-overloadable-function xref-elisp-overloadable-no-methods () + "doc string overloadable no-methods") + +(define-overloadable-function xref-elisp-overloadable-no-default () + "doc string overloadable no-default") + +;; FIXME: byte compiler complains about unused lexical arguments +;; generated by this macro. +(define-mode-local-override xref-elisp-overloadable-no-default c-mode + (start end &optional nonterminal depth returnonerror) + "doc string overloadable no-default c-mode." + "result overloadable no-default c-mode.") + +(define-overloadable-function xref-elisp-overloadable-co-located-default () + "doc string overloadable co-located-default" + "result overloadable co-located-default.") + +(define-mode-local-override xref-elisp-overloadable-co-located-default c-mode + (start end &optional nonterminal depth returnonerror) + "doc string overloadable co-located-default c-mode." + "result overloadable co-located-default c-mode.") + +(define-overloadable-function xref-elisp-overloadable-separate-default () + "doc string overloadable separate-default.") + +(defun xref-elisp-overloadable-separate-default-default () + "doc string overloadable separate-default default" + "result overloadable separate-default.") + +(define-mode-local-override xref-elisp-overloadable-separate-default c-mode + (start end &optional nonterminal depth returnonerror) + "doc string overloadable separate-default c-mode." + "result overloadable separate-default c-mode.") + +(xref-elisp-deftest find-defs-define-overload-no-methods + (elisp--xref-find-definitions 'xref-elisp-overloadable-no-methods) + (list + (xref-make "(define-overloadable-function xref-elisp-overloadable-no-methods)" + (xref-make-elisp-location + 'xref-elisp-overloadable-no-methods 'define-overloadable-function + (expand-file-name "elisp-mode-tests.el" emacs-test-dir))) + )) + +(xref-elisp-deftest find-defs-define-overload-no-default + (elisp--xref-find-definitions 'xref-elisp-overloadable-no-default) + (list + (xref-make "(define-overloadable-function xref-elisp-overloadable-no-default)" + (xref-make-elisp-location + 'xref-elisp-overloadable-no-default 'define-overloadable-function + (expand-file-name "elisp-mode-tests.el" emacs-test-dir))) + (xref-make "(define-mode-local-override xref-elisp-overloadable-no-default c-mode)" + (xref-make-elisp-location + '(xref-elisp-overloadable-no-default-c-mode . c-mode) 'define-mode-local-override + (expand-file-name "elisp-mode-tests.el" emacs-test-dir))) + )) + +(xref-elisp-deftest find-defs-define-overload-co-located-default + (elisp--xref-find-definitions 'xref-elisp-overloadable-co-located-default) + (list + (xref-make "(define-overloadable-function xref-elisp-overloadable-co-located-default)" + (xref-make-elisp-location + 'xref-elisp-overloadable-co-located-default 'define-overloadable-function + (expand-file-name "elisp-mode-tests.el" emacs-test-dir))) + (xref-make "(define-mode-local-override xref-elisp-overloadable-co-located-default c-mode)" + (xref-make-elisp-location + '(xref-elisp-overloadable-co-located-default-c-mode . c-mode) 'define-mode-local-override + (expand-file-name "elisp-mode-tests.el" emacs-test-dir))) + )) + +(xref-elisp-deftest find-defs-define-overload-separate-default + (elisp--xref-find-definitions 'xref-elisp-overloadable-separate-default) + (list + (xref-make "(define-overloadable-function xref-elisp-overloadable-separate-default)" + (xref-make-elisp-location + 'xref-elisp-overloadable-separate-default 'define-overloadable-function + (expand-file-name "elisp-mode-tests.el" emacs-test-dir))) + (xref-make "(defun xref-elisp-overloadable-separate-default-default)" + (xref-make-elisp-location + 'xref-elisp-overloadable-separate-default-default nil + (expand-file-name "elisp-mode-tests.el" emacs-test-dir))) + (xref-make "(define-mode-local-override xref-elisp-overloadable-separate-default c-mode)" + (xref-make-elisp-location + '(xref-elisp-overloadable-separate-default-c-mode . c-mode) 'define-mode-local-override + (expand-file-name "elisp-mode-tests.el" emacs-test-dir))) + )) + (xref-elisp-deftest find-defs-defun-el (elisp--xref-find-definitions 'xref-find-definitions) (list -- 2.39.5