aboutsummaryrefslogtreecommitdiffstats
path: root/lua
diff options
context:
space:
mode:
authorRaphael <glepnir@neovim.pro>2022-12-24 11:28:48 +0800
committerGitHub <noreply@github.com>2022-12-24 11:28:48 +0800
commitb0bd4297763024bfeb0c3065609361fb599c3594 (patch)
tree8a6ac57e4d28fdcaa3d21d7b90da4e84a37acf21 /lua
parentdocs: update server_configurations.md (diff)
downloadnvim-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.lua163
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)