Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 90 lines (79 sloc) 3.35 kb
4850d4a @stuartsierra Refactor to independent namespaces with minimal dependencies
stuartsierra authored
1 ;; Copyright (c) Stuart Sierra, 2012. All rights reserved. The use and
2 ;; distribution terms for this software are covered by the Eclipse
3 ;; Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
4 ;; which can be found in the file epl-v10.html at the root of this
5 ;; distribution. By using this software in any fashion, you are
6 ;; agreeing to be bound by the terms of this license. You must not
7 ;; remove this notice, or any other, from this software.
8
9 (ns ^{:author "Stuart Sierra"
10 :doc "Parse Clojure namespace (ns) declarations and extract
11 dependencies."}
12 clojure.tools.namespace.parse
13 (:require [clojure.set :as set]))
14
15 (defn comment?
16 "Returns true if form is a (comment ...)"
17 [form]
18 (and (list? form) (= 'comment (first form))))
19
20 (defn ns-decl?
21 "Returns true if form is a (ns ...) declaration."
22 [form]
23 (and (list? form) (= 'ns (first form))))
24
25 (defn read-ns-decl
26 "Attempts to read a (ns ...) declaration from a
27 java.io.PushbackReader, and returns the unevaluated form. Returns
28 nil if read fails or if a ns declaration cannot be found. The ns
29 declaration must be the first Clojure form in the file, except for
30 (comment ...) forms."
31 [rdr]
32 (try
10f03a7 @stuartsierra Add comment in source code pointing to TNS-1
stuartsierra authored
33 (loop [] (let [form (doto (read rdr) str)] ; str forces errors, see TNS-1
4850d4a @stuartsierra Refactor to independent namespaces with minimal dependencies
stuartsierra authored
34 (cond
35 (ns-decl? form) form
36 (comment? form) (recur)
37 :else nil)))
38 (catch Exception e nil)))
39
40 ;;; Parsing dependencies
41
e37221f @stuartsierra Parse prefix lists represented as vectors; TNS-9 and TNS-11
stuartsierra authored
42 (defn- prefix-spec?
43 "Returns true if form represents a libspec prefix list like
44 (prefix name1 name1) or [com.example.prefix [name1 :as name1]]"
45 [form]
46 (and (sequential? form) ; should be a list, but often is not
47 (symbol? (first form))
930833d @stuartsierra Fix regression: supporting bare vector as libspec
stuartsierra authored
48 (not-any? keyword? form)
49 (< 1 (count form)))) ; not a bare vector like [foo]
e37221f @stuartsierra Parse prefix lists represented as vectors; TNS-9 and TNS-11
stuartsierra authored
50
51 (defn- option-spec?
930833d @stuartsierra Fix regression: supporting bare vector as libspec
stuartsierra authored
52 "Returns true if form represents a libspec vector containing optional
53 keyword arguments like [namespace :as alias] or
54 [namespace :refer (x y)] or just [namespace]"
e37221f @stuartsierra Parse prefix lists represented as vectors; TNS-9 and TNS-11
stuartsierra authored
55 [form]
56 (and (sequential? form) ; should be a vector, but often is not
57 (symbol? (first form))
930833d @stuartsierra Fix regression: supporting bare vector as libspec
stuartsierra authored
58 (or (keyword? (second form)) ; vector like [foo :as f]
59 (= 1 (count form))))) ; bare vector like [foo]
e37221f @stuartsierra Parse prefix lists represented as vectors; TNS-9 and TNS-11
stuartsierra authored
60
4850d4a @stuartsierra Refactor to independent namespaces with minimal dependencies
stuartsierra authored
61 (defn- deps-from-libspec [prefix form]
e37221f @stuartsierra Parse prefix lists represented as vectors; TNS-9 and TNS-11
stuartsierra authored
62 (cond (prefix-spec? form)
4850d4a @stuartsierra Refactor to independent namespaces with minimal dependencies
stuartsierra authored
63 (apply set/union
64 (map (fn [f] (deps-from-libspec
65 (symbol (str (when prefix (str prefix "."))
66 (first form)))
67 f))
68 (rest form)))
e37221f @stuartsierra Parse prefix lists represented as vectors; TNS-9 and TNS-11
stuartsierra authored
69 (option-spec? form)
4850d4a @stuartsierra Refactor to independent namespaces with minimal dependencies
stuartsierra authored
70 (deps-from-libspec prefix (first form))
71 (symbol? form)
72 #{(symbol (str (when prefix (str prefix ".")) form))}
e37221f @stuartsierra Parse prefix lists represented as vectors; TNS-9 and TNS-11
stuartsierra authored
73 (keyword? form) ; Some people write (:require ... :reload-all)
4850d4a @stuartsierra Refactor to independent namespaces with minimal dependencies
stuartsierra authored
74 #{}
75 :else
76 (throw (IllegalArgumentException.
77 (pr-str "Unparsable namespace form:" form)))))
78
79 (defn- deps-from-ns-form [form]
80 (when (and (list? form)
81 (contains? #{:use :require} (first form)))
82 (apply set/union (map #(deps-from-libspec nil %) (rest form)))))
83
84 (defn deps-from-ns-decl
85 "Given an (ns...) declaration form (unevaluated), returns a set of
86 symbols naming the dependencies of that namespace. Handles :use and
87 :require clauses but not :load."
88 [decl]
89 (apply set/union (map deps-from-ns-form decl)))
Something went wrong with that request. Please try again.