-
-
Notifications
You must be signed in to change notification settings - Fork 6.3k
fix(lsp): check for configuration workspace folders when reusing clients #31340
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Related neovim/nvim-lspconfig#3452 @glepnir |
local config_folders = lsp._get_workspace_folders(config.workspace_folders or config.root_dir) | ||
or {} | ||
for _, config_folder in ipairs(config_folders) do | ||
for _, client_folder in ipairs(client.workspace_folders) do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if we'd need to handle the case somehow differently where config_folders
contains workspaces not present in client.workspace_folder
.
If the user provides workspace [a, b] and ends up with a client that has [a, c] that might be confusing.
We could extend the client workspace's automatically (getting [a, b, c] in ^)
Or require exact matches?
No idea what's less suprising and more convenient.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm FWIW nvim-lspconfig reuses a client as long as the name matches, so I don’t think this approach is too revolutionary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reusing always if only the name matches sounds broken to me.
Say you have:
workspace/project-a/
workspace/project-b/
and you open a file within project-a
the first time. That will start a client
Now you open a file in project-b
, which has a different set of dependencies, but same language. If it re-used the client from project-a, you'd have a language server that can resolve dependencies of project-a
but not project-b
, and likely get lots of errors.
As for the workspace folders - I don't use them myself so I'm not that familiar with the common use-cases, but my understanding is that they allow you to do things like this:
workspace/project-a/
workspace/project-b/
workspace/shared/
Where project-a and project-b are independent, but both use shared
.
So, if you're using a single nvim client to work on both a and b in parallel you'd likely want to have two clients, one with workspaceFolders [project-a, shared] and one with [project-b, shared].
Anything else would either lead to seeing dependencies you shouldn't, or miss dependencies you should see.
Please correct me if that's not the case.
This at least improves the situation, right?
Based on ^ I think it might make the situation worse
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reusing always if only the name matches sounds broken to me.
I'm not suggesting we do this. I just mention that this is nvim-lspconfig
's approach and so I don't find the current reuse_client
overly flexible in comparison.
As for workspace folders, you bring a good point. I can change the current implementation to only reuse a client when the configuration only includes folders that an existing client is already aware of.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LMK what you think :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nvim-lspconfig reuses a client as long as the name matches,
No. The latest refactoring turned it into this. It resulted in some clients being reused that shouldn't be reused.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@glepnir which refactor is that? Are you referring to neovim/nvim-lspconfig#3450?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. I used a wrong server for testing before . I think the problem still exists. When loading multiple projects of the same language from the session. You can't know the ability of the server to be started when the second buffer is triggered. Because it may be uninitialized. That is to say, clinet.initialized is nil. You can't know whether it supports workspaceFolder. Here must wait for the initialization of the started server to be completed before deciding whether to reuse or a new instance. I think the core should handle this situation if i am wrong please correct me .
Another problem is the logic of lsoconfig reuse_client. It may not be applicable here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@glepnir Please correct me if I'm wrong, but before my change this function reuses clients based on their name, prioritizing one in the same root directory but still falling back to just comparing names. The PR I made didn't change the client reuse logic at all, it merely focused on replacing start_client
by start
, but I can stop my contributions if they're unwelcome.
As for the issue you're describing I still don't see why on_init
doesn't handle this scenario (which I already mentioned here). You can see from the editor implementation how that callback is called after initialization.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Previously I used a timer to wait for the first server to initialize. The refactoring removed this part. So the core better consider this case.
This at least improves the situation, right? So let's unblock it and can improve later if possible. |
3e02ae5
to
d7e102f
Compare
@justinmk @lewis6991 @mfussenegger Do you still want this? I don't want to work on a PR that won't get merged anyway. |
I approved. I don't understand this area or its impacts well enough, so I'm deferring to someone else (@mfussenegger) to merge. |
That SGTM, any objection from @mfussenegger if that is implemented? |
Note that I already added this to the PR. |
Backport? |
Not sure. I wouldn't consider this a fix per se but more of an improvement, but I'll let others decide. |
…ders #31608 Problem: regression since #31340 `nvim -l repro.lua`: ```lua vim.lsp.start { cmd = { 'lua-language-server' }, name = 'lua_ls' } vim.lsp.start { cmd = { 'lua-language-server' }, name = 'lua_ls', root_dir = 'foo' } -- swapped case will be ok: -- vim.lsp.start { cmd = { 'lua-language-server' }, name = 'lua_ls', root_dir = 'foo' } -- vim.lsp.start { cmd = { 'lua-language-server' }, name = 'lua_ls' } ``` Failure: ``` E5113: Error while calling lua chunk: /…/lua/vim/lsp.lua:214: bad argument #1 to 'ipairs' (table expected, got nil) stack traceback: [C]: in function 'ipairs' /…/lua/vim/lsp.lua:214: in function 'reuse_client' /…/lua/vim/lsp.lua:629: in function 'start' repro.lua:34: in main chunk ```
…ders neovim#31608 Problem: regression since neovim#31340 `nvim -l repro.lua`: ```lua vim.lsp.start { cmd = { 'lua-language-server' }, name = 'lua_ls' } vim.lsp.start { cmd = { 'lua-language-server' }, name = 'lua_ls', root_dir = 'foo' } -- swapped case will be ok: -- vim.lsp.start { cmd = { 'lua-language-server' }, name = 'lua_ls', root_dir = 'foo' } -- vim.lsp.start { cmd = { 'lua-language-server' }, name = 'lua_ls' } ``` Failure: ``` E5113: Error while calling lua chunk: /…/lua/vim/lsp.lua:214: bad argument neovim#1 to 'ipairs' (table expected, got nil) stack traceback: [C]: in function 'ipairs' /…/lua/vim/lsp.lua:214: in function 'reuse_client' /…/lua/vim/lsp.lua:629: in function 'start' repro.lua:34: in main chunk ```
Checking workspace folders in the input configuration in the default
reuse_client
implementation forvim.lsp.start
.