cider icon indicating copy to clipboard operation
cider copied to clipboard

Cider jumps to clojure.core/fn as source of stack frames for top level anonymous functions

Open hugoduncan opened this issue 3 years ago • 13 comments

Expected behavior

Cider jumps to the correct source when clicking a stack trace frame.

Actual behavior

Cider jumps to clojure.core/fn as source of stack frames for top level anonymous functions.

Steps to reproduce the problem

(def ^{:test (fn [] (throw (ex-info "err" {})))} my-fn
  (fn []))

(defn call-my-fn []
  ((:test (meta #'my-fn))))

(call-my-fn)

Click on the first displayed stack frame - opens clojure,core/fn.

Note that this is the pattern used by deftest.

Environment & Version information

All things master head. Mac.

CIDER version information

;; CIDER 0.26.0snapshot, nREPL 0.8.0-alpha5
;; Clojure 1.10.1, Java 1.8.0_252

Emacs version

GNU Emacs 26.3 (build 1, x86_64-apple-darwin18.2.0, NS appkit-1671.20 Version 10.14.3 (Build 18D109)) of 2019-09-02

hugoduncan avatar Jul 24 '20 17:07 hugoduncan

I'll take a look, but I have a feeling this might be tricky to solve as I doubt we can get meaningful location metadata for lambdas.

bbatsov avatar Jul 25 '20 19:07 bbatsov

When run from a compiled namespace, the displayed file name and line number are correct.

hugoduncan avatar Jul 27 '20 10:07 hugoduncan

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contribution and understanding!

stale[bot] avatar Oct 25 '20 11:10 stale[bot]

This issues been automatically closed due to lack of activity. Feel free to re-open it if you ever come back to it.

stale[bot] avatar Nov 24 '20 23:11 stale[bot]

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contribution and understanding!

stale[bot] avatar Apr 08 '21 23:04 stale[bot]

This issues been automatically closed due to lack of activity. Feel free to re-open it if you ever come back to it.

stale[bot] avatar Jun 02 '21 17:06 stale[bot]

I was just looking for this issue yesterday. It would be very useful to jump to test source lines from exceptions thrown in tests.

hugoduncan avatar Jun 03 '21 01:06 hugoduncan

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contribution and understanding!

stale[bot] avatar Sep 19 '21 20:09 stale[bot]

This is hurting my workflow as well. The stack trace shows the right file & line information, so why does CIDER jump somewhere else?

opqdonut avatar Feb 16 '22 11:02 opqdonut

Moved issue to the Orchard repo which is where I believe it belongs technically, and also where it can get best attention (as you can see in https://github.com/clojure-emacs/cider/issues, the CIDER tracker is more of mixed bag, so issues are more likely to pile up).

Will investigate when I have the chance.

vemv avatar Feb 16 '22 11:02 vemv

Finally, it doesn't seem that there's an issue in Orchard or cider-nrepl.

The following patch can be applied to cider-nrepl:

diff --git a/test/clj/cider/nrepl/middleware/stacktrace_test.clj b/test/clj/cider/nrepl/middleware/stacktrace_test.clj
index f5660c9..11ccfa9 100644
--- a/test/clj/cider/nrepl/middleware/stacktrace_test.clj
+++ b/test/clj/cider/nrepl/middleware/stacktrace_test.clj
@@ -17,15 +17,32 @@
 (defn stack-frames
   [form]
   (analyze-stacktrace
-   (try (eval form)
-        (catch Exception e
-          e))))
+   (let [this-ns *ns*]
+     (try
+       (eval form)
+       (catch Exception e
+         e)
+       (finally
+         (-> this-ns str symbol in-ns))))))
 
 ;; ## Test fixtures
 
 (def form1 '(throw (ex-info "oops" {:x 1} (ex-info "cause" {:y 2}))))
 (def form2 '(do (defn oops [] (+ 1 "2"))
                 (oops)))
+
+(def form-issue-153 '(do
+                       (ns cider.nrepl.middleware.stacktrace-test.foo.bar.baz)
+                       (def ^{:test (fn [] (throw (ex-info "err" {})))} my-fn
+                         (fn []))
+
+                       (defn call-my-fn []
+                         ((:test (meta #'my-fn))))
+
+                       (call-my-fn)))
+
+(->> (stack-frames form-issue-153) clojure.pprint/pprint)
+
 (def form3 '(not-defined))
 (defn divi [x y] (/ x y))
 (def form4 '(divi 1 0))

Ten running lein test :only cider.nrepl.middleware.stacktrace-test will show the following pprinted stacktrace:

({:fn "fn",
  :method "invokeStatic",
  :ns "cider.nrepl.middleware.stacktrace-test.foo.bar.baz",
  :name
  "cider.nrepl.middleware.stacktrace_test.foo.bar.baz$fn__2628/invokeStatic",
  :file "stacktrace_test.clj",
  :type :clj,
  :file-url nil,
  :line 36,
  :var "cider.nrepl.middleware.stacktrace-test.foo.bar.baz/fn",
  :class "cider.nrepl.middleware.stacktrace_test.foo.bar.baz$fn__2628",
  :flags #{:tooling :clj}}
 {:fn "fn",
  :method "invoke",
  :ns "cider.nrepl.middleware.stacktrace-test.foo.bar.baz",
  :name
  "cider.nrepl.middleware.stacktrace_test.foo.bar.baz$fn__2628/invoke",
  :file "stacktrace_test.clj",
  :type :clj,
  :file-url nil,
  :line 36,
  :var "cider.nrepl.middleware.stacktrace-test.foo.bar.baz/fn",
  :class "cider.nrepl.middleware.stacktrace_test.foo.bar.baz$fn__2628",
  :flags #{:dup :tooling :clj}}
 {:fn "call-my-fn",
  :method "invokeStatic",
  :ns "cider.nrepl.middleware.stacktrace-test.foo.bar.baz",
  :name
  "cider.nrepl.middleware.stacktrace_test.foo.bar.baz$call_my_fn/invokeStatic",
  :file "stacktrace_test.clj",
  :type :clj,
  :file-url
  "file:/Users/vemv/cider-nrepl-upstream/test/clj/cider/nrepl/middleware/stacktrace_test.clj",
  :line 40,
  :var "cider.nrepl.middleware.stacktrace-test.foo.bar.baz/call-my-fn",
  :class
  "cider.nrepl.middleware.stacktrace_test.foo.bar.baz$call_my_fn",
  :flags #{:tooling :clj}}
 ,,,

In the first item, one can see a :fn "fn", :ns "cider.nrepl.middleware.stacktrace-test.foo.bar.baz" entry, with correct :line info.

So it's cider.el that isn't making sense of this info - maybe it infers from fn that it's clojure.core/fn?

vemv avatar Feb 22 '22 15:02 vemv

The relevant cider.el code probably is https://github.com/clojure-emacs/cider/blob/956984faa1f8a5edc9eb94eacdf530cb9404850b/cider-stacktrace.el#L531-L552 . Note how it handles var/class/method info, which maps 1:1 to what cider.nrepl.middleware.stacktrace is returning (see the data in https://github.com/clojure-emacs/cider/issues/3157#issuecomment-1047892402)

Maybe (cider-resolve-java-class ...) shouldn't be used for this code path? Perhaps that's what's returning clojure.core/fn.

Because I use an old fork I'm not in a position to hack on it atm, feel free to.

vemv avatar Feb 22 '22 15:02 vemv

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contribution and understanding!

stale[bot] avatar Jun 13 '22 02:06 stale[bot]