diff --git a/modules/tools/lookup/autoload/lookup.el b/modules/tools/lookup/autoload/lookup.el index 5360a82d5..6b0e35ed4 100644 --- a/modules/tools/lookup/autoload/lookup.el +++ b/modules/tools/lookup/autoload/lookup.el @@ -185,20 +185,23 @@ This can be passed nil as its second argument to unset handlers for MODES. e.g. (autoload 'xref--show-defs "xref") (defun +lookup--xref-show (fn identifier &optional show-fn) - (let ((xrefs (funcall fn + (let ((origin (point-marker)) + (xrefs (funcall fn (xref-find-backend) identifier))) - (when xrefs - (let* ((jumped nil) - (xref-after-jump-hook - (cons (lambda () (setq jumped t)) - xref-after-jump-hook))) - (funcall (or show-fn #'xref--show-defs) - (lambda () xrefs) - nil) - (if (cdr xrefs) - 'deferred - jumped))))) + (unwind-protect + (when xrefs + (funcall (or show-fn #'xref--show-defs) + (lambda () xrefs) + nil) + ;; Some xref backends may report "success" without moving point (e.g. + ;; returning the current location). In that case, allow fallback + ;; backends to run. + (if (cdr xrefs) + 'deferred + (or (not (eq (marker-buffer origin) (current-buffer))) + (/= (marker-position origin) (point))))) + (set-marker origin nil)))) (defun +lookup-dictionary-definition-backend-fn (identifier) "Look up dictionary definition for IDENTIFIER." diff --git a/modules/tools/lookup/test/test-lookup.el b/modules/tools/lookup/test/test-lookup.el new file mode 100644 index 000000000..5a7bec011 --- /dev/null +++ b/modules/tools/lookup/test/test-lookup.el @@ -0,0 +1,35 @@ +;; -*- lexical-binding: t; no-byte-compile: t; -*- +;;; tools/lookup/test/test-lookup.el + +(describe "tools/lookup" + (before-all + (load! "../autoload/lookup")) + + (describe "xref fallback behavior" + (it "does not treat a no-op single xref result as success" + (with-temp-buffer + (insert "foo") + (goto-char (point-min)) + (let ((origin (point-marker)) + (xref-after-jump-hook nil)) + (unwind-protect + (cl-letf (((symbol-function 'xref-find-backend) + (lambda () 'fake)) + ((symbol-function 'xref-backend-definitions) + (lambda (_backend _identifier) + (list (xref-make "here" + (xref-make-buffer-location + (current-buffer) + (point)))))) + ;; Simulate a backend that triggers jump hooks without + ;; changing point/buffer. + ((symbol-function 'xref--show-defs) + (lambda (_fetcher _alist) + (run-hooks 'xref-after-jump-hook) + nil))) + (expect (+lookup--run-handlers + '+lookup-xref-definitions-backend-fn + "foo" + origin) + :to-be nil)) + (set-marker origin nil)))))))