2019-11-24 04:01:18 -07:00
local vim = vim
2019-11-20 15:21:57 -07:00
local validate = vim.validate
local api = vim.api
2019-11-20 16:35:18 -07:00
local vfn = vim.fn
2019-11-20 15:21:57 -07:00
local util = require ' vim.lsp.util '
2019-11-21 17:23:12 -07:00
local list_extend = vim.list_extend
2019-11-20 15:21:57 -07:00
local M = { }
local function ok_or_nil ( status , ... )
2019-11-20 17:16:36 -07:00
if not status then return end
return ...
2019-11-20 15:21:57 -07:00
end
local function npcall ( fn , ... )
2019-11-20 17:16:36 -07:00
return ok_or_nil ( pcall ( fn , ... ) )
2019-11-20 15:21:57 -07:00
end
2019-11-20 16:35:18 -07:00
local function request ( method , params , callback )
2019-11-20 17:16:36 -07:00
validate {
method = { method , ' s ' } ;
2019-11-26 06:59:40 -07:00
callback = { callback , ' f ' , true } ;
2019-11-20 17:16:36 -07:00
}
2019-11-26 06:59:40 -07:00
return vim.lsp . buf_request ( 0 , method , params , callback )
2019-11-20 16:35:18 -07:00
end
2020-07-02 04:09:17 -07:00
--- Sends a notification through all clients associated with current buffer.
--
--@return `true` if server responds.
2020-02-26 12:22:14 -07:00
function M . server_ready ( )
return not not vim.lsp . buf_notify ( 0 , " window/progress " , { } )
end
2019-11-20 16:35:18 -07:00
function M . hover ( )
2019-11-21 16:41:32 -07:00
local params = util.make_position_params ( )
2019-11-26 06:59:40 -07:00
request ( ' textDocument/hover ' , params )
2019-11-20 15:21:57 -07:00
end
function M . declaration ( )
2019-11-21 16:41:32 -07:00
local params = util.make_position_params ( )
2019-11-26 06:59:40 -07:00
request ( ' textDocument/declaration ' , params )
2019-11-20 16:35:18 -07:00
end
function M . definition ( )
2019-11-21 16:41:32 -07:00
local params = util.make_position_params ( )
2019-11-26 06:59:40 -07:00
request ( ' textDocument/definition ' , params )
2019-11-20 15:21:57 -07:00
end
function M . type_definition ( )
2019-11-21 16:41:32 -07:00
local params = util.make_position_params ( )
2019-11-26 06:59:40 -07:00
request ( ' textDocument/typeDefinition ' , params )
2019-11-20 15:21:57 -07:00
end
function M . implementation ( )
2019-11-21 16:41:32 -07:00
local params = util.make_position_params ( )
2019-11-26 06:59:40 -07:00
request ( ' textDocument/implementation ' , params )
2019-11-20 17:03:32 -07:00
end
2019-11-20 16:35:18 -07:00
function M . signature_help ( )
2019-11-21 16:41:32 -07:00
local params = util.make_position_params ( )
2019-11-26 06:59:40 -07:00
request ( ' textDocument/signatureHelp ' , params )
2019-11-20 15:21:57 -07:00
end
-- TODO(ashkan) ?
2019-11-20 16:35:18 -07:00
function M . completion ( context )
2019-11-21 16:41:32 -07:00
local params = util.make_position_params ( )
2019-11-20 17:16:36 -07:00
params.context = context
2019-11-26 06:59:40 -07:00
return request ( ' textDocument/completion ' , params )
2019-11-20 15:21:57 -07:00
end
2019-11-20 21:51:44 -07:00
function M . formatting ( options )
2020-05-05 08:23:45 -07:00
local params = util.make_formatting_params ( options )
2019-11-26 06:59:40 -07:00
return request ( ' textDocument/formatting ' , params )
2019-11-20 21:51:44 -07:00
end
2020-07-02 04:09:17 -07:00
--- 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()|.
2020-05-05 08:23:45 -07:00
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
2019-11-20 21:51:44 -07:00
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 } ;
}
2020-02-10 23:53:14 -07:00
local sts = vim.bo . softtabstop ;
2019-11-21 16:19:06 -07:00
options = vim.tbl_extend ( ' keep ' , options or { } , {
2020-02-10 23:53:14 -07:00
tabSize = ( sts > 0 and sts ) or ( sts < 0 and vim.bo . shiftwidth ) or vim.bo . tabstop ;
2019-11-26 06:59:40 -07:00
insertSpaces = vim.bo . expandtab ;
2019-11-21 16:19:06 -07:00
} )
2019-11-21 17:23:12 -07:00
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
2019-11-26 06:59:40 -07:00
A = { A [ 1 ] , util.character_offset ( 0 , A [ 1 ] , A [ 2 ] ) }
2019-11-21 17:23:12 -07:00
end
if B [ 2 ] > 0 then
2019-11-26 06:59:40 -07:00
B = { B [ 1 ] , util.character_offset ( 0 , B [ 1 ] , B [ 2 ] ) }
2019-11-21 17:23:12 -07:00
end
2019-11-20 21:51:44 -07:00
local params = {
textDocument = { uri = vim.uri_from_bufnr ( 0 ) } ;
range = {
2019-11-21 17:23:12 -07:00
start = { line = A [ 1 ] ; character = A [ 2 ] ; } ;
[ " end " ] = { line = B [ 1 ] ; character = B [ 2 ] ; } ;
2019-11-20 21:51:44 -07:00
} ;
2019-11-21 16:19:06 -07:00
options = options ;
2019-11-20 21:51:44 -07:00
}
2019-11-26 06:59:40 -07:00
return request ( ' textDocument/rangeFormatting ' , params )
2019-11-20 15:21:57 -07:00
end
2019-11-20 17:03:32 -07:00
function M . rename ( new_name )
2019-11-20 17:16:36 -07:00
-- 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.
2019-11-21 16:41:32 -07:00
local params = util.make_position_params ( )
2020-06-27 11:10:19 -07:00
new_name = new_name or npcall ( vfn.input , " New Name: " , vfn.expand ( ' <cword> ' ) )
2019-11-20 17:16:36 -07:00
if not ( new_name and # new_name > 0 ) then return end
params.newName = new_name
2019-11-26 06:59:40 -07:00
request ( ' textDocument/rename ' , params )
2019-11-20 17:03:32 -07:00
end
2019-11-24 04:01:18 -07:00
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
2019-11-26 06:59:40 -07:00
request ( ' textDocument/references ' , params )
2019-11-24 04:01:18 -07:00
end
2020-02-22 05:14:10 -07:00
function M . document_symbol ( )
local params = { textDocument = util.make_text_document_params ( ) }
request ( ' textDocument/documentSymbol ' , params )
end
2020-07-02 04:09:17 -07:00
--- 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.
2020-05-02 08:56:05 -07:00
function M . workspace_symbol ( query )
query = query or npcall ( vfn.input , " Query: " )
local params = { query = query }
request ( ' workspace/symbol ' , params )
end
2020-02-26 12:10:16 -07:00
--- 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
2020-05-15 16:18:59 -07:00
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
2019-11-20 15:21:57 -07:00
return M
2019-11-20 17:16:36 -07:00
-- vim:sw=2 ts=2 et