mirror of
https://github.com/neovim/neovim.git
synced 2024-12-25 13:45:15 -07:00
LSP: Feature/add workspace folders (#12638)
* First implementation of workspace folders * Add completion for current directory * Add tracking of workspace folders * Add workspace folder listing * Add checks on adding/removing workspaces * Add appropriate initialization options * Add documentation * Make workspaceFolders available wherever client is
This commit is contained in:
parent
2d5dd85eef
commit
0d83a1c43f
@ -996,6 +996,19 @@ type_definition() *vim.lsp.buf.type_definition()*
|
|||||||
Jumps to the definition of the type of the symbol under the
|
Jumps to the definition of the type of the symbol under the
|
||||||
cursor.
|
cursor.
|
||||||
|
|
||||||
|
add_workspace_folder({path}) *vim.lsp.buf.add_workspace_folder()*
|
||||||
|
Add the folder at path to the workspace folders. If {path} is
|
||||||
|
not provided, the user will be prompted for a path using
|
||||||
|
|input()|.
|
||||||
|
|
||||||
|
remove_workspace_folder({path}) *vim.lsp.buf.remove_workspace_folder()*
|
||||||
|
Remove the folder at path from the workspace folders. If
|
||||||
|
{path} is not provided, the user will be prompted for
|
||||||
|
a path using |input()|.
|
||||||
|
|
||||||
|
list_workspace_folders() *vim.lsp.buf.list_workspace_folders()*
|
||||||
|
List all folders in the workspace.
|
||||||
|
|
||||||
workspace_symbol({query}) *vim.lsp.buf.workspace_symbol()*
|
workspace_symbol({query}) *vim.lsp.buf.workspace_symbol()*
|
||||||
Lists all symbols in the current workspace in the quickfix
|
Lists all symbols in the current workspace in the quickfix
|
||||||
window.
|
window.
|
||||||
|
@ -597,7 +597,10 @@ function lsp.start_client(config)
|
|||||||
-- -- workspace folder in the user interface.
|
-- -- workspace folder in the user interface.
|
||||||
-- name
|
-- name
|
||||||
-- }
|
-- }
|
||||||
workspaceFolders = nil;
|
workspaceFolders = {{
|
||||||
|
uri = vim.uri_from_fname(config.root_dir);
|
||||||
|
name = string.format("%s", config.root_dir);
|
||||||
|
}};
|
||||||
}
|
}
|
||||||
if config.before_init then
|
if config.before_init then
|
||||||
-- TODO(ashkan) handle errors here.
|
-- TODO(ashkan) handle errors here.
|
||||||
@ -610,6 +613,7 @@ function lsp.start_client(config)
|
|||||||
rpc.notify('initialized', {[vim.type_idx]=vim.types.dictionary})
|
rpc.notify('initialized', {[vim.type_idx]=vim.types.dictionary})
|
||||||
client.initialized = true
|
client.initialized = true
|
||||||
uninitialized_clients[client_id] = nil
|
uninitialized_clients[client_id] = nil
|
||||||
|
client.workspaceFolders = initialize_params.workspaceFolders
|
||||||
client.server_capabilities = assert(result.capabilities, "initialize result doesn't contain capabilities")
|
client.server_capabilities = assert(result.capabilities, "initialize result doesn't contain capabilities")
|
||||||
-- These are the cleaned up capabilities we use for dynamically deciding
|
-- These are the cleaned up capabilities we use for dynamically deciding
|
||||||
-- when to send certain events to clients.
|
-- when to send certain events to clients.
|
||||||
|
@ -238,6 +238,61 @@ function M.outgoing_calls()
|
|||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- List workspace folders.
|
||||||
|
function M.list_workspace_folders()
|
||||||
|
local workspace_folders = {}
|
||||||
|
for _, client in ipairs(vim.lsp.buf_get_clients()) do
|
||||||
|
for _, folder in ipairs(client.workspaceFolders) do
|
||||||
|
table.insert(workspace_folders, folder.name)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return workspace_folders
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Add a workspace folder.
|
||||||
|
function M.add_workspace_folder(workspace_folder)
|
||||||
|
workspace_folder = workspace_folder or npcall(vfn.input, "Workspace Folder: ", vfn.expand('%:p:h'))
|
||||||
|
vim.api.nvim_command("redraw")
|
||||||
|
if not (workspace_folder and #workspace_folder > 0) then return end
|
||||||
|
if vim.fn.isdirectory(workspace_folder) == 0 then
|
||||||
|
print(workspace_folder, " is not a valid directory")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local params = util.make_workspace_params({{uri = vim.uri_from_fname(workspace_folder); name = workspace_folder}}, {{}})
|
||||||
|
for _, client in ipairs(vim.lsp.buf_get_clients()) do
|
||||||
|
local found = false
|
||||||
|
for _, folder in ipairs(client.workspaceFolders) 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
|
||||||
|
vim.lsp.buf_notify(0, 'workspace/didChangeWorkspaceFolders', params)
|
||||||
|
table.insert(client.workspaceFolders, params.event.added[1])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Remove a workspace folder.
|
||||||
|
function M.remove_workspace_folder(workspace_folder)
|
||||||
|
workspace_folder = workspace_folder or npcall(vfn.input, "Workspace Folder: ", vfn.expand('%:p:h'))
|
||||||
|
vim.api.nvim_command("redraw")
|
||||||
|
if not (workspace_folder and #workspace_folder > 0) then return end
|
||||||
|
local params = util.make_workspace_params({{}}, {{uri = vim.uri_from_fname(workspace_folder); name = workspace_folder}})
|
||||||
|
for _, client in ipairs(vim.lsp.buf_get_clients()) do
|
||||||
|
for idx, folder in ipairs(client.workspaceFolders) do
|
||||||
|
if folder.name == workspace_folder then
|
||||||
|
vim.lsp.buf_notify(0, 'workspace/didChangeWorkspaceFolders', params)
|
||||||
|
client.workspaceFolders[idx] = nil
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
print(workspace_folder, "is not currently part of the workspace")
|
||||||
|
end
|
||||||
|
|
||||||
--- Lists all symbols in the current workspace in the quickfix window.
|
--- Lists all symbols in the current workspace in the quickfix window.
|
||||||
---
|
---
|
||||||
--- The list is filtered against {query}; if the argument is omitted from the
|
--- The list is filtered against {query}; if the argument is omitted from the
|
||||||
|
@ -716,6 +716,7 @@ function protocol.make_client_capabilities()
|
|||||||
};
|
};
|
||||||
hierarchicalWorkspaceSymbolSupport = true;
|
hierarchicalWorkspaceSymbolSupport = true;
|
||||||
};
|
};
|
||||||
|
workspaceFolders = true;
|
||||||
applyEdit = true;
|
applyEdit = true;
|
||||||
};
|
};
|
||||||
callHierarchy = {
|
callHierarchy = {
|
||||||
@ -974,6 +975,28 @@ function protocol.resolve_capabilities(server_capabilities)
|
|||||||
error("The server sent invalid implementationProvider")
|
error("The server sent invalid implementationProvider")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local workspace = server_capabilities.workspace
|
||||||
|
local workspace_properties = {}
|
||||||
|
if workspace == nil or workspace.workspaceFolders == nil then
|
||||||
|
-- Defaults if omitted.
|
||||||
|
workspace_properties = {
|
||||||
|
workspace_folder_properties = {
|
||||||
|
supported = false;
|
||||||
|
changeNotifications=false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elseif type(workspace.workspaceFolders) == 'table' then
|
||||||
|
workspace_properties = {
|
||||||
|
workspace_folder_properties = {
|
||||||
|
supported = vim.F.ifnil(workspace.workspaceFolders.supported, false);
|
||||||
|
changeNotifications = vim.F.ifnil(workspace.workspaceFolders.changeNotifications, false);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
error("The server sent invalid workspace")
|
||||||
|
end
|
||||||
|
|
||||||
local signature_help_properties
|
local signature_help_properties
|
||||||
if server_capabilities.signatureHelpProvider == nil then
|
if server_capabilities.signatureHelpProvider == nil then
|
||||||
signature_help_properties = {
|
signature_help_properties = {
|
||||||
@ -993,6 +1016,7 @@ function protocol.resolve_capabilities(server_capabilities)
|
|||||||
return vim.tbl_extend("error"
|
return vim.tbl_extend("error"
|
||||||
, text_document_sync_properties
|
, text_document_sync_properties
|
||||||
, signature_help_properties
|
, signature_help_properties
|
||||||
|
, workspace_properties
|
||||||
, general_properties
|
, general_properties
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
@ -1314,6 +1314,9 @@ function M.make_text_document_params()
|
|||||||
return { uri = vim.uri_from_bufnr(0) }
|
return { uri = vim.uri_from_bufnr(0) }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function M.make_workspace_params(added, removed)
|
||||||
|
return { event = { added = added; removed = removed; } }
|
||||||
|
end
|
||||||
--- Returns visual width of tabstop.
|
--- Returns visual width of tabstop.
|
||||||
---
|
---
|
||||||
--@see |softtabstop|
|
--@see |softtabstop|
|
||||||
|
Loading…
Reference in New Issue
Block a user