Skip to content

Commit f7f8e2c

Browse files
authored
Avoid cider--error-phase-of-last-exception recursive loop (#3607)
Fixes #3605
1 parent 21cdfeb commit f7f8e2c

File tree

2 files changed

+42
-14
lines changed

2 files changed

+42
-14
lines changed

CHANGELOG.md

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

33
## master (unreleased)
44

5+
### Bugs fixed
6+
7+
- [#3605](https://github.com/clojure-emacs/cider/issues/3605): avoid `cider--error-phase-of-last-exception` recursive loop.
8+
59
## 1.13.0 (2024-01-14)
610

711
### Changes

cider-eval.el

+38-14
Original file line numberDiff line numberDiff line change
@@ -764,7 +764,8 @@ and ON-SUCCESS-CALLBACK an optional callback.
764764
The handler simply inserts the result value in BUFFER."
765765
(let ((eval-buffer (current-buffer))
766766
(res "")
767-
(failed nil))
767+
(failed nil)
768+
(error-phase-requested nil)) ;; avoid requesting the phase more than once - can happen if there are errors during the phase nrepl sync request.
768769
(nrepl-make-response-handler (or buffer eval-buffer)
769770
;; value handler:
770771
(lambda (_buffer value)
@@ -781,7 +782,10 @@ The handler simply inserts the result value in BUFFER."
781782
(when (and source-buffer
782783
(listp bounds)) ;; if it's a list, it represents bounds, otherwise it's a string (code) and we can't display the overlay
783784
(with-current-buffer source-buffer
784-
(let* ((phase (cider--error-phase-of-last-exception buffer))
785+
(let* ((phase (if error-phase-requested
786+
nil
787+
(setq error-phase-requested t)
788+
(cider--error-phase-of-last-exception buffer)))
785789
(end (or (car-safe (cdr-safe bounds)) bounds))
786790
(end (when end
787791
(copy-marker end))))
@@ -845,12 +849,16 @@ REPL buffer. This is controlled via
845849
(when-let ((conn (with-current-buffer buffer
846850
(cider-current-repl))))
847851
(when (cider-nrepl-op-supported-p "analyze-last-stacktrace" conn)
848-
(when-let* ((result (nrepl-send-sync-request (thread-last (map-merge 'list
849-
'(("op" "analyze-last-stacktrace"))
850-
(cider--nrepl-print-request-map fill-column))
851-
(seq-mapcat #'identity))
852-
conn)))
853-
(nrepl-dict-get result "phase"))))))
852+
(let ((nrepl-err-handler (lambda (&rest _))) ;; ignore any errors during this request to avoid any recursion
853+
(nrepl-sync-request-timeout 4)) ;; ensure that this feature cannot possibly create an overly laggy UX
854+
(when-let* ((result (nrepl-send-sync-request (thread-last (map-merge 'list
855+
'(("op" "analyze-last-stacktrace"))
856+
(cider--nrepl-print-request-map fill-column))
857+
(seq-mapcat #'identity))
858+
conn
859+
'abort-on-input ;; favor responsiveness over this feature, in case something went wrong.
860+
)))
861+
(nrepl-dict-get result "phase")))))))
854862

855863
(defcustom cider-inline-error-message-function #'cider--shorten-error-message
856864
"A function that will shorten a given error message,
@@ -905,17 +913,24 @@ when `cider-auto-inspect-after-eval' is non-nil."
905913
(beg (when beg (copy-marker beg)))
906914
(end (when end (copy-marker end)))
907915
(fringed nil)
908-
(res ""))
916+
(res "")
917+
(error-phase-requested nil)) ;; avoid requesting the phase more than once - can happen if there are errors during the phase nrepl sync request.
909918
(nrepl-make-response-handler (or buffer eval-buffer)
919+
;; value handler:
910920
(lambda (_buffer value)
911921
(setq res (concat res value))
912922
(cider--display-interactive-eval-result res 'value end))
923+
;; stdout handler:
913924
(lambda (_buffer out)
914925
(cider-emit-interactive-eval-output out))
926+
;; stderr handler:
915927
(lambda (buffer err)
916928
(cider-emit-interactive-eval-err-output err)
917929

918-
(let ((phase (cider--error-phase-of-last-exception buffer)))
930+
(let ((phase (if error-phase-requested
931+
nil
932+
(setq error-phase-requested t)
933+
(cider--error-phase-of-last-exception buffer))))
919934

920935
(cider--maybe-display-error-as-overlay phase err end)
921936

@@ -927,6 +942,7 @@ when `cider-auto-inspect-after-eval' is non-nil."
927942
;; the error is 'right there' in the current line
928943
;; and needs no jumping:
929944
phase)))
945+
;; done handler:
930946
(lambda (buffer)
931947
(if beg
932948
(unless fringed
@@ -946,7 +962,8 @@ when `cider-auto-inspect-after-eval' is non-nil."
946962
"Make a load file handler for BUFFER.
947963
Optional argument DONE-HANDLER lambda will be run once load is complete."
948964
(let ((eval-buffer (current-buffer))
949-
(res ""))
965+
(res "")
966+
(error-phase-requested nil)) ;; avoid requesting the phase more than once - can happen if there are errors during the phase nrepl sync request.
950967
(nrepl-make-response-handler (or buffer eval-buffer)
951968
(lambda (buffer value)
952969
(cider--display-interactive-eval-result value 'value)
@@ -963,7 +980,10 @@ Optional argument DONE-HANDLER lambda will be run once load is complete."
963980
;; 1.- Jump to the error line:
964981
(cider-handle-compilation-errors err eval-buffer)
965982
(with-current-buffer eval-buffer
966-
(let* ((phase (cider--error-phase-of-last-exception buffer))
983+
(let* ((phase (if error-phase-requested
984+
nil
985+
(setq error-phase-requested t)
986+
(cider--error-phase-of-last-exception buffer)))
967987
;; 2.- Calculate the overlay position, which is the point (per the previous jump),
968988
;; and then end-of-line (for ensuring the overlay will be rendered properly):
969989
(end (save-excursion
@@ -1072,7 +1092,8 @@ and SOURCE-BUFFER the original buffer
10721092
This is used by pretty-printing commands."
10731093
;; NOTE: cider-eval-register behavior is not implemented here for performance reasons.
10741094
;; See https://github.com/clojure-emacs/cider/pull/3162
1075-
(let ((chosen-buffer (or buffer (current-buffer))))
1095+
(let ((chosen-buffer (or buffer (current-buffer)))
1096+
(error-phase-requested nil)) ;; avoid requesting the phase more than once - can happen if there are errors during the phase nrepl sync request.
10761097
(nrepl-make-response-handler
10771098
chosen-buffer
10781099
;; value handler:
@@ -1087,7 +1108,10 @@ This is used by pretty-printing commands."
10871108
(when (and source-buffer
10881109
(listp bounds)) ;; if it's a list, it represents bounds, otherwise it's a string (code) and we can't display the overlay
10891110
(with-current-buffer source-buffer
1090-
(let* ((phase (cider--error-phase-of-last-exception buffer))
1111+
(let* ((phase (if error-phase-requested
1112+
nil
1113+
(setq error-phase-requested t)
1114+
(cider--error-phase-of-last-exception buffer)))
10911115
(end (or (car-safe (cdr-safe bounds)) bounds))
10921116
(end (when end
10931117
(copy-marker end))))

0 commit comments

Comments
 (0)