Skip to content

Commit bbef4f4

Browse files
committed
*cider-error*: open a given exception in the Inspector by clicking it
Fixes #3565
1 parent 1299a4e commit bbef4f4

File tree

4 files changed

+87
-7
lines changed

4 files changed

+87
-7
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
## master (unreleased)
44

5+
### New features
6+
7+
- [#3565](https://github.com/clojure-emacs/cider/issues/3565): [`*cider-error*`](https://docs.cider.mx/cider/usage/dealing_with_errors.html#inspector-integration): open a given Exception in the [Inspector](https://docs.cider.mx/cider/debugging/inspector.html) by clicking it, or hitting <kbd>p</kbd>.
8+
59
### Changes
610

711
- CIDER [Inspector](https://docs.cider.mx/cider/debugging/inspector.html): display Java class/method/field info when available.

cider-inspector.el

+24
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,17 @@ See `cider-sync-request:inspect-push' and `cider-inspector--render-value'"
236236
(cider-inspector--render-value result 'v2)
237237
(cider-inspector-next-inspectable-object 1))))
238238

239+
(defun cider-inspector-inspect-last-exception (index)
240+
"Inspects the exception in the cause stack identified by INDEX."
241+
(interactive)
242+
(cl-assert (numberp index))
243+
(setq cider-inspector--current-repl (cider-current-repl))
244+
(let ((result (cider-sync-request:inspect-last-exception index 'v2)))
245+
(when (nrepl-dict-get result "value")
246+
(push (point) cider-inspector-location-stack)
247+
(cider-inspector--render-value result 'v2)
248+
(cider-inspector-next-inspectable-object 1))))
249+
239250
(defun cider-inspector-previous-sibling ()
240251
"Inspect the previous sibling value within a sequential parent.
241252
See `cider-sync-request:inspect-previous-sibling' and `cider-inspector--render-value'"
@@ -387,6 +398,19 @@ instead of just its \"value\" entry."
387398
result
388399
(nrepl-dict-get result "value"))))
389400

401+
;;;###autoload
402+
(defun cider-sync-request:inspect-last-exception (index &optional v2)
403+
"Inspects the exception in the cause stack identified by INDEX,
404+
V2 indicates if the entire response should be returned
405+
instead of just its \"value\" entry."
406+
(cl-assert (numberp index))
407+
(let ((result (thread-first `("op" "inspect-last-exception"
408+
"index" ,index)
409+
(cider-nrepl-send-sync-request cider-inspector--current-repl))))
410+
(if v2
411+
result
412+
(nrepl-dict-get result "value"))))
413+
390414
(defun cider-sync-request:inspect-next-sibling (&optional v2)
391415
"Inspect the next sibling value within a sequential parent,
392416
V2 indicates if the entire response should be returned

cider-stacktrace.el

+41-7
Original file line numberDiff line numberDiff line change
@@ -799,19 +799,52 @@ the NAME. The whole group is prefixed by string INDENT."
799799
(cider-stacktrace--insert-named-group indent2 "extras: \n")
800800
(cider-stacktrace-emit-indented extra (concat indent2 " ") nil t)))))))
801801

802-
(defun cider-stacktrace-render-cause (buffer cause num note)
803-
"Emit into BUFFER the CAUSE NUM, exception class, message, data, and NOTE."
802+
(declare-function cider-inspector-inspect-last-exception "cider-inspector")
803+
804+
(defun cider-stacktrace--inspect-class (event)
805+
"Mouse handler for EVENT."
806+
(interactive "e")
807+
(let* ((pos (posn-point (event-end event)))
808+
(window (posn-window (event-end event)))
809+
(buffer (window-buffer window))
810+
(inspect-index (with-current-buffer buffer
811+
(get-text-property pos 'inspect-index))))
812+
(cider-inspector-inspect-last-exception inspect-index)))
813+
814+
(defun cider-stacktrace--inspect-class-kbd ()
815+
"Keyboard handler."
816+
(interactive)
817+
(when-let ((inspect-index (get-text-property (point) 'inspect-index)))
818+
(cider-inspector-inspect-last-exception inspect-index)))
819+
820+
(defvar cider-stacktrace-exception-map
821+
(let ((map (make-sparse-keymap)))
822+
(define-key map [mouse-1] #'cider-stacktrace--inspect-class)
823+
(define-key map (kbd "p") #'cider-stacktrace--inspect-class-kbd)
824+
(define-key map (kbd "i") #'cider-stacktrace--inspect-class-kbd)
825+
map))
826+
827+
(defun cider-stacktrace-render-cause (buffer cause num note &optional inspect-index)
828+
"Emit into BUFFER the CAUSE NUM, exception class, message, data, and NOTE,
829+
make INSPECT-INDEX actionable if present."
804830
(with-current-buffer buffer
805831
(nrepl-dbind-response cause (class message data spec stacktrace)
806832
(let ((indent " ")
807833
(class-face 'cider-stacktrace-error-class-face)
808834
(message-face 'cider-stacktrace-error-message-face))
809835
(cider-propertize-region `(cause ,num)
810836
;; Detail level 0: exception class
811-
(cider-propertize-region '(detail 0)
837+
(cider-propertize-region `(detail
838+
0
839+
840+
inspect-index
841+
,inspect-index
842+
843+
keymap
844+
,cider-stacktrace-exception-map)
812845
(insert (format "%d. " num)
813846
(propertize note 'font-lock-face 'font-lock-comment-face) " "
814-
(propertize class 'font-lock-face class-face)
847+
(propertize class 'font-lock-face class-face 'mouse-face 'highlight)
815848
"\n"))
816849
;; Detail level 1: message + ex-data
817850
(cider-propertize-region '(detail 1)
@@ -885,10 +918,11 @@ through the `cider-stacktrace-suppressed-errors' variable."
885918
(cider-stacktrace-render-suppression-toggle buffer error-types)
886919
(insert "\n\n"))
887920
;; Stacktrace exceptions & frames
888-
(let ((num (length causes)))
921+
(let* ((causes-length (length causes))
922+
(num causes-length))
889923
(dolist (cause causes)
890-
(let ((note (if (= num (length causes)) "Unhandled" "Caused by")))
891-
(cider-stacktrace-render-cause buffer cause num note)
924+
(let ((note (if (= num causes-length) "Unhandled" "Caused by")))
925+
(cider-stacktrace-render-cause buffer cause num note (- causes-length num))
892926
(setq num (1- num))))))
893927
(cider-stacktrace-initialize causes)
894928
(font-lock-refresh-defaults)))

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

+18
Original file line numberDiff line numberDiff line change
@@ -295,3 +295,21 @@ Cider recognizes stacktraces printed in the following formats:
295295
buffer. When `cider-stacktrace-analyze-at-point` fails to detect the
296296
stacktrace, `cider-stacktrace-analyze-in-region` can be used to
297297
select the stacktrace manually.
298+
299+
== Inspector integration
300+
301+
Within `*cider-error*`, when clicking directly a top-level exception (any of them in the cause chain),
302+
that specific exception will be inspected with the CIDER xref:debugging/inspector.adoc[Inspector].
303+
304+
This allows you to better understand intrincate `ex-data`.
305+
306+
This clicking is defined and customizable in `cider-stacktrace-exception-map`, which has the following defaults:
307+
308+
=== Keybindings
309+
310+
|===
311+
| Action | Description
312+
313+
| kbd:[click] or kbd:[i] or kbd:[p]
314+
| Open the given exception in the Inspector.
315+
|===

0 commit comments

Comments
 (0)