Skip to content

Commit

Permalink
Add mandatory/all methods to RefLike protocol
Browse files Browse the repository at this point in the history
These methods allow a RefLike implementation to determine which
dependencies are optional for a reflike, and which dependencies are
mandatory.

Resolves: weavejester#77
See also: weavejester#63, weavejester#68
  • Loading branch information
clyfe committed Dec 5, 2020
1 parent d26aa89 commit d83602c
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 5 deletions.
12 changes: 9 additions & 3 deletions src/integrant/core.cljc
Expand Up @@ -10,6 +10,8 @@

(defprotocol RefLike
(ref-key [r] "Return the key of the reference.")
(ref-mandatory-keys [r] "Returns the mandatory keys.")
(ref-all-keys [r] "Returns the mandatory and optional keys.")
(ref-resolve [r config resolvef] "Return the resolved value."))

(defonce
Expand Down Expand Up @@ -63,13 +65,17 @@
(defrecord Ref [key]
RefLike
(ref-key [_] key)
(ref-mandatory-keys [_] #{key})
(ref-all-keys [_] #{key})
(ref-resolve [_ config resolvef]
(let [[k v] (first (find-derived config key))]
(resolvef k v))))

(defrecord RefSet [key]
RefLike
(ref-key [_] key)
(ref-mandatory-keys [_] #{})
(ref-all-keys [_] #{key})
(ref-resolve [_ config resolvef]
(set (for [[k v] (find-derived config key)]
(resolvef k v)))))
Expand Down Expand Up @@ -124,9 +130,9 @@
(throw (ambiguous-key-exception m k (map key kvs))))
(first kvs)))

(defn- find-derived-refs [config v include-refsets?]
(->> (depth-search (if include-refsets? reflike? ref?) v)
(map ref-key)
(defn- find-derived-refs [config v optional-deps?]
(->> (depth-search reflike? v)
(mapcat (if optional-deps? ref-all-keys ref-mandatory-keys))
(mapcat #(map key (find-derived config %)))))

(defn dependency-graph
Expand Down
33 changes: 31 additions & 2 deletions test/integrant/core_test.cljc
Expand Up @@ -57,13 +57,21 @@
(is (ig/ref? (ig/ref ::foo)))
(is (ig/ref? (ig/ref [::foo ::bar])))
(is (ig/reflike? (ig/ref ::foo)))
(is (ig/reflike? (ig/ref [::foo ::bar]))))
(is (ig/reflike? (ig/ref [::foo ::bar])))
(is (= #{::foo} (ig/ref-mandatory-keys (ig/ref ::foo))))
(is (= #{::foo} (ig/ref-all-keys (ig/ref ::foo))))
(is (= #{[::foo ::bar]} (ig/ref-mandatory-keys (ig/ref [::foo ::bar]))))
(is (= #{[::foo ::bar]} (ig/ref-all-keys (ig/ref [::foo ::bar])))))

(deftest refset-test
(is (ig/refset? (ig/refset ::foo)))
(is (ig/refset? (ig/refset [::foo ::bar])))
(is (ig/reflike? (ig/refset ::foo)))
(is (ig/reflike? (ig/refset [::foo ::bar]))))
(is (ig/reflike? (ig/refset [::foo ::bar])))
(is (= #{} (ig/ref-mandatory-keys (ig/refset ::foo))))
(is (= #{::foo} (ig/ref-all-keys (ig/refset ::foo))))
(is (= #{} (ig/ref-mandatory-keys (ig/refset [::foo ::bar]))))
(is (= #{[::foo ::bar]} (ig/ref-all-keys (ig/refset [::foo ::bar])))))

(deftest composite-keyword-test
(let [k (ig/composite-keyword [::a ::b])]
Expand Down Expand Up @@ -152,6 +160,14 @@
'#{integrant.test.foo}))
(is (some? (find-ns 'integrant.test.foo))))))

(defrecord RefThing [key]
ig/RefLike
(ref-key [_] key)
(ref-mandatory-keys [_] #{::p})
(ref-all-keys [_] #{::pp ::p})
(ref-resolve [_ config resolvef]
(set (for [[k v] (ig/find-derived config key)]
(resolvef k v)))))

(deftest dependency-graph-test
(let [m {::a (ig/ref ::p), ::b (ig/refset ::ppp) ::p 1, ::pp 2}]
Expand All @@ -165,6 +181,19 @@
(let [g (ig/dependency-graph m {:optional-deps? false})]
(is (dep/depends? g ::a ::p))
(is (not (dep/depends? g ::b ::p)))
(is (not (dep/depends? g ::b ::pp))))))
(let [m {::a (->RefThing ::p), ::b (->RefThing ::ppp), ::p 1, ::pp 2}]
(testing "graph with refthings and all deps"
(let [g (ig/dependency-graph m)]
(is (dep/depends? g ::a ::p))
(is (dep/depends? g ::a ::pp))
(is (dep/depends? g ::b ::p))
(is (dep/depends? g ::b ::pp))))
(testing "graph with refthings and and mandatory deps"
(let [g (ig/dependency-graph m {:optional-deps? false})]
(is (dep/depends? g ::a ::p))
(is (not (dep/depends? g ::a ::pp)))
(is (dep/depends? g ::b ::p))
(is (not (dep/depends? g ::b ::pp)))))))

(deftest key-comparator-test
Expand Down

0 comments on commit d83602c

Please sign in to comment.