Skip to content

Commit cfbefad

Browse files
author
dnolen
committed
improve code for finding spec-fn caller
1 parent 0fcbef2 commit cfbefad

3 files changed

Lines changed: 66 additions & 24 deletions

File tree

src/main/cljs/cljs/spec/test.cljc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
'~(:name v)))))
2929

3030
(defmacro unstrument-1
31-
[s opts]
31+
[s]
3232
(let [v (ana-api/resolve &env s)]
3333
(when v
3434
`(let [raw# (unstrument-1* ~s (var ~s))]

src/main/cljs/cljs/spec/test.cljs

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@
77
; You must not remove this notice, or any other, from this software.
88

99
(ns cljs.spec.test
10-
(:require-macros [cljs.spec.test :refer [with-instrument-disabled]])
10+
(:require-macros [cljs.spec.test :as m :refer [with-instrument-disabled]])
1111
(:require
1212
[goog.userAgent.product :as product]
13-
[clojure.string :as str]
13+
[clojure.string :as string]
1414
[cljs.stacktrace :as st]
1515
[cljs.pprint :as pp]
1616
[cljs.spec :as s]
@@ -57,17 +57,28 @@
5757
(when-not (s/valid? spec v nil)
5858
(s/explain-data spec v)))
5959

60+
(defn- find-caller [st]
61+
(letfn [(search-spec-fn [frame]
62+
(when frame
63+
(let [s (:function frame)]
64+
(and (string? s) (not (string/blank? s))
65+
(re-find #"cljs\.spec\.test\.spec_checking_fn" s)))))]
66+
(->> st
67+
(drop-while #(not (search-spec-fn %)))
68+
(drop-while search-spec-fn)
69+
first)))
70+
6071
(defn- spec-checking-fn
6172
[v f fn-spec]
6273
(let [fn-spec (@#'s/maybe-spec fn-spec)
6374
conform! (fn [v role spec data args]
6475
(let [conformed (s/conform spec data)]
6576
(if (= ::s/invalid conformed)
66-
(let [caller (-> (st/parse-stacktrace
67-
(get-host-port)
68-
(.-stack (js/Error.))
69-
(get-env) nil)
70-
first)
77+
(let [caller (find-caller
78+
(st/parse-stacktrace
79+
(get-host-port)
80+
(.-stack (js/Error.))
81+
(get-env) nil))
7182
ed (merge (assoc (s/explain-data* spec [role] [] [] data)
7283
::s/args args
7384
::s/failure :instrument)
@@ -208,7 +219,8 @@ Returns a map as quick-check, with :explain-data added if
208219

209220

210221
(comment
211-
(require '[cljs.pprint :as pp]
222+
(require
223+
'[cljs.pprint :as pp]
212224
'[cljs.spec :as s]
213225
'[cljs.spec.impl.gen :as gen]
214226
'[cljs.test :as ctest])
@@ -232,6 +244,27 @@ Returns a map as quick-check, with :explain-data added if
232244
(cljs.spec.test/run-tests 'clojure.core)
233245
(test/run-all-tests)
234246

247+
;; example evaluation
248+
(defn ranged-rand
249+
"Returns random int in range start <= rand < end"
250+
[start end]
251+
(+ start (long (rand (- end start)))))
252+
253+
(s/fdef ranged-rand
254+
:args (s/and (s/cat :start int? :end int?)
255+
#(< (:start %) (:end %)))
256+
:ret int?
257+
:fn (s/and #(>= (:ret %) (-> % :args :start))
258+
#(< (:ret %) (-> % :args :end))))
259+
260+
(m/instrument-1 ranged-rand {})
261+
(ranged-rand 8 5)
262+
(defn foo
263+
([a])
264+
([a b]
265+
(ranged-rand 8 5)))
266+
(foo 1 2)
267+
(m/unstrument-1 ranged-rand)
235268
)
236269

237270

src/main/cljs/cljs/stacktrace.cljc

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -452,7 +452,7 @@ goog.events.getProxy/f<@http://localhost:9000/out/goog/events/events.js:276:16"
452452
[repl-env st err {:keys [output-dir] :as opts}]
453453
(letfn [(process-frame [frame-str]
454454
(when-not (or (string/blank? frame-str)
455-
(== -1 (.indexOf frame-str "\tat")))
455+
(== -1 (.indexOf frame-str "\tat")))
456456
(let [frame-str (string/replace frame-str #"\s+at\s+" "")
457457
[function file-and-line] (string/split frame-str #"\s+")
458458
[file-part line-part] (string/split file-and-line #":")]
@@ -502,23 +502,32 @@ goog.events.getProxy/f<@http://localhost:9000/out/goog/events/events.js:276:16"
502502

503503
(defmethod parse-stacktrace :nodejs
504504
[repl-env st err {:keys [output-dir] :as opts}]
505-
(letfn [(process-frame [frame-str]
505+
(letfn [(parse-source-loc-info [x]
506+
(when (and x (not (string/blank? x)))
507+
(parse-int x)))
508+
(process-frame [frame-str]
506509
(when-not (or (string/blank? frame-str)
507-
(== -1 (.indexOf frame-str " at")))
510+
(nil? (re-find #"^\s+at" frame-str)))
508511
(let [frame-str (string/replace frame-str #"\s+at\s+" "")]
509512
(when-not (string/starts-with? frame-str "repl:")
510-
(let [[function file-and-line] (string/split frame-str #"\s+")
511-
[file-part line-part] (string/split file-and-line #":")]
512-
{:file (string/replace (.substring file-part 1)
513-
(str output-dir
514-
#?(:clj File/separator :cljs "/"))
515-
"")
516-
:function function
517-
:line (when (and line-part (not (string/blank? line-part)))
518-
(parse-int
519-
(.substring line-part 0
520-
(dec (count line-part)))))
521-
:column 0})))))]
513+
(let [parts (string/split frame-str #"\s+")
514+
[function file&line] (if (== 2 (count parts))
515+
[(first parts)
516+
(subs (second parts) 1
517+
(dec (count (second parts))))]
518+
[nil (first parts)])
519+
[file-part line-part col-part] (string/split file&line #":")]
520+
{:file (if function
521+
(cond-> file-part
522+
output-dir
523+
(string/replace
524+
(str output-dir
525+
#?(:clj File/separator :cljs "/"))
526+
""))
527+
file-part)
528+
:function function
529+
:line (parse-source-loc-info line-part)
530+
:column (parse-source-loc-info col-part)})))))]
522531
(->> (string/split st #"\n")
523532
(map process-frame)
524533
(remove nil?)

0 commit comments

Comments
 (0)