|
11 | 11 | [nrepl.transport Transport])) |
12 | 12 |
|
13 | 13 | (defn- root-cause [^Throwable t] |
14 | | - (when t |
15 | | - (loop [t t] |
16 | | - (if-some [cause (.getCause t)] |
17 | | - (recur cause) |
18 | | - t)))) |
| 14 | + (if-some [cause (some-> t .getCause)] |
| 15 | + (recur cause) |
| 16 | + t)) |
19 | 17 |
|
20 | 18 | (defn print-root-trace [^Throwable t] |
21 | 19 | (stacktrace/print-stack-trace (root-cause t))) |
22 | 20 |
|
23 | | -(defn trace [^Throwable t] |
24 | | - (let [trace (with-out-str |
25 | | - (.printStackTrace t (java.io.PrintWriter. *out*)))] |
26 | | - (if-some [idx (str/index-of trace "\n\tat clojure.lang.Compiler.eval(Compiler.java:")] |
27 | | - (subs trace 0 idx) |
28 | | - trace))) |
| 21 | +(defn- duplicate? [^StackTraceElement prev-el ^StackTraceElement el] |
| 22 | + (and |
| 23 | + (= (.getClassName prev-el) (.getClassName el)) |
| 24 | + (= (.getFileName prev-el) (.getFileName el)) |
| 25 | + (= "invokeStatic" (.getMethodName prev-el)) |
| 26 | + (#{"invoke" "doInvoke"} (.getMethodName el)))) |
| 27 | + |
| 28 | +(defn- clear-duplicates [els] |
| 29 | + (for [[prev-el el] (map vector (cons nil els) els) |
| 30 | + :when (or (nil? prev-el) (not (duplicate? prev-el el)))] |
| 31 | + el)) |
| 32 | + |
| 33 | +(defn- trace-element-str [^StackTraceElement el] |
| 34 | + (let [file (.getFileName el) |
| 35 | + clojure? (and file |
| 36 | + (or (.endsWith file ".clj") |
| 37 | + (.endsWith file ".cljc") |
| 38 | + (= file "NO_SOURCE_FILE")))] |
| 39 | + (str |
| 40 | + "\t" |
| 41 | + (if clojure? |
| 42 | + (clojure.lang.Compiler/demunge (.getClassName el)) |
| 43 | + (str (.getClassName el) "." (.getMethodName el))) |
| 44 | + " (" |
| 45 | + (.getFileName el) |
| 46 | + ":" |
| 47 | + (.getLineNumber el) |
| 48 | + ")"))) |
| 49 | + |
| 50 | +(defn- trace-str [^Throwable t] |
| 51 | + (str |
| 52 | + (.getSimpleName (class t)) |
| 53 | + ": " |
| 54 | + (.getMessage t) |
| 55 | + (when-some [data (ex-data t)] (str " " (pr-str data))) |
| 56 | + "\n" |
| 57 | + (->> (.getStackTrace t) |
| 58 | + (take-while #(not= "clojure.lang.Compiler" (.getClassName ^StackTraceElement %))) |
| 59 | + (remove #(#{"clojure.lang.RestFn" "clojure.lang.AFn"} (.getClassName ^StackTraceElement %))) |
| 60 | + (clear-duplicates) |
| 61 | + (map trace-element-str) |
| 62 | + (str/join "\n")))) |
29 | 63 |
|
30 | 64 | (defn- caught-transport [{:keys [transport] :as msg}] |
31 | 65 | (reify Transport |
|
44 | 78 | root (assoc |
45 | 79 | ::root-ex-msg (.getMessage root) |
46 | 80 | ::root-ex-class (.getSimpleName (class root)) |
47 | | - ::trace (trace root)) |
| 81 | + ::trace (trace-str root)) |
48 | 82 | loc (merge loc) |
49 | 83 | data (update ::print/keys (fnil conj []) ::root-ex-data) |
50 | 84 | data (assoc ::root-ex-data data))] |
|
0 commit comments