Skip to content

Commit d916e2e

Browse files
authored
Implement new middleware op: suggest-libspecs (#392)
Closes #384
1 parent 1e2987e commit d916e2e

19 files changed

+615
-82
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22

33
## Unreleased
44

5+
## 3.7.0
6+
7+
* Implement new middleware op: `suggest-libspecs`
8+
* Supports a beta clj-refactor.el feature.
9+
510
## 3.6.0
611

712
* [#387](https://github.com/clojure-emacs/refactor-nrepl/issues/387): extend clj-kondo `:unused-namespace` integration. Now namespace local configuration is also taken into account.

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ deploy: check-env .inline-deps
3939
jar: .inline-deps
4040
lein with-profile -user,+$(VERSION),+plugin.mranderson/config jar
4141

42-
# Usage: PROJECT_VERSION=3.2.1 make install
42+
# Usage: PROJECT_VERSION=3.7.0 make install
4343
# PROJECT_VERSION is needed because it's not computed dynamically
4444
install: check-install-env .inline-deps
4545
lein with-profile -user,+$(VERSION),+plugin.mranderson/config install

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ Be aware that this isn't the case if you connect to an already running REPL proc
2626
Add the following, either in your project's `project.clj`, or in the `:user` profile found at `~/.lein/profiles.clj`:
2727

2828
```clojure
29-
:plugins [[refactor-nrepl "3.6.0"]
30-
[cider/cider-nrepl "0.28.3"]]
29+
:plugins [[refactor-nrepl "3.7.0"]
30+
[cider/cider-nrepl "0.31.0"]]
3131
```
3232

3333
### Embedded nREPL
@@ -365,7 +365,7 @@ When you want to release locally to the following:
365365
And here's how to deploy to Clojars:
366366

367367
```bash
368-
git tag -a v3.6.0 -m "3.6.0"
368+
git tag -a v3.7.0 -m "3.7.0"
369369
git push --tags
370370
```
371371

@@ -375,7 +375,7 @@ An extensive changelog is available [here](CHANGELOG.md).
375375

376376
## License
377377

378-
Copyright © 2013-2022 Benedek Fazekas, Magnar Sveen, Alex Baranosky, Lars Andersen, Bozhidar Batsov
378+
Copyright © 2013-2023 Benedek Fazekas, Magnar Sveen, Alex Baranosky, Lars Andersen, Bozhidar Batsov
379379

380380
Distributed under the Eclipse Public License, the same as Clojure.
381381

src/refactor_nrepl/ns/libspecs.clj

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,38 @@
33
[refactor-nrepl.core :as core]
44
[refactor-nrepl.ns.ns-parser :as ns-parser]
55
[refactor-nrepl.ns.suggest-aliases :as suggest-aliases]
6-
[refactor-nrepl.util :as util])
6+
[refactor-nrepl.util :as util]
7+
[refactor-nrepl.util.meta :as meta])
78
(:import
89
(java.io File)))
910

1011
;; The structure here is {path {lang [timestamp value]}}
1112
;; where lang is either :clj or :cljs
1213
(def ^:private cache (atom {}))
1314

15+
(defn vec-distinct-into [x y]
16+
(into []
17+
(comp cat
18+
(distinct))
19+
[x y]))
20+
21+
(defn merge-libspecs-meta [a b]
22+
(let [{:keys [used-from files]} (meta b)]
23+
(cond-> a
24+
(seq used-from) (vary-meta update :used-from vec-distinct-into used-from)
25+
(seq files) (vary-meta update :files vec-distinct-into files))))
26+
1427
(defn- aliases [libspecs]
15-
(->> libspecs
16-
(map (juxt :as :ns))
17-
(remove #(nil? (first %)))
18-
distinct))
28+
(meta/distinct merge-libspecs-meta
29+
(into []
30+
(comp (map (juxt :as :ns))
31+
(filter first))
32+
libspecs)))
1933

