lsp

borkdude 2025-12-09T11:26:26.288029Z

would it be an idea to also list the amount of usages of locals?

(let [x 1] ;; 1 references
  x)
This way it would be easier to decide if you could inline a local

ericdallo 2025-12-09T11:41:59.969079Z

I think it could add too much noise, but possible

borkdude 2025-12-09T11:46:24.191999Z

The case of 1 usage would be interesting to me since in that case you could directly inline the binding value

ericdallo 2025-12-09T11:47:12.470119Z

Maybe you want a diagnostic for when only a single usage of a local?

ericdallo 2025-12-09T11:47:17.511999Z

A single diagnostic maybe

borkdude 2025-12-09T11:47:52.615529Z

I could do this in clj-kondo but it's not always something you want to fix

borkdude 2025-12-09T11:48:10.988509Z

So this is why I was thinking about LSP references

ericdallo 2025-12-09T11:48:44.067999Z

Yeah I get it

ericdallo 2025-12-09T11:48:59.620009Z

As a optional feature sounds ok to me

ericdallo 2025-12-09T11:49:16.953779Z

TBH don't think too many people would want this running by default

borkdude 2025-12-09T11:54:13.415719Z

I think only showing it with 1 reference would be a better default

1
borkdude 2025-12-09T11:54:40.626569Z

Also not a diagnostic, just a side info like references

ericdallo 2025-12-09T11:55:06.250739Z

I don't think so, lens are good for consistent UI, this is sounding to me more like a info diagnostic, something you wanna show to user but it's not a warning or error

ericdallo 2025-12-09T11:55:24.348879Z

that's why the diagnostic is called info

borkdude 2025-12-09T11:59:09.072089Z

I think diagnostic is too intrusive for this, even info

ericdallo 2025-12-09T11:59:41.272079Z

Even only for 1 usage and optional?

borkdude 2025-12-09T12:06:42.233959Z

I can first experiment with this in clj-kondo

ericdallo 2025-12-09T12:06:59.244669Z

I think it's a good idea to try

2025-12-09T12:09:42.193449Z

what do other language lsps do? like rust or java. do they say how many references a local has?

ericdallo 2025-12-09T12:20:06.392109Z

They don't

👍 1
ericdallo 2025-12-09T12:20:44.593949Z

What rust does is show the type of the var which is awesome, I already thought how to apply that for clojure but not good or easy

ericdallo 2025-12-09T12:20:59.319069Z

Because there the type is optional and has a way to type of you want

ericdallo 2025-12-09T12:21:12.799379Z

Clojure doesn't has this syntax so it would look weird

Stig Brautaset 2025-12-09T12:49:40.776189Z

Even if it showed number/string/list/vector/map that would be a good start. I've made mistakes a couple times because of the difference in behaviour for conj and list/vector.

ericdallo 2025-12-09T12:50:50.498259Z

yeah me too, the problem I saw with that approach was that it was incredibly noisy, but also type inference in a static analysis is not easy to do

1
borkdude 2025-12-09T12:51:31.011189Z

> type inference in a static analysis is not easy to do this part is done by clj-kondo, clojure-lsp doesn't do any type analysis AFAIK

Stig Brautaset 2025-12-09T12:51:36.077139Z

I'm a +1 to "let me know if this let-bind has only one use" btw.

ericdallo 2025-12-09T12:51:55.174219Z

@borkdude I know, it was for testing purposes

ericdallo 2025-12-09T12:52:10.382139Z

need to experiment again with that

borkdude 2025-12-09T12:52:19.492829Z

testing purposes?

ericdallo 2025-12-09T12:52:29.821549Z

yes, I was testing if that feature would look like nice

borkdude 2025-12-09T12:52:35.428259Z

ah ok

borkdude 2025-12-09T12:52:59.080159Z

> I'm a +1 to "let me know if this let-bind has only one use" btw. Well I guess clj-kondo could make an optional linter for this

👍 2
borkdude 2025-12-09T12:53:04.264789Z

that you can set to :info

👍 1
borkdude 2025-12-09T13:36:33.960009Z

borkdude 2025-12-09T13:37:26.432359Z

Also a lot of squiggles in destructuring. I guess :let and destructuring are cases where you can't avoid introducing bindings

ericdallo 2025-12-09T13:38:06.785859Z

