Skip to content

Commit 15b6d20

Browse files
authored
[Fix #2831] Add xref integration (#3026)
xref.el is an Emacs built-in package that was introduced in Emacs 25.1.
1 parent aa6cd9f commit 15b6d20

File tree

4 files changed

+91
-2
lines changed

4 files changed

+91
-2
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
### New features
66

7+
* [#2831](https://github.com/clojure-emacs/cider/issues/2831): Add xref integration.
78
* [#3017](https://github.com/clojure-emacs/cider/issues/3017): Annotate company completion kinds.
89

910
### Bugs fixed

cider-find.el

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,13 @@
3232

3333
(require 'thingatpt)
3434

35+
(defcustom cider-use-xref t
36+
"Enable xref integration."
37+
:type 'boolean
38+
:safe #'booleanp
39+
:group 'cider
40+
:version '(cider . "1.2.0"))
41+
3542
(defun cider--find-var-other-window (var &optional line)
3643
"Find the definition of VAR, optionally at a specific LINE.
3744
@@ -226,5 +233,71 @@ thing at point."
226233
(cider--find-ns kw-ns arg)
227234
(search-forward-regexp kw-to-find nil 'noerror)))
228235

236+
(defun cider--xref-backend ()
237+
"Used for xref integration."
238+
'cider)
239+
240+
(cl-defmethod xref-backend-identifier-at-point ((_backend (eql cider)))
241+
"Return the relevant identifier at point."
242+
(cider-symbol-at-point 'look-back))
243+
244+
(defun cider--var-to-xref-location (var)
245+
"Get location of definition of VAR."
246+
(when-let* ((info (cider-var-info var))
247+
(line (nrepl-dict-get info "line"))
248+
(file (nrepl-dict-get info "file"))
249+
(buf (cider--find-buffer-for-file file)))
250+
(xref-make-buffer-location
251+
buf
252+
(with-current-buffer buf
253+
(save-excursion
254+
(goto-char 0)
255+
(forward-line (1- line))
256+
(back-to-indentation)
257+
(point))))))
258+
259+
(cl-defmethod xref-backend-definitions ((_backend (eql cider)) var)
260+
"Find definitions of VAR."
261+
(cider-ensure-connected)
262+
(cider-ensure-op-supported "ns-path")
263+
(when-let* ((loc (cider--var-to-xref-location var)))
264+
(list (xref-make var loc))))
265+
266+
(cl-defmethod xref-backend-identifier-completion-table ((_backend (eql cider)))
267+
"Return the completion table for identifiers."
268+
(cider-ensure-connected)
269+
(when-let* ((ns (cider-current-ns))
270+
(results (cider-sync-request:ns-vars ns)))
271+
results))
272+
273+
(cl-defmethod xref-backend-references ((_backend (eql cider)) var)
274+
"Find references of VAR."
275+
(cider-ensure-connected)
276+
(cider-ensure-op-supported "fn-refs")
277+
(when-let* ((ns (cider-current-ns))
278+
(results (cider-sync-request:fn-refs ns var)))
279+
(mapcar (lambda (info)
280+
(let* ((filename (nrepl-dict-get info "file"))
281+
(column (nrepl-dict-get info "column"))
282+
(line (nrepl-dict-get info "line"))
283+
(loc (xref-make-file-location filename line column)))
284+
(xref-make filename loc)))
285+
results)))
286+
287+
(cl-defmethod xref-backend-apropos ((_backend (eql cider)) pattern)
288+
"Find all symbols that match regexp PATTERN."
289+
(cider-ensure-connected)
290+
(cider-ensure-op-supported "apropos")
291+
(when-let* ((ns (cider-current-ns))
292+
(results (cider-sync-request:apropos pattern ns t t completion-ignore-case)))
293+
(mapcar (lambda (info)
294+
(let* ((symbol (nrepl-dict-get info "name"))
295+
(loc (cider--var-to-xref-location symbol))
296+
(type (nrepl-dict-get info "type"))
297+
(doc (nrepl-dict-get info "doc")))
298+
(xref-make (format "[%s] %s\n %s" (propertize symbol 'face 'bold) (capitalize type) doc)
299+
loc)))
300+
results)))
301+
229302
(provide 'cider-find)
230303
;;; cider-find.el ends here

cider-mode.el

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
(require 'cider-profile) ; required only for the menu
4141
(require 'cider-completion)
4242
(require 'cider-inspector)
43+
(require 'cider-find)
4344
(require 'subr-x)
4445
(require 'cider-compat)
4546

@@ -478,12 +479,13 @@ As it stands Emacs fires these events on <mouse-8> and <mouse-9> on 'x' and
478479
(defconst cider-mode-map
479480
(let ((map (make-sparse-keymap)))
480481
(define-key map (kbd "C-c C-d") 'cider-doc-map)
481-
(define-key map (kbd "M-.") #'cider-find-var)
482+
(unless cider-use-xref
483+
(define-key map (kbd "M-.") #'cider-find-var)
484+
(define-key map (kbd "M-,") #'cider-pop-back))
482485
(define-key map (kbd (if cider--has-many-mouse-buttons "<mouse-8>" "<mouse-4>")) #'xref-pop-marker-stack)
483486
(define-key map (kbd (if cider--has-many-mouse-buttons "<mouse-9>" "<mouse-5>")) #'cider-find-dwim-at-mouse)
484487
(define-key map (kbd "C-c C-.") #'cider-find-ns)
485488
(define-key map (kbd "C-c C-:") #'cider-find-keyword)
486-
(define-key map (kbd "M-,") #'cider-pop-back)
487489
(define-key map (kbd "C-c M-.") #'cider-find-resource)
488490
(define-key map (kbd "M-TAB") #'complete-symbol)
489491
(define-key map (kbd "C-M-x") #'cider-eval-defun-at-point)
@@ -1053,13 +1055,17 @@ property."
10531055
(when cider-dynamic-indentation
10541056
(setq-local clojure-get-indent-function #'cider--get-symbol-indent))
10551057
(setq-local clojure-expected-ns-function #'cider-expected-ns)
1058+
(when cider-use-xref
1059+
(add-hook 'xref-backend-functions #'cider--xref-backend nil 'local))
10561060
(setq next-error-function #'cider-jump-to-compilation-error))
10571061
;; Mode cleanup
10581062
(mapc #'kill-local-variable '(completion-at-point-functions
10591063
next-error-function
10601064
x-gtk-use-system-tooltips
10611065
font-lock-fontify-region-function
10621066
clojure-get-indent-function))
1067+
(when cider-use-xref
1068+
(remove-hook 'xref-backend-functions #'cider--xref-backend 'local))
10631069
(remove-hook 'font-lock-mode-hook #'cider-refresh-dynamic-font-lock 'local)
10641070
(font-lock-add-keywords nil cider--reader-conditionals-font-lock-keywords)
10651071
(font-lock-remove-keywords nil cider--dynamic-font-lock-keywords)

doc/modules/ROOT/pages/usage/misc_features.adoc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,3 +343,12 @@ to format EDN using `clojure.tools.reader.edn`. The following commands are provi
343343
* `cider-format-edn-defun`
344344
* `cider-format-edn-region`
345345
* `cider-format-edn-buffer`
346+
347+
== https://www.gnu.org/software/emacs/manual/html_node/emacs/Xref.html[Xref] integration
348+
349+
Beginning with version 1.2.0, cider support Emacs built-in xref, which means `M-.` (xref-find-definitions) will just work as expected. You can disable it with:
350+
351+
[source,lisp]
352+
----
353+
(setq cider-user-xref nil)
354+
----

0 commit comments

Comments
 (0)