92 lines
3.4 KiB
Clojure
92 lines
3.4 KiB
Clojure
(ns scittle.impl.error
|
|
(:refer-clojure :exclude [println])
|
|
(:require [clojure.string :as str]
|
|
[sci.core :as sci]))
|
|
|
|
(defn println [& strs]
|
|
(.error js/console (str/join " " strs)))
|
|
|
|
(defn ruler [title]
|
|
(println (apply str "----- " title " " (repeat (- 50 7 (count title)) \-))))
|
|
|
|
(defn split-stacktrace [stacktrace verbose?]
|
|
(if verbose? [stacktrace]
|
|
(let [stack-count (count stacktrace)]
|
|
(if (<= stack-count 10)
|
|
[stacktrace]
|
|
[(take 5 stacktrace)
|
|
(drop (- stack-count 5) stacktrace)]))))
|
|
|
|
(defn print-stacktrace
|
|
[stacktrace {:keys [:verbose?]}]
|
|
(let [stacktrace (sci/format-stacktrace stacktrace)
|
|
segments (split-stacktrace stacktrace verbose?)
|
|
[fst snd] segments]
|
|
(run! #(print % "\n") fst)
|
|
(when snd
|
|
(print "...\n")
|
|
(run! #(print % "\n") snd))))
|
|
|
|
(defn error-context [ex src-map]
|
|
(let [{:keys [:file :line :column]} (ex-data ex)]
|
|
(when (and file line)
|
|
(when-let [content (get src-map file)]
|
|
(let [matching-line (dec line)
|
|
start-line (max (- matching-line 4) 0)
|
|
end-line (+ matching-line 6)
|
|
[before after] (->>
|
|
(str/split-lines content)
|
|
(map-indexed list)
|
|
(drop start-line)
|
|
(take (- end-line start-line))
|
|
(split-at (inc (- matching-line start-line))))
|
|
snippet-lines (concat before
|
|
[[nil (str (str/join "" (repeat (dec column) " "))
|
|
(str "^--- " (ex-message ex)))]]
|
|
after)
|
|
indices (map first snippet-lines)
|
|
max-size (reduce max 0 (map (comp count str) indices))
|
|
snippet-lines (map (fn [[idx line]]
|
|
(if idx
|
|
(let [line-number (inc idx)]
|
|
(str (.padStart (str line-number) max-size "0") " " line))
|
|
(str (str/join (repeat (+ 2 max-size) " ")) line)))
|
|
snippet-lines)]
|
|
(str "\n" (str/join "\n" snippet-lines)))))))
|
|
|
|
(defn right-pad [s n]
|
|
(let [n (- n (count s))]
|
|
(str s (str/join (repeat n " ")))))
|
|
|
|
(defn error-handler [e src-map]
|
|
(let [d (ex-data e)
|
|
sci-error? (isa? (:type d) :sci/error)
|
|
stacktrace (sci/stacktrace e)]
|
|
(ruler "Scittle error")
|
|
(when-let [name (.-name e)]
|
|
(when-not (= "Error" name)
|
|
(println "Type: " name)))
|
|
(when-let [m (.-message e)]
|
|
(println (str "Message: " m)))
|
|
(when-let [d (ex-data (ex-cause e) #_(.getCause e))]
|
|
(print (str "Data: "))
|
|
(prn d))
|
|
(let [{:keys [:file :line :column]} d]
|
|
(when line
|
|
(println (str "Location: "
|
|
(when file (str file ":"))
|
|
line ":" column""))))
|
|
(when-let [phase (:phase d)]
|
|
(println "Phase: " phase))
|
|
(when-let [ec (when sci-error?
|
|
(error-context e src-map))]
|
|
(ruler "Context")
|
|
(println ec))
|
|
(when sci-error?
|
|
(when-let
|
|
[st (let [st (with-out-str
|
|
(when stacktrace
|
|
(print-stacktrace stacktrace src-map)))]
|
|
(when-not (str/blank? st) st))]
|
|
(ruler "Stack trace")
|
|
(println st)))))
|