Skip to content

Commit 7ccea8c

Browse files
committed
[Fix #289] Namespaced keywords vs find (local) symbol
The edge-case handling for local symbols in opt-maps wasn't using a reader that was configured correctly and choked on a namespaced keyword.
1 parent 317ba2f commit 7ccea8c

File tree

6 files changed

+50
-18
lines changed

6 files changed

+50
-18
lines changed

CHANGELOG.md

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

33
## Unreleased
44

5+
### Bugs fixed
6+
* [#289](https://github.com/clojure-emacs/refactor-nrepl/issues/289): Fix an edge-case with involving keywords that caused find-symbol to crash.
57
* [#305](https://github.com/clojure-emacs/refactor-nrepl/issues/305): Don't put `:as` or `:refer` on their own lines in the ns form, when the libspec is so long it causes the line to wrap.
68
* [clojure-emacs/clj-refactor.el#459](https://github.com/clojure-emacs/clj-refactor.el/issues/459): `clean-ns` should conform to the style guide: `(:require` in the ns form should be followed by a newline.
79
* You can opt out via the new `:insert-newline-after-require` configuration option.

project.clj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
:filespecs [{:type :bytes :path "refactor-nrepl/refactor-nrepl/project.clj" :bytes ~(slurp "project.clj")}]
2828
:profiles {;; Clojure versions matrix
2929
:provided {:dependencies [[cider/cider-nrepl "0.25.9"]
30-
[org.clojure/clojure "1.8.0"]]}
30+
[org.clojure/clojure "1.9.0"]]}
3131
:1.8 {:dependencies [[org.clojure/clojure "1.8.0"]
3232
[org.clojure/clojurescript "1.8.51"]
3333
[javax.xml.bind/jaxb-api "2.3.1"]]}

src/refactor_nrepl/core.clj

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,3 +380,12 @@
380380
[symbol-or-keyword]
381381
(when (prefix symbol-or-keyword)
382382
symbol-or-keyword))
383+
384+
(defmacro with-clojure-version->=
385+
"Guard the evaluation of `body` with a test on the current clojure version."
386+
{:style/indent 1}
387+
[{:keys [major minor] :as _clojure-version} & body]
388+
(when (or (> (:major *clojure-version*) major)
389+
(and (= (:major *clojure-version*) major)
390+
(>= (:minor *clojure-version*) minor)))
391+
`(do ~@body)))

src/refactor_nrepl/find/find_symbol.clj

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
[s-expressions :as sexp]]
1111
[refactor-nrepl.find.find-macros :refer [find-macro]]
1212
[refactor-nrepl.find.util :as find-util]
13-
[refactor-nrepl.ns.libspecs :as libspecs])
13+
[refactor-nrepl.ns.libspecs :as libspecs]
14+
[clojure.tools.reader :as reader])
1415
(:import (java.io File)))
1516

1617
(def ^:private symbol-regex #"[\w\.:\*\+\-_!\?]+")
@@ -140,12 +141,14 @@
140141

141142
(defn- get&read-enclosing-sexps
142143
[file-content {:keys [^long line-beg ^long col-beg]}]
143-
(binding [*read-eval* false]
144+
(binding [*read-eval* false
145+
clojure.tools.reader/*alias-map*
146+
(ns-aliases (core/ns-from-string file-content))]
144147
(let [line (dec line-beg)
145148
encl-sexp-level1 (or (sexp/get-enclosing-sexp file-content line col-beg) "")
146149
encl-sexp-level2 (or (sexp/get-enclosing-sexp file-content line col-beg 2) "")]
147-
[encl-sexp-level1 (read-string encl-sexp-level1)
148-
encl-sexp-level2 (read-string encl-sexp-level2)])))
150+
[encl-sexp-level1 (reader/read-string encl-sexp-level1)
151+
encl-sexp-level2 (reader/read-string encl-sexp-level2)])))
149152

150153
(defn- optmap-with-default?
151154
[var-name _file-content [_ [_ level1-form _ level2-form]]]

test/refactor_nrepl/integration_tests.clj

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
[clojure.test :refer :all]
44
[nrepl.server :as nrepl]
55
[refactor-nrepl middleware
6+
[analyzer :as analyzer]
67
[client :refer :all]
78
[core :as core]]
89
[clojure.string :as str])
@@ -58,11 +59,11 @@
5859
(defn ns-ast-throw-error-for-five [^String content]
5960
(if (.contains content "com.example.five")
6061
(throw (IllegalThreadStateException. "FAILED!"))
61-
(#'refactor-nrepl.analyzer/cachable-ast content)))
62+
(#'analyzer/cachable-ast content)))
6263

6364
(deftest test-find-two-foo-errors-ignored
6465
(with-testproject-on-classpath
65-
(with-redefs [refactor-nrepl.analyzer/ns-ast ns-ast-throw-error-for-five]
66+
(with-redefs [analyzer/ns-ast ns-ast-throw-error-for-five]
6667
(let [transport (connect :port 7777)
6768
response (find-usages :transport transport :ns 'com.example.two
6869
:file (str test-project-dir "/src/com/example/one.clj")
@@ -186,46 +187,55 @@
186187
(with-testproject-on-classpath
187188
(let [five-file (str test-project-dir "/src/com/example/five.clj")
188189
transport (connect :port 7777)
189-
response (find-usages :transport transport :name "foo" :file five-file :line 46 :column 10)
190+
response (find-usages :transport transport :name "foo" :file five-file :line 47 :column 10)
190191
result (remove keyword? response)]
191192
(is (= 3 (count result)) (format "expected 3 results but got %d" (count result))))))
192193

193194
(deftest find-local-in-optmap-default-linebreaks
194195
(with-testproject-on-classpath
195196
(let [five-file (str test-project-dir "/src/com/example/five.clj")
196197
transport (connect :port 7777)
197-
response (find-usages :transport transport :name "foo" :file five-file :line 49 :column 12)
198+
response (find-usages :transport transport :name "foo" :file five-file :line 50 :column 12)
198199
result (remove keyword? response)]
199200
(is (= 3 (count result)) (format "expected 3 results but got %d" (count result))))))
200201

201202
(deftest find-local-in-optmap-default-in-let
202203
(with-testproject-on-classpath
203204
(let [five-file (str test-project-dir "/src/com/example/five.clj")
204205
transport (connect :port 7777)
205-
response (find-usages :transport transport :name "foo" :file five-file :line 59 :column 12)
206+
response (find-usages :transport transport :name "foo" :file five-file :line 60 :column 12)
206207
result (remove keyword? response)]
207208
(is (= 3 (count result)) (format "expected 3 results but got %d" (count result))))))
208209

210+
(core/with-clojure-version->= {:major 1 :minor 9}
211+
(deftest find-local-in-namespaced-destructuring
212+
(with-testproject-on-classpath
213+
(let [five-file (str test-project-dir "/src/com/example/five.clj")
214+
transport (connect :port 7777)
215+
response (find-usages :transport transport :name "foo" :file five-file :line 67 :column 16)
216+
result (remove keyword? response)]
217+
(is (= 2 (count result)) (format "expected 3 results but got %d" (count result)))))))
218+
209219
(deftest test-find-used-locals
210220
(with-testproject-on-classpath
211221
(let [five-file (str test-project-dir "/src/com/example/five.clj")
212222
transport (connect :port 7777)]
213-
(is (= (find-unbound :transport transport :file five-file :line 12 :column 6)
223+
(is (= (find-unbound :transport transport :file five-file :line 13 :column 6)
214224
'(s)))
215-
(is (= (find-unbound :transport transport :file five-file :line 13 :column 13)
225+
(is (= (find-unbound :transport transport :file five-file :line 14 :column 13)
216226
'(s sep)))
217227

218-
(is (= (find-unbound :transport transport :file five-file :line 20 :column 16)
228+
(is (= (find-unbound :transport transport :file five-file :line 21 :column 16)
219229
'(p)))
220-
(is (= (find-unbound :transport transport :file five-file :line 27 :column 8)
230+
(is (= (find-unbound :transport transport :file five-file :line 28 :column 8)
221231
'(sep strings)))
222232

223-
(is (= (find-unbound :transport transport :file five-file :line 34 :column 8)
233+
(is (= (find-unbound :transport transport :file five-file :line 35 :column 8)
224234
'(name)))
225235

226-
(is (= (find-unbound :transport transport :file five-file :line 37 :column 5)
236+
(is (= (find-unbound :transport transport :file five-file :line 38 :column 5)
227237
'(n)))
228-
(is (= (find-unbound :transport transport :file five-file :line 41 :column 4)
238+
(is (= (find-unbound :transport transport :file five-file :line 42 :column 4)
229239
'(x y z a b c))))))
230240

231241
(deftest find-unbound-fails-on-cljs

test/resources/testproject/src/com/example/five.clj

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
(ns com.example.five
2-
(:require [clojure.string :refer [join split blank? trim] :as str]))
2+
(:require [clojure.string :refer [join split blank? trim] :as str]
3+
[refactor-nrepl.core :as core]))
34

45
;; remove parameters to run the tests
56
(defn fn-with-unbounds [s sep]
@@ -58,6 +59,13 @@
5859
[:bar :foo]
5960
(count foo)))
6061

62+
(core/with-clojure-version->= {:major 1 :minor 9}
63+
(defn fn-with-let-with-namespaced-keyword-destructuring []
64+
;; https://github.com/clojure-emacs/refactor-nrepl/issues/289
65+
(let [{::str/keys [foo bar]} (hash-map)]
66+
[:bar :foo]
67+
(count foo))))
68+
6169
;; This was causing both find-local-symbol and find-macros to blow up, for
6270
;; different reasons
6371
::str/bar

0 commit comments

Comments
 (0)