diff --git a/project.clj b/project.clj index 7de18388c..2739a7e3c 100644 --- a/project.clj +++ b/project.clj @@ -1,4 +1,4 @@ -(def VERSION "0.19.0-SNAPSHOT") + (def VERSION "0.19.0-SNAPSHOT") (defproject cider/cider-nrepl VERSION :description "nREPL middlewares for CIDER" diff --git a/src/cider/nrepl/middleware/stacktrace.clj b/src/cider/nrepl/middleware/stacktrace.clj index f031238fd..0938a8c33 100644 --- a/src/cider/nrepl/middleware/stacktrace.clj +++ b/src/cider/nrepl/middleware/stacktrace.clj @@ -205,20 +205,30 @@ (defn extract-location "If the cause is a compiler exception, extract the useful location information - from its message. Include relative path for simpler reporting." - [{:keys [class message] :as cause}] + from its message or from `:location` if provided. + Include relative path for simpler reporting." + [{:keys [class message location] :as cause}] (if (= class "clojure.lang.Compiler$CompilerException") - (let [[_ msg file line column] - (re-find #"(.*?), compiling:\((.*):(\d+):(\d+)\)" message)] + (if-not (empty? location) (assoc cause - :message msg - :file file - :file-url (some-> file + :file (:clojure.error/source location) + :file-url (some-> (:clojure.error/source location) path->url u/transform-value) - :path (relative-path file) - :line (Integer/parseInt line) - :column (Integer/parseInt column))) + :path (relative-path (:clojure.error/source location)) + :line (:clojure.error/line location) + :column (:clojure.error/column location)) + (let [[_ msg file line column] + (re-find #"(.*?), compiling:\((.*):(\d+):(\d+)\)" message)] + (assoc cause + :message msg + :file file + :file-url (some-> file + path->url + u/transform-value) + :path (relative-path file) + :line (Integer/parseInt line) + :column (Integer/parseInt column)))) cause)) ;; CLJS REPLs use :repl-env to store huge amounts of analyzer/compiler state @@ -289,8 +299,12 @@ (assoc m :message "Spec assertion failed." :spec (prepare-spec-data data pprint-fn)) - (assoc m - :data (with-out-str (pprint-fn data)))) + (-> m + (assoc :data (with-out-str (pprint-fn data))) + (assoc :location + (select-keys data [:clojure.error/line :clojure.error/column + :clojure.error/phase :clojure.error/source + :clojure.error/symbol])))) m))) (defn analyze-causes diff --git a/test/clj/cider/nrepl/middleware/stacktrace_test.clj b/test/clj/cider/nrepl/middleware/stacktrace_test.clj index 0876c35cd..8b2243e3b 100644 --- a/test/clj/cider/nrepl/middleware/stacktrace_test.clj +++ b/test/clj/cider/nrepl/middleware/stacktrace_test.clj @@ -144,4 +144,34 @@ :line 1 :column 42} (extract-location {:class "clojure.lang.Compiler$CompilerException" - :message "java.lang.NegativeArraySizeException, compiling:(/foo/bar/baz.clj:1:42)"}))))) + :message "java.lang.NegativeArraySizeException, compiling:(/foo/bar/baz.clj:1:42)"})))) + (testing "extract-location with location-data already present" + (= {:class "clojure.lang.Compiler$CompilerException" + :message "Syntax error macroexpanding clojure.core/let at (1:1)." + :file nil + :file-url nil + :path "/foo/bar/baz.clj" + :line 1 + :column 42} + (extract-location {:class "clojure.lang.Compiler$CompilerException" + :location {:clojure.error/line 1 + :clojure.error/column 42 + :clojure.error/source "/foo/bar/baz.clj" + :clojure.error/phase :macroexpand + :clojure.error/symbol 'clojure.core/let} + :message "Syntax error macroexpanding clojure.core/let at (1:1)."})))) + +(deftest analyze-cause-test + (testing "check that location-data is returned" + (let [e (ex-info "wat?" {:clojure.error/line 1 + :clojure.error/column 42 + :clojure.error/source "/foo/bar/baz.clj" + :clojure.error/phase :macroexpand + :clojure.error/symbol 'clojure.core/let}) + cause (analyze-cause e identity)] + (is (= {:clojure.error/line 1 + :clojure.error/column 42 + :clojure.error/source "/foo/bar/baz.clj" + :clojure.error/phase :macroexpand + :clojure.error/symbol 'clojure.core/let} + (:location cause))))))