Add configurability for which subsystem (nrepl, clojure-lsp, other) that provides features, such as code navigation, etc
Currently, a lot of features that are provided by LSP get overwritten by nrepl when you are connected to it. There have been a few requests for this to be optional in Slack.
I just ran headfirst into this when working in LSP itself, since I couldn't test some of the features when connected to it by repl π
Not sure if it's worth the effort/complexity, but we could provide an options map that lets users decide which provider is used. Something like:
{
:provide-hover :nrepl
:provide-completion :lsp
:provide-snippets :merge
}
Even if we don't want to make it optional, we should probably build a merge for some of the providers.
What do you think?
I like the suggestion to make this behavior more of a configuration. Maybe it should be vectors of the preference order?
{
:provide-hover [:repl :lsp]
:provide-destination [:both]
:provide-completion [:lsp :repl]
:provide-snippets [:merge]
}
Both lsp and the repl might be unavailable, I am thinking...
(That :both for destination is not thought trough at all. It is more that sometimes lsp holds the truth here and something the repl, and it varies from time to time. I somehow doubt though that providing two destinations will actually help. π)
Depends a little bit on which provider. Completions might be OK to merge, but we'd have to play around with it
Currently, it seems that the only two places that should get an option are declarations and completions. Hover has special handling from calva to make the clojuredoc better, so thereβs not really a point in switching to lsp (unless we base that code on lsps clojuredoc results) and everything else goes through lsp anyway. But I realized that by extending custom snippets and adding custom hovers, I kind of started on the way of adding custom LSP bit by bit. The next bit would probably be codeActions or even codeLenses.
Now I'm wondering if we should just fully embrace the madness and expose all (reasonable) LSP middleware calls to custom snippets, so that dependency-based tools can just provide extra stuff. It's probably a bit much but it would provide a lot of possibilities for creative tooling shananigans.
The smarter, conservative approach is probably to start exposing them bit by bit, but keep in mind that we are actually creating a parallel LSP that is easier to maintain if we provide a similar API. (Even though the idea of having the full-blown, queriable LSP in process with my code makes me strangely excited π€ͺ )
WDYT @PEZ @bpringe @ericdallo?
I think it sounds very cool. It will need some nice way for the user to opt in on things. I can see Calva turning into a christmas tree with code lenses, gutter decorations and what-not. And we probably should build it a separate system for it. (Not sure if this is what you meant, @Cyrik , but anyway, if we can avoid creating dependencies, we should, I think.)
Looks good, a flag/flags that allow use LSP options instead of NREPL is something I'm missing for some time
I don't think we would make this configuration user facing though. Rather use it to give Calva a nice default behavior around this.
I don't think we would make this configuration user facing though. Rather use it to give Calva a nice default behavior around this.
What do you mean? I wanted to add it as an option. Not sure how this would help with defaults?
I mean that I want to avoid adding settings for the users if it can be avoided. But I think that the configuration approach to how clojure-lsp and nrepl info should be reconciled is great. We can always make some of it user configurable later.
So it turns out that the lsp-client middleware doesn't seem to give us the functionality we need. If I ask LSP for completions or definitions the middleware call is canceled and I have no way to look at the results. So merging stuff coming out of nrepl / snippets and LSP doesn't work through middleware. I was about to add a way to get at the client directly, but it turns out that @PEZ is adding that anyway in #1595. So I'll wait for that to be done so I can build on top of that.
I'm not changing anything about client access in #1595, though. But in #1562 I added a getClient() thing. Maybe that is what you need?
You are correct, I somehow missed that and just saw you using it in #1595. Perfect, then I can continue here π
@PEZ @Cyrik any news here? From upvotes seems like this is something we should try offer to users somehow I think (One more person asked to me about this today, that's why I'm asking)
@ericdallo I'm working on it, but have been on a work trip last week and now I'm slowly catching up on everything else. Didn't realize it had so many upvotes π
I'll try to get around to it this week, the weekend should be comparatively free.
No hurries, just good to know someone is working on that! thank you!
Hey @Cyrik thanks for tackling this. Recently I'd been working on another feature (Github on mobile doesn't have the easy insert issue number hyperlink lol) that pertains to handling c-lsp's additionalTextEdits property for completion auto-import. I ended up going thru several rabbitholes wherein the problem you're trying to solve became very apparent.
I have experience with LSP and building VSC extensions, and am personally desperate to surface all the wonderful repl/lsp features into my day to day workflow with clojure - so, is it possible, or would you be interested, in working on this together?
@riotrah sure, always happy to collaborate. It's probably easiest if you drop me a message on slack @lukas Domagala. Sidenote I was hoping to actually finish this today, but I'd still like your input
The basics are done here. There are a few improvements left, but we've started new tickets for them. There's a preview for anyone wanting to help test it.