From bdf6d8733e2a954031de86e9a2d09c3b03f6641d Mon Sep 17 00:00:00 2001 From: Jason Hansen Date: Mon, 20 Feb 2023 23:24:47 -0700 Subject: fix(lsp): wrong format of bufnr and client order in error message (#22336) --- runtime/lua/vim/lsp.lua | 4 ++-- 1 file changed, 2 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 c5392ac154..0a620e1367 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -1736,8 +1736,8 @@ function lsp.buf_detach_client(bufnr, client_id) vim.notify( string.format( 'Buffer (id: %d) is not attached to client (id: %d). Cannot detach.', - client_id, - bufnr + bufnr, + client_id ) ) return -- cgit From 1803dadb209b9193ad8673b243091a4602b3a855 Mon Sep 17 00:00:00 2001 From: Raphael Date: Fri, 24 Feb 2023 19:55:50 +0800 Subject: refactor(lsp): remove deprecated code (#22389) --- runtime/lua/vim/lsp.lua | 20 -------------------- 1 file changed, 20 deletions(-) (limited to 'runtime/lua/vim/lsp.lua') diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index 0a620e1367..206c7c9b7e 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -1294,26 +1294,6 @@ function lsp.start_client(config) client.server_capabilities = assert(result.capabilities, "initialize result doesn't contain capabilities") client.server_capabilities = protocol.resolve_capabilities(client.server_capabilities) - - -- Deprecation wrapper: this will be removed in 0.8 - local mt = {} - mt.__index = function(table, key) - if key == 'resolved_capabilities' then - vim.notify_once( - '[LSP] Accessing client.resolved_capabilities is deprecated, ' - .. 'update your plugins or configuration to access client.server_capabilities instead.' - .. 'The new key/value pairs in server_capabilities directly match those ' - .. 'defined in the language server protocol', - vim.log.levels.WARN - ) - rawset(table, key, protocol._resolve_capabilities_compat(client.server_capabilities)) - return rawget(table, key) - else - return rawget(table, key) - end - end - setmetatable(client, mt) - client.supports_method = function(method) local required_capability = lsp._request_name_to_capability[method] -- if we don't know about the method, assume that the client supports it. -- cgit From c1514d7e6762ed62dee027ecc29bafd4aae2206e Mon Sep 17 00:00:00 2001 From: Mathias Fußenegger Date: Sat, 25 Feb 2023 18:47:05 +0100 Subject: fix(lsp): fix some type annotations (#22397) --- runtime/lua/vim/lsp.lua | 97 ++++++++++++++++++++++++------------------------- 1 file changed, 47 insertions(+), 50 deletions(-) (limited to 'runtime/lua/vim/lsp.lua') diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index 206c7c9b7e..d215b4c47e 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -67,7 +67,7 @@ lsp._request_name_to_capability = { ---@private --- Concatenates and writes a list of strings to the Vim error buffer. --- ----@param {...} table[] List to write to the buffer +---@param ... string List to write to the buffer local function err_message(...) nvim_err_writeln(table.concat(vim.tbl_flatten({ ... }))) nvim_command('redraw') @@ -76,9 +76,8 @@ end ---@private --- Returns the buffer number for the given {bufnr}. --- ----@param bufnr (number|nil) Buffer number to resolve. Defaults to the current ----buffer if not given. ----@returns bufnr (number) Number of requested buffer +---@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 } }) if bufnr == nil or bufnr == 0 then @@ -104,7 +103,7 @@ end --- Checks whether a given path is a directory. --- ---@param filename (string) path to check ----@returns true if {filename} exists and is a directory, false otherwise +---@return boolean # true if {filename} exists and is a directory, false otherwise local function is_dir(filename) validate({ filename = { filename, 's' } }) local stat = uv.fs_stat(filename) @@ -133,7 +132,7 @@ local format_line_ending = { ---@private ---@param bufnr (number) ----@returns (string) +---@return string local function buf_get_line_ending(bufnr) return format_line_ending[nvim_buf_get_option(bufnr, 'fileformat')] or '\n' end @@ -142,7 +141,7 @@ local client_index = 0 ---@private --- Returns a new, unused client id. --- ----@returns (number) client id +---@return integer client_id local function next_client_id() client_index = client_index + 1 return client_index @@ -197,7 +196,7 @@ lsp.client_errors = tbl_extend( --- Normalizes {encoding} to valid LSP encoding names. --- ---@param encoding (string) Encoding to normalize ----@returns (string) normalized encoding name +---@return string # normalized encoding name local function validate_encoding(encoding) validate({ encoding = { encoding, 's' }, @@ -215,9 +214,8 @@ end --- Parses a command invocation into the command itself and its args. If there --- are no arguments, an empty table is returned as the second argument. --- ----@param input (List) ----@returns (string) the command ----@returns (list of strings) its arguments +---@param input string[] +---@return string command, string[] args #the command and arguments function lsp._cmd_parts(input) validate({ cmd = { @@ -244,9 +242,9 @@ end ---@private --- Augments a validator function with support for optional (nil) values. --- ----@param fn (fun(v)) The original validator function; should return a +---@param fn (fun(v): boolean) The original validator function; should return a ---bool. ----@returns (fun(v)) The augmented function. Also returns true if {v} is +---@return fun(v): boolean # The augmented function. Also returns true if {v} is ---`nil`. local function optional_validator(fn) return function(v) @@ -258,10 +256,8 @@ end --- Validates a client configuration as given to |vim.lsp.start_client()|. --- ---@param config (table) ----@returns (table) "Cleaned" config, containing only the command, its +---@return table config Cleaned config, containing the command, its ---arguments, and a valid encoding. ---- ----@see |vim.lsp.start_client()| local function validate_client_config(config) validate({ config = { config, 't' }, @@ -314,7 +310,7 @@ end --- Returns full text of buffer {bufnr} as a string. --- ---@param bufnr (number) Buffer handle, or 0 for current. ----@returns Buffer text as string. +---@return string # Buffer text as string. local function buf_get_full_text(bufnr) local line_ending = buf_get_line_ending(bufnr) local text = table.concat(nvim_buf_get_lines(bufnr, 0, -1, true), line_ending) @@ -331,7 +327,7 @@ end --- even if it has side effects. --- ---@param fn (function) Function to run ----@returns (function) Memoized function +---@return function fn Memoized function local function once(fn) local value local ran = false @@ -373,7 +369,7 @@ do --- @field lines string[] snapshot of buffer lines from last didChange --- @field lines_tmp string[] --- @field pending_changes table[] List of debounced changes in incremental sync mode - --- @field timer nil|userdata uv_timer + --- @field timer nil|uv.uv_timer_t uv_timer --- @field last_flush nil|number uv.hrtime of the last flush/didChange-notification --- @field needs_flush boolean true if buffer updates haven't been sent to clients/servers yet --- @field refs number how many clients are using this group @@ -648,7 +644,7 @@ do if debounce == 0 then send_changes(bufnr, group.sync_kind, state, buf_state) else - local timer = uv.new_timer() + local timer = assert(uv.new_timer(), 'Must be able to create timer') buf_state.timer = timer timer:start( debounce, @@ -1006,7 +1002,7 @@ end --- server will base its workspaceFolders, rootUri, and rootPath --- on initialization. --- ----@returns Client id. |vim.lsp.get_client_by_id()| Note: client may not be +---@return integer|nil client_id. |vim.lsp.get_client_by_id()| Note: client may not be --- fully initialized. Use `on_init` to do any actions once --- the client has been initialized. function lsp.start_client(config) @@ -1037,7 +1033,7 @@ function lsp.start_client(config) --- Returns the default handler if the user hasn't set a custom one. --- ---@param method (string) LSP method name - ---@returns (fn) The handler for the given method, if defined, or the default from |vim.lsp.handlers| + ---@return function|nil The handler for the given method, if defined, or the default from |vim.lsp.handlers| local function resolve_handler(method) return handlers[method] or default_handlers[method] end @@ -1343,11 +1339,11 @@ function lsp.start_client(config) --- This is a thin wrapper around {client.rpc.request} with some additional --- checks for capabilities and handler availability. --- - ---@param method (string) LSP method name. - ---@param params (table) LSP request params. - ---@param handler (function|nil) Response |lsp-handler| for this method. - ---@param bufnr (number) Buffer handle (0 for current). - ---@returns ({status}, [request_id]): {status} is a bool indicating + ---@param method string LSP method name. + ---@param params table LSP request params. + ---@param handler lsp-handler|nil Response |lsp-handler| for this method. + ---@param bufnr integer Buffer handle (0 for current). + ---@return boolean status, integer|nil request_id {status} is a bool indicating ---whether the request was successful. If it is `false`, then it will ---always be `false` (the client has shutdown). If it was ---successful, then it will return {request_id} as the @@ -1395,10 +1391,11 @@ function lsp.start_client(config) ---@param timeout_ms (number|nil) Maximum time in milliseconds to wait for --- a result. Defaults to 1000 ---@param bufnr (number) Buffer handle (0 for current). - ---@returns { err=err, result=result }, a dictionary, 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`. + ---@return {err: lsp.ResponseError|nil, result:any}|nil, string|nil err # a dictionary, 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`. ---@see |vim.lsp.buf_request_sync()| function client.request_sync(method, params, timeout_ms, bufnr) local request_result = nil @@ -1429,7 +1426,7 @@ function lsp.start_client(config) --- ---@param method string LSP method name. ---@param params table|nil LSP request params. - ---@returns {status} (bool) true if the notification was successful. + ---@return boolean status true if the notification was successful. ---If it is false, then it will always be false ---(the client has shutdown). function client.notify(method, params) @@ -1443,7 +1440,7 @@ function lsp.start_client(config) --- Cancels a request with a given request id. --- ---@param id (number) id of request to cancel - ---@returns true if any client returns true; false otherwise + ---@return boolean status true if notification was successful. false otherwise ---@see |vim.lsp.client.notify()| function client.cancel_request(id) validate({ id = { id, 'n' } }) @@ -1489,7 +1486,7 @@ function lsp.start_client(config) ---@private --- Checks whether a client is stopped. --- - ---@returns (bool) true if client is stopped or in the process of being + ---@return boolean # true if client is stopped or in the process of being ---stopped; false otherwise function client.is_stopped() return rpc.is_closing() @@ -1497,7 +1494,7 @@ function lsp.start_client(config) ---@private --- Runs the on_attach function from the client's config if it was defined. - ---@param bufnr (number) Buffer number + ---@param bufnr integer Buffer number function client._on_attach(bufnr) text_document_did_open_handler(bufnr, client) @@ -1771,8 +1768,8 @@ end --- Returns list of buffers attached to client_id. --- ----@param client_id number client id ----@returns list of buffer ids +---@param client_id integer client id +---@return integer[] buffers list of buffer ids function lsp.get_buffers_by_client_id(client_id) local client = lsp.get_client_by_id(client_id) return client and vim.tbl_keys(client.attached_buffers) or {} @@ -1906,7 +1903,7 @@ api.nvim_create_autocmd('VimLeavePre', { ---@param handler function|nil See |lsp-handler| --- If nil, follows resolution strategy defined in |lsp-handler-configuration| --- ----@returns 2-tuple: +---@return table, fun() 2-tuple: --- - Map of client-id:request-id pairs for all successful requests. --- - Function which can be used to cancel all the requests. You could instead --- iterate all clients and call their `cancel_request()` methods. @@ -1964,10 +1961,10 @@ end ---@param method (string) LSP method name ---@param params (table|nil) Parameters to send to the server ---@param callback (function) The callback to call when all requests are finished. --- Unlike `buf_request`, this will collect all the responses from each server instead of handling them. --- A map of client_id:request_result will be provided to the callback --- ----@returns (function) A function that will cancel all requests which is the same as the one returned from `buf_request`. +--- Unlike `buf_request`, this will collect all the responses from each server instead of handling them. +--- A map of client_id:request_result will be provided to the callback +--- +---@return fun() cancel A function that will cancel all requests function lsp.buf_request_all(bufnr, method, params, callback) local request_results = {} local result_count = 0 @@ -2008,9 +2005,9 @@ end ---@param timeout_ms (number|nil) Maximum time in milliseconds to wait for a --- result. Defaults to 1000 --- ----@returns Map of client_id:request_result. On timeout, cancel or error, ---- returns `(nil, err)` where `err` is a string describing the failure ---- reason. +---@return table|nil result, string|nil err Map of client_id:request_result. +--- On timeout, cancel or error, returns `(nil, err)` where `err` is a string describing +--- the failure reason. function lsp.buf_request_sync(bufnr, method, params, timeout_ms) local request_results @@ -2035,7 +2032,7 @@ end ---@param method (string) Name of the request method ---@param params (any) Arguments to send to the server --- ----@returns true if any client returns true; false otherwise +---@return boolean success true if any client returns true; false otherwise function lsp.buf_notify(bufnr, method, params) validate({ bufnr = { bufnr, 'n', true }, @@ -2172,7 +2169,7 @@ function lsp.formatexpr(opts) for _, client in pairs(lsp.get_active_clients({ bufnr = bufnr })) do if client.supports_method('textDocument/rangeFormatting') then local params = util.make_formatting_params() - local end_line = vim.fn.getline(end_lnum) + local end_line = vim.fn.getline(end_lnum) --[[@as string]] local end_col = util._str_utfindex_enc(end_line, nil, client.offset_encoding) params.range = { start = { @@ -2207,7 +2204,7 @@ end ---@param pattern string Pattern used to find a workspace symbol ---@param flags string See |tag-function| --- ----@returns A list of matching tags +---@return table[] tags A list of matching tags function lsp.tagfunc(...) return require('vim.lsp.tagfunc')(...) end @@ -2215,7 +2212,7 @@ end ---Checks whether a client is stopped. --- ---@param client_id (number) ----@returns true if client is stopped, false otherwise. +---@return boolean stopped true if client is stopped, false otherwise. function lsp.client_is_stopped(client_id) return active_clients[client_id] == nil end @@ -2262,7 +2259,7 @@ function lsp.set_log_level(level) end --- Gets the path of the logfile used by the LSP client. ----@returns (String) Path to logfile. +---@return string path to log file function lsp.get_log_path() return log.get_filename() end -- cgit From f89e3497c88f59916e3bce2e902be9b0f8bf15ba Mon Sep 17 00:00:00 2001 From: Mike Date: Mon, 27 Feb 2023 14:19:41 -0600 Subject: docs(lsp): update cmd_env description (#22438) --- 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 d215b4c47e..61a06ff7a7 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -908,11 +908,11 @@ end --- the `cmd` process. Not related to `root_dir`. --- --- - cmd_env: (table) Environment flags to pass to the LSP on ---- spawn. Can be specified using keys like a map or as a list with `k=v` ---- pairs or both. Non-string values are coerced to string. +--- spawn. Must be specified using a map-like table. +--- Non-string values are coerced to string. --- Example: ---
----                   { "PRODUCTION=true"; "TEST=123"; PORT = 8080; HOST = "0.0.0.0"; }
+---                   { PORT = 8080; HOST = "0.0.0.0"; }
 ---       
--- --- - detached: (boolean, default true) Daemonize the server process so that it runs in a -- cgit From 96d3616a531b2626e3ab9b4fa2c5dea03a927717 Mon Sep 17 00:00:00 2001 From: Jens Claes Date: Wed, 1 Mar 2023 11:35:16 +0100 Subject: fix(lsp): callHierarchy methods also require the callHierarchyProvider (#22427) --- runtime/lua/vim/lsp.lua | 2 ++ 1 file changed, 2 insertions(+) (limited to 'runtime/lua/vim/lsp.lua') diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index 61a06ff7a7..fed56ff846 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -46,6 +46,8 @@ lsp._request_name_to_capability = { ['textDocument/typeDefinition'] = { 'typeDefinitionProvider' }, ['textDocument/documentSymbol'] = { 'documentSymbolProvider' }, ['textDocument/prepareCallHierarchy'] = { 'callHierarchyProvider' }, + ['callHierarchy/incomingCalls'] = { 'callHierarchyProvider' }, + ['callHierarchy/outgoingCalls'] = { 'callHierarchyProvider' }, ['textDocument/rename'] = { 'renameProvider' }, ['textDocument/prepareRename'] = { 'renameProvider', 'prepareProvider' }, ['textDocument/codeAction'] = { 'codeActionProvider' }, -- cgit From 896d672736b32a8f4a4fa51844b44f266dcdcc6c Mon Sep 17 00:00:00 2001 From: Mathias Fußenegger Date: Wed, 1 Mar 2023 15:33:13 +0100 Subject: fix(lsp): use buffer scheme for files not stored on disk (#22407) Sending `didOpen` with a `file` scheme causes problems with some language servers because they expect the file to exist on disk. See https://github.com/microsoft/language-server-protocol/pull/1679 --- runtime/lua/vim/lsp.lua | 54 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 42 insertions(+), 12 deletions(-) (limited to 'runtime/lua/vim/lsp.lua') diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index fed56ff846..a6d550f48f 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -367,7 +367,7 @@ do --- @field offset_encoding "utf-8"|"utf-16"|"utf-32" --- --- @class CTBufferState - --- @field name string name of the buffer + --- @field uri string uri of the buffer --- @field lines string[] snapshot of buffer lines from last didChange --- @field lines_tmp string[] --- @field pending_changes table[] List of debounced changes in incremental sync mode @@ -486,8 +486,12 @@ do if buf_state then buf_state.refs = buf_state.refs + 1 else + local uri = vim.uri_from_bufnr(bufnr) + if not uv.fs_stat(api.nvim_buf_get_name(bufnr)) then + uri = uri:gsub('^file://', 'buffer://') + end buf_state = { - name = api.nvim_buf_get_name(bufnr), + uri = uri, lines = {}, lines_tmp = {}, pending_changes = {}, @@ -502,12 +506,26 @@ do end ---@private - function changetracking._get_and_set_name(client, bufnr, name) + ---@param client table + ---@param bufnr integer + ---@return string uri + function changetracking._get_uri(client, bufnr) local state = state_by_group[get_group(client)] or {} local buf_state = (state.buffers or {})[bufnr] - local old_name = buf_state.name - buf_state.name = name - return old_name + return assert(buf_state.uri, 'Must have an URI set') + end + + ---@private + ---@param client table + ---@param bufnr integer + ---@param uri string + ---@return string uri + function changetracking._get_and_set_uri(client, bufnr, uri) + local state = state_by_group[get_group(client)] or {} + local buf_state = (state.buffers or {})[bufnr] + local old_uri = buf_state.uri + buf_state.uri = uri + return old_uri end ---@private @@ -594,7 +612,7 @@ do { text = buf_get_full_text(bufnr) }, } end - local uri = vim.uri_from_bufnr(bufnr) + local uri = buf_state.uri for _, client in pairs(state.clients) do if not client.is_stopped() and lsp.buf_is_attached(bufnr, client.id) then client.notify('textDocument/didChange', { @@ -707,11 +725,14 @@ local function text_document_did_open_handler(bufnr, client) return end local filetype = nvim_buf_get_option(bufnr, 'filetype') - + local uri = vim.uri_from_bufnr(bufnr) + if not uv.fs_stat(api.nvim_buf_get_name(bufnr)) then + uri = uri:gsub('^file://', 'buffer://') + end local params = { textDocument = { version = 0, - uri = vim.uri_from_bufnr(bufnr), + uri = uri, languageId = client.config.get_language_id(bufnr, filetype), text = buf_get_full_text(bufnr), }, @@ -1560,8 +1581,13 @@ local function text_document_did_save_handler(bufnr) local text = once(buf_get_full_text) for_each_buffer_client(bufnr, function(client) 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 + local old_uri = changetracking._get_and_set_uri(client, bufnr, uri) + if old_uri and name ~= old_uri then + client.notify('textDocument/didClose', { + textDocument = { + uri = old_uri, + }, + }) client.notify('textDocument/didOpen', { textDocument = { version = 0, @@ -1664,8 +1690,12 @@ function lsp.buf_attach_client(bufnr, client_id) end) end, on_detach = function() - local params = { textDocument = { uri = uri } } for_each_buffer_client(bufnr, function(client, _) + local params = { + textDocument = { + uri = changetracking._get_uri(client, bufnr), + }, + } changetracking.reset_buf(client, bufnr) if vim.tbl_get(client.server_capabilities, 'textDocumentSync', 'openClose') then client.notify('textDocument/didClose', params) -- cgit From 014981c9006f9b96b8045e609dc27f4a84da5263 Mon Sep 17 00:00:00 2001 From: Gregory Anders <8965202+gpanders@users.noreply.github.com> Date: Wed, 1 Mar 2023 09:47:56 -0700 Subject: fix(lsp): only fire LspDetach for attached buffers (#22468) If the LSP server fails to start then the client never initializes and thus never calls its on_attach function and an LspAttach event is never fired. However, the on_exit function still fires a LspDetach event, so user autocommands that attempt to "clean up" in LspDetach may run into problems if they assume that the buffer was already attached. The solution is to only fire an LspDetach event if the buffer was already attached in the first place. --- runtime/lua/vim/lsp.lua | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'runtime/lua/vim/lsp.lua') diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index a6d550f48f..a56e141c29 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -1155,14 +1155,19 @@ function lsp.start_client(config) pcall(config.on_exit, code, signal, client_id) end + local client = active_clients[client_id] and active_clients[client_id] + or uninitialized_clients[client_id] + for bufnr, client_ids in pairs(all_buffer_active_clients) do if client_ids[client_id] then vim.schedule(function() - nvim_exec_autocmds('LspDetach', { - buffer = bufnr, - modeline = false, - data = { client_id = client_id }, - }) + if client and client.attached_buffers[bufnr] then + nvim_exec_autocmds('LspDetach', { + buffer = bufnr, + modeline = false, + data = { client_id = client_id }, + }) + end local namespace = vim.lsp.diagnostic.get_namespace(client_id) vim.diagnostic.reset(namespace, bufnr) @@ -1178,8 +1183,6 @@ function lsp.start_client(config) -- Schedule the deletion of the client object so that it exists in the execution of LspDetach -- autocommands vim.schedule(function() - local client = active_clients[client_id] and active_clients[client_id] - or uninitialized_clients[client_id] active_clients[client_id] = nil uninitialized_clients[client_id] = nil -- cgit From 706bcab75eaad2c370d61bf828531054439d3a3e Mon Sep 17 00:00:00 2001 From: Jaehwang Jung Date: Tue, 7 Mar 2023 15:17:52 +0900 Subject: docs(lsp): change type annotations from number → integer (#22510) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- runtime/lua/vim/lsp.lua | 72 ++++++++++++++++++++++++------------------------- 1 file changed, 36 insertions(+), 36 deletions(-) (limited to 'runtime/lua/vim/lsp.lua') diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index a56e141c29..9a0b3f3100 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -363,7 +363,7 @@ do --- smallest debounce interval is used and we don't group clients by different intervals. --- --- @class CTGroup - --- @field sync_kind number TextDocumentSyncKind, considers config.flags.allow_incremental_sync + --- @field sync_kind integer TextDocumentSyncKind, considers config.flags.allow_incremental_sync --- @field offset_encoding "utf-8"|"utf-16"|"utf-32" --- --- @class CTBufferState @@ -374,12 +374,12 @@ do --- @field timer nil|uv.uv_timer_t uv_timer --- @field last_flush nil|number uv.hrtime of the last flush/didChange-notification --- @field needs_flush boolean true if buffer updates haven't been sent to clients/servers yet - --- @field refs number how many clients are using this group + --- @field refs integer how many clients are using this group --- --- @class CTGroupState - --- @field buffers table - --- @field debounce number debounce duration in ms - --- @field clients table clients using this state. {client_id, client} + --- @field buffers table + --- @field debounce integer debounce duration in ms + --- @field clients table clients using this state. {client_id, client} ---@private ---@param group CTGroup @@ -568,7 +568,7 @@ do -- -- This turns the debounce into a kind of client rate limiting -- - ---@param debounce number + ---@param debounce integer ---@param buf_state CTBufferState ---@return number local function next_debounce(debounce, buf_state) @@ -585,8 +585,8 @@ do end ---@private - ---@param bufnr number - ---@param sync_kind number protocol.TextDocumentSyncKind + ---@param bufnr integer + ---@param sync_kind integer protocol.TextDocumentSyncKind ---@param state CTGroupState ---@param buf_state CTBufferState local function send_changes(bufnr, sync_kind, state, buf_state) @@ -714,7 +714,7 @@ end ---@private --- Default handler for the 'textDocument/didOpen' LSP notification. --- ----@param bufnr number Number of the buffer, or 0 for current +---@param bufnr integer Number of the buffer, or 0 for current ---@param client table Client object local function text_document_did_open_handler(bufnr, client) changetracking.init(client, bufnr) @@ -1095,7 +1095,7 @@ function lsp.start_client(config) ---@private --- Invoked when the client operation throws an error. --- - ---@param code (number) Error code + ---@param code (integer) Error code ---@param err (...) Other arguments may be passed depending on the error kind ---@see `vim.lsp.rpc.client_errors` for possible errors. Use ---`vim.lsp.rpc.client_errors[code]` to get a human-friendly name. @@ -1148,8 +1148,8 @@ function lsp.start_client(config) ---@private --- Invoked on client exit. --- - ---@param code (number) exit code of the process - ---@param signal (number) the signal used to terminate (if any) + ---@param code (integer) exit code of the process + ---@param signal (integer) the signal used to terminate (if any) function dispatch.on_exit(code, signal) if config.on_exit then pcall(config.on_exit, code, signal, client_id) @@ -1414,9 +1414,9 @@ function lsp.start_client(config) --- ---@param method (string) LSP method name. ---@param params (table) LSP request params. - ---@param timeout_ms (number|nil) Maximum time in milliseconds to wait for + ---@param timeout_ms (integer|nil) Maximum time in milliseconds to wait for --- a result. Defaults to 1000 - ---@param bufnr (number) Buffer handle (0 for current). + ---@param bufnr (integer) Buffer handle (0 for current). ---@return {err: lsp.ResponseError|nil, result:any}|nil, string|nil err # a dictionary, where --- `err` and `result` come from the |lsp-handler|. --- On timeout, cancel or error, returns `(nil, err)` where `err` is a @@ -1465,7 +1465,7 @@ function lsp.start_client(config) ---@private --- Cancels a request with a given request id. --- - ---@param id (number) id of request to cancel + ---@param id (integer) id of request to cancel ---@return boolean status true if notification was successful. false otherwise ---@see |vim.lsp.client.notify()| function client.cancel_request(id) @@ -1622,8 +1622,8 @@ end --- --- Without calling this, the server won't be notified of changes to a buffer. --- ----@param bufnr (number) Buffer handle, or 0 for current ----@param client_id (number) Client id +---@param bufnr (integer) Buffer handle, or 0 for current +---@param client_id (integer) Client id function lsp.buf_attach_client(bufnr, client_id) validate({ bufnr = { bufnr, 'n', true }, @@ -1734,8 +1734,8 @@ end --- Note: While the server is notified that the text document (buffer) --- was closed, it is still able to send notifications should it ignore this notification. --- ----@param bufnr number Buffer handle, or 0 for current ----@param client_id number Client id +---@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 }, @@ -1785,8 +1785,8 @@ end --- Checks if a buffer is attached for a particular client. --- ----@param bufnr (number) Buffer handle, or 0 for current ----@param client_id (number) the client id +---@param bufnr (integer) Buffer handle, or 0 for current +---@param client_id (integer) the client id function lsp.buf_is_attached(bufnr, client_id) return (all_buffer_active_clients[resolve_bufnr(bufnr)] or {})[client_id] == true end @@ -1794,7 +1794,7 @@ end --- Gets a client by id, or nil if the id is invalid. --- The returned client may not yet be fully initialized. --- ----@param client_id number client id +---@param client_id integer client id --- ---@returns |vim.lsp.client| object, or nil function lsp.get_client_by_id(client_id) @@ -1821,7 +1821,7 @@ end --- By default asks the server to shutdown, unless stop was requested --- already for this client, then force-shutdown is attempted. --- ----@param client_id number|table id or |vim.lsp.client| object, or list thereof +---@param client_id integer|table id or |vim.lsp.client| object, or list thereof ---@param force boolean|nil shutdown forcefully function lsp.stop_client(client_id, force) local ids = type(client_id) == 'table' and client_id or { client_id } @@ -1837,8 +1837,8 @@ function lsp.stop_client(client_id, force) end ---@class vim.lsp.get_active_clients.filter ----@field id number|nil Match clients by id ----@field bufnr number|nil match clients attached to the given buffer +---@field id integer|nil Match clients by id +---@field bufnr integer|nil match clients attached to the given buffer ---@field name string|nil match clients by name --- Get active clients. @@ -1932,7 +1932,7 @@ api.nvim_create_autocmd('VimLeavePre', { --- Sends an async request for all active clients attached to the --- buffer. --- ----@param bufnr (number) Buffer handle, or 0 for current. +---@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 function|nil See |lsp-handler| @@ -1992,7 +1992,7 @@ end ---Parameters are the same as |vim.lsp.buf_request()| but the return result and callback are ---different. --- ----@param bufnr (number) Buffer handle, or 0 for current. +---@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 callback (function) The callback to call when all requests are finished. @@ -2034,10 +2034,10 @@ end --- Parameters are the same as |vim.lsp.buf_request()| but the return result is --- different. Wait maximum of {timeout_ms} (default 1000) ms. --- ----@param bufnr (number) Buffer handle, or 0 for current. +---@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 timeout_ms (number|nil) Maximum time in milliseconds to wait for a +---@param timeout_ms (integer|nil) Maximum time in milliseconds to wait for a --- result. Defaults to 1000 --- ---@return table|nil result, string|nil err Map of client_id:request_result. @@ -2106,10 +2106,10 @@ end ---@see |complete-items| ---@see |CompleteDone| --- ----@param findstart number 0 or 1, decides behavior ----@param base number findstart=0, text to match against +---@param findstart integer 0 or 1, decides behavior +---@param base integer findstart=0, text to match against --- ----@returns (number) Decided by {findstart}: +---@returns (integer) Decided by {findstart}: --- - findstart=0: column where the completion starts, or -2 or -3 --- - findstart=1: list of matches (actually just calls |complete()|) function lsp.omnifunc(findstart, base) @@ -2246,7 +2246,7 @@ end ---Checks whether a client is stopped. --- ----@param client_id (number) +---@param client_id (integer) ---@return boolean stopped true if client is stopped, false otherwise. function lsp.client_is_stopped(client_id) return active_clients[client_id] == nil @@ -2255,7 +2255,7 @@ end --- Gets a map of client_id:client pairs for the given buffer, where each value --- is a |vim.lsp.client| object. --- ----@param bufnr (number|nil): Buffer handle, or 0 for current +---@param bufnr (integer|nil): Buffer handle, or 0 for current ---@returns (table) Table of (client_id, client) pairs ---@deprecated Use |vim.lsp.get_active_clients()| instead. function lsp.buf_get_clients(bufnr) @@ -2284,7 +2284,7 @@ lsp.log_levels = log.levels --- ---@see |vim.lsp.log_levels| --- ----@param level (number|string) the case insensitive level name or number +---@param level (integer|string) the case insensitive level name or number function lsp.set_log_level(level) if type(level) == 'string' or type(level) == 'number' then log.set_level(level) @@ -2301,7 +2301,7 @@ end --- Invokes a function for each LSP client attached to a buffer. --- ----@param bufnr number Buffer number +---@param bufnr integer Buffer number ---@param fn function Function to run on each client attached to buffer --- {bufnr}. The function takes the client, client ID, and --- buffer number as arguments. Example: -- cgit From 9ef7297ef142354ace8b1f3f277d0eee3cfdc6d4 Mon Sep 17 00:00:00 2001 From: Michal Liszcz Date: Thu, 9 Mar 2023 15:12:56 +0100 Subject: feat(lsp): overwrite omnifunc/tagfunc set by ftplugin #22267 Problem: Some built-in ftplugins set omnifunc/tagfunc/formatexpr which causes lsp.lua:set_defaults() to skip setup of defaults for those filetypes. For example the C++ ftplugin has: omnifunc=ccomplete#Complete Last set from /usr/share/nvim/runtime/ftplugin/c.vim line 30 so the changes done in #95c65a6b221fe6e1cf91e8322e7d7571dc511a71 will always be skipped for C++ files. Solution: Overwrite omnifunc/tagfunc/formatexpr options that were set by stock ftplugin. Fixes #21001 --- runtime/lua/vim/lsp.lua | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) (limited to 'runtime/lua/vim/lsp.lua') diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index 9a0b3f3100..cb77e9636f 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -1112,19 +1112,43 @@ function lsp.start_client(config) end end + ---@private + -- Determines whether the given option can be set by `set_defaults`. + local function is_empty_or_default(bufnr, option) + if vim.bo[bufnr][option] == '' then + return true + end + + local old_bufnr = vim.fn.bufnr('') + local last_set_from = vim.fn.gettext('\n\tLast set from ') + local line = vim.fn.gettext(' line ') + + vim.cmd.buffer(bufnr) + local scriptname = vim.fn + .execute('verbose set ' .. option .. '?') + :match(last_set_from .. '(.*)' .. line .. '%d+') + vim.cmd.buffer(old_bufnr) + + if not scriptname then + return false + end + local vimruntime = vim.fn.getenv('VIMRUNTIME') + return vim.startswith(vim.fn.expand(scriptname), vim.fn.expand(vimruntime)) + end + ---@private local function set_defaults(client, bufnr) local capabilities = client.server_capabilities - if capabilities.definitionProvider and vim.bo[bufnr].tagfunc == '' then + if capabilities.definitionProvider and is_empty_or_default(bufnr, 'tagfunc') then vim.bo[bufnr].tagfunc = 'v:lua.vim.lsp.tagfunc' end - if capabilities.completionProvider and vim.bo[bufnr].omnifunc == '' then + if capabilities.completionProvider and is_empty_or_default(bufnr, 'omnifunc') then vim.bo[bufnr].omnifunc = 'v:lua.vim.lsp.omnifunc' end if capabilities.documentRangeFormattingProvider - and vim.bo[bufnr].formatprg == '' - and vim.bo[bufnr].formatexpr == '' + and is_empty_or_default(bufnr, 'formatprg') + and is_empty_or_default(bufnr, 'formatexpr') then vim.bo[bufnr].formatexpr = 'v:lua.vim.lsp.formatexpr()' end -- cgit From 0ecb4d725e9e2086b045670e4c2fa8962b63d99c Mon Sep 17 00:00:00 2001 From: Jaehwang Jung Date: Fri, 10 Mar 2023 06:17:08 +0900 Subject: docs(lsp): type annotation for lsp.client (#22509) * Also fix newly found type mismatch. * Note that it generates new warnings about using @private client methods. A proper fix would be to revamp the lsp client documentation altogether. --- runtime/lua/vim/lsp.lua | 7 +++++-- 1 file changed, 5 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 cb77e9636f..c85d38a50e 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -154,6 +154,8 @@ local all_buffer_active_clients = {} local uninitialized_clients = {} ---@private +---@param bufnr? integer +---@param fn fun(client: lsp.Client, client_id: integer, bufnr: integer) local function for_each_buffer_client(bufnr, fn, restrict_client_ids) validate({ fn = { fn, 'f' }, @@ -1240,6 +1242,7 @@ function lsp.start_client(config) return end + ---@class lsp.Client local client = { id = client_id, name = name, @@ -1390,7 +1393,7 @@ function lsp.start_client(config) --- checks for capabilities and handler availability. --- ---@param method string LSP method name. - ---@param params table LSP request params. + ---@param params table|nil LSP request params. ---@param handler lsp-handler|nil Response |lsp-handler| for this method. ---@param bufnr integer Buffer handle (0 for current). ---@return boolean status, integer|nil request_id {status} is a bool indicating @@ -2087,7 +2090,7 @@ function lsp.buf_request_sync(bufnr, method, params, timeout_ms) end --- Send a notification to a server ----@param bufnr (number|nil) The number of the buffer +---@param bufnr (integer|nil) The number of the buffer ---@param method (string) Name of the request method ---@param params (any) Arguments to send to the server --- -- cgit From 236c20795eb9f11e21e0719b735ea741711acc08 Mon Sep 17 00:00:00 2001 From: Mathias Fußenegger Date: Sat, 11 Mar 2023 07:35:23 +0100 Subject: revert: "fix(lsp): use buffer scheme for files not stored on disk" (#22604) Although using `buffer://` for unsaved file buffers fixes issues with language servers like eclipse.jdt.ls or ansible-language-server, it breaks completion and signature help for clangd. A regression is worse than a fix for something else, so this reverts commit 896d672736b32a8f4a4fa51844b44f266dcdcc6c. The spec change is also still in dicussion, see https://github.com/microsoft/language-server-protocol/pull/1679#discussion_r1130704886 --- runtime/lua/vim/lsp.lua | 54 +++++++++++-------------------------------------- 1 file changed, 12 insertions(+), 42 deletions(-) (limited to 'runtime/lua/vim/lsp.lua') diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index c85d38a50e..117b32dc57 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -369,7 +369,7 @@ do --- @field offset_encoding "utf-8"|"utf-16"|"utf-32" --- --- @class CTBufferState - --- @field uri string uri of the buffer + --- @field name string name of the buffer --- @field lines string[] snapshot of buffer lines from last didChange --- @field lines_tmp string[] --- @field pending_changes table[] List of debounced changes in incremental sync mode @@ -488,12 +488,8 @@ do if buf_state then buf_state.refs = buf_state.refs + 1 else - local uri = vim.uri_from_bufnr(bufnr) - if not uv.fs_stat(api.nvim_buf_get_name(bufnr)) then - uri = uri:gsub('^file://', 'buffer://') - end buf_state = { - uri = uri, + name = api.nvim_buf_get_name(bufnr), lines = {}, lines_tmp = {}, pending_changes = {}, @@ -508,26 +504,12 @@ do end ---@private - ---@param client table - ---@param bufnr integer - ---@return string uri - function changetracking._get_uri(client, bufnr) - local state = state_by_group[get_group(client)] or {} - local buf_state = (state.buffers or {})[bufnr] - return assert(buf_state.uri, 'Must have an URI set') - end - - ---@private - ---@param client table - ---@param bufnr integer - ---@param uri string - ---@return string uri - function changetracking._get_and_set_uri(client, bufnr, uri) + function changetracking._get_and_set_name(client, bufnr, name) local state = state_by_group[get_group(client)] or {} local buf_state = (state.buffers or {})[bufnr] - local old_uri = buf_state.uri - buf_state.uri = uri - return old_uri + local old_name = buf_state.name + buf_state.name = name + return old_name end ---@private @@ -614,7 +596,7 @@ do { text = buf_get_full_text(bufnr) }, } end - local uri = buf_state.uri + local uri = vim.uri_from_bufnr(bufnr) for _, client in pairs(state.clients) do if not client.is_stopped() and lsp.buf_is_attached(bufnr, client.id) then client.notify('textDocument/didChange', { @@ -727,14 +709,11 @@ local function text_document_did_open_handler(bufnr, client) return end local filetype = nvim_buf_get_option(bufnr, 'filetype') - local uri = vim.uri_from_bufnr(bufnr) - if not uv.fs_stat(api.nvim_buf_get_name(bufnr)) then - uri = uri:gsub('^file://', 'buffer://') - end + local params = { textDocument = { version = 0, - uri = uri, + uri = vim.uri_from_bufnr(bufnr), languageId = client.config.get_language_id(bufnr, filetype), text = buf_get_full_text(bufnr), }, @@ -1611,13 +1590,8 @@ local function text_document_did_save_handler(bufnr) local text = once(buf_get_full_text) for_each_buffer_client(bufnr, function(client) local name = api.nvim_buf_get_name(bufnr) - local old_uri = changetracking._get_and_set_uri(client, bufnr, uri) - if old_uri and name ~= old_uri then - client.notify('textDocument/didClose', { - textDocument = { - uri = old_uri, - }, - }) + local old_name = changetracking._get_and_set_name(client, bufnr, name) + if old_name and name ~= old_name then client.notify('textDocument/didOpen', { textDocument = { version = 0, @@ -1720,12 +1694,8 @@ function lsp.buf_attach_client(bufnr, client_id) end) end, on_detach = function() + local params = { textDocument = { uri = uri } } for_each_buffer_client(bufnr, function(client, _) - local params = { - textDocument = { - uri = changetracking._get_uri(client, bufnr), - }, - } changetracking.reset_buf(client, bufnr) if vim.tbl_get(client.server_capabilities, 'textDocumentSync', 'openClose') then client.notify('textDocument/didClose', params) -- cgit From 23dc2a59b6e13b0dbab47c6c64ac5a55095b258b Mon Sep 17 00:00:00 2001 From: Mathias Fußenegger Date: Sat, 11 Mar 2023 14:50:14 +0100 Subject: fix(lsp): send didClose on buffer rename (#22623) Subset of https://github.com/neovim/neovim/pull/22407 that was reverted in https://github.com/neovim/neovim/pull/22604 If a buffer is renamed sending `didClose` for the old buffer helps ensure the language server doesn't keep a stale document in memory. --- runtime/lua/vim/lsp.lua | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'runtime/lua/vim/lsp.lua') diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index 117b32dc57..1896543da3 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -1,3 +1,4 @@ +---@diagnostic disable: invisible local default_handlers = require('vim.lsp.handlers') local log = require('vim.lsp.log') local lsp_rpc = require('vim.lsp.rpc') @@ -1592,6 +1593,11 @@ 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('textDocument/didClose', { + textDocument = { + uri = vim.uri_from_fname(old_name), + }, + }) client.notify('textDocument/didOpen', { textDocument = { version = 0, -- cgit From 0ce626b783dcca8eed08a2bb5a18e2c3ef931fbe Mon Sep 17 00:00:00 2001 From: Jaehwang Jung Date: Sat, 11 Mar 2023 22:50:53 +0900 Subject: docs(lsp): more precise type annotations (#22621) --- runtime/lua/vim/lsp.lua | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'runtime/lua/vim/lsp.lua') diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index 1896543da3..39665a3d4f 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -1038,7 +1038,7 @@ function lsp.start_client(config) --- Returns the default handler if the user hasn't set a custom one. --- ---@param method (string) LSP method name - ---@return function|nil The handler for the given method, if defined, or the default from |vim.lsp.handlers| + ---@return lsp-handler|nil The handler for the given method, if defined, or the default from |vim.lsp.handlers| local function resolve_handler(method) return handlers[method] or default_handlers[method] end @@ -1938,7 +1938,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 handler function|nil See |lsp-handler| +---@param handler lsp-handler|nil See |lsp-handler| --- If nil, follows resolution strategy defined in |lsp-handler-configuration| --- ---@return table, fun() 2-tuple: @@ -1998,9 +1998,10 @@ 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 callback (function) The callback to call when all requests are finished. +---@param callback fun(request_results: table) (function) +--- The callback to call when all requests are finished. --- Unlike `buf_request`, this will collect all the responses from each server instead of handling them. ---- A map of client_id:request_result will be provided to the callback +--- A map of client_id:request_result will be provided to the callback. --- ---@return fun() cancel A function that will cancel all requests function lsp.buf_request_all(bufnr, method, params, callback) @@ -2043,9 +2044,8 @@ end ---@param timeout_ms (integer|nil) Maximum time in milliseconds to wait for a --- result. Defaults to 1000 --- ----@return table|nil result, string|nil err Map of client_id:request_result. ---- On timeout, cancel or error, returns `(nil, err)` where `err` is a string describing ---- the failure reason. +---@return table|nil (table) result Map of client_id:request_result. +---@return string|nil err On timeout, cancel, or error, `err` is a string describing the failure reason, and `result` is nil. function lsp.buf_request_sync(bufnr, method, params, timeout_ms) local request_results -- cgit From 6162269fa3107b23fd18c6c6d0e3e8fb73cfb45e Mon Sep 17 00:00:00 2001 From: August Masquelier <31262046+levouh@users.noreply.github.com> Date: Fri, 17 Mar 2023 05:26:13 -0600 Subject: fix(lsp): avoid switching buffers on lsp attach (#22689) --- runtime/lua/vim/lsp.lua | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'runtime/lua/vim/lsp.lua') diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index 39665a3d4f..7e8c73ddb6 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -1101,21 +1101,21 @@ function lsp.start_client(config) return true end - local old_bufnr = vim.fn.bufnr('') local last_set_from = vim.fn.gettext('\n\tLast set from ') local line = vim.fn.gettext(' line ') + local scriptname - vim.cmd.buffer(bufnr) - local scriptname = vim.fn - .execute('verbose set ' .. option .. '?') - :match(last_set_from .. '(.*)' .. line .. '%d+') - vim.cmd.buffer(old_bufnr) + vim.api.nvim_buf_call(bufnr, function() + scriptname = vim.fn + .execute('verbose set ' .. option .. '?') + :match(last_set_from .. '(.*)' .. line .. '%d+') + end) if not scriptname then return false end - local vimruntime = vim.fn.getenv('VIMRUNTIME') - return vim.startswith(vim.fn.expand(scriptname), vim.fn.expand(vimruntime)) + + return vim.startswith(vim.fn.expand(scriptname), vim.fn.expand('$VIMRUNTIME')) end ---@private -- cgit From 999cb36c2bb64d1f93bb6f8e607e0eb26eadcd63 Mon Sep 17 00:00:00 2001 From: Michal Liszcz Date: Wed, 5 Apr 2023 14:02:08 +0200 Subject: refactor(lsp): do not parse verbose output when overwriting options (#22810) --- runtime/lua/vim/lsp.lua | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) (limited to 'runtime/lua/vim/lsp.lua') diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index 7e8c73ddb6..2d39f2d45d 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -1101,21 +1101,16 @@ function lsp.start_client(config) return true end - local last_set_from = vim.fn.gettext('\n\tLast set from ') - local line = vim.fn.gettext(' line ') - local scriptname - - vim.api.nvim_buf_call(bufnr, function() - scriptname = vim.fn - .execute('verbose set ' .. option .. '?') - :match(last_set_from .. '(.*)' .. line .. '%d+') - end) + local info = vim.api.nvim_get_option_info2(option, { buf = bufnr }) + local scriptinfo = vim.tbl_filter(function(e) + return e.sid == info.last_set_sid + end, vim.fn.getscriptinfo()) - if not scriptname then + if #scriptinfo ~= 1 then return false end - return vim.startswith(vim.fn.expand(scriptname), vim.fn.expand('$VIMRUNTIME')) + return vim.startswith(scriptinfo[1].name, vim.fn.expand('$VIMRUNTIME')) end ---@private -- cgit From bfb28b62dab756ec76a73506c2070ddf491a0cdd Mon Sep 17 00:00:00 2001 From: Gregory Anders <8965202+gpanders@users.noreply.github.com> Date: Thu, 13 Apr 2023 15:29:13 -0600 Subject: refactor: remove modelines from Lua files Now that we have builtin EditorConfig support and a formatting check in CI, these are not necessary. --- runtime/lua/vim/lsp.lua | 1 - 1 file changed, 1 deletion(-) (limited to 'runtime/lua/vim/lsp.lua') diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index 2d39f2d45d..3db3545786 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -2384,4 +2384,3 @@ lsp.commands = setmetatable({}, { }) return lsp --- vim:sw=2 ts=2 et -- cgit From 4d04feb6629cb049cb2a13ba35f0c8d3c6b67ff4 Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Fri, 14 Apr 2023 10:39:57 +0200 Subject: feat(lua): vim.tbl_contains supports general tables and predicates (#23040) * feat(lua): vim.tbl_contains supports general tables and predicates Problem: `vim.tbl_contains` only works for list-like tables (integer keys without gaps) and primitive values (in particular, not for nested tables). Solution: Rename `vim.tbl_contains` to `vim.list_contains` and add new `vim.tbl_contains` that works for general tables and optionally allows `value` to be a predicate function that is checked for every key. --- runtime/lua/vim/lsp.lua | 4 ++-- 1 file changed, 2 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 3db3545786..5c78bd7580 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -171,7 +171,7 @@ local function for_each_buffer_client(bufnr, fn, restrict_client_ids) if restrict_client_ids and #restrict_client_ids > 0 then local filtered_client_ids = {} for client_id in pairs(client_ids) do - if vim.tbl_contains(restrict_client_ids, client_id) then + if vim.list_contains(restrict_client_ids, client_id) then filtered_client_ids[client_id] = true end end @@ -2186,7 +2186,7 @@ function lsp.formatexpr(opts) opts = opts or {} local timeout_ms = opts.timeout_ms or 500 - if vim.tbl_contains({ 'i', 'R', 'ic', 'ix' }, vim.fn.mode()) then + if vim.list_contains({ 'i', 'R', 'ic', 'ix' }, vim.fn.mode()) then -- `formatexpr` is also called when exceeding `textwidth` in insert mode -- fall back to internal formatting return 1 -- cgit From 02f92978fe4f4d465260a9936dca1526bbe76931 Mon Sep 17 00:00:00 2001 From: hituzi no sippo <43565959+hituzi-no-sippo@users.noreply.github.com> Date: Wed, 10 May 2023 00:24:49 +0900 Subject: docs(lsp): fix type of `config.cmd` argument for `vim.lsp.start_client` (#23550) --- 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 5c78bd7580..b86d41b234 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -901,7 +901,7 @@ end --- Field `cmd` in {config} is required. --- ---@param config (table) Configuration for the server: ---- - cmd: (table|string|fun(dispatchers: table):table) command string or +--- - cmd: (string[]|fun(dispatchers: table):table) command string or --- list treated like |jobstart()|. The command must launch the language server --- process. `cmd` can also be a function that creates an RPC client. --- The function receives a dispatchers table and must return a table with the -- cgit From 4e5061dba765df2a74ac4a8182f6e7fe21da125d Mon Sep 17 00:00:00 2001 From: hituzi no sippo <43565959+hituzi-no-sippo@users.noreply.github.com> Date: Wed, 10 May 2023 04:00:29 +0900 Subject: docs(lsp): fix `config.cmd` argument for `vim.lsp.start_client` (#23560) --- runtime/lua/vim/lsp.lua | 4 ++-- 1 file changed, 2 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 b86d41b234..a724593188 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -901,8 +901,8 @@ end --- Field `cmd` in {config} is required. --- ---@param config (table) Configuration for the server: ---- - cmd: (string[]|fun(dispatchers: table):table) command string or ---- list treated like |jobstart()|. The command must launch the language server +--- - cmd: (string[]|fun(dispatchers: table):table) command a list of +--- strings treated like |jobstart()|. The command must launch the language server --- process. `cmd` can also be a function that creates an RPC client. --- The function receives a dispatchers table and must return a table with the --- functions `request`, `notify`, `is_closing` and `terminate` -- cgit From 08991b078267e5de0a19a136d00d4f71ad651a32 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Sat, 13 May 2023 21:33:22 +0200 Subject: docs: small fixes Co-authored-by: Christian Clason Co-authored-by: Gregory Anders Co-authored-by: HiPhish Co-authored-by: Julio B Co-authored-by: T727 <74924917+T-727@users.noreply.github.com> Co-authored-by: camoz Co-authored-by: champignoom <66909116+champignoom@users.noreply.github.com> --- 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 a724593188..92f5653158 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -913,7 +913,7 @@ end --- the `cmd` process. Not related to `root_dir`. --- --- - cmd_env: (table) Environment flags to pass to the LSP on ---- spawn. Must be specified using a map-like table. +--- spawn. Must be specified using a table. --- Non-string values are coerced to string. --- Example: ---
-- 
cgit 


From 1fe1bb084d0099fc4f9bfdc11189485d0f74b75a Mon Sep 17 00:00:00 2001
From: Lewis Russell 
Date: Mon, 19 Dec 2022 16:37:45 +0000
Subject: refactor(options): deprecate nvim[_buf|_win]_[gs]et_option

Co-authored-by: zeertzjq 
Co-authored-by: famiu 
---
 runtime/lua/vim/lsp.lua | 16 ++++++----------
 1 file changed, 6 insertions(+), 10 deletions(-)

(limited to 'runtime/lua/vim/lsp.lua')

diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua
index 92f5653158..2e6ca7a0ac 100644
--- a/runtime/lua/vim/lsp.lua
+++ b/runtime/lua/vim/lsp.lua
@@ -8,12 +8,8 @@ local sync = require('vim.lsp.sync')
 local semantic_tokens = require('vim.lsp.semantic_tokens')
 
 local api = vim.api
-local nvim_err_writeln, nvim_buf_get_lines, nvim_command, nvim_buf_get_option, nvim_exec_autocmds =
-  api.nvim_err_writeln,
-  api.nvim_buf_get_lines,
-  api.nvim_command,
-  api.nvim_buf_get_option,
-  api.nvim_exec_autocmds
+local nvim_err_writeln, nvim_buf_get_lines, nvim_command, nvim_exec_autocmds =
+  api.nvim_err_writeln, api.nvim_buf_get_lines, api.nvim_command, api.nvim_exec_autocmds
 local uv = vim.loop
 local tbl_isempty, tbl_extend = vim.tbl_isempty, vim.tbl_extend
 local validate = vim.validate
@@ -137,7 +133,7 @@ local format_line_ending = {
 ---@param bufnr (number)
 ---@return string
 local function buf_get_line_ending(bufnr)
-  return format_line_ending[nvim_buf_get_option(bufnr, 'fileformat')] or '\n'
+  return format_line_ending[vim.bo[bufnr].fileformat] or '\n'
 end
 
 local client_index = 0
@@ -319,7 +315,7 @@ end
 local function buf_get_full_text(bufnr)
   local line_ending = buf_get_line_ending(bufnr)
   local text = table.concat(nvim_buf_get_lines(bufnr, 0, -1, true), line_ending)
-  if nvim_buf_get_option(bufnr, 'eol') then
+  if vim.bo[bufnr].eol then
     text = text .. line_ending
   end
   return text
@@ -709,7 +705,7 @@ local function text_document_did_open_handler(bufnr, client)
   if not api.nvim_buf_is_loaded(bufnr) then
     return
   end
-  local filetype = nvim_buf_get_option(bufnr, 'filetype')
+  local filetype = vim.bo[bufnr].filetype
 
   local params = {
     textDocument = {
@@ -2177,7 +2173,7 @@ end
 ---
 --- Currently only supports a single client. This can be set via
 --- `setlocal formatexpr=v:lua.vim.lsp.formatexpr()` but will typically or in `on_attach`
---- via ``vim.api.nvim_buf_set_option(bufnr, 'formatexpr', 'v:lua.vim.lsp.formatexpr(#{timeout_ms:250})')``.
+--- via ``vim.bo[bufnr].formatexpr = 'v:lua.vim.lsp.formatexpr(#{timeout_ms:250})'``.
 ---
 ---@param opts table options for customizing the formatting expression which takes the
 ---                   following optional keys:
-- 
cgit 


From ddd92a70d2aab5247895e89abaaa79c62ba7dbb4 Mon Sep 17 00:00:00 2001
From: Folke Lemaitre 
Date: Sun, 28 May 2023 07:51:28 +0200
Subject: feat(lsp): initial support for dynamic capabilities (#23681)

- `client.dynamic_capabilities` is an object that tracks client register/unregister
- `client.supports_method` will additionally check if a dynamic capability supports the method, taking document filters into account. But only if the client enabled `dynamicRegistration` for the capability
- updated the default client capabilities to include dynamicRegistration for:
    - formatting
    - rangeFormatting
    - hover
    - codeAction
    - hover
    - rename
---
 runtime/lua/vim/lsp.lua | 121 +++++++++++++++++++++++++++---------------------
 1 file changed, 68 insertions(+), 53 deletions(-)

(limited to 'runtime/lua/vim/lsp.lua')

diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua
index 2e6ca7a0ac..5337abea25 100644
--- a/runtime/lua/vim/lsp.lua
+++ b/runtime/lua/vim/lsp.lua
@@ -50,6 +50,7 @@ lsp._request_name_to_capability = {
   ['textDocument/codeAction'] = { 'codeActionProvider' },
   ['textDocument/codeLens'] = { 'codeLensProvider' },
   ['codeLens/resolve'] = { 'codeLensProvider', 'resolveProvider' },
+  ['codeAction/resolve'] = { 'codeActionProvider', 'resolveProvider' },
   ['workspace/executeCommand'] = { 'executeCommandProvider' },
   ['workspace/symbol'] = { 'workspaceSymbolProvider' },
   ['textDocument/references'] = { 'referencesProvider' },
@@ -886,6 +887,47 @@ function lsp.start(config, opts)
   return client_id
 end
 
+---@private
+-- Determines whether the given option can be set by `set_defaults`.
+local function is_empty_or_default(bufnr, option)
+  if vim.bo[bufnr][option] == '' then
+    return true
+  end
+
+  local info = vim.api.nvim_get_option