2034
(defn- aliases-by-frequencies [libspecs]
21-
(let [grouped (->> libspecs
22-
(mapcat aliases) ; => [[str clojure.string] ...]
35+
(let [grouped (->> (into []
36+
(mapcat aliases) ; => [[str clojure.string] ...]
37+
libspecs)
2338
(sort-by (comp str second))
2439
(group-by first) ; => {str [[str clojure.string] [str clojure.string]] ...}
2540
)]
@@ -37,13 +52,28 @@
3752
(when (= ts (.lastModified f))
3853
v)))
3954

55+
(defn add-used-from-meta [libspecs ^File f]
56+
(let [extension (case (re-find #"\.clj[cs]?$" (-> f .getAbsolutePath))
57+
".clj" [:clj] ;; these are expressed as vectors, so that `#'merge-libspecs-meta` can operate upon them
58+
".cljs" [:cljs]
59+
".cljc" [:cljc]
60+
nil)]
61+
(if-not extension
62+
libspecs
63+
(into []
64+
(map (fn [libspec]
65+
(cond-> libspec
66+
(not (-> libspec :ns string?))
67+
(update :ns vary-meta assoc :used-from extension))))
68+
libspecs))))
69+
4070
(defn- put-cached-ns-info! [^File f lang]
4171
(binding [;; briefly memoize this function to avoid repeating its IO cost while `f` is being cached:
4272
ns-parser/*read-ns-form-with-meta* (memoize core/read-ns-form-with-meta)]
4373
(let [libspecs (ns-parser/get-libspecs-from-file lang f)
4474
[_ namespace-name] (ns-parser/*read-ns-form-with-meta* lang f)
4575
suggested-aliases (suggest-aliases/suggested-aliases namespace-name)
46-
v {:libspecs libspecs
76+
v {:libspecs (add-used-from-meta libspecs f)
4777
:namespace-name namespace-name
4878
:suggested-aliases suggested-aliases
4979
:test-like-ns-name? (suggest-aliases/test-like-ns-name? namespace-name)}]

src/refactor_nrepl/ns/ns_parser.clj

Lines changed: 47 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
(:require
1515
[clojure.java.io :as io]
1616
[clojure.set :as set]
17+
[clojure.string :as string]
1718
[refactor-nrepl.core :as core])
1819
(:import
1920
(java.io File)))
@@ -25,6 +26,39 @@
2526
(into {:ns ns} (->> specs (partition 2) (map vec))))
2627
{:ns (symbol libspec)}))
2728

29+
(defn ns-decl->resource-path [ns-decl extension]
30+
(-> ns-decl
31+
second
32+
str
33+
munge
34+
(string/replace "." "/")
35+
(str extension)))
36+
37+
(defn resource-path->filenames [resource-path]
38+
(->> (-> (Thread/currentThread)
39+
(.getContextClassLoader)
40+
(.getResources resource-path))
41+
(enumeration-seq)
42+
(distinct)
43+
(mapv str)))
44+
45+
(defn ns-sym->ns-filenames [ns-sym]
46+
(let [base (-> ns-sym
47+
str
48+
(string/replace "-" "_")
49+
(string/replace "." "/"))]
50+
(not-empty (into []
51+
(comp (keep (fn [extension]
52+
(-> base (str extension) resource-path->filenames not-empty)))
53+
cat)
54+
[".clj" ".cljs" ".cljc"]))))
55+
56+
(defn add-file-meta [{ns-sym :ns :as m}]
57+
{:pre [ns-sym]}
58+
(let [files (ns-sym->ns-filenames ns-sym)]
59+
(cond-> m
60+
files (update :ns vary-meta assoc :files files))))
61+
2862
(defn- expand-prefix-specs
2963
"Eliminate prefix lists."
3064
[libspecs]
@@ -57,17 +91,20 @@
5791
~@body))
5892

5993
(defn- extract-libspecs [ns-form]
60-
(mapcat identity
94+
(reduce into
95+
[]
6196
[(with-libspecs-from ns-form :require
62-
(->> libspecs
63-
expand-prefix-specs
64-
(map libspec-vector->map)))
97+
(into []
98+
(comp (map libspec-vector->map)
99+
(map add-file-meta))
100+
(expand-prefix-specs libspecs)))
65101

66102
(with-libspecs-from ns-form :use
67-
(->> libspecs
68-
expand-prefix-specs
69-
(map use-to-refer-all)
70-
(map libspec-vector->map)))]))
103+
(into []
104+
(comp (map use-to-refer-all)
105+
(map libspec-vector->map)
106+
(map add-file-meta))
107+
(expand-prefix-specs libspecs)))]))
71108

72109
(defn get-libspecs [ns-form]
73110
(some->> ns-form
@@ -139,12 +176,13 @@
139176
Dialect is either :clj or :cljs, the default is :clj."
140177
([^File f]
141178
(get-libspecs-from-file :clj f))
179+
142180
([dialect ^File f]
143181
(some->> f
144182
.getAbsolutePath
145183
(*read-ns-form-with-meta* dialect)
146184
((juxt get-libspecs get-required-macros))
147-
(mapcat identity))))
185+
(reduce into []))))
148186

149187
(defn aliases
150188
"Return a map of namespace aliases given a seq of libspecs.

0 commit comments

Comments
 (0)