diff options
Diffstat (limited to 'runtime/lua')
-rw-r--r-- | runtime/lua/vim/lsp.lua | 51 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/handlers.lua | 1 | ||||
-rw-r--r-- | runtime/lua/vim/treesitter/languagetree.lua | 18 | ||||
-rw-r--r-- | runtime/lua/vim/treesitter/query.lua | 19 |
4 files changed, 74 insertions, 15 deletions
diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index 9e05eeae89..a6f118abde 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -121,6 +121,9 @@ local active_clients = {} local all_buffer_active_clients = {} local uninitialized_clients = {} +-- Tracks all buffers attached to a client. +local all_client_active_buffers = {} + --@private --- Invokes a function for each LSP client attached to the buffer {bufnr}. --- @@ -226,6 +229,7 @@ local function validate_client_config(config) on_error = { config.on_error, "f", true }; on_exit = { config.on_exit, "f", true }; on_init = { config.on_init, "f", true }; + settings = { config.settings, "t", true }; before_init = { config.before_init, "f", true }; offset_encoding = { config.offset_encoding, "s", true }; flags = { config.flags, "t", true }; @@ -399,6 +403,10 @@ end --- --@param handlers Map of language server method names to |lsp-handler| --- +--@param settings Map with language server specific settings. These are +--- returned to the language server if requested via `workspace/configuration`. +--- Keys are case-sensitive. +--- --@param init_options Values to pass in the initialization request --- as `initializationOptions`. See `initialize` in the LSP spec. --- @@ -425,7 +433,10 @@ end --- the server may send. For example, clangd sends --- `initialize_result.offsetEncoding` if `capabilities.offsetEncoding` was --- sent to it. You can only modify the `client.offset_encoding` here before ---- any notifications are sent. +--- any notifications are sent. Most language servers expect to be sent client specified settings after +--- initialization. Neovim does not make this assumption. A +--- `workspace/didChangeConfiguration` notification should be sent +--- to the server during on_init. --- --@param on_exit Callback (code, signal, client_id) invoked on client --- exit. @@ -458,6 +469,7 @@ function lsp.start_client(config) local cmd, cmd_args, offset_encoding = cleaned_config.cmd, cleaned_config.cmd_args, cleaned_config.offset_encoding config.flags = config.flags or {} + config.settings = config.settings or {} local client_id = next_client_id() @@ -879,9 +891,7 @@ end function lsp._text_document_did_save_handler(bufnr) bufnr = resolve_bufnr(bufnr) local uri = vim.uri_from_bufnr(bufnr) - local text = once(function() - return table.concat(nvim_buf_get_lines(bufnr, 0, -1, false), '\n') - end) + local text = once(buf_get_full_text) for_each_buffer_client(bufnr, function(client, _client_id) if client.resolved_capabilities.text_document_save then local included_text @@ -924,7 +934,7 @@ function lsp.buf_attach_client(bufnr, client_id) on_lines = text_document_did_change_handler; on_detach = function() local params = { textDocument = { uri = uri; } } - for_each_buffer_client(bufnr, function(client, _client_id) + for_each_buffer_client(bufnr, function(client, _) if client.resolved_capabilities.text_document_open_close then client.notify('textDocument/didClose', params) end @@ -938,6 +948,13 @@ function lsp.buf_attach_client(bufnr, client_id) utf_sizes = true; }) end + + if not all_client_active_buffers[client_id] then + all_client_active_buffers[client_id] = {} + end + + table.insert(all_client_active_buffers[client_id], bufnr) + if buffer_client_ids[client_id] then return end -- This is our first time attaching this client to this buffer. buffer_client_ids[client_id] = true @@ -969,6 +986,19 @@ function lsp.get_client_by_id(client_id) return active_clients[client_id] or uninitialized_clients[client_id] end +--- Returns list of buffers attached to client_id. +-- +--@param client_id client id +--@returns list of buffer ids +function lsp.get_buffers_by_client_id(client_id) + local active_client_buffers = all_client_active_buffers[client_id] + if active_client_buffers then + return active_client_buffers + else + return {} + end +end + --- Stops a client(s). --- --- You can also use the `stop()` function on a |vim.lsp.client| object. @@ -986,12 +1016,23 @@ end function lsp.stop_client(client_id, force) local ids = type(client_id) == 'table' and client_id or {client_id} for _, id in ipairs(ids) do + local resolved_client_id if type(id) == 'table' and id.stop ~= nil then id.stop(force) + resolved_client_id = id.id elseif active_clients[id] then active_clients[id].stop(force) + resolved_client_id = id elseif uninitialized_clients[id] then uninitialized_clients[id].stop(true) + resolved_client_id = id + end + if resolved_client_id then + local client_buffers = lsp.get_buffers_by_client_id(resolved_client_id) + for idx = 1, #client_buffers do + lsp.diagnostic.clear(client_buffers[idx], resolved_client_id) + end + all_client_active_buffers[resolved_client_id] = nil end end end diff --git a/runtime/lua/vim/lsp/handlers.lua b/runtime/lua/vim/lsp/handlers.lua index b4a1eff316..7eac3febd9 100644 --- a/runtime/lua/vim/lsp/handlers.lua +++ b/runtime/lua/vim/lsp/handlers.lua @@ -162,6 +162,7 @@ M['workspace/configuration'] = function(err, _, params, client_id) local client = vim.lsp.get_client_by_id(client_id) if not client then err_message("LSP[id=", client_id, "] client has shut down after sending the message") + return end if err then error(vim.inspect(err)) end if not params.items then diff --git a/runtime/lua/vim/treesitter/languagetree.lua b/runtime/lua/vim/treesitter/languagetree.lua index 9c620c422c..c864fe5878 100644 --- a/runtime/lua/vim/treesitter/languagetree.lua +++ b/runtime/lua/vim/treesitter/languagetree.lua @@ -425,23 +425,21 @@ function LanguageTree:register_cbs(cbs) end end -local function region_contains(region, range) - for _, node in ipairs(region) do - local start_row, start_col, end_row, end_col = node:range() - local start_fits = start_row < range[1] or (start_row == range[1] and start_col <= range[2]) - local end_fits = end_row > range[3] or (end_row == range[3] and end_col >= range[4]) +local function tree_contains(tree, range) + local start_row, start_col, end_row, end_col = tree:root():range() + local start_fits = start_row < range[1] or (start_row == range[1] and start_col <= range[2]) + local end_fits = end_row > range[3] or (end_row == range[3] and end_col >= range[4]) - if start_fits and end_fits then - return true - end + if start_fits and end_fits then + return true end return false end function LanguageTree:contains(range) - for _, region in pairs(self._regions) do - if region_contains(region, range) then + for _, tree in pairs(self._trees) do + if tree_contains(tree, range) then return true end end diff --git a/runtime/lua/vim/treesitter/query.lua b/runtime/lua/vim/treesitter/query.lua index 5a27d740a2..e49f54681d 100644 --- a/runtime/lua/vim/treesitter/query.lua +++ b/runtime/lua/vim/treesitter/query.lua @@ -340,6 +340,19 @@ function Query:apply_directives(match, pattern, source, metadata) end end + +--- Returns the start and stop value if set else the node's range. +-- When the node's range is used, the stop is incremented by 1 +-- to make the search inclusive. +local function value_or_node_range(start, stop, node) + if start == nil and stop == nil then + local node_start, _, node_stop, _ = node:range() + return node_start, node_stop + 1 -- Make stop inclusive + end + + return start, stop +end + --- Iterates of the captures of self on a given range. -- -- @param node The node under witch the search will occur @@ -353,6 +366,9 @@ function Query:iter_captures(node, source, start, stop) if type(source) == "number" and source == 0 then source = vim.api.nvim_get_current_buf() end + + start, stop = value_or_node_range(start, stop, node) + local raw_iter = node:_rawquery(self.query, true, start, stop) local function iter() local capture, captured_node, match = raw_iter() @@ -385,6 +401,9 @@ function Query:iter_matches(node, source, start, stop) if type(source) == "number" and source == 0 then source = vim.api.nvim_get_current_buf() end + + start, stop = value_or_node_range(start, stop, node) + local raw_iter = node:_rawquery(self.query, false, start, stop) local function iter() local pattern, match = raw_iter() |