From 3f3e4837d5f7d2d9cb1c89bd3a5b2ee8a730772a Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 16 Oct 2024 17:03:48 +0100 Subject: perf(validate): use lighter version - Also fix `vim.validate()` for PUC Lua when showing errors for values that aren't string or number. --- runtime/lua/vim/lsp.lua | 32 ++++++++++++-------------------- 1 file changed, 12 insertions(+), 20 deletions(-) (limited to 'runtime/lua/vim/lsp.lua') diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index 60677554ce..8a0eef418d 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -86,7 +86,7 @@ lsp._request_name_to_capability = { ---@param bufnr (integer|nil) Buffer number to resolve. Defaults to current buffer ---@return integer bufnr local function resolve_bufnr(bufnr) - validate({ bufnr = { bufnr, 'n', true } }) + validate('bufnr', bufnr, 'number', true) if bufnr == nil or bufnr == 0 then return api.nvim_get_current_buf() end @@ -630,10 +630,8 @@ end ---@param client_id (integer) Client id ---@return boolean success `true` if client was attached successfully; `false` otherwise function lsp.buf_attach_client(bufnr, client_id) - validate({ - bufnr = { bufnr, 'n', true }, - client_id = { client_id, 'n' }, - }) + validate('bufnr', bufnr, 'number', true) + validate('client_id', client_id, 'number') bufnr = resolve_bufnr(bufnr) if not api.nvim_buf_is_loaded(bufnr) then log.warn(string.format('buf_attach_client called on unloaded buffer (id: %d): ', bufnr)) @@ -669,10 +667,8 @@ end ---@param bufnr integer Buffer handle, or 0 for current ---@param client_id integer Client id function lsp.buf_detach_client(bufnr, client_id) - validate({ - bufnr = { bufnr, 'n', true }, - client_id = { client_id, 'n' }, - }) + validate('bufnr', bufnr, 'number', true) + validate('client_id', client_id, 'number') bufnr = resolve_bufnr(bufnr) local client = all_clients[client_id] @@ -773,7 +769,7 @@ end ---@param filter? vim.lsp.get_clients.Filter ---@return vim.lsp.Client[]: List of |vim.lsp.Client| objects function lsp.get_clients(filter) - validate({ filter = { filter, 't', true } }) + validate('filter', filter, 'table', true) filter = filter or {} @@ -870,12 +866,10 @@ api.nvim_create_autocmd('VimLeavePre', { ---cancel all the requests. You could instead ---iterate all clients and call their `cancel_request()` methods. function lsp.buf_request(bufnr, method, params, handler, on_unsupported) - validate({ - bufnr = { bufnr, 'n', true }, - method = { method, 's' }, - handler = { handler, 'f', true }, - on_unsupported = { on_unsupported, 'f', true }, - }) + validate('bufnr', bufnr, 'number', true) + validate('method', method, 'string') + validate('handler', handler, 'function', true) + validate('on_unsupported', on_unsupported, 'function', true) bufnr = resolve_bufnr(bufnr) local method_supported = false @@ -992,10 +986,8 @@ end --- ---@return boolean success true if any client returns true; false otherwise function lsp.buf_notify(bufnr, method, params) - validate({ - bufnr = { bufnr, 'n', true }, - method = { method, 's' }, - }) + validate('bufnr', bufnr, 'number', true) + validate('method', method, 'string') local resp = false for _, client in ipairs(lsp.get_clients({ bufnr = bufnr })) do if client.rpc.notify(method, params) then -- cgit From 3a86b60032bd659c2b12e984abb40cee93568558 Mon Sep 17 00:00:00 2001 From: dundargoc Date: Sun, 29 Sep 2024 14:07:21 +0200 Subject: docs: misc Co-authored-by: David Pedersen Co-authored-by: Gregory Anders Co-authored-by: Leo Schlosser Co-authored-by: zeertzjq --- runtime/lua/vim/lsp.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'runtime/lua/vim/lsp.lua') diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index 8a0eef418d..76658b7012 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -235,9 +235,9 @@ end --- - `name` arbitrary name for the LSP client. Should be unique per language server. --- - `cmd` command string[] or function, described at |vim.lsp.start_client()|. --- - `root_dir` path to the project root. By default this is used to decide if an existing client ---- should be re-used. The example above uses |vim.fs.root()| and |vim.fs.dirname()| to detect ---- the root by traversing the file system upwards starting from the current directory until ---- either a `pyproject.toml` or `setup.py` file is found. +--- should be re-used. The example above uses |vim.fs.root()| to detect the root by traversing +--- the file system upwards starting from the current directory until either a `pyproject.toml` +--- or `setup.py` file is found. --- - `workspace_folders` list of `{ uri:string, name: string }` tables specifying the project root --- folders used by the language server. If `nil` the property is derived from `root_dir` for --- convenience. -- cgit From 2dcbfe78fcec5f73ce061bb24b718187b9c6b134 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Thu, 24 Oct 2024 10:18:36 +0100 Subject: fix(lsp.buf): use correct offset_encoding for all requests Problem: `lsp.buf_request` send the same params to all servers and many calls to this pass PositionalParams which depends on the clients offset_encoding. This can result with incorrect params being sent to a server. Solution: `lsp.buf_request` `params` argument can now be passed as a function which takes the client as the first argument. This is used in lsp/buf.lua to construct correct params for each client request. --- runtime/lua/vim/lsp.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'runtime/lua/vim/lsp.lua') diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index 76658b7012..4f13ad5721 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -854,7 +854,7 @@ api.nvim_create_autocmd('VimLeavePre', { --- ---@param bufnr (integer) Buffer handle, or 0 for current. ---@param method (string) LSP method name ----@param params table|nil Parameters to send to the server +---@param params? table|(fun(client: vim.lsp.Client, bufnr: integer): table?) Parameters to send to the server ---@param handler? lsp.Handler See |lsp-handler| --- If nil, follows resolution strategy defined in |lsp-handler-configuration| ---@param on_unsupported? fun() @@ -879,7 +879,8 @@ function lsp.buf_request(bufnr, method, params, handler, on_unsupported) if client.supports_method(method, { bufnr = bufnr }) then method_supported = true - local request_success, request_id = client.request(method, params, handler, bufnr) + local cparams = type(params) == 'function' and params(client, bufnr) or params --[[@as table?]] + local request_success, request_id = client.request(method, cparams, handler, bufnr) -- This could only fail if the client shut down in the time since we looked -- it up and we did the request, which should be rare. if request_success then -- cgit From 25b53b593ef6f229fbec5b3dc205a7539579d13a Mon Sep 17 00:00:00 2001 From: Tristan Knight Date: Sat, 26 Oct 2024 15:38:25 +0100 Subject: refactor(lsp): drop str_byteindex/str_utfindex wrappers #30915 * deprecate old signatures * move to new str_byteindex/str_utfindex signature * use single-underscore name (double-underscore is reserved for Lua itself) --- runtime/lua/vim/lsp.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'runtime/lua/vim/lsp.lua') diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index 4f13ad5721..125238a8e9 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -1049,7 +1049,7 @@ function lsp.formatexpr(opts) if client.supports_method(ms.textDocument_rangeFormatting) then local params = util.make_formatting_params() local end_line = vim.fn.getline(end_lnum) --[[@as string]] - local end_col = util._str_utfindex_enc(end_line, nil, client.offset_encoding) + local end_col = vim.str_utfindex(end_line, client.offset_encoding) --- @cast params +lsp.DocumentRangeFormattingParams params.range = { start = { -- cgit From adf7c98d607b362dd3b25d6d0bee0d1212c472dd Mon Sep 17 00:00:00 2001 From: Gregory Anders Date: Sun, 27 Oct 2024 11:35:45 -0500 Subject: fix(lsp): compare URI instead of workspace folder name (#30962) The workspace folder name is meant to be a human-readable name which is only used in the UI. Comparing the name against root_dir is thus not a valid comparison. Instead, we should compare the workspace folder's URI against the root dir URI. --- runtime/lua/vim/lsp.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'runtime/lua/vim/lsp.lua') diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index 125238a8e9..a41a3f1585 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -189,9 +189,10 @@ local function reuse_client_default(client, config) end if config.root_dir then + local root = vim.uri_from_fname(config.root_dir) for _, dir in ipairs(client.workspace_folders or {}) do -- note: do not need to check client.root_dir since that should be client.workspace_folders[1] - if config.root_dir == dir.name then + if root == dir.uri then return true end end -- cgit From 1471dfc85964a9d95c216619d715bfe449d97c19 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Thu, 24 Oct 2024 16:44:09 +0100 Subject: refactor(lsp): buf_request_all --- runtime/lua/vim/lsp.lua | 36 +++++++++++++++--------------------- 1 file changed, 15 insertions(+), 21 deletions(-) (limited to 'runtime/lua/vim/lsp.lua') diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index 4f13ad5721..4065785c5a 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -915,35 +915,29 @@ end --- ---@param bufnr (integer) Buffer handle, or 0 for current. ---@param method (string) LSP method name ----@param params (table|nil) Parameters to send to the server ----@param handler fun(results: table) (function) +---@param params? table|(fun(client: vim.lsp.Client, bufnr: integer): table?) Parameters to send to the server +---@param handler lsp.MultiHandler (function) --- Handler called after all requests are completed. Server results are passed as --- a `client_id:result` map. ---@return function cancel Function that cancels all requests. function lsp.buf_request_all(bufnr, method, params, handler) - local results = {} --- @type table - local result_count = 0 - local expected_result_count = 0 - - local set_expected_result_count = once(function() - for _, client in ipairs(lsp.get_clients({ bufnr = bufnr })) do - if client.supports_method(method, { bufnr = bufnr }) then - expected_result_count = expected_result_count + 1 - end + local results = {} --- @type table + local remaining --- @type integer? + + local _, cancel = lsp.buf_request(bufnr, method, params, function(err, result, ctx, config) + if not remaining then + -- Calculate as late as possible in case a client is removed during the request + remaining = #lsp.get_clients({ bufnr = bufnr, method = method }) end - end) - local function _sync_handler(err, result, ctx) - results[ctx.client_id] = { error = err, result = result } - result_count = result_count + 1 - set_expected_result_count() + -- The error key is deprecated and will be removed in 0.13 + results[ctx.client_id] = { err = err, error = err, result = result } + remaining = remaining - 1 - if result_count >= expected_result_count then - handler(results) + if remaining == 0 then + handler(results, ctx, config) end - end - - local _, cancel = lsp.buf_request(bufnr, method, params, _sync_handler) + end) return cancel end -- cgit From 8260e4860b27a54a061bd8e2a9da23069993953a Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Thu, 24 Oct 2024 16:47:41 +0100 Subject: feat(lsp)!: multiple client support for vim.lsp.buf.hover() Deprecate `vim.lsp.handlers.hover` and `vim.lsp.handlers['textDocument/hover']` --- runtime/lua/vim/lsp.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'runtime/lua/vim/lsp.lua') diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index 4065785c5a..685dcae851 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -915,7 +915,9 @@ end --- ---@param bufnr (integer) Buffer handle, or 0 for current. ---@param method (string) LSP method name ----@param params? table|(fun(client: vim.lsp.Client, bufnr: integer): table?) Parameters to send to the server +---@param params? table|(fun(client: vim.lsp.Client, bufnr: integer): table?) Parameters to send to the server. +--- Can also be passed as a function that returns the params table for cases where +--- parameters are specific to the client. ---@param handler lsp.MultiHandler (function) --- Handler called after all requests are completed. Server results are passed as --- a `client_id:result` map. -- cgit From 9b357e30fdd0a575480182872331fdb87e9cc331 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Tue, 29 Oct 2024 09:36:02 +0000 Subject: feat(lsp)!: remove client-server handlers from vim.lsp.handlers - Partition the handlers in vim.lsp.handlers as: - client to server response handlers (RCS) - server to client request handlers (RSC) - server to client notification handlers (NSC) Note use string indexes instead of protocol.methods for improved typing in LuaLS (tip: use hover on RCS, RSC or NSC). --- runtime/lua/vim/lsp.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'runtime/lua/vim/lsp.lua') diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index a8ae283f64..42a0ccc3d4 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -1165,6 +1165,7 @@ function lsp.for_each_buffer_client(bufnr, fn) end end +--- @deprecated --- Function to manage overriding defaults for LSP handlers. ---@param handler (lsp.Handler) See |lsp-handler| ---@param override_config (table) Table containing the keys to override behavior of the {handler} -- cgit From 989a37a594649528f28432388c0e7e28e8be2753 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Tue, 5 Nov 2024 17:34:21 +0000 Subject: refactor(lsp): fold in dynamic_registration code into the client Problem: Capability register logic is spread across 3 files. Solution: - Consolidate (and simplify) logic into the client. - Teach client.supports_method about resolve methods --- runtime/lua/vim/lsp.lua | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'runtime/lua/vim/lsp.lua') diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index 42a0ccc3d4..0de3b4ee4d 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -3,7 +3,6 @@ local validate = vim.validate local lsp = vim._defer_require('vim.lsp', { _changetracking = ..., --- @module 'vim.lsp._changetracking' - _dynamic = ..., --- @module 'vim.lsp._dynamic' _snippet_grammar = ..., --- @module 'vim.lsp._snippet_grammar' _tagfunc = ..., --- @module 'vim.lsp._tagfunc' _watchfiles = ..., --- @module 'vim.lsp._watchfiles' @@ -31,6 +30,13 @@ local changetracking = lsp._changetracking ---@nodoc lsp.rpc_response_error = lsp.rpc.rpc_response_error +lsp._resolve_to_request = { + [ms.codeAction_resolve] = ms.textDocument_codeAction, + [ms.codeLens_resolve] = ms.textDocument_codeLens, + [ms.documentLink_resolve] = ms.textDocument_documentLink, + [ms.inlayHint_resolve] = ms.textDocument_inlayHint, +} + -- maps request name to the required server_capability in the client. lsp._request_name_to_capability = { [ms.callHierarchy_incomingCalls] = { 'callHierarchyProvider' }, -- cgit