Skip to content

Commit

Permalink
CLJS-639: warning when records initialized incorrectly
Browse files Browse the repository at this point in the history
When not a defrecord internal constructor call check the arity of the
instantiation form against the fields - ignoring extmap, meta and
hash. This is done by setting :internal-ctor meta on the record symbol,
otherwise the logic is identical to deftype*. Fix some formatting.
  • Loading branch information
swannodette committed Nov 19, 2013
1 parent 34821a2 commit 8c6dd24
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 11 deletions.
10 changes: 7 additions & 3 deletions src/clj/cljs/analyzer.clj
Expand Up @@ -758,9 +758,10 @@
argexprs (vec (map #(analyze enve %) args))
known-num-fields (:num-fields (resolve-existing-var env ctor))
argc (count args)]
(when (and known-num-fields (not= known-num-fields argc) (:fn-arity *cljs-warnings*))
(when (and (:fn-arity *cljs-warnings*)
(not (-> ctor meta :internal-ctor))
known-num-fields (not= known-num-fields argc))
(warning :fn-arity env {:argc argc :ctor ctor}))

{:env env :op :new :form form :ctor ctorexpr :args argexprs
:children (into [ctorexpr] argexprs)})))

Expand Down Expand Up @@ -961,7 +962,10 @@
(let [t (:name (resolve-var (dissoc env :locals) tsym))]
(swap! env/*compiler* update-in [::namespaces (-> env :ns :name) :defs tsym]
(fn [m]
(let [m (assoc (or m {}) :name t :type true)]
(let [m (assoc (or m {})
:name t
:type true
:num-fields (count fields))]
(merge m
{:protocols (-> tsym meta :protocols)}
(source-info tsym env)))))
Expand Down
17 changes: 9 additions & 8 deletions src/clj/cljs/core.clj
Expand Up @@ -908,18 +908,19 @@
(~'defrecord* ~tagname ~hinted-fields ~pmasks)
(extend-type ~tagname ~@(dt->et tagname impls fields true))))))

(defn- build-map-factory
[rsym rname fields]
(defn- build-map-factory [rsym rname fields]
(let [fn-name (symbol (core/str 'map-> rsym))
ms (gensym)
ks (map keyword fields)
getters (map (fn [k] `(~k ~ms)) ks)]
`(defn ~fn-name
[~ms]
ms (gensym)
ks (map keyword fields)
getters (map (fn [k] `(~k ~ms)) ks)]
`(defn ~fn-name [~ms]
(new ~rname ~@getters nil (dissoc ~ms ~@ks)))))

(defmacro defrecord [rsym fields & impls]
(let [r (:name (cljs.analyzer/resolve-var (dissoc &env :locals) rsym))]
(let [rsym (vary-meta rsym assoc :internal-ctor true)
r (vary-meta
(:name (cljs.analyzer/resolve-var (dissoc &env :locals) rsym))
assoc :internal-ctor true)]
`(let []
~(emit-defrecord &env rsym r fields impls)
(set! (.-cljs$lang$type ~r) true)
Expand Down

0 comments on commit 8c6dd24

Please sign in to comment.