Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce cider-ignored-error-phases #3423

Merged
merged 3 commits into from
Aug 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 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 Expand Up @@ -42,7 +44,7 @@
- [#3375](https://github.com/clojure-emacs/cider/pull/3375): `cider-test`: don't render a newline between expected and actual, most times.
- Improve `nrepl-dict` error reporting.
- Bump the injected `piggieback` to [0.5.3](https://github.com/nrepl/piggieback/blob/0.5.3/CHANGES.md#053-2021-10-26).
- Bump the injected `cider-nrepl` to [0.35.1](https://github.com/clojure-emacs/cider-nrepl/blob/v0.35.1/CHANGELOG.md#0351-2023-08-18).
- Bump the injected `cider-nrepl` to [0.36.0](https://github.com/clojure-emacs/cider-nrepl/blob/v0.36.0/CHANGELOG.md#0360-2023-08-21).
- Improves indentation, font-locking and other metadata support for ClojureScript.
- Updates [Orchard](https://github.com/clojure-emacs/orchard/blob/v0.14.2/CHANGELOG.md)
- introduces support for displaying the docstring and arglists of 'indirect' vars (e.g. `(def foo bar)`) for Clojure/Script.
Expand All @@ -51,7 +53,8 @@
- avoiding side-effecting `->` evaluation for pure-ClojureScript chains.
- Updates [Compliment](https://github.com/alexander-yakushev/compliment/blob/0.4.0/CHANGELOG.md#040-2023-07-05)
- Supports better completions for var-quote (`#'some/var`).
- Updates [Haystack](https://github.com/clojure-emacs/haystack/blob/v0.1.0/CHANGELOG.md#010).
- Updates [Haystack](https://github.com/clojure-emacs/haystack/blob/0077b5c49f4aef1c7f89d5430d6dda2f9e7d78d4/CHANGELOG.md#020-2023-08-20).
- Now, in `*cider-error*`, more internal stackframes will be hidden under the `tooling` category.

## 1.7.0 (2023-03-23)

Expand Down
53 changes: 46 additions & 7 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 All @@ -523,7 +561,8 @@ It delegates the actual error content to the eval or op handler."
(defconst cider-clojure-1.10-error `(sequence
"Syntax error "
(minimal-match (zero-or-more anything))
"compiling "
(or "compiling "
"macroexpanding ")
(minimal-match (zero-or-more anything))
"at ("
(group-n 2 (minimal-match (zero-or-more anything)))
Expand Down
9 changes: 8 additions & 1 deletion cider-stacktrace.el
Original file line number Diff line number Diff line change
Expand Up @@ -496,7 +496,14 @@ When it reaches 3, it wraps to 0."
(cider-stacktrace-toggle 'repl))

(defun cider-stacktrace-toggle-tooling ()
"Toggle display of Tooling stack frames (compiler, nREPL middleware, etc)."
"Toggle display of tooling stack frames.

These include:

* Clojure compiler and runtime internals
* may be `.clj' or `.java' files.
* nREPL internals
* CIDER internals."
(interactive)
(cider-stacktrace-toggle 'tooling))

Expand Down
2 changes: 1 addition & 1 deletion cider.el
Original file line number Diff line number Diff line change
Expand Up @@ -489,7 +489,7 @@ the artifact.")
(defconst cider-latest-clojure-version "1.10.1"
"Latest supported version of Clojure.")

(defconst cider-required-middleware-version "0.35.1"
(defconst cider-required-middleware-version "0.36.0"
"The CIDER nREPL version that's known to work properly with CIDER.")

(defcustom cider-injected-middleware-version cider-required-middleware-version
Expand Down
2 changes: 1 addition & 1 deletion dev/docker-sample-project/project.clj
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
:dependencies [[org.clojure/clojure "1.11.1"]
[clj-http "3.12.3"]]
:source-paths ["src"]
:plugins [[cider/cider-nrepl "0.35.1"]])
:plugins [[cider/cider-nrepl "0.36.0"]])
2 changes: 1 addition & 1 deletion dev/tramp-sample-project/project.clj
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
:dependencies [[org.clojure/clojure "1.11.1"]
[clj-http "3.12.3"]]
:source-paths ["src"]
:plugins [[cider/cider-nrepl "0.35.1"]])
:plugins [[cider/cider-nrepl "0.36.0"]])
11 changes: 5 additions & 6 deletions doc/modules/ROOT/pages/basics/middleware_setup.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ Use the convenient plugin for defaults, either in your project's

[source,clojure]
----
:plugins [[cider/cider-nrepl "0.35.1"]
:plugins [[cider/cider-nrepl "0.36.0"]
[mx.cider/enrich-classpath "x.y.z"]]
----

Expand All @@ -46,9 +46,8 @@ A minimal `profiles.clj` for CIDER would be:

[source,clojure]
----
{:repl {:plugins [[cider/cider-nrepl "0.35.1"]
{:repl {:plugins [[cider/cider-nrepl "0.36.0"]
[mx.cider/enrich-classpath "1.9.0"]]}}
----

WARNING: Be careful not to place this in the `:user` profile, as this way CIDER's
middleware will always get loaded, causing `lein` to start slower. You really
Expand All @@ -67,7 +66,7 @@ all of their projects using a `~/.boot/profile.boot` file like so:
(require 'boot.repl)

(swap! boot.repl/*default-dependencies*
concat '[[cider/cider-nrepl "0.35.1"]])
concat '[[cider/cider-nrepl "0.36.0"]])

(swap! boot.repl/*default-middleware*
conj 'cider.nrepl/cider-middleware)
Expand All @@ -84,11 +83,11 @@ run `cider-connect` or `cider-connect-cljs`.

[source,clojure]
----
:cider-clj {:extra-deps {cider/cider-nrepl {:mvn/version "0.35.1"}}
:cider-clj {:extra-deps {cider/cider-nrepl {:mvn/version "0.36.0"}}
:main-opts ["-m" "nrepl.cmdline" "--middleware" "[cider.nrepl/cider-middleware]"]}

:cider-cljs {:extra-deps {org.clojure/clojurescript {:mvn/version "1.10.339"}
cider/cider-nrepl {:mvn/version "0.35.1"}
cider/cider-nrepl {:mvn/version "0.36.0"}
cider/piggieback {:mvn/version "0.5.3"}}
:main-opts ["-m" "nrepl.cmdline" "--middleware"
"[cider.nrepl/cider-middleware,cider.piggieback/wrap-cljs-repl]"]}
Expand Down
4 changes: 2 additions & 2 deletions doc/modules/ROOT/pages/basics/up_and_running.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ simple - CIDER simply passes the extra dependencies and nREPL configuration to
your build tool in the command it runs to start the nREPL server. Here's how
this looks for `tools.deps`:

$ clojure -Sdeps '{:deps {nrepl {:mvn/version "0.6.0"} cider/cider-nrepl {:mvn/version "0.35.1"}}}' -m nrepl.cmdline --middleware '["cider.nrepl/cider-middleware"]'
$ clojure -Sdeps '{:deps {nrepl {:mvn/version "0.6.0"} cider/cider-nrepl {:mvn/version "0.36.0"}}}' -m nrepl.cmdline --middleware '["cider.nrepl/cider-middleware"]'

TIP: If you don't want `cider-jack-in` to inject dependencies automatically, set
`cider-inject-dependencies-at-jack-in` to `nil`. Note that you'll have to setup
Expand Down Expand Up @@ -292,7 +292,7 @@ It is also possible for plain `clj`, although the command is somewhat longer:

[source,sh]
----
$ clj -Sdeps '{:deps {cider/cider-nrepl {:mvn/version "0.35.1"}}}' -m nrepl.cmdline --middleware "[cider.nrepl/cider-middleware]"
$ clj -Sdeps '{:deps {cider/cider-nrepl {:mvn/version "0.36.0"}}}' -m nrepl.cmdline --middleware "[cider.nrepl/cider-middleware]"
----

Alternatively, you can start nREPL either manually or using the facilities
Expand Down
2 changes: 1 addition & 1 deletion doc/modules/ROOT/pages/cljs/shadow-cljs.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ And connect to it with `cider-connect`.
...For that to work, `shadow-cljs.edn` contents like the following are assumed:

```clj
:dependencies [[cider/cider-nrepl "0.35.1"] ;; mandatory (unless it's inherited from deps.edn or otherwise present in the classpath of shadow-cljs's JVM process)
:dependencies [[cider/cider-nrepl "0.36.0"] ;; mandatory (unless it's inherited from deps.edn or otherwise present in the classpath of shadow-cljs's JVM process)
[refactor-nrepl/refactor-nrepl "3.9.0"]] ;; refactor-nrepl is optional

:nrepl {:middleware [cider.nrepl/cider-middleware ;; it's advisable to explicitly add this middleware. It's automatically added by shadow-cljs (if available in the classpath), unless `:nrepl {:cider false}`
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
9 changes: 9 additions & 0 deletions test/cider-eval-tests.el
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,12 @@
(with-temp-file filename
(insert "🍻"))
(expect (cider-provide-file filename) :to-equal "8J+Nuw=="))))

(describe "cider-extract-error-info"
(it "Matches Clojure compilation exceptions"
(expect (cider-extract-error-info cider-compilation-regexp "Syntax error compiling clojure.core/let at (src/haystack/analyzer.clj:18:1).\n[1] - failed: even-number-of-forms? at: [:bindings] spec: :clojure.core.specs.alpha/bindings\n")
:to-equal '("src/haystack/analyzer.clj" 18 1 cider-error-highlight-face "Syntax error compiling clojure.core/let at (src/haystack/analyzer.clj:18:1).\n[1] - failed: even-number-of-forms? at: [:bindings] spec: :clojure.core.specs.alpha/bindings\n"))
(expect (cider-extract-error-info cider-compilation-regexp "Syntax error macroexpanding clojure.core/let at (src/haystack/analyzer.clj:18:1).\n[1] - failed: even-number-of-forms? at: [:bindings] spec: :clojure.core.specs.alpha/bindings\n")
:to-equal '("src/haystack/analyzer.clj" 18 1 cider-error-highlight-face "Syntax error macroexpanding clojure.core/let at (src/haystack/analyzer.clj:18:1).\n[1] - failed: even-number-of-forms? at: [:bindings] spec: :clojure.core.specs.alpha/bindings\n"))
(expect (cider-extract-error-info cider-compilation-regexp "Syntax error FOOING clojure.core/let at (src/haystack/analyzer.clj:18:1).\n[1] - failed: even-number-of-forms? at: [:bindings] spec: :clojure.core.specs.alpha/bindings\n")
:to-equal nil)))
Loading
Loading