aboutsummaryrefslogtreecommitdiffstats
path: root/lua/lspconfig/util.lua
diff options
context:
space:
mode:
authorLewis Russell <lewis6991@gmail.com>2023-08-22 12:12:06 +0100
committerLewis Russell <lewis6991@gmail.com>2023-08-22 13:22:07 +0100
commit204f08ea407e4b3b7ad272287e1821f47e52d4b3 (patch)
tree738debbf786be2ecf67dbe203f642f65bd6c6199 /lua/lspconfig/util.lua
parentdocs: update server_configurations.md (diff)
downloadnvim-lspconfig-204f08ea407e4b3b7ad272287e1821f47e52d4b3.tar
nvim-lspconfig-204f08ea407e4b3b7ad272287e1821f47e52d4b3.tar.gz
nvim-lspconfig-204f08ea407e4b3b7ad272287e1821f47e52d4b3.tar.bz2
nvim-lspconfig-204f08ea407e4b3b7ad272287e1821f47e52d4b3.tar.lz
nvim-lspconfig-204f08ea407e4b3b7ad272287e1821f47e52d4b3.tar.xz
nvim-lspconfig-204f08ea407e4b3b7ad272287e1821f47e52d4b3.tar.zst
nvim-lspconfig-204f08ea407e4b3b7ad272287e1821f47e52d4b3.zip
refactor: move manager to separate module
- Move manager logic to own module - Move async logic to own module - Improve type annotations
Diffstat (limited to 'lua/lspconfig/util.lua')
-rw-r--r--lua/lspconfig/util.lua191
1 files changed, 6 insertions, 185 deletions
diff --git a/lua/lspconfig/util.lua b/lua/lspconfig/util.lua
index f4e2ab78..2233f7ac 100644
--- a/lua/lspconfig/util.lua
+++ b/lua/lspconfig/util.lua
@@ -137,6 +137,8 @@ M.path = (function()
end
end
+ --- @param path string
+ --- @return string?
local function dirname(path)
local strip_dir_pat = '/([^/]+)$'
local strip_sep_pat = '/$'
@@ -227,191 +229,6 @@ M.path = (function()
}
end)()
-local function check_in_workspace(client, root_dir)
- if not client.workspace_folders then
- return false
- end
-
- for _, dir in ipairs(client.workspace_folders) do
- if (root_dir .. '/'):sub(1, #dir.name + 1) == dir.name .. '/' then
- return true
- end
- end
-
- return false
-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 manager = {}
-
- function manager.add(root_dir, single_file, bufnr)
- root_dir = M.path.sanitize(root_dir)
-
- local function get_client_from_cache(client_name)
- if vim.tbl_count(clients) == 0 then
- return
- end
-
- if clients[root_dir] then
- for _, id in pairs(clients[root_dir]) do
- local client = lsp.get_client_by_id(id)
- if client and client.name == client_name then
- return client
- end
- end
- end
-
- local all_client_ids = {}
- vim.tbl_map(function(val)
- vim.list_extend(all_client_ids, { unpack(val) })
- end, clients)
-
- for _, id in ipairs(all_client_ids) do
- local client = lsp.get_client_by_id(id)
- if client and client.name == client_name then
- return client
- end
- end
- end
-
- local function attach_and_cache(root, client_id)
- lsp.buf_attach_client(bufnr, client_id)
- if not clients[root] then
- clients[root] = {}
- end
- if not vim.tbl_contains(clients[root], client_id) then
- clients[root][#clients[root] + 1] = client_id
- end
- end
-
- local new_config = make_config(root_dir)
-
- local function register_workspace_folders(client)
- local params = {
- event = {
- added = { { uri = vim.uri_from_fname(root_dir), name = root_dir } },
- removed = {},
- },
- }
- client.rpc.notify('workspace/didChangeWorkspaceFolders', params)
- if not client.workspace_folders then
- client.workspace_folders = {}
- end
- client.workspace_folders[#client.workspace_folders + 1] = params.event.added[1]
- attach_and_cache(root_dir, client.id)
- end
-
- local function start_new_client()
- -- 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()
- for index, id in pairs(clients[root_dir]) do
- local exist = lsp.get_client_by_id(id)
- if exist.name == new_config.name then
- table.remove(clients[root_dir], index)
- end
- end
- 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
-
- -- 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
- local client_id = lsp.start_client(new_config)
- if not client_id then
- return
- end
- attach_and_cache(root_dir, client_id)
- end
-
- local function attach_or_spawn(client)
- if check_in_workspace(client, root_dir) then
- return attach_and_cache(root_dir, client.id)
- end
-
- local supported = vim.tbl_get(client, 'server_capabilities', 'workspace', 'workspaceFolders', 'supported')
- if supported then
- return register_workspace_folders(client)
- end
- start_new_client()
- end
-
- local attach_after_client_initialized = function(client)
- local timer = vim.loop.new_timer()
- timer:start(
- 0,
- 10,
- vim.schedule_wrap(function()
- if client.initialized and client.server_capabilities and not timer:is_closing() then
- attach_or_spawn(client)
- timer:stop()
- timer:close()
- end
- end)
- )
- end
-
- local client = get_client_from_cache(new_config.name)
-
- if not client then
- return start_new_client()
- end
-
- if clients[root_dir] or single_file then
- lsp.buf_attach_client(bufnr, client.id)
- return
- end
-
- -- make sure neovim had exchanged capabilities from language server
- -- it's useful to check server support workspaceFolders or not
- if client.initialized and client.server_capabilities then
- attach_or_spawn(client)
- else
- attach_after_client_initialized(client)
- end
- end
-
- function manager.clients()
- local res = {}
- for _, client_ids in pairs(clients) do
- for _, id in ipairs(client_ids) do
- local client = lsp.get_client_by_id(id)
- if client then
- res[#res + 1] = client
- end
- end
- end
- return res
- end
-
- return manager
-end
-
function M.search_ancestors(startpath, func)
validate { func = { func, 'f' } }
if func(startpath) then
@@ -447,6 +264,7 @@ function M.root_pattern(...)
return M.search_ancestors(startpath, matcher)
end
end
+
function M.find_git_ancestor(startpath)
return M.search_ancestors(startpath, function(path)
-- Support git directories and git files (worktrees)
@@ -455,6 +273,7 @@ function M.find_git_ancestor(startpath)
end
end)
end
+
function M.find_mercurial_ancestor(startpath)
return M.search_ancestors(startpath, function(path)
-- Support Mercurial directories
@@ -463,6 +282,7 @@ function M.find_mercurial_ancestor(startpath)
end
end)
end
+
function M.find_node_modules_ancestor(startpath)
return M.search_ancestors(startpath, function(path)
if M.path.is_dir(M.path.join(path, 'node_modules')) then
@@ -470,6 +290,7 @@ function M.find_node_modules_ancestor(startpath)
end
end)
end
+
function M.find_package_json_ancestor(startpath)
return M.search_ancestors(startpath, function(path)
if M.path.is_file(M.path.join(path, 'package.json')) then