yeah, beisdes that looks good

borkdude 2025-12-09T13:38:35.137289Z

also in cases like:

(let [foo ...]
  (map #(foo %) ...))
it's only reported once. this is also not good since moving the expression inline would be a performance regression

borkdude 2025-12-09T13:38:40.775369Z

I don't think that looks good at all

borkdude 2025-12-09T13:39:11.999999Z

ericdallo 2025-12-09T13:39:25.567969Z

I think those are just false-positives to fix, besides that it's exactly what the feature is suppose to do, highlightth the local being used once

ericdallo 2025-12-09T13:39:59.453489Z

for example squigls in function args are another false positive

borkdude 2025-12-09T13:40:11.280479Z

often introducing a local is also informative, giving something a name to clear up intent

borkdude 2025-12-09T13:40:28.406189Z

yes, those need to be eliminated

borkdude 2025-12-09T13:40:46.974129Z

but this is something kondo can't really do reliably:

(let [foo ...]
  (map #(foo %) ...))

😔 1
borkdude 2025-12-09T13:41:03.260109Z

so I'm already convinced this isn't a good idea

1
borkdude 2025-12-09T13:41:43.026359Z

I've pushed this to let-binding-single-usage if anyone wants to play around with it.

ericdallo 2025-12-09T13:41:50.994549Z

yeah, also I do think using 1 reference or 1 reference only in place of squigles would make way more noiser than currently

borkdude 2025-12-09T13:42:18.322419Z

One case that got me thinking was:

(let [x 1 y x] y)
can be simplified to:
(let [x 1] x)

👍 1
ericdallo 2025-12-09T13:42:26.891239Z

code lens are cool, but we need to be careful to not add too much noise, var-definitions are good because you have few in a file

borkdude 2025-12-09T13:42:34.488749Z

agreed

dominicm 2025-12-10T08:45:33.941169Z

Is this something that plugins for your editor could do? Seems like all the information needed is there?

borkdude 2025-12-10T08:46:55.660419Z

yes, clojure-lsp is such a plugin

borkdude 2025-12-10T08:47:12.737929Z

but I already got it working and it's way too noisy, so ..

dominicm 2025-12-10T08:47:43.353099Z

I don't really want clojure lsp dictating ui components in my editor. But an editor specific plugin could do all sorts with the information queried from lsp.

JR 2025-12-09T19:40:31.875179Z

I miss the if -> cond refactoring (and reverse) from my Java days with Intellij. I did a prototype for clojure-lsp to do this. Is something like this worth adding, did I miss something that does it already, or should I open an issue and contribute? (video in thread)

👍 1
JR 2025-12-16T20:18:28.364629Z

@ericdallo I have a branch with these ready for a PR. What's better for the PR? To be • based on my previous PR with extract-function, or • based on master so it can be applied independently?

ericdallo 2025-12-16T20:31:20.162479Z

cool! for sure separated!

👍 1
ericdallo 2025-12-29T17:21:25.400899Z

Merged! great PR, thank you!

👍 1
JR 2025-12-17T13:38:07.804339Z

Oops, I went to push and noticed: - [ ] I updated documentation if applicable (`docs` folder) And that got me to thinking about the naming. They're named: • Change nested if to cond, and • Change cond to nested if right now. Is that good enough? Here's the videos of them working in emacs

ericdallo 2025-12-17T13:49:25.975819Z

they look great! the naming looks good too, I will happily review it soon

👍 1
JR 2025-12-09T19:40:58.345909Z

Prototype

🙏 1
ericdallo 2025-12-09T19:41:55.085999Z

that looks completely valid, I would use that code action :)

ericdallo 2025-12-09T19:42:14.499349Z

would be nice to provide the other way around as well, same we did for thread and unwind thread

ericdallo 2025-12-09T19:42:25.858199Z

and couple of more actions like that

JR 2025-12-09T19:43:45.436409Z

Yup, working on the reverse now. It might also be nice to put in some enhancements so an if-not ... gets turned into a (not (... but I figure one step at a time.

ericdallo 2025-12-09T19:44:24.025369Z

makes sense

JR 2025-12-09T19:51:28.392449Z

Filed https://github.com/clojure-lsp/clojure-lsp/issues/2171. If it's OK, I'll volunteer for it.

👍 1