From eaa1c4737792b45ba3411bdf93f74b28c1a37bc6 Mon Sep 17 00:00:00 2001 From: Folke Lemaitre Date: Thu, 8 Jul 2021 17:40:41 +0200 Subject: backport: fix(lsp): restore diagnostics extmarks that were moved to the last edit line (#15023) --- runtime/lua/vim/lsp/diagnostic.lua | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/lsp/diagnostic.lua b/runtime/lua/vim/lsp/diagnostic.lua index c67ea0c07a..c83e29aa64 100644 --- a/runtime/lua/vim/lsp/diagnostic.lua +++ b/runtime/lua/vim/lsp/diagnostic.lua @@ -1042,16 +1042,17 @@ function M.on_publish_diagnostics(_, _, params, client_id, _, config) end -- restores the extmarks set by M.display +--- @param last number last line that was changed -- @private -local function restore_extmarks(bufnr) - local lcount = api.nvim_buf_line_count(bufnr) +local function restore_extmarks(bufnr, last) for client_id, extmarks in pairs(diagnostic_cache_extmarks[bufnr]) do local ns = M._get_diagnostic_namespace(client_id) local extmarks_current = api.nvim_buf_get_extmarks(bufnr, ns, 0, -1, {details = true}) local found = {} for _, extmark in ipairs(extmarks_current) do - -- HACK: the missing extmarks seem to still exist, but at the line after the last - if extmark[2] < lcount then + -- nvim_buf_set_lines will move any extmark to the line after the last + -- nvim_buf_set_text will move any extmark to the last line + if extmark[2] ~= last + 1 then found[extmark[1]] = true end end @@ -1076,8 +1077,8 @@ local function save_extmarks(bufnr, client_id) bufnr = bufnr == 0 and api.nvim_get_current_buf() or bufnr if not diagnostic_attached_buffers[bufnr] then api.nvim_buf_attach(bufnr, false, { - on_lines = function() - restore_extmarks(bufnr) + on_lines = function(_, _, _, _, _, last) + restore_extmarks(bufnr, last - 1) end, on_detach = function() diagnostic_cache_extmarks[bufnr] = nil -- cgit From 9f73b7c214c679bd2d82d192751e70a6b6251d69 Mon Sep 17 00:00:00 2001 From: Oliver Marriott Date: Sun, 11 Jul 2021 04:11:33 +1000 Subject: backport: fix(lsp): correctly check for windows in lsp logger (#14954) --- runtime/lua/vim/lsp/log.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/lsp/log.lua b/runtime/lua/vim/lsp/log.lua index 471a311c16..73fafb9715 100644 --- a/runtime/lua/vim/lsp/log.lua +++ b/runtime/lua/vim/lsp/log.lua @@ -17,7 +17,7 @@ local current_log_level = log.levels.WARN local log_date_format = "%FT%H:%M:%S%z" do - local path_sep = vim.loop.os_uname().sysname == "Windows" and "\\" or "/" + local path_sep = vim.loop.os_uname().version:match("Windows") and "\\" or "/" --@private local function path_join(...) return table.concat(vim.tbl_flatten{...}, path_sep) -- cgit From 33000bd9cff3efe54c4ca14756008300d18ac07b Mon Sep 17 00:00:00 2001 From: Mathias Fussenegger Date: Sun, 11 Jul 2021 10:47:47 +0200 Subject: backport: fix(lsp): Ensure users get feedback on references/symbols errors or empty results Relates to https://github.com/neovim/neovim/issues/15050 Users should get some indication if there was an error or an empty result. --- runtime/lua/vim/lsp/handlers.lua | 45 +++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 19 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/lsp/handlers.lua b/runtime/lua/vim/lsp/handlers.lua index 41852b9d88..4266134fe6 100644 --- a/runtime/lua/vim/lsp/handlers.lua +++ b/runtime/lua/vim/lsp/handlers.lua @@ -191,30 +191,37 @@ M['textDocument/codeLens'] = function(...) return require('vim.lsp.codelens').on_codelens(...) end ---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_references -M['textDocument/references'] = function(_, _, result) - if not result then return end - util.set_qflist(util.locations_to_items(result)) - api.nvim_command("copen") -end ---@private ---- Prints given list of symbols to the quickfix list. ---@param _ (not used) ---@param _ (not used) ---@param result (list of Symbols) LSP method name ---@param result (table) result of LSP method; a location or a list of locations. ----(`textDocument/definition` can return `Location` or `Location[]` -local symbol_handler = function(_, _, result, _, bufnr) - if not result or vim.tbl_isempty(result) then return end - util.set_qflist(util.symbols_to_items(result, bufnr)) - api.nvim_command("copen") +--@private +--- Return a function that converts LSP responses to quickfix items and opens the qflist +-- +--@param map_result function `((resp, bufnr) -> list)` to convert the response +--@param entity name of the resource used in a `not found` error message +local function response_to_qflist(map_result, entity) + return function(err, _, result, _, bufnr) + if err then + vim.notify(err.message, vim.log.levels.ERROR) + return + end + if not result or vim.tbl_isempty(result) then + vim.notify('No ' .. entity .. ' found') + else + util.set_qflist(map_result(result, bufnr)) + api.nvim_command("copen") + end + end end + + +--@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_references +M['textDocument/references'] = response_to_qflist(util.locations_to_items, 'references') + --@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_documentSymbol -M['textDocument/documentSymbol'] = symbol_handler +M['textDocument/documentSymbol'] = response_to_qflist(util.symbols_to_items, 'document symbols') + --@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_symbol -M['workspace/symbol'] = symbol_handler +M['workspace/symbol'] = response_to_qflist(util.symbols_to_items, 'symbols') --@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_rename M['textDocument/rename'] = function(_, _, result) -- cgit From a265201307f6d7551518b67e16de68f5b9e2527c Mon Sep 17 00:00:00 2001 From: Mathias Fussenegger Date: Sun, 11 Jul 2021 11:22:35 +0200 Subject: backport: fix(lsp): Ensure human readable errors are printed `return err_message(tostring(err))` caused errors to be printed as `table: 0x123456789` instead of showing the error code and error message. This also removes some `if err` blocks that never got called because at the end of `handlers.lua` all the handlers are wrapped with logic that adds generic error handling. --- runtime/lua/vim/lsp/handlers.lua | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/lsp/handlers.lua b/runtime/lua/vim/lsp/handlers.lua index 4266134fe6..0c0aa0ceb6 100644 --- a/runtime/lua/vim/lsp/handlers.lua +++ b/runtime/lua/vim/lsp/handlers.lua @@ -18,10 +18,8 @@ local function err_message(...) end --@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_executeCommand -M['workspace/executeCommand'] = function(err, _) - if err then - error("Could not execute code action: "..err.message) - end +M['workspace/executeCommand'] = function() + -- Error handling is done implicitly by wrapping all handlers; see end of this file end -- @msg of type ProgressParams @@ -158,13 +156,12 @@ M['workspace/applyEdit'] = function(_, _, workspace_edit) end --@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_configuration -M['workspace/configuration'] = function(err, _, params, client_id) +M['workspace/configuration'] = function(_, _, 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 return {} end @@ -199,11 +196,7 @@ end --@param map_result function `((resp, bufnr) -> list)` to convert the response --@param entity name of the resource used in a `not found` error message local function response_to_qflist(map_result, entity) - return function(err, _, result, _, bufnr) - if err then - vim.notify(err.message, vim.log.levels.ERROR) - return - end + return function(_, _, result, _, bufnr) if not result or vim.tbl_isempty(result) then vim.notify('No ' .. entity .. ' found') else @@ -443,7 +436,12 @@ for k, fn in pairs(M) do }) if err then - return err_message(tostring(err)) + -- LSP spec: + -- interface ResponseError: + -- code: integer; + -- message: string; + -- data?: string | number | boolean | array | object | null; + return err_message(tostring(err.code) .. ': ' .. err.message) end return fn(err, method, params, client_id, bufnr, config) -- cgit From f7002337c02a3a6b73b7d1409186c864b129413d Mon Sep 17 00:00:00 2001 From: notomo Date: Thu, 26 Aug 2021 23:37:36 +0900 Subject: backport: fix(lua): verify buffer in highlight.on_yank (#15482) Resolve an issue with deferred clearing of highlight failing if the buffer is deleted before the timeout by checking whether the buffer is valid first. --- runtime/lua/vim/highlight.lua | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/highlight.lua b/runtime/lua/vim/highlight.lua index 0012dce081..ef44383f59 100644 --- a/runtime/lua/vim/highlight.lua +++ b/runtime/lua/vim/highlight.lua @@ -85,7 +85,11 @@ function highlight.on_yank(opts) highlight.range(bufnr, yank_ns, higroup, pos1, pos2, event.regtype, event.inclusive) vim.defer_fn( - function() api.nvim_buf_clear_namespace(bufnr, yank_ns, 0, -1) end, + function() + if api.nvim_buf_is_valid(bufnr) then + api.nvim_buf_clear_namespace(bufnr, yank_ns, 0, -1) + end + end, timeout ) end -- cgit From 132053c1d2bd101fb5d43b31e87073ba92c329d1 Mon Sep 17 00:00:00 2001 From: Jose Alvarez Date: Mon, 30 Aug 2021 20:46:00 +0900 Subject: backport: fix(lsp): resolve bufnr in buf_is_attached (#15523) --- runtime/lua/vim/lsp.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'runtime/lua/vim') diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index 75faf9bcc7..6575e453da 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -1150,7 +1150,7 @@ end ---@param bufnr (number) Buffer handle, or 0 for current ---@param client_id (number) the client id function lsp.buf_is_attached(bufnr, client_id) - return (all_buffer_active_clients[bufnr] or {})[client_id] == true + return (all_buffer_active_clients[resolve_bufnr(bufnr)] or {})[client_id] == true end --- Gets a client by id, or nil if the id is invalid. -- cgit