Skip to content

Commit 87de5fb

Browse files
Fix when get-enclosing-sexp sometimes selects a non enclosing sexp
1 parent 6124429 commit 87de5fb

File tree

3 files changed

+30
-18
lines changed

3 files changed

+30
-18
lines changed

src/refactor_nrepl/s_expressions.clj

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -30,24 +30,29 @@
3030
(zip/string zloc)))
3131
(take-while (complement nil?) (iterate zip/left zloc)))))
3232

33+
(defn- node-at-loc?
34+
"True if node encloses point defined by `loc-line` and `loc-column`."
35+
[zloc ^long loc-line ^long loc-column]
36+
(let [[line end-line column end-column] (->> (zip/node zloc)
37+
meta
38+
((juxt :row :end-row :col :end-col))
39+
(map (comp dec long)))]
40+
(or (< line loc-line end-line)
41+
(and (or (= line loc-line)
42+
(= end-line loc-line))
43+
(<= column loc-column end-column)))))
44+
3345
(defn- zip-to
34-
"Move the zipper to the node at line and col"
35-
[zipper ^long line ^long col]
36-
(let [distance (fn [zloc]
37-
(let [node (zip/node zloc)
38-
line-beg (dec (long (:row (meta node))))
39-
line-end (dec (long (:end-row (meta node))))
40-
col-beg (dec (long (:col (meta node))))
41-
col-end (dec (long (:end-col (meta node))))]
42-
(+ (* 1000 (Math/abs (- line line-beg)))
43-
(* 100 (Math/abs (- line line-end)))
44-
(* 10 (Math/abs (- col col-beg)))
45-
(Math/abs (- col col-end)))))]
46-
(reduce (fn [best zloc] (if (< (long (distance zloc)) (long (distance best)))
47-
zloc
48-
best))
49-
zipper
50-
(all-zlocs zipper))))
46+
"Move the zipper to the node at `loc-line` and `loc-col`.
47+
48+
Implementation uses `all-zlocs` and exploits the fact that it generates
49+
a seq of nodes in depth-first order."
50+
[zipper ^long loc-line ^long loc-column]
51+
(reduce
52+
(fn [node-at-loc zloc]
53+
(if (node-at-loc? zloc loc-line loc-column) zloc node-at-loc))
54+
zipper
55+
(all-zlocs zipper)))
5156

5257
(defn get-enclosing-sexp
5358
"Extracts the sexp enclosing point at LINE and COLUMN in FILE-CONTENT,

test/refactor_nrepl/s_expressions_test.clj

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@
1111
;; some other stuff
1212
(foobar baz)")
1313
(def binding-location [3 8])
14-
(def funcall-location [6 8])
1514
(def set-location [7 35])
1615
(def map-location [7 28])
1716
(def weird-location [1 5])
1817
(def println-location [5 8])
18+
(def when-not-location [10 9])
1919

2020
(t/deftest get-enclosing-sexp-test
2121
(t/is (= "[some :bindings
@@ -28,5 +28,8 @@
2828
(t/is (= "#{more}" (apply sut/get-enclosing-sexp file-content set-location)))
2929
(t/is (= "{:qux [#{more}]}" (apply sut/get-enclosing-sexp file-content map-location)))
3030
(t/is (= nil (apply sut/get-enclosing-sexp weird-file-content weird-location)))
31+
(t/is (= "(when-not (= true true)
32+
(= 5 (* 2 2)))"
33+
(apply sut/get-enclosing-sexp file-content when-not-location)))
3134
(t/is (= nil (sut/get-first-sexp weird-file-content)))
3235
(t/is (= "#{foo bar baz}" (sut/get-first-sexp file-content-with-set))))

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,7 @@
66
(println #{some}
77
;; unhelpful comment )
88
(prn {"foo" {:qux [#{more}]}}))))
9+
10+
(defn bar []
11+
(when-not (= true true)
12+
(= 5 (* 2 2))))

0 commit comments

Comments
 (0)