diff options
| author | Raphael <glepnir@neovim.pro> | 2022-12-24 11:28:48 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-12-24 11:28:48 +0800 |
| commit | b0bd4297763024bfeb0c3065609361fb599c3594 (patch) | |
| tree | 8a6ac57e4d28fdcaa3d21d7b90da4e84a37acf21 /lua | |
| parent | docs: update server_configurations.md (diff) | |
| download | nvim-lspconfig-b0bd4297763024bfeb0c3065609361fb599c3594.tar nvim-lspconfig-b0bd4297763024bfeb0c3065609361fb599c3594.tar.gz nvim-lspconfig-b0bd4297763024bfeb0c3065609361fb599c3594.tar.bz2 nvim-lspconfig-b0bd4297763024bfeb0c3065609361fb599c3594.tar.lz nvim-lspconfig-b0bd4297763024bfeb0c3065609361fb599c3594.tar.xz nvim-lspconfig-b0bd4297763024bfeb0c3065609361fb599c3594.tar.zst nvim-lspconfig-b0bd4297763024bfeb0c3065609361fb599c3594.zip | |
refactor: remove single_clients and improve clients reuse (#2334)
* refactor: remove single_clients and improve clients reuse
* fix: remove unused param
* chore: correct check
* fix: improve
* fix: remove debug print
* fix: add comment
* chore: don't insert workspace when single file mode
* chore: add comment
Diffstat (limited to 'lua')
| -rw-r--r-- | lua/lspconfig/util.lua | 163 |
1 files changed, 83 insertions, 80 deletions
diff --git a/lua/lspconfig/util.lua b/lua/lspconfig/util.lua index fcf286d0..20244bb8 100644 --- a/lua/lspconfig/util.lua +++ b/lua/lspconfig/util.lua @@ -230,113 +230,116 @@ end)() -- Returns a function(root_dir), which, when called with a root_dir it hasn't -- seen before, will call make_config(root_dir) and start a new client. function M.server_per_root_dir_manager(make_config) + -- a table store the root dir with clients in this dir local clients = {} - local single_file_clients = {} local manager = {} function manager.add(root_dir, single_file) local client_id - -- This is technically unnecessary, as lspconfig's path utilities should be hermetic, - -- however users are free to return strings in custom root resolvers. root_dir = M.path.sanitize(root_dir) - if single_file then - client_id = single_file_clients[root_dir] - elseif root_dir and M.path.is_dir(root_dir) then - client_id = clients[root_dir] - else - return + + local client_id_iterator = function(client_ids, conf) + for _, id in ipairs(client_ids) do + local client = lsp.get_client_by_id(id) + -- if found the workspace field in server_capabilities the server support workspace + -- if server not support the worskspace spawn a new server instance then. + if client and client.name == conf.name and client.server_capabilities.workspace then + return client + end + end end + -- get client which support workspace from clients table local get_client_from_cache = function(conf) - local id - if vim.tbl_count(clients) == 1 then - id = vim.tbl_values(clients)[1] - elseif vim.tbl_count(single_file_clients) == 1 then - id = vim.tbl_values(single_file_clients)[1] - else + if vim.tbl_count(clients) == 0 then return end - local client = lsp.get_client_by_id(id) - if - client - and client.server_capabilities - and client.server_capabilities.workspaceFolders - and client.server_capabilities.workspaceFolders.supported - and client.name == conf.name - then - return client + local client + + if clients[root_dir] then + client = client_id_iterator(clients[root_dir], conf) + else + for _, ids in pairs(clients) do + client = client_id_iterator(ids, conf) + if client then + break + end + end end - return nil + + return client end - -- Check if we have a client already or start and store it. - if not client_id then - local new_config = make_config(root_dir) - local client = get_client_from_cache(new_config) - if client then - local params = lsp.util.make_workspace_params( - { { uri = vim.uri_from_fname(root_dir), name = root_dir } }, - { {} } - ) - client.rpc.notify('workspace/didChangeWorkspaceFolders', params) - if not client.workspace_folders then - client.workspace_folders = {} - end - table.insert(client.workspace_folders, params.event.added[1]) + local new_config = make_config(root_dir) + local client = get_client_from_cache(new_config) + + if client then + -- if in single file mode just return this client id don't insert the new + -- root dir into the workspace_folders + if single_file then return client.id end - -- do nothing if the client is not enabled - if new_config.enabled == false then - return + local params = lsp.util.make_workspace_params({ { uri = vim.uri_from_fname(root_dir), name = root_dir } }, { {} }) + client.rpc.notify('workspace/didChangeWorkspaceFolders', params) + if not client.workspace_folders then + client.workspace_folders = {} end - if not new_config.cmd then - vim.notify( - string.format( - '[lspconfig] cmd not defined for %q. Manually set cmd in the setup {} call according to server_configurations.md, see :help lspconfig-index.', - new_config.name - ), - vim.log.levels.ERROR - ) - return + table.insert(client.workspace_folders, params.event.added[1]) + if not clients[root_dir] then + clients[root_dir] = {} end - new_config.on_exit = M.add_hook_before(new_config.on_exit, function() - clients[root_dir] = nil - single_file_clients[root_dir] = nil - end) + table.insert(clients[root_dir], client.id) + return client.id + end - -- Launch the server in the root directory used internally by lspconfig, if otherwise unset - -- also check that the path exist - if not new_config.cmd_cwd and uv.fs_realpath(root_dir) then - new_config.cmd_cwd = root_dir - end + -- do nothing if the client is not enabled + if new_config.enabled == false then + return + end + if not new_config.cmd then + vim.notify( + string.format( + '[lspconfig] cmd not defined for %q. Manually set cmd in the setup {} call according to server_configurations.md, see :help lspconfig-index.', + new_config.name + ), + vim.log.levels.ERROR + ) + return + end + new_config.on_exit = M.add_hook_before(new_config.on_exit, function() + clients[root_dir] = nil + end) - -- Sending rootDirectory and workspaceFolders as null is not explicitly - -- codified in the spec. Certain servers crash if initialized with a NULL - -- root directory. - if single_file then - new_config.root_dir = nil - new_config.workspace_folders = nil - end - client_id = lsp.start_client(new_config) + -- Launch the server in the root directory used internally by lspconfig, if otherwise unset + -- also check that the path exist + if not new_config.cmd_cwd and uv.fs_realpath(root_dir) then + new_config.cmd_cwd = root_dir + end - -- Handle failures in start_client - if not client_id then - return - end + -- Sending rootDirectory and workspaceFolders as null is not explicitly + -- codified in the spec. Certain servers crash if initialized with a NULL + -- root directory. + if single_file then + new_config.root_dir = nil + new_config.workspace_folders = nil + end + client_id = lsp.start_client(new_config) - if single_file then - single_file_clients[root_dir] = client_id - else - clients[root_dir] = client_id - end + -- Handle failures in start_client + if not client_id then + return + end + + if not clients[root_dir] then + clients[root_dir] = {} end + table.insert(clients[root_dir], client_id) return client_id end - function manager.clients(single_file) + function manager.clients() local res = {} - local client_list = single_file and single_file_clients or clients - for _, id in pairs(client_list) do + for _, id in pairs(clients) do local client = lsp.get_client_by_id(id) if client then table.insert(res, client) |
