Skip to content

Commit

Permalink
Introduce cider-ignored-error-phases
Browse files Browse the repository at this point in the history
Fixes #3418
  • Loading branch information
vemv committed Aug 22, 2023
1 parent 9b1c9ae commit 003ebfa
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 6 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
- `cider-test`: add timing information.
- `cider-test`: fail-fast by default, as controlled by the new `cider-test-fail-fast` defcustom and `cider-test-toggle-fail-fast` keybinding.
- Infer indentation specs when possible ([doc](https://docs.cider.mx/cider/indent_spec.html#indentation-inference)).
- [#3418](https://github.com/clojure-emacs/cider/issues/3418): Introduce `cider-clojure-compilation-error-phases`.
- This prevents stacktraces from showing up whenever the [:clojure.error/phase](https://clojure.org/reference/repl_and_main#_at_repl) indicates that it's a compilation error.
- Add new customization variable `cider-clojurec-eval-destination` to allow specifying which REPL CLJC evals are sent to.
- [#3354](https://github.com/clojure-emacs/cider/issues/3354): Add new customization variable `cider-reuse-dead-repls` to control how dead REPL buffers are reused on new connections.

Expand Down
50 changes: 44 additions & 6 deletions cider-eval.el
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,15 @@ not to be automatically shown.
Irrespective of the value of this variable, the `cider-error-buffer' is
always generated in the background. Use `cider-selector' to
navigate to this buffer."
navigate to this buffer.
Please note, if the error phase belongs to
one of the `cider-clojure-compilation-error-phases',
then no stacktrace showing will happen.
That defcustom takes precedence over this one.
See its doc for understanding its rationale. You can also customize it to nil
in order to void its effect."
:type '(choice (const :tag "always" t)
(const except-in-repl)
(const only-in-repl)
Expand Down Expand Up @@ -478,32 +486,62 @@ op/situation that originated this error."
(let ((error-buffer (cider-new-error-buffer #'cider-stacktrace-mode error-types)))
(cider-stacktrace-render error-buffer (reverse causes) error-types))))

(defun cider--handle-stacktrace-response (response causes)
"Handle stacktrace op RESPONSE, aggregating the result into CAUSES.
(defcustom cider-clojure-compilation-error-phases '("read-source"
"macro-syntax-check"
"macroexpansion"
"compile-syntax-check"
"compilation"
;; "execution" is certainly not to be included here.
;; "read-eval-result" and "print-eval-result" are not to be included here,
;; because they mean that the code has been successfully executed.
)
"Error phases which will not cause the `*cider-error*' buffer to pop up.
The default value results in no stacktrace being shown for compile-time errors.
Note that `*cider-error*' pop behavior is otherwise controlled
by the `cider-show-error-buffer' defcustom.
`cider-clojure-compilation-error-phases' takes precedence.
If you wish phases to be ignored, set this variable to nil instead.
You can learn more about Clojure's error phases at:
https://clojure.org/reference/repl_and_main#_at_repl"
:type 'list
:group 'cider
:package-version '(cider . "0.18.0"))

(defun cider--handle-stacktrace-response (response causes ex-phase)
"Handle stacktrace RESPONSE, aggregate the result into CAUSES, honor EX-PHASE.
If RESPONSE contains a cause, cons it onto CAUSES and return that. If
RESPONSE is the final message (i.e. it contains a status), render CAUSES
into a new error buffer."
(nrepl-dbind-response response (class msg status type)
(cond ((and (member "notification" status) causes)
(nrepl-notify msg type))
(class (cons response causes))
(status (cider--render-stacktrace-causes causes)))))
(status
(unless (member ex-phase cider-clojure-compilation-error-phases)
(cider--render-stacktrace-causes causes))))))

(defun cider-default-err-op-handler ()
"Display the last exception, with middleware support."
;; Causes are returned as a series of messages, which we aggregate in `causes'
(let (causes)
(let (causes ex-phase)
(cider-nrepl-send-request
(thread-last
(map-merge 'list
'(("op" "analyze-last-stacktrace"))
(cider--nrepl-print-request-map fill-column))
(seq-mapcat #'identity))
(lambda (response)
(nrepl-dbind-response response (phase)
(when phase
(setq ex-phase phase)))
;; While the return value of `cider--handle-stacktrace-response' is not
;; meaningful for the last message, we do not need the value of `causes'
;; after it has been handled, so it's fine to set it unconditionally here
(setq causes (cider--handle-stacktrace-response response causes))))))
(setq causes (cider--handle-stacktrace-response response causes ex-phase))))))

(defun cider-default-err-handler ()
"This function determines how the error buffer is shown.
Expand Down
13 changes: 13 additions & 0 deletions doc/modules/ROOT/pages/usage/dealing_with_errors.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,19 @@ temporary overlay or in the echo area:
(setq cider-show-error-buffer nil)
----

Starting from CIDER 1.8.0, only runtime exceptions (and not compilation errors)
will cause a stacktrace buffer to be shown. This better follows Clojure 1.10's
https://clojure.org/reference/repl_and_main#_at_repl[intended semantics].
This behavior is controlled by the `cider-clojure-compilation-error-phases` configuration option.
If you wish for the error phase to be ignored, and to only take `cider-show-error-buffer` into account,
please customize:

[source,lisp]
----
(setq cider-clojure-compilation-error-phases nil)
----


At times, the error being displayed will originate from a bug in CIDER
itself. These internal errors might frequently occur and interrupt
your workflow, but you might not want to suppress *all* stacktrace
Expand Down

0 comments on commit 003ebfa

Please sign in to comment.