如何在Clojure项目中定义所有变量?

时间:2017-08-11 21:00:40

标签: clojure namespaces

我正在收集项目中的所有用户定义函数。作为测试成员身份的一种方式,我使用:

(defn get-var-namespace
  [qualified-var]
  {:pre [(var? qualified-var)]}
  (-> qualified-var meta :ns))

(defn project-name
  "returns a string representation of the root project name.
  this is the same as the directory that the project is located in"
  []
  (last (str/split (System/getProperty "user.dir") #"/")))

(defn get-project-namespaces
  "return all namespaces defined within the project"
  []
  (let [p-name (project-name)]
    (filter (fn [x]
              (let [n (first (str/split (str (ns-name x)) #"\."))]
                (= n p-name))) (all-ns))))

(defn user-defined-var? [project-namespaces var]
  (some #{(get-var-namespace var)} project-namespaces))


(defn namespace-deps
  "returns a map whose keys are user defined functions and vals are sets of
  user defined functions."
  [project-namespaces ns]
  (let [find-vars-in-expr
        (fn [x] (let [nodes (ast/nodes x)
                      top-level (:var (first nodes))
                      non-recursive-deps (remove #{top-level}
                                                 (filter (partial var-has-user-ns project-namespaces)
                                                         (filter some? (map :var nodes))))]
                  {top-level (set non-recursive-deps)}))]
    (dissoc (apply merge-with clojure.set/union
                   (map find-vars-in-expr (jvm/analyze-ns ns))) nil)))

作为例子

clj-smart-test.core> (clojure.pprint/pprint (namespace-deps (get-project-namespaces) *ns*))
{#'clj-smart-test.core/foo
 #{#'clj-smart-test.baz/baz1 #'clj-smart-test.core/bar
   #'clj-smart-test.foo/foo #'clj-smart-test.core/k},
 #'clj-smart-test.core/get-project-namespaces
 #{#'clj-smart-test.core/project-name},
 #'clj-smart-test.core/project-name #{},
 #'clj-smart-test.core/var-has-user-ns
 #{#'clj-smart-test.core/get-var-namespace},
 #'clj-smart-test.core/bar #{},
 #'clj-smart-test.core/f #{},
 #'clj-smart-test.core/get-var-namespace #{},
 #'clj-smart-test.core/namespace-deps
 #{#'clj-smart-test.core/var-has-user-ns},
 #'clj-smart-test.core/k #{}}
nil

我是否需要了解任何角落案例?我知道用户可以在文件中创建一个任意名称空间,所以我不能总是假设创建项目的目录为例如lein new my-project,它将my-project作为根目录。此版本无法捕获defrecord等。

0 个答案:

没有答案