|
5 | 5 | :author "Jeff Valk, Oleksandr Yakushev"} |
6 | 6 | (:require |
7 | 7 | [clojure.java.io :as io] |
| 8 | + [clojure.main] |
8 | 9 | [clojure.pprint :as pp] |
9 | 10 | [clojure.repl :as repl] |
10 | 11 | [clojure.spec.alpha :as s] |
11 | 12 | [clojure.string :as str] |
12 | 13 | [orchard.info :as info] |
13 | | - [orchard.java.resource :as resource]) |
| 14 | + [orchard.java.resource :as resource] |
| 15 | + [orchard.misc :refer [assoc-some]]) |
14 | 16 | (:import |
15 | 17 | (java.io StringWriter) |
16 | 18 | (java.net URL) |
|
166 | 168 | (if (< i 0) |
167 | 169 | frames |
168 | 170 | (let [frame-name (:name (get frames i)) |
169 | | - tooling? (or (tooling-frame-name? frame-name) |
170 | | - ;; Everything runs from a Thread, so this frame, if at |
171 | | - ;; the end, is irrelevant. However one can invoke this |
172 | | - ;; method 'by hand', which is why we only skip |
173 | | - ;; consecutive frames that match this. |
174 | | - (and all-tooling-so-far? |
175 | | - (re-find #"^java\.lang\.Thread/run|^java\.util\.concurrent" |
176 | | - frame-name)))] |
| 171 | + tooling? (and frame-name |
| 172 | + (or (tooling-frame-name? frame-name) |
| 173 | + ;; Everything runs from a Thread, so this frame, |
| 174 | + ;; if at the end, is irrelevant. However one can |
| 175 | + ;; invoke this method 'by hand', which is why we |
| 176 | + ;; only skip consecutive frames that match this. |
| 177 | + (and all-tooling-so-far? |
| 178 | + (re-find #"^java\.lang\.Thread/run|^java\.util\.concurrent" |
| 179 | + frame-name))))] |
177 | 180 | (recur (cond-> frames |
178 | 181 | tooling? (update i flag-frame :tooling)) |
179 | 182 | (dec i) (and all-tooling-so-far? tooling?)))))) |
|
260 | 263 | (print-fn % writer) |
261 | 264 | (str writer)) |
262 | 265 | phase (-> cause-data :data :clojure.error/phase) |
263 | | - m {:class (name (:type cause-data)) |
264 | | - :phase phase |
265 | | - :message (:message cause-data) |
266 | | - :stacktrace (analyze-stacktrace-data |
267 | | - (cond (seq (:trace cause-data)) (:trace cause-data) |
268 | | - (:at cause-data) [(:at cause-data)]))}] |
| 266 | + m (-> {:class (name (:type cause-data)) |
| 267 | + :phase phase |
| 268 | + :message (:message cause-data) |
| 269 | + :stacktrace (analyze-stacktrace-data |
| 270 | + (cond (seq (:trace cause-data)) (:trace cause-data) |
| 271 | + (:at cause-data) [(:at cause-data)]))} |
| 272 | + (assoc-some :triage (:triage cause-data)))] |
269 | 273 | (if-let [data (filter-ex-data (:data cause-data))] |
270 | 274 | (if (::s/failure data) |
271 | 275 | (assoc m |
|
280 | 284 | :clojure.error/symbol]))) |
281 | 285 | m))) |
282 | 286 |
|
| 287 | +(defn- maybe-triage-message |
| 288 | + "If the exception is a compiler error which carries Spec-based explanation data, |
| 289 | + transform it into human readable error message string." |
| 290 | + [exception-data] |
| 291 | + (try |
| 292 | + ;; ex-triage may throw an exception if :phase is incorrect |
| 293 | + (when-let [explanation-data (:clojure.error/spec |
| 294 | + (clojure.main/ex-triage exception-data))] |
| 295 | + (with-out-str (s/explain-out explanation-data))) |
| 296 | + (catch Exception _))) |
| 297 | + |
283 | 298 | (defn- analyze-causes |
284 | 299 | "Analyze the cause chain of the `exception-data` in `Throwable->map` format." |
285 | 300 | [exception-data print-fn] |
286 | | - (let [causes (vec (:via exception-data)) |
287 | | - ;; If the first cause lacks :trace, add :trace of the exception there. |
288 | | - causes (if (:trace (first causes)) |
289 | | - causes |
290 | | - (assoc-in causes [0 :trace] (:trace exception-data)))] |
| 301 | + (let [triage-message (maybe-triage-message exception-data) |
| 302 | + causes (update (vec (:via exception-data)) 0 |
| 303 | + #(cond-> % |
| 304 | + ;; If the first cause lacks :trace, add :trace of the |
| 305 | + ;; exception there. |
| 306 | + (nil? (:trace %)) (assoc :trace (:trace exception-data)) |
| 307 | + ;; If non-nil, assoc triage-message to first cause. |
| 308 | + triage-message (assoc :triage triage-message)))] |
291 | 309 | (mapv #(extract-location (analyze-cause % print-fn)) causes))) |
292 | 310 |
|
293 | 311 | (defn analyze |
|
0 commit comments