aboutsummaryrefslogtreecommitdiff
path: root/runtime/lua/vim/lsp/buf.lua
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/lua/vim/lsp/buf.lua')
-rw-r--r--runtime/lua/vim/lsp/buf.lua154
1 files changed, 109 insertions, 45 deletions
diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua
index 2e27617997..fa62905c0a 100644
--- a/runtime/lua/vim/lsp/buf.lua
+++ b/runtime/lua/vim/lsp/buf.lua
@@ -1,31 +1,55 @@
local vim = vim
local validate = vim.validate
-local api = vim.api
local vfn = vim.fn
local util = require 'vim.lsp.util'
-local list_extend = vim.list_extend
local M = {}
+--@private
+--- Returns nil if {status} is false or nil, otherwise returns the rest of the
+--- arguments.
local function ok_or_nil(status, ...)
if not status then return end
return ...
end
+
+--@private
+--- Swallows errors.
+---
+--@param fn Function to run
+--@param ... Function arguments
+--@returns Result of `fn(...)` if there are no errors, otherwise nil.
+--- Returns nil if errors occur during {fn}, otherwise returns
local function npcall(fn, ...)
return ok_or_nil(pcall(fn, ...))
end
-local function request(method, params, callback)
+--@private
+--- Sends an async request to all active clients attached to the current
+--- buffer.
+---
+--@param method (string) LSP method name
+--@param params (optional, table) Parameters to send to the server
+--@param handler (optional, functionnil) See |lsp-handler|. Follows |lsp-handler-resolution|
+--
+--@returns 2-tuple:
+--- - Map of client-id:request-id pairs for all successful requests.
+--- - Function which can be used to cancel all the requests. You could instead
+--- iterate all clients and call their `cancel_request()` methods.
+---
+--@see |vim.lsp.buf_request()|
+local function request(method, params, handler)
validate {
method = {method, 's'};
- callback = {callback, 'f', true};
+ handler = {handler, 'f', true};
}
- return vim.lsp.buf_request(0, method, params, callback)
+ return vim.lsp.buf_request(0, method, params, handler)
end
---- Sends a notification through all clients associated with current buffer.
---
---@return `true` if server responds.
+--- Checks whether the language servers attached to the current buffer are
+--- ready.
+---
+--@returns `true` if server responds.
function M.server_ready()
return not not vim.lsp.buf_notify(0, "window/progress", {})
end
@@ -38,6 +62,7 @@ function M.hover()
end
--- Jumps to the declaration of the symbol under the cursor.
+--@note Many servers do not implement this method. Generally, see |vim.lsp.buf.definition()| instead.
---
function M.declaration()
local params = util.make_position_params()
@@ -74,6 +99,12 @@ end
--- Retrieves the completion items at the current cursor position. Can only be
--- called in Insert mode.
+---
+--@param context (context support not yet implemented) Additional information
+--- about the context in which a completion was triggered (how it was triggered,
+--- and by which trigger character, if applicable)
+---
+--@see |vim.lsp.protocol.constants.CompletionTriggerKind|
function M.completion(context)
local params = util.make_position_params()
params.context = context
@@ -82,64 +113,60 @@ end
--- Formats the current buffer.
---
---- The optional {options} table can be used to specify FormattingOptions, a
---- list of which is available at
---- https://microsoft.github.io/language-server-protocol/specification#textDocument_formatting.
+--@param options (optional, table) Can be used to specify FormattingOptions.
--- Some unspecified options will be automatically derived from the current
--- Neovim options.
+--
+--@see https://microsoft.github.io/language-server-protocol/specification#textDocument_formatting
function M.formatting(options)
local params = util.make_formatting_params(options)
return request('textDocument/formatting', params)
end
---- Perform |vim.lsp.buf.formatting()| synchronously.
+--- Performs |vim.lsp.buf.formatting()| synchronously.
---
--- Useful for running on save, to make sure buffer is formatted prior to being
---- saved. {timeout_ms} is passed on to |vim.lsp.buf_request_sync()|.
+--- saved. {timeout_ms} is passed on to |vim.lsp.buf_request_sync()|. Example:
+---
+--- <pre>
+--- vim.api.nvim_command[[autocmd BufWritePre <buffer> lua vim.lsp.buf.formatting_sync()]]
+--- </pre>
+---
+--@param options Table with valid `FormattingOptions` entries
+--@param timeout_ms (number) Request timeout
function M.formatting_sync(options, timeout_ms)
local params = util.make_formatting_params(options)
local result = vim.lsp.buf_request_sync(0, "textDocument/formatting", params, timeout_ms)
+ if not result or vim.tbl_isempty(result) then return end
+ local _, formatting_result = next(result)
+ result = formatting_result.result
if not result then return end
- result = result[1].result
vim.lsp.util.apply_text_edits(result)
end
+--- Formats a given range.
+---
+--@param options Table with valid `FormattingOptions` entries.
+--@param start_pos ({number, number}, optional) mark-indexed position.
+---Defaults to the start of the last visual selection.
+--@param start_pos ({number, number}, optional) mark-indexed position.
+---Defaults to the end of the last visual selection.
function M.range_formatting(options, start_pos, end_pos)
- validate {
- options = {options, 't', true};
- start_pos = {start_pos, 't', true};
- end_pos = {end_pos, 't', true};
- }
+ validate { options = {options, 't', true} }
local sts = vim.bo.softtabstop;
options = vim.tbl_extend('keep', options or {}, {
tabSize = (sts > 0 and sts) or (sts < 0 and vim.bo.shiftwidth) or vim.bo.tabstop;
insertSpaces = vim.bo.expandtab;
})
- local A = list_extend({}, start_pos or api.nvim_buf_get_mark(0, '<'))
- local B = list_extend({}, end_pos or api.nvim_buf_get_mark(0, '>'))
- -- convert to 0-index
- A[1] = A[1] - 1
- B[1] = B[1] - 1
- -- account for encoding.
- if A[2] > 0 then
- A = {A[1], util.character_offset(0, A[1], A[2])}
- end
- if B[2] > 0 then
- B = {B[1], util.character_offset(0, B[1], B[2])}
- end
- local params = {
- textDocument = { uri = vim.uri_from_bufnr(0) };
- range = {
- start = { line = A[1]; character = A[2]; };
- ["end"] = { line = B[1]; character = B[2]; };
- };
- options = options;
- }
+ local params = util.make_given_range_params(start_pos, end_pos)
+ params.options = options
return request('textDocument/rangeFormatting', params)
end
---- Renames all references to the symbol under the cursor. If {new_name} is not
---- provided, the user will be prompted for a new name using |input()|.
+--- Renames all references to the symbol under the cursor.
+---
+--@param new_name (string) If not provided, the user will be prompted for a new
+---name using |input()|.
function M.rename(new_name)
-- TODO(ashkan) use prepareRename
-- * result: [`Range`](#range) \| `{ range: Range, placeholder: string }` \| `null` describing the range of the string to rename and optionally a placeholder text of the string content to be renamed. If `null` is returned then it is deemed that a 'textDocument/rename' request is not valid at the given position.
@@ -152,6 +179,8 @@ end
--- Lists all the references to the symbol under the cursor in the quickfix window.
---
+--@param context (table) Context for the request
+--@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_references
function M.references(context)
validate { context = { context, 't', true } }
local params = util.make_position_params()
@@ -169,6 +198,7 @@ function M.document_symbol()
request('textDocument/documentSymbol', params)
end
+--@private
local function pick_call_hierarchy_item(call_hierarchy_items)
if not call_hierarchy_items then return end
if #call_hierarchy_items == 1 then
@@ -186,6 +216,9 @@ local function pick_call_hierarchy_item(call_hierarchy_items)
return choice
end
+--- Lists all the call sites of the symbol under the cursor in the
+--- |quickfix| window. If the symbol can resolve to multiple
+--- items, the user can pick one in the |inputlist|.
function M.incoming_calls()
local params = util.make_position_params()
request('textDocument/prepareCallHierarchy', params, function(_, _, result)
@@ -194,6 +227,9 @@ function M.incoming_calls()
end)
end
+--- Lists all the items that are called by the symbol under the
+--- cursor in the |quickfix| window. If the symbol can resolve to
+--- multiple items, the user can pick one in the |inputlist|.
function M.outgoing_calls()
local params = util.make_position_params()
request('textDocument/prepareCallHierarchy', params, function(_, _, result)
@@ -204,9 +240,11 @@ end
--- Lists all symbols in the current workspace in the quickfix window.
---
---- The list is filtered against the optional argument {query};
---- if the argument is omitted from the call, the user is prompted to enter a string on the command line.
---- An empty string means no filtering is done.
+--- The list is filtered against {query}; if the argument is omitted from the
+--- call, the user is prompted to enter a string on the command line. An empty
+--- string means no filtering is done.
+---
+--@param query (string, optional)
function M.workspace_symbol(query)
query = query or npcall(vfn.input, "Query: ")
local params = {query = query}
@@ -227,18 +265,44 @@ function M.document_highlight()
request('textDocument/documentHighlight', params)
end
+--- Removes document highlights from current buffer.
+---
function M.clear_references()
util.buf_clear_references()
end
+--- Selects a code action from the input list that is available at the current
+--- cursor position.
+--
+--@param context: (table, optional) Valid `CodeActionContext` object
+--@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_codeAction
function M.code_action(context)
validate { context = { context, 't', true } }
- context = context or { diagnostics = util.get_line_diagnostics() }
+ context = context or { diagnostics = vim.lsp.diagnostic.get_line_diagnostics() }
local params = util.make_range_params()
params.context = context
request('textDocument/codeAction', params)
end
+--- Performs |vim.lsp.buf.code_action()| for a given range.
+---
+--@param context: (table, optional) Valid `CodeActionContext` object
+--@param start_pos ({number, number}, optional) mark-indexed position.
+---Defaults to the start of the last visual selection.
+--@param end_pos ({number, number}, optional) mark-indexed position.
+---Defaults to the end of the last visual selection.
+function M.range_code_action(context, start_pos, end_pos)
+ validate { context = { context, 't', true } }
+ context = context or { diagnostics = vim.lsp.diagnostic.get_line_diagnostics() }
+ local params = util.make_given_range_params(start_pos, end_pos)
+ params.context = context
+ request('textDocument/codeAction', params)
+end
+
+--- Executes an LSP server command.
+---
+--@param command A valid `ExecuteCommandParams` object
+--@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_executeCommand
function M.execute_command(command)
validate {
command = { command.command, 's' },