diff options
-rw-r--r-- | CHANGELOG.md | 1 | ||||
-rw-r--r-- | cider-debug.el | 93 | ||||
-rw-r--r-- | test/cider-tests.el | 17 |
3 files changed, 67 insertions, 44 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 67db534f..95ef7947 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ### Bugs fixed * [#1632](https://github.com/clojure-emacs/cider/pull/1632): Redefining a function correctly updates eldoc. +* [#1630](https://github.com/clojure-emacs/cider/pull/1630): The debugger no longer gets confused inside `@` redefs. * [#1599](https://github.com/clojure-emacs/cider/pull/1599): Don't error when test makes 0 assertions. * [#1563](https://github.com/clojure-emacs/cider/issues/1563): Handle invalid regular expressions in apropos. * [#1625](https://github.com/clojure-emacs/cider/issues/1625): Display a more meaningful message when running diff --git a/cider-debug.el b/cider-debug.el index a3931b06..46d94091 100644 --- a/cider-debug.el +++ b/cider-debug.el @@ -477,51 +477,56 @@ key of a map, and it means \"go to the value associated with this key\"." (while coordinates (while (clojure--looking-at-non-logical-sexp) (forward-sexp)) - (down-list) - ;; Are we entering a syntax-quote? - (when (looking-back "`\\(#{\\|[{[(]\\)" (line-beginning-position)) - ;; If we are, this affects all nested structures until the next `~', - ;; so we set this variable for all following steps in the loop. - (setq in-syntax-quote t)) - (when in-syntax-quote - ;; A `(. .) is read as (seq (concat (list .) (list .))). This pops - ;; the `seq', since the real coordinates are inside the `concat'. - (pop coordinates) - ;; Non-list seqs like `[] and `{} are read with - ;; an extra (apply vector ...), so pop it too. - (unless (eq ?\( (char-before)) - (pop coordinates))) - ;; #(...) is read as (fn* ([] ...)), so we patch that here. - (when (looking-back "#(" (line-beginning-position)) - (pop coordinates)) - (if coordinates - (let ((next (pop coordinates))) - (when in-syntax-quote - ;; We're inside the `concat' form, but we need to discard the - ;; actual `concat' symbol from the coordinate. - (setq next (1- next))) - ;; String coordinates are map keys. - (if (stringp next) - (cider--debug-goto-keyval next) - (clojure-forward-logical-sexp next) + ;; An `@x` is read as (deref x), so we pop coordinates once to account + ;; for the extra depth, and move past the @ char. + (if (eq ?@ (char-after)) + (progn (forward-char 1) + (pop coordinates)) + (down-list) + ;; Are we entering a syntax-quote? + (when (looking-back "`\\(#{\\|[{[(]\\)" (line-beginning-position)) + ;; If we are, this affects all nested structures until the next `~', + ;; so we set this variable for all following steps in the loop. + (setq in-syntax-quote t)) + (when in-syntax-quote + ;; A `(. .) is read as (seq (concat (list .) (list .))). This pops + ;; the `seq', since the real coordinates are inside the `concat'. + (pop coordinates) + ;; Non-list seqs like `[] and `{} are read with + ;; an extra (apply vector ...), so pop it too. + (unless (eq ?\( (char-before)) + (pop coordinates))) + ;; #(...) is read as (fn* ([] ...)), so we patch that here. + (when (looking-back "#(" (line-beginning-position)) + (pop coordinates)) + (if coordinates + (let ((next (pop coordinates))) (when in-syntax-quote - (clojure-forward-logical-sexp 1) - (forward-sexp -1) - ;; Here a syntax-quote is ending. - (let ((match (when (looking-at "~@?") - (match-string 0)))) - (when match - (setq in-syntax-quote nil)) - ;; A `~@' is read as the object itself, so we don't pop - ;; anything. - (unless (equal "~@" match) - ;; Anything else (including a `~') is read as a `list' - ;; form inside the `concat', so we need to pop the list - ;; from the coordinates. - (pop coordinates)))))) - ;; If that extra pop was the last coordinate, this represents the - ;; entire #(...), so we should move back out. - (backward-up-list))) + ;; We're inside the `concat' form, but we need to discard the + ;; actual `concat' symbol from the coordinate. + (setq next (1- next))) + ;; String coordinates are map keys. + (if (stringp next) + (cider--debug-goto-keyval next) + (clojure-forward-logical-sexp next) + (when in-syntax-quote + (clojure-forward-logical-sexp 1) + (forward-sexp -1) + ;; Here a syntax-quote is ending. + (let ((match (when (looking-at "~@?") + (match-string 0)))) + (when match + (setq in-syntax-quote nil)) + ;; A `~@' is read as the object itself, so we don't pop + ;; anything. + (unless (equal "~@" match) + ;; Anything else (including a `~') is read as a `list' + ;; form inside the `concat', so we need to pop the list + ;; from the coordinates. + (pop coordinates)))))) + ;; If that extra pop was the last coordinate, this represents the + ;; entire #(...), so we should move back out. + (backward-up-list)))) ;; Place point at the end of instrumented sexp. (clojure-forward-logical-sexp 1)) ;; Avoid throwing actual errors, since this happens on every breakpoint. diff --git a/test/cider-tests.el b/test/cider-tests.el index 582a0c56..19e98805 100644 --- a/test/cider-tests.el +++ b/test/cider-tests.el @@ -112,6 +112,23 @@ (cider--debug-move-point '(2 1 1 1)) (should (string= (buffer-substring (point-min) (point)) "`[(~d)")))) +(ert-deftest test-debug-move-point-@ () + (with-temp-buffer + (clojure-mode) + (save-excursion (insert "(let [x (atom 1)] @x)")) + (cider--debug-move-point '(2 1)) + (should (looking-back "@x"))) + (with-temp-buffer + (clojure-mode) + (save-excursion (insert "(do @(do (atom {})))")) + (cider--debug-move-point '(1 1 1)) + (should (looking-back "(atom {})"))) + (with-temp-buffer + (clojure-mode) + (save-excursion (insert "(do @@(do (atom {})))")) + (cider--debug-move-point '(1 1 1 1)) + (should (looking-back "(atom {})")))) + (ert-deftest test-debug-move-point-metadata () (with-temp-buffer (clojure-mode) |