Skip to content

Commit

Permalink
refactor(lsp): move workspace folder logic into the client
Browse files Browse the repository at this point in the history
- Changed `reuse_client` to check workspace folders in addition to
  root_dir.
  • Loading branch information
lewis6991 committed Apr 2, 2024
1 parent ffe3002 commit d9235ef
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 41 deletions.
28 changes: 23 additions & 5 deletions runtime/lua/vim/lsp.lua
Expand Up @@ -164,6 +164,28 @@ local function once(fn)
end
end

--- @param client vim.lsp.Client
--- @param config vim.lsp.ClientConfig
--- @return boolean
local function reuse_client_default(client, config)
if client.name ~= config.name then
return false
end

if config.root_dir then
for _, dir in ipairs(client.workspace_folders or {}) do
-- note: do not need to check client.root_dir since that should be client.workspace_folders[1]
if config.root_dir == dir.name then
return true
end
end
end

-- TODO(lewis6991): also check config.workspace_folders

return false
end

--- @class vim.lsp.start.Opts
--- @inlinedoc
---
Expand Down Expand Up @@ -216,11 +238,7 @@ end
--- @return integer? client_id
function lsp.start(config, opts)
opts = opts or {}
local reuse_client = opts.reuse_client
or function(client, conf)
return client.root_dir == conf.root_dir and client.name == conf.name
end

local reuse_client = opts.reuse_client or reuse_client_default
local bufnr = resolve_bufnr(opts.bufnr)

for _, client in pairs(all_clients) do
Expand Down
40 changes: 5 additions & 35 deletions runtime/lua/vim/lsp/buf.lua
Expand Up @@ -521,28 +521,9 @@ function M.add_workspace_folder(workspace_folder)
print(workspace_folder, ' is not a valid directory')
return
end
local new_workspace = {
uri = vim.uri_from_fname(workspace_folder),
name = workspace_folder,
}
local params = { event = { added = { new_workspace }, removed = {} } }
local bufnr = vim.api.nvim_get_current_buf()
local bufnr = api.nvim_get_current_buf()
for _, client in pairs(vim.lsp.get_clients({ bufnr = bufnr })) do
local found = false
for _, folder in pairs(client.workspace_folders or {}) do
if folder.name == workspace_folder then
found = true
print(workspace_folder, 'is already part of this workspace')
break
end
end
if not found then
client.notify(ms.workspace_didChangeWorkspaceFolders, params)
if not client.workspace_folders then
client.workspace_folders = {}
end
table.insert(client.workspace_folders, new_workspace)
end
client:_add_workspace_folder(workspace_folder)
end
end

Expand All @@ -554,23 +535,12 @@ function M.remove_workspace_folder(workspace_folder)
workspace_folder = workspace_folder
or npcall(vim.fn.input, 'Workspace Folder: ', vim.fn.expand('%:p:h'))
api.nvim_command('redraw')
if not (workspace_folder and #workspace_folder > 0) then
if not workspace_folder or #workspace_folder == 0 then
return
end
local workspace = {
uri = vim.uri_from_fname(workspace_folder),
name = workspace_folder,
}
local params = { event = { added = {}, removed = { workspace } } }
local bufnr = vim.api.nvim_get_current_buf()
local bufnr = api.nvim_get_current_buf()
for _, client in pairs(vim.lsp.get_clients({ bufnr = bufnr })) do
for idx, folder in pairs(client.workspace_folders) do
if folder.name == workspace_folder then
client.notify(ms.workspace_didChangeWorkspaceFolders, params)
client.workspace_folders[idx] = nil
return
end
end
client:_remove_workspace_folder(workspace_folder)
end
print(workspace_folder, 'is not currently part of the workspace')
end
Expand Down
43 changes: 42 additions & 1 deletion runtime/lua/vim/lsp/client.lua
Expand Up @@ -420,7 +420,7 @@ local function get_workspace_folders(workspace_folders, root_dir)
return {
{
uri = vim.uri_from_fname(root_dir),
name = string.format('%s', root_dir),
name = root_dir,
},
}
end
Expand Down Expand Up @@ -1065,4 +1065,45 @@ function Client:_on_exit(code, signal)
)
end

--- @package
--- Add a directory to the workspace folders.
--- @param dir string?
function Client:_add_workspace_folder(dir)
for _, folder in pairs(self.workspace_folders or {}) do
if folder.name == dir then
print(dir, 'is already part of this workspace')
return
end
end

local wf = assert(get_workspace_folders(nil, dir))

self:_notify(ms.workspace_didChangeWorkspaceFolders, {
event = { added = wf, removed = {} },
})

if not self.workspace_folders then
self.workspace_folders = {}
end
vim.list_extend(self.workspace_folders, wf)
end

--- @package
--- Remove a directory to the workspace folders.
--- @param dir string?
function Client:_remove_workspace_folder(dir)
local wf = assert(get_workspace_folders(nil, dir))

self:_notify(ms.workspace_didChangeWorkspaceFolders, {
event = { added = {}, removed = wf },
})

for idx, folder in pairs(self.workspace_folders) do
if folder.name == dir then
table.remove(self.workspace_folders, idx)
break
end
end
end

return Client

0 comments on commit d9235ef

Please sign in to comment.