Skip to content

Commit 9edb2d2

Browse files
vemvbbatsov
authored andcommitted
cider-ns-refresh: summarize errors as an overlay
Fixes #3628
1 parent cfe2de3 commit 9edb2d2

File tree

4 files changed

+189
-2
lines changed

4 files changed

+189
-2
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
### Changes
1212

1313
- [#3626](https://github.com/clojure-emacs/cider/issues/3626): `cider-ns-refresh`: jump to the relevant file/line on errors.
14+
- [#3628](https://github.com/clojure-emacs/cider/issues/3628): `cider-ns-refresh`: summarize errors as an overlay.
1415
- Bump the injected nREPL to [1.1.1](https://github.com/nrepl/nrepl/blob/v1.1.1/CHANGELOG.md#111-2024-02-20).
1516
- Bump the injected `cider-nrepl` to [0.46.0](https://github.com/clojure-emacs/cider-nrepl/blob/1cc9b2/CHANGELOG.md#0460-2024-0305).
1617
- Updates [Orchard](https://github.com/clojure-emacs/orchard/blob/v0.23.0/CHANGELOG.md#0230-2024-03-03).

cider-ns.el

+17-2
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,8 @@ namespace-qualified function of zero arity."
120120

121121
(defun cider-ns--present-error (error)
122122
"Render the `ERROR' stacktrace,
123-
and jump to the adequate file/line location."
123+
and jump to the adequate file/line location,
124+
presenting the error message as an overlay."
124125
(let* ((buf)
125126
(jump-args (seq-some (lambda (cause-dict) ;; a dict representing an exception cause
126127
(nrepl-dbind-response cause-dict (file-url line column)
@@ -132,7 +133,21 @@ and jump to the adequate file/line location."
132133
(list buf (cons line column)))))
133134
error)))
134135
(when jump-args
135-
(apply #'cider-jump-to jump-args))
136+
(apply #'cider-jump-to jump-args)
137+
(when-let ((message (seq-some (lambda (cause-dict)
138+
(nrepl-dbind-response cause-dict (message)
139+
message))
140+
;; `reverse' the causes as the first one typically is a CompilerException, which the second one is the actual exception:
141+
(reverse error))))
142+
(with-current-buffer buf
143+
(let ((cider-result-use-clojure-font-lock nil)
144+
(trimmed-err (funcall cider-inline-error-message-function message)))
145+
(cider--display-interactive-eval-result trimmed-err
146+
'error
147+
(save-excursion
148+
(end-of-defun)
149+
(point))
150+
'cider-error-overlay-face)))))
136151
(cider--render-stacktrace-causes error)
137152
;; Select the window displaying the 'culprit' buffer so that the user can immediately fix it,
138153
;; as most times the displayed stacktrace doesn't need much inspection:

test/cider-ns-tests.el

+169
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,172 @@
3434
(it "raises a user error if cider is not connected"
3535
(spy-on 'cider-connected-p :and-return-value nil)
3636
(expect (cider-ns-refresh) :to-throw 'user-error)))
37+
38+
(defvar cider-ns-tests--sample-file-url
39+
"file:test/cider_ns_tests.clj")
40+
41+
(defvar cider-ns-tests--sample-causes
42+
`((dict "class" "clojure.lang.Compiler$CompilerException" "column" 0 "compile-like" "false" "data" "{:clojure.error/phase :read-source,
43+
:clojure.error/line 23,
44+
:clojure.error/column 0,
45+
:clojure.error/source \"gpml/handler/chat.clj\"}" "file" "gpml/handler/chat.clj" "file-url" ,cider-ns-tests--sample-file-url "line" 23 "location"
46+
(dict "clojure.error/column" 0 "clojure.error/line" 23 "clojure.error/phase" "read-source" "clojure.error/source" "gpml/handler/chat.clj")
47+
"message" "Syntax error reading source at (gpml/handler/chat.clj:23:0)." "path" "gpml/handler/chat.clj" "phase" "read-source" "stacktrace"
48+
((dict "class" "clojure.lang.Compiler" "file" "Compiler.java" "file-url" nil "flags"
49+
("tooling" "java")
50+
"line" 7643 "method" "load" "name" "clojure.lang.Compiler/load" "type" "java")
51+
(dict "class" "clojure.lang.RT" "file" "RT.java" "file-url" nil "flags"
52+
("tooling" "java")
53+
"line" 381 "method" "loadResourceScript" "name" "clojure.lang.RT/loadResourceScript" "type" "java")
54+
(dict "class" "clojure.lang.RT" "file" "RT.java" "file-url" nil "flags"
55+
("dup" "tooling" "java")
56+
"line" 372 "method" "loadResourceScript" "name" "clojure.lang.RT/loadResourceScript" "type" "java")
57+
(dict "class" "clojure.lang.RT" "file" "RT.java" "file-url" nil "flags"
58+
("tooling" "java")
59+
"line" 459 "method" "load" "name" "clojure.lang.RT/load" "type" "java")
60+
(dict "class" "clojure.lang.RT" "file" "RT.java" "file-url" nil "flags"
61+
("dup" "tooling" "java")
62+
"line" 424 "method" "load" "name" "clojure.lang.RT/load" "type" "java")
63+
(dict "class" "clojure.core$load$fn__6924" "file" "core.clj" "file-url" "jar:file:/Users/vemv/.m2/repository/org/clojure/clojure/1.12.900/clojure-1.12.900.jar!/clojure/core.clj" "flags"
64+
("clj")
65+
"fn" "load/fn" "line" 6167 "method" "invoke" "name" "clojure.core$load$fn__6924/invoke" "ns" "clojure.core" "type" "clj" "var" "clojure.core/load")
66+
(dict "class" "clojure.core$load" "file" "core.clj" "file-url" "jar:file:/Users/vemv/.m2/repository/org/clojure/clojure/1.12.900/clojure-1.12.900.jar!/clojure/core.clj" "flags"
67+
("clj")
68+
"fn" "load" "line" 6166 "method" "invokeStatic" "name" "clojure.core$load/invokeStatic" "ns" "clojure.core" "type" "clj" "var" "clojure.core/load")
69+
(dict "class" "clojure.core$load" "file" "core.clj" "file-url" "jar:file:/Users/vemv/.m2/repository/org/clojure/clojure/1.12.900/clojure-1.12.900.jar!/clojure/core.clj" "flags"
70+
("clj")
71+
"fn" "load" "line" 6150 "method" "doInvoke" "name" "clojure.core$load/doInvoke" "ns" "clojure.core" "type" "clj" "var" "clojure.core/load")
72+
(dict "class" "clojure.lang.RestFn" "file" "RestFn.java" "file-url" nil "flags"
73+
("tooling" "java")
74+
"line" 411 "method" "invoke" "name" "clojure.lang.RestFn/invoke" "type" "java")
75+
(dict "class" "clojure.core$load_one" "file" "core.clj" "file-url" "jar:file:/Users/vemv/.m2/repository/org/clojure/clojure/1.12.900/clojure-1.12.900.jar!/clojure/core.clj" "flags"
76+
("clj")
77+
"fn" "load-one" "line" 5939 "method" "invokeStatic" "name" "clojure.core$load_one/invokeStatic" "ns" "clojure.core" "type" "clj" "var" "clojure.core/load-one")
78+
(dict "class" "clojure.core$load_one" "file" "core.clj" "file-url" "jar:file:/Users/vemv/.m2/repository/org/clojure/clojure/1.12.900/clojure-1.12.900.jar!/clojure/core.clj" "flags"
79+
("clj")
80+
"fn" "load-one" "line" 5934 "method" "invoke" "name" "clojure.core$load_one/invoke" "ns" "clojure.core" "type" "clj" "var" "clojure.core/load-one")
81+
(dict "class" "clojure.core$load_lib$fn__6866" "file" "core.clj" "file-url" "jar:file:/Users/vemv/.m2/repository/org/clojure/clojure/1.12.900/clojure-1.12.900.jar!/clojure/core.clj" "flags"
82+
("clj")
83+
"fn" "load-lib/fn" "line" 5981 "method" "invoke" "name" "clojure.core$load_lib$fn__6866/invoke" "ns" "clojure.core" "type" "clj" "var" "clojure.core/load-lib")
84+
(dict "class" "clojure.core$load_lib" "file" "core.clj" "file-url" "jar:file:/Users/vemv/.m2/repository/org/clojure/clojure/1.12.900/clojure-1.12.900.jar!/clojure/core.clj" "flags"
85+
("clj")
86+
"fn" "load-lib" "line" 5980 "method" "invokeStatic" "name" "clojure.core$load_lib/invokeStatic" "ns" "clojure.core" "type" "clj" "var" "clojure.core/load-lib")
87+
(dict "class" "clojure.core$load_lib" "file" "core.clj" "file-url" "jar:file:/Users/vemv/.m2/repository/org/clojure/clojure/1.12.900/clojure-1.12.900.jar!/clojure/core.clj" "flags"
88+
("clj")
89+
"fn" "load-lib" "line" 5959 "method" "doInvoke" "name" "clojure.core$load_lib/doInvoke" "ns" "clojure.core" "type" "clj" "var" "clojure.core/load-lib")
90+
(dict "class" "clojure.lang.RestFn" "file" "RestFn.java" "file-url" nil "flags"
91+
("tooling" "java")
92+
"line" 145 "method" "applyTo" "name" "clojure.lang.RestFn/applyTo" "type" "java")
93+
(dict "class" "clojure.core$apply" "file" "core.clj" "file-url" "jar:file:/Users/vemv/.m2/repository/org/clojure/clojure/1.12.900/clojure-1.12.900.jar!/clojure/core.clj" "flags"
94+
("tooling" "clj")
95+
"fn" "apply" "line" 669 "method" "invokeStatic" "name" "clojure.core$apply/invokeStatic" "ns" "clojure.core" "type" "clj" "var" "clojure.core/apply")
96+
(dict "class" "clojure.core$load_libs" "file" "core.clj" "file-url" "jar:file:/Users/vemv/.m2/repository/org/clojure/clojure/1.12.900/clojure-1.12.900.jar!/clojure/core.clj" "flags"
97+
("clj")
98+
"fn" "load-libs" "line" 6022 "method" "invokeStatic" "name" "clojure.core$load_libs/invokeStatic" "ns" "clojure.core" "type" "clj" "var" "clojure.core/load-libs")
99+
(dict "class" "clojure.core$load_libs" "file" "core.clj" "file-url" "jar:file:/Users/vemv/.m2/repository/org/clojure/clojure/1.12.900/clojure-1.12.900.jar!/clojure/core.clj" "flags"
100+
("clj")
101+
"fn" "load-libs" "line" 6006 "method" "doInvoke" "name" "clojure.core$load_libs/doInvoke" "ns" "clojure.core" "type" "clj" "var" "clojure.core/load-libs")
102+
(dict "class" "clojure.lang.RestFn" "file" "RestFn.java" "file-url" nil "flags"
103+
("tooling" "java")
104+
"line" 140 "method" "applyTo" "name" "clojure.lang.RestFn/applyTo" "type" "java")
105+
(dict "class" "clojure.core$apply" "file" "core.clj" "file-url" "jar:file:/Users/vemv/.m2/repository/org/clojure/clojure/1.12.900/clojure-1.12.900.jar!/clojure/core.clj" "flags"
106+
("tooling" "clj")
107+
"fn" "apply" "line" 669 "method" "invokeStatic" "name" "clojure.core$apply/invokeStatic" "ns" "clojure.core" "type" "clj" "var" "clojure.core/apply")
108+
(dict "class" "clojure.core$require" "file" "core.clj" "file-url" "jar:file:/Users/vemv/.m2/repository/org/clojure/clojure/1.12.900/clojure-1.12.900.jar!/clojure/core.clj" "flags"
109+
("clj")
110+
"fn" "require" "line" 6044 "method" "invokeStatic" "name" "clojure.core$require/invokeStatic" "ns" "clojure.core" "type" "clj" "var" "clojure.core/require")
111+
(dict "class" "clojure.core$require" "file" "core.clj" "file-url" "jar:file:/Users/vemv/.m2/repository/org/clojure/clojure/1.12.900/clojure-1.12.900.jar!/clojure/core.clj" "flags"
112+
("dup" "clj")
113+
"fn" "require" "line" 6044 "method" "doInvoke" "name" "clojure.core$require/doInvoke" "ns" "clojure.core" "type" "clj" "var" "clojure.core/require")
114+
(dict "class" "clojure.lang.RestFn" "file" "RestFn.java" "file-url" nil "flags"
115+
("tooling" "java")
116+
"line" 424 "method" "invoke" "name" "clojure.lang.RestFn/invoke" "type" "java")))
117+
(dict "class" "java.lang.RuntimeException" "compile-like" "false" "message" "Invalid token: :::a" "phase" nil "stacktrace"
118+
((dict "class" "clojure.lang.Util" "file" "Util.java" "file-url" nil "flags"
119+
("java")
120+
"line" 221 "method" "runtimeException" "name" "clojure.lang.Util/runtimeException" "type" "java")
121+
(dict "class" "clojure.lang.LispReader" "file" "LispReader.java" "file-url" nil "flags"
122+
("java")
123+
"line" 412 "method" "interpretToken" "name" "clojure.lang.LispReader/interpretToken" "type" "java")
124+
(dict "class" "clojure.lang.LispReader" "file" "LispReader.java" "file-url" nil "flags"
125+
("java")
126+
"line" 305 "method" "read" "name" "clojure.lang.LispReader/read" "type" "java")
127+
(dict "class" "clojure.lang.LispReader" "file" "LispReader.java" "file-url" nil "flags"
128+
("dup" "java")
129+
"line" 216 "method" "read" "name" "clojure.lang.LispReader/read" "type" "java")
130+
(dict "class" "clojure.lang.Compiler" "file" "Compiler.java" "file-url" nil "flags"
131+
("tooling" "java")
132+
"line" 7631 "method" "load" "name" "clojure.lang.Compiler/load" "type" "java")
133+
(dict "class" "clojure.lang.RT" "file" "RT.java" "file-url" nil "flags"
134+
("tooling" "java")
135+
"line" 381 "method" "loadResourceScript" "name" "clojure.lang.RT/loadResourceScript" "type" "java")
136+
(dict "class" "clojure.lang.RT" "file" "RT.java" "file-url" nil "flags"
137+
("dup" "tooling" "java")
138+
"line" 372 "method" "loadResourceScript" "name" "clojure.lang.RT/loadResourceScript" "type" "java")
139+
(dict "class" "clojure.lang.RT" "file" "RT.java" "file-url" nil "flags"
140+
("tooling" "java")
141+
"line" 459 "method" "load" "name" "clojure.lang.RT/load" "type" "java")
142+
(dict "class" "clojure.lang.RT" "file" "RT.java" "file-url" nil "flags"
143+
("dup" "tooling" "java")
144+
"line" 424 "method" "load" "name" "clojure.lang.RT/load" "type" "java")
145+
(dict "class" "clojure.core$load$fn__6924" "file" "core.clj" "file-url" "jar:file:/Users/vemv/.m2/repository/org/clojure/clojure/1.12.900/clojure-1.12.900.jar!/clojure/core.clj" "flags"
146+
("clj")
147+
"fn" "load/fn" "line" 6167 "method" "invoke" "name" "clojure.core$load$fn__6924/invoke" "ns" "clojure.core" "type" "clj" "var" "clojure.core/load")
148+
(dict "class" "clojure.core$load" "file" "core.clj" "file-url" "jar:file:/Users/vemv/.m2/repository/org/clojure/clojure/1.12.900/clojure-1.12.900.jar!/clojure/core.clj" "flags"
149+
("clj")
150+
"fn" "load" "line" 6166 "method" "invokeStatic" "name" "clojure.core$load/invokeStatic" "ns" "clojure.core" "type" "clj" "var" "clojure.core/load")
151+
(dict "class" "clojure.core$load" "file" "core.clj" "file-url" "jar:file:/Users/vemv/.m2/repository/org/clojure/clojure/1.12.900/clojure-1.12.900.jar!/clojure/core.clj" "flags"
152+
("clj")
153+
"fn" "load" "line" 6150 "method" "doInvoke" "name" "clojure.core$load/doInvoke" "ns" "clojure.core" "type" "clj" "var" "clojure.core/load")
154+
(dict "class" "clojure.lang.RestFn" "file" "RestFn.java" "file-url" nil "flags"
155+
("tooling" "java")
156+
"line" 411 "method" "invoke" "name" "clojure.lang.RestFn/invoke" "type" "java")
157+
(dict "class" "clojure.core$load_one" "file" "core.clj" "file-url" "jar:file:/Users/vemv/.m2/repository/org/clojure/clojure/1.12.900/clojure-1.12.900.jar!/clojure/core.clj" "flags"
158+
("clj")
159+
"fn" "load-one" "line" 5939 "method" "invokeStatic" "name" "clojure.core$load_one/invokeStatic" "ns" "clojure.core" "type" "clj" "var" "clojure.core/load-one")
160+
(dict "class" "clojure.core$load_one" "file" "core.clj" "file-url" "jar:file:/Users/vemv/.m2/repository/org/clojure/clojure/1.12.900/clojure-1.12.900.jar!/clojure/core.clj" "flags"
161+
("clj")
162+
"fn" "load-one" "line" 5934 "method" "invoke" "name" "clojure.core$load_one/invoke" "ns" "clojure.core" "type" "clj" "var" "clojure.core/load-one")
163+
(dict "class" "clojure.core$load_lib$fn__6866" "file" "core.clj" "file-url" "jar:file:/Users/vemv/.m2/repository/org/clojure/clojure/1.12.900/clojure-1.12.900.jar!/clojure/core.clj" "flags"
164+
("clj")
165+
"fn" "load-lib/fn" "line" 5981 "method" "invoke" "name" "clojure.core$load_lib$fn__6866/invoke" "ns" "clojure.core" "type" "clj" "var" "clojure.core/load-lib")
166+
(dict "class" "clojure.core$load_lib" "file" "core.clj" "file-url" "jar:file:/Users/vemv/.m2/repository/org/clojure/clojure/1.12.900/clojure-1.12.900.jar!/clojure/core.clj" "flags"
167+
("clj")
168+
"fn" "load-lib" "line" 5980 "method" "invokeStatic" "name" "clojure.core$load_lib/invokeStatic" "ns" "clojure.core" "type" "clj" "var" "clojure.core/load-lib")
169+
(dict "class" "clojure.core$load_lib" "file" "core.clj" "file-url" "jar:file:/Users/vemv/.m2/repository/org/clojure/clojure/1.12.900/clojure-1.12.900.jar!/clojure/core.clj" "flags"
170+
("clj")
171+
"fn" "load-lib" "line" 5959 "method" "doInvoke" "name" "clojure.core$load_lib/doInvoke" "ns" "clojure.core" "type" "clj" "var" "clojure.core/load-lib")
172+
(dict "class" "clojure.lang.RestFn" "file" "RestFn.java" "file-url" nil "flags"
173+
("tooling" "java")
174+
"line" 145 "method" "applyTo" "name" "clojure.lang.RestFn/applyTo" "type" "java")
175+
(dict "class" "clojure.core$apply" "file" "core.clj" "file-url" "jar:file:/Users/vemv/.m2/repository/org/clojure/clojure/1.12.900/clojure-1.12.900.jar!/clojure/core.clj" "flags"
176+
("tooling" "clj")
177+
"fn" "apply" "line" 669 "method" "invokeStatic" "name" "clojure.core$apply/invokeStatic" "ns" "clojure.core" "type" "clj" "var" "clojure.core/apply")
178+
(dict "class" "clojure.core$load_libs" "file" "core.clj" "file-url" "jar:file:/Users/vemv/.m2/repository/org/clojure/clojure/1.12.900/clojure-1.12.900.jar!/clojure/core.clj" "flags"
179+
("clj")
180+
"fn" "load-libs" "line" 6022 "method" "invokeStatic" "name" "clojure.core$load_libs/invokeStatic" "ns" "clojure.core" "type" "clj" "var" "clojure.core/load-libs")
181+
(dict "class" "clojure.core$load_libs" "file" "core.clj" "file-url" "jar:file:/Users/vemv/.m2/repository/org/clojure/clojure/1.12.900/clojure-1.12.900.jar!/clojure/core.clj" "flags"
182+
("clj")
183+
"fn" "load-libs" "line" 6006 "method" "doInvoke" "name" "clojure.core$load_libs/doInvoke" "ns" "clojure.core" "type" "clj" "var" "clojure.core/load-libs")
184+
(dict "class" "clojure.lang.RestFn" "file" "RestFn.java" "file-url" nil "flags"
185+
("tooling" "java")
186+
"line" 140 "method" "applyTo" "name" "clojure.lang.RestFn/applyTo" "type" "java")
187+
(dict "class" "clojure.core$apply" "file" "core.clj" "file-url" "jar:file:/Users/vemv/.m2/repository/org/clojure/clojure/1.12.900/clojure-1.12.900.jar!/clojure/core.clj" "flags"
188+
("tooling" "clj")
189+
"fn" "apply" "line" 669 "method" "invokeStatic" "name" "clojure.core$apply/invokeStatic" "ns" "clojure.core" "type" "clj" "var" "clojure.core/apply")
190+
(dict "class" "clojure.core$require" "file" "core.clj" "file-url" "jar:file:/Users/vemv/.m2/repository/org/clojure/clojure/1.12.900/clojure-1.12.900.jar!/clojure/core.clj" "flags"
191+
("clj")
192+
"fn" "require" "line" 6044 "method" "invokeStatic" "name" "clojure.core$require/invokeStatic" "ns" "clojure.core" "type" "clj" "var" "clojure.core/require")
193+
(dict "class" "clojure.core$require" "file" "core.clj" "file-url" "jar:file:/Users/vemv/.m2/repository/org/clojure/clojure/1.12.900/clojure-1.12.900.jar!/clojure/core.clj" "flags"
194+
("dup" "clj")
195+
"fn" "require" "line" 6044 "method" "doInvoke" "name" "clojure.core$require/doInvoke" "ns" "clojure.core" "type" "clj" "var" "clojure.core/require")
196+
(dict "class" "clojure.lang.RestFn" "file" "RestFn.java" "file-url" nil "flags"
197+
("tooling" "java")
198+
"line" 424 "method" "invoke" "name" "clojure.lang.RestFn/invoke" "type" "java") ))))
199+
200+
(describe "cider-ns--present-error"
201+
(it "Works without throwing errors"
202+
(with-clojure-buffer ""
203+
(cider-ns--present-error cider-ns-tests--sample-causes)
204+
(when-let ((b (get-buffer "*cider-error*"))) ;; Clean it up for other tests
205+
(kill-buffer b)))))

test/cider_ns_tests.clj

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
(ns cider-ns-tests
2+
"Supports cider-ns-tests.el")

0 commit comments

Comments
 (0)