aboutsummaryrefslogtreecommitdiff
path: root/runtime/lua/vim/lsp.lua
diff options
context:
space:
mode:
authorPatrice Peterson <patrice.peterson@mailbox.org>2020-08-19 18:17:08 +0200
committerPatrice Peterson <patrice.peterson@mailbox.org>2020-08-23 13:48:25 +0200
commitac05343a1023874243ee9fdd490c21c42a737157 (patch)
tree2466eb3c28b09b8e77ba7e1d3696555672fbb38e /runtime/lua/vim/lsp.lua
parent8c49e3d50959e24dadd688f56a18f104bd5fd934 (diff)
downloadrneovim-ac05343a1023874243ee9fdd490c21c42a737157.tar.gz
rneovim-ac05343a1023874243ee9fdd490c21c42a737157.tar.bz2
rneovim-ac05343a1023874243ee9fdd490c21c42a737157.zip
Add docs for most vim.lsp methods
Most of the lsp.log will be addressed in a separate PR.
Diffstat (limited to 'runtime/lua/vim/lsp.lua')
-rw-r--r--runtime/lua/vim/lsp.lua255
1 files changed, 219 insertions, 36 deletions
diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua
index 6fe1d15b7e..9d7ab9b74f 100644
--- a/runtime/lua/vim/lsp.lua
+++ b/runtime/lua/vim/lsp.lua
@@ -27,11 +27,21 @@ local lsp = {
-- TODO improve handling of scratch buffers with LSP attached.
+--@private
+--- Concatenates and writes a list of strings to the Vim error buffer.
+---
+--@param {...} (List of strings) List to write to the buffer
local function err_message(...)
nvim_err_writeln(table.concat(vim.tbl_flatten{...}))
nvim_command("redraw")
end
+--@private
+--- Returns the buffer number for the given {bufnr}.
+---
+--@param bufnr (number) Buffer number to resolve. Defaults to the current
+---buffer if not given.
+--@returns bufnr (number) Number of requested buffer
local function resolve_bufnr(bufnr)
validate { bufnr = { bufnr, 'n', true } }
if bufnr == nil or bufnr == 0 then
@@ -40,6 +50,11 @@ local function resolve_bufnr(bufnr)
return bufnr
end
+--@private
+--- Checks whether a given path is a directory.
+---
+--@param filename (string) path to check
+--@returns true if {filename} exists and is a directory, false otherwise
local function is_dir(filename)
validate{filename={filename,'s'}}
local stat = uv.fs_stat(filename)
@@ -55,6 +70,10 @@ local valid_encodings = {
}
local client_index = 0
+--@private
+--- Returns a new, unused client id.
+---
+--@returns (number) client id
local function next_client_id()
client_index = client_index + 1
return client_index
@@ -64,6 +83,12 @@ local active_clients = {}
local all_buffer_active_clients = {}
local uninitialized_clients = {}
+--@private
+--- Invokes a callback for each LSP client attached to the buffer {bufnr}.
+---
+--@param bufnr (Number) of buffer
+--@param callback (function({client}, {client_id}, {bufnr}) Function to run on
+---each client attached to that buffer.
local function for_each_buffer_client(bufnr, callback)
validate {
callback = { callback, 'f' };
@@ -88,6 +113,11 @@ lsp.client_errors = tbl_extend("error", lsp_rpc.client_errors, vim.tbl_add_rever
ON_INIT_CALLBACK_ERROR = table.maxn(lsp_rpc.client_errors) + 1;
})
+--@private
+--- Normalizes {encoding} to valid LSP encoding names.
+---
+--@param encoding (string) Encoding to normalize
+--@returns (string) normalized encoding name
local function validate_encoding(encoding)
validate {
encoding = { encoding, 's' };
@@ -96,6 +126,13 @@ local function validate_encoding(encoding)
or error(string.format("Invalid offset encoding %q. Must be one of: 'utf-8', 'utf-16', 'utf-32'", encoding))
end
+--@internal
+--- Parses a command invocation into the command itself and its args. If there
+--- are no arguments, an empty table is returned as the second argument.
+---
+--@param input (List)
+--@returns (string) the command
+--@returns (list of strings) its arguments
function lsp._cmd_parts(input)
vim.validate{cmd={
input,
@@ -114,12 +151,27 @@ function lsp._cmd_parts(input)
return cmd, cmd_args
end
+--@private
+--- Augments a validator function with support for optional (nil) values.
+---
+--@param fn (function(v)) The original validator function; should return a
+---bool.
+--@returns (function(v)) The augmented function. Also returns true if {v} is
+---`nil`.
local function optional_validator(fn)
return function(v)
return v == nil or fn(v)
end
end
+--@private
+--- Validates a client configuration as given to |vim.lsp.start_client()|.
+---
+--@param config (table)
+--@returns (table) "Cleaned" config, containing only the command, its
+---arguments, and a valid encoding.
+---
+--@see |vim.lsp.start_client()|
local function validate_client_config(config)
validate {
config = { config, 't' };
@@ -148,6 +200,11 @@ local function validate_client_config(config)
}
end
+--@private
+--- Returns full text of buffer {bufnr} as a string.
+---
+--@param bufnr (number) Buffer handle, or 0 for current.
+--@returns Buffer text as string.
local function buf_get_full_text(bufnr)
local text = table.concat(nvim_buf_get_lines(bufnr, 0, -1, true), '\n')
if nvim_buf_get_option(bufnr, 'eol') then
@@ -156,6 +213,11 @@ local function buf_get_full_text(bufnr)
return text
end
+--@private
+--- Default handler for the 'textDocument/didOpen' LSP notification.
+---
+--@param bufnr (Number) Number of the buffer, or 0 for current
+--@param client Client object
local function text_document_did_open_handler(bufnr, client)
if not client.resolved_capabilities.text_document_open_close then
return
@@ -176,74 +238,88 @@ local function text_document_did_open_handler(bufnr, client)
util.buf_versions[bufnr] = params.textDocument.version
end
---- LSP client object.
+--- LSP client object. You can get an active client object via
+--- |vim.lsp.get_client_by_id()| or |vim.lsp.get_active_clients()|.
---
--- - Methods:
---
---- - request(method, params, [callback])
---- Send a request to the server. If callback is not specified, it will use
---- {client.callbacks} to try to find a callback. If one is not found there,
---- then an error will occur.
+--- - request(method, params, [callback], bufnr)
+--- Sends a request to the server.
--- This is a thin wrapper around {client.rpc.request} with some additional
--- checking.
---- Returns a boolean to indicate if the notification was successful. If it
---- is false, then it will always be false (the client has shutdown).
---- If it was successful, then it will return the request id as the second
---- result. You can use this with `notify("$/cancel", { id = request_id })`
---- to cancel the request. This helper is made automatically with
---- |vim.lsp.buf_request()|
---- Returns: status, [client_id]
+--- If {callback} is not specified, it will use {client.callbacks} to try to
+--- find a callback. If one is not found there, then an error will occur.
+--- Returns: {status}, {[client_id]}. {status} is a boolean indicating if
+--- the notification was successful. If it is `false`, then it will always
+--- be `false` (the client has shutdown).
+--- If {status} is `true`, the function returns {request_id} as the second
+--- result. You can use this with `client.cancel_request(request_id)`
+--- to cancel the request.
---
--- - notify(method, params)
---- This is just {client.rpc.notify}()
---- Returns a boolean to indicate if the notification was successful. If it
---- is false, then it will always be false (the client has shutdown).
---- Returns: status
+--- Sends a notification to an LSP server.
+--- Returns: a boolean to indicate if the notification was successful. If
+--- it is false, then it will always be false (the client has shutdown).
---
--- - cancel_request(id)
---- This is just {client.rpc.notify}("$/cancelRequest", { id = id })
---- Returns the same as `notify()`.
+--- Cancels a request with a given request id.
+--- Returns: same as `notify()`.
---
--- - stop([force])
---- Stop a client, optionally with force.
+--- Stops a client, optionally with force.
--- By default, it will just ask the server to shutdown without force.
--- If you request to stop a client which has previously been requested to
--- shutdown, it will automatically escalate and force shutdown.
---
--- - is_stopped()
---- Returns true if the client is fully stopped.
+--- Checks whether a client is stopped.
+--- Returns: true if the client is fully stopped.
+---
+--- - on_attach(bufnr)
+--- Runs the on_attach function from the client's config if it was defined.
---
--- - Members
---- - id (number): The id allocated to the client.
+--- - {id} (number): The id allocated to the client.
---
---- - name (string): If a name is specified on creation, that will be
+--- - {name} (string): If a name is specified on creation, that will be
--- used. Otherwise it is just the client id. This is used for
--- logs and messages.
---
---- - offset_encoding (string): The encoding used for communicating
---- with the server. You can modify this in the `on_init` method
+--- - {rpc} (table): RPC client object, for low level interaction with the
+--- client. See |vim.lsp.rpc.start()|.
+---
+--- - {offset_encoding} (string): The encoding used for communicating
+--- with the server. You can modify this in the `config`'s `on_init` method
--- before text is sent to the server.
---
---- - callbacks (table): The callbacks used by the client as
+--- - {callbacks} (table): The callbacks used by the client as
--- described in |lsp-callbacks|.
---
---- - config (table): copy of the table that was passed by the user
+--- - {config} (table): copy of the table that was passed by the user
--- to |vim.lsp.start_client()|.
---
---- - server_capabilities (table): Response from the server sent on
+--- - {server_capabilities} (table): Response from the server sent on
--- `initialize` describing the server's capabilities.
---
---- - resolved_capabilities (table): Normalized table of
+--- - {resolved_capabilities} (table): Normalized table of
--- capabilities that we have detected based on the initialize
--- response from the server in `server_capabilities`.
function lsp.client()
error()
end
+-- FIXME: Currently all methods on the `vim.lsp.client` object are documented
+-- twice: Here, and on the methods themselves (e.g. `client.request()`). This
+-- is a workaround for the vimdoc generator script not handling method names
+-- correctly. If you change the documentation on either, please make sure to
+-- update the other as well.
+
--- Starts and initializes a client with the given configuration.
---
--- Parameters `cmd` and `root_dir` are required.
---
+--- The following parameters describe fields in the {config} table.
+---
--@param root_dir: (required, string) Directory where the LSP server will base
--- its rootUri on initialization.
---
@@ -271,8 +347,8 @@ end
---
--@param callbacks Map of language server method names to
--- `function(err, method, params, client_id)` handler. Invoked for:
---- - Notifications from the server, where `err` will always be `nil`.
---- - Requests initiated by the server. For these you can respond by returning
+--- - Notifications to the server, where `err` will always be `nil`.
+--- - Requests by the server. For these you can respond by returning
--- two values: `result, err` where err must be shaped like a RPC error,
--- i.e. `{ code, message, data? }`. Use |vim.lsp.rpc_response_error()| to
--- help with this.
@@ -297,7 +373,7 @@ end
--@param before_init Callback with parameters (initialize_params, config)
--- invoked before the LSP "initialize" phase, where `params` contains the
--- parameters being sent to the server and `config` is the config that was
---- passed to `start_client()`. You can use this to modify parameters before
+--- passed to |vim.lsp.start_client()|. You can use this to modify parameters before
--- they are sent.
---
--@param on_init Callback (client, initialize_result) invoked after LSP
@@ -335,10 +411,23 @@ function lsp.start_client(config)
local handlers = {}
+ --@private
+ --- Returns the callback associated with an LSP method. Returns the default
+ --- callback if the user hasn't set a custom one.
+ ---
+ --@param method (string) LSP method name
+ --@returns (fn) The callback for the given method, if defined, or the default
+ ---from |lsp-callbacks|
local function resolve_callback(method)
return callbacks[method] or default_callbacks[method]
end
+ --@private
+ --- Handles a notification sent by an LSP server by invoking the
+ --- corresponding callback.
+ ---
+ --@param method (string) LSP method name
+ --@param params (table) The parameters for that method.
function handlers.notification(method, params)
local _ = log.debug() and log.debug('notification', method, params)
local callback = resolve_callback(method)
@@ -348,6 +437,12 @@ function lsp.start_client(config)
end
end
+ --@private
+ --- Handles a request from an LSP server by invoking the corresponding
+ --- callback.
+ ---
+ --@param method (string) LSP method name
+ --@param params (table) The parameters for that method
function handlers.server_request(method, params)
local _ = log.debug() and log.debug('server_request', method, params)
local callback = resolve_callback(method)
@@ -359,6 +454,13 @@ function lsp.start_client(config)
return nil, lsp.rpc_response_error(protocol.ErrorCodes.MethodNotFound)
end
+ --@private
+ --- Invoked when the client operation throws an error.
+ ---
+ --@param code (number) Error code
+ --@param err (...) Other arguments may be passed depending on the error kind
+ --@see |vim.lsp.client_errors| for possible errors. Use
+ ---`vim.lsp.client_errors[code]` to get a human-friendly name.
function handlers.on_error(code, err)
local _ = log.error() and log.error(log_prefix, "on_error", { code = lsp.client_errors[code], err = err })
err_message(log_prefix, ': Error ', lsp.client_errors[code], ': ', vim.inspect(err))
@@ -371,6 +473,11 @@ function lsp.start_client(config)
end
end
+ --@private
+ --- Invoked on client exit.
+ ---
+ --@param code (number) exit code of the process
+ --@param signal (number) the signal used to terminate (if any)
function handlers.on_exit(code, signal)
active_clients[client_id] = nil
uninitialized_clients[client_id] = nil
@@ -411,6 +518,7 @@ function lsp.start_client(config)
-- initialize finishes.
uninitialized_clients[client_id] = client;
+ --@private
local function initialize()
local valid_traces = {
off = 'off'; messages = 'messages'; verbose = 'verbose';
@@ -488,6 +596,12 @@ function lsp.start_client(config)
end)
end
+ --@private
+ --- Throws error for a method that is not supported by the current LSP
+ --- server.
+ ---
+ --@param method (string) an LSP method name not supported by the LSP server.
+ --@returns (error) a 'MethodNotFound' JSON-RPC error response.
local function unsupported_method(method)
local msg = "server doesn't support "..method
local _ = log.warn() and log.warn(msg)
@@ -495,8 +609,28 @@ function lsp.start_client(config)
return lsp.rpc_response_error(protocol.ErrorCodes.MethodNotFound, msg)
end
- --- Checks capabilities before rpc.request-ing.
+ --@private
+ --- Sends a request to the server.
+ ---
+ --- This is a thin wrapper around {client.rpc.request} with some additional
+ --- checks for capabilities and callback availability.
+ ---
+ --@param method (string) LSP method name.
+ --@param params (table) LSP request params.
+ --@param callback (function, optional) Response handler for this method.
+ ---If {callback} is not specified, it will use {client.callbacks} to try to
+ ---find a callback. If one is not found there, then an error will occur.
+ --@param bufnr (number) Buffer handle (0 for current).
+ --@returns ({status}, [request_id]): {status} is a bool indicating
+ ---whether the request was successful. If it is `false`, then it will
+ ---always be `false` (the client has shutdown). If it was
+ ---successful, then it will return {request_id} as the
+ ---second result. You can use this with `client.cancel_request(request_id)`
+ ---to cancel the-request.
+ --@see |vim.lsp.buf_request()|
function client.request(method, params, callback, bufnr)
+ -- FIXME: callback is optional, but bufnr is apparently not? Shouldn't that
+ -- require a `select('#', ...)` call?
if not callback then
callback = resolve_callback(method)
or error(string.format("not found: %q request callback for client %q.", method, client.name))
@@ -521,10 +655,25 @@ function lsp.start_client(config)
end)
end
+ --@private
+ --- Sends a notification to an LSP server.
+ ---
+ --@param method (string) LSP method name.
+ --@param params (optional, table) LSP request params.
+ --@param bufnr (number) Buffer handle, or 0 for current.
+ --@returns {status} (bool) true if the notification was successful.
+ ---If it is false, then it will always be false
+ ---(the client has shutdown).
function client.notify(...)
return rpc.notify(...)
end
+ --@private
+ --- Cancels a request with a given request id.
+ ---
+ --@param id (number) id of request to cancel
+ --@returns true if any client returns true; false otherwise
+ --@see |vim.lsp.client.notify()|
function client.cancel_request(id)
validate{id = {id, 'n'}}
return rpc.notify("$/cancelRequest", { id = id })
@@ -533,6 +682,14 @@ function lsp.start_client(config)
-- Track this so that we can escalate automatically if we've alredy tried a
-- graceful shutdown
local tried_graceful_shutdown = false
+ --@private
+ --- Stops a client, optionally with force.
+ ---
+ ---By default, it will just ask the - server to shutdown without force. If
+ --- you request to stop a client which has previously been requested to
+ --- shutdown, it will automatically escalate and force shutdown.
+ ---
+ --@param force (bool, optional)
function client.stop(force)
local handle = rpc.handle
if handle:is_closing() then
@@ -554,10 +711,18 @@ function lsp.start_client(config)
end)
end
+ --@private
+ --- Checks whether a client is stopped.
+ ---
+ --@returns (bool) true if client is stopped or in the process of being
+ ---stopped; false otherwise
function client.is_stopped()
return rpc.handle:is_closing()
end
+ --@private
+ --- Runs the on_attach function from the client's config if it was defined.
+ --@param bufnr (number) Buffer number
function client._on_attach(bufnr)
text_document_did_open_handler(bufnr, client)
if config.on_attach then
@@ -571,6 +736,12 @@ function lsp.start_client(config)
return client_id
end
+--@private
+--- Memoizes a function. On first run, the function return value is saved and
+--- immediately returned on subsequent runs.
+---
+--@param fn (function) Function to run
+--@returns (function) Memoized function
local function once(fn)
local value
return function(...)
@@ -579,6 +750,9 @@ local function once(fn)
end
end
+--@private
+--@fn text_document_did_change_handler(_, bufnr, changedtick, firstline, lastline, new_lastline, old_byte_size, old_utf32_size, old_utf16_size)
+--- Notify all attached clients that a buffer has changed.
local text_document_did_change_handler
do
local encoding_index = { ["utf-8"] = 1; ["utf-16"] = 2; ["utf-32"] = 3; }
@@ -735,7 +909,7 @@ end
---
--@param client_id client id number
---
---@return |vim.lsp.client| object, or nil
+--@returns |vim.lsp.client| object, or nil
function lsp.get_client_by_id(client_id)
return active_clients[client_id]
end
@@ -769,7 +943,7 @@ end
--- Gets all active clients.
---
---@return Table of |vim.lsp.client| objects
+--@returns Table of |vim.lsp.client| objects
function lsp.get_active_clients()
return vim.tbl_values(active_clients)
end
@@ -904,7 +1078,7 @@ end
--@param findstart 0 or 1, decides behavior
--@param base If findstart=0, text to match against
---
---@return (number) Decided by `findstart`:
+--@returns (number) Decided by `findstart`:
--- - findstart=0: column where the completion starts, or -2 or -3
--- - findstart=1: list of matches (actually just calls |complete()|)
function lsp.omnifunc(findstart, base)
@@ -948,6 +1122,10 @@ function lsp.omnifunc(findstart, base)
return -2
end
+---Checks whether a client is stopped.
+---
+--@param client_id (Number)
+--@returns true if client is stopped, false otherwise.
function lsp.client_is_stopped(client_id)
return active_clients[client_id] == nil
end
@@ -992,12 +1170,17 @@ function lsp.set_log_level(level)
end
--- Gets the path of the logfile used by the LSP client.
+--@returns (String) Path to logfile.
function lsp.get_log_path()
return log.get_filename()
end
--- Define the LspDiagnostics signs if they're not defined already.
+-- Defines the LspDiagnostics signs if they're not defined already.
do
+ --@private
+ --- Defines a sign if it isn't already defined.
+ --@param name (String) Name of the sign
+ --@param properties (table) Properties to attach to the sign
local function define_default_sign(name, properties)
if vim.tbl_isempty(vim.fn.sign_getdefined(name)) then
vim.fn.sign_define(name, properties)