|
3 | 3 | ;;;; Distributed under the Eclipse Public License, the same as Clojure. |
4 | 4 | (ns refactor-nrepl.ns.slam.hound.regrow |
5 | 5 | (:require |
6 | | - [clojure.set :as set] |
7 | 6 | [nrepl.middleware.interruptible-eval :refer [*msg*]] |
8 | | - [refactor-nrepl.ns.slam.hound.search :as search]) |
9 | | - (:import |
10 | | - (clojure.lang IMapEntry IRecord))) |
| 7 | + [refactor-nrepl.ns.slam.hound.search :as search])) |
11 | 8 |
|
12 | 9 | (def ^:dynamic *cache* (atom {})) |
13 | 10 | (def ^:dynamic *dirty-ns* (atom #{})) |
|
20 | 17 |
|
21 | 18 | (alter-var-root #'clojure.main/repl wrap-clojure-repl) |
22 | 19 |
|
23 | | -(defmacro ^:private caching [key & body] |
24 | | - `(if *cache* |
25 | | - (if-let [v# (get @*cache* ~key)] |
26 | | - v# |
27 | | - (let [v# (do ~@body)] |
28 | | - (swap! *cache* assoc ~key v#) |
29 | | - v#)) |
30 | | - (do ~@body))) |
31 | | - |
32 | 20 | (defn cache-with-dirty-tracking |
33 | 21 | "The function to be cached, f, should have two signatures. A zero-operand |
34 | 22 | signature which computes the result for all namespaces, and a two-operand |
|
59 | 47 | (defn- all-ns-imports [] |
60 | 48 | (cache-with-dirty-tracking :all-ns-imports all-ns-imports*)) |
61 | 49 |
|
62 | | -(defn- ns->symbols [] |
63 | | - (caching :ns->symbols |
64 | | - (let [xs (all-ns)] |
65 | | - (zipmap xs (mapv (comp set keys ns-publics) xs))))) |
66 | | - |
67 | 50 | (defn- symbols->ns-syms* |
68 | 51 | ([] |
69 | 52 | (symbols->ns-syms* {} (all-ns))) |
|
79 | 62 | (defn- symbols->ns-syms [] |
80 | 63 | (cache-with-dirty-tracking :symbols->ns-syms symbols->ns-syms*)) |
81 | 64 |
|
82 | | -(defn- walk |
83 | | - "Adapted from clojure.walk/walk and clojure.walk/prewalk; this version |
84 | | - preserves metadata on compound forms." |
85 | | - [f form] |
86 | | - (-> (cond |
87 | | - (list? form) (apply list (map f form)) |
88 | | - (instance? IMapEntry form) (vec (map f form)) |
89 | | - (seq? form) (doall (map f form)) |
90 | | - (instance? IRecord form) (reduce (fn [r x] (conj r (f x))) form form) |
91 | | - (coll? form) (into (empty form) (map f form)) |
92 | | - :else form) |
93 | | - (as-> form (if-let [m (meta form)] |
94 | | - (with-meta form m) |
95 | | - form)))) |
96 | | - |
97 | | -(defn- prewalk [f form] |
98 | | - (walk (partial prewalk f) (f form))) |
99 | | - |
100 | | -(defn- symbols-in-body [body] |
101 | | - (filter symbol? (remove coll? (rest (tree-seq coll? seq body))))) |
102 | | - |
103 | | -(defn- remove-var-form |
104 | | - "Remove (var symbol) forms from body" |
105 | | - [expr] |
106 | | - (if (and (coll? expr) (= (first expr) 'var)) |
107 | | - nil |
108 | | - expr)) |
109 | | - |
110 | | -(def ^:private ns-qualifed-syms |
111 | | - (memoize |
112 | | - (fn [body] |
113 | | - (apply merge-with set/union {} |
114 | | - (for [ss (symbols-in-body body) |
115 | | - :let [[_ alias var-name] (re-matches #"(.+)/(.+)" (str ss))] |
116 | | - :when alias] |
117 | | - {(symbol alias) #{(symbol var-name)}}))))) |
118 | | - |
119 | 65 | (defn- ns-import-candidates |
120 | 66 | "Search (all-ns) for imports that match missing-sym, returning a set of |
121 | 67 | class symbols. This is slower than scanning through the list of static |
|
128 | 74 | s)) |
129 | 75 | #{} (vals (all-ns-imports)))) |
130 | 76 |
|
131 | | -(defn- alias-candidates [_type missing body] |
132 | | - (set |
133 | | - (let [syms-with-alias (get (ns-qualifed-syms body) missing)] |
134 | | - (when (seq syms-with-alias) |
135 | | - (let [ns->syms (ns->symbols)] |
136 | | - (for [ns (all-ns) |
137 | | - :when (set/subset? syms-with-alias (ns->syms ns))] |
138 | | - (ns-name ns))))))) |
139 | | - |
140 | 77 | (defn candidates |
141 | 78 | "Return a set of class or ns symbols that match the given constraints." |
142 | | - [type missing body old-ns-map] |
| 79 | + [type missing _body _old-ns-map] |
143 | 80 | (case type |
144 | 81 | :import (into (ns-import-candidates missing) |
145 | 82 | (get @search/available-classes-by-last-segment missing)) |
146 | | - :alias (let [cs (alias-candidates type missing body)] |
147 | | - (if (seq cs) |
148 | | - cs |
149 | | - ;; Try the alias search again without dynamically resolved vars |
150 | | - ;; in case #' was used to resolve private vars in an aliased ns |
151 | | - (let [body' (prewalk remove-var-form body)] |
152 | | - (if (= body' body) |
153 | | - cs |
154 | | - (alias-candidates type missing body'))))) |
155 | | - :refer (get (symbols->ns-syms) missing) |
156 | | - :rename (reduce-kv |
157 | | - (fn [s ns orig->rename] |
158 | | - (cond-> s |
159 | | - (some #{missing} (vals orig->rename)) (conj ns))) |
160 | | - #{} (:rename old-ns-map)))) |
| 83 | + :refer (get (symbols->ns-syms) missing))) |
0 commit comments