chore(lsp): clean up initialization process (#16369)

* send vim.NIL instead of not sending workspaceFolders
* read fallback rootPath and rootUri from workspaceFolders
* update documentation
This commit is contained in:
Michael Lingelbach 2021-11-21 11:39:30 -05:00 committed by GitHub
parent 120a881630
commit a2749482d9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 65 additions and 53 deletions

View File

@ -745,15 +745,12 @@ set_log_level({level}) *vim.lsp.set_log_level()*
start_client({config}) *vim.lsp.start_client()* start_client({config}) *vim.lsp.start_client()*
Starts and initializes a client with the given configuration. Starts and initializes a client with the given configuration.
Parameters `cmd` and `root_dir` are required. Parameter `cmd` is required.
The following parameters describe fields in the {config} The following parameters describe fields in the {config}
table. table.
Parameters: ~ Parameters: ~
{root_dir} (string) Directory where the LSP
server will base its rootUri on
initialization.
{cmd} (required, string or list treated {cmd} (required, string or list treated
like |jobstart()|) Base command that like |jobstart()|) Base command that
initiates the LSP client. initiates the LSP client.
@ -768,6 +765,13 @@ start_client({config}) *vim.lsp.start_client()*
{ "PRODUCTION=true"; "TEST=123"; PORT = 8080; HOST = "0.0.0.0"; } { "PRODUCTION=true"; "TEST=123"; PORT = 8080; HOST = "0.0.0.0"; }
< <
{workspace_folders} (table) List of workspace folders
passed to the language server. For
backwards compatibility rootUri and
rootPath will be derived from the
first workspace folder in this list.
See `workspaceFolders` in the LSP
spec.
{capabilities} Map overriding the default {capabilities} Map overriding the default
capabilities defined by capabilities defined by
|vim.lsp.protocol.make_client_capabilities()|, |vim.lsp.protocol.make_client_capabilities()|,
@ -801,10 +805,6 @@ start_client({config}) *vim.lsp.start_client()*
See `initialize` in the LSP spec. See `initialize` in the LSP spec.
{name} (string, default=client-id) Name in {name} (string, default=client-id) Name in
log messages. log messages.
{workspace_folders} (table) List of workspace folders
passed to the language server.
Defaults to root_dir if not set. See
`workspaceFolders` in the LSP spec
{get_language_id} function(bufnr, filetype) -> language {get_language_id} function(bufnr, filetype) -> language
ID as string. Defaults to the ID as string. Defaults to the
filetype. filetype.
@ -873,6 +873,10 @@ start_client({config}) *vim.lsp.start_client()*
debounce occurs if nil debounce occurs if nil
• exit_timeout (number, default 500): • exit_timeout (number, default 500):
Milliseconds to wait for server to Milliseconds to wait for server to
{root_dir} string Directory where the LSP server
will base its workspaceFolders,
rootUri, and rootPath on
initialization.
Return: ~ Return: ~
Client id. |vim.lsp.get_client_by_id()| Note: client may Client id. |vim.lsp.get_client_by_id()| Note: client may

View File

@ -1617,14 +1617,12 @@ validate({opt}) *vim.validate()*
vim.validate{arg1={{'foo'}, 'table'}, arg2={'foo', 'string'}} vim.validate{arg1={{'foo'}, 'table'}, arg2={'foo', 'string'}}
=> NOP (success) => NOP (success)
<
> vim.validate{arg1={1, 'table'}}
vim.validate{arg1={1, 'table'}} => error('arg1: expected table, got number')
=> error('arg1: expected table, got number')
< vim.validate{arg1={3, function(a) return (a % 2) == 0 end, 'even number'}}
> => error('arg1: expected even number, got 3')
vim.validate{arg1={3, function(a) return (a % 2) == 0 end, 'even number'}}
=> error('arg1: expected even number, got 3')
< <
Parameters: ~ Parameters: ~

View File

@ -531,11 +531,9 @@ Query:iter_matches({self}, {node}, {source}, {start}, {stop})
for id, node in pairs(match) do for id, node in pairs(match) do
local name = query.captures[id] local name = query.captures[id]
-- `node` was captured by the `name` capture in the match -- `node` was captured by the `name` capture in the match
<
> local node_data = metadata[id] -- Node level metadata
local node_data = metadata[id] -- Node level metadata
<
>
... use the info here ... ... use the info here ...
end end
end end

View File

@ -236,7 +236,6 @@ local function validate_client_config(config)
config = { config, 't' }; config = { config, 't' };
} }
validate { validate {
root_dir = { config.root_dir, optional_validator(is_dir), "directory" };
handlers = { config.handlers, "t", true }; handlers = { config.handlers, "t", true };
capabilities = { config.capabilities, "t", true }; capabilities = { config.capabilities, "t", true };
cmd_cwd = { config.cmd_cwd, optional_validator(is_dir), "directory" }; cmd_cwd = { config.cmd_cwd, optional_validator(is_dir), "directory" };
@ -566,12 +565,10 @@ end
-- --
--- Starts and initializes a client with the given configuration. --- Starts and initializes a client with the given configuration.
--- ---
--- Parameters `cmd` and `root_dir` are required. --- Parameter `cmd` is required.
--- ---
--- The following parameters describe fields in the {config} table. --- The following parameters describe fields in the {config} table.
--- ---
---@param root_dir: (string) Directory where the LSP server will base
--- its rootUri on initialization.
--- ---
---@param cmd: (required, string or list treated like |jobstart()|) Base command ---@param cmd: (required, string or list treated like |jobstart()|) Base command
--- that initiates the LSP client. --- that initiates the LSP client.
@ -587,6 +584,11 @@ end
--- { "PRODUCTION=true"; "TEST=123"; PORT = 8080; HOST = "0.0.0.0"; } --- { "PRODUCTION=true"; "TEST=123"; PORT = 8080; HOST = "0.0.0.0"; }
--- </pre> --- </pre>
--- ---
---@param workspace_folders (table) List of workspace folders passed to the
--- language server. For backwards compatibility rootUri and rootPath will be
--- derived from the first workspace folder in this list. See `workspaceFolders` in
--- the LSP spec.
---
---@param capabilities Map overriding the default capabilities defined by ---@param capabilities Map overriding the default capabilities defined by
--- |vim.lsp.protocol.make_client_capabilities()|, passed to the language --- |vim.lsp.protocol.make_client_capabilities()|, passed to the language
--- server on initialization. Hint: use make_client_capabilities() and modify --- server on initialization. Hint: use make_client_capabilities() and modify
@ -610,10 +612,6 @@ end
--- as `initializationOptions`. See `initialize` in the LSP spec. --- as `initializationOptions`. See `initialize` in the LSP spec.
--- ---
---@param name (string, default=client-id) Name in log messages. ---@param name (string, default=client-id) Name in log messages.
--
---@param workspace_folders (table) List of workspace folders passed to the
--- language server. Defaults to root_dir if not set. See `workspaceFolders` in
--- the LSP spec
--- ---
---@param get_language_id function(bufnr, filetype) -> language ID as string. ---@param get_language_id function(bufnr, filetype) -> language ID as string.
--- Defaults to the filetype. --- Defaults to the filetype.
@ -663,6 +661,11 @@ end
--- - exit_timeout (number, default 500): Milliseconds to wait for server to --- - exit_timeout (number, default 500): Milliseconds to wait for server to
-- exit cleanly after sending the 'shutdown' request before sending kill -15. -- exit cleanly after sending the 'shutdown' request before sending kill -15.
-- If set to false, nvim exits immediately after sending the 'shutdown' request to the server. -- If set to false, nvim exits immediately after sending the 'shutdown' request to the server.
---
---@param root_dir string Directory where the LSP
--- server will base its workspaceFolders, rootUri, and rootPath
--- on initialization.
---
---@returns Client id. |vim.lsp.get_client_by_id()| Note: client may not be ---@returns Client id. |vim.lsp.get_client_by_id()| Note: client may not be
--- fully initialized. Use `on_init` to do any actions once --- fully initialized. Use `on_init` to do any actions once
--- the client has been initialized. --- the client has been initialized.
@ -805,11 +808,24 @@ function lsp.start_client(config)
} }
local version = vim.version() local version = vim.version()
if config.root_dir and not config.workspace_folders then local workspace_folders
config.workspace_folders = {{ local root_uri
uri = vim.uri_from_fname(config.root_dir); local root_path
name = string.format("%s", config.root_dir); if config.workspace_folders or config.root_dir then
}}; if config.root_dir and not config.workspace_folders then
workspace_folders = {{
uri = vim.uri_from_fname(config.root_dir);
name = string.format("%s", config.root_dir);
}};
else
workspace_folders = config.workspace_folders
end
root_uri = workspace_folders[1].uri
root_path = vim.uri_to_fname(root_uri)
else
workspace_folders = vim.NIL
root_uri = vim.NIL
root_path = vim.NIL
end end
local initialize_params = { local initialize_params = {
@ -827,10 +843,15 @@ function lsp.start_client(config)
-- The rootPath of the workspace. Is null if no folder is open. -- The rootPath of the workspace. Is null if no folder is open.
-- --
-- @deprecated in favour of rootUri. -- @deprecated in favour of rootUri.
rootPath = config.root_dir; rootPath = root_path;
-- The rootUri of the workspace. Is null if no folder is open. If both -- The rootUri of the workspace. Is null if no folder is open. If both
-- `rootPath` and `rootUri` are set `rootUri` wins. -- `rootPath` and `rootUri` are set `rootUri` wins.
rootUri = config.root_dir and vim.uri_from_fname(config.root_dir); rootUri = root_uri;
-- The workspace folders configured in the client when the server starts.
-- This property is only available if the client supports workspace folders.
-- It can be `null` if the client supports workspace folders but none are
-- configured.
workspaceFolders = workspace_folders;
-- User provided initialization options. -- User provided initialization options.
initializationOptions = config.init_options; initializationOptions = config.init_options;
-- The capabilities provided by the client (editor or tool) -- The capabilities provided by the client (editor or tool)
@ -838,21 +859,6 @@ function lsp.start_client(config)
-- The initial trace setting. If omitted trace is disabled ("off"). -- The initial trace setting. If omitted trace is disabled ("off").
-- trace = "off" | "messages" | "verbose"; -- trace = "off" | "messages" | "verbose";
trace = valid_traces[config.trace] or 'off'; trace = valid_traces[config.trace] or 'off';
-- The workspace folders configured in the client when the server starts.
-- This property is only available if the client supports workspace folders.
-- It can be `null` if the client supports workspace folders but none are
-- configured.
--
-- Since 3.6.0
-- workspaceFolders?: WorkspaceFolder[] | null;
-- export interface WorkspaceFolder {
-- -- The associated URI for this workspace folder.
-- uri
-- -- The name of the workspace folder. Used to refer to this
-- -- workspace folder in the user interface.
-- name
-- }
workspaceFolders = config.workspace_folders,
} }
if config.before_init then if config.before_init then
-- TODO(ashkan) handle errors here. -- TODO(ashkan) handle errors here.

View File

@ -66,7 +66,10 @@ local function fake_lsp_server_setup(test_name, timeout_ms, options)
end end
end; end;
}); });
root_dir = vim.loop.cwd(); workspace_folders = {{
uri = 'file://' .. vim.loop.cwd(),
name = 'test_folder',
}};
on_init = function(client, result) on_init = function(client, result)
TEST_RPC_CLIENT = client TEST_RPC_CLIENT = client
vim.rpcrequest(1, "init", result) vim.rpcrequest(1, "init", result)
@ -153,7 +156,10 @@ describe('LSP', function()
"-c", string.format("lua TEST_NAME = %q", test_name), "-c", string.format("lua TEST_NAME = %q", test_name),
"-c", "luafile "..fixture_filename; "-c", "luafile "..fixture_filename;
}; };
root_dir = vim.loop.cwd(); workspace_folders = {{
uri = 'file://' .. vim.loop.cwd(),
name = 'test_folder',
}};
} }
end end
TEST_CLIENT1 = test__start_client() TEST_CLIENT1 = test__start_client()