Skip to content

Commit

Permalink
Reject resolve calls returning nil
Browse files Browse the repository at this point in the history
Fixes #9
  • Loading branch information
vemv committed Jun 5, 2019
1 parent 75f1954 commit d75606d
Show file tree
Hide file tree
Showing 5 changed files with 19 additions and 7 deletions.
2 changes: 0 additions & 2 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
* [ ] Documentation
* [ ] Security
* [ ] Performance
* [ ] Cross-compatibility (Clojure/ClojureScript)

## Reviewer checklist

Expand All @@ -32,4 +31,3 @@
* [ ] Documentation
* [ ] Security
* [ ] Performance
* [ ] Cross-compatibility (Clojure/ClojureScript)
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Functions related to Component or protocols will go here.

`implement` is a safer layer over raw metadata-based protocol extension.

> Metadata-based protocol extension might be a reliable solution against [this](https://github.com/clojure/tools.namespace/tree/bb9d7a1e98cc5a1ff53107966c96af6886eb0f5b#warnings-for-protocols) problem.
> Metadata-based protocol extension has recently proven to be a reliable solution against [this](https://github.com/clojure/tools.namespace/tree/bb9d7a1e98cc5a1ff53107966c96af6886eb0f5b#warnings-for-protocols) problem.
In plain Clojure you might be tempted to do:

Expand All @@ -36,8 +36,10 @@ However, several things might go wrong:
* e.g. to a function of not emitted by `defprotocol`
* What if `start` does not evaluate to a function?
* i.e. any other kind of value

`implement` guards you against all of those. It also provides some sugar (symbols don't have to be quoted) and enforcement (you cannot pass anything other than a symbol; this aims to avoid deeply nested, non-reusable code).

`implement` guards you against all of those, preventing the lack of errors (or opaque errors, at best) that you'd get otherwise.

It also provides some sugar (symbols don't have to be quoted) and enforcement (you cannot pass anything other than a symbol; this aims to avoid deeply nested, non-reusable code).

This is how it looks like:

Expand Down
2 changes: 1 addition & 1 deletion src/nedap/utils/modular/api.clj
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
{:style/indent 1}
[object & methods]
{:pre [(check! (spec/coll-of ::method-pair :min-count 1) (partition 2 methods)
metadata-extension-supported? *clojure-version*)]}
metadata-extension-supported? *clojure-version*)]}
(implement/implement object *ns* methods))

(defmacro add-method
Expand Down
5 changes: 4 additions & 1 deletion src/nedap/utils/modular/impl/implement.clj
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@

(defn fully-qualify [ns s]
(if (qualified-symbol? s)
(symbol (resolve s)) ;; turns 'component/start into 'com.stuartsierra.component/start
;; turn 'component/start into 'com.stuartsierra.component/start:
(do
(check! resolve s)
(symbol (resolve s)))
(symbol (str ns) (str s))))

(defn implement [obj ns kvs]
Expand Down
9 changes: 9 additions & 0 deletions test/unit/nedap/utils/modular/api/implement.clj
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,15 @@
(is (thrown? Exception (eval '(sut/implement {}
foo-impl oooooommmmmggggg))))))

(testing "spurious aliases in either side of the mapping"
(with-out-str
(is (thrown? Exception (eval '(sut/implement {}
made/up inc)))))

(with-out-str
(is (thrown? Exception (eval '(sut/implement {}
foo made/up))))))

(testing "Implementing incompatible protocols is prevented"
(is (thrown-with-msg? Exception #"The targeted protocol does not have `:extend-via-metadata` activated."
(sut/implement {}
Expand Down

0 comments on commit d75606d

Please sign in to comment.