Skip to content

Commit 20ba8ef

Browse files
author
dnolen
committed
CLJS-2843: s/explain of evaluated predicate yields :s/unknown
port CLJ-2068, currently won't work under advanced due to munging
1 parent 78a013a commit 20ba8ef

File tree

2 files changed

+43
-3
lines changed

2 files changed

+43
-3
lines changed

src/main/cljs/cljs/spec/alpha.cljs

+20-1
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,14 @@
120120
(when (ident? spec-or-k)
121121
(throw (js/Error. (str "Unable to resolve spec: " spec-or-k))))))
122122

123+
(defn fn-sym [f-n]
124+
(when-not (str/blank? f-n)
125+
(let [xs (map demunge (str/split f-n "$"))]
126+
(when (c/and (<= 2 (count xs))
127+
(every? #(not (str/blank? %)) xs))
128+
(let [[xs y] ((juxt butlast last) xs)]
129+
(symbol (str (str/join "." xs) "/" y)))))))
130+
123131
(defprotocol Specize
124132
(specize* [_] [_ form]))
125133

@@ -132,9 +140,20 @@
132140
(specize* ([s] (specize* (reg-resolve! s)))
133141
([s _] (specize* (reg-resolve! s))))
134142

143+
PersistentHashSet
144+
(specize* ([s] (spec-impl s s nil nil))
145+
([s form] (spec-impl form s nil nil)))
146+
147+
PersistentTreeSet
148+
(specize* ([s] (spec-impl s s nil nil))
149+
([s form] (spec-impl form s nil nil)))
150+
135151
default
136152
(specize*
137-
([o] (spec-impl ::unknown o nil nil))
153+
([o]
154+
(if-let [f-n (c/and (fn? o) (fn-sym (.-name o)))]
155+
(spec-impl f-n o nil nil)
156+
(spec-impl ::unknown o nil nil)))
138157
([o form] (spec-impl form o nil nil))))
139158

140159
(defn- specize

src/test/cljs/cljs/spec_test.cljs

+23-2
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,19 @@
136136
lrange (s/int-in 7 42)
137137
drange (s/double-in :infinite? false :NaN? false :min 3.1 :max 3.2)
138138
irange (s/inst-in #inst "1939" #inst "1946")]
139+
140+
(when-not js/COMPILED
141+
;; CLJS-2483: these won't work with both :advanced and :none optimization settings
142+
(are [spec x conformed ed]
143+
(let [co (s/conform spec x)
144+
e (::s/problems (s/explain-data spec x))]
145+
(when (not= conformed co) (println "conform fail\n\texpect=" conformed "\n\tactual=" co))
146+
(when (not (every? true? (map submap? ed e)))
147+
(println "explain failures\n\texpect=" ed "\n\tactual failures=" e "\n\tsubmap?=" (map submap? ed e)))
148+
(and (= conformed co) (every? true? (map submap? ed e))))
149+
keyword? nil ::s/invalid [{:pred `keyword? :val nil}]
150+
keyword? "abc" ::s/invalid [{:pred `keyword? :val "abc"}]))
151+
139152
(are [spec x conformed ed]
140153
(let [co (s/conform spec x)
141154
e (::s/problems (s/explain-data spec x))]
@@ -160,8 +173,6 @@
160173
;; drange Double/NaN ::s/invalid {[] {:pred '(not (isNaN %)), :val Double/NaN}}
161174

162175
keyword? :k :k nil
163-
keyword? nil ::s/invalid [{:pred ::s/unknown :val nil}]
164-
keyword? "abc" ::s/invalid [{:pred ::s/unknown :val "abc"}]
165176

166177
a 6 6 nil
167178
a 3 ::s/invalid '[{:pred (cljs.core/fn [%] (cljs.core/> % 5)), :val 3}]
@@ -420,6 +431,16 @@
420431

421432
(s/def ::cljs-2940-foo (s/cat :bar (s/nilable ::cljs-2940-foo)))
422433

434+
(deftest describing-evaled-specs
435+
(let [sp #{1 2}]
436+
(is (= (s/describe sp) (s/form sp) sp)))
437+
;; won't work under advanced
438+
(when-not js/COMPILED
439+
(is (= (s/describe odd?) 'odd?))
440+
(is (= (s/form odd?) 'cljs.core/odd?)))
441+
(is (= (s/describe #(odd? %)) ::s/unknown))
442+
(is (= (s/form #(odd? %)) ::s/unknown)))
443+
423444
(comment
424445

425446
(run-tests)

0 commit comments

Comments
 (0)