Skip to content

Commit 87c542d

Browse files
author
dnolen
committed
fix def/fdef symbol resolution, replace fn-spec with more general get-spec
same as Clojure 4978bf5c
1 parent bcf60ce commit 87c542d

File tree

3 files changed

+42
-38
lines changed

3 files changed

+42
-38
lines changed

src/main/cljs/cljs/repl.cljs

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@
4949
(when doc
5050
(println " " doc))))
5151
(when n
52-
(when-let [fnspec (spec/fn-spec (symbol (str (ns-name n)) (name nm)))]
52+
(when-let [fnspec (spec/get-spec (symbol (str (ns-name n)) (name nm)))]
5353
(print "Spec")
5454
(doseq [role [:args :ret :fn]]
5555
(when-let [spec (get fnspec role)]

src/main/cljs/cljs/spec.cljc

+23-19
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88

99
(ns cljs.spec
1010
(:refer-clojure :exclude [+ * and or cat def keys resolve])
11-
(:require [cljs.analyzer.api :refer [resolve]]
11+
(:require [cljs.analyzer :as ana]
12+
[cljs.analyzer.api :refer [resolve]]
1213
[clojure.walk :as walk]
1314
[cljs.spec.impl.gen :as gen]
1415
[clojure.string :as str]))
@@ -35,11 +36,22 @@
3536
(sequential? form) (walk/postwalk #(if (symbol? %) (res env %) %) (unfn form))
3637
:else form))
3738

39+
(defn- ns-qualify
40+
"Qualify symbol s by resolving it or using the current *ns*."
41+
[env s]
42+
(if (namespace s)
43+
(let [v (resolve env s)]
44+
(assert v (str "Unable to resolve: " s))
45+
(->sym v))
46+
(symbol (str ana/*cljs-ns*) (str s))))
47+
3848
(defmacro def
39-
"Given a namespace-qualified keyword or symbol k, and a spec, spec-name, predicate or regex-op
40-
makes an entry in the registry mapping k to the spec"
49+
"Given a namespace-qualified keyword or resolveable symbol k, and a spec,
50+
spec-name, predicate or regex-op makes an entry in the registry mapping k to
51+
the spec"
4152
[k spec-form]
42-
`(cljs.spec/def-impl ~k '~(res &env spec-form) ~spec-form))
53+
(let [k (if (symbol? k) (ns-qualify &env k) k)]
54+
`(cljs.spec/def-impl '~k '~(res &env spec-form) ~spec-form)))
4355

4456
(defmacro spec
4557
"Takes a single predicate form, e.g. can be the name of a predicate,
@@ -248,6 +260,9 @@
248260
and returns a spec whose conform/explain take a fn and validates it
249261
using generative testing. The conformed value is always the fn itself.
250262
263+
See 'fdef' for a single operation that creates an fspec and
264+
registers it, as well as a full description of :args, :ret and :fn
265+
251266
Optionally takes :gen generator-fn, which must be a fn of no args
252267
that returns a test.check generator."
253268
[& {:keys [args ret fn gen]}]
@@ -264,15 +279,6 @@
264279
(assert (not (empty? preds)))
265280
`(cljs.spec/tuple-impl '~(mapv #(res &env %) preds) ~(vec preds)))
266281

267-
(defn- ns-qualify
268-
"Qualify symbol s by resolving it or using the current *ns*."
269-
[env s]
270-
(if-let [resolved (resolve env s)]
271-
(->sym resolved)
272-
(if (namespace s)
273-
s
274-
(symbol (str (.-name *ns*)) (str s)))))
275-
276282
(def ^:private _speced_vars (atom #{}))
277283

278284
(defn speced-vars*
@@ -308,8 +314,8 @@ specified, return speced vars from all namespaces."
308314
expected to contain predicates that relate those values
309315
310316
Qualifies fn-sym with resolve, or using *ns* if no resolution found.
311-
Registers specs in the global registry, where they can be retrieved
312-
by calling fn-spec.
317+
Registers an fspec in the global registry, where it can be retrieved
318+
by calling get-spec with the var or full-qualified symbol.
313319
314320
Once registered, function specs are included in doc, checked by
315321
instrument, tested by the runner clojure.spec.test/run-tests, and (if
@@ -329,10 +335,8 @@ specified, return speced vars from all namespaces."
329335
:sym symbol?)
330336
:ret symbol?)"
331337
[fn-sym & specs]
332-
(let [env &env
333-
qn (ns-qualify env fn-sym)]
334-
(swap! _speced_vars conj qn)
335-
`(cljs.spec/def '~qn (cljs.spec/fspec ~@specs))))
338+
(swap! _speced_vars conj (ns-qualify &env fn-sym))
339+
`(cljs.spec/def ~fn-sym (cljs.spec/fspec ~@specs)))
336340

337341
(defmacro with-instrument-disabled
338342
"Disables instrument's checking of calls, within a scope."

src/main/cljs/cljs/spec.cljs

+18-18
Original file line numberDiff line numberDiff line change
@@ -238,18 +238,30 @@
238238
(defn ^:skip-wiki def-impl
239239
"Do not call this directly, use 'def'"
240240
[k form spec]
241-
(assert (c/and (named? k) (namespace k)) "k must be namespaced keyword/symbol")
241+
(assert (c/and (named? k) (namespace k)) "k must be namespaced keyword or resolveable symbol")
242242
(let [spec (if (c/or (spec? spec) (regex? spec) (get @registry-ref spec))
243243
spec
244244
(spec-impl form spec nil nil))]
245245
(swap! registry-ref assoc k spec)
246246
k))
247247

248248
(defn registry
249-
"returns the registry map"
249+
"returns the registry map, prefer 'get-spec' to lookup a spec by name"
250250
[]
251251
@registry-ref)
252252

253+
(defn- ->sym
254+
"Returns a symbol from a symbol or var"
255+
[x]
256+
(if (var? x)
257+
(.-sym x)
258+
x))
259+
260+
(defn get-spec
261+
"Returns spec registered for keyword/symbol/var k, or nil."
262+
[k]
263+
(get (registry) (if (keyword? k) k (->sym k))))
264+
253265
(declare map-spec)
254266

255267
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; instrument ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -259,23 +271,11 @@
259271
[spec v]
260272
)
261273

262-
(defn- ->sym
263-
"Returns a symbol from a symbol or var"
264-
[x]
265-
(if (var? x)
266-
(.-sym x)
267-
x))
268-
269274
(defn- fn-spec?
270275
"Fn-spec must include at least :args or :ret specs."
271276
[m]
272277
(c/or (:args m) (:ret m)))
273278

274-
(defn fn-spec
275-
"Returns fspec of specs for var or symbol v, or nil."
276-
[v]
277-
(get (registry) (->sym v)))
278-
279279
(defn- spec-checking-fn
280280
[v f]
281281
(let [conform! (fn [v role spec data args]
@@ -292,7 +292,7 @@
292292
[& args]
293293
(if *instrument-enabled*
294294
(s/with-instrument-disabled
295-
(let [specs (fn-spec v)]
295+
(let [specs (get-spec v)]
296296
(when (:args specs) (conform! v :args (:args specs) args args))
297297
(binding [*instrument-enabled* true]
298298
(apply f args))))
@@ -301,7 +301,7 @@
301301

302302
(defn- macroexpand-check
303303
[v args]
304-
(let [specs (fn-spec v)]
304+
(let [specs (get-spec v)]
305305
(when-let [arg-spec (:args specs)]
306306
(when (= ::invalid (conform arg-spec args))
307307
(let [ed (assoc (explain-data* arg-spec [:args]
@@ -323,7 +323,7 @@
323323

324324
(defn instrument*
325325
[v]
326-
(let [spec (fn-spec v)]
326+
(let [spec (get-spec v)]
327327
(if (fn-spec? spec)
328328
(locking instrumented-vars
329329
(let [{:keys [raw wrapped]} (get @instrumented-vars v)
@@ -1128,7 +1128,7 @@
11281128
"Return true if start <= val and val < end"
11291129
[start end val]
11301130
(cond
1131-
(integer? val) (and (<= start val) (< val end))
1131+
(integer? val) (c/and (<= start val) (< val end))
11321132

11331133
(instance? goog.math.Long val)
11341134
(c/and (.lessThanOrEqual start val)

0 commit comments

Comments
 (0)