diff options
| author | Lewis Russell <lewis6991@gmail.com> | 2024-11-14 11:53:20 +0000 |
|---|---|---|
| committer | Lewis Russell <me@lewisr.dev> | 2024-11-20 08:51:45 +0000 |
| commit | 454ae672aad172a299dcff7c33c5e61a3b631c90 (patch) | |
| tree | 0a7116ed6967563ca724cc3169e4ec72f40b70c0 /runtime | |
| parent | f55c842ec7eabd2e12749411babdcadba47438bc (diff) | |
| download | rneovim-454ae672aad172a299dcff7c33c5e61a3b631c90.tar.gz rneovim-454ae672aad172a299dcff7c33c5e61a3b631c90.tar.bz2 rneovim-454ae672aad172a299dcff7c33c5e61a3b631c90.zip | |
feat(lsp): deprecate non-method client functions
Deprecated:
- `client.request()` -> `client:request()`
- `client.request_sync()` -> `client:request_sync()`
- `client.notify()` -> `client:notify()`
- `client.cancel_request()` -> `client:cancel_request()`
- `client.stop()` -> `client:stop()`
- `client.is_stopped()` `client:is_stopped()`
- `client.supports_method()` -> `client:supports_method()`
- `client.on_attach()` -> `client:on_attach()`
Fixed docgen to link class fields to the full function doc.
Diffstat (limited to 'runtime')
| -rw-r--r-- | runtime/doc/deprecated.txt | 8 | ||||
| -rw-r--r-- | runtime/doc/lsp.txt | 169 | ||||
| -rw-r--r-- | runtime/doc/lua.txt | 10 | ||||
| -rw-r--r-- | runtime/doc/news.txt | 1 | ||||
| -rw-r--r-- | runtime/lua/vim/lsp.lua | 54 | ||||
| -rw-r--r-- | runtime/lua/vim/lsp/_changetracking.lua | 6 | ||||
| -rw-r--r-- | runtime/lua/vim/lsp/_tagfunc.lua | 2 | ||||
| -rw-r--r-- | runtime/lua/vim/lsp/_watchfiles.lua | 2 | ||||
| -rw-r--r-- | runtime/lua/vim/lsp/buf.lua | 30 | ||||
| -rw-r--r-- | runtime/lua/vim/lsp/client.lua | 214 | ||||
| -rw-r--r-- | runtime/lua/vim/lsp/codelens.lua | 2 | ||||
| -rw-r--r-- | runtime/lua/vim/lsp/completion.lua | 6 | ||||
| -rw-r--r-- | runtime/lua/vim/lsp/inlay_hint.lua | 4 | ||||
| -rw-r--r-- | runtime/lua/vim/lsp/semantic_tokens.lua | 8 | ||||
| -rw-r--r-- | runtime/lua/vim/lsp/util.lua | 4 |
15 files changed, 284 insertions, 236 deletions
diff --git a/runtime/doc/deprecated.txt b/runtime/doc/deprecated.txt index 5e809ad26c..d0cbfefb47 100644 --- a/runtime/doc/deprecated.txt +++ b/runtime/doc/deprecated.txt @@ -56,6 +56,14 @@ LSP No longer support client to server response handlers. Only server to client requests/notification handlers are supported. • *vim.lsp.handlers.signature_help()* Use |vim.lsp.buf.signature_help()| instead. +• `client.request()` Use |Client:request()| instead. +• `client.request_sync()` Use |Client:request_sync()| instead. +• `client.notify()` Use |Client:notify()| instead. +• `client.cancel_request()` Use |Client:cancel_request()| instead. +• `client.stop()` Use |Client:stop()| instead. +• `client.is_stopped()` Use |Client:is_stopped()| instead. +• `client.supports_method()` Use |Client:supports_method()| instead. +• `client.on_attach()` Use |Client:on_attach()| instead. ------------------------------------------------------------------------------ DEPRECATED IN 0.10 *deprecated-0.10* diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt index 64bef849fc..ae26abd34d 100644 --- a/runtime/doc/lsp.txt +++ b/runtime/doc/lsp.txt @@ -972,54 +972,24 @@ Lua module: vim.lsp.client *lsp-client* • {capabilities} (`lsp.ClientCapabilities`) The capabilities provided by the client (editor or tool) • {dynamic_capabilities} (`lsp.DynamicCapabilities`) - • {request} (`fun(method: string, params: table?, handler: lsp.Handler?, bufnr: integer?): boolean, integer?`) - Sends a request to the server. This is a thin - wrapper around {client.rpc.request} with some - additional checking. If {handler} is not - specified and if there's no respective global - handler, then an error will occur. Returns: - {status}, {client_id}?. {status} is a boolean - indicating if the notification was successful. - If it is `false`, then it will always be - `false` (the client has shutdown). If {status} - is `true`, the function returns {request_id} - as the second result. You can use this with - `client.cancel_request(request_id)` to cancel - the request. - • {request_sync} (`fun(method: string, params: table?, timeout_ms: integer?, bufnr: integer): {err: lsp.ResponseError?, result:any}?, string?`) - err # a dict - • {notify} (`fun(method: string, params: table?): boolean`) - Sends a notification to an LSP server. - Returns: a boolean to indicate if the - notification was successful. If it is false, - then it will always be false (the client has - shutdown). - • {cancel_request} (`fun(id: integer): boolean`) Cancels a - request with a given request id. Returns: same - as `notify()`. - • {stop} (`fun(force?: boolean)`) Stops a client, - optionally with force. By default, it will - just ask the server to shutdown without force. - If you request to stop a client which has - previously been requested to shutdown, it will - automatically escalate and force shutdown. - • {on_attach} (`fun(bufnr: integer)`) Runs the on_attach - function from the client's config if it was - defined. Useful for buffer-local setup. - • {supports_method} (`fun(method: string, opts?: {bufnr: integer?}): boolean`) - Checks if a client supports a given method. - Always returns true for unknown off-spec - methods. {opts} is a optional - `{bufnr?: integer}` table. Some language - server capabilities can be file specific. - • {is_stopped} (`fun(): boolean`) Checks whether a client is - stopped. Returns: true if the client is fully - stopped. + • {request} (`fun(self: vim.lsp.Client, method: string, params: table?, handler: lsp.Handler?, bufnr: integer?): boolean, integer?`) + See |Client:request()|. + • {request_sync} (`fun(self: vim.lsp.Client, method: string, params: table, timeout_ms: integer?, bufnr: integer): {err: lsp.ResponseError?, result:any}?, string?`) + See |Client:request_sync()|. + • {notify} (`fun(self: vim.lsp.Client, method: string, params: table?): boolean`) + See |Client:notify()|. + • {cancel_request} (`fun(self: vim.lsp.Client, id: integer): boolean`) + See |Client:cancel_request()|. + • {stop} (`fun(self: vim.lsp.Client, force: boolean?)`) + See |Client:stop()|. + • {is_stopped} (`fun(self: vim.lsp.Client): boolean`) See + |Client:is_stopped()|. • {exec_cmd} (`fun(self: vim.lsp.Client, command: lsp.Command, context: {bufnr?: integer}?, handler: lsp.Handler?)`) - Execute a lsp command, either via client - command function (if available) or via - workspace/executeCommand (if supported by the - server) + See |Client:exec_cmd()|. + • {on_attach} (`fun(self: vim.lsp.Client, bufnr: integer)`) + See |Client:on_attach()|. + • {supports_method} (`fun(self: vim.lsp.Client, method: string, bufnr: integer?)`) + See |Client:supports_method()|. *vim.lsp.Client.Progress* Extends: |vim.Ringbuf| @@ -1150,6 +1120,18 @@ Lua module: vim.lsp.client *lsp-client* on initialization. +Client:cancel_request({id}) *Client:cancel_request()* + Cancels a request with a given request id. + + Parameters: ~ + • {id} (`integer`) id of request to cancel + + Return: ~ + (`boolean`) status indicating if the notification was successful. + + See also: ~ + • |Client:notify()| + Client:exec_cmd({command}, {context}, {handler}) *Client:exec_cmd()* Execute a lsp command, either via client command function (if available) or via workspace/executeCommand (if supported by the server) @@ -1159,6 +1141,95 @@ Client:exec_cmd({command}, {context}, {handler}) *Client:exec_cmd()* • {context} (`{bufnr?: integer}?`) • {handler} (`lsp.Handler?`) only called if a server command +Client:is_stopped() *Client:is_stopped()* + Checks whether a client is stopped. + + Return: ~ + (`boolean`) true if client is stopped or in the process of being + stopped; false otherwise + +Client:notify({method}, {params}) *Client:notify()* + Sends a notification to an LSP server. + + Parameters: ~ + • {method} (`string`) LSP method name. + • {params} (`table?`) LSP request params. + + Return: ~ + (`boolean`) status indicating if the notification was successful. If + it is false, then the client has shutdown. + +Client:on_attach({bufnr}) *Client:on_attach()* + Runs the on_attach function from the client's config if it was defined. + Useful for buffer-local setup. + + Parameters: ~ + • {bufnr} (`integer`) Buffer number + + *Client:request()* +Client:request({method}, {params}, {handler}, {bufnr}) + Sends a request to the server. + + This is a thin wrapper around {client.rpc.request} with some additional + checks for capabilities and handler availability. + + Parameters: ~ + • {method} (`string`) LSP method name. + • {params} (`table?`) LSP request params. + • {handler} (`lsp.Handler?`) Response |lsp-handler| for this method. + • {bufnr} (`integer?`) Buffer handle. 0 for current (default). + + Return (multiple): ~ + (`boolean`) status indicates whether the request was successful. If it + is `false`, then it will always be `false` (the client has shutdown). + (`integer?`) request_id Can be used with |Client:cancel_request()|. + `nil` is request failed. + + See also: ~ + • |vim.lsp.buf_request_all()| + + *Client:request_sync()* +Client:request_sync({method}, {params}, {timeout_ms}, {bufnr}) + Sends a request to the server and synchronously waits for the response. + + This is a wrapper around |Client:request()| + + Parameters: ~ + • {method} (`string`) LSP method name. + • {params} (`table`) LSP request params. + • {timeout_ms} (`integer?`) Maximum time in milliseconds to wait for a + result. Defaults to 1000 + • {bufnr} (`integer`) Buffer handle (0 for current). + + Return (multiple): ~ + (`{err: lsp.ResponseError?, result:any}?`) `result` and `err` from the + |lsp-handler|. `nil` is the request was unsuccessful + (`string?`) err On timeout, cancel or error, where `err` is a string + describing the failure reason. + + See also: ~ + • |vim.lsp.buf_request_sync()| + +Client:stop({force}) *Client:stop()* + Stops a client, optionally with force. + + By default, it will just request the server to shutdown without force. If + you request to stop a client which has previously been requested to + shutdown, it will automatically escalate and force shutdown. + + Parameters: ~ + • {force} (`boolean?`) + +Client:supports_method({method}, {bufnr}) *Client:supports_method()* + Checks if a client supports a given method. Always returns true for + unknown off-spec methods. + + Note: Some language server capabilities can be file specific. + + Parameters: ~ + • {method} (`string`) + • {bufnr} (`integer?`) + ============================================================================== Lua module: vim.lsp.buf *lsp-buf* @@ -1599,12 +1670,12 @@ get({filter}) *vim.lsp.inlay_hint.get()* local hint = vim.lsp.inlay_hint.get({ bufnr = 0 })[1] -- 0 for current buffer local client = vim.lsp.get_client_by_id(hint.client_id) - local resp = client.request_sync('inlayHint/resolve', hint.inlay_hint, 100, 0) + local resp = client:request_sync('inlayHint/resolve', hint.inlay_hint, 100, 0) local resolved_hint = assert(resp and resp.result, resp.err) vim.lsp.util.apply_text_edits(resolved_hint.textEdits, 0, client.encoding) location = resolved_hint.label[1].location - client.request('textDocument/hover', { + client:request('textDocument/hover', { textDocument = { uri = location.uri }, position = location.range.start, }) diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt index 243c907180..4d4a51872a 100644 --- a/runtime/doc/lua.txt +++ b/runtime/doc/lua.txt @@ -1937,12 +1937,10 @@ vim.show_pos({bufnr}, {row}, {col}, {filter}) *vim.show_pos()* *vim.Ringbuf* Fields: ~ - • {clear} (`fun()`) Clear all items - • {push} (`fun(item: T)`) Adds an item, overriding the oldest item if - the buffer is full. - • {pop} (`fun(): T?`) Removes and returns the first unread item - • {peek} (`fun(): T?`) Returns the first unread item without removing - it + • {clear} (`fun()`) See |Ringbuf:clear()|. + • {push} (`fun(item: T)`) See |Ringbuf:push()|. + • {pop} (`fun(): T?`) See |Ringbuf:pop()|. + • {peek} (`fun(): T?`) See |Ringbuf:peek()|. Ringbuf:clear() *Ringbuf:clear()* diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index d19df84023..32deb85278 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -218,6 +218,7 @@ LSP • The client now supports `'utf-8'` and `'utf-32'` position encodings. • |vim.lsp.buf.hover()| now highlights hover ranges using the |hl-LspReferenceTarget| highlight group. +• Functions in |vim.lsp.Client| can now be called as methods. LUA diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index 0de3b4ee4d..c032d25cb1 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -349,17 +349,17 @@ end ---@param bufnr integer function lsp._set_defaults(client, bufnr) if - client.supports_method(ms.textDocument_definition) and is_empty_or_default(bufnr, 'tagfunc') + client:supports_method(ms.textDocument_definition) and is_empty_or_default(bufnr, 'tagfunc') then vim.bo[bufnr].tagfunc = 'v:lua.vim.lsp.tagfunc' end if - client.supports_method(ms.textDocument_completion) and is_empty_or_default(bufnr, 'omnifunc') + client:supports_method(ms.textDocument_completion) and is_empty_or_default(bufnr, 'omnifunc') then vim.bo[bufnr].omnifunc = 'v:lua.vim.lsp.omnifunc' end if - client.supports_method(ms.textDocument_rangeFormatting) + client:supports_method(ms.textDocument_rangeFormatting) and is_empty_or_default(bufnr, 'formatprg') and is_empty_or_default(bufnr, 'formatexpr') then @@ -367,14 +367,14 @@ function lsp._set_defaults(client, bufnr) end vim._with({ buf = bufnr }, function() if - client.supports_method(ms.textDocument_hover) + client:supports_method(ms.textDocument_hover) and is_empty_or_default(bufnr, 'keywordprg') and vim.fn.maparg('K', 'n', false, false) == '' then vim.keymap.set('n', 'K', vim.lsp.buf.hover, { buffer = bufnr, desc = 'vim.lsp.buf.hover()' }) end end) - if client.supports_method(ms.textDocument_diagnostic) then + if client:supports_method(ms.textDocument_diagnostic) then lsp.diagnostic._enable(bufnr) end end @@ -485,12 +485,12 @@ local function text_document_did_save_handler(bufnr) local name = api.nvim_buf_get_name(bufnr) local old_name = changetracking._get_and_set_name(client, bufnr, name) if old_name and name ~= old_name then - client.notify(ms.textDocument_didClose, { + client:notify(ms.textDocument_didClose, { textDocument = { uri = vim.uri_from_fname(old_name), }, }) - client.notify(ms.textDocument_didOpen, { + client:notify(ms.textDocument_didOpen, { textDocument = { version = 0, uri = uri, @@ -506,7 +506,7 @@ local function text_document_did_save_handler(bufnr) if type(save_capability) == 'table' and save_capability.includeText then included_text = text(bufnr) end - client.notify(ms.textDocument_didSave, { + client:notify(ms.textDocument_didSave, { textDocument = { uri = uri, }, @@ -527,10 +527,10 @@ local function buf_detach_client(bufnr, client) changetracking.reset_buf(client, bufnr) - if client.supports_method(ms.textDocument_didClose) then + if client:supports_method(ms.textDocument_didClose) then local uri = vim.uri_from_bufnr(bufnr) local params = { textDocument = { uri = uri } } - client.notify(ms.textDocument_didClose, params) + client:notify(ms.textDocument_didClose, params) end client.attached_buffers[bufnr] = nil @@ -564,12 +564,12 @@ local function buf_attach(bufnr) }, reason = protocol.TextDocumentSaveReason.Manual, ---@type integer } - if client.supports_method(ms.textDocument_willSave) then - client.notify(ms.textDocument_willSave, params) + if client:supports_method(ms.textDocument_willSave) then + client:notify(ms.textDocument_willSave, params) end - if client.supports_method(ms.textDocument_willSaveWaitUntil) then + if client:supports_method(ms.textDocument_willSaveWaitUntil) then local result, err = - client.request_sync(ms.textDocument_willSaveWaitUntil, params, 1000, ctx.buf) + client:request_sync(ms.textDocument_willSaveWaitUntil, params, 1000, ctx.buf) if result and result.result then util.apply_text_edits(result.result, ctx.buf, client.offset_encoding) elseif err then @@ -603,8 +603,8 @@ local function buf_attach(bufnr) local params = { textDocument = { uri = uri } } for _, client in ipairs(clients) do changetracking.reset_buf(client, bufnr) - if client.supports_method(ms.textDocument_didClose) then - client.notify(ms.textDocument_didClose, params) + if client:supports_method(ms.textDocument_didClose) then + client:notify(ms.textDocument_didClose, params) end end for _, client in ipairs(clients) do @@ -662,7 +662,7 @@ function lsp.buf_attach_client(bufnr, client_id) -- Send didOpen for the client if it is initialized. If it isn't initialized -- then it will send didOpen on initialize. if client.initialized then - client:_on_attach(bufnr) + client:on_attach(bufnr) end return true end @@ -740,13 +740,13 @@ function lsp.stop_client(client_id, force) for _, id in ipairs(ids) do if type(id) == 'table' then if id.stop then - id.stop(force) + id:stop(force) end else --- @cast id -vim.lsp.Client local client = all_clients[id] if client then - client.stop(force) + client:stop(force) end end end @@ -790,7 +790,7 @@ function lsp.get_clients(filter) and (filter.id == nil or client.id == filter.id) and (filter.bufnr == nil or client.attached_buffers[bufnr]) and (filter.name == nil or client.name == filter.name) - and (filter.method == nil or client.supports_method(filter.method, { bufnr = filter.bufnr })) + and (filter.method == nil or client:supports_method(filter.method, filter.bufnr)) and (filter._uninitialized or client.initialized) then clients[#clients + 1] = client @@ -812,7 +812,7 @@ api.nvim_create_autocmd('VimLeavePre', { local active_clients = lsp.get_clients() log.info('exit_handler', active_clients) for _, client in pairs(all_clients) do - client.stop() + client:stop() end local timeouts = {} --- @type table<integer,integer> @@ -847,7 +847,7 @@ api.nvim_create_autocmd('VimLeavePre', { if not vim.wait(max_timeout, check_clients_closed, poll_time) then for client_id, client in pairs(active_clients) do if timeouts[client_id] ~= nil then - client.stop(true) + client:stop(true) end end end @@ -883,11 +883,11 @@ function lsp.buf_request(bufnr, method, params, handler, on_unsupported) local clients = lsp.get_clients({ bufnr = bufnr }) local client_request_ids = {} --- @type table<integer,integer> for _, client in ipairs(clients) do - if client.supports_method(method, { bufnr = bufnr }) then + if client:supports_method(method, bufnr) then method_supported = true local cparams = type(params) == 'function' and params(client, bufnr) or params --[[@as table?]] - local request_success, request_id = client.request(method, cparams, handler, bufnr) + 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 @@ -910,7 +910,7 @@ function lsp.buf_request(bufnr, method, params, handler, on_unsupported) local function _cancel_all_requests() for client_id, request_id in pairs(client_request_ids) do local client = all_clients[client_id] - client.cancel_request(request_id) + client:cancel_request(request_id) end end @@ -1049,7 +1049,7 @@ function lsp.formatexpr(opts) end local bufnr = api.nvim_get_current_buf() for _, client in pairs(lsp.get_clients({ bufnr = bufnr })) do - if client.supports_method(ms.textDocument_rangeFormatting) then + 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 = vim.str_utfindex(end_line, client.offset_encoding) @@ -1065,7 +1065,7 @@ function lsp.formatexpr(opts) }, } local response = - client.request_sync(ms.textDocument_rangeFormatting, params, timeout_ms, bufnr) + client:request_sync(ms.textDocument_rangeFormatting, params, timeout_ms, bufnr) if response and response.result then lsp.util.apply_text_edits(response.result, bufnr, client.offset_encoding) return 0 diff --git a/runtime/lua/vim/lsp/_changetracking.lua b/runtime/lua/vim/lsp/_changetracking.lua index b2be53269f..8588502697 100644 --- a/runtime/lua/vim/lsp/_changetracking.lua +++ b/runtime/lua/vim/lsp/_changetracking.lua @@ -40,7 +40,7 @@ local M = {} --- @class vim.lsp.CTGroupState --- @field buffers table<integer,vim.lsp.CTBufferState> --- @field debounce integer debounce duration in ms ---- @field clients table<integer, table> clients using this state. {client_id, client} +--- @field clients table<integer, vim.lsp.Client> clients using this state. {client_id, client} ---@param group vim.lsp.CTGroup ---@return string @@ -273,8 +273,8 @@ local function send_changes(bufnr, sync_kind, state, buf_state) end local uri = vim.uri_from_bufnr(bufnr) for _, client in pairs(state.clients) do - if not client.is_stopped() and vim.lsp.buf_is_attached(bufnr, client.id) then - client.notify(protocol.Methods.textDocument_didChange, { + if not client:is_stopped() and vim.lsp.buf_is_attached(bufnr, client.id) then + client:notify(protocol.Methods.textDocument_didChange, { textDocument = { uri = uri, version = util.buf_versions[bufnr], diff --git a/runtime/lua/vim/lsp/_tagfunc.lua b/runtime/lua/vim/lsp/_tagfunc.lua index f75d43f373..f6ffc63824 100644 --- a/runtime/lua/vim/lsp/_tagfunc.lua +++ b/runtime/lua/vim/lsp/_tagfunc.lua @@ -59,7 +59,7 @@ local function query_definition(pattern) remaining = remaining - 1 end local params = util.make_position_params(win, client.offset_encoding) - client.request(ms.textDocument_definition, params, on_response, bufnr) + client:request(ms.textDocument_definition, params, on_response, bufnr) end vim.wait(1000, function() return remaining == 0 diff --git a/runtime/lua/vim/lsp/_watchfiles.lua b/runtime/lua/vim/lsp/_watchfiles.lua index c4cdb5aea8..248969885c 100644 --- a/runtime/lua/vim/lsp/_watchfiles.lua +++ b/runtime/lua/vim/lsp/_watchfiles.lua @@ -116,7 +116,7 @@ function M.register(reg, client_id) local params = { changes = change_queues[client_id], } - client.notify(ms.workspace_didChangeWatchedFiles, params) + client:notify(ms.workspace_didChangeWatchedFiles, params) queue_timers[client_id] = nil change_queues[client_id] = nil change_cache[client_id] = nil diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua index 6383855a30..10c0dbefdc 100644 --- a/runtime/lua/vim/lsp/buf.lua +++ b/runtime/lua/vim/lsp/buf.lua @@ -232,7 +232,7 @@ local function get_locations(method, opts) end for _, client in ipairs(clients) do local params = util.make_position_params(win, client.offset_encoding) - client.request(method, params, function(_, result) + client:request(method, params, function(_, result) on_response(_, result, client) end) end @@ -568,12 +568,14 @@ function M.format(opts) end if opts.async then + --- @param idx integer + --- @param client vim.lsp.Client local function do_format(idx, client) if not client then return end local params = set_range(client, util.make_formatting_params(opts.formatting_options)) - client.request(method, params, function(...) + client:request(method, params, function(...) local handler = client.handlers[method] or lsp.handlers[method] handler(...) do_format(next(clients, idx)) @@ -584,7 +586,7 @@ function M.format(opts) local timeout_ms = opts.timeout_ms or 1000 for _, client in pairs(clients) do local params = set_range(client, util.make_formatting_params(opts.formatting_options)) - local result, err = client.request_sync(method, params, timeout_ms, bufnr) + local result, err = client:request_sync(method, params, timeout_ms, bufnr) if result and result.result then util.apply_text_edits(result.result, bufnr, client.offset_encoding) elseif err then @@ -648,6 +650,8 @@ function M.rename(new_name, opts) )[1] end + --- @param idx integer + --- @param client? vim.lsp.Client local function try_use_client(idx, client) if not client then return @@ -659,15 +663,15 @@ function M.rename(new_name, opts) params.newName = name local handler = client.handlers[ms.textDocument_rename] or lsp.handlers[ms.textDocument_rename] - client.request(ms.textDocument_rename, params, function(...) + client:request(ms.textDocument_rename, params, function(...) handler(...) try_use_client(next(clients, idx)) end, bufnr) end - if client.supports_method(ms.textDocument_prepareRename) then + if client:supports_method(ms.textDocument_prepareRename) then local params = util.make_position_params(win, client.offset_encoding) - client.request(ms.textDocument_prepareRename, params, function(err, result) + client:request(ms.textDocument_prepareRename, params, function(err, result) if err or result == nil then if next(clients, idx) then try_use_client(next(clients, idx)) @@ -706,7 +710,7 @@ function M.rename(new_name, opts) end, bufnr) else assert( - client.supports_method(ms.textDocument_rename), + client:supports_method(ms.textDocument_rename), 'Client must support textDocument/rename' ) if new_name then @@ -781,7 +785,7 @@ function M.references(context, opts) params.context = context or { includeDeclaration = true, } - client.request(ms.textDocument_references, params, function(_, result) + client:request(ms.textDocument_references, params, function(_, result) local items = util.locations_to_items(result or {}, client.offset_encoding) vim.list_extend(all_items, items) remaining = remaining - 1 @@ -813,7 +817,7 @@ local function request_with_id(client_id, method, params, handler, bufnr) ) return end - client.request(method, params, handler, bufnr) + client:request(method, params, handler, bufnr) end --- @param item lsp.TypeHierarchyItem|lsp.CallHierarchyItem @@ -880,7 +884,7 @@ local function hierarchy(method) for _, client in ipairs(clients) do local params = util.make_position_params(win, client.offset_encoding) --- @param result lsp.CallHierarchyItem[]|lsp.TypeHierarchyItem[]? - client.request(prepare_method, params, function(err, result, ctx) + client:request(prepare_method, params, function(err, result, ctx) if err then vim.notify(err.message, vim.log.levels.WARN) elseif result then @@ -1131,8 +1135,8 @@ local function on_code_action_results(results, opts) local action = choice.action local bufnr = assert(choice.ctx.bufnr, 'Must have buffer number') - if not action.edit and client.supports_method(ms.codeAction_resolve) then - client.request(ms.codeAction_resolve, action, function(err, resolved_action) + if not action.edit and client:supports_method(ms.codeAction_resolve) then + client:request(ms.codeAction_resolve, action, function(err, resolved_action) if err then if action.command then apply_action(action, client, choice.ctx) @@ -1253,7 +1257,7 @@ function M.code_action(opts) }) end - client.request(ms.textDocument_codeAction, params, on_result, bufnr) + client:request(ms.textDocument_codeAction, params, on_result, bufnr) end end diff --git a/runtime/lua/vim/lsp/client.lua b/runtime/lua/vim/lsp/client.lua index 11ecb87507..3b79da99ea 100644 --- a/runtime/lua/vim/lsp/client.lua +++ b/runtime/lua/vim/lsp/client.lua @@ -219,70 +219,28 @@ local validate = vim.validate --- @field private registrations table<string,lsp.Registration[]> --- @field dynamic_capabilities lsp.DynamicCapabilities --- ---- Sends a request to the server. ---- This is a thin wrapper around {client.rpc.request} with some additional ---- checking. ---- If {handler} is not specified and if there's no respective global ---- handler, then an error will occur. ---- Returns: {status}, {client_id}?. {status} is a boolean indicating if ---- the notification was successful. If it is `false`, then it will always ---- be `false` (the client has shutdown). ---- If {status} is `true`, the function returns {request_id} as the second ---- result. You can use this with `client.cancel_request(request_id)` to cancel ---- the request. ---- @field request fun(method: string, params: table?, handler: lsp.Handler?, bufnr: integer?): boolean, integer? ---- ---- Sends a request to the server and synchronously waits for the response. ---- This is a wrapper around {client.request} ---- Returns: { err=err, result=result }, a dict, where `err` and `result` ---- come from the |lsp-handler|. On timeout, cancel or error, returns `(nil, ---- err)` where `err` is a string describing the failure reason. If the request ---- was unsuccessful returns `nil`. ---- @field request_sync fun(method: string, params: table?, timeout_ms: integer?, bufnr: integer): {err: lsp.ResponseError|nil, result:any}|nil, string|nil err # a dict ---- ---- Sends a notification to an LSP server. ---- Returns: a boolean to indicate if the notification was successful. If ---- it is false, then it will always be false (the client has shutdown). ---- @field notify fun(method: string, params: table?): boolean ---- ---- Cancels a request with a given request id. ---- Returns: same as `notify()`. ---- @field cancel_request fun(id: integer): boolean ---- ---- Stops a client, optionally with force. ---- By default, it will just ask the server to shutdown without force. ---- If you request to stop a client which has previously been requested to ---- shutdown, it will automatically escalate and force shutdown. ---- @field stop fun(force?: boolean) ---- ---- Runs the on_attach function from the client's config if it was defined. ---- Useful for buffer-local setup. ---- @field on_attach fun(bufnr: integer) ---- --- @field private _before_init_cb? vim.lsp.client.before_init_cb --- @field private _on_attach_cbs vim.lsp.client.on_attach_cb[] --- @field private _on_init_cbs vim.lsp.client.on_init_cb[] --- @field private _on_exit_cbs vim.lsp.client.on_exit_cb[] --- @field private _on_error_cb? fun(code: integer, err: string) ---- ---- Checks if a client supports a given method. ---- Always returns true for unknown off-spec methods. ---- {opts} is a optional `{bufnr?: integer}` table. ---- Some language server capabilities can be file specific. ---- @field supports_method fun(method: string, opts?: {bufnr: integer?}): boolean ---- ---- Checks whether a client is stopped. ---- Returns: true if the client is fully stopped. ---- @field is_stopped fun(): boolean local Client = {} Client.__index = Client ---- @param cls table ---- @param meth any ---- @return function -local function method_wrapper(cls, meth) - return function(...) - return meth(cls, ...) +--- @param obj table<string,any> +--- @param cls table<string,function> +--- @param name string +local function method_wrapper(obj, cls, name) + local meth = assert(cls[name]) + obj[name] = function(...) + local arg = select(1, ...) + if arg and getmetatable(arg) == cls then + -- First argument is self, call meth directly + return meth(...) + end + vim.deprecate('client.' .. name, 'client:' .. name, '0.13') + -- First argument is not self, insert it + return meth(obj, ...) end end @@ -499,24 +457,23 @@ function Client.create(config) end, } - self.request = method_wrapper(self, Client._request) - self.request_sync = method_wrapper(self, Client._request_sync) - self.notify = method_wrapper(self, Client._notify) - self.cancel_request = method_wrapper(self, Client._cance |