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.lua251
1 files changed, 251 insertions, 0 deletions
diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua
new file mode 100644
index 0000000000..2e27617997
--- /dev/null
+++ b/runtime/lua/vim/lsp/buf.lua
@@ -0,0 +1,251 @@
+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 = {}
+
+local function ok_or_nil(status, ...)
+ if not status then return end
+ return ...
+end
+local function npcall(fn, ...)
+ return ok_or_nil(pcall(fn, ...))
+end
+
+local function request(method, params, callback)
+ validate {
+ method = {method, 's'};
+ callback = {callback, 'f', true};
+ }
+ return vim.lsp.buf_request(0, method, params, callback)
+end
+
+--- Sends a notification through all clients associated with current buffer.
+--
+--@return `true` if server responds.
+function M.server_ready()
+ return not not vim.lsp.buf_notify(0, "window/progress", {})
+end
+
+--- Displays hover information about the symbol under the cursor in a floating
+--- window. Calling the function twice will jump into the floating window.
+function M.hover()
+ local params = util.make_position_params()
+ request('textDocument/hover', params)
+end
+
+--- Jumps to the declaration of the symbol under the cursor.
+---
+function M.declaration()
+ local params = util.make_position_params()
+ request('textDocument/declaration', params)
+end
+
+--- Jumps to the definition of the symbol under the cursor.
+---
+function M.definition()
+ local params = util.make_position_params()
+ request('textDocument/definition', params)
+end
+
+--- Jumps to the definition of the type of the symbol under the cursor.
+---
+function M.type_definition()
+ local params = util.make_position_params()
+ request('textDocument/typeDefinition', params)
+end
+
+--- Lists all the implementations for the symbol under the cursor in the
+--- quickfix window.
+function M.implementation()
+ local params = util.make_position_params()
+ request('textDocument/implementation', params)
+end
+
+--- Displays signature information about the symbol under the cursor in a
+--- floating window.
+function M.signature_help()
+ local params = util.make_position_params()
+ request('textDocument/signatureHelp', params)
+end
+
+--- Retrieves the completion items at the current cursor position. Can only be
+--- called in Insert mode.
+function M.completion(context)
+ local params = util.make_position_params()
+ params.context = context
+ return request('textDocument/completion', params)
+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.
+--- Some unspecified options will be automatically derived from the current
+--- Neovim options.
+function M.formatting(options)
+ local params = util.make_formatting_params(options)
+ return request('textDocument/formatting', params)
+end
+
+--- Perform |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()|.
+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 then return end
+ result = result[1].result
+ vim.lsp.util.apply_text_edits(result)
+end
+
+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};
+ }
+ 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;
+ }
+ 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()|.
+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.
+ local params = util.make_position_params()
+ new_name = new_name or npcall(vfn.input, "New Name: ", vfn.expand('<cword>'))
+ if not (new_name and #new_name > 0) then return end
+ params.newName = new_name
+ request('textDocument/rename', params)
+end
+
+--- Lists all the references to the symbol under the cursor in the quickfix window.
+---
+function M.references(context)
+ validate { context = { context, 't', true } }
+ local params = util.make_position_params()
+ params.context = context or {
+ includeDeclaration = true;
+ }
+ params[vim.type_idx] = vim.types.dictionary
+ request('textDocument/references', params)
+end
+
+--- Lists all symbols in the current buffer in the quickfix window.
+---
+function M.document_symbol()
+ local params = { textDocument = util.make_text_document_params() }
+ request('textDocument/documentSymbol', params)
+end
+
+local function pick_call_hierarchy_item(call_hierarchy_items)
+ if not call_hierarchy_items then return end
+ if #call_hierarchy_items == 1 then
+ return call_hierarchy_items[1]
+ end
+ local items = {}
+ for i, item in ipairs(call_hierarchy_items) do
+ local entry = item.detail or item.name
+ table.insert(items, string.format("%d. %s", i, entry))
+ end
+ local choice = vim.fn.inputlist(items)
+ if choice < 1 or choice > #items then
+ return
+ end
+ return choice
+end
+
+function M.incoming_calls()
+ local params = util.make_position_params()
+ request('textDocument/prepareCallHierarchy', params, function(_, _, result)
+ local call_hierarchy_item = pick_call_hierarchy_item(result)
+ vim.lsp.buf_request(0, 'callHierarchy/incomingCalls', { item = call_hierarchy_item })
+ end)
+end
+
+function M.outgoing_calls()
+ local params = util.make_position_params()
+ request('textDocument/prepareCallHierarchy', params, function(_, _, result)
+ local call_hierarchy_item = pick_call_hierarchy_item(result)
+ vim.lsp.buf_request(0, 'callHierarchy/outgoingCalls', { item = call_hierarchy_item })
+ end)
+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.
+function M.workspace_symbol(query)
+ query = query or npcall(vfn.input, "Query: ")
+ local params = {query = query}
+ request('workspace/symbol', params)
+end
+
+--- Send request to server to resolve document highlights for the
+--- current text document position. This request can be associated
+--- to key mapping or to events such as `CursorHold`, eg:
+---
+--- <pre>
+--- vim.api.nvim_command [[autocmd CursorHold <buffer> lua vim.lsp.buf.document_highlight()]]
+--- vim.api.nvim_command [[autocmd CursorHoldI <buffer> lua vim.lsp.buf.document_highlight()]]
+--- vim.api.nvim_command [[autocmd CursorMoved <buffer> lua vim.lsp.buf.clear_references()]]
+--- </pre>
+function M.document_highlight()
+ local params = util.make_position_params()
+ request('textDocument/documentHighlight', params)
+end
+
+function M.clear_references()
+ util.buf_clear_references()
+end
+
+function M.code_action(context)
+ validate { context = { context, 't', true } }
+ context = context or { diagnostics = util.get_line_diagnostics() }
+ local params = util.make_range_params()
+ params.context = context
+ request('textDocument/codeAction', params)
+end
+
+function M.execute_command(command)
+ validate {
+ command = { command.command, 's' },
+ arguments = { command.arguments, 't', true }
+ }
+ request('workspace/executeCommand', command)
+end
+
+return M
+-- vim:sw=2 ts=2 et