I thought I found a bug with anonymous reader functions in extract-function, but it seems like it might be in the clojure-lsp parsing. This returns x as I expected
(z/string (h/load-code-and-zloc "(f x|)" "file:///a.clj")) => x
but with the reader #, it returns the whole thing
(z/string (h/load-code-and-zloc "#(f x|)" "file:///a.clj")) => #(f x)
I tried looking into it but so far I haven't found where this is parsed, but it seems like it might be a bug?
Adding a space makes it seem like an off by one issue:
(z/string (h/load-code-and-zloc "#(f x| )" "file:///a.clj")) => " "
(still reports "x" when the # is removed)
in terms of this custom dsl in clojure-lsp, when you have x|y you expect that it returns the position of y not x , so the | usually goes like a cursor, in front of the thing you wanna check
you will see that (z/string (h/load-code-and-zloc "#(f |x)" "file:///a.clj")) => x
but I agree it's a weird behavior but TBH not sure it's common to have cursor in the close paren of a sexpr, but if that's easy to fix in that dsl, I'm ok with that
but yeah it's tricky, especially on closing things like your example with a space, we get the closer thing IIRC
Ah, so the | is the zloc to the right, unless there's nothing to the right, in which case it goes to the left? And something funky happens when enclosed in #()? If so, you're right, I suppose it's better not to rely on that behavior.
yeah we created that dsl 4 years ago, but it's something like that 😂
Maybe I'll walk right looking at zlocs until I find something that's beyond the cursor coordinates
Then the zloc I'm looking for will be the last thing
I don't think it's the code in positions-from-text in internal.clj that's the issue - that code seemed correct. I can reproduce it with
(h/load-code-and-locs (str "#(f x|)") "file:///a.clj") => [1 6]
(z/string (clojure-lsp.parser/to-pos (clojure-lsp.parser/zloc-of-file (h/db) "file:///a.clj") 1 6)) => "#(f x)"
It looks like [1 6] part (finding the |) is correctIn any case, I can hunt around for it, but it's probably not something obvious 🙂
hum yes, probably some behavior from rewrite-clj we were not expecting
good catch! thank you!
I think I found this one. The edit.clj:zloc-in-range function is missing :fn. The change is straightforward (below). Regressions run OK and the problem in extract-function that I was seeing is gone. Should I open an issue?
diff --git a/lib/src/clojure_lsp/refactor/edit.clj b/lib/src/clojure_lsp/refactor/edit.clj
index a70b5137..f0316122 100644
--- a/lib/src/clojure_lsp/refactor/edit.clj
+++ b/lib/src/clojure_lsp/refactor/edit.clj
@@ -39,7 +39,7 @@
(and (= (-> loc z/node meta :end-col)
(:end-col pos))
(z/rightmost? loc)
- (contains? #{:list :vector :map :set} (z/tag (z/up loc)))
+ (contains? #{:list :vector :map :set :fn} (z/tag (z/up loc)))
(some-> loc z/up z/node meta (in-range? pos)))))
(defn find-by-heritability
diff --git a/lib/test/clojure_lsp/refactor/edit_test.clj b/lib/test/clojure_lsp/refactor/edit_test.clj
index 7343a31f..a4961024 100644
--- a/lib/test/clojure_lsp/refactor/edit_test.clj
+++ b/lib/test/clojure_lsp/refactor/edit_test.clj
@@ -14,6 +14,7 @@
(is (= "1" (-> "1 #?(+ 1 2) 3" z/of-string (edit/find-at-pos 1 1) z/string)))
(is (= "2" (-> "1 #?(+ 1 2) 3" z/of-string (edit/find-at-pos 1 10) z/string)))
(is (= "3" (-> "1 #?(+ 1 2) 3" z/of-string (edit/find-at-pos 1 13) z/string)))
+ (is (= "x" (-> "#(+ x)" z/of-string (edit/find-at-pos 1 6) z/string)))
(is (= "some" (-> "some (def other {:foo/bar 1})" z/of-string (edit/find-at-pos 1 1) z/string)))
(is (= "some" (-> "some (def other #:foo{:bar 1})" z/of-string (edit/find-at-pos 1 1) z/string)))
(testing "finds in any branch"
I figure it's probably a bug, so I went ahead and entered https://github.com/clojure-lsp/clojure-lsp/issues/2208 I can submit a PR for it too
Hopefully I'm not too far out over my skis, but I went ahead an did a PR too: https://github.com/clojure-lsp/clojure-lsp/pull/2209