lsp

JR 2026-01-12T15:23:01.405319Z

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?

JR 2026-01-12T16:54:55.052879Z

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)

ericdallo 2026-01-12T20:47:42.597769Z

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

ericdallo 2026-01-12T20:48:01.643729Z

you will see that (z/string (h/load-code-and-zloc "#(f |x)" "file:///a.clj")) => x

ericdallo 2026-01-12T20:48:40.563699Z

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

ericdallo 2026-01-12T20:49:21.370479Z

but yeah it's tricky, especially on closing things like your example with a space, we get the closer thing IIRC

JR 2026-01-12T20:51:20.778309Z

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.

ericdallo 2026-01-12T20:52:00.009649Z

yeah we created that dsl 4 years ago, but it's something like that 😂

JR 2026-01-12T20:52:06.429989Z

Maybe I'll walk right looking at zlocs until I find something that's beyond the cursor coordinates

JR 2026-01-12T20:52:42.044899Z

Then the zloc I'm looking for will be the last thing

JR 2026-01-12T21:07:18.168859Z

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 correct

JR 2026-01-12T21:11:41.841099Z

In any case, I can hunt around for it, but it's probably not something obvious 🙂

ericdallo 2026-01-12T21:17:05.543129Z

hum yes, probably some behavior from rewrite-clj we were not expecting

👍 1
ericdallo 2026-01-14T12:23:32.763119Z

good catch! thank you!

JR 2026-01-13T22:39:45.831639Z

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"

JR 2026-01-13T22:53:17.506079Z

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

JR 2026-01-13T23:03:54.125079Z

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