diff --git a/src/taoensso/truss.cljc b/src/taoensso/truss.cljc index c57f21b..a2c7a0f 100644 --- a/src/taoensso/truss.cljc +++ b/src/taoensso/truss.cljc @@ -25,6 +25,12 @@ You may attach arbitrary debug info to assertion violations like: `(have string? x :data {:my-arbitrary-debug-info \"foo\"})` + Re: use of Truss assertions within other macro bodies: + Due to CLJ-865, call site information (e.g. line number) of + outer macro will unfortunately be lost. + + See `keep-callsite` util for a workaround. + See also `have?`, `have!`." {:arglists '([x] [pred (:in) x] [pred (:in) x & more-xs])} [& args] `(-invariant :elidable nil ~(:line (meta &form)) ~args))) @@ -119,6 +125,28 @@ ;;;; Utils +#?(:clj + (defmacro keep-callsite + "CLJ-865 unfortunately means that it's currently not possible + for an inner macro to access the &form metadata of an outer macro. + + This means that inner macros lose call site information like the + line number of the outer macro. + + This util offers a workaround to authors of the outer macro: + (defmacro foo1 [x] `(truss/have ~x)) ; W/o line info + (defmacro foo2 [x] (keep-callsite `(truss/have ~x))) ; With line info" + + {:added "v1.8.0 (2022-12-13)"} + [& body] `(with-meta (do ~@body) (meta ~'&form)))) + +(comment + (defmacro foo1 [x] `(have ~x)) + (defmacro foo2 [x] (keep-callsite `(have ~x))) + + (foo1 nil) + (foo2 nil)) + (defn get-data "Returns current value of dynamic assertion data." [] impl/*data*) diff --git a/test/taoensso/truss_tests.cljc b/test/taoensso/truss_tests.cljc index a81959d..e0c4a76 100644 --- a/test/taoensso/truss_tests.cljc +++ b/test/taoensso/truss_tests.cljc @@ -7,7 +7,8 @@ [taoensso.truss.impl :as impl]) #?(:cljs - (:require-macros [taoensso.truss-tests :refer [my-macro1]]))) + (:require-macros [taoensso.truss-tests :refer + [my-macro1 my-macro2 my-macro3]]))) (comment (remove-ns 'taoensso.truss-tests) @@ -149,4 +150,13 @@ [(is (throws? (my-macro1 n :kw))) (is (= @n 1))]))) +(defmacro my-macro2 [x] `(have string? ~x)) +(defmacro my-macro3 [x] (truss/keep-callsite `(have string? ~x))) + +(deftest _clj-865 + (testing "Clojure issue #865" + [(is (= (my-macro2 "str") "str")) + (is (= (->> (my-macro2 :kw) throws ex-data :loc :line) nil)) + (is (integer? (->> (my-macro3 :kw) throws ex-data :loc :line)))])) + #?(:cljs (test/run-tests))