Skip to content

Commit fb975c6

Browse files
authored
Honor clj-kondo :unused-namespace config, if present (#361)
1 parent 7930b3b commit fb975c6

File tree

7 files changed

+106
-14
lines changed

7 files changed

+106
-14
lines changed

.clj-kondo/config.edn

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,7 @@
4040
clojure.tools.namespace.track tracker}}
4141
:unresolved-symbol {:exclude [(refactor-nrepl.ns.ns-parser/with-libspecs-from [libspecs])
4242
(refactor-nrepl.middleware/set-descriptor! [set-descriptor!])]}
43-
:unresolved-namespace {:exclude [clojure.main]}}}
43+
:unresolved-namespace {:exclude [clojure.main]}
44+
;; for integration tests:
45+
:unused-namespace {:exclude [sample.unused.namespace
46+
"more.unused.namespaces*"]}}}

CHANGELOG.md

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

33
## Unreleased
44

5+
* [#361](https://github.com/clojure-emacs/refactor-nrepl/pull/361) Honor clj-kondo `:unused-namespace` config, if present
6+
* This piece of config can inform/complement refactor-nrepl's own config.
7+
58
## 3.2.2 (2022-01-29)
69

710
* Fix a minor artifact in the previous release (the version would be reported as 0.0.0).

README.md

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

2727
```clojure
28-
:plugins [[refactor-nrepl "3.2.1"]
28+
:plugins [[refactor-nrepl "3.3.0"]
2929
[cider/cider-nrepl "0.25.9"]]
3030
```
3131

@@ -37,7 +37,7 @@ Add the following in `~/.boot/profile.boot`:
3737
(require 'boot.repl)
3838

3939
(swap! boot.repl/*default-dependencies* conj
40-
'[refactor-nrepl "3.2.1"]
40+
'[refactor-nrepl "3.3.0"]
4141
'[cider/cider-nrepl "0.25.9"])
4242

4343
(swap! boot.repl/*default-middleware* conj
@@ -121,6 +121,7 @@ Configuration settings are passed along with each msg, currently the recognized
121121
;; even if they're otherwise unused.
122122
;; This seq of strings will be used as regexp patterns to match
123123
;; against the libspec name.
124+
;; This value is automatically augmented with configured clj-kondo's :unused-namespace config.
124125
:libspec-whitelist ["^cljsjs"]
125126

126127
;; Regexes matching paths that are to be ignored
@@ -370,12 +371,12 @@ If you want to use `mranderson` while developing locally with the REPL, the sour
370371

371372
When you want to release locally to the following:
372373

373-
PROJECT_VERSION=3.2.1 make install
374+
PROJECT_VERSION=3.3.0 make install
374375

375376
And here's how to deploy to Clojars:
376377

377378
```bash
378-
git tag -a v3.2.1 -m "3.2.1"
379+
git tag -a v3.3.0 -m "3.3.0"
379380
git push --tags
380381
```
381382

src/refactor_nrepl/middleware.clj

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
[clojure.walk :as walk]
66
[refactor-nrepl.config :as config]
77
[refactor-nrepl.core :as core]
8+
[refactor-nrepl.ns.libspec-allowlist :as libspec-allowlist]
89
[refactor-nrepl.ns.libspecs :refer [namespace-aliases]]
910
[refactor-nrepl.stubs-for-interface :refer [stubs-for-interface]]))
1011

@@ -59,10 +60,11 @@
5960
~transport (response-for ~msg (err-info e# :refactor-nrepl-error))))))
6061

6162
(defmacro ^:private reply [transport msg & kvs]
62-
`(with-errors-being-passed-on ~transport ~msg
63-
(config/with-config ~msg
64-
(transport/send ~transport
65-
(response-for ~msg ~(apply hash-map kvs))))))
63+
`(libspec-allowlist/with-memoized-libspec-allowlist
64+
(with-errors-being-passed-on ~transport ~msg
65+
(config/with-config ~msg
66+
(transport/send ~transport
67+
(response-for ~msg ~(apply hash-map kvs)))))))
6668

6769
(defn- bencode-friendly-data [data]
6870
;; Bencode only supports byte strings, integers, lists and maps.
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
(ns refactor-nrepl.ns.libspec-allowlist
2+
(:require
3+
[clojure.java.io :as io]
4+
[refactor-nrepl.config :as config])
5+
(:import
6+
(java.util.regex Pattern)))
7+
8+
(defn- libspec-allowlist* []
9+
(let [kondo-file (io/file ".clj-kondo" "config.edn")
10+
exclude (when (.exists kondo-file)
11+
(try
12+
(-> kondo-file slurp read-string :linters :unused-namespace :exclude)
13+
(catch Exception e
14+
(when (System/getenv "CI")
15+
(throw e)))))]
16+
(->> exclude
17+
(mapv (fn [entry]
18+
(if (symbol? entry)
19+
(str "^" (Pattern/quote (str entry)) "$")
20+
entry)))
21+
(into (:libspec-whitelist config/*config*)))))
22+
23+
(def ^:private ^:dynamic *libspec-allowlist* nil)
24+
25+
(defn with-memoized-libspec-allowlist* [f]
26+
(binding [*libspec-allowlist* (memoize libspec-allowlist*)]
27+
(f)))
28+
29+
(defn libspec-allowlist
30+
"Obtains a libspec allowlist, which is the result of merging clj-refactor's own `:libspec-whitelist`
31+
with clj-kondo's `:unused-namespace` config.
32+
33+
Uses a memoized version if available."
34+
[]
35+
(or *libspec-allowlist*
36+
(libspec-allowlist*)))
37+
38+
(defmacro with-memoized-libspec-allowlist
39+
"Memoizes the libspec-allowlist internals while `body` is executing.
40+
41+
_Temporary_ memoization is important because:
42+
43+
* one does want to reload clj-kondo config if the user changes it, without needing a JVM restart;
44+
* one doesn't want that to imply a performance hit in terms of repeatedly reading clj-kondo config files."
45+
{:style/indent 0}
46+
[& body]
47+
`(with-memoized-libspec-allowlist*
48+
(fn []
49+
~@body)))

src/refactor_nrepl/ns/prune_dependencies.clj

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
(ns refactor-nrepl.ns.prune-dependencies
22
(:require
33
[cider.nrepl.middleware.info :as info]
4-
[refactor-nrepl.config :as config]
54
[refactor-nrepl.core :as core]
65
[refactor-nrepl.find.symbols-in-file :as symbols-in-file]
6+
[refactor-nrepl.ns.libspec-allowlist :as libspec-allowlist]
77
[refactor-nrepl.util :as util]))
88

99
(defn- lookup-symbol-ns
@@ -108,11 +108,13 @@
108108
;; Some namespaces, e.g. those containing only protocol extensions,
109109
;; are side-effecting at load but might look unused and otherwise be
110110
;; pruned.
111-
(defn- libspec-should-never-be-pruned? [libspec]
111+
(defn libspec-should-never-be-pruned?
112+
"Should `libspec` never be pruned away by the `clean-ns` op?"
113+
[libspec]
112114
(let [ns-name (str (:ns libspec))]
113-
(some (fn [^String pattern]
114-
(re-find (re-pattern pattern) ns-name))
115-
(:libspec-whitelist config/*config*))))
115+
(boolean (some (fn [^String pattern]
116+
(-> pattern re-pattern (re-find ns-name)))
117+
(libspec-allowlist/libspec-allowlist)))))
116118

117119
(defn- prune-libspec [symbols-in-file current-ns libspec]
118120
(if (libspec-should-never-be-pruned? libspec)
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
(ns refactor-nrepl.ns.libspec-allowlist-test
2+
(:require
3+
[clojure.test :refer [are deftest is testing]]
4+
[refactor-nrepl.ns.libspec-allowlist :as sut]
5+
[refactor-nrepl.ns.prune-dependencies :as prune-dependencies]))
6+
7+
(deftest libspec-allowlist
8+
(testing "Takes into account refactor-nrepls own config, and .clj-kondo/config files alike,
9+
merging their results"
10+
(is (= [;; From refactor-nrepl's default config:
11+
"^cljsjs"
12+
;; from our .clj-kondo file - symbols become quoted patterns:
13+
"^\\Qsample.unused.namespace\\E$"
14+
;; from our .clj-kondo file - strings have 'regex' semantics so are kept as-is:
15+
"more.unused.namespaces*"]
16+
17+
(sut/libspec-allowlist)))
18+
19+
(is (every? string? (sut/libspec-allowlist))
20+
"Items coming from different sources all have the same class,
21+
ensuring they will be treated homogeneously by refactor-nrepl")
22+
23+
(testing "`libspec-should-never-be-pruned?` is integrated with clj-kondo logic,
24+
effecively parsing its config into well-formed regexes"
25+
(are [input expected] (= expected
26+
(prune-dependencies/libspec-should-never-be-pruned? {:ns input}))
27+
'sample.unused.namespace true
28+
'Asample.unused.namespace false
29+
'sample.unused.namespaceB false
30+
'more.unused.namespaces true
31+
'more.unused.namespacessss true
32+
'more.unused.namespac false))))

0 commit comments

Comments
 (0)