diff options
| author | Lewis Russell <lewis6991@gmail.com> | 2023-08-22 12:12:06 +0100 |
|---|---|---|
| committer | Lewis Russell <lewis6991@gmail.com> | 2023-08-22 13:22:07 +0100 |
| commit | 204f08ea407e4b3b7ad272287e1821f47e52d4b3 (patch) | |
| tree | 738debbf786be2ecf67dbe203f642f65bd6c6199 /lua/lspconfig/util.lua | |
| parent | docs: update server_configurations.md (diff) | |
| download | nvim-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.lua | 191 |
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 |
