Skip to content

Commit c5e7522

Browse files
committed
[Fix #239] Teach clean-ns about more metadata
The performance hit in considering literally every piece of metadata shouldn't be too detrimental so we'll just err on the side of caution for now.
1 parent 2295c2c commit c5e7522

File tree

5 files changed

+57
-32
lines changed

5 files changed

+57
-32
lines changed

src/refactor_nrepl/find/symbols_in_file.clj

Lines changed: 36 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,12 @@
3434
(.substring s 0 (dec (.length s)))
3535
s))))
3636

37+
(defn- strip-meta-from-reader
38+
[metadata]
39+
(-> metadata
40+
(dissoc :line :column :end-line :end-column)
41+
not-empty))
42+
3743
(defn symbols-in-file
3844
"Return a set of all the symbols occurring in the file at path.
3945
@@ -63,24 +69,33 @@
6369
(let [rdr (-> path slurp core/file-content-sans-ns
6470
readers/indexing-push-back-reader)
6571
rdr-opts {:read-cond :allow :features #{dialect} :eof :eof}
66-
syms (atom #{})
67-
collect-symbol (fn [form]
68-
;; Regular symbol
69-
(when (symbol? form)
70-
(swap! syms conj (normalize-ctor-call form)))
71-
;; Classes used in typehints
72-
(when-let [t (:tag (meta form))]
73-
(swap! syms conj t))
74-
(when (and (keyword? form)
75-
(core/fully-qualified? form))
76-
(swap! syms conj
77-
(symbol (core/prefix form)
78-
(core/suffix form))))
79-
form)]
80-
(loop [form (reader/read rdr-opts rdr)]
81-
(when (not= form :eof)
82-
(walk/prewalk collect-symbol form)
83-
(recur (reader/read rdr-opts rdr))))
84-
(->> @syms
85-
(map (partial fix-ns-of-backquoted-symbols (dialect parsed-ns)))
86-
set)))))))
72+
syms (atom #{})]
73+
(letfn [(collect-symbols [form]
74+
(let [minimal-meta (strip-meta-from-reader (meta form))]
75+
;; metadata used in metadata-based protocol extensions
76+
;; see #239 for an example
77+
(when minimal-meta
78+
(->> minimal-meta
79+
seq
80+
flatten
81+
(run! collect-symbols)))
82+
;; Regular symbol
83+
(when (symbol? form)
84+
(swap! syms conj (normalize-ctor-call form)))
85+
;; Classes used in typehints
86+
(when-let [t (:tag minimal-meta)]
87+
(swap! syms conj t))
88+
(when (and (keyword? form)
89+
(core/fully-qualified? form))
90+
(swap! syms conj
91+
(symbol (core/prefix form)
92+
(core/suffix form)))))
93+
form)]
94+
(loop [form (reader/read rdr-opts rdr)]
95+
(when (not= form :eof)
96+
(walk/prewalk collect-symbols form)
97+
(recur (reader/read rdr-opts rdr))))
98+
(->> @syms
99+
(map
100+
(partial fix-ns-of-backquoted-symbols (dialect parsed-ns)))
101+
set))))))))

src/refactor_nrepl/ns/clean_ns.clj

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,11 @@
4343
(assert (core/source-file? path))
4444
;; Prefix notation not supported in cljs.
4545
;; We also turn it off for cljc for reasons of symmetry
46-
(config/with-config {:prefix-rewriting (if (or (core/cljs-file? path)
47-
(core/cljc-file? path))
48-
false
49-
(:prefix-rewriting config/*config*))}
46+
(config/with-config {:prefix-rewriting
47+
(if (or (core/cljs-file? path)
48+
(core/cljc-file? path))
49+
false
50+
(:prefix-rewriting config/*config*))}
5051
(let [ns-form (validate (core/read-ns-form-with-meta path))
5152
deps-preprocessor (if (get config/*config* :prune-ns-form)
5253
#(prune-dependencies % path)

test/refactor_nrepl/ns/clean_ns_test.clj

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -235,9 +235,10 @@
235235
(is (= expected actual))))
236236

237237
(deftest preserves-all-meta
238-
(let [actual (pprint-ns (clean-ns ns-with-lots-of-meta))
239-
expected (slurp (:path ns-with-lots-of-meta-clean))]
240-
(is (= expected actual))))
238+
(config/with-config {:prefix-rewriting false}
239+
(let [actual (pprint-ns (clean-ns ns-with-lots-of-meta))
240+
expected (slurp (:path ns-with-lots-of-meta-clean))]
241+
(is (= expected actual)))))
241242

242243
(deftest does-not-remove-dollar-sign-if-valid-symbol
243244
(let [cleaned (pprint-ns (clean-ns ns-using-dollar))]
Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,19 @@
1-
(ns ^:md1 ^:md2 ^{:longhand "as well" :really? "yes" :ok true} ns-with-gen-class-methods-meta
1+
(ns ^:md1 ^:md2 ^{:longhand "as well" :really? "yes" :ok true}
2+
ns-with-gen-class-methods-meta
23
(:gen-class
34
:methods [^:static [foo [String] String]
45
^{:test true} [bar [String] String]
56
^{:other "text"} [baz [String] String]]
67
:name Name)
7-
(:require [clojure.string :as s]
8-
[clojure.pprint :refer [fresh-line]]))
8+
(:require
9+
[clojure.string :as s]
10+
[clojure.pprint :refer [fresh-line]]
11+
[clojure.edn :as edn]))
912

1013
(defn useit
1114
[]
1215
(fresh-line))
16+
17+
(defn issue-239-metadata-based-protocol-extension []
18+
;; https://github.com/clojure-emacs/refactor-nrepl/issues/239
19+
^{`s/whatever-goes true} {})

test/resources/ns_with_lots_of_meta_clean.clj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@
77
^{:other "text"} [baz [String] String]]
88
:name Name)
99
(:require
10-
[clojure.pprint :refer [fresh-line]]))
10+
[clojure.pprint :refer [fresh-line]]
11+
[clojure.string :as s]))

0 commit comments

Comments
 (0)