diff options
Diffstat (limited to 'runtime/lua/vim/lsp/buf.lua')
-rw-r--r-- | runtime/lua/vim/lsp/buf.lua | 154 |
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' }, |