8f6abbf8caf3cec5b47cfbb8641e8ed7f9eb50df — Zach Smith 5 months ago 5b29e62
Make field validation more informative when proto is unknown
2 files changed, 23 insertions(+), 11 deletions(-)

M fugue.janet
M test/fugue.janet
M fugue.janet => fugue.janet +13 -9
@@ 46,9 46,9 @@
  (let [proto-fields ;(if (table? obj)
                        (fields (table/getproto obj))
  (let [proto-fields (if (table? obj)
                       (fields (table/getproto obj))
        obj-fields (or (get-in obj [:_meta :fields]) @[])]
    (array ;proto-fields ;obj-fields)))

@@ 67,17 67,21 @@

(defn- validate-field
  [field fields]
  [field fields name]
  (unless fields
    (errorf "Field validation for `%s` failed; no fields registered" (string field)))
    (errorf "Field validation for `%s` failed; proto %s not registered"
            (string field)
            (string name)))
  (unless (index-of field fields)
    (errorf "Field `%s` not found; got fields: %q" (string field) fields)))
    (errorf "Field `%s` not found; got fields: %q"
            (string field)

(defn- validate-proto-match
  [name attrs]
  (let [fields (comp-aware-fields name)]
    (loop [k :keys attrs]
      (validate-field k fields))))
      (validate-field k fields name))))

(defn- warn-proto-method-shadow
  [name proto]

@@ 823,9 827,9 @@
  [proto x &opt y]
  (let [[obj field] (if y [x y] [nil x])
        fields (fields (eval proto))]
        fields (comp-aware-fields proto)]

    (validate-field field fields)
    (validate-field field fields proto)

    (if-not obj

M test/fugue.janet => test/fugue.janet +10 -2
@@ 459,15 459,23 @@
    (is (= "A2" (a-slot-haver :name)))
    (is (= "B2" (b-slot-haver :name)))))

(def DefinedButNotAProto @{})

(deftest @-macro
  (is (= (fugue/@ SlotHaver :name) :name))
  (let [a-slot-haver (new-SlotHaver :name "Freddie")
        not-a-member-of-queen {:name "Queen Victoria"}]
        not-a-member-of-queen @{:name "Queen Victoria"}]
    (is (= "Freddie" (a-slot-haver (fugue/@ SlotHaver :name))))
    (is (= "Freddie" (fugue/@ SlotHaver a-slot-haver :name)))
    (set (a-slot-haver (fugue/@ SlotHaver :name)) "Brian May")
    (is (= "Brian May" (a-slot-haver :name)))
    (is (thrown? (fugue/@ SlotHaver not-a-member-of-queen :name)))))
    # Throws at runtime, because the table isn't a child of SlotHaver
    (is (thrown? (fugue/@ SlotHaver not-a-member-of-queen :name)))
    # Throws at compiletime, because the symbol isn't defined
    (is (thrown? (apply [fugue/@ 'SomeUndefinedProto :one-of-its-fields])))
    # Throws at compiletime, because the symbol is defined but not
    # known to Fugue
    (is (thrown? (apply [fugue/@ 'DefinedButNotAProto :one-of-its-fields])))))

(fugue/defproto MyMatcher nil name {})