Skip to content

Commit

Permalink
[#51] Polish a bit the xref functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
bbatsov committed May 2, 2019
1 parent 5b96f22 commit 057ee16
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 17 deletions.
33 changes: 25 additions & 8 deletions src/orchard/xref.clj
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
(ns orchard.xref
"Utilities for finding function dependencies and
usages."
references."
{:added "0.5.0"}
(:require
[orchard.query :as q]))

(defn- as-val [thing]
(defn- as-val
"Convert `thing` to a function value."
[thing]
(cond
(var? thing) (deref thing)
(symbol? thing) (deref (find-var thing))
(fn? thing) thing))

(defn fdeps
(defn fn-deps
"Returns a set with all the functions invoked by `val`.
`val` must be a function value, a var or a symbol."
`val` can be a function value, a var or a symbol."
{:added "0.5"}
[val]
(let [val (as-val val)]
(set (some->> val class .getDeclaredFields
Expand All @@ -25,12 +28,26 @@
(.get f val))
nil)))))))

(defn xref
(defn- fn->sym
"Convert a function value `f` to symbol."
[f]
(symbol (Compiler/demunge (.getName (type f)))))

(defn- as-var
"Convert `thing` to a var."
[thing]
(cond
(var? thing) thing
(symbol? thing) (find-var thing)
(fn? thing) (find-var (f->sym thing))))

(defn fn-refs
"Find all functions that refer `var`.
It can be either a var or a symbol that can resolved to a var."
`var` can be a function value, a var or a symbol."
{:added "0.5"}
[var]
(let [var (if (var? var) var (find-var var))
(let [var (as-var var)
all-vars (q/vars {:ns-query {:project? true} :private? true})
all-vals (map deref all-vars)
deps-map (zipmap all-vars (map fdeps all-vals))]
deps-map (zipmap all-vars (map fn-deps all-vals))]
(map first (filter (fn [[k v]] (contains? v var)) deps-map))))
21 changes: 12 additions & 9 deletions test/orchard/xref_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,27 @@
(defn- dummy-fn [x]
(map #(* % 2) (filter even? (range 1 10))))

(deftest fdeps-test
(deftest fn-deps-test
(testing "with a fn value"
(is (= (xref/fdeps dummy-fn)
(is (= (xref/fn-deps dummy-fn)
#{#'clojure.core/map #'clojure.core/filter
#'clojure.core/even? #'clojure.core/range})))
(testing "with a var"
(is (= (xref/fdeps #'dummy-fn)
(is (= (xref/fn-deps #'dummy-fn)
#{#'clojure.core/map #'clojure.core/filter
#'clojure.core/even? #'clojure.core/range})))
(testing "with a symbol"
(is (= (xref/fdeps 'orchard.xref-test/dummy-fn)
(is (= (xref/fn-deps 'orchard.xref-test/dummy-fn)
#{#'clojure.core/map #'clojure.core/filter
#'clojure.core/even? #'clojure.core/range}))))

(deftest xref-test
(deftest fn-refs-test
(testing "with a fn value"
(is (= (xref/fn-refs dummy-fn) '()))
(is (contains? (into #{} (xref/fn-refs #'map)) #'orchard.xref-test/dummy-fn)))
(testing "with a var"
(is (= (xref/xref #'dummy-fn) '()))
(is (contains? (into #{} (xref/xref #'map)) #'orchard.xref-test/dummy-fn)))
(is (= (xref/fn-refs #'dummy-fn) '()))
(is (contains? (into #{} (xref/fn-refs #'map)) #'orchard.xref-test/dummy-fn)))
(testing "with a symbol"
(is (= (xref/xref 'orchard.xref-test/dummy-fn) '()))
(is (contains? (into #{} (xref/xref #'map)) #'orchard.xref-test/dummy-fn))))
(is (= (xref/fn-refs 'orchard.xref-test/dummy-fn) '()))
(is (contains? (into #{} (xref/fn-refs #'map)) #'orchard.xref-test/dummy-fn))))

0 comments on commit 057ee16

Please sign in to comment.