diff options
Diffstat (limited to 'runtime/lua/vim/lsp')
-rw-r--r-- | runtime/lua/vim/lsp/_changetracking.lua | 373 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/_completion.lua | 52 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/_dynamic.lua | 31 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/_meta.lua | 10 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/_meta/protocol.lua | 1320 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/_tagfunc.lua (renamed from runtime/lua/vim/lsp/tagfunc.lua) | 0 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/_watchfiles.lua | 118 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/buf.lua | 279 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/client.lua | 1056 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/codelens.lua | 45 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/diagnostic.lua | 208 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/handlers.lua | 212 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/health.lua | 46 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/inlay_hint.lua | 72 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/log.lua | 214 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/protocol.lua | 150 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/rpc.lua | 456 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/semantic_tokens.lua | 90 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/sync.lua | 57 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/util.lua | 274 |
20 files changed, 3827 insertions, 1236 deletions
diff --git a/runtime/lua/vim/lsp/_changetracking.lua b/runtime/lua/vim/lsp/_changetracking.lua new file mode 100644 index 0000000000..b2be53269f --- /dev/null +++ b/runtime/lua/vim/lsp/_changetracking.lua @@ -0,0 +1,373 @@ +local protocol = require('vim.lsp.protocol') +local sync = require('vim.lsp.sync') +local util = require('vim.lsp.util') + +local api = vim.api +local uv = vim.uv + +local M = {} + +--- LSP has 3 different sync modes: +--- - None (Servers will read the files themselves when needed) +--- - Full (Client sends the full buffer content on updates) +--- - Incremental (Client sends only the changed parts) +--- +--- Changes are tracked per buffer. +--- A buffer can have multiple clients attached and each client needs to send the changes +--- To minimize the amount of changesets to compute, computation is grouped: +--- +--- None: One group for all clients +--- Full: One group for all clients +--- Incremental: One group per `offset_encoding` +--- +--- Sending changes can be debounced per buffer. To simplify the implementation the +--- smallest debounce interval is used and we don't group clients by different intervals. +--- +--- @class vim.lsp.CTGroup +--- @field sync_kind integer TextDocumentSyncKind, considers config.flags.allow_incremental_sync +--- @field offset_encoding "utf-8"|"utf-16"|"utf-32" +--- +--- @class vim.lsp.CTBufferState +--- @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 +--- @field timer 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 integer how many clients are using this group +--- +--- @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} + +---@param group vim.lsp.CTGroup +---@return string +local function group_key(group) + if group.sync_kind == protocol.TextDocumentSyncKind.Incremental then + return tostring(group.sync_kind) .. '\0' .. group.offset_encoding + end + return tostring(group.sync_kind) +end + +---@type table<vim.lsp.CTGroup,vim.lsp.CTGroupState> +local state_by_group = setmetatable({}, { + __index = function(tbl, k) + return rawget(tbl, group_key(k)) + end, + __newindex = function(tbl, k, v) + rawset(tbl, group_key(k), v) + end, +}) + +---@param client vim.lsp.Client +---@return vim.lsp.CTGroup +local function get_group(client) + local allow_inc_sync = vim.F.if_nil(client.flags.allow_incremental_sync, true) --- @type boolean + local change_capability = vim.tbl_get(client.server_capabilities, 'textDocumentSync', 'change') + local sync_kind = change_capability or protocol.TextDocumentSyncKind.None + if not allow_inc_sync and change_capability == protocol.TextDocumentSyncKind.Incremental then + sync_kind = protocol.TextDocumentSyncKind.Full --[[@as integer]] + end + return { + sync_kind = sync_kind, + offset_encoding = client.offset_encoding, + } +end + +---@param state vim.lsp.CTBufferState +---@param encoding string +---@param bufnr integer +---@param firstline integer +---@param lastline integer +---@param new_lastline integer +---@return lsp.TextDocumentContentChangeEvent +local function incremental_changes(state, encoding, bufnr, firstline, lastline, new_lastline) + local prev_lines = state.lines + local curr_lines = state.lines_tmp + + local changed_lines = api.nvim_buf_get_lines(bufnr, firstline, new_lastline, true) + for i = 1, firstline do + curr_lines[i] = prev_lines[i] + end + for i = firstline + 1, new_lastline do + curr_lines[i] = changed_lines[i - firstline] + end + for i = lastline + 1, #prev_lines do + curr_lines[i - lastline + new_lastline] = prev_lines[i] + end + if vim.tbl_isempty(curr_lines) then + -- Can happen when deleting the entire contents of a buffer, see https://github.com/neovim/neovim/issues/16259. + curr_lines[1] = '' + end + + local line_ending = vim.lsp._buf_get_line_ending(bufnr) + local incremental_change = sync.compute_diff( + state.lines, + curr_lines, + firstline, + lastline, + new_lastline, + encoding, + line_ending + ) + + -- Double-buffering of lines tables is used to reduce the load on the garbage collector. + -- At this point the prev_lines table is useless, but its internal storage has already been allocated, + -- so let's keep it around for the next didChange event, in which it will become the next + -- curr_lines table. Note that setting elements to nil doesn't actually deallocate slots in the + -- internal storage - it merely marks them as free, for the GC to deallocate them. + for i in ipairs(prev_lines) do + prev_lines[i] = nil + end + state.lines = curr_lines + state.lines_tmp = prev_lines + + return incremental_change +end + +---@param client vim.lsp.Client +---@param bufnr integer +function M.init(client, bufnr) + assert(client.offset_encoding, 'lsp client must have an offset_encoding') + local group = get_group(client) + local state = state_by_group[group] + if state then + state.debounce = math.min(state.debounce, client.flags.debounce_text_changes or 150) + state.clients[client.id] = client + else + state = { + buffers = {}, + debounce = client.flags.debounce_text_changes or 150, + clients = { + [client.id] = client, + }, + } + state_by_group[group] = state + end + local buf_state = state.buffers[bufnr] + if buf_state then + buf_state.refs = buf_state.refs + 1 + else + buf_state = { + name = api.nvim_buf_get_name(bufnr), + lines = {}, + lines_tmp = {}, + pending_changes = {}, + needs_flush = false, + refs = 1, + } + state.buffers[bufnr] = buf_state + if group.sync_kind == protocol.TextDocumentSyncKind.Incremental then + buf_state.lines = api.nvim_buf_get_lines(bufnr, 0, -1, true) + end + end +end + +--- @param client vim.lsp.Client +--- @param bufnr integer +--- @param name string +--- @return string +function M._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_name = buf_state.name + buf_state.name = name + return old_name +end + +---@param buf_state vim.lsp.CTBufferState +local function reset_timer(buf_state) + local timer = buf_state.timer + if timer then + buf_state.timer = nil + if not timer:is_closing() then + timer:stop() + timer:close() + end + end +end + +--- @param client vim.lsp.Client +--- @param bufnr integer +function M.reset_buf(client, bufnr) + M.flush(client, bufnr) + local state = state_by_group[get_group(client)] + if not state then + return + end + assert(state.buffers, 'CTGroupState must have buffers') + local buf_state = state.buffers[bufnr] + buf_state.refs = buf_state.refs - 1 + assert(buf_state.refs >= 0, 'refcount on buffer state must not get negative') + if buf_state.refs == 0 then + state.buffers[bufnr] = nil + reset_timer(buf_state) + end +end + +--- @param client vim.lsp.Client +function M.reset(client) + local state = state_by_group[get_group(client)] + if not state then + return + end + state.clients[client.id] = nil + if vim.tbl_count(state.clients) == 0 then + for _, buf_state in pairs(state.buffers) do + reset_timer(buf_state) + end + state.buffers = {} + end +end + +-- Adjust debounce time by taking time of last didChange notification into +-- consideration. If the last didChange happened more than `debounce` time ago, +-- debounce can be skipped and otherwise maybe reduced. +-- +-- This turns the debounce into a kind of client rate limiting +-- +---@param debounce integer +---@param buf_state vim.lsp.CTBufferState +---@return number +local function next_debounce(debounce, buf_state) + if debounce == 0 then + return 0 + end + local ns_to_ms = 0.000001 + if not buf_state.last_flush then + return debounce + end + local now = uv.hrtime() + local ms_since_last_flush = (now - buf_state.last_flush) * ns_to_ms + return math.max(debounce - ms_since_last_flush, 0) +end + +---@param bufnr integer +---@param sync_kind integer protocol.TextDocumentSyncKind +---@param state vim.lsp.CTGroupState +---@param buf_state vim.lsp.CTBufferState +local function send_changes(bufnr, sync_kind, state, buf_state) + if not buf_state.needs_flush then + return + end + buf_state.last_flush = uv.hrtime() + buf_state.needs_flush = false + + if not api.nvim_buf_is_valid(bufnr) then + buf_state.pending_changes = {} + return + end + + local changes --- @type lsp.TextDocumentContentChangeEvent[] + if sync_kind == protocol.TextDocumentSyncKind.None then + return + elseif sync_kind == protocol.TextDocumentSyncKind.Incremental then + changes = buf_state.pending_changes + buf_state.pending_changes = {} + else + changes = { + { text = vim.lsp._buf_get_full_text(bufnr) }, + } + 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, { + textDocument = { + uri = uri, + version = util.buf_versions[bufnr], + }, + contentChanges = changes, + }) + end + end +end + +--- @param bufnr integer +--- @param firstline integer +--- @param lastline integer +--- @param new_lastline integer +--- @param group vim.lsp.CTGroup +local function send_changes_for_group(bufnr, firstline, lastline, new_lastline, group) + local state = state_by_group[group] + if not state then + error( + string.format( + 'changetracking.init must have been called for all LSP clients. group=%s states=%s', + vim.inspect(group), + vim.inspect(vim.tbl_keys(state_by_group)) + ) + ) + end + local buf_state = state.buffers[bufnr] + buf_state.needs_flush = true + reset_timer(buf_state) + local debounce = next_debounce(state.debounce, buf_state) + if group.sync_kind == protocol.TextDocumentSyncKind.Incremental then + -- This must be done immediately and cannot be delayed + -- The contents would further change and startline/endline may no longer fit + local changes = incremental_changes( + buf_state, + group.offset_encoding, + bufnr, + firstline, + lastline, + new_lastline + ) + table.insert(buf_state.pending_changes, changes) + end + if debounce == 0 then + send_changes(bufnr, group.sync_kind, state, buf_state) + else + local timer = assert(uv.new_timer(), 'Must be able to create timer') + buf_state.timer = timer + timer:start( + debounce, + 0, + vim.schedule_wrap(function() + reset_timer(buf_state) + send_changes(bufnr, group.sync_kind, state, buf_state) + end) + ) + end +end + +--- @param bufnr integer +--- @param firstline integer +--- @param lastline integer +--- @param new_lastline integer +function M.send_changes(bufnr, firstline, lastline, new_lastline) + local groups = {} ---@type table<string,vim.lsp.CTGroup> + for _, client in pairs(vim.lsp.get_clients({ bufnr = bufnr })) do + local group = get_group(client) + groups[group_key(group)] = group + end + for _, group in pairs(groups) do + send_changes_for_group(bufnr, firstline, lastline, new_lastline, group) + end +end + +--- Flushes any outstanding change notification. +---@param client vim.lsp.Client +---@param bufnr? integer +function M.flush(client, bufnr) + local group = get_group(client) + local state = state_by_group[group] + if not state then + return + end + if bufnr then + local buf_state = state.buffers[bufnr] or {} + reset_timer(buf_state) + send_changes(bufnr, group.sync_kind, state, buf_state) + else + for buf, buf_state in pairs(state.buffers) do + reset_timer(buf_state) + send_changes(buf, group.sync_kind, state, buf_state) + end + end +end + +return M diff --git a/runtime/lua/vim/lsp/_completion.lua b/runtime/lua/vim/lsp/_completion.lua index 7a607d6c13..a169f96565 100644 --- a/runtime/lua/vim/lsp/_completion.lua +++ b/runtime/lua/vim/lsp/_completion.lua @@ -4,11 +4,21 @@ local lsp = vim.lsp local protocol = lsp.protocol local ms = protocol.Methods +--- @alias vim.lsp.CompletionResult lsp.CompletionList | lsp.CompletionItem[] + +-- TODO(mariasolos): Remove this declaration once we figure out a better way to handle +-- literal/anonymous types (see https://github.com/neovim/neovim/pull/27542/files#r1495259331). +--- @class lsp.ItemDefaults +--- @field editRange lsp.Range | { insert: lsp.Range, replace: lsp.Range } | nil +--- @field insertTextFormat lsp.InsertTextFormat? +--- @field insertTextMode lsp.InsertTextMode? +--- @field data any + ---@param input string unparsed snippet ---@return string parsed snippet local function parse_snippet(input) local ok, parsed = pcall(function() - return require('vim.lsp._snippet_grammar').parse(input) + return vim.lsp._snippet_grammar.parse(input) end) return ok and tostring(parsed) or input end @@ -37,19 +47,49 @@ local function get_completion_word(item) return item.label end ----@param result lsp.CompletionList|lsp.CompletionItem[] +--- Applies the given defaults to the completion item, modifying it in place. +--- +--- @param item lsp.CompletionItem +--- @param defaults lsp.ItemDefaults? +local function apply_defaults(item, defaults) + if not defaults then + return + end + + item.insertTextFormat = item.insertTextFormat or defaults.insertTextFormat + item.insertTextMode = item.insertTextMode or defaults.insertTextMode + item.data = item.data or defaults.data + if defaults.editRange then + local textEdit = item.textEdit or {} + item.textEdit = textEdit + textEdit.newText = textEdit.newText or item.textEditText or item.insertText + if defaults.editRange.start then + textEdit.range = textEdit.range or defaults.editRange + elseif defaults.editRange.insert then + textEdit.insert = defaults.editRange.insert + textEdit.replace = defaults.editRange.replace + end + end +end + +---@param result vim.lsp.CompletionResult ---@return lsp.CompletionItem[] local function get_items(result) if result.items then + for _, item in ipairs(result.items) do + ---@diagnostic disable-next-line: param-type-mismatch + apply_defaults(item, result.itemDefaults) + end return result.items + else + return result end - return result end --- Turns the result of a `textDocument/completion` request into vim-compatible --- |complete-items|. --- ----@param result lsp.CompletionList|lsp.CompletionItem[] Result of `textDocument/completion` +---@param result vim.lsp.CompletionResult Result of `textDocument/completion` ---@param prefix string prefix to filter the completion items ---@return table[] ---@see complete-items @@ -130,7 +170,7 @@ end ---@param lnum integer 0-indexed line number ---@param client_start_boundary integer 0-indexed word boundary ---@param server_start_boundary? integer 0-indexed word boundary, based on textEdit.range.start.character ----@param result lsp.CompletionList|lsp.CompletionItem[] +---@param result vim.lsp.CompletionResult ---@param encoding string ---@return table[] matches ---@return integer? server_start_boundary @@ -206,7 +246,7 @@ function M.omnifunc(findstart, base) local params = util.make_position_params(win, client.offset_encoding) client.request(ms.textDocument_completion, params, function(err, result) if err then - require('vim.lsp.log').warn(err.message) + vim.lsp.log.warn(err.message) end if result and vim.fn.mode() == 'i' then local matches diff --git a/runtime/lua/vim/lsp/_dynamic.lua b/runtime/lua/vim/lsp/_dynamic.lua index 04040e8e28..819b03a63a 100644 --- a/runtime/lua/vim/lsp/_dynamic.lua +++ b/runtime/lua/vim/lsp/_dynamic.lua @@ -1,4 +1,4 @@ -local wf = require('vim.lsp._watchfiles') +local glob = vim.glob --- @class lsp.DynamicCapabilities --- @field capabilities table<string, lsp.Registration[]> @@ -6,6 +6,7 @@ local wf = require('vim.lsp._watchfiles') local M = {} --- @param client_id number +--- @return lsp.DynamicCapabilities function M.new(client_id) return setmetatable({ capabilities = {}, @@ -18,12 +19,12 @@ function M:supports_registration(method) if not client then return false end - local capability = vim.tbl_get(client.config.capabilities, unpack(vim.split(method, '/'))) + local capability = vim.tbl_get(client.capabilities, unpack(vim.split(method, '/'))) return type(capability) == 'table' and capability.dynamicRegistration end --- @param registrations lsp.Registration[] ---- @private +--- @package function M:register(registrations) -- remove duplicates self:unregister(registrations) @@ -37,7 +38,7 @@ function M:register(registrations) end --- @param unregisterations lsp.Unregistration[] ---- @private +--- @package function M:unregister(unregisterations) for _, unreg in ipairs(unregisterations) do local method = unreg.method @@ -55,9 +56,9 @@ function M:unregister(unregisterations) end --- @param method string ---- @param opts? {bufnr?: number} +--- @param opts? {bufnr: integer?} --- @return lsp.Registration? (table|nil) the registration if found ---- @private +--- @package function M:get(method, opts) opts = opts or {} opts.bufnr = opts.bufnr or vim.api.nvim_get_current_buf() @@ -69,15 +70,15 @@ function M:get(method, opts) if not documentSelector then return reg end - if M.match(opts.bufnr, documentSelector) then + if self:match(opts.bufnr, documentSelector) then return reg end end end --- @param method string ---- @param opts? {bufnr?: number} ---- @private +--- @param opts? {bufnr: integer?} +--- @package function M:supports(method, opts) return self:get(method, opts) ~= nil end @@ -85,19 +86,23 @@ end --- @param bufnr number --- @param documentSelector lsp.DocumentSelector --- @private -function M.match(bufnr, documentSelector) - local ft = vim.bo[bufnr].filetype +function M:match(bufnr, documentSelector) + local client = vim.lsp.get_client_by_id(self.client_id) + if not client then + return false + end + local language = client.get_language_id(bufnr, vim.bo[bufnr].filetype) local uri = vim.uri_from_bufnr(bufnr) local fname = vim.uri_to_fname(uri) for _, filter in ipairs(documentSelector) do local matches = true - if filter.language and ft ~= filter.language then + if filter.language and language ~= filter.language then matches = false end if matches and filter.scheme and not vim.startswith(uri, filter.scheme .. ':') then matches = false end - if matches and filter.pattern and not wf._match(filter.pattern, fname) then + if matches and filter.pattern and not glob.to_lpeg(filter.pattern):match(fname) then matches = false end if matches then diff --git a/runtime/lua/vim/lsp/_meta.lua b/runtime/lua/vim/lsp/_meta.lua index acf799264e..be3222828d 100644 --- a/runtime/lua/vim/lsp/_meta.lua +++ b/runtime/lua/vim/lsp/_meta.lua @@ -1,22 +1,16 @@ ---@meta error('Cannot require a meta file') ----@alias lsp-handler fun(err: lsp.ResponseError|nil, result: any, context: lsp.HandlerContext, config: table|nil): any? +---@alias lsp.Handler fun(err: lsp.ResponseError?, result: any, context: lsp.HandlerContext, config?: table): ...any ---@class lsp.HandlerContext ---@field method string ---@field client_id integer ---@field bufnr? integer ---@field params? any +---@field version? integer ---@class lsp.ResponseError ---@field code integer ---@field message string ---@field data string|number|boolean|table[]|table|nil - ---- @class lsp.DocumentFilter ---- @field language? string ---- @field scheme? string ---- @field pattern? string - ---- @alias lsp.RegisterOptions any | lsp.StaticRegistrationOptions | lsp.TextDocumentRegistrationOptions diff --git a/runtime/lua/vim/lsp/_meta/protocol.lua b/runtime/lua/vim/lsp/_meta/protocol.lua index 72b0f00f65..a5da5ac6b7 100644 --- a/runtime/lua/vim/lsp/_meta/protocol.lua +++ b/runtime/lua/vim/lsp/_meta/protocol.lua @@ -1,7 +1,11 @@ --[[ -This file is autogenerated from scripts/gen_lsp.lua +THIS FILE IS GENERATED by scripts/gen_lsp.lua +DO NOT EDIT MANUALLY + +Based on LSP protocol 3.18 + Regenerate: -nvim -l scripts/gen_lsp.lua gen --version 3.18 --runtime/lua/vim/lsp/_meta/protocol.lua +nvim -l scripts/gen_lsp.lua gen --version 3.18 --]] ---@meta @@ -9,111 +13,132 @@ error('Cannot require a meta file') ---@alias lsp.null nil ---@alias uinteger integer ----@alias lsp.decimal number +---@alias decimal number ---@alias lsp.DocumentUri string ---@alias lsp.URI string ----@alias lsp.LSPObject table<string, lsp.LSPAny> ----@alias lsp.LSPArray lsp.LSPAny[] ----@alias lsp.LSPAny lsp.LSPObject|lsp.LSPArray|string|number|boolean|nil ---@class lsp.ImplementationParams: lsp.TextDocumentPositionParams, lsp.WorkDoneProgressParams, lsp.PartialResultParams ---Represents a location inside a resource, such as a line ---inside a text file. ---@class lsp.Location +--- ---@field uri lsp.DocumentUri +--- ---@field range lsp.Range ----@class lsp.ImplementationRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.StaticRegistrationOptions +---@class lsp.ImplementationRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.ImplementationOptions, lsp.StaticRegistrationOptions ---@class lsp.TypeDefinitionParams: lsp.TextDocumentPositionParams, lsp.WorkDoneProgressParams, lsp.PartialResultParams ----@class lsp.TypeDefinitionRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.StaticRegistrationOptions +---@class lsp.TypeDefinitionRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.TypeDefinitionOptions, lsp.StaticRegistrationOptions ---A workspace folder inside a client. ---@class lsp.WorkspaceFolder +--- ---The associated URI for this workspace folder. ---@field uri lsp.URI +--- ---The name of the workspace folder. Used to refer to this ---workspace folder in the user interface. ---@field name string ---The parameters of a `workspace/didChangeWorkspaceFolders` notification. ---@class lsp.DidChangeWorkspaceFoldersParams +--- ---The actual workspace folder change event. ---@field event lsp.WorkspaceFoldersChangeEvent ---The parameters of a configuration request. ---@class lsp.ConfigurationParams +--- ---@field items lsp.ConfigurationItem[] ---Parameters for a {@link DocumentColorRequest}. ----@class lsp.DocumentColorParams +---@class lsp.DocumentColorParams: lsp.WorkDoneProgressParams, lsp.PartialResultParams +--- ---The text document. ---@field textDocument lsp.TextDocumentIdentifier ---Represents a color range from a document. ---@class lsp.ColorInformation +--- ---The range in the document where this color appears. ---@field range lsp.Range +--- ---The actual color value for this color range. ---@field color lsp.Color ----@class lsp.DocumentColorRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.StaticRegistrationOptions +---@class lsp.DocumentColorRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.DocumentColorOptions, lsp.StaticRegistrationOptions ---Parameters for a {@link ColorPresentationRequest}. ----@class lsp.ColorPresentationParams +---@class lsp.ColorPresentationParams: lsp.WorkDoneProgressParams, lsp.PartialResultParams +--- ---The text document. ---@field textDocument lsp.TextDocumentIdentifier +--- ---The color to request presentations for. ---@field color lsp.Color +--- ---The range where the color would be inserted. Serves as a context. ---@field range lsp.Range ---@class lsp.ColorPresentation +--- ---The label of this color presentation. It will be shown on the color ---picker header. By default this is also the text that is inserted when selecting ---this color presentation. ---@field label string +--- ---An {@link TextEdit edit} which is applied to a document when selecting ---this presentation for the color. When `falsy` the {@link ColorPresentation.label label} ---is used. ---@field textEdit? lsp.TextEdit +--- ---An optional array of additional {@link TextEdit text edits} that are applied when ---selecting this color presentation. Edits must not overlap with the main {@link ColorPresentation.textEdit edit} nor with themselves. ---@field additionalTextEdits? lsp.TextEdit[] ---@class lsp.WorkDoneProgressOptions +--- ---@field workDoneProgress? boolean ---General text document registration options. ---@class lsp.TextDocumentRegistrationOptions +--- ---A document selector to identify the scope of the registration. If set to null ---the document selector provided on the client side will be used. ---@field documentSelector lsp.DocumentSelector|lsp.null ---Parameters for a {@link FoldingRangeRequest}. ----@class lsp.FoldingRangeParams +---@class lsp.FoldingRangeParams: lsp.WorkDoneProgressParams, lsp.PartialResultParams +--- ---The text document. ---@field textDocument lsp.TextDocumentIdentifier ---Represents a folding range. To be valid, start and end line must be bigger than zero and smaller ---than the number of lines in the document. Clients are free to ignore invalid ranges. ---@class lsp.FoldingRange +--- ---The zero-based start line of the range to fold. The folded area starts after the line's last character. ---To be valid, the end must be zero or larger and smaller than the number of lines in the document. ---@field startLine uinteger +--- ---The zero-based character offset from where the folded range starts. If not defined, defaults to the length of the start line. ---@field startCharacter? uinteger +--- ---The zero-based end line of the range to fold. The folded area ends with the line's last character. ---To be valid, the end must be zero or larger and smaller than the number of lines in the document. ---@field endLine uinteger +--- ---The zero-based character offset before the folded range ends. If not defined, defaults to the length of the end line. ---@field endCharacter? uinteger +--- ---Describes the kind of the folding range such as `comment' or 'region'. The kind ---is used to categorize folding ranges and used by commands like 'Fold all comments'. ---See {@link FoldingRangeKind} for an enumeration of standardized kinds. ---@field kind? lsp.FoldingRangeKind +--- ---The text that the client should show when the specified range is ---collapsed. If not defined or not supported by the client, a default ---will be chosen by the client. @@ -121,34 +146,40 @@ error('Cannot require a meta file') ---@since 3.17.0 ---@field collapsedText? string ----@class lsp.FoldingRangeRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.StaticRegistrationOptions +---@class lsp.FoldingRangeRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.FoldingRangeOptions, lsp.StaticRegistrationOptions ---@class lsp.DeclarationParams: lsp.TextDocumentPositionParams, lsp.WorkDoneProgressParams, lsp.PartialResultParams ----@class lsp.DeclarationRegistrationOptions: lsp.DeclarationOptions, lsp.StaticRegistrationOptions +---@class lsp.DeclarationRegistrationOptions: lsp.DeclarationOptions, lsp.TextDocumentRegistrationOptions, lsp.StaticRegistrationOptions ---A parameter literal used in selection range requests. ----@class lsp.SelectionRangeParams +---@class lsp.SelectionRangeParams: lsp.WorkDoneProgressParams, lsp.PartialResultParams +--- ---The text document. ---@field textDocument lsp.TextDocumentIdentifier +--- ---The positions inside the text document. ---@field positions lsp.Position[] ---A selection range represents a part of a selection hierarchy. A selection range ---may have a parent selection range that contains it. ---@class lsp.SelectionRange +--- ---The {@link Range range} of this selection range. ---@field range lsp.Range +--- ---The parent selection range containing this range. Therefore `parent.range` must contain `this.range`. ---@field parent? lsp.SelectionRange ----@class lsp.SelectionRangeRegistrationOptions: lsp.SelectionRangeOptions, lsp.StaticRegistrationOptions +---@class lsp.SelectionRangeRegistrationOptions: lsp.SelectionRangeOptions, lsp.TextDocumentRegistrationOptions, lsp.StaticRegistrationOptions ---@class lsp.WorkDoneProgressCreateParams +--- ---The token to be used to report progress. ---@field token lsp.ProgressToken ---@class lsp.WorkDoneProgressCancelParams +--- ---The token to be used to report progress. ---@field token lsp.ProgressToken @@ -162,21 +193,29 @@ error('Cannot require a meta file') --- ---@since 3.16.0 ---@class lsp.CallHierarchyItem +--- ---The name of this item. ---@field name string +--- ---The kind of this item. ---@field kind lsp.SymbolKind +--- ---Tags for this item. ---@field tags? lsp.SymbolTag[] +--- ---More detail for this item, e.g. the signature of a function. ---@field detail? string +--- ---The resource identifier of this item. ---@field uri lsp.DocumentUri +--- ---The range enclosing this symbol not including leading/trailing whitespace but everything else, e.g. comments and code. ---@field range lsp.Range +--- ---The range that should be selected and revealed when this symbol is being picked, e.g. the name of a function. ---Must be contained by the {@link CallHierarchyItem.range `range`}. ---@field selectionRange lsp.Range +--- ---A data entry field that is preserved between a call hierarchy prepare and ---incoming calls or outgoing calls requests. ---@field data? lsp.LSPAny @@ -184,20 +223,23 @@ error('Cannot require a meta file') ---Call hierarchy options used during static or dynamic registration. --- ---@since 3.16.0 ----@class lsp.CallHierarchyRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.StaticRegistrationOptions +---@class lsp.CallHierarchyRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.CallHierarchyOptions, lsp.StaticRegistrationOptions ---The parameter of a `callHierarchy/incomingCalls` request. --- ---@since 3.16.0 ----@class lsp.CallHierarchyIncomingCallsParams +---@class lsp.CallHierarchyIncomingCallsParams: lsp.WorkDoneProgressParams, lsp.PartialResultParams +--- ---@field item lsp.CallHierarchyItem ---Represents an incoming call, e.g. a caller of a method or constructor. --- ---@since 3.16.0 ---@class lsp.CallHierarchyIncomingCall +--- ---The item that makes the call. ---@field from lsp.CallHierarchyItem +--- ---The ranges at which the calls appear. This is relative to the caller ---denoted by {@link CallHierarchyIncomingCall.from `this.from`}. ---@field fromRanges lsp.Range[] @@ -205,64 +247,78 @@ error('Cannot require a meta file') ---The parameter of a `callHierarchy/outgoingCalls` request. --- ---@since 3.16.0 ----@class lsp.CallHierarchyOutgoingCallsParams +---@class lsp.CallHierarchyOutgoingCallsParams: lsp.WorkDoneProgressParams, lsp.PartialResultParams +--- ---@field item lsp.CallHierarchyItem ---Represents an outgoing call, e.g. calling a getter from a method or a method from a constructor etc. --- ---@since 3.16.0 ---@class lsp.CallHierarchyOutgoingCall +--- ---The item that is called. ---@field to lsp.CallHierarchyItem +--- ---The range at which this item is called. This is the range relative to the caller, e.g the item ---passed to {@link CallHierarchyItemProvider.provideCallHierarchyOutgoingCalls `provideCallHierarchyOutgoingCalls`} ---and not {@link CallHierarchyOutgoingCall.to `this.to`}. ---@field fromRanges lsp.Range[] ---@since 3.16.0 ----@class lsp.SemanticTokensParams +---@class lsp.SemanticTokensParams: lsp.WorkDoneProgressParams, lsp.PartialResultParams +--- ---The text document. ---@field textDocument lsp.TextDocumentIdentifier ---@since 3.16.0 ---@class lsp.SemanticTokens +--- ---An optional result id. If provided and clients support delta updating ---the client will include the result id in the next semantic token request. ---A server can then instead of computing all semantic tokens again simply ---send a delta. ---@field resultId? string +--- ---The actual tokens. ---@field data uinteger[] ---@since 3.16.0 ---@class lsp.SemanticTokensPartialResult +--- ---@field data uinteger[] ---@since 3.16.0 ----@class lsp.SemanticTokensRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.StaticRegistrationOptions +---@class lsp.SemanticTokensRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.SemanticTokensOptions, lsp.StaticRegistrationOptions ---@since 3.16.0 ----@class lsp.SemanticTokensDeltaParams +---@class lsp.SemanticTokensDeltaParams: lsp.WorkDoneProgressParams, lsp.PartialResultParams +--- ---The text document. ---@field textDocument lsp.TextDocumentIdentifier +--- ---The result id of a previous response. The result Id can either point to a full response ---or a delta response depending on what was received last. ---@field previousResultId string ---@since 3.16.0 ---@class lsp.SemanticTokensDelta +--- ---@field resultId? string +--- ---The semantic token edits to transform a previous result into a new result. ---@field edits lsp.SemanticTokensEdit[] ---@since 3.16.0 ---@class lsp.SemanticTokensDeltaPartialResult +--- ---@field edits lsp.SemanticTokensEdit[] ---@since 3.16.0 ----@class lsp.SemanticTokensRangeParams +---@class lsp.SemanticTokensRangeParams: lsp.WorkDoneProgressParams, lsp.PartialResultParams +--- ---The text document. ---@field textDocument lsp.TextDocumentIdentifier +--- ---The range the semantic tokens are requested for. ---@field range lsp.Range @@ -270,17 +326,21 @@ error('Cannot require a meta file') --- ---@since 3.16.0 ---@class lsp.ShowDocumentParams +--- ---The uri to show. ---@field uri lsp.URI +--- ---Indicates to show the resource in an external program. ---To show, for example, `https://code.visualstudio.com/` ---in the default WEB browser set `external` to `true`. ---@field external? boolean +--- ---An optional property to indicate whether the editor ---showing the document should take focus or not. ---Clients might ignore this property if an external ---program is started. ---@field takeFocus? boolean +--- ---An optional selection range if the document is a text ---document. Clients might ignore the property if an ---external program is started or the file is not a text @@ -291,6 +351,7 @@ error('Cannot require a meta file') --- ---@since 3.16.0 ---@class lsp.ShowDocumentResult +--- ---A boolean indicating if the show was successful. ---@field success boolean @@ -300,21 +361,24 @@ error('Cannot require a meta file') --- ---@since 3.16.0 ---@class lsp.LinkedEditingRanges +--- ---A list of ranges that can be edited together. The ranges must have ---identical length and contain identical text content. The ranges cannot overlap. ---@field ranges lsp.Range[] +--- ---An optional word pattern (regular expression) that describes valid contents for ---the given ranges. If no pattern is provided, the client configuration's word ---pattern will be used. ---@field wordPattern? string ----@class lsp.LinkedEditingRangeRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.StaticRegistrationOptions +---@class lsp.LinkedEditingRangeRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.LinkedEditingRangeOptions, lsp.StaticRegistrationOptions ---The parameters sent in notifications/requests for user-initiated creation of ---files. --- ---@since 3.16.0 ---@class lsp.CreateFilesParams +--- ---An array of all files/folders created in this operation. ---@field files lsp.FileCreate[] @@ -331,8 +395,10 @@ error('Cannot require a meta file') ---cause failure of the operation. How the client recovers from the failure is described by ---the client capability: `workspace.workspaceEdit.failureHandling` ---@class lsp.WorkspaceEdit +--- ---Holds changes to existing resources. ---@field changes? table<lsp.DocumentUri, lsp.TextEdit[]> +--- ---Depending on the client capability `workspace.workspaceEdit.resourceOperations` document changes ---are either an array of `TextDocumentEdit`s to express changes to n different text documents ---where each text document edit addresses a specific version of a text document. Or it can contain @@ -343,7 +409,8 @@ error('Cannot require a meta file') --- ---If a client neither supports `documentChanges` nor `workspace.workspaceEdit.resourceOperations` then ---only plain `TextEdit`s using the `changes` property are supported. ----@field documentChanges? lsp.TextDocumentEdit|lsp.CreateFile|lsp.RenameFile|lsp.DeleteFile[] +---@field documentChanges? (lsp.TextDocumentEdit|lsp.CreateFile|lsp.RenameFile|lsp.DeleteFile)[] +--- ---A map of change annotations that can be referenced in `AnnotatedTextEdit`s or create, rename and ---delete file / folder operations. --- @@ -356,6 +423,7 @@ error('Cannot require a meta file') --- ---@since 3.16.0 ---@class lsp.FileOperationRegistrationOptions +--- ---The actual filters. ---@field filters lsp.FileOperationFilter[] @@ -364,6 +432,7 @@ error('Cannot require a meta file') --- ---@since 3.16.0 ---@class lsp.RenameFilesParams +--- ---An array of all files/folders renamed in this operation. When a folder is renamed, only ---the folder will be included, and not its children. ---@field files lsp.FileRename[] @@ -373,6 +442,7 @@ error('Cannot require a meta file') --- ---@since 3.16.0 ---@class lsp.DeleteFilesParams +--- ---An array of all files/folders deleted in this operation. ---@field files lsp.FileDelete[] @@ -382,17 +452,21 @@ error('Cannot require a meta file') --- ---@since 3.16.0 ---@class lsp.Moniker +--- ---The scheme of the moniker. For example tsc or .Net ---@field scheme string +--- ---The identifier of the moniker. The value is opaque in LSIF however ---schema owners are allowed to define the structure if they want. ---@field identifier string +--- ---The scope in which the moniker is unique ---@field unique lsp.UniquenessLevel +--- ---The moniker kind if known. ---@field kind? lsp.MonikerKind ----@class lsp.MonikerRegistrationOptions: lsp.TextDocumentRegistrationOptions +---@class lsp.MonikerRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.MonikerOptions ---The parameter of a `textDocument/prepareTypeHierarchy` request. --- @@ -401,23 +475,31 @@ error('Cannot require a meta file') ---@since 3.17.0 ---@class lsp.TypeHierarchyItem +--- ---The name of this item. ---@field name string +--- ---The kind of this item. ---@field kind lsp.SymbolKind +--- ---Tags for this item. ---@field tags? lsp.SymbolTag[] +--- ---More detail for this item, e.g. the signature of a function. ---@field detail? string +--- ---The resource identifier of this item. ---@field uri lsp.DocumentUri +--- ---The range enclosing this symbol not including leading/trailing whitespace ---but everything else, e.g. comments and code. ---@field range lsp.Range +--- ---The range that should be selected and revealed when this symbol is being ---picked, e.g. the name of a function. Must be contained by the ---{@link TypeHierarchyItem.range `range`}. ---@field selectionRange lsp.Range +--- ---A data entry field that is preserved between a type hierarchy prepare and ---supertypes or subtypes requests. It could also be used to identify the ---type hierarchy in the server, helping improve the performance on @@ -427,28 +509,33 @@ error('Cannot require a meta file') ---Type hierarchy options used during static or dynamic registration. --- ---@since 3.17.0 ----@class lsp.TypeHierarchyRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.StaticRegistrationOptions +---@class lsp.TypeHierarchyRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.TypeHierarchyOptions, lsp.StaticRegistrationOptions ---The parameter of a `typeHierarchy/supertypes` request. --- ---@since 3.17.0 ----@class lsp.TypeHierarchySupertypesParams +---@class lsp.TypeHierarchySupertypesParams: lsp.WorkDoneProgressParams, lsp.PartialResultParams +--- ---@field item lsp.TypeHierarchyItem ---The parameter of a `typeHierarchy/subtypes` request. --- ---@since 3.17.0 ----@class lsp.TypeHierarchySubtypesParams +---@class lsp.TypeHierarchySubtypesParams: lsp.WorkDoneProgressParams, lsp.PartialResultParams +--- ---@field item lsp.TypeHierarchyItem ---A parameter literal used in inline value requests. --- ---@since 3.17.0 ----@class lsp.InlineValueParams +---@class lsp.InlineValueParams: lsp.WorkDoneProgressParams +--- ---The text document. ---@field textDocument lsp.TextDocumentIdentifier +--- ---The document range for which inline values should be computed. ---@field range lsp.Range +--- ---Additional information about the context in which inline values were ---requested. ---@field context lsp.InlineValueContext @@ -456,14 +543,16 @@ error('Cannot require a meta file') ---Inline value options used during static or dynamic registration. --- ---@since 3.17.0 ----@class lsp.InlineValueRegistrationOptions: lsp.InlineValueOptions, lsp.StaticRegistrationOptions +---@class lsp.InlineValueRegistrationOptions: lsp.InlineValueOptions, lsp.TextDocumentRegistrationOptions, lsp.StaticRegistrationOptions ---A parameter literal used in inlay hint requests. --- ---@since 3.17.0 ----@class lsp.InlayHintParams +---@class lsp.InlayHintParams: lsp.WorkDoneProgressParams +--- ---The text document. ---@field textDocument lsp.TextDocumentIdentifier +--- ---The document range for which inlay hints should be computed. ---@field range lsp.Range @@ -471,36 +560,47 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.InlayHint +--- ---The position of this hint. +--- +---If multiple hints have the same position, they will be shown in the order +---they appear in the response. ---@field position lsp.Position +--- ---The label of this hint. A human readable string or an array of ---InlayHintLabelPart label parts. --- ---*Note* that neither the string nor the label part can be empty. ---@field label string|lsp.InlayHintLabelPart[] +--- ---The kind of this hint. Can be omitted in which case the client ---should fall back to a reasonable default. ---@field kind? lsp.InlayHintKind +--- ---Optional text edits that are performed when accepting this inlay hint. --- ---*Note* that edits are expected to change the document so that the inlay ---hint (or its nearest variant) is now part of the document and the inlay ---hint itself is now obsolete. ---@field textEdits? lsp.TextEdit[] +--- ---The tooltip text when you hover over this item. ---@field tooltip? string|lsp.MarkupContent +--- ---Render padding before the hint. --- ---Note: Padding should use the editor's background color, not the ---background color of the hint itself. That means padding can be used ---to visually align/separate an inlay hint. ---@field paddingLeft? boolean +--- ---Render padding after the hint. --- ---Note: Padding should use the editor's background color, not the ---background color of the hint itself. That means padding can be used ---to visually align/separate an inlay hint. ---@field paddingRight? boolean +--- ---A data entry field that is preserved on an inlay hint between ---a `textDocument/inlayHint` and a `inlayHint/resolve` request. ---@field data? lsp.LSPAny @@ -508,16 +608,19 @@ error('Cannot require a meta file') ---Inlay hint options used during static or dynamic registration. --- ---@since 3.17.0 ----@class lsp.InlayHintRegistrationOptions: lsp.InlayHintOptions, lsp.StaticRegistrationOptions +---@class lsp.InlayHintRegistrationOptions: lsp.InlayHintOptions, lsp.TextDocumentRegistrationOptions, lsp.StaticRegistrationOptions ---Parameters of the document diagnostic request. --- ---@since 3.17.0 ----@class lsp.DocumentDiagnosticParams +---@class lsp.DocumentDiagnosticParams: lsp.WorkDoneProgressParams, lsp.PartialResultParams +--- ---The text document. ---@field textDocument lsp.TextDocumentIdentifier +--- ---The additional identifier provided during registration. ---@field identifier? string +--- ---The result id of a previous response if provided. ---@field previousResultId? string @@ -525,25 +628,29 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.DocumentDiagnosticReportPartialResult +--- ---@field relatedDocuments table<lsp.DocumentUri, lsp.FullDocumentDiagnosticReport|lsp.UnchangedDocumentDiagnosticReport> ---Cancellation data returned from a diagnostic request. --- ---@since 3.17.0 ---@class lsp.DiagnosticServerCancellationData +--- ---@field retriggerRequest boolean ---Diagnostic registration options. --- ---@since 3.17.0 ----@class lsp.DiagnosticRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.StaticRegistrationOptions +---@class lsp.DiagnosticRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.DiagnosticOptions, lsp.StaticRegistrationOptions ---Parameters of the workspace diagnostic request. --- ---@since 3.17.0 ----@class lsp.WorkspaceDiagnosticParams +---@class lsp.WorkspaceDiagnosticParams: lsp.WorkDoneProgressParams, lsp.PartialResultParams +--- ---The additional identifier provided during registration. ---@field identifier? string +--- ---The currently known diagnostic reports with their ---previous result ids. ---@field previousResultIds lsp.PreviousResultId[] @@ -552,20 +659,24 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.WorkspaceDiagnosticReport +--- ---@field items lsp.WorkspaceDocumentDiagnosticReport[] ---A partial result for a workspace diagnostic report. --- ---@since 3.17.0 ---@class lsp.WorkspaceDiagnosticReportPartialResult +--- ---@field items lsp.WorkspaceDocumentDiagnosticReport[] ---The params sent in an open notebook document notification. --- ---@since 3.17.0 ---@class lsp.DidOpenNotebookDocumentParams +--- ---The notebook document that got opened. ---@field notebookDocument lsp.NotebookDocument +--- ---The text documents that represent the content ---of a notebook cell. ---@field cellTextDocuments lsp.TextDocumentItem[] @@ -574,11 +685,13 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.DidChangeNotebookDocumentParams +--- ---The notebook document that did change. The version number points ---to the version after all provided changes have been applied. If ---only the text document content of a cell changes the notebook version ---doesn't necessarily have to change. ---@field notebookDocument lsp.VersionedNotebookDocumentIdentifier +--- ---The actual changes to the notebook document. --- ---The changes describe single state changes to the notebook document. @@ -598,6 +711,7 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.DidSaveNotebookDocumentParams +--- ---The notebook document that got saved. ---@field notebookDocument lsp.NotebookDocumentIdentifier @@ -605,8 +719,10 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.DidCloseNotebookDocumentParams +--- ---The notebook document that got closed. ---@field notebookDocument lsp.NotebookDocumentIdentifier +--- ---The text documents that represent the content ---of a notebook cell that got closed. ---@field cellTextDocuments lsp.TextDocumentIdentifier[] @@ -614,56 +730,71 @@ error('Cannot require a meta file') ---A parameter literal used in inline completion requests. --- ---@since 3.18.0 +---@proposed ---@class lsp.InlineCompletionParams: lsp.TextDocumentPositionParams, lsp.WorkDoneProgressParams +--- ---Additional information about the context in which inline completions were ---requested. ---@field context lsp.InlineCompletionContext ---Represents a collection of {@link InlineCompletionItem inline completion items} to be presented in the editor. +--- +---@since 3.18.0 +---@proposed ---@class lsp.InlineCompletionList +--- ---The inline completion items ---@field items lsp.InlineCompletionItem[] ---An inline completion item represents a text snippet that is proposed inline to complete text that is being typed. --- ---@since 3.18.0 +---@proposed ---@class lsp.InlineCompletionItem +--- ---The text to replace the range with. Must be set. ----@field insertText string ----The format of the insert text. The format applies to the `insertText`. If omitted defaults to `InsertTextFormat.PlainText`. ----@field insertTextFormat? lsp.InsertTextFormat +---@field insertText string|lsp.StringValue +--- ---A text that is used to decide if this inline completion should be shown. When `falsy` the {@link InlineCompletionItem.insertText} is used. ---@field filterText? string +--- ---The range to replace. Must begin and end on the same line. ---@field range? lsp.Range +--- ---An optional {@link Command} that is executed *after* inserting this completion. ---@field command? lsp.Command ---Inline completion options used during static or dynamic registration. --- ---@since 3.18.0 ----@class lsp.InlineCompletionRegistrationOptions: lsp.InlineCompletionOptions, lsp.StaticRegistrationOptions +---@proposed +---@class lsp.InlineCompletionRegistrationOptions: lsp.InlineCompletionOptions, lsp.TextDocumentRegistrationOptions, lsp.StaticRegistrationOptions ---@class lsp.RegistrationParams +--- ---@field registrations lsp.Registration[] ---@class lsp.UnregistrationParams +--- ---@field unregisterations lsp.Unregistration[] ----@class lsp.InitializeParams: lsp._InitializeParams +---@class lsp.InitializeParams: lsp._InitializeParams, lsp.WorkspaceFoldersInitializeParams ---The result returned from an initialize request. ---@class lsp.InitializeResult +--- ---The capabilities the language server provides. ---@field capabilities lsp.ServerCapabilities +--- ---Information about the server. --- ---@since 3.15.0 ----@field serverInfo? anonym1 +---@field serverInfo? lsp._anonym1.serverInfo ---The data type of the ResponseError if the ---initialize request fails. ---@class lsp.InitializeError +--- ---Indicates whether the client execute the following retry logic: ---(1) show the message provided by the ResponseError to the user ---(2) user selects retry or cancel @@ -674,49 +805,62 @@ error('Cannot require a meta file') ---The parameters of a change configuration notification. ---@class lsp.DidChangeConfigurationParams +--- ---The actual changed settings ---@field settings lsp.LSPAny ---@class lsp.DidChangeConfigurationRegistrationOptions +--- ---@field section? string|string[] ---The parameters of a notification message. ---@class lsp.ShowMessageParams +--- ---The message type. See {@link MessageType} ---@field type lsp.MessageType +--- ---The actual message. ---@field message string ---@class lsp.ShowMessageRequestParams +--- ---The message type. See {@link MessageType} ---@field type lsp.MessageType +--- ---The actual message. ---@field message string +--- ---The message action items to present. ---@field actions? lsp.MessageActionItem[] ---@class lsp.MessageActionItem +--- ---A short title like 'Retry', 'Open Log' etc. ---@field title string ---The log message parameters. ---@class lsp.LogMessageParams +--- ---The message type. See {@link MessageType} ---@field type lsp.MessageType +--- ---The actual message. ---@field message string ---The parameters sent in an open text document notification ---@class lsp.DidOpenTextDocumentParams +--- ---The document that was opened. ---@field textDocument lsp.TextDocumentItem ---The change text document notification's parameters. ---@class lsp.DidChangeTextDocumentParams +--- ---The document that did change. The version number points ---to the version after all provided content changes have ---been applied. ---@field textDocument lsp.VersionedTextDocumentIdentifier +--- ---The actual content changes. The content changes describe single state changes ---to the document. So if there are two content changes c1 (at array index 0) and ---c2 (at array index 1) for a document in state S then c1 moves the document from @@ -732,64 +876,78 @@ error('Cannot require a meta file') ---Describe options to be used when registered for text document change events. ---@class lsp.TextDocumentChangeRegistrationOptions: lsp.TextDocumentRegistrationOptions +--- ---How documents are synced to the server. ---@field syncKind lsp.TextDocumentSyncKind ---The parameters sent in a close text document notification ---@class lsp.DidCloseTextDocumentParams +--- ---The document that was closed. ---@field textDocument lsp.TextDocumentIdentifier ---The parameters sent in a save text document notification ---@class lsp.DidSaveTextDocumentParams +--- ---The document that was saved. ---@field textDocument lsp.TextDocumentIdentifier +--- ---Optional the content when saved. Depends on the includeText value ---when the save notification was requested. ---@field text? string ---Save registration options. ----@class lsp.TextDocumentSaveRegistrationOptions: lsp.TextDocumentRegistrationOptions +---@class lsp.TextDocumentSaveRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.SaveOptions ---The parameters sent in a will save text document notification. ---@class lsp.WillSaveTextDocumentParams +--- ---The document that will be saved. ---@field textDocument lsp.TextDocumentIdentifier +--- ---The 'TextDocumentSaveReason'. ---@field reason lsp.TextDocumentSaveReason ---A text edit applicable to a text document. ---@class lsp.TextEdit +--- ---The range of the text document to be manipulated. To insert ---text into a document create a range where start === end. ---@field range lsp.Range +--- ---The string to be inserted. For delete operations use an ---empty string. ---@field newText string ---The watched files change notification's parameters. ---@class lsp.DidChangeWatchedFilesParams +--- ---The actual file events. ---@field changes lsp.FileEvent[] ---Describe options to be used when registered for text document change events. ---@class lsp.DidChangeWatchedFilesRegistrationOptions +--- ---The watchers to register. ---@field watchers lsp.FileSystemWatcher[] ---The publish diagnostic notification's parameters. ---@class lsp.PublishDiagnosticsParams +--- ---The URI for which diagnostic information is reported. ---@field uri lsp.DocumentUri +--- ---Optional the version number of the document the diagnostics are published for. --- ---@since 3.15.0 ---@field version? integer +--- ---An array of diagnostic information items. ---@field diagnostics lsp.Diagnostic[] ---Completion parameters ---@class lsp.CompletionParams: lsp.TextDocumentPositionParams, lsp.WorkDoneProgressParams, lsp.PartialResultParams +--- ---The completion context. This is only available it the client specifies ---to send this using the client capability `textDocument.completion.contextSupport === true` ---@field context? lsp.CompletionContext @@ -797,6 +955,7 @@ error('Cannot require a meta file') ---A completion item represents a text snippet that is ---proposed to complete text that is being typed. ---@class lsp.CompletionItem +--- ---The label of this completion item. --- ---The label property is also by default the text that @@ -805,39 +964,49 @@ error('Cannot require a meta file') ---If label details are provided the label itself should ---be an unqualified name of the completion item. ---@field label string +--- ---Additional details for the label --- ---@since 3.17.0 ---@field labelDetails? lsp.CompletionItemLabelDetails +--- ---The kind of this completion item. Based of the kind ---an icon is chosen by the editor. ---@field kind? lsp.CompletionItemKind +--- ---Tags for this completion item. --- ---@since 3.15.0 ---@field tags? lsp.CompletionItemTag[] +--- ---A human-readable string with additional information ---about this item, like type or symbol information. ---@field detail? string +--- ---A human-readable string that represents a doc-comment. ---@field documentation? string|lsp.MarkupContent +--- ---Indicates if this item is deprecated. ---@deprecated Use `tags` instead. ---@field deprecated? boolean +--- ---Select this item when showing. --- ---*Note* that only one completion item can be selected and that the ---tool / client decides which item that is. The rule is that the *first* ---item of those that match best is selected. ---@field preselect? boolean +--- ---A string that should be used when comparing this item ---with other items. When `falsy` the {@link CompletionItem.label label} ---is used. ---@field sortText? string +--- ---A string that should be used when filtering a set of ---completion items. When `falsy` the {@link CompletionItem.label label} ---is used. ---@field filterText? string +--- ---A string that should be inserted into a document when selecting ---this completion. When `falsy` the {@link CompletionItem.label label} ---is used. @@ -850,6 +1019,7 @@ error('Cannot require a meta file') ---recommended to use `textEdit` instead since it avoids additional client ---side interpretation. ---@field insertText? string +--- ---The format of the insert text. The format applies to both the ---`insertText` property and the `newText` property of a provided ---`textEdit`. If omitted defaults to `InsertTextFormat.PlainText`. @@ -857,12 +1027,14 @@ error('Cannot require a meta file') ---Please note that the insertTextFormat doesn't apply to ---`additionalTextEdits`. ---@field insertTextFormat? lsp.InsertTextFormat +--- ---How whitespace and indentation is handled during completion ---item insertion. If not provided the clients default value depends on ---the `textDocument.completion.insertTextMode` client capability. --- ---@since 3.16.0 ---@field insertTextMode? lsp.InsertTextMode +--- ---An {@link TextEdit edit} which is applied to a document when selecting ---this completion. When an edit is provided the value of ---{@link CompletionItem.insertText insertText} is ignored. @@ -884,6 +1056,7 @@ error('Cannot require a meta file') --- ---@since 3.16.0 additional type `InsertReplaceEdit` ---@field textEdit? lsp.TextEdit|lsp.InsertReplaceEdit +--- ---The edit text used if the completion item is part of a CompletionList and ---CompletionList defines an item default for the text edit range. --- @@ -895,6 +1068,7 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@field textEditText? string +--- ---An optional array of additional {@link TextEdit text edits} that are applied when ---selecting this completion. Edits must not overlap (including the same insert position) ---with the main {@link CompletionItem.textEdit edit} nor with themselves. @@ -903,14 +1077,17 @@ error('Cannot require a meta file') ---(for example adding an import statement at the top of the file if the completion item will ---insert an unqualified type). ---@field additionalTextEdits? lsp.TextEdit[] +--- ---An optional set of characters that when pressed while this completion is active will accept it first and ---then type that character. *Note* that all commit characters should have `length=1` and that superfluous ---characters will be ignored. ---@field commitCharacters? string[] +--- ---An optional {@link Command command} that is executed *after* inserting this completion. *Note* that ---additional modifications to the current document should be described with the ---{@link CompletionItem.additionalTextEdits additionalTextEdits}-property. ---@field command? lsp.Command +--- ---A data entry field that is preserved on a completion item between a ---{@link CompletionRequest} and a {@link CompletionResolveRequest}. ---@field data? lsp.LSPAny @@ -918,11 +1095,13 @@ error('Cannot require a meta file') ---Represents a collection of {@link CompletionItem completion items} to be presented ---in the editor. ---@class lsp.CompletionList +--- ---This list it not complete. Further typing results in recomputing this list. --- ---Recomputed lists have all their items replaced (not appended) in the ---incomplete completion sessions. ---@field isIncomplete boolean +--- ---In many cases the items of an actual completion result share the same ---value for properties like `commitCharacters` or the range of a text ---edit. A completion list can therefore define item defaults which will @@ -936,29 +1115,33 @@ error('Cannot require a meta file') ---capability. --- ---@since 3.17.0 ----@field itemDefaults? anonym3 +---@field itemDefaults? lsp._anonym2.itemDefaults +--- ---The completion items. ---@field items lsp.CompletionItem[] ---Registration options for a {@link CompletionRequest}. ----@class lsp.CompletionRegistrationOptions: lsp.TextDocumentRegistrationOptions +---@class lsp.CompletionRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.CompletionOptions ---Parameters for a {@link HoverRequest}. ---@class lsp.HoverParams: lsp.TextDocumentPositionParams, lsp.WorkDoneProgressParams ---The result of a hover request. ---@class lsp.Hover +--- ---The hover's content ---@field contents lsp.MarkupContent|lsp.MarkedString|lsp.MarkedString[] +--- ---An optional range inside the text document that is used to ---visualize the hover, e.g. by changing the background color. ---@field range? lsp.Range ---Registration options for a {@link HoverRequest}. ----@class lsp.HoverRegistrationOptions: lsp.TextDocumentRegistrationOptions +---@class lsp.HoverRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.HoverOptions ---Parameters for a {@link SignatureHelpRequest}. ---@class lsp.SignatureHelpParams: lsp.TextDocumentPositionParams, lsp.WorkDoneProgressParams +--- ---The signature help context. This is only available if the client specifies ---to send this using the client capability `textDocument.signatureHelp.contextSupport === true` --- @@ -969,8 +1152,10 @@ error('Cannot require a meta file') ---callable. There can be multiple signature but only one ---active and only one active parameter. ---@class lsp.SignatureHelp +--- ---One or more signatures. ---@field signatures lsp.SignatureInformation[] +--- ---The active signature. If omitted or the value lies outside the ---range of `signatures` the value defaults to zero or is ignored if ---the `SignatureHelp` has no signatures. @@ -981,30 +1166,41 @@ error('Cannot require a meta file') ---In future version of the protocol this property might become ---mandatory to better express this. ---@field activeSignature? uinteger ----The active parameter of the active signature. If omitted or the value ----lies outside the range of `signatures[activeSignature].parameters` ----defaults to 0 if the active signature has parameters. If ----the active signature has no parameters it is ignored. +--- +---The active parameter of the active signature. +--- +---If `null`, no parameter of the signature is active (for example a named +---argument that does not match any declared parameters). This is only valid +---since 3.18.0 and if the client specifies the client capability +---`textDocument.signatureHelp.noActiveParameterSupport === true` +--- +---If omitted or the value lies outside the range of +---`signatures[activeSignature].parameters` defaults to 0 if the active +---signature has parameters. +--- +---If the active signature has no parameters it is ignored. +--- ---In future version of the protocol this property might become ----mandatory to better express the active parameter if the ----active signature does have any. ----@field activeParameter? uinteger +---mandatory (but still nullable) to better express the active parameter if +---the active signature does have any. +---@field activeParameter? uinteger|lsp.null ---Registration options for a {@link SignatureHelpRequest}. ----@class lsp.SignatureHelpRegistrationOptions: lsp.TextDocumentRegistrationOptions +---@class lsp.SignatureHelpRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.SignatureHelpOptions ---Parameters for a {@link DefinitionRequest}. ---@class lsp.DefinitionParams: lsp.TextDocumentPositionParams, lsp.WorkDoneProgressParams, lsp.PartialResultParams ---Registration options for a {@link DefinitionRequest}. ----@class lsp.DefinitionRegistrationOptions: lsp.TextDocumentRegistrationOptions +---@class lsp.DefinitionRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.DefinitionOptions ---Parameters for a {@link ReferencesRequest}. ---@class lsp.ReferenceParams: lsp.TextDocumentPositionParams, lsp.WorkDoneProgressParams, lsp.PartialResultParams +--- ---@field context lsp.ReferenceContext ---Registration options for a {@link ReferencesRequest}. ----@class lsp.ReferenceRegistrationOptions: lsp.TextDocumentRegistrationOptions +---@class lsp.ReferenceRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.ReferenceOptions ---Parameters for a {@link DocumentHighlightRequest}. ---@class lsp.DocumentHighlightParams: lsp.TextDocumentPositionParams, lsp.WorkDoneProgressParams, lsp.PartialResultParams @@ -1013,26 +1209,31 @@ error('Cannot require a meta file') ---special attention. Usually a document highlight is visualized by changing ---the background color of its range. ---@class lsp.DocumentHighlight +--- ---The range this highlight applies to. ---@field range lsp.Range +--- ---The highlight kind, default is {@link DocumentHighlightKind.Text text}. ---@field kind? lsp.DocumentHighlightKind ---Registration options for a {@link DocumentHighlightRequest}. ----@class lsp.DocumentHighlightRegistrationOptions: lsp.TextDocumentRegistrationOptions +---@class lsp.DocumentHighlightRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.DocumentHighlightOptions ---Parameters for a {@link DocumentSymbolRequest}. ----@class lsp.DocumentSymbolParams +---@class lsp.DocumentSymbolParams: lsp.WorkDoneProgressParams, lsp.PartialResultParams +--- ---The text document. ---@field textDocument lsp.TextDocumentIdentifier ---Represents information about programming constructs like variables, classes, ---interfaces etc. ---@class lsp.SymbolInformation: lsp.BaseSymbolInformation +--- ---Indicates if this symbol is deprecated. --- ---@deprecated Use tags instead ---@field deprecated? boolean +--- ---The location of this symbol. The location's range is used by a tool ---to reveal the location in the editor. If the symbol is selected in the ---tool the range's start information is used to position the cursor. So @@ -1049,40 +1250,51 @@ error('Cannot require a meta file') ---have two ranges: one that encloses its definition and one that points to ---its most interesting range, e.g. the range of an identifier. ---@class lsp.DocumentSymbol +--- ---The name of this symbol. Will be displayed in the user interface and therefore must not be ---an empty string or a string only consisting of white spaces. ---@field name string +--- ---More detail for this symbol, e.g the signature of a function. ---@field detail? string +--- ---The kind of this symbol. ---@field kind lsp.SymbolKind +--- ---Tags for this document symbol. --- ---@since 3.16.0 ---@field tags? lsp.SymbolTag[] +--- ---Indicates if this symbol is deprecated. --- ---@deprecated Use tags instead ---@field deprecated? boolean +--- ---The range enclosing this symbol not including leading/trailing whitespace but everything else ---like comments. This information is typically used to determine if the clients cursor is ---inside the symbol to reveal in the symbol in the UI. ---@field range lsp.Range +--- ---The range that should be selected and revealed when this symbol is being picked, e.g the name of a function. ---Must be contained by the `range`. ---@field selectionRange lsp.Range +--- ---Children of this symbol, e.g. properties of a class. ---@field children? lsp.DocumentSymbol[] ---Registration options for a {@link DocumentSymbolRequest}. ----@class lsp.DocumentSymbolRegistrationOptions: lsp.TextDocumentRegistrationOptions +---@class lsp.DocumentSymbolRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.DocumentSymbolOptions ---The parameters of a {@link CodeActionRequest}. ----@class lsp.CodeActionParams +---@class lsp.CodeActionParams: lsp.WorkDoneProgressParams, lsp.PartialResultParams +--- ---The document in which the command was invoked. ---@field textDocument lsp.TextDocumentIdentifier +--- ---The range for which the command was invoked. ---@field range lsp.Range +--- ---Context carrying additional information. ---@field context lsp.CodeActionContext @@ -1091,10 +1303,13 @@ error('Cannot require a meta file') ---an array of arguments which will be passed to the command handler ---function when invoked. ---@class lsp.Command +--- ---Title of the command, like `save`. ---@field title string +--- ---The identifier of the actual command handler. ---@field command string +--- ---Arguments that the command handler should be ---invoked with. ---@field arguments? lsp.LSPAny[] @@ -1104,14 +1319,18 @@ error('Cannot require a meta file') --- ---A CodeAction must set either `edit` and/or a `command`. If both are supplied, the `edit` is applied first, then the `command` is executed. ---@class lsp.CodeAction +--- ---A short, human-readable, title for this code action. ---@field title string +--- ---The kind of the code action. --- ---Used to filter code actions. ---@field kind? lsp.CodeActionKind +--- ---The diagnostics that this code action resolves. ---@field diagnostics? lsp.Diagnostic[] +--- ---Marks this as a preferred action. Preferred actions are used by the `auto fix` command and can be targeted ---by keybindings. --- @@ -1120,6 +1339,7 @@ error('Cannot require a meta file') --- ---@since 3.15.0 ---@field isPreferred? boolean +--- ---Marks that the code action cannot currently be applied. --- ---Clients should follow the following guidelines regarding disabled code actions: @@ -1135,13 +1355,16 @@ error('Cannot require a meta file') --- error message with `reason` in the editor. --- ---@since 3.16.0 ----@field disabled? anonym4 +---@field disabled? lsp._anonym4.disabled +--- ---The workspace edit this code action performs. ---@field edit? lsp.WorkspaceEdit +--- ---A command this code action executes. If a code action ---provides an edit and a command, first the edit is ---executed and then the command. ---@field command? lsp.Command +--- ---A data entry field that is preserved on a code action between ---a `textDocument/codeAction` and a `codeAction/resolve` request. --- @@ -1149,10 +1372,11 @@ error('Cannot require a meta file') ---@field data? lsp.LSPAny ---Registration options for a {@link CodeActionRequest}. ----@class lsp.CodeActionRegistrationOptions: lsp.TextDocumentRegistrationOptions +---@class lsp.CodeActionRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.CodeActionOptions ---The parameters of a {@link WorkspaceSymbolRequest}. ----@class lsp.WorkspaceSymbolParams +---@class lsp.WorkspaceSymbolParams: lsp.WorkDoneProgressParams, lsp.PartialResultParams +--- ---A query string to filter symbols by. Clients may send an empty ---string here to request all symbols. ---@field query string @@ -1163,12 +1387,14 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.WorkspaceSymbol: lsp.BaseSymbolInformation +--- ---The location of the symbol. Whether a server is allowed to ---return a location without a range depends on the client ---capability `workspace.symbol.resolveSupport`. --- ---See SymbolInformation#location for more details. ----@field location lsp.Location|anonym5 +---@field location lsp.Location|lsp._anonym5.location +--- ---A data entry field that is preserved on a workspace symbol between a ---workspace symbol request and a workspace symbol resolve request. ---@field data? lsp.LSPAny @@ -1177,7 +1403,8 @@ error('Cannot require a meta file') ---@class lsp.WorkspaceSymbolRegistrationOptions: lsp.WorkspaceSymbolOptions ---The parameters of a {@link CodeLensRequest}. ----@class lsp.CodeLensParams +---@class lsp.CodeLensParams: lsp.WorkDoneProgressParams, lsp.PartialResultParams +--- ---The document to request code lens for. ---@field textDocument lsp.TextDocumentIdentifier @@ -1187,30 +1414,36 @@ error('Cannot require a meta file') ---A code lens is _unresolved_ when no command is associated to it. For performance ---reasons the creation of a code lens and resolving should be done in two stages. ---@class lsp.CodeLens +--- ---The range in which this code lens is valid. Should only span a single line. ---@field range lsp.Range +--- ---The command this code lens represents. ---@field command? lsp.Command +--- ---A data entry field that is preserved on a code lens item between ----a {@link CodeLensRequest} and a [CodeLensResolveRequest] ----(#CodeLensResolveRequest) +---a {@link CodeLensRequest} and a {@link CodeLensResolveRequest} ---@field data? lsp.LSPAny ---Registration options for a {@link CodeLensRequest}. ----@class lsp.CodeLensRegistrationOptions: lsp.TextDocumentRegistrationOptions +---@class lsp.CodeLensRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.CodeLensOptions ---The parameters of a {@link DocumentLinkRequest}. ----@class lsp.DocumentLinkParams +---@class lsp.DocumentLinkParams: lsp.WorkDoneProgressParams, lsp.PartialResultParams +--- ---The document to provide document links for. ---@field textDocument lsp.TextDocumentIdentifier ---A document link is a range in a text document that links to an internal or external resource, like another ---text document or a web site. ---@class lsp.DocumentLink +--- ---The range this link applies to. ---@field range lsp.Range +--- ---The uri this link points to. If missing a resolve request is sent later. ---@field target? lsp.URI +--- ---The tooltip text when you hover over this link. --- ---If a tooltip is provided, is will be displayed in a string that includes instructions on how to @@ -1219,86 +1452,104 @@ error('Cannot require a meta file') --- ---@since 3.15.0 ---@field tooltip? string +--- ---A data entry field that is preserved on a document link between a ---DocumentLinkRequest and a DocumentLinkResolveRequest. ---@field data? lsp.LSPAny ---Registration options for a {@link DocumentLinkRequest}. ----@class lsp.DocumentLinkRegistrationOptions: lsp.TextDocumentRegistrationOptions +---@class lsp.DocumentLinkRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.DocumentLinkOptions ---The parameters of a {@link DocumentFormattingRequest}. ----@class lsp.DocumentFormattingParams +---@class lsp.DocumentFormattingParams: lsp.WorkDoneProgressParams +--- ---The document to format. ---@field textDocument lsp.TextDocumentIdentifier +--- ---The format options. ---@field options lsp.FormattingOptions ---Registration options for a {@link DocumentFormattingRequest}. ----@class lsp.DocumentFormattingRegistrationOptions: lsp.TextDocumentRegistrationOptions +---@class lsp.DocumentFormattingRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.DocumentFormattingOptions ---The parameters of a {@link DocumentRangeFormattingRequest}. ----@class lsp.DocumentRangeFormattingParams +---@class lsp.DocumentRangeFormattingParams: lsp.WorkDoneProgressParams +--- ---The document to format. ---@field textDocument lsp.TextDocumentIdentifier +--- ---The range to format ---@field range lsp.Range +--- ---The format options ---@field options lsp.FormattingOptions ---Registration options for a {@link DocumentRangeFormattingRequest}. ----@class lsp.DocumentRangeFormattingRegistrationOptions: lsp.TextDocumentRegistrationOptions +---@class lsp.DocumentRangeFormattingRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.DocumentRangeFormattingOptions ---The parameters of a {@link DocumentRangesFormattingRequest}. --- ---@since 3.18.0 ---@proposed ----@class lsp.DocumentRangesFormattingParams +---@class lsp.DocumentRangesFormattingParams: lsp.WorkDoneProgressParams +--- ---The document to format. ---@field textDocument lsp.TextDocumentIdentifier +--- ---The ranges to format ---@field ranges lsp.Range[] +--- ---The format options ---@field options lsp.FormattingOptions ---The parameters of a {@link DocumentOnTypeFormattingRequest}. ---@class lsp.DocumentOnTypeFormattingParams +--- ---The document to format. ---@field textDocument lsp.TextDocumentIdentifier +--- ---The position around which the on type formatting should happen. ---This is not necessarily the exact position where the character denoted ---by the property `ch` got typed. ---@field position lsp.Position +--- ---The character that has been typed that triggered the formatting ---on type request. That is not necessarily the last character that ---got inserted into the document since the client could auto insert ---characters as well (e.g. like automatic brace completion). ---@field ch string +--- ---The formatting options. ---@field options lsp.FormattingOptions ---Registration options for a {@link DocumentOnTypeFormattingRequest}. ----@class lsp.DocumentOnTypeFormattingRegistrationOptions: lsp.TextDocumentRegistrationOptions +---@class lsp.DocumentOnTypeFormattingRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.DocumentOnTypeFormattingOptions ---The parameters of a {@link RenameRequest}. ----@class lsp.RenameParams +---@class lsp.RenameParams: lsp.WorkDoneProgressParams +--- ---The document to rename. ---@field textDocument lsp.TextDocumentIdentifier +--- ---The position at which this request was sent. ---@field position lsp.Position +--- ---The new name of the symbol. If the given name is not valid the ---request must return a {@link ResponseError} with an ---appropriate message set. ---@field newName string ---Registration options for a {@link RenameRequest}. ----@class lsp.RenameRegistrationOptions: lsp.TextDocumentRegistrationOptions +---@class lsp.RenameRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.RenameOptions ---@class lsp.PrepareRenameParams: lsp.TextDocumentPositionParams, lsp.WorkDoneProgressParams ---The parameters of a {@link ExecuteCommandRequest}. ----@class lsp.ExecuteCommandParams +---@class lsp.ExecuteCommandParams: lsp.WorkDoneProgressParams +--- ---The identifier of the actual command handler. ---@field command string +--- ---Arguments that the command should be invoked with. ---@field arguments? lsp.LSPAny[] @@ -1307,10 +1558,12 @@ error('Cannot require a meta file') ---The parameters passed via an apply workspace edit request. ---@class lsp.ApplyWorkspaceEditParams +--- ---An optional label of the workspace edit. This label is ---presented in the user interface for example on an undo ---stack to undo the workspace edit. ---@field label? string +--- ---The edits to apply. ---@field edit lsp.WorkspaceEdit @@ -1318,34 +1571,42 @@ error('Cannot require a meta file') --- ---@since 3.17 renamed from ApplyWorkspaceEditResponse ---@class lsp.ApplyWorkspaceEditResult +--- ---Indicates whether the edit was applied or not. ---@field applied boolean +--- ---An optional textual description for why the edit was not applied. ---This may be used by the server for diagnostic logging or to provide ---a suitable error for a request that triggered the edit. ---@field failureReason? string +--- ---Depending on the client's failure handling strategy `failedChange` might ---contain the index of the change that failed. This property is only available ---if the client signals a `failureHandlingStrategy` in its client capabilities. ---@field failedChange? uinteger ---@class lsp.WorkDoneProgressBegin +--- ---@field kind "begin" +--- ---Mandatory title of the progress operation. Used to briefly inform about ---the kind of operation being performed. --- ---Examples: "Indexing" or "Linking dependencies". ---@field title string +--- ---Controls if a cancel button should show to allow the user to cancel the ---long running operation. Clients that don't support cancellation are allowed ---to ignore the setting. ---@field cancellable? boolean +--- ---Optional, more detailed associated progress message. Contains ---complementary information to the `title`. --- ---Examples: "3/25 files", "project/src/module2", "node_modules/some_dep". ---If unset, the previous progress message (if any) is still valid. ---@field message? string +--- ---Optional progress percentage to display (value 100 is considered 100%). ---If not provided infinite progress is assumed and clients are allowed ---to ignore the `percentage` value in subsequent in report notifications. @@ -1355,18 +1616,22 @@ error('Cannot require a meta file') ---@field percentage? uinteger ---@class lsp.WorkDoneProgressReport +--- ---@field kind "report" +--- ---Controls enablement state of a cancel button. --- ---Clients that don't support cancellation or don't support controlling the button's ---enablement state are allowed to ignore the property. ---@field cancellable? boolean +--- ---Optional, more detailed associated progress message. Contains ---complementary information to the `title`. --- ---Examples: "3/25 files", "project/src/module2", "node_modules/some_dep". ---If unset, the previous progress message (if any) is still valid. ---@field message? string +--- ---Optional progress percentage to display (value 100 is considered 100%). ---If not provided infinite progress is assumed and clients are allowed ---to ignore the `percentage` value in subsequent in report notifications. @@ -1376,41 +1641,53 @@ error('Cannot require a meta file') ---@field percentage? uinteger ---@class lsp.WorkDoneProgressEnd +--- ---@field kind "end" +--- ---Optional, a final message indicating to for example indicate the outcome ---of the operation. ---@field message? string ---@class lsp.SetTraceParams +--- ---@field value lsp.TraceValues ---@class lsp.LogTraceParams +--- ---@field message string +--- ---@field verbose? string ---@class lsp.CancelParams +--- ---The request id to cancel. ---@field id integer|string ---@class lsp.ProgressParams +--- ---The progress token provided by the client or server. ---@field token lsp.ProgressToken +--- ---The progress data. ---@field value lsp.LSPAny ---A parameter literal used in requests to pass a text document and a position inside that ---document. ---@class lsp.TextDocumentPositionParams +--- ---The text document. ---@field textDocument lsp.TextDocumentIdentifier +--- ---The position inside the text document. ---@field position lsp.Position ---@class lsp.WorkDoneProgressParams +--- ---An optional token that a server can use to report work done progress. ---@field workDoneToken? lsp.ProgressToken ---@class lsp.PartialResultParams +--- ---An optional token that a server can use to report partial results (e.g. streaming) to ---the client. ---@field partialResultToken? lsp.ProgressToken @@ -1418,17 +1695,21 @@ error('Cannot require a meta file') ---Represents the connection of two locations. Provides additional metadata over normal {@link Location locations}, ---including an origin range. ---@class lsp.LocationLink +--- ---Span of the origin of this link. --- ---Used as the underlined span for mouse interaction. Defaults to the word range at ---the definition position. ---@field originSelectionRange? lsp.Range +--- ---The target resource identifier of this link. ---@field targetUri lsp.DocumentUri +--- ---The full target range of this link. If the target for example is a symbol then target range is the ---range enclosing this symbol not including leading/trailing whitespace but everything else ---like comments. This information is typically used to highlight the range in the editor. ---@field targetRange lsp.Range +--- ---The range that should be selected and revealed when this link is being followed, e.g the name of a function. ---Must be contained by the `targetRange`. See also `DocumentSymbol#range` ---@field targetSelectionRange lsp.Range @@ -1445,56 +1726,68 @@ error('Cannot require a meta file') ---} ---``` ---@class lsp.Range +--- ---The range's start position. ---@field start lsp.Position +--- ---The range's end position. ---@field end lsp.Position ----@class lsp.ImplementationOptions +---@class lsp.ImplementationOptions: lsp.WorkDoneProgressOptions ---Static registration options to be returned in the initialize ---request. ---@class lsp.StaticRegistrationOptions +--- ---The id used to register the request. The id can be used to deregister ---the request again. See also Registration#id. ---@field id? string ----@class lsp.TypeDefinitionOptions +---@class lsp.TypeDefinitionOptions: lsp.WorkDoneProgressOptions ---The workspace folder change event. ---@class lsp.WorkspaceFoldersChangeEvent +--- ---The array of added workspace folders ---@field added lsp.WorkspaceFolder[] +--- ---The array of the removed workspace folders ---@field removed lsp.WorkspaceFolder[] ---@class lsp.ConfigurationItem +--- ---The scope to get the configuration section for. ----@field scopeUri? string +---@field scopeUri? lsp.URI +--- ---The configuration section asked for. ---@field section? string ---A literal to identify a text document in the client. ---@class lsp.TextDocumentIdentifier +--- ---The text document's uri. ---@field uri lsp.DocumentUri ---Represents a color in RGBA space. ---@class lsp.Color +--- ---The red component of this color in the range [0-1]. ---@field red decimal +--- ---The green component of this color in the range [0-1]. ---@field green decimal +--- ---The blue component of this color in the range [0-1]. ---@field blue decimal +--- ---The alpha component of this color in the range [0-1]. ---@field alpha decimal ----@class lsp.DocumentColorOptions +---@class lsp.DocumentColorOptions: lsp.WorkDoneProgressOptions ----@class lsp.FoldingRangeOptions +---@class lsp.FoldingRangeOptions: lsp.WorkDoneProgressOptions ----@class lsp.DeclarationOptions +---@class lsp.DeclarationOptions: lsp.WorkDoneProgressOptions ---Position in a text document expressed as zero-based line and character ---offset. Prior to 3.17 the offsets were always based on a UTF-16 string @@ -1503,14 +1796,14 @@ error('Cannot require a meta file') ---offset of b is 3 since `𐐀` is represented using two code units in UTF-16. ---Since 3.17 clients and servers can agree on a different string encoding ---representation (e.g. UTF-8). The client announces it's supported encoding ----via the client capability [`general.positionEncodings`](#clientCapabilities). +---via the client capability [`general.positionEncodings`](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#clientCapabilities). ---The value is an array of position encodings the client supports, with ---decreasing preference (e.g. the encoding at index `0` is the most preferred ---one). To stay backwards compatible the only mandatory encoding is UTF-16 ---represented via the string `utf-16`. The server can pick one of the ---encodings offered by the client and signals that encoding back to the ---client via the initialize result's property ----[`capabilities.positionEncoding`](#serverCapabilities). If the string value +---[`capabilities.positionEncoding`](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#serverCapabilities). If the string value ---`utf-16` is missing from the client's capability `general.positionEncodings` ---servers can safely assume that the client supports UTF-16. If the server ---omits the position encoding in its initialize result the encoding defaults @@ -1524,11 +1817,13 @@ error('Cannot require a meta file') --- ---@since 3.17.0 - support for negotiated position encoding. ---@class lsp.Position +--- ---Line position in a document (zero-based). --- ---If a line number is greater than the number of lines in a document, it defaults back to the number of lines in the document. ---If a line number is negative, it defaults to 0. ---@field line uinteger +--- ---Character offset on a line in a document (zero-based). --- ---The meaning of this offset is determined by the negotiated @@ -1538,38 +1833,45 @@ error('Cannot require a meta file') ---line length. ---@field character uinteger ----@class lsp.SelectionRangeOptions +---@class lsp.SelectionRangeOptions: lsp.WorkDoneProgressOptions ---Call hierarchy options used during static registration. --- ---@since 3.16.0 ----@class lsp.CallHierarchyOptions +---@class lsp.CallHierarchyOptions: lsp.WorkDoneProgressOptions ---@since 3.16.0 ----@class lsp.SemanticTokensOptions +---@class lsp.SemanticTokensOptions: lsp.WorkDoneProgressOptions +--- ---The legend used by the server ---@field legend lsp.SemanticTokensLegend +--- ---Server supports providing semantic tokens for a specific range ---of a document. ----@field range? boolean|anonym6 +---@field range? boolean|lsp._anonym6.range +--- ---Server supports providing semantic tokens for a full document. ----@field full? boolean|anonym7 +---@field full? boolean|lsp._anonym7.full ---@since 3.16.0 ---@class lsp.SemanticTokensEdit +--- ---The start offset of the edit. ---@field start uinteger +--- ---The count of elements to remove. ---@field deleteCount uinteger +--- ---The elements to insert. ---@field data? uinteger[] ----@class lsp.LinkedEditingRangeOptions +---@class lsp.LinkedEditingRangeOptions: lsp.WorkDoneProgressOptions ---Represents information on a file/folder create. --- ---@since 3.16.0 ---@class lsp.FileCreate +--- ---A file:// URI for the location of the file/folder being created. ---@field uri string @@ -1578,40 +1880,52 @@ error('Cannot require a meta file') ---So the creator of a TextDocumentEdit doesn't need to sort the array of edits or do any ---kind of ordering. However the edits must be non overlapping. ---@class lsp.TextDocumentEdit +--- ---The text document to change. ---@field textDocument lsp.OptionalVersionedTextDocumentIdentifier +--- ---The edits to be applied. --- ---@since 3.16.0 - support for AnnotatedTextEdit. This is guarded using a ---client capability. ----@field edits lsp.TextEdit|lsp.AnnotatedTextEdit[] +---@field edits (lsp.TextEdit|lsp.AnnotatedTextEdit)[] ---Create file operation. ---@class lsp.CreateFile: lsp.ResourceOperation +--- ---A create ---@field kind "create" +--- ---The resource to create. ---@field uri lsp.DocumentUri +--- ---Additional options ---@field options? lsp.CreateFileOptions ---Rename file operation ---@class lsp.RenameFile: lsp.ResourceOperation +--- ---A rename ---@field kind "rename" +--- ---The old (existing) location. ---@field oldUri lsp.DocumentUri +--- ---The new location. ---@field newUri lsp.DocumentUri +--- ---Rename options. ---@field options? lsp.RenameFileOptions ---Delete file operation ---@class lsp.DeleteFile: lsp.ResourceOperation +--- ---A delete ---@field kind "delete" +--- ---The file to delete. ---@field uri lsp.DocumentUri +--- ---Delete options. ---@field options? lsp.DeleteFileOptions @@ -1619,12 +1933,15 @@ error('Cannot require a meta file') --- ---@since 3.16.0 ---@class lsp.ChangeAnnotation +--- ---A human-readable string describing the actual change. The string ---is rendered prominent in the user interface. ---@field label string +--- ---A flag which indicates that user confirmation is needed ---before applying the change. ---@field needsConfirmation? boolean +--- ---A human-readable string which is rendered less prominent in ---the user interface. ---@field description? string @@ -1634,8 +1951,10 @@ error('Cannot require a meta file') --- ---@since 3.16.0 ---@class lsp.FileOperationFilter +--- ---A Uri scheme like `file` or `untitled`. ---@field scheme? string +--- ---The actual file operation pattern. ---@field pattern lsp.FileOperationPattern @@ -1643,8 +1962,10 @@ error('Cannot require a meta file') --- ---@since 3.16.0 ---@class lsp.FileRename +--- ---A file:// URI for the original location of the file/folder being renamed. ---@field oldUri string +--- ---A file:// URI for the new location of the file/folder being renamed. ---@field newUri string @@ -1652,20 +1973,23 @@ error('Cannot require a meta file') --- ---@since 3.16.0 ---@class lsp.FileDelete +--- ---A file:// URI for the location of the file/folder being deleted. ---@field uri string ----@class lsp.MonikerOptions +---@class lsp.MonikerOptions: lsp.WorkDoneProgressOptions ---Type hierarchy options used during static registration. --- ---@since 3.17.0 ----@class lsp.TypeHierarchyOptions +---@class lsp.TypeHierarchyOptions: lsp.WorkDoneProgressOptions ---@since 3.17.0 ---@class lsp.InlineValueContext +--- ---The stack frame (as a DAP Id) where the execution has stopped. ---@field frameId integer +--- ---The document range where execution has stopped. ---Typically the end position of the range denotes the line where the inline values are shown. ---@field stoppedLocation lsp.Range @@ -1674,8 +1998,10 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.InlineValueText +--- ---The document range for which the inline value applies. ---@field range lsp.Range +--- ---The text of the inline value. ---@field text string @@ -1685,11 +2011,14 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.InlineValueVariableLookup +--- ---The document range for which the inline value applies. ---The range is used to extract the variable name from the underlying document. ---@field range lsp.Range +--- ---If specified the name of the variable to look up. ---@field variableName? string +--- ---How to perform the lookup. ---@field caseSensitiveLookup boolean @@ -1699,28 +2028,33 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.InlineValueEvaluatableExpression +--- ---The document range for which the inline value applies. ---The range is used to extract the evaluatable expression from the underlying document. ---@field range lsp.Range +--- ---If specified the expression overrides the extracted expression. ---@field expression? string ---Inline value options used during static registration. --- ---@since 3.17.0 ----@class lsp.InlineValueOptions +---@class lsp.InlineValueOptions: lsp.WorkDoneProgressOptions ---An inlay hint label part allows for interactive and composite labels ---of inlay hints. --- ---@since 3.17.0 ---@class lsp.InlayHintLabelPart +--- ---The value of this label part. ---@field value string +--- ---The tooltip text when you hover over this label part. Depending on ---the client capability `inlayHint.resolveSupport` clients might resolve ---this property late using the resolve request. ---@field tooltip? string|lsp.MarkupContent +--- ---An optional source code location that represents this ---label part. --- @@ -1733,6 +2067,7 @@ error('Cannot require a meta file') ---Depending on the client capability `inlayHint.resolveSupport` clients ---might resolve this property late using the resolve request. ---@field location? lsp.Location +--- ---An optional command for this label part. --- ---Depending on the client capability `inlayHint.resolveSupport` clients @@ -1762,15 +2097,18 @@ error('Cannot require a meta file') ---*Please Note* that clients might sanitize the return markdown. A client could decide to ---remove HTML from the markdown to avoid script execution. ---@class lsp.MarkupContent +--- ---The type of the Markup ---@field kind lsp.MarkupKind +--- ---The content itself ---@field value string ---Inlay hint options used during static registration. --- ---@since 3.17.0 ----@class lsp.InlayHintOptions +---@class lsp.InlayHintOptions: lsp.WorkDoneProgressOptions +--- ---The server provides support to resolve additional ---information for an inlay hint item. ---@field resolveProvider? boolean @@ -1779,6 +2117,7 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.RelatedFullDocumentDiagnosticReport: lsp.FullDocumentDiagnosticReport +--- ---Diagnostics of related documents. This information is useful ---in programming languages where code in a file A can generate ---diagnostics in a file B which A depends on. An example of @@ -1792,6 +2131,7 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.RelatedUnchangedDocumentDiagnosticReport: lsp.UnchangedDocumentDiagnosticReport +--- ---Diagnostics of related documents. This information is useful ---in programming languages where code in a file A can generate ---diagnostics in a file B which A depends on. An example of @@ -1805,12 +2145,15 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.FullDocumentDiagnosticReport +--- ---A full document diagnostic report. ---@field kind "full" +--- ---An optional result id. If provided it will ---be sent on the next diagnostic request for the ---same document. ---@field resultId? string +--- ---The actual items. ---@field items lsp.Diagnostic[] @@ -1819,11 +2162,13 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.UnchangedDocumentDiagnosticReport +--- ---A document diagnostic report indicating ---no changes to the last result. A server can ---only return `unchanged` if result ids are ---provided. ---@field kind "unchanged" +--- ---A result id which will be sent on the next ---diagnostic request for the same document. ---@field resultId string @@ -1831,15 +2176,18 @@ error('Cannot require a meta file') ---Diagnostic options. --- ---@since 3.17.0 ----@class lsp.DiagnosticOptions +---@class lsp.DiagnosticOptions: lsp.WorkDoneProgressOptions +--- ---An optional identifier under which the diagnostics are ---managed by the client. ---@field identifier? string +--- ---Whether the language has inter file dependencies meaning that ---editing code in one file can result in a different diagnostic ---set in another file. Inter file dependencies are common for ---most programming languages and typically uncommon for linters. ---@field interFileDependencies boolean +--- ---The server provides support for workspace diagnostics as well. ---@field workspaceDiagnostics boolean @@ -1847,9 +2195,11 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.PreviousResultId +--- ---The URI for which the client knowns a ---result id. ---@field uri lsp.DocumentUri +--- ---The value of the previous result id. ---@field value string @@ -1857,31 +2207,40 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.NotebookDocument +--- ---The notebook document's uri. ---@field uri lsp.URI +--- ---The type of the notebook. ---@field notebookType string +--- ---The version number of this document (it will increase after each ---change, including undo/redo). ---@field version integer +--- ---Additional metadata stored with the notebook ---document. --- ---Note: should always be an object literal (e.g. LSPObject) ---@field metadata? lsp.LSPObject +--- ---The cells of a notebook. ---@field cells lsp.NotebookCell[] ---An item to transfer a text document from the client to the ---server. ---@class lsp.TextDocumentItem +--- ---The text document's uri. ---@field uri lsp.DocumentUri +--- ---The text document's language identifier. ---@field languageId string +--- ---The version number of this document (it will increase after each ---change, including undo/redo). ---@field version integer +--- ---The content of the opened text document. ---@field text string @@ -1889,8 +2248,10 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.VersionedNotebookDocumentIdentifier +--- ---The version number of this notebook document. ---@field version integer +--- ---The notebook document's uri. ---@field uri lsp.URI @@ -1898,64 +2259,97 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.NotebookDocumentChangeEvent +--- ---The changed meta data if any. --- ---Note: should always be an object literal (e.g. LSPObject) ---@field metadata? lsp.LSPObject +--- ---Changes to cells ----@field cells? anonym10 +---@field cells? lsp._anonym8.cells ---A literal to identify a notebook document in the client. --- ---@since 3.17.0 ---@class lsp.NotebookDocumentIdentifier +--- ---The notebook document's uri. ---@field uri lsp.URI ---Provides information about the context in which an inline completion was requested. --- ---@since 3.18.0 +---@proposed ---@class lsp.InlineCompletionContext +--- ---Describes how the inline completion was triggered. ---@field triggerKind lsp.InlineCompletionTriggerKind +--- ---Provides information about the currently selected item in the autocomplete widget if it is visible. ---@field selectedCompletionInfo? lsp.SelectedCompletionInfo +---A string value used as a snippet is a template which allows to insert text +---and to control the editor cursor when insertion happens. +--- +---A snippet can define tab stops and placeholders with `$1`, `$2` +---and `${3:foo}`. `$0` defines the final tab stop, it defaults to +---the end of the snippet. Variables are defined with `$name` and +---`${name:default value}`. +--- +---@since 3.18.0 +---@proposed +---@class lsp.StringValue +--- +---The kind of string value. +---@field kind "snippet" +--- +---The snippet string. +---@field value string + ---Inline completion options used during static registration. --- ---@since 3.18.0 ----@class lsp.InlineCompletionOptions +---@proposed +---@class lsp.InlineCompletionOptions: lsp.WorkDoneProgressOptions ----General parameters to to register for an notification or to register a provider. +---General parameters to register for a notification or to register a provider. ---@class lsp.Registration +--- ---The id used to register the request. The id can be used to deregister ---the request again. ---@field id string +--- ---The method / capability to register for. ---@field method string +--- ---Options necessary for the registration. ---@field registerOptions? lsp.LSPAny ---General parameters to unregister a request or notification. ---@class lsp.Unregistration +--- ---The id used to unregister the request or notification. Usually an id ---provided during the register request. ---@field id string +--- ---The method to unregister for. ---@field method string ---The initialize parameters ----@class lsp._InitializeParams +---@class lsp._InitializeParams: lsp.WorkDoneProgressParams +--- ---The process Id of the parent process that started ---the server. --- ---Is `null` if the process has not been started by another process. ---If the parent process is not alive then the server should exit. ---@field processId integer|lsp.null +--- ---Information about the client --- ---@since 3.15.0 ----@field clientInfo? anonym11 +---@field clientInfo? lsp._anonym11.clientInfo +--- ---The locale the client is currently showing the user interface ---in. This must not necessarily be the locale of the operating ---system. @@ -1965,25 +2359,31 @@ error('Cannot require a meta file') --- ---@since 3.16.0 ---@field locale? string +--- ---The rootPath of the workspace. Is null ---if no folder is open. --- ---@deprecated in favour of rootUri. ---@field rootPath? string|lsp.null +--- ---The rootUri of the workspace. Is null if no ---folder is open. If both `rootPath` and `rootUri` are set ---`rootUri` wins. --- ---@deprecated in favour of workspaceFolders. ---@field rootUri lsp.DocumentUri|lsp.null +--- ---The capabilities provided by the client (editor or tool) ---@field capabilities lsp.ClientCapabilities +--- ---User provided initialization options. ---@field initializationOptions? lsp.LSPAny +--- ---The initial trace setting. If omitted trace is disabled ('off'). ---@field trace? lsp.TraceValues ---@class lsp.WorkspaceFoldersInitializeParams +--- ---The workspace folders configured in the client when the server starts. --- ---This property is only available if the client supports workspace folders. @@ -1996,6 +2396,7 @@ error('Cannot require a meta file') ---Defines the capabilities provided by a language ---server. ---@class lsp.ServerCapabilities +--- ---The position encoding the server picked from the encodings offered ---by the client via the client capability `general.positionEncodings`. --- @@ -2006,125 +2407,167 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@field positionEncoding? lsp.PositionEncodingKind +--- ---Defines how text documents are synced. Is either a detailed structure ---defining each notification or for backwards compatibility the ---TextDocumentSyncKind number. ---@field textDocumentSync? lsp.TextDocumentSyncOptions|lsp.TextDocumentSyncKind +--- ---Defines how notebook documents are synced. --- ---@since 3.17.0 ---@field notebookDocumentSync? lsp.NotebookDocumentSyncOptions|lsp.NotebookDocumentSyncRegistrationOptions +--- ---The server provides completion support. ---@field completionProvider? lsp.CompletionOptions +--- ---The server provides hover support. ---@field hoverProvider? boolean|lsp.HoverOptions +--- ---The server provides signature help support. ---@field signatureHelpProvider? lsp.SignatureHelpOptions +--- ---The server provides Goto Declaration support. ---@field declarationProvider? boolean|lsp.DeclarationOptions|lsp.DeclarationRegistrationOptions +--- ---The server provides goto definition support. ---@field definitionProvider? boolean|lsp.DefinitionOptions +--- ---The server provides Goto Type Definition support. ---@field typeDefinitionProvider? boolean|lsp.TypeDefinitionOptions|lsp.TypeDefinitionRegistrationOptions +--- ---The server provides Goto Implementation support. ---@field implementationProvider? boolean|lsp.ImplementationOptions|lsp.ImplementationRegistrationOptions +--- ---The server provides find references support. ---@field referencesProvider? boolean|lsp.ReferenceOptions +--- ---The server provides document highlight support. ---@field documentHighlightProvider? boolean|lsp.DocumentHighlightOptions +--- ---The server provides document symbol support. ---@field documentSymbolProvider? boolean|lsp.DocumentSymbolOptions +--- ---The server provides code actions. CodeActionOptions may only be ---specified if the client states that it supports ---`codeActionLiteralSupport` in its initial `initialize` request. ---@field codeActionProvider? boolean|lsp.CodeActionOptions +--- ---The server provides code lens. ---@field codeLensProvider? lsp.CodeLensOptions +--- ---The server provides document link support. ---@field documentLinkProvider? lsp.DocumentLinkOptions +--- ---The server provides color provider support. ---@field colorProvider? boolean|lsp.DocumentColorOptions|lsp.DocumentColorRegistrationOptions +--- ---The server provides workspace symbol support. ---@field workspaceSymbolProvider? boolean|lsp.WorkspaceSymbolOptions +--- ---The server provides document formatting. ---@field documentFormattingProvider? boolean|lsp.DocumentFormattingOptions +--- ---The server provides document range formatting. ---@field documentRangeFormattingProvider? boolean|lsp.DocumentRangeFormattingOptions +--- ---The server provides document formatting on typing. ---@field documentOnTypeFormattingProvider? lsp.DocumentOnTypeFormattingOptions +--- ---The server provides rename support. RenameOptions may only be ---specified if the client states that it supports ---`prepareSupport` in its initial `initialize` request. ---@field renameProvider? boolean|lsp.RenameOptions +--- ---The server provides folding provider support. ---@field foldingRangeProvider? boolean|lsp.FoldingRangeOptions|lsp.FoldingRangeRegistrationOptions +--- ---The server provides selection range support. ---@field selectionRangeProvider? boolean|lsp.SelectionRangeOptions|lsp.SelectionRangeRegistrationOptions +--- ---The server provides execute command support. ---@field executeCommandProvider? lsp.ExecuteCommandOptions +--- ---The server provides call hierarchy support. --- ---@since 3.16.0 ---@field callHierarchyProvider? boolean|lsp.CallHierarchyOptions|lsp.CallHierarchyRegistrationOptions +--- ---The server provides linked editing range support. --- ---@since 3.16.0 ---@field linkedEditingRangeProvider? boolean|lsp.LinkedEditingRangeOptions|lsp.LinkedEditingRangeRegistrationOptions +--- ---The server provides semantic tokens support. --- ---@since 3.16.0 ---@field semanticTokensProvider? lsp.SemanticTokensOptions|lsp.SemanticTokensRegistrationOptions +--- ---The server provides moniker support. --- ---@since 3.16.0 ---@field monikerProvider? boolean|lsp.MonikerOptions|lsp.MonikerRegistrationOptions +--- ---The server provides type hierarchy support. --- ---@since 3.17.0 ---@field typeHierarchyProvider? boolean|lsp.TypeHierarchyOptions|lsp.TypeHierarchyRegistrationOptions +--- ---The server provides inline values. --- ---@since 3.17.0 ---@field inlineValueProvider? boolean|lsp.InlineValueOptions|lsp.InlineValueRegistrationOptions +--- ---The server provides inlay hints. --- ---@since 3.17.0 ---@field inlayHintProvider? boolean|lsp.InlayHintOptions|lsp.InlayHintRegistrationOptions +--- ---The server has support for pull model diagnostics. --- ---@since 3.17.0 ---@field diagnosticProvider? lsp.DiagnosticOptions|lsp.DiagnosticRegistrationOptions +--- ---Inline completion options used during static registration. --- ---@since 3.18.0 +---@proposed ---@field inlineCompletionProvider? boolean|lsp.InlineCompletionOptions +--- ---Workspace specific server capabilities. ----@field workspace? anonym12 +---@field workspace? lsp._anonym12.workspace +--- ---Experimental server capabilities. ---@field experimental? lsp.LSPAny ---A text document identifier to denote a specific version of a text document. ---@class lsp.VersionedTextDocumentIdentifier: lsp.TextDocumentIdentifier +--- ---The version number of this document. ---@field version integer ---Save options. ---@class lsp.SaveOptions +--- ---The client is supposed to include the content on save. ---@field includeText? boolean ---An event describing a file change. ---@class lsp.FileEvent +--- ---The file's uri. ---@field uri lsp.DocumentUri +--- ---The change type. ---@field type lsp.FileChangeType ---@class lsp.FileSystemWatcher +--- ---The glob pattern to watch. See {@link GlobPattern glob pattern} for more detail. --- ---@since 3.17.0 support for relative patterns. ---@field globPattern lsp.GlobPattern +--- ---The kind of events of interest. If omitted it defaults ---to WatchKind.Create | WatchKind.Change | WatchKind.Delete ---which is 7. @@ -2133,31 +2576,40 @@ error('Cannot require a meta file') ---Represents a diagnostic, such as a compiler error or warning. Diagnostic objects ---are only valid in the scope of a resource. ---@class lsp.Diagnostic +--- ---The range at which the message applies ---@field range lsp.Range +--- ---The diagnostic's severity. Can be omitted. If omitted it is up to the ---client to interpret diagnostics as error, warning, info or hint. ---@field severity? lsp.DiagnosticSeverity +--- ---The diagnostic's code, which usually appear in the user interface. ---@field code? integer|string +--- ---An optional property to describe the error code. ---Requires the code field (above) to be present/not null. --- ---@since 3.16.0 ---@field codeDescription? lsp.CodeDescription +--- ---A human-readable string describing the source of this ---diagnostic, e.g. 'typescript' or 'super lint'. It usually ---appears in the user interface. ---@field source? string +--- ---The diagnostic's message. It usually appears in the user interface ---@field message string +--- ---Additional metadata about the diagnostic. --- ---@since 3.15.0 ---@field tags? lsp.DiagnosticTag[] +--- ---An array of related diagnostic information, e.g. when symbol-names within ---a scope collide all definitions can be marked via this property. ---@field relatedInformation? lsp.DiagnosticRelatedInformation[] +--- ---A data entry field that is preserved between a `textDocument/publishDiagnostics` ---notification and `textDocument/codeAction` request. --- @@ -2166,8 +2618,10 @@ error('Cannot require a meta file') ---Contains additional information about the context in which a completion request is triggered. ---@class lsp.CompletionContext +--- ---How the completion was triggered. ---@field triggerKind lsp.CompletionTriggerKind +--- ---The trigger character (a single character) that has trigger code complete. ---Is undefined if `triggerKind !== CompletionTriggerKind.TriggerCharacter` ---@field triggerCharacter? string @@ -2176,9 +2630,11 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.CompletionItemLabelDetails +--- ---An optional string which is rendered less prominently directly after {@link CompletionItem.label label}, ---without any spacing. Should be used for function signatures and type annotations. ---@field detail? string +--- ---An optional string which is rendered less prominently after {@link CompletionItem.detail}. Should be used ---for fully qualified names and file paths. ---@field description? string @@ -2187,15 +2643,19 @@ error('Cannot require a meta file') --- ---@since 3.16.0 ---@class lsp.InsertReplaceEdit +--- ---The string to be inserted. ---@field newText string +--- ---The range if the insert is requested ---@field insert lsp.Range +--- ---The range if the replace is requested. ---@field replace lsp.Range ---Completion options. ----@class lsp.CompletionOptions +---@class lsp.CompletionOptions: lsp.WorkDoneProgressOptions +--- ---Most tools trigger completion request automatically without explicitly requesting ---it using a keyboard shortcut (e.g. Ctrl+Space). Typically they do so when the user ---starts to type an identifier. For example if the user types `c` in a JavaScript file @@ -2205,6 +2665,7 @@ error('Cannot require a meta file') ---If code complete should automatically be trigger on characters not being valid inside ---an identifier (for example `.` in JavaScript) list them in `triggerCharacters`. ---@field triggerCharacters? string[] +--- ---The list of all possible characters that commit a completion. This field can be used ---if clients don't support individual commit characters per completion item. See ---`ClientCapabilities.textDocument.completion.completionItem.commitCharactersSupport` @@ -2214,33 +2675,39 @@ error('Cannot require a meta file') --- ---@since 3.2.0 ---@field allCommitCharacters? string[] +--- ---The server provides support to resolve additional ---information for a completion item. ---@field resolveProvider? boolean +--- ---The server supports the following `CompletionItem` specific ---capabilities. --- ---@since 3.17.0 ----@field completionItem? anonym13 +---@field completionItem? lsp._anonym13.completionItem ---Hover options. ----@class lsp.HoverOptions +---@class lsp.HoverOptions: lsp.WorkDoneProgressOptions ---Additional information about the context in which a signature help request was triggered. --- ---@since 3.15.0 ---@class lsp.SignatureHelpContext +--- ---Action that caused signature help to be triggered. ---@field triggerKind lsp.SignatureHelpTriggerKind +--- ---Character that caused signature help to be triggered. --- ---This is undefined when `triggerKind !== SignatureHelpTriggerKind.TriggerCharacter` ---@field triggerCharacter? string +--- ---`true` if signature help was already showing when it was triggered. --- ---Retriggers occurs when the signature help is already active and can be caused by actions such as ---typing a trigger character, a cursor move, or document content changes. ---@field isRetrigger boolean +--- ---The currently active `SignatureHelp`. --- ---The `activeSignatureHelp` has its `SignatureHelp.activeSignature` field updated based on @@ -2251,25 +2718,37 @@ error('Cannot require a meta file') ---can have a label, like a function-name, a doc-comment, and ---a set of parameters. ---@class lsp.SignatureInformation +--- ---The label of this signature. Will be shown in ---the UI. ---@field label string +--- ---The human-readable doc-comment of this signature. Will be shown ---in the UI but can be omitted. ---@field documentation? string|lsp.MarkupContent +--- ---The parameters of this signature. ---@field parameters? lsp.ParameterInformation[] +--- ---The index of the active parameter. --- ----If provided, this is used in place of `SignatureHelp.activeParameter`. +---If `null`, no parameter of the signature is active (for example a named +---argument that does not match any declared parameters). This is only valid +---since 3.18.0 and if the client specifies the client capability +---`textDocument.signatureHelp.noActiveParameterSupport === true` +--- +---If provided (or `null`), this is used in place of +---`SignatureHelp.activeParameter`. --- ---@since 3.16.0 ----@field activeParameter? uinteger +---@field activeParameter? uinteger|lsp.null ---Server Capabilities for a {@link SignatureHelpRequest}. ----@class lsp.SignatureHelpOptions +---@class lsp.SignatureHelpOptions: lsp.WorkDoneProgressOptions +--- ---List of characters that trigger signature help automatically. ---@field triggerCharacters? string[] +--- ---List of characters that re-trigger signature help. --- ---These trigger characters are only active when signature help is already showing. All trigger characters @@ -2279,30 +2758,35 @@ error('Cannot require a meta file') ---@field retriggerCharacters? string[] ---Server Capabilities for a {@link DefinitionRequest}. ----@class lsp.DefinitionOptions +---@class lsp.DefinitionOptions: lsp.WorkDoneProgressOptions ---Value-object that contains additional information when ---requesting references. ---@class lsp.ReferenceContext +--- ---Include the declaration of the current symbol. ---@field includeDeclaration boolean ---Reference options. ----@class lsp.ReferenceOptions +---@class lsp.ReferenceOptions: lsp.WorkDoneProgressOptions ---Provider options for a {@link DocumentHighlightRequest}. ----@class lsp.DocumentHighlightOptions +---@class lsp.DocumentHighlightOptions: lsp.WorkDoneProgressOptions ---A base for all symbol information. ---@class lsp.BaseSymbolInformation +--- ---The name of this symbol. ---@field name string +--- ---The kind of this symbol. ---@field kind lsp.SymbolKind +--- ---Tags for this symbol. --- ---@since 3.16.0 ---@field tags? lsp.SymbolTag[] +--- ---The name of the symbol containing this symbol. This information is for ---user interface purposes (e.g. to render a qualifier in the user interface ---if necessary). It can't be used to re-infer a hierarchy for the document @@ -2310,7 +2794,8 @@ error('Cannot require a meta file') ---@field containerName? string ---Provider options for a {@link DocumentSymbolRequest}. ----@class lsp.DocumentSymbolOptions +---@class lsp.DocumentSymbolOptions: lsp.WorkDoneProgressOptions +--- ---A human-readable string that is shown when multiple outlines trees ---are shown for the same document. --- @@ -2320,29 +2805,34 @@ error('Cannot require a meta file') ---Contains additional diagnostic information about the context in which ---a {@link CodeActionProvider.provideCodeActions code action} is run. ---@class lsp.CodeActionContext +--- ---An array of diagnostics known on the client side overlapping the range provided to the ---`textDocument/codeAction` request. They are provided so that the server knows which ---errors are currently presented to the user for the given range. There is no guarantee ---that these accurately reflect the error state of the resource. The primary parameter ---to compute code actions is the provided range. ---@field diagnostics lsp.Diagnostic[] +--- ---Requested kind of actions to return. --- ---Actions not of this kind are filtered out by the client before being shown. So servers ---can omit computing them. ---@field only? lsp.CodeActionKind[] +--- ---The reason why code actions were requested. --- ---@since 3.17.0 ---@field triggerKind? lsp.CodeActionTriggerKind ---Provider options for a {@link CodeActionRequest}. ----@class lsp.CodeActionOptions +---@class lsp.CodeActionOptions: lsp.WorkDoneProgressOptions +--- ---CodeActionKinds that this server may return. --- ---The list of kinds may be generic, such as `CodeActionKind.Refactor`, or the server ---may list out every specific kind they provide. ---@field codeActionKinds? lsp.CodeActionKind[] +--- ---The server provides support to resolve additional ---information for a code action. --- @@ -2350,7 +2840,8 @@ error('Cannot require a meta file') ---@field resolveProvider? boolean ---Server capabilities for a {@link WorkspaceSymbolRequest}. ----@class lsp.WorkspaceSymbolOptions +---@class lsp.WorkspaceSymbolOptions: lsp.WorkDoneProgressOptions +--- ---The server provides support to resolve additional ---information for a workspace symbol. --- @@ -2358,39 +2849,47 @@ error('Cannot require a meta file') ---@field resolveProvider? boolean ---Code Lens provider options of a {@link CodeLensRequest}. ----@class lsp.CodeLensOptions +---@class lsp.CodeLensOptions: lsp.WorkDoneProgressOptions +--- ---Code lens has a resolve provider as well. ---@field resolveProvider? boolean ---Provider options for a {@link DocumentLinkRequest}. ----@class lsp.DocumentLinkOptions +---@class lsp.DocumentLinkOptions: lsp.WorkDoneProgressOptions +--- ---Document links have a resolve provider as well. ---@field resolveProvider? boolean ---Value-object describing what options formatting should use. ---@class lsp.FormattingOptions +--- ---Size of a tab in spaces. ---@field tabSize uinteger +--- ---Prefer spaces over tabs. ---@field insertSpaces boolean +--- ---Trim trailing whitespace on a line. --- ---@since 3.15.0 ---@field trimTrailingWhitespace? boolean +--- ---Insert a newline character at the end of the file if one does not exist. --- ---@since 3.15.0 ---@field insertFinalNewline? boolean +--- ---Trim all newlines after the final newline at the end of the file. --- ---@since 3.15.0 ---@field trimFinalNewlines? boolean ---Provider options for a {@link DocumentFormattingRequest}. ----@class lsp.DocumentFormattingOptions +---@class lsp.DocumentFormattingOptions: lsp.WorkDoneProgressOptions ---Provider options for a {@link DocumentRangeFormattingRequest}. ----@class lsp.DocumentRangeFormattingOptions +---@class lsp.DocumentRangeFormattingOptions: lsp.WorkDoneProgressOptions +--- ---Whether the server supports formatting multiple ranges at once. --- ---@since 3.18.0 @@ -2399,32 +2898,39 @@ error('Cannot require a meta file') ---Provider options for a {@link DocumentOnTypeFormattingRequest}. ---@class lsp.DocumentOnTypeFormattingOptions +--- ---A character on which formatting should be triggered, like `{`. ---@field firstTriggerCharacter string +--- ---More trigger characters. ---@field moreTriggerCharacter? string[] ---Provider options for a {@link RenameRequest}. ----@class lsp.RenameOptions +---@class lsp.RenameOptions: lsp.WorkDoneProgressOptions +--- ---Renames should be checked and tested before being executed. --- ---@since version 3.12.0 ---@field prepareProvider? boolean ---The server capabilities of a {@link ExecuteCommandRequest}. ----@class lsp.ExecuteCommandOptions +---@class lsp.ExecuteCommandOptions: lsp.WorkDoneProgressOptions +--- ---The commands to be executed on the server ---@field commands string[] ---@since 3.16.0 ---@class lsp.SemanticTokensLegend +--- ---The token types a server uses. ---@field tokenTypes string[] +--- ---The token modifiers a server uses. ---@field tokenModifiers string[] ---A text document identifier to optionally denote a specific version of a text document. ---@class lsp.OptionalVersionedTextDocumentIdentifier: lsp.TextDocumentIdentifier +--- ---The version number of this document. If a versioned text document identifier ---is sent from the server to the client and the file is not open in the editor ---(the server has not received an open notification before) the server can send @@ -2436,13 +2942,16 @@ error('Cannot require a meta file') --- ---@since 3.16.0. ---@class lsp.AnnotatedTextEdit: lsp.TextEdit +--- ---The actual identifier of the change annotation ---@field annotationId lsp.ChangeAnnotationIdentifier ---A generic resource operation. ---@class lsp.ResourceOperation +--- ---The resource operation kind. ---@field kind string +--- ---An optional annotation identifier describing the operation. --- ---@since 3.16.0 @@ -2450,22 +2959,28 @@ error('Cannot require a meta file') ---Options to create a file. ---@class lsp.CreateFileOptions +--- ---Overwrite existing file. Overwrite wins over `ignoreIfExists` ---@field overwrite? boolean +--- ---Ignore if exists. ---@field ignoreIfExists? boolean ---Rename file options ---@class lsp.RenameFileOptions +--- ---Overwrite target if existing. Overwrite wins over `ignoreIfExists` ---@field overwrite? boolean +--- ---Ignores if target exists. ---@field ignoreIfExists? boolean ---Delete file options ---@class lsp.DeleteFileOptions +--- ---Delete the content recursively if a folder is denoted. ---@field recursive? boolean +--- ---Ignore the operation if the file doesn't exist. ---@field ignoreIfNotExists? boolean @@ -2474,18 +2989,21 @@ error('Cannot require a meta file') --- ---@since 3.16.0 ---@class lsp.FileOperationPattern +--- ---The glob pattern to match. Glob patterns can have the following syntax: ---- `*` to match one or more characters in a path segment ---- `?` to match on one character in a path segment ---- `**` to match any number of path segments, including none ----- `{}` to group sub patterns into an OR expression. (e.g. `**/*.{ts,js}` matches all TypeScript and JavaScript files) +---- `{}` to group sub patterns into an OR expression. (e.g. `**/*.{ts,js}` matches all TypeScript and JavaScript files) ---- `[]` to declare a range of characters to match in a path segment (e.g., `example.[0-9]` to match on `example.0`, `example.1`, …) ---- `[!...]` to negate a range of characters to match in a path segment (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but not `example.0`) ---@field glob string +--- ---Whether to match files or folders with this pattern. --- ---Matches both if undefined. ---@field matches? lsp.FileOperationPatternKind +--- ---Additional options used during matching. ---@field options? lsp.FileOperationPatternOptions @@ -2493,8 +3011,10 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.WorkspaceFullDocumentDiagnosticReport: lsp.FullDocumentDiagnosticReport +--- ---The URI for which diagnostic information is reported. ---@field uri lsp.DocumentUri +--- ---The version number for which the diagnostics are reported. ---If the document is not marked as open `null` can be provided. ---@field version integer|lsp.null @@ -2503,8 +3023,10 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.WorkspaceUnchangedDocumentDiagnosticReport: lsp.UnchangedDocumentDiagnosticReport +--- ---The URI for which diagnostic information is reported. ---@field uri lsp.DocumentUri +--- ---The version number for which the diagnostics are reported. ---If the document is not marked as open `null` can be provided. ---@field version integer|lsp.null @@ -2517,15 +3039,19 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.NotebookCell +--- ---The cell's kind ---@field kind lsp.NotebookCellKind +--- ---The URI of the cell's text document ---content. ---@field document lsp.DocumentUri +--- ---Additional metadata stored with the cell. --- ---Note: should always be an object literal (e.g. LSPObject) ---@field metadata? lsp.LSPObject +--- ---Additional execution summary information ---if supported by the client. ---@field executionSummary? lsp.ExecutionSummary @@ -2535,54 +3061,71 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.NotebookCellArrayChange +--- ---The start oftest of the cell that changed. ---@field start uinteger +--- ---The deleted cells ---@field deleteCount uinteger +--- ---The new cells, if any ---@field cells? lsp.NotebookCell[] ---Describes the currently selected completion item. --- ---@since 3.18.0 +---@proposed ---@class lsp.SelectedCompletionInfo +--- ---The range that will be replaced if this completion item is accepted. ---@field range lsp.Range +--- ---The text the range will be replaced with if this completion is accepted. ---@field text string ---Defines the capabilities provided by the client. ---@class lsp.ClientCapabilities +--- ---Workspace specific client capabilities. ---@field workspace? lsp.WorkspaceClientCapabilities +--- ---Text document specific client capabilities. ---@field textDocument? lsp.TextDocumentClientCapabilities +--- ---Capabilities specific to the notebook document support. --- ---@since 3.17.0 ---@field notebookDocument? lsp.NotebookDocumentClientCapabilities +--- ---Window specific client capabilities. ---@field window? lsp.WindowClientCapabilities +--- ---General client capabilities. --- ---@since 3.16.0 ---@field general? lsp.GeneralClientCapabilities +--- ---Experimental client capabilities. ---@field experimental? lsp.LSPAny ---@class lsp.TextDocumentSyncOptions +--- ---Open and close notifications are sent to the server. If omitted open close notification should not ---be sent. ---@field openClose? boolean +--- ---Change notifications are sent to the server. See TextDocumentSyncKind.None, TextDocumentSyncKind.Full ---and TextDocumentSyncKind.Incremental. If omitted it defaults to TextDocumentSyncKind.None. ---@field change? lsp.TextDocumentSyncKind +--- ---If present will save notifications are sent to the server. If omitted the notification should not be ---sent. ---@field willSave? boolean +--- ---If present will save wait until requests are sent to the server. If omitted the request should not be ---sent. ---@field willSaveWaitUntil? boolean +--- ---If present save notifications are sent to the server. If omitted the notification should not be ---sent. ---@field save? boolean|lsp.SaveOptions @@ -2601,8 +3144,10 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.NotebookDocumentSyncOptions +--- ---The notebooks to be synced ----@field notebookSelector anonym15|anonym17[] +---@field notebookSelector (lsp._anonym14.notebookSelector|lsp._anonym16.notebookSelector)[] +--- ---Whether save notification should be forwarded to ---the server. Will only be honored if mode === `notebook`. ---@field save? boolean @@ -2613,8 +3158,10 @@ error('Cannot require a meta file') ---@class lsp.NotebookDocumentSyncRegistrationOptions: lsp.NotebookDocumentSyncOptions, lsp.StaticRegistrationOptions ---@class lsp.WorkspaceFoldersServerCapabilities +--- ---The server has support for workspace folders ---@field supported? boolean +--- ---Whether the server wants to receive workspace folder ---change notifications. --- @@ -2628,16 +3175,22 @@ error('Cannot require a meta file') --- ---@since 3.16.0 ---@class lsp.FileOperationOptions +--- ---The server is interested in receiving didCreateFiles notifications. ---@field didCreate? lsp.FileOperationRegistrationOptions +--- ---The server is interested in receiving willCreateFiles requests. ---@field willCreate? lsp.FileOperationRegistrationOptions +--- ---The server is interested in receiving didRenameFiles notifications. ---@field didRename? lsp.FileOperationRegistrationOptions +--- ---The server is interested in receiving willRenameFiles requests. ---@field willRename? lsp.FileOperationRegistrationOptions +--- ---The server is interested in receiving didDeleteFiles file notifications. ---@field didDelete? lsp.FileOperationRegistrationOptions +--- ---The server is interested in receiving willDeleteFiles file requests. ---@field willDelete? lsp.FileOperationRegistrationOptions @@ -2645,6 +3198,7 @@ error('Cannot require a meta file') --- ---@since 3.16.0 ---@class lsp.CodeDescription +--- ---An URI to open with more information about the diagnostic error. ---@field href lsp.URI @@ -2652,14 +3206,17 @@ error('Cannot require a meta file') ---used to point to code locations that cause or related to a diagnostics, e.g when duplicating ---a symbol in a scope. ---@class lsp.DiagnosticRelatedInformation +--- ---The location of this related diagnostic information. ---@field location lsp.Location +--- ---The message of this related diagnostic information. ---@field message string ---Represents a parameter of a callable-signature. A parameter can ---have a label and a doc-comment. ---@class lsp.ParameterInformation +--- ---The label of this parameter information. --- ---Either a string or an inclusive start and exclusive end offsets within its containing @@ -2669,6 +3226,7 @@ error('Cannot require a meta file') ---*Note*: a label of type string should be a substring of its containing signature label. ---Its intended use case is to highlight the parameter label part in the `SignatureInformation.label`. ---@field label string|{ [1]: uinteger, [2]: uinteger } +--- ---The human-readable doc-comment of this parameter. Will be shown ---in the UI but can be omitted. ---@field documentation? string|lsp.MarkupContent @@ -2678,11 +3236,13 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.NotebookCellTextDocumentFilter +--- ---A filter that matches against the notebook ---containing the notebook cell. If a string ---value is provided it matches against the ---notebook type. '*' matches every notebook. ---@field notebook string|lsp.NotebookDocumentFilter +--- ---A language id like `python`. --- ---Will be matched against the language id of the @@ -2693,178 +3253,235 @@ error('Cannot require a meta file') --- ---@since 3.16.0 ---@class lsp.FileOperationPatternOptions +--- ---The pattern should be matched ignoring casing. ---@field ignoreCase? boolean ---@class lsp.ExecutionSummary +--- ---A strict monotonically increasing value ---indicating the execution order of a cell ---inside a notebook. ---@field executionOrder uinteger +--- ---Whether the execution was successful or ---not if known by the client. ---@field success? boolean ---Workspace specific client capabilities. ---@class lsp.WorkspaceClientCapabilities +--- ---The client supports applying batch edits ---to the workspace by supporting the request ---'workspace/applyEdit' ---@field applyEdit? boolean +--- ---Capabilities specific to `WorkspaceEdit`s. ---@field workspaceEdit? lsp.WorkspaceEditClientCapabilities +--- ---Capabilities specific to the `workspace/didChangeConfiguration` notification. ---@field didChangeConfiguration? lsp.DidChangeConfigurationClientCapabilities +--- ---Capabilities specific to the `workspace/didChangeWatchedFiles` notification. ---@field didChangeWatchedFiles? lsp.DidChangeWatchedFilesClientCapabilities +--- ---Capabilities specific to the `workspace/symbol` request. ---@field symbol? lsp.WorkspaceSymbolClientCapabilities +--- ---Capabilities specific to the `workspace/executeCommand` request. ---@field executeCommand? lsp.ExecuteCommandClientCapabilities +--- ---The client has support for workspace folders. --- ---@since 3.6.0 ---@field workspaceFolders? boolean +--- ---The client supports `workspace/configuration` requests. --- ---@since 3.6.0 ---@field configuration? boolean +--- ---Capabilities specific to the semantic token requests scoped to the ---workspace. --- ---@since 3.16.0. ---@field semanticTokens? lsp.SemanticTokensWorkspaceClientCapabilities +--- ---Capabilities specific to the code lens requests scoped to the ---workspace. --- ---@since 3.16.0. ---@field codeLens? lsp.CodeLensWorkspaceClientCapabilities +--- ---The client has support for file notifications/requests for user operations on files. --- ---Since 3.16.0 ---@field fileOperations? lsp.FileOperationClientCapabilities +--- ---Capabilities specific to the inline values requests scoped to the ---workspace. --- ---@since 3.17.0. ---@field inlineValue? lsp.InlineValueWorkspaceClientCapabilities +--- ---Capabilities specific to the inlay hint requests scoped to the ---workspace. --- ---@since 3.17.0. ---@field inlayHint? lsp.InlayHintWorkspaceClientCapabilities +--- ---Capabilities specific to the diagnostic requests scoped to the ---workspace. --- ---@since 3.17.0. ---@field diagnostics? lsp.DiagnosticWorkspaceClientCapabilities +--- +---Capabilities specific to the folding range requests scoped to the workspace. +--- +---@since 3.18.0 +---@proposed +---@field foldingRange? lsp.FoldingRangeWorkspaceClientCapabilities ---Text document specific client capabilities. ---@class lsp.TextDocumentClientCapabilities +--- ---Defines which synchronization capabilities the client supports. ---@field synchronization? lsp.TextDocumentSyncClientCapabilities +--- ---Capabilities specific to the `textDocument/completion` request. ---@field completion? lsp.CompletionClientCapabilities +--- ---Capabilities specific to the `textDocument/hover` request. ---@field hover? lsp.HoverClientCapabilities +--- ---Capabilities specific to the `textDocument/signatureHelp` request. ---@field signatureHelp? lsp.SignatureHelpClientCapabilities +--- ---Capabilities specific to the `textDocument/declaration` request. --- ---@since 3.14.0 ---@field declaration? lsp.DeclarationClientCapabilities +--- ---Capabilities specific to the `textDocument/definition` request. ---@field definition? lsp.DefinitionClientCapabilities +--- ---Capabilities specific to the `textDocument/typeDefinition` request. --- ---@since 3.6.0 ---@field typeDefinition? lsp.TypeDefinitionClientCapabilities +--- ---Capabilities specific to the `textDocument/implementation` request. --- ---@since 3.6.0 ---@field implementation? lsp.ImplementationClientCapabilities +--- ---Capabilities specific to the `textDocument/references` request. ---@field references? lsp.ReferenceClientCapabilities +--- ---Capabilities specific to the `textDocument/documentHighlight` request. ---@field documentHighlight? lsp.DocumentHighlightClientCapabilities +--- ---Capabilities specific to the `textDocument/documentSymbol` request. ---@field documentSymbol? lsp.DocumentSymbolClientCapabilities +--- ---Capabilities specific to the `textDocument/codeAction` request. ---@field codeAction? lsp.CodeActionClientCapabilities +--- ---Capabilities specific to the `textDocument/codeLens` request. ---@field codeLens? lsp.CodeLensClientCapabilities +--- ---Capabilities specific to the `textDocument/documentLink` request. ---@field documentLink? lsp.DocumentLinkClientCapabilities +--- ---Capabilities specific to the `textDocument/documentColor` and the ---`textDocument/colorPresentation` request. --- ---@since 3.6.0 ---@field colorProvider? lsp.DocumentColorClientCapabilities +--- ---Capabilities specific to the `textDocument/formatting` request. ---@field formatting? lsp.DocumentFormattingClientCapabilities +--- ---Capabilities specific to the `textDocument/rangeFormatting` request. ---@field rangeFormatting? lsp.DocumentRangeFormattingClientCapabilities +--- ---Capabilities specific to the `textDocument/onTypeFormatting` request. ---@field onTypeFormatting? lsp.DocumentOnTypeFormattingClientCapabilities +--- ---Capabilities specific to the `textDocument/rename` request. ---@field rename? lsp.RenameClientCapabilities +--- ---Capabilities specific to the `textDocument/foldingRange` request. --- ---@since 3.10.0 ---@field foldingRange? lsp.FoldingRangeClientCapabilities +--- ---Capabilities specific to the `textDocument/selectionRange` request. --- ---@since 3.15.0 ---@field selectionRange? lsp.SelectionRangeClientCapabilities +--- ---Capabilities specific to the `textDocument/publishDiagnostics` notification. ---@field publishDiagnostics? lsp.PublishDiagnosticsClientCapabilities +--- ---Capabilities specific to the various call hierarchy requests. --- ---@since 3.16.0 ---@field callHierarchy? lsp.CallHierarchyClientCapabilities +--- ---Capabilities specific to the various semantic token request. --- ---@since 3.16.0 ---@field semanticTokens? lsp.SemanticTokensClientCapabilities +--- ---Capabilities specific to the `textDocument/linkedEditingRange` request. --- ---@since 3.16.0 ---@field linkedEditingRange? lsp.LinkedEditingRangeClientCapabilities +--- ---Client capabilities specific to the `textDocument/moniker` request. --- ---@since 3.16.0 ---@field moniker? lsp.MonikerClientCapabilities +--- ---Capabilities specific to the various type hierarchy requests. --- ---@since 3.17.0 ---@field typeHierarchy? lsp.TypeHierarchyClientCapabilities +--- ---Capabilities specific to the `textDocument/inlineValue` request. --- ---@since 3.17.0 ---@field inlineValue? lsp.InlineValueClientCapabilities +--- ---Capabilities specific to the `textDocument/inlayHint` request. --- ---@since 3.17.0 ---@field inlayHint? lsp.InlayHintClientCapabilities +--- ---Capabilities specific to the diagnostic pull model. --- ---@since 3.17.0 ---@field diagnostic? lsp.DiagnosticClientCapabilities +--- ---Client capabilities specific to inline completions. --- ---@since 3.18.0 +---@proposed ---@field inlineCompletion? lsp.InlineCompletionClientCapabilities ---Capabilities specific to the notebook document support. --- ---@since 3.17.0 ---@class lsp.NotebookDocumentClientCapabilities +--- ---Capabilities specific to notebook document synchronization --- ---@since 3.17.0 ---@field synchronization lsp.NotebookDocumentSyncClientCapabilities ---@class lsp.WindowClientCapabilities +--- ---It indicates whether the client supports server initiated ---progress using the `window/workDoneProgress/create` request. --- @@ -2875,10 +3492,12 @@ error('Cannot require a meta file') --- ---@since 3.15.0 ---@field workDoneProgress? boolean +--- ---Capabilities specific to the showMessage request. --- ---@since 3.16.0 ---@field showMessage? lsp.ShowMessageRequestClientCapabilities +--- ---Capabilities specific to the showDocument request. --- ---@since 3.16.0 @@ -2888,21 +3507,25 @@ error('Cannot require a meta file') --- ---@since 3.16.0 ---@class lsp.GeneralClientCapabilities +--- ---Client capability that signals how the client ---handles stale requests (e.g. a request ---for which the client will not process the response ---anymore since the information is outdated). --- ---@since 3.17.0 ----@field staleRequestSupport? anonym18 +---@field staleRequestSupport? lsp._anonym18.staleRequestSupport +--- ---Client capabilities specific to regular expressions. --- ---@since 3.16.0 ---@field regularExpressions? lsp.RegularExpressionsClientCapabilities +--- ---Client capabilities specific to the client's markdown parser. --- ---@since 3.16.0 ---@field markdown? lsp.MarkdownClientCapabilities +--- ---The position encodings supported by the client. Client and server ---have to agree on the same position encoding to ensure that offsets ---(e.g. character position in a line) are interpreted the same on both @@ -2929,25 +3552,31 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.RelativePattern +--- ---A workspace folder or a base URI to which this pattern will be matched ---against relatively. ---@field baseUri lsp.WorkspaceFolder|lsp.URI +--- ---The actual glob pattern; ---@field pattern lsp.Pattern ---@class lsp.WorkspaceEditClientCapabilities +--- ---The client supports versioned document changes in `WorkspaceEdit`s ---@field documentChanges? boolean +--- ---The resource operations the client supports. Clients should at least ---support 'create', 'rename' and 'delete' files and folders. --- ---@since 3.13.0 ---@field resourceOperations? lsp.ResourceOperationKind[] +--- ---The failure handling strategy of a client if applying the workspace edit ---fails. --- ---@since 3.13.0 ---@field failureHandling? lsp.FailureHandlingKind +--- ---Whether the client normalizes line endings to the client specific ---setting. ---If set to `true` the client will normalize line ending characters @@ -2956,21 +3585,25 @@ error('Cannot require a meta file') --- ---@since 3.16.0 ---@field normalizesLineEndings? boolean +--- ---Whether the client in general supports change annotations on text edits, ---create file, rename file and delete file changes. --- ---@since 3.16.0 ----@field changeAnnotationSupport? anonym19 +---@field changeAnnotationSupport? lsp._anonym19.changeAnnotationSupport ---@class lsp.DidChangeConfigurationClientCapabilities +--- ---Did change configuration notification supports dynamic registration. ---@field dynamicRegistration? boolean ---@class lsp.DidChangeWatchedFilesClientCapabilities +--- ---Did change watched files notification supports dynamic registration. Please note ---that the current protocol doesn't support static configuration for file changes ---from the server side. ---@field dynamicRegistration? boolean +--- ---Whether the client has support for {@link RelativePattern relative pattern} ---or not. --- @@ -2979,29 +3612,35 @@ error('Cannot require a meta file') ---Client capabilities for a {@link WorkspaceSymbolRequest}. ---@class lsp.WorkspaceSymbolClientCapabilities +--- ---Symbol request supports dynamic registration. ---@field dynamicRegistration? boolean +--- ---Specific capabilities for the `SymbolKind` in the `workspace/symbol` request. ----@field symbolKind? anonym20 +---@field symbolKind? lsp._anonym20.symbolKind +--- ---The client supports tags on `SymbolInformation`. ---Clients supporting tags have to handle unknown tags gracefully. --- ---@since 3.16.0 ----@field tagSupport? anonym21 +---@field tagSupport? lsp._anonym21.tagSupport +--- ---The client support partial workspace symbols. The client will send the ---request `workspaceSymbol/resolve` to the server to resolve additional ---properties. --- ---@since 3.17.0 ----@field resolveSupport? anonym22 +---@field resolveSupport? lsp._anonym22.resolveSupport ---The client capabilities of a {@link ExecuteCommandRequest}. ---@class lsp.ExecuteCommandClientCapabilities +--- ---Execute command supports dynamic registration. ---@field dynamicRegistration? boolean ---@since 3.16.0 ---@class lsp.SemanticTokensWorkspaceClientCapabilities +--- ---Whether the client implementation supports a refresh request sent from ---the server to the client. --- @@ -3013,6 +3652,7 @@ error('Cannot require a meta file') ---@since 3.16.0 ---@class lsp.CodeLensWorkspaceClientCapabilities +--- ---Whether the client implementation supports a refresh request sent from the ---server to the client. --- @@ -3029,18 +3669,25 @@ error('Cannot require a meta file') --- ---@since 3.16.0 ---@class lsp.FileOperationClientCapabilities +--- ---Whether the client supports dynamic registration for file requests/notifications. ---@field dynamicRegistration? boolean +--- ---The client has support for sending didCreateFiles notifications. ---@field didCreate? boolean +--- ---The client has support for sending willCreateFiles requests. ---@field willCreate? boolean +--- ---The client has support for sending didRenameFiles notifications. ---@field didRename? boolean +--- ---The client has support for sending willRenameFiles requests. ---@field willRename? boolean +--- ---The client has support for sending didDeleteFiles notifications. ---@field didDelete? boolean +--- ---The client has support for sending willDeleteFiles requests. ---@field willDelete? boolean @@ -3048,6 +3695,7 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.InlineValueWorkspaceClientCapabilities +--- ---Whether the client implementation supports a refresh request sent from the ---server to the client. --- @@ -3061,6 +3709,7 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.InlayHintWorkspaceClientCapabilities +--- ---Whether the client implementation supports a refresh request sent from ---the server to the client. --- @@ -3074,6 +3723,7 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.DiagnosticWorkspaceClientCapabilities +--- ---Whether the client implementation supports a refresh request sent from ---the server to the client. --- @@ -3083,55 +3733,88 @@ error('Cannot require a meta file') ---change that requires such a calculation. ---@field refreshSupport? boolean +---Client workspace capabilities specific to folding ranges +--- +---@since 3.18.0 +---@proposed +---@class lsp.FoldingRangeWorkspaceClientCapabilities +--- +---Whether the client implementation supports a refresh request sent from the +---server to the client. +--- +---Note that this event is global and will force the client to refresh all +---folding ranges currently shown. It should be used with absolute care and is +---useful for situation where a server for example detects a project wide +---change that requires such a calculation. +--- +---@since 3.18.0 +---@proposed +---@field refreshSupport? boolean + ---@class lsp.TextDocumentSyncClientCapabilities +--- ---Whether text document synchronization supports dynamic registration. ---@field dynamicRegistration? boolean +--- ---The client supports sending will save notifications. ---@field willSave? boolean +--- ---The client supports sending a will save request and ---waits for a response providing text edits which will ---be applied to the document before it is saved. ---@field willSaveWaitUntil? boolean +--- ---The client supports did save notifications. ---@field didSave? boolean ---Completion client capabilities ---@class lsp.CompletionClientCapabilities +--- ---Whether completion supports dynamic registration. ---@field dynamicRegistration? boolean +--- ---The client supports the following `CompletionItem` specific ---capabilities. ----@field completionItem? anonym26 ----@field completionItemKind? anonym27 +---@field completionItem? lsp._anonym23.completionItem +--- +---@field completionItemKind? lsp._anonym27.completionItemKind +--- ---Defines how the client handles whitespace and indentation ---when accepting a completion item that uses multi line ---text in either `insertText` or `textEdit`. --- ---@since 3.17.0 ---@field insertTextMode? lsp.InsertTextMode +--- ---The client supports to send additional context information for a ---`textDocument/completion` request. ---@field contextSupport? boolean +--- ---The client supports the following `CompletionList` specific ---capabilities. --- ---@since 3.17.0 ----@field completionList? anonym28 +---@field completionList? lsp._anonym28.completionList ---@class lsp.HoverClientCapabilities +--- ---Whether hover supports dynamic registration. ---@field dynamicRegistration? boolean +--- ---Client supports the following content formats for the content ---property. The order describes the preferred format of the client. ---@field contentFormat? lsp.MarkupKind[] ---Client Capabilities for a {@link SignatureHelpRequest}. ---@class lsp.SignatureHelpClientCapabilities +--- ---Whether signature help supports dynamic registration. ---@field dynamicRegistration? boolean +--- ---The client supports the following `SignatureInformation` ---specific properties. ----@field signatureInformation? anonym30 +---@field signatureInformation? lsp._anonym29.signatureInformation +--- ---The client supports to send additional context information for a ---`textDocument/signatureHelp` request. A client that opts into ---contextSupport will also support the `retriggerCharacters` on @@ -3142,17 +3825,21 @@ error('Cannot require a meta file') ---@since 3.14.0 ---@class lsp.DeclarationClientCapabilities +--- ---Whether declaration supports dynamic registration. If this is set to `true` ---the client supports the new `DeclarationRegistrationOptions` return value ---for the corresponding server capability as well. ---@field dynamicRegistration? boolean +--- ---The client supports additional metadata in the form of declaration links. ---@field linkSupport? boolean ---Client Capabilities for a {@link DefinitionRequest}. ---@class lsp.DefinitionClientCapabilities +--- ---Whether definition supports dynamic registration. ---@field dynamicRegistration? boolean +--- ---The client supports additional metadata in the form of definition links. --- ---@since 3.14.0 @@ -3160,10 +3847,12 @@ error('Cannot require a meta file') ---Since 3.6.0 ---@class lsp.TypeDefinitionClientCapabilities +--- ---Whether implementation supports dynamic registration. If this is set to `true` ---the client supports the new `TypeDefinitionRegistrationOptions` return value ---for the corresponding server capability as well. ---@field dynamicRegistration? boolean +--- ---The client supports additional metadata in the form of definition links. --- ---Since 3.14.0 @@ -3171,10 +3860,12 @@ error('Cannot require a meta file') ---@since 3.6.0 ---@class lsp.ImplementationClientCapabilities +--- ---Whether implementation supports dynamic registration. If this is set to `true` ---the client supports the new `ImplementationRegistrationOptions` return value ---for the corresponding server capability as well. ---@field dynamicRegistration? boolean +--- ---The client supports additional metadata in the form of definition links. --- ---@since 3.14.0 @@ -3182,29 +3873,36 @@ error('Cannot require a meta file') ---Client Capabilities for a {@link ReferencesRequest}. ---@class lsp.ReferenceClientCapabilities +--- ---Whether references supports dynamic registration. ---@field dynamicRegistration? boolean ---Client Capabilities for a {@link DocumentHighlightRequest}. ---@class lsp.DocumentHighlightClientCapabilities +--- ---Whether document highlight supports dynamic registration. ---@field dynamicRegistration? boolean ---Client Capabilities for a {@link DocumentSymbolRequest}. ---@class lsp.DocumentSymbolClientCapabilities +--- ---Whether document symbol supports dynamic registration. ---@field dynamicRegistration? boolean +--- ---Specific capabilities for the `SymbolKind` in the ---`textDocument/documentSymbol` request. ----@field symbolKind? anonym31 +---@field symbolKind? lsp._anonym31.symbolKind +--- ---The client supports hierarchical document symbols. ---@field hierarchicalDocumentSymbolSupport? boolean +--- ---The client supports tags on `SymbolInformation`. Tags are supported on ---`DocumentSymbol` if `hierarchicalDocumentSymbolSupport` is set to true. ---Clients supporting tags have to handle unknown tags gracefully. --- ---@since 3.16.0 ----@field tagSupport? anonym32 +---@field tagSupport? lsp._anonym32.tagSupport +--- ---The client supports an additional label presented in the UI when ---registering a document symbol provider. --- @@ -3213,33 +3911,40 @@ error('Cannot require a meta file') ---The Client Capabilities of a {@link CodeActionRequest}. ---@class lsp.CodeActionClientCapabilities +--- ---Whether code action supports dynamic registration. ---@field dynamicRegistration? boolean +--- ---The client support code action literals of type `CodeAction` as a valid ---response of the `textDocument/codeAction` request. If the property is not ---set the request can only return `Command` literals. --- ---@since 3.8.0 ----@field codeActionLiteralSupport? anonym34 +---@field codeActionLiteralSupport? lsp._anonym33.codeActionLiteralSupport +--- ---Whether code action supports the `isPreferred` property. --- ---@since 3.15.0 ---@field isPreferredSupport? boolean +--- ---Whether code action supports the `disabled` property. --- ---@since 3.16.0 ---@field disabledSupport? boolean +--- ---Whether code action supports the `data` property which is ---preserved between a `textDocument/codeAction` and a ---`codeAction/resolve` request. --- ---@since 3.16.0 ---@field dataSupport? boolean +--- ---Whether the client supports resolving additional code action ---properties via a separate `codeAction/resolve` request. --- ---@since 3.16.0 ----@field resolveSupport? anonym35 +---@field resolveSupport? lsp._anonym35.resolveSupport +--- ---Whether the client honors the change annotations in ---text edits and resource operations returned via the ---`CodeAction#edit` property by for example presenting @@ -3251,19 +3956,23 @@ error('Cannot require a meta file') ---The client capabilities of a {@link CodeLensRequest}. ---@class lsp.CodeLensClientCapabilities +--- ---Whether code lens supports dynamic registration. ---@field dynamicRegistration? boolean ---The client capabilities of a {@link DocumentLinkRequest}. ---@class lsp.DocumentLinkClientCapabilities +--- ---Whether document link supports dynamic registration. ---@field dynamicRegistration? boolean +--- ---Whether the client supports the `tooltip` property on `DocumentLink`. --- ---@since 3.15.0 ---@field tooltipSupport? boolean ---@class lsp.DocumentColorClientCapabilities +--- ---Whether implementation supports dynamic registration. If this is set to `true` ---the client supports the new `DocumentColorRegistrationOptions` return value ---for the corresponding server capability as well. @@ -3271,13 +3980,16 @@ error('Cannot require a meta file') ---Client capabilities of a {@link DocumentFormattingRequest}. ---@class lsp.DocumentFormattingClientCapabilities +--- ---Whether formatting supports dynamic registration. ---@field dynamicRegistration? boolean ---Client capabilities of a {@link DocumentRangeFormattingRequest}. ---@class lsp.DocumentRangeFormattingClientCapabilities +--- ---Whether range formatting supports dynamic registration. ---@field dynamicRegistration? boolean +--- ---Whether the client supports formatting multiple ranges at once. --- ---@since 3.18.0 @@ -3286,17 +3998,21 @@ error('Cannot require a meta file') ---Client capabilities of a {@link DocumentOnTypeFormattingRequest}. ---@class lsp.DocumentOnTypeFormattingClientCapabilities +--- ---Whether on type formatting supports dynamic registration. ---@field dynamicRegistration? boolean ---@class lsp.RenameClientCapabilities +--- ---Whether rename supports dynamic registration. ---@field dynamicRegistration? boolean +--- ---Client supports testing for validity of rename operations ---before execution. --- ---@since 3.12.0 ---@field prepareSupport? boolean +--- ---Client supports the default behavior result. --- ---The value indicates the default behavior used by the @@ -3304,6 +4020,7 @@ error('Cannot require a meta file') --- ---@since 3.16.0 ---@field prepareSupportDefaultBehavior? lsp.PrepareSupportDefaultBehavior +--- ---Whether the client honors the change annotations in ---text edits and resource operations returned via the ---rename request's workspace edit by for example presenting @@ -3314,29 +4031,35 @@ error('Cannot require a meta file') ---@field honorsChangeAnnotations? boolean ---@class lsp.FoldingRangeClientCapabilities +--- ---Whether implementation supports dynamic registration for folding range ---providers. If this is set to `true` the client supports the new ---`FoldingRangeRegistrationOptions` return value for the corresponding ---server capability as well. ---@field dynamicRegistration? boolean +--- ---The maximum number of folding ranges that the client prefers to receive ---per document. The value serves as a hint, servers are free to follow the ---limit. ---@field rangeLimit? uinteger +--- ---If set, the client signals that it only supports folding complete lines. ---If set, client will ignore specified `startCharacter` and `endCharacter` ---properties in a FoldingRange. ---@field lineFoldingOnly? boolean +--- ---Specific options for the folding range kind. --- ---@since 3.17.0 ----@field foldingRangeKind? anonym36 +---@field foldingRangeKind? lsp._anonym36.foldingRangeKind +--- ---Specific options for the folding range. --- ---@since 3.17.0 ----@field foldingRange? anonym37 +---@field foldingRange? lsp._anonym37.foldingRange ---@class lsp.SelectionRangeClientCapabilities +--- ---Whether implementation supports dynamic registration for selection range providers. If this is set to `true` ---the client supports the new `SelectionRangeRegistrationOptions` return value for the corresponding server ---capability as well. @@ -3344,22 +4067,27 @@ error('Cannot require a meta file') ---The publish diagnostic client capabilities. ---@class lsp.PublishDiagnosticsClientCapabilities +--- ---Whether the clients accepts diagnostics with related information. ---@field relatedInformation? boolean +--- ---Client supports the tag property to provide meta data about a diagnostic. ---Clients supporting tags have to handle unknown tags gracefully. --- ---@since 3.15.0 ----@field tagSupport? anonym38 +---@field tagSupport? lsp._anonym38.tagSupport +--- ---Whether the client interprets the version property of the ---`textDocument/publishDiagnostics` notification's parameter. --- ---@since 3.15.0 ---@field versionSupport? boolean +--- ---Client supports a codeDescription property --- ---@since 3.16.0 ---@field codeDescriptionSupport? boolean +--- ---Whether code action supports the `data` property which is ---preserved between a `textDocument/publishDiagnostics` and ---`textDocument/codeAction` request. @@ -3369,6 +4097,7 @@ error('Cannot require a meta file') ---@since 3.16.0 ---@class lsp.CallHierarchyClientCapabilities +--- ---Whether implementation supports dynamic registration. If this is set to `true` ---the client supports the new `(TextDocumentRegistrationOptions & StaticRegistrationOptions)` ---return value for the corresponding server capability as well. @@ -3376,10 +4105,12 @@ error('Cannot require a meta file') ---@since 3.16.0 ---@class lsp.SemanticTokensClientCapabilities +--- ---Whether implementation supports dynamic registration. If this is set to `true` ---the client supports the new `(TextDocumentRegistrationOptions & StaticRegistrationOptions)` ---return value for the corresponding server capability as well. ---@field dynamicRegistration? boolean +--- ---Which requests the client supports and might send to the server ---depending on the server's capability. Please note that clients might not ---show semantic tokens or degrade some of the user experience if a range @@ -3388,17 +4119,23 @@ error('Cannot require a meta file') ---`request.range` are both set to true but the server only provides a ---range provider the client might not render a minimap correctly or might ---even decide to not show any semantic tokens at all. ----@field requests anonym41 +---@field requests lsp._anonym39.requests +--- ---The token types that the client supports. ---@field tokenTypes string[] +--- ---The token modifiers that the client supports. ---@field tokenModifiers string[] +--- ---The token formats the clients supports. ---@field formats lsp.TokenFormat[] +--- ---Whether the client supports tokens that can overlap each other. ---@field overlappingTokenSupport? boolean +--- ---Whether the client supports tokens that can span multiple lines. ---@field multilineTokenSupport? boolean +--- ---Whether the client allows the server to actively cancel a ---semantic token request, e.g. supports returning ---LSPErrorCodes.ServerCancelled. If a server does the client @@ -3406,6 +4143,7 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@field serverCancelSupport? boolean +--- ---Whether the client uses semantic tokens to augment existing ---syntax tokens. If set to `true` client side created syntax ---tokens and semantic tokens are both used for colorization. If @@ -3422,6 +4160,7 @@ error('Cannot require a meta file') --- ---@since 3.16.0 ---@class lsp.LinkedEditingRangeClientCapabilities +--- ---Whether implementation supports dynamic registration. If this is set to `true` ---the client supports the new `(TextDocumentRegistrationOptions & StaticRegistrationOptions)` ---return value for the corresponding server capability as well. @@ -3431,6 +4170,7 @@ error('Cannot require a meta file') --- ---@since 3.16.0 ---@class lsp.MonikerClientCapabilities +--- ---Whether moniker supports dynamic registration. If this is set to `true` ---the client supports the new `MonikerRegistrationOptions` return value ---for the corresponding server capability as well. @@ -3438,6 +4178,7 @@ error('Cannot require a meta file') ---@since 3.17.0 ---@class lsp.TypeHierarchyClientCapabilities +--- ---Whether implementation supports dynamic registration. If this is set to `true` ---the client supports the new `(TextDocumentRegistrationOptions & StaticRegistrationOptions)` ---return value for the corresponding server capability as well. @@ -3447,6 +4188,7 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.InlineValueClientCapabilities +--- ---Whether implementation supports dynamic registration for inline value providers. ---@field dynamicRegistration? boolean @@ -3454,27 +4196,33 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.InlayHintClientCapabilities +--- ---Whether inlay hints support dynamic registration. ---@field dynamicRegistration? boolean +--- ---Indicates which properties a client can resolve lazily on an inlay ---hint. ----@field resolveSupport? anonym42 +---@field resolveSupport? lsp._anonym42.resolveSupport ---Client capabilities specific to diagnostic pull requests. --- ---@since 3.17.0 ---@class lsp.DiagnosticClientCapabilities +--- ---Whether implementation supports dynamic registration. If this is set to `true` ---the client supports the new `(TextDocumentRegistrationOptions & StaticRegistrationOptions)` ---return value for the corresponding server capability as well. ---@field dynamicRegistration? boolean +--- ---Whether the clients supports related documents for document diagnostic pulls. ---@field relatedDocumentSupport? boolean ---Client capabilities specific to inline completions. --- ---@since 3.18.0 +---@proposed ---@class lsp.InlineCompletionClientCapabilities +--- ---Whether implementation supports dynamic registration for inline completion providers. ---@field dynamicRegistration? boolean @@ -3482,23 +4230,27 @@ error('Cannot require a meta file') --- ---@since 3.17.0 ---@class lsp.NotebookDocumentSyncClientCapabilities +--- ---Whether implementation supports dynamic registration. If this is ---set to `true` the client supports the new ---`(TextDocumentRegistrationOptions & StaticRegistrationOptions)` ---return value for the corresponding server capability as well. ---@field dynamicRegistration? boolean +--- ---The client supports sending execution summary data per cell. ---@field executionSummarySupport? boolean ---Show message request client capabilities ---@class lsp.ShowMessageRequestClientCapabilities +--- ---Capabilities specific to the `MessageActionItem` type. ----@field messageActionItem? anonym43 +---@field messageActionItem? lsp._anonym43.messageActionItem ---Client capabilities for the showDocument request. --- ---@since 3.16.0 ---@class lsp.ShowDocumentClientCapabilities +--- ---The client has support for the showDocument ---request. ---@field support boolean @@ -3507,8 +4259,10 @@ error('Cannot require a meta file') --- ---@since 3.16.0 ---@class lsp.RegularExpressionsClientCapabilities +--- ---The engine's name. ---@field engine string +--- ---The engine's version. ---@field version? string @@ -3516,10 +4270,13 @@ error('Cannot require a meta file') --- ---@since 3.16.0 ---@class lsp.MarkdownClientCapabilities +--- ---The name of the parser. ---@field parser string +--- ---The version of the parser. ---@field version? string +--- ---A list of HTML tags that the client allows / supports in ---Markdown. --- @@ -3662,18 +4419,13 @@ error('Cannot require a meta file') ---| 1 # Type ---| 2 # Parameter ----Defines whether the insert text in a completion item should be interpreted as ----plain text or a snippet. ----@alias lsp.InsertTextFormat ----| 1 # PlainText ----| 2 # Snippet - ---The message type ---@alias lsp.MessageType ---| 1 # Error ---| 2 # Warning ---| 3 # Info ---| 4 # Log +---| 5 # Debug ---Defines how the host (editor) should sync ---document changes to the language server. @@ -3723,6 +4475,12 @@ error('Cannot require a meta file') ---@alias lsp.CompletionItemTag ---| 1 # Deprecated +---Defines whether the insert text in a completion item should be interpreted as +---plain text or a snippet. +---@alias lsp.InsertTextFormat +---| 1 # PlainText +---| 2 # Snippet + ---How whitespace and indentation is handled during completion ---item insertion. --- @@ -3766,6 +4524,7 @@ error('Cannot require a meta file') ---Describes how an {@link InlineCompletionItemProvider inline completion provider} was triggered. --- ---@since 3.18.0 +---@proposed ---@alias lsp.InlineCompletionTriggerKind ---| 0 # Invoked ---| 1 # Automatic @@ -3912,11 +4671,11 @@ error('Cannot require a meta file') ---@since 3.17.0 ---@alias lsp.DocumentDiagnosticReport lsp.RelatedFullDocumentDiagnosticReport|lsp.RelatedUnchangedDocumentDiagnosticReport ----@alias lsp.PrepareRenameResult lsp.Range|anonym44|anonym45 +---@alias lsp.PrepareRenameResult lsp.Range|lsp._anonym44.PrepareRenameResult|lsp._anonym45.PrepareRenameResult ---A document selector is the combination of one or many document filters. --- ----@sample `let sel:DocumentSelector = [{ language: 'typescript' }, { language: 'json', pattern: '**∕tsconfig.json' }]`; +---\@sample `let sel:DocumentSelector = [{ language: 'typescript' }, { language: 'json', pattern: '**∕tsconfig.json' }]`; --- ---The use of a string as a document filter is deprecated @since 3.16.0. ---@alias lsp.DocumentSelector lsp.DocumentFilter[] @@ -3933,7 +4692,7 @@ error('Cannot require a meta file') ---An event describing a change to a text document. If only a text is provided ---it is considered to be the full content of the document. ----@alias lsp.TextDocumentContentChangeEvent anonym46|anonym47 +---@alias lsp.TextDocumentContentChangeEvent lsp._anonym46.TextDocumentContentChangeEvent|lsp._anonym47.TextDocumentContentChangeEvent ---MarkedString can be used to render human readable text. It is either a markdown string ---or a code-block that provides a language and a code snippet. The language identifier @@ -3947,7 +4706,7 @@ error('Cannot require a meta file') --- ---Note that markdown strings will be sanitized - that means html will be escaped. ---@deprecated use MarkupContent instead. ----@alias lsp.MarkedString string|anonym48 +---@alias lsp.MarkedString string|lsp._anonym48.MarkedString ---A document filter describes a top level text document or ---a notebook cell document. @@ -3972,120 +4731,145 @@ error('Cannot require a meta file') ---- `*` to match one or more characters in a path segment ---- `?` to match on one character in a path segment ---- `**` to match any number of path segments, including none ----- `{}` to group sub patterns into an OR expression. (e.g. `**/*.{ts,js}` matches all TypeScript and JavaScript files) +---- `{}` to group sub patterns into an OR expression. (e.g. `**/*.{ts,js}` matches all TypeScript and JavaScript files) ---- `[]` to declare a range of characters to match in a path segment (e.g., `example.[0-9]` to match on `example.0`, `example.1`, …) ---- `[!...]` to negate a range of characters to match in a path segment (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but not `example.0`) --- ----@sample A language filter that applies to typescript files on disk: `{ language: 'typescript', scheme: 'file' }` ----@sample A language filter that applies to all package.json paths: `{ language: 'json', pattern: '**package.json' }` +---\@sample A language filter that applies to typescript files on disk: `{ language: 'typescript', scheme: 'file' }` +---\@sample A language filter that applies to all package.json paths: `{ language: 'json', pattern: '**package.json' }` --- ---@since 3.17.0 ----@alias lsp.TextDocumentFilter anonym49|anonym50|anonym51 +---@alias lsp.TextDocumentFilter lsp._anonym49.TextDocumentFilter|lsp._anonym50.TextDocumentFilter|lsp._anonym51.TextDocumentFilter ---A notebook document filter denotes a notebook document by ---different properties. The properties will be match ---against the notebook's URI (same as with documents) --- ---@since 3.17.0 ----@alias lsp.NotebookDocumentFilter anonym52|anonym53|anonym54 +---@alias lsp.NotebookDocumentFilter lsp._anonym52.NotebookDocumentFilter|lsp._anonym53.NotebookDocumentFilter|lsp._anonym54.NotebookDocumentFilter ---The glob pattern to watch relative to the base path. Glob patterns can have the following syntax: ---- `*` to match one or more characters in a path segment ---- `?` to match on one character in a path segment ---- `**` to match any number of path segments, including none ----- `{}` to group conditions (e.g. `**/*.{ts,js}` matches all TypeScript and JavaScript files) +---- `{}` to group conditions (e.g. `**/*.{ts,js}` matches all TypeScript and JavaScript files) ---- `[]` to declare a range of characters to match in a path segment (e.g., `example.[0-9]` to match on `example.0`, `example.1`, …) ---- `[!...]` to negate a range of characters to match in a path segment (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but not `example.0`) --- ---@since 3.17.0 ---@alias lsp.Pattern string ----@class anonym1 +---@class lsp._anonym1.serverInfo +--- ---The name of the server as defined by the server. ---@field name string +--- ---The server's version as defined by the server. ---@field version? string ----@class anonym3 +---@class lsp._anonym3.itemDefaults.editRange +--- ---@field insert lsp.Range +--- ---@field replace lsp.Range ----@class anonym2 +---@class lsp._anonym2.itemDefaults +--- ---A default commit character set. --- ---@since 3.17.0 ---@field commitCharacters? string[] +--- ---A default edit range. --- ---@since 3.17.0 ----@field editRange? lsp.Range|anonym3 +---@field editRange? lsp.Range|lsp._anonym3.itemDefaults.editRange +--- ---A default insert text format. --- ---@since 3.17.0 ---@field insertTextFormat? lsp.InsertTextFormat +--- ---A default insert text mode. --- ---@since 3.17.0 ---@field insertTextMode? lsp.InsertTextMode +--- ---A default data value. --- ---@since 3.17.0 ---@field data? lsp.LSPAny ----@class anonym4 +---@class lsp._anonym4.disabled +--- ---Human readable description of why the code action is currently disabled. --- ---This is displayed in the code actions UI. ---@field reason string ----@class anonym5 +---@class lsp._anonym5.location +--- ---@field uri lsp.DocumentUri ----@class anonym6 +---@class lsp._anonym6.range ----@class anonym7 +---@class lsp._anonym7.full +--- ---The server supports deltas for full documents. ---@field delta? boolean ----@class anonym9 +---@class lsp._anonym9.cells.structure +--- ---The change to the cell array. ---@field array lsp.NotebookCellArrayChange +--- ---Additional opened cell text documents. ---@field didOpen? lsp.TextDocumentItem[] +--- ---Additional closed cell text documents. ---@field didClose? lsp.TextDocumentIdentifier[] ----@class anonym10 +---@class lsp._anonym10.cells.textContent +--- ---@field document lsp.VersionedTextDocumentIdentifier +--- ---@field changes lsp.TextDocumentContentChangeEvent[] ----@class anonym8 +---@class lsp._anonym8.cells +--- ---Changes to the cell structure to add or ---remove cells. ----@field structure? anonym9 +---@field structure? lsp._anonym9.cells.structure +--- ---Changes to notebook cells properties like its ---kind, execution summary or metadata. ---@field data? lsp.NotebookCell[] +--- ---Changes to the text content of notebook cells. ----@field textContent? anonym10[] +---@field textContent? lsp._anonym10.cells.textContent[] ----@class anonym11 +---@class lsp._anonym11.clientInfo +--- ---The name of the client as defined by the client. ---@field name string +--- ---The client's version as defined by the client. ---@field version? string ----@class anonym12 +---@class lsp._anonym12.workspace +--- ---The server supports workspace folder. --- ---@since 3.6.0 ---@field workspaceFolders? lsp.WorkspaceFoldersServerCapabilities +--- ---The server is interested in notifications/requests for operations on files. --- ---@since 3.16.0 ---@field fileOperations? lsp.FileOperationOptions ----@class anonym13 +---@class lsp._anonym13.completionItem +--- ---The server has support for completion item label ---details (see also `CompletionItemLabelDetails`) when ---receiving a completion item in a resolve call. @@ -4093,43 +4877,53 @@ error('Cannot require a meta file') ---@since 3.17.0 ---@field labelDetailsSupport? boolean ----@class anonym15 +---@class lsp._anonym15.notebookSelector.cells +--- ---@field language string ----@class anonym14 +---@class lsp._anonym14.notebookSelector +--- ---The notebook to be synced If a string ---value is provided it matches against the ---notebook type. '*' matches every notebook. ---@field notebook string|lsp.NotebookDocumentFilter +--- ---The cells of the matching notebook to be synced. ----@field cells? anonym15[] +---@field cells? lsp._anonym15.notebookSelector.cells[] ----@class anonym17 +---@class lsp._anonym17.notebookSelector.cells +--- ---@field language string ----@class anonym16 +---@class lsp._anonym16.notebookSelector +--- ---The notebook to be synced If a string ---value is provided it matches against the ---notebook type. '*' matches every notebook. ---@field notebook? string|lsp.NotebookDocumentFilter +--- ---The cells of the matching notebook to be synced. ----@field cells anonym17[] +---@field cells lsp._anonym17.notebookSelector.cells[] ----@class anonym18 +---@class lsp._anonym18.staleRequestSupport +--- ---The client will actively cancel the request. ---@field cancel boolean +--- ---The list of requests for which the client ---will retry the request if it receives a ---response with error code `ContentModified` ---@field retryOnContentModified string[] ----@class anonym19 +---@class lsp._anonym19.changeAnnotationSupport +--- ---Whether the client groups edits with equal labels into tree nodes, ---for instance all edits labelled with "Changes in Strings" would ---be a tree node. ---@field groupsOnLabel? boolean ----@class anonym20 +---@class lsp._anonym20.symbolKind +--- ---The symbol kind values the client supports. When this ---property exists the client also guarantees that it will ---handle values outside its set gracefully and falls back @@ -4140,27 +4934,33 @@ error('Cannot require a meta file') ---the initial version of the protocol. ---@field valueSet? lsp.SymbolKind[] ----@class anonym21 +---@class lsp._anonym21.tagSupport +--- ---The tags supported by the client. ---@field valueSet lsp.SymbolTag[] ----@class anonym22 +---@class lsp._anonym22.resolveSupport +--- ---The properties that a client can resolve lazily. Usually ---`location.range` ---@field properties string[] ----@class anonym24 +---@class lsp._anonym24.completionItem.tagSupport +--- ---The tags supported by the client. ---@field valueSet lsp.CompletionItemTag[] ----@class anonym25 +---@class lsp._anonym25.completionItem.resolveSupport +--- ---The properties that a client can resolve lazily. ---@field properties string[] ----@class anonym26 +---@class lsp._anonym26.completionItem.insertTextModeSupport +--- ---@field valueSet lsp.InsertTextMode[] ----@class anonym23 +---@class lsp._anonym23.completionItem +--- ---Client supports snippets as insert text. --- ---A snippet can define tab stops and placeholders with `$1`, `$2` @@ -4168,46 +4968,56 @@ error('Cannot require a meta file') ---the end of the snippet. Placeholders with equal identifiers are linked, ---that is typing in one will update others too. ---@field snippetSupport? boolean +--- ---Client supports commit characters on a completion item. ---@field commitCharactersSupport? boolean +--- ---Client supports the following content formats for the documentation ---property. The order describes the preferred format of the client. ---@field documentationFormat? lsp.MarkupKind[] +--- ---Client supports the deprecated property on a completion item. ---@field deprecatedSupport? boolean +--- ---Client supports the preselect property on a completion item. ---@field preselectSupport? boolean +--- ---Client supports the tag property on a completion item. Clients supporting ---tags have to handle unknown tags gracefully. Clients especially need to ---preserve unknown tags when sending a completion item back to the server in ---a resolve call. --- ---@since 3.15.0 ----@field tagSupport? anonym24 +---@field tagSupport? lsp._anonym24.completionItem.tagSupport +--- ---Client support insert replace edit to control different behavior if a ---completion item is inserted in the text or should replace text. --- ---@since 3.16.0 ---@field insertReplaceSupport? boolean +--- ---Indicates which properties a client can resolve lazily on a completion ---item. Before version 3.16.0 only the predefined properties `documentation` ---and `details` could be resolved lazily. --- ---@since 3.16.0 ----@field resolveSupport? anonym25 +---@field resolveSupport? lsp._anonym25.completionItem.resolveSupport +--- ---The client supports the `insertTextMode` property on ---a completion item to override the whitespace handling mode ---as defined by the client (see `insertTextMode`). --- ---@since 3.16.0 ----@field insertTextModeSupport? anonym26 +---@field insertTextModeSupport? lsp._anonym26.completionItem.insertTextModeSupport +--- ---The client has support for completion item label ---details (see also `CompletionItemLabelDetails`). --- ---@since 3.17.0 ---@field labelDetailsSupport? boolean ----@class anonym27 +---@class lsp._anonym27.completionItemKind +--- ---The completion item kind values the client supports. When this ---property exists the client also guarantees that it will ---handle values outside its set gracefully and falls back @@ -4218,7 +5028,8 @@ error('Cannot require a meta file') ---the initial version of the protocol. ---@field valueSet? lsp.CompletionItemKind[] ----@class anonym28 +---@class lsp._anonym28.completionList +--- ---The client supports the following itemDefaults on ---a completion list. --- @@ -4229,26 +5040,38 @@ error('Cannot require a meta file') ---@since 3.17.0 ---@field itemDefaults? string[] ----@class anonym30 +---@class lsp._anonym30.signatureInformation.parameterInformation +--- ---The client supports processing label offsets instead of a ---simple label string. --- ---@since 3.14.0 ---@field labelOffsetSupport? boolean ----@class anonym29 +---@class lsp._anonym29.signatureInformation +--- ---Client supports the following content formats for the documentation ---property. The order describes the preferred format of the client. ---@field documentationFormat? lsp.MarkupKind[] +--- ---Client capabilities specific to parameter information. ----@field parameterInformation? anonym30 +---@field parameterInformation? lsp._anonym30.signatureInformation.parameterInformation +--- ---The client supports the `activeParameter` property on `SignatureInformation` ---literal. --- ---@since 3.16.0 ---@field activeParameterSupport? boolean +--- +---The client supports the `activeParameter` property on +---`SignatureInformation` being set to `null` to indicate that no +---parameter should be active. +--- +---@since 3.18.0 +---@field noActiveParameterSupport? boolean ----@class anonym31 +---@class lsp._anonym31.symbolKind +--- ---The symbol kind values the client supports. When this ---property exists the client also guarantees that it will ---handle values outside its set gracefully and falls back @@ -4259,138 +5082,177 @@ error('Cannot require a meta file') ---the initial version of the protocol. ---@field valueSet? lsp.SymbolKind[] ----@class anonym32 +---@class lsp._anonym32.tagSupport +--- ---The tags supported by the client. ---@field valueSet lsp.SymbolTag[] ----@class anonym34 +---@class lsp._anonym34.codeActionLiteralSupport.codeActionKind +--- ---The code action kind values the client supports. When this ---property exists the client also guarantees that it will ---handle values outside its set gracefully and falls back ---to a default value when unknown. ---@field valueSet lsp.CodeActionKind[] ----@class anonym33 +---@class lsp._anonym33.codeActionLiteralSupport +--- ---The code action kind is support with the following value ---set. ----@field codeActionKind anonym34 +---@field codeActionKind lsp._anonym34.codeActionLiteralSupport.codeActionKind ----@class anonym35 +---@class lsp._anonym35.resolveSupport +--- ---The properties that a client can resolve lazily. ---@field properties string[] ----@class anonym36 +---@class lsp._anonym36.foldingRangeKind +--- ---The folding range kind values the client supports. When this ---property exists the client also guarantees that it will ---handle values outside its set gracefully and falls back ---to a default value when unknown. ---@field valueSet? lsp.FoldingRangeKind[] ----@class anonym37 +---@class lsp._anonym37.foldingRange +--- ---If set, the client signals that it supports setting collapsedText on ---folding ranges to display custom labels instead of the default text. --- ---@since 3.17.0 ---@field collapsedText? boolean ----@class anonym38 +---@class lsp._anonym38.tagSupport +--- ---The tags supported by the client. ---@field valueSet lsp.DiagnosticTag[] ----@class anonym40 +---@class lsp._anonym40.requests.range ----@class anonym41 +---@class lsp._anonym41.requests.full +--- ---The client will send the `textDocument/semanticTokens/full/delta` request if ---the server provides a corresponding handler. ---@field delta? boolean ----@class anonym39 +---@class lsp._anonym39.requests +--- ---The client will send the `textDocument/semanticTokens/range` request if ---the server provides a corresponding handler. ----@field range? boolean|anonym40 +---@field range? boolean|lsp._anonym40.requests.range +--- ---The client will send the `textDocument/semanticTokens/full` request if ---the server provides a corresponding handler. ----@field full? boolean|anonym41 +---@field full? boolean|lsp._anonym41.requests.full ----@class anonym42 +---@class lsp._anonym42.resolveSupport +--- ---The properties that a client can resolve lazily. ---@field properties string[] ----@class anonym43 +---@class lsp._anonym43.messageActionItem +--- ---Whether the client supports additional attributes which ---are preserved and send back to the server in the ---request's response. ---@field additionalPropertiesSupport? boolean ----@class anonym44 +---@class lsp._anonym44.PrepareRenameResult +--- ---@field range lsp.Range +--- ---@field placeholder string ----@class anonym45 +---@class lsp._anonym45.PrepareRenameResult +--- ---@field defaultBehavior boolean ----@class anonym46 +---@class lsp._anonym46.TextDocumentContentChangeEvent +--- ---The range of the document that changed. ---@field range lsp.Range +--- ---The optional length of the range that got replaced. --- ---@deprecated use range instead. ---@field rangeLength? uinteger +--- ---The new text for the provided range. ---@field text string ----@class anonym47 +---@class lsp._anonym47.TextDocumentContentChangeEvent +--- ---The new text of the whole document. ---@field text string ----@class anonym48 +---@class lsp._anonym48.MarkedString +--- ---@field language string +--- ---@field value string ----@class anonym49 +---@class lsp._anonym49.TextDocumentFilter +--- ---A language id, like `typescript`. ---@field language string +--- ---A Uri {@link Uri.scheme scheme}, like `file` or `untitled`. ---@field scheme? string ----A glob pattern, like `*.{ts,js}`. +--- +---A glob pattern, like **/*.{ts,js}. See TextDocumentFilter for examples. ---@field pattern? string ----@class anonym50 +---@class lsp._anonym50.TextDocumentFilter +--- ---A language id, like `typescript`. ---@field language? string +--- ---A Uri {@link Uri.scheme scheme}, like `file` or `untitled`. ---@field scheme string ----A glob pattern, like `*.{ts,js}`. +--- +---A glob pattern, like **/*.{ts,js}. See TextDocumentFilter for examples. ---@field pattern? string ----@class anonym51 +---@class lsp._anonym51.TextDocumentFilter +--- ---A language id, like `typescript`. ---@field language? string +--- ---A Uri {@link Uri.scheme scheme}, like `file` or `untitled`. ---@field scheme? string ----A glob pattern, like `*.{ts,js}`. +--- +---A glob pattern, like **/*.{ts,js}. See TextDocumentFilter for examples. ---@field pattern string ----@class anonym52 +---@class lsp._anonym52.NotebookDocumentFilter +--- ---The type of the enclosing notebook. ---@field notebookType string +--- ---A Uri {@link Uri.scheme scheme}, like `file` or `untitled`. ---@field scheme? string +--- ---A glob pattern. ---@field pattern? string ----@class anonym53 +---@class lsp._anonym53.NotebookDocumentFilter +--- ---The type of the enclosing notebook. ---@field notebookType? string +--- ---A Uri {@link Uri.scheme scheme}, like `file` or `untitled`. ---@field scheme string +--- ---A glob pattern. ---@field pattern? string ----@class anonym54 +---@class lsp._anonym54.NotebookDocumentFilter +--- ---The type of the enclosing notebook. ---@field notebookType? string +--- ---A Uri {@link Uri.scheme scheme}, like `file` or `untitled`. ---@field scheme? string +--- ---A glob pattern. ---@field pattern string diff --git a/runtime/lua/vim/lsp/tagfunc.lua b/runtime/lua/vim/lsp/_tagfunc.lua index 4ad50e4a58..4ad50e4a58 100644 --- a/runtime/lua/vim/lsp/tagfunc.lua +++ b/runtime/lua/vim/lsp/_tagfunc.lua diff --git a/runtime/lua/vim/lsp/_watchfiles.lua b/runtime/lua/vim/lsp/_watchfiles.lua index 1fd112631d..49328fbe9b 100644 --- a/runtime/lua/vim/lsp/_watchfiles.lua +++ b/runtime/lua/vim/lsp/_watchfiles.lua @@ -1,95 +1,20 @@ local bit = require('bit') -local watch = require('vim._watch') +local glob = vim.glob +local watch = vim._watch local protocol = require('vim.lsp.protocol') local ms = protocol.Methods local lpeg = vim.lpeg local M = {} ---- Parses the raw pattern into an |lpeg| pattern. LPeg patterns natively support the "this" or "that" ---- alternative constructions described in the LSP spec that cannot be expressed in a standard Lua pattern. ---- ----@param pattern string The raw glob pattern ----@return vim.lpeg.Pattern? pattern An |lpeg| representation of the pattern, or nil if the pattern is invalid. -local function parse(pattern) - local l = lpeg - - local P, S, V = lpeg.P, lpeg.S, lpeg.V - local C, Cc, Ct, Cf = lpeg.C, lpeg.Cc, lpeg.Ct, lpeg.Cf - - local pathsep = '/' - - local function class(inv, ranges) - for i, r in ipairs(ranges) do - ranges[i] = r[1] .. r[2] - end - local patt = l.R(unpack(ranges)) - if inv == '!' then - patt = P(1) - patt - end - return patt - end - - local function add(acc, a) - return acc + a - end - - local function mul(acc, m) - return acc * m - end - - local function star(stars, after) - return (-after * (l.P(1) - pathsep)) ^ #stars * after - end - - local function dstar(after) - return (-after * l.P(1)) ^ 0 * after - end - - local p = P({ - 'Pattern', - Pattern = V('Elem') ^ -1 * V('End'), - Elem = Cf( - (V('DStar') + V('Star') + V('Ques') + V('Class') + V('CondList') + V('Literal')) - * (V('Elem') + V('End')), - mul - ), - DStar = P('**') * (P(pathsep) * (V('Elem') + V('End')) + V('End')) / dstar, - Star = C(P('*') ^ 1) * (V('Elem') + V('End')) / star, - Ques = P('?') * Cc(l.P(1) - pathsep), - Class = P('[') * C(P('!') ^ -1) * Ct(Ct(C(1) * '-' * C(P(1) - ']')) ^ 1 * ']') / class, - CondList = P('{') * Cf(V('Cond') * (P(',') * V('Cond')) ^ 0, add) * '}', - -- TODO: '*' inside a {} condition is interpreted literally but should probably have the same - -- wildcard semantics it usually has. - -- Fixing this is non-trivial because '*' should match non-greedily up to "the rest of the - -- pattern" which in all other cases is the entire succeeding part of the pattern, but at the end of a {} - -- condition means "everything after the {}" where several other options separated by ',' may - -- exist in between that should not be matched by '*'. - Cond = Cf((V('Ques') + V('Class') + V('CondList') + (V('Literal') - S(',}'))) ^ 1, mul) - + Cc(l.P(0)), - Literal = P(1) / l.P, - End = P(-1) * Cc(l.P(-1)), - }) - - return p:match(pattern) --[[@as vim.lpeg.Pattern?]] -end - ----@private ---- Implementation of LSP 3.17.0's pattern matching: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#pattern ---- ----@param pattern string|vim.lpeg.Pattern The glob pattern (raw or parsed) to match. ----@param s string The string to match against pattern. ----@return boolean Whether or not pattern matches s. -function M._match(pattern, s) - if type(pattern) == 'string' then - local p = assert(parse(pattern)) - return p:match(s) ~= nil - end - return pattern:match(s) ~= nil +if vim.fn.has('win32') == 1 or vim.fn.has('mac') == 1 then + M._watchfunc = watch.watch +elseif vim.fn.executable('fswatch') == 1 then + M._watchfunc = watch.fswatch +else + M._watchfunc = watch.watchdirs end -M._watchfunc = (vim.fn.has('win32') == 1 or vim.fn.has('mac') == 1) and watch.watch or watch.poll - ---@type table<integer, table<string, function[]>> client id -> registration id -> cancel function local cancels = vim.defaulttable() @@ -112,9 +37,9 @@ local to_lsp_change_type = { --- Default excludes the same as VSCode's `files.watcherExclude` setting. --- https://github.com/microsoft/vscode/blob/eef30e7165e19b33daa1e15e92fa34ff4a5df0d3/src/vs/workbench/contrib/files/browser/files.contribution.ts#L261 ---@type vim.lpeg.Pattern parsed Lpeg pattern -M._poll_exclude_pattern = parse('**/.git/{objects,subtree-cache}/**') - + parse('**/node_modules/*/**') - + parse('**/.hg/store/**') +M._poll_exclude_pattern = glob.to_lpeg('**/.git/{objects,subtree-cache}/**') + + glob.to_lpeg('**/node_modules/*/**') + + glob.to_lpeg('**/.hg/store/**') --- Registers the workspace/didChangeWatchedFiles capability dynamically. --- @@ -125,12 +50,8 @@ function M.register(reg, ctx) local client = assert(vim.lsp.get_client_by_id(client_id), 'Client must be running') -- Ill-behaved servers may not honor the client capability and try to register -- anyway, so ignore requests when the user has opted out of the feature. - local has_capability = vim.tbl_get( - client.config.capabilities or {}, - 'workspace', - 'didChangeWatchedFiles', - 'dynamicRegistration' - ) + local has_capability = + vim.tbl_get(client.capabilities, 'workspace', 'didChangeWatchedFiles', 'dynamicRegistration') if not has_capability or not client.workspace_folders then return end @@ -143,7 +64,7 @@ function M.register(reg, ctx) local glob_pattern = w.globPattern if type(glob_pattern) == 'string' then - local pattern = parse(glob_pattern) + local pattern = glob.to_lpeg(glob_pattern) if not pattern then error('Cannot parse pattern: ' .. glob_pattern) end @@ -155,7 +76,7 @@ function M.register(reg, ctx) local base_uri = glob_pattern.baseUri local uri = type(base_uri) == 'string' and base_uri or base_uri.uri local base_dir = vim.uri_to_fname(uri) - local pattern = parse(glob_pattern.pattern) + local pattern = glob.to_lpeg(glob_pattern.pattern) if not pattern then error('Cannot parse pattern: ' .. glob_pattern.pattern) end @@ -248,4 +169,13 @@ function M.unregister(unreg, ctx) end end +--- @param client_id integer +function M.cancel(client_id) + for _, reg_cancels in pairs(cancels[client_id]) do + for _, cancel in pairs(reg_cancels) do + cancel() + end + end +end + return M diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua index cf9acc0808..50121f30b2 100644 --- a/runtime/lua/vim/lsp/buf.lua +++ b/runtime/lua/vim/lsp/buf.lua @@ -11,8 +11,8 @@ local M = {} --- ---@param method (string) LSP method name ---@param params (table|nil) Parameters to send to the server ----@param handler (function|nil) See |lsp-handler|. Follows |lsp-handler-resolution| --- +---@param handler lsp.Handler? See |lsp-handler|. Follows |lsp-handler-resolution| +--- ---@return table<integer, integer> client_request_ids Map of client-id:request-id pairs ---for all successful requests. ---@return function _cancel_all_requests Function which can be used to @@ -28,16 +28,6 @@ local function request(method, params, handler) return vim.lsp.buf_request(0, method, params, handler) end ---- Checks whether the language servers attached to the current buffer are ---- ready. ---- ----@return boolean if server responds. ----@deprecated -function M.server_ready() - vim.deprecate('vim.lsp.buf.server_ready', nil, '0.10.0') - return not not vim.lsp.buf_notify(0, 'window/progress', {}) -end - --- Displays hover information about the symbol under the cursor in a floating --- window. Calling the function twice will jump into the floating window. function M.hover() @@ -46,10 +36,10 @@ function M.hover() end local function request_with_options(name, params, options) - local req_handler + local req_handler --- @type function? if options then req_handler = function(err, result, ctx, config) - local client = vim.lsp.get_client_by_id(ctx.client_id) + local client = assert(vim.lsp.get_client_by_id(ctx.client_id)) local handler = client.handlers[name] or vim.lsp.handlers[name] handler(err, result, ctx, vim.tbl_extend('force', config or {}, options)) end @@ -57,35 +47,57 @@ local function request_with_options(name, params, options) request(name, params, req_handler) end ---- Jumps to the declaration of the symbol under the cursor. ----@note Many servers do not implement this method. Generally, see |vim.lsp.buf.definition()| instead. +--- @class vim.lsp.ListOpts --- ----@param options table|nil additional options ---- - reuse_win: (boolean) Jump to existing window if buffer is already open. ---- - on_list: (function) |lsp-on-list-handler| replacing the default handler. ---- Called for any non-empty result. +--- list-handler replacing the default handler. +--- Called for any non-empty result. +--- This table can be used with |setqflist()| or |setloclist()|. E.g.: +--- ```lua +--- local function on_list(options) +--- vim.fn.setqflist({}, ' ', options) +--- vim.cmd.cfirst() +--- end +--- +--- vim.lsp.buf.definition({ on_list = on_list }) +--- vim.lsp.buf.references(nil, { on_list = on_list }) +--- ``` +--- +--- If you prefer loclist do something like this: +--- ```lua +--- local function on_list(options) +--- vim.fn.setloclist(0, {}, ' ', options) +--- vim.cmd.lopen() +--- end +--- ``` +--- @field on_list? fun(t: vim.lsp.LocationOpts.OnList) + +--- @class vim.lsp.LocationOpts.OnList +--- @field items table[] Structured like |setqflist-what| +--- @field title? string Title for the list. +--- @field context? table `ctx` from |lsp-handler| + +--- @class vim.lsp.LocationOpts: vim.lsp.ListOpts +--- +--- Jump to existing window if buffer is already open. +--- @field reuse_win? boolean + +--- Jumps to the declaration of the symbol under the cursor. +--- @note Many servers do not implement this method. Generally, see |vim.lsp.buf.definition()| instead. +--- @param options? vim.lsp.LocationOpts function M.declaration(options) local params = util.make_position_params() request_with_options(ms.textDocument_declaration, params, options) end --- Jumps to the definition of the symbol under the cursor. ---- ----@param options table|nil additional options ---- - reuse_win: (boolean) Jump to existing window if buffer is already open. ---- - on_list: (function) |lsp-on-list-handler| replacing the default handler. ---- Called for any non-empty result. +--- @param options? vim.lsp.LocationOpts function M.definition(options) local params = util.make_position_params() request_with_options(ms.textDocument_definition, params, options) end --- Jumps to the definition of the type of the symbol under the cursor. ---- ----@param options table|nil additional options ---- - reuse_win: (boolean) Jump to existing window if buffer is already open. ---- - on_list: (function) |lsp-on-list-handler| replacing the default handler. ---- Called for any non-empty result. +--- @param options? vim.lsp.LocationOpts function M.type_definition(options) local params = util.make_position_params() request_with_options(ms.textDocument_typeDefinition, params, options) @@ -93,10 +105,7 @@ end --- Lists all the implementations for the symbol under the cursor in the --- quickfix window. ---- ----@param options table|nil additional options ---- - on_list: (function) |lsp-on-list-handler| replacing the default handler. ---- Called for any non-empty result. +--- @param options? vim.lsp.LocationOpts function M.implementation(options) local params = util.make_position_params() request_with_options(ms.textDocument_implementation, params, options) @@ -156,44 +165,55 @@ local function range_from_selection(bufnr, mode) } end +--- @class vim.lsp.buf.format.Opts +--- @inlinedoc +--- +--- Can be used to specify FormattingOptions. Some unspecified options will be +--- automatically derived from the current Nvim options. +--- See https://microsoft.github.io/language-server-protocol/specification/#formattingOptions +--- @field formatting_options? table +--- +--- Time in milliseconds to block for formatting requests. No effect if async=true. +--- (default: `1000`) +--- @field timeout_ms? integer +--- +--- Restrict formatting to the clients attached to the given buffer. +--- (default: current buffer) +--- @field bufnr? integer +--- +--- Predicate used to filter clients. Receives a client as argument and must +--- return a boolean. Clients matching the predicate are included. Example: +--- ```lua +--- -- Never request typescript-language-server for formatting +--- vim.lsp.buf.format { +--- filter = function(client) return client.name ~= "tsserver" end +--- } +--- ``` +--- @field filter? fun(client: vim.lsp.Client): boolean? +--- +--- If true the method won't block. +--- Editing the buffer while formatting asynchronous can lead to unexpected +--- changes. +--- (Default: false) +--- @field async? boolean +--- +--- Restrict formatting to the client with ID (client.id) matching this field. +--- @field id? integer +--- +--- Restrict formatting to the client with name (client.name) matching this field. +--- @field name? string +--- +--- Range to format. +--- Table must contain `start` and `end` keys with {row,col} tuples using +--- (1,0) indexing. +--- (Default: current selection in visual mode, `nil` in other modes, +--- formatting the full buffer) +--- @field range? {start:integer[],end:integer[]} + --- Formats a buffer using the attached (and optionally filtered) language --- server clients. --- ---- @param options table|nil Optional table which holds the following optional fields: ---- - formatting_options (table|nil): ---- Can be used to specify FormattingOptions. Some unspecified options will be ---- automatically derived from the current Nvim options. ---- See https://microsoft.github.io/language-server-protocol/specification/#formattingOptions ---- - timeout_ms (integer|nil, default 1000): ---- Time in milliseconds to block for formatting requests. No effect if async=true ---- - bufnr (number|nil): ---- Restrict formatting to the clients attached to the given buffer, defaults to the current ---- buffer (0). ---- ---- - filter (function|nil): ---- Predicate used to filter clients. Receives a client as argument and must return a ---- boolean. Clients matching the predicate are included. Example: <pre>lua ---- -- Never request typescript-language-server for formatting ---- vim.lsp.buf.format { ---- filter = function(client) return client.name ~= "tsserver" end ---- } ---- </pre> ---- ---- - async boolean|nil ---- If true the method won't block. Defaults to false. ---- Editing the buffer while formatting asynchronous can lead to unexpected ---- changes. ---- ---- - id (number|nil): ---- Restrict formatting to the client with ID (client.id) matching this field. ---- - name (string|nil): ---- Restrict formatting to the client with name (client.name) matching this field. ---- ---- - range (table|nil) Range to format. ---- Table must contain `start` and `end` keys with {row,col} tuples using ---- (1,0) indexing. ---- Defaults to current selection in visual mode ---- Defaults to `nil` in other modes, formatting the full buffer +--- @param options? vim.lsp.buf.format.Opts function M.format(options) options = options or {} local bufnr = options.bufnr or api.nvim_get_current_buf() @@ -218,6 +238,9 @@ function M.format(options) vim.notify('[LSP] Format request failed, no matching language servers.') end + --- @param client vim.lsp.Client + --- @param params lsp.DocumentFormattingParams + --- @return lsp.DocumentFormattingParams local function set_range(client, params) if range then local range_params = @@ -228,8 +251,7 @@ function M.format(options) end if options.async then - local do_format - do_format = function(idx, client) + local function do_format(idx, client) if not client then return end @@ -255,17 +277,25 @@ function M.format(options) end end +--- @class vim.lsp.buf.rename.Opts +--- @inlinedoc +--- +--- Predicate used to filter clients. Receives a client as argument and +--- must return a boolean. Clients matching the predicate are included. +--- @field filter? fun(client: vim.lsp.Client): boolean? +--- +--- Restrict clients used for rename to ones where client.name matches +--- this field. +--- @field name? string +--- +--- (default: current buffer) +--- @field bufnr? integer + --- Renames all references to the symbol under the cursor. --- ---@param new_name string|nil If not provided, the user will be prompted for a new --- name using |vim.ui.input()|. ----@param options table|nil additional options ---- - filter (function|nil): ---- Predicate used to filter clients. Receives a client as argument and ---- must return a boolean. Clients matching the predicate are included. ---- - name (string|nil): ---- Restrict clients used for rename to ones where client.name matches ---- this field. +---@param options? vim.lsp.buf.rename.Opts Additional options: function M.rename(new_name, options) options = options or {} local bufnr = options.bufnr or api.nvim_get_current_buf() @@ -299,12 +329,12 @@ function M.rename(new_name, options) )[1] end - local try_use_client - try_use_client = function(idx, client) + local function try_use_client(idx, client) if not client then return end + --- @param name string local function rename(name) local params = util.make_position_params(win, client.offset_encoding) params.newName = name @@ -385,8 +415,7 @@ end --- ---@param context (table|nil) Context for the request ---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_references ----@param options table|nil additional options ---- - on_list: (function) handler for list results. See |lsp-on-list-handler| +---@param options? vim.lsp.ListOpts function M.references(context, options) validate({ context = { context, 't', true } }) local params = util.make_position_params() @@ -397,14 +426,13 @@ function M.references(context, options) end --- Lists all symbols in the current buffer in the quickfix window. ---- ----@param options table|nil additional options ---- - on_list: (function) handler for list results. See |lsp-on-list-handler| +--- @param options? vim.lsp.ListOpts function M.document_symbol(options) local params = { textDocument = util.make_text_document_params() } request_with_options(ms.textDocument_documentSymbol, params, options) end +--- @param call_hierarchy_items lsp.CallHierarchyItem[]? local function pick_call_hierarchy_item(call_hierarchy_items) if not call_hierarchy_items then return @@ -424,8 +452,10 @@ local function pick_call_hierarchy_item(call_hierarchy_items) return choice end +--- @param method string local function call_hierarchy(method) local params = util.make_position_params() + --- @param result lsp.CallHierarchyItem[]? request(ms.textDocument_prepareCallHierarchy, params, function(err, result, ctx) if err then vim.notify(err.message, vim.log.levels.WARN) @@ -472,6 +502,7 @@ end --- Add the folder at path to the workspace folders. If {path} is --- not provided, the user will be prompted for a path using |input()|. +--- @param workspace_folder? string function M.add_workspace_folder(workspace_folder) workspace_folder = workspace_folder or npcall(vim.fn.input, 'Workspace Folder: ', vim.fn.expand('%:p:h'), 'dir') @@ -511,6 +542,7 @@ end --- Remove the folder at path from the workspace folders. If --- {path} is not provided, the user will be prompted for --- a path using |input()|. +--- @param workspace_folder? string function M.remove_workspace_folder(workspace_folder) workspace_folder = workspace_folder or npcall(vim.fn.input, 'Workspace Folder: ', vim.fn.expand('%:p:h')) @@ -542,9 +574,8 @@ end --- call, the user is prompted to enter a string on the command line. An empty --- string means no filtering is done. --- ----@param query string|nil optional ----@param options table|nil additional options ---- - on_list: (function) handler for list results. See |lsp-on-list-handler| +--- @param query string? optional +--- @param options? vim.lsp.ListOpts function M.workspace_symbol(query, options) query = query or npcall(vim.fn.input, 'Query: ') if query == nil then @@ -579,16 +610,36 @@ function M.clear_references() util.buf_clear_references() end +---@nodoc ---@class vim.lsp.CodeActionResultEntry ---@field error? lsp.ResponseError ---@field result? (lsp.Command|lsp.CodeAction)[] ---@field ctx lsp.HandlerContext ----@class vim.lsp.buf.code_action.opts ----@field context? lsp.CodeActionContext ----@field filter? fun(x: lsp.CodeAction|lsp.Command):boolean ----@field apply? boolean ----@field range? {start: integer[], end: integer[]} +--- @class vim.lsp.buf.code_action.Opts +--- @inlinedoc +--- +--- Corresponds to `CodeActionContext` of the LSP specification: +--- - {diagnostics}? (`table`) LSP `Diagnostic[]`. Inferred from the current +--- position if not provided. +--- - {only}? (`table`) List of LSP `CodeActionKind`s used to filter the code actions. +--- Most language servers support values like `refactor` +--- or `quickfix`. +--- - {triggerKind}? (`integer`) The reason why code actions were requested. +--- @field context? lsp.CodeActionContext +--- +--- Predicate taking an `CodeAction` and returning a boolean. +--- @field filter? fun(x: lsp.CodeAction|lsp.Command):boolean +--- +--- When set to `true`, and there is just one remaining action +--- (after filtering), the action is applied without user query. +--- @field apply? boolean +--- +--- Range for which code actions should be requested. +--- If in visual mode this defaults to the active selection. +--- Table must contain `start` and `end` keys with {row,col} tuples +--- using mark-like indexing. See |api-indexing| +--- @field range? {start: integer[], end: integer[]} --- This is not public because the main extension point is --- vim.ui.select which can be overridden independently. @@ -599,7 +650,7 @@ end --- need to be able to link a `CodeAction|Command` to the right client for --- `codeAction/resolve` ---@param results table<integer, vim.lsp.CodeActionResultEntry> ----@param opts? vim.lsp.buf.code_action.opts +---@param opts? vim.lsp.buf.code_action.Opts local function on_code_action_results(results, opts) ---@param a lsp.Command|lsp.CodeAction local function action_filter(a) @@ -644,15 +695,16 @@ local function on_code_action_results(results, opts) end ---@param action lsp.Command|lsp.CodeAction - ---@param client lsp.Client + ---@param client vim.lsp.Client ---@param ctx lsp.HandlerContext local function apply_action(action, client, ctx) if action.edit then util.apply_workspace_edit(action.edit, client.offset_encoding) end - if action.command then - local command = type(action.command) == 'table' and action.command or action - client._exec_cmd(command, ctx) + local a_cmd = action.command + if a_cmd then + local command = type(a_cmd) == 'table' and a_cmd or action + client:_exec_cmd(command, ctx) end end @@ -673,7 +725,6 @@ local function on_code_action_results(results, opts) -- command: string -- arguments?: any[] -- - ---@type lsp.Client local client = assert(vim.lsp.get_client_by_id(choice.ctx.client_id)) local action = choice.action local bufnr = assert(choice.ctx.bufnr, 'Must have buffer number') @@ -723,29 +774,7 @@ end --- Selects a code action available at the current --- cursor position. --- ----@param options table|nil Optional table which holds the following optional fields: ---- - context: (table|nil) ---- Corresponds to `CodeActionContext` of the LSP specification: ---- - diagnostics (table|nil): ---- LSP `Diagnostic[]`. Inferred from the current ---- position if not provided. ---- - only (table|nil): ---- List of LSP `CodeActionKind`s used to filter the code actions. ---- Most language servers support values like `refactor` ---- or `quickfix`. ---- - triggerKind (number|nil): The reason why code actions were requested. ---- - filter: (function|nil) ---- Predicate taking an `CodeAction` and returning a boolean. ---- - apply: (boolean|nil) ---- When set to `true`, and there is just one remaining action ---- (after filtering), the action is applied without user query. ---- ---- - range: (table|nil) ---- Range for which code actions should be requested. ---- If in visual mode this defaults to the active selection. ---- Table must contain `start` and `end` keys with {row,col} tuples ---- using mark-like indexing. See |api-indexing| ---- +---@param options? vim.lsp.buf.code_action.Opts ---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_codeAction ---@see vim.lsp.protocol.CodeActionTriggerKind function M.code_action(options) @@ -753,6 +782,7 @@ function M.code_action(options) options = options or {} -- Detect old API call code_action(context) which should now be -- code_action({ context = context} ) + --- @diagnostic disable-next-line:undefined-field if options.diagnostics or options.only then options = { options = options } end @@ -811,9 +841,8 @@ function M.code_action(options) end --- Executes an LSP server command. ---- ----@param command_params table A valid `ExecuteCommandParams` object ----@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_executeCommand +--- @param command_params lsp.ExecuteCommandParams +--- @see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_executeCommand function M.execute_command(command_params) validate({ command = { command_params.command, 's' }, diff --git a/runtime/lua/vim/lsp/client.lua b/runtime/lua/vim/lsp/client.lua new file mode 100644 index 0000000000..ff0db166d5 --- /dev/null +++ b/runtime/lua/vim/lsp/client.lua @@ -0,0 +1,1056 @@ +local uv = vim.uv +local api = vim.api +local lsp = vim.lsp +local log = lsp.log +local ms = lsp.protocol.Methods +local changetracking = lsp._changetracking +local validate = vim.validate + +--- @alias vim.lsp.client.on_init_cb fun(client: vim.lsp.Client, initialize_result: lsp.InitializeResult) +--- @alias vim.lsp.client.on_attach_cb fun(client: vim.lsp.Client, bufnr: integer) +--- @alias vim.lsp.client.on_exit_cb fun(code: integer, signal: integer, client_id: integer) +--- @alias vim.lsp.client.before_init_cb fun(params: lsp.InitializeParams, config: vim.lsp.ClientConfig) + +--- @class vim.lsp.Client.Flags +--- @inlinedoc +--- +--- Allow using incremental sync for buffer edits +--- (defailt: `true`) +--- @field allow_incremental_sync? boolean +--- +--- Debounce `didChange` notifications to the server by the given number in milliseconds. +--- No debounce occurs if `nil`. +--- (default: `150`) +--- @field debounce_text_changes integer +--- +--- Milliseconds to wait for server to exit cleanly after sending the +--- "shutdown" request before sending kill -15. If set to false, nvim exits +--- immediately after sending the "shutdown" request to the server. +--- (default: `false`) +--- @field exit_timeout integer|false + +--- @class vim.lsp.ClientConfig +--- command string[] that launches the language +--- server (treated as in |jobstart()|, must be absolute or on `$PATH`, shell constructs like +--- "~" are not expanded), or function that creates an RPC client. Function receives +--- a `dispatchers` table and returns a table with member functions `request`, `notify`, +--- `is_closing` and `terminate`. +--- See |vim.lsp.rpc.request()|, |vim.lsp.rpc.notify()|. +--- For TCP there is a builtin RPC client factory: |vim.lsp.rpc.connect()| +--- @field cmd string[]|fun(dispatchers: vim.lsp.rpc.Dispatchers): vim.lsp.rpc.PublicClient? +--- +--- Directory to launch the `cmd` process. Not related to `root_dir`. +--- (default: cwd) +--- @field cmd_cwd? string +--- +--- Environment flags to pass to the LSP on spawn. +--- Must be specified using a table. +--- Non-string values are coerced to string. +--- Example: +--- ```lua +--- { PORT = 8080; HOST = "0.0.0.0"; } +--- ``` +--- @field cmd_env? table +--- +--- Daemonize the server process so that it runs in a separate process group from Nvim. +--- Nvim will shutdown the process on exit, but if Nvim fails to exit cleanly this could leave +--- behind orphaned server processes. +--- (default: true) +--- @field detached? boolean +--- +--- List of workspace folders passed to the language server. +--- For backwards compatibility rootUri and rootPath will be derived from the first workspace +--- folder in this list. See `workspaceFolders` in the LSP spec. +--- @field workspace_folders? lsp.WorkspaceFolder[] +--- +--- Map overriding the default capabilities defined by |vim.lsp.protocol.make_client_capabilities()|, +--- passed to the language server on initialization. Hint: use make_client_capabilities() and modify +--- its result. +--- - Note: To send an empty dictionary use |vim.empty_dict()|, else it will be encoded as an +--- array. +--- @field capabilities? lsp.ClientCapabilities +--- +--- Map of language server method names to |lsp-handler| +--- @field handlers? table<string,function> +--- +--- Map with language server specific settings. +--- See the {settings} in |vim.lsp.Client|. +--- @field settings? table +--- +--- Table that maps string of clientside commands to user-defined functions. +--- Commands passed to start_client take precedence over the global command registry. Each key +--- must be a unique command name, and the value is a function which is called if any LSP action +--- (code action, code lenses, ...) triggers the command. +--- @field commands? table<string,fun(command: lsp.Command, ctx: table)> +--- +--- Values to pass in the initialization request as `initializationOptions`. See `initialize` in +--- the LSP spec. +--- @field init_options? table +--- +--- Name in log messages. +--- (default: client-id) +--- @field name? string +--- +--- Language ID as string. Defaults to the filetype. +--- @field get_language_id? fun(bufnr: integer, filetype: string): string +--- +--- The encoding that the LSP server expects. Client does not verify this is correct. +--- @field offset_encoding? 'utf-8'|'utf-16'|'utf-32' +--- +--- Callback invoked when the client operation throws an error. `code` is a number describing the error. +--- 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 human-friendly name. +--- @field on_error? fun(code: integer, err: string) +--- +--- Callback invoked before the LSP "initialize" phase, where `params` contains the parameters +--- being sent to the server and `config` is the config that was passed to |vim.lsp.start_client()|. +--- You can use this to modify parameters before they are sent. +--- @field before_init? fun(params: lsp.InitializeParams, config: vim.lsp.ClientConfig) +--- +--- Callback invoked after LSP "initialize", where `result` is a table of `capabilities` +--- and anything else the server may send. For example, clangd sends +--- `initialize_result.offsetEncoding` if `capabilities.offsetEncoding` was sent to it. +--- You can only modify the `client.offset_encoding` here before any notifications are sent. +--- @field on_init? elem_or_list<fun(client: vim.lsp.Client, initialize_result: lsp.InitializeResult)> +--- +--- Callback invoked on client exit. +--- - code: exit code of the process +--- - signal: number describing the signal used to terminate (if any) +--- - client_id: client handle +--- @field on_exit? elem_or_list<fun(code: integer, signal: integer, client_id: integer)> +--- +--- Callback invoked when client attaches to a buffer. +--- @field on_attach? elem_or_list<fun(client: vim.lsp.Client, bufnr: integer)> +--- +--- Passed directly to the language server in the initialize request. Invalid/empty values will +--- (default: "off") +--- @field trace? 'off'|'messages'|'verbose' +--- +--- A table with flags for the client. The current (experimental) flags are: +--- @field flags? vim.lsp.Client.Flags +--- +--- Directory where the LSP server will base its workspaceFolders, rootUri, and rootPath on initialization. +--- @field root_dir? string + +--- @class vim.lsp.Client.Progress: vim.Ringbuf<{token: integer|string, value: any}> +--- @field pending table<lsp.ProgressToken,lsp.LSPAny> + +--- @class vim.lsp.Client +--- +--- The id allocated to the client. +--- @field id integer +--- +--- If a name is specified on creation, that will be used. Otherwise it is just +--- the client id. This is used for logs and messages. +--- @field name string +--- +--- RPC client object, for low level interaction with the client. +--- See |vim.lsp.rpc.start()|. +--- @field rpc vim.lsp.rpc.PublicClient +--- +--- The encoding used for communicating with the server. You can modify this in +--- the `config`'s `on_init` method before text is sent to the server. +--- @field offset_encoding string +--- +--- The handlers used by the client as described in |lsp-handler|. +--- @field handlers table<string,lsp.Handler> +--- +--- The current pending requests in flight to the server. Entries are key-value +--- pairs with the key being the request id while the value is a table with +--- `type`, `bufnr`, and `method` key-value pairs. `type` is either "pending" +--- for an active request, or "cancel" for a cancel request. It will be +--- "complete" ephemerally while executing |LspRequest| autocmds when replies +--- are received from the server. +--- @field requests table<integer,{ type: string, bufnr: integer, method: string}> +--- +--- copy of the table that was passed by the user +--- to |vim.lsp.start_client()|. +--- @field config vim.lsp.ClientConfig +--- +--- Response from the server sent on `initialize` describing the server's +--- capabilities. +--- @field server_capabilities lsp.ServerCapabilities? +--- +--- A ring buffer (|vim.ringbuf()|) containing progress messages +--- sent by the server. +--- @field progress vim.lsp.Client.Progress +--- +--- @field initialized true? +--- +--- The workspace folders configured in the client when the server starts. +--- This property is only available if the client supports workspace folders. +--- It can be `null` if the client supports workspace folders but none are +--- configured. +--- @field workspace_folders lsp.WorkspaceFolder[]? +--- @field root_dir string +--- +--- @field attached_buffers table<integer,true> +--- @field private _log_prefix string +--- +--- Track this so that we can escalate automatically if we've already tried a +--- graceful shutdown +--- @field private _graceful_shutdown_failed true? +--- +--- The initial trace setting. If omitted trace is disabled ("off"). +--- trace = "off" | "messages" | "verbose"; +--- @field private _trace 'off'|'messages'|'verbose' +--- +--- Table of command name to function which is called if any LSP action +--- (code action, code lenses, ...) triggers the command. +--- Client commands take precedence over the global command registry. +--- @field commands table<string,fun(command: lsp.Command, ctx: table)> +--- +--- Map with language server specific settings. These are returned to the +--- language server if requested via `workspace/configuration`. Keys are +--- case-sensitive. +--- @field settings table +--- +--- A table with flags for the client. The current (experimental) flags are: +--- @field flags vim.lsp.Client.Flags +--- +--- @field get_language_id fun(bufnr: integer, filetype: string): string +--- +--- The capabilities provided by the client (editor or tool) +--- @field capabilities lsp.ClientCapabilities +--- @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 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`. +--- @field request_sync fun(method: string, params: table?, timeout_ms: integer?, bufnr: integer): {err: lsp.ResponseError|nil, result:any}|nil, string|nil err # a dictionary, where +--- +--- 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, ...) + end +end + +local client_index = 0 + +--- Checks whether a given path is a directory. +--- @param filename (string) path to check +--- @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) + return stat and stat.type == 'directory' or false +end + +local valid_encodings = { + ['utf-8'] = 'utf-8', + ['utf-16'] = 'utf-16', + ['utf-32'] = 'utf-32', + ['utf8'] = 'utf-8', + ['utf16'] = 'utf-16', + ['utf32'] = 'utf-32', + UTF8 = 'utf-8', + UTF16 = 'utf-16', + UTF32 = 'utf-32', +} + +--- Normalizes {encoding} to valid LSP encoding names. +--- @param encoding string? Encoding to normalize +--- @return string # normalized encoding name +local function validate_encoding(encoding) + validate({ + encoding = { encoding, 's', true }, + }) + if not encoding then + return valid_encodings.UTF16 + end + return valid_encodings[encoding:lower()] + or error( + string.format( + "Invalid offset encoding %q. Must be one of: 'utf-8', 'utf-16', 'utf-32'", + encoding + ) + ) +end + +--- Augments a validator function with support for optional (nil) values. +--- @param fn (fun(v): boolean) The original validator function; should return a +--- bool. +--- @return fun(v): boolean # The augmented function. Also returns true if {v} is +--- `nil`. +local function optional_validator(fn) + return function(v) + return v == nil or fn(v) + end +end + +--- By default, get_language_id just returns the exact filetype it is passed. +--- It is possible to pass in something that will calculate a different filetype, +--- to be sent by the client. +--- @param _bufnr integer +--- @param filetype string +local function default_get_language_id(_bufnr, filetype) + return filetype +end + +--- Validates a client configuration as given to |vim.lsp.start_client()|. +--- @param config vim.lsp.ClientConfig +local function validate_config(config) + validate({ + config = { config, 't' }, + }) + validate({ + handlers = { config.handlers, 't', true }, + capabilities = { config.capabilities, 't', true }, + cmd_cwd = { config.cmd_cwd, optional_validator(is_dir), 'directory' }, + cmd_env = { config.cmd_env, 't', true }, + detached = { config.detached, 'b', true }, + name = { config.name, 's', true }, + on_error = { config.on_error, 'f', true }, + on_exit = { config.on_exit, { 'f', 't' }, true }, + on_init = { config.on_init, { 'f', 't' }, true }, + on_attach = { config.on_attach, { 'f', 't' }, true }, + settings = { config.settings, 't', true }, + commands = { config.commands, 't', true }, + before_init = { config.before_init, { 'f', 't' }, true }, + offset_encoding = { config.offset_encoding, 's', true }, + flags = { config.flags, 't', true }, + get_language_id = { config.get_language_id, 'f', true }, + }) + + assert( + ( + not config.flags + or not config.flags.debounce_text_changes + or type(config.flags.debounce_text_changes) == 'number' + ), + 'flags.debounce_text_changes must be a number with the debounce time in milliseconds' + ) +end + +--- @param trace string +--- @return 'off'|'messages'|'verbose' +local function get_trace(trace) + local valid_traces = { + off = 'off', + messages = 'messages', + verbose = 'verbose', + } + return trace and valid_traces[trace] or 'off' +end + +--- @param id integer +--- @param config vim.lsp.ClientConfig +--- @return string +local function get_name(id, config) + local name = config.name + if name then + return name + end + + if type(config.cmd) == 'table' and config.cmd[1] then + return assert(vim.fs.basename(config.cmd[1])) + end + + return tostring(id) +end + +--- @param workspace_folders lsp.WorkspaceFolder[]? +--- @param root_dir string? +--- @return lsp.WorkspaceFolder[]? +local function get_workspace_folders(workspace_folders, root_dir) + if workspace_folders then + return workspace_folders + end + if root_dir then + return { + { + uri = vim.uri_from_fname(root_dir), + name = string.format('%s', root_dir), + }, + } + end +end + +--- @generic T +--- @param x elem_or_list<T>? +--- @return T[] +local function ensure_list(x) + if type(x) == 'table' then + return x + end + return { x } +end + +--- @package +--- @param config vim.lsp.ClientConfig +--- @return vim.lsp.Client? +function Client.create(config) + validate_config(config) + + client_index = client_index + 1 + local id = client_index + local name = get_name(id, config) + + --- @class vim.lsp.Client + local self = { + id = id, + config = config, + handlers = config.handlers or {}, + offset_encoding = validate_encoding(config.offset_encoding), + name = name, + _log_prefix = string.format('LSP[%s]', name), + requests = {}, + attached_buffers = {}, + server_capabilities = {}, + dynamic_capabilities = lsp._dynamic.new(id), + commands = config.commands or {}, + settings = config.settings or {}, + flags = config.flags or {}, + get_language_id = config.get_language_id or default_get_language_id, + capabilities = config.capabilities or lsp.protocol.make_client_capabilities(), + workspace_folders = get_workspace_folders(config.workspace_folders, config.root_dir), + root_dir = config.root_dir, + _before_init_cb = config.before_init, + _on_init_cbs = ensure_list(config.on_init), + _on_exit_cbs = ensure_list(config.on_exit), + _on_attach_cbs = ensure_list(config.on_attach), + _on_error_cb = config.on_error, + _root_dir = config.root_dir, + _trace = get_trace(config.trace), + + --- Contains $/progress report messages. + --- They have the format {token: integer|string, value: any} + --- For "work done progress", value will be one of: + --- - lsp.WorkDoneProgressBegin, + --- - lsp.WorkDoneProgressReport (extended with title from Begin) + --- - lsp.WorkDoneProgressEnd (extended with title from Begin) + progress = vim.ringbuf(50) --[[@as vim.lsp.Client.Progress]], + + --- @deprecated use client.progress instead + messages = { name = name, messages = {}, progress = {}, status = {} }, + } + + 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._cancel_request) + self.stop = method_wrapper(self, Client._stop) + self.is_stopped = method_wrapper(self, Client._is_stopped) + self.on_attach = method_wrapper(self, Client._on_attach) + self.supports_method = method_wrapper(self, Client._supports_method) + + --- @type table<string|integer, string> title of unfinished progress sequences by token + self.progress.pending = {} + + --- @type vim.lsp.rpc.Dispatchers + local dispatchers = { + notification = method_wrapper(self, Client._notification), + server_request = method_wrapper(self, Client._server_request), + on_error = method_wrapper(self, Client._on_error), + on_exit = method_wrapper(self, Client._on_exit), + } + + -- Start the RPC client. + local rpc --- @type vim.lsp.rpc.PublicClient? + local config_cmd = config.cmd + if type(config_cmd) == 'function' then + rpc = config_cmd(dispatchers) + else + rpc = lsp.rpc.start(config_cmd, dispatchers, { + cwd = config.cmd_cwd, + env = config.cmd_env, + detached = config.detached, + }) + end + + -- Return nil if the rpc client fails to start + if not rpc then + return + end + + self.rpc = rpc + + setmetatable(self, Client) + + return self +end + +--- @private +--- @param cbs function[] +--- @param error_id integer +--- @param ... any +function Client:_run_callbacks(cbs, error_id, ...) + for _, cb in pairs(cbs) do + --- @type boolean, string? + local status, err = pcall(cb, ...) + if not status then + self:write_error(error_id, err) + end + end +end + +--- @package +function Client:initialize() + local config = self.config + + local root_uri --- @type string? + local root_path --- @type string? + if self.workspace_folders then + root_uri = self.workspace_folders[1].uri + root_path = vim.uri_to_fname(root_uri) + end + + local initialize_params = { + -- The process Id of the parent process that started the server. Is null if + -- the process has not been started by another process. If the parent + -- process is not alive then the server should exit (see exit notification) + -- its process. + processId = uv.os_getpid(), + -- Information about the client + -- since 3.15.0 + clientInfo = { + name = 'Neovim', + version = tostring(vim.version()), + }, + -- The rootPath of the workspace. Is null if no folder is open. + -- + -- @deprecated in favour of rootUri. + rootPath = root_path or vim.NIL, + -- The rootUri of the workspace. Is null if no folder is open. If both + -- `rootPath` and `rootUri` are set `rootUri` wins. + rootUri = root_uri or vim.NIL, + workspaceFolders = self.workspace_folders or vim.NIL, + -- User provided initialization options. + initializationOptions = config.init_options, + capabilities = self.capabilities, + trace = self._trace, + } + + self:_run_callbacks( + { self._before_init_cb }, + lsp.client_errors.BEFORE_INIT_CALLBACK_ERROR, + initialize_params, + config + ) + + log.trace(self._log_prefix, 'initialize_params', initialize_params) + + local rpc = self.rpc + + rpc.request('initialize', initialize_params, function(init_err, result) + assert(not init_err, tostring(init_err)) + assert(result, 'server sent empty result') + rpc.notify('initialized', vim.empty_dict()) + self.initialized = true + + -- These are the cleaned up capabilities we use for dynamically deciding + -- when to send certain events to clients. + self.server_capabilities = + assert(result.capabilities, "initialize result doesn't contain capabilities") + self.server_capabilities = assert(lsp.protocol.resolve_capabilities(self.server_capabilities)) + + if self.server_capabilities.positionEncoding then + self.offset_encoding = self.server_capabilities.positionEncoding + end + + if next(self.settings) then + self:_notify(ms.workspace_didChangeConfiguration, { settings = self.settings }) + end + + self:_run_callbacks(self._on_init_cbs, lsp.client_errors.ON_INIT_CALLBACK_ERROR, self, result) + + log.info( + self._log_prefix, + 'server_capabilities', + { server_capabilities = self.server_capabilities } + ) + end) +end + +--- @private +--- Returns the handler associated with an LSP method. +--- Returns the default handler if the user hasn't set a custom one. +--- +--- @param method (string) LSP method name +--- @return lsp.Handler|nil handler for the given method, if defined, or the default from |vim.lsp.handlers| +function Client:_resolve_handler(method) + return self.handlers[method] or lsp.handlers[method] +end + +--- Returns the buffer number for the given {bufnr}. +--- +--- @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 + return api.nvim_get_current_buf() + end + return bufnr +end + +--- @private +--- Sends a request to the server. +--- +--- 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|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 +--- 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 +--- second result. You can use this with `client.cancel_request(request_id)` +--- to cancel the-request. +--- @see |vim.lsp.buf_request_all()| +function Client:_request(method, params, handler, bufnr) + if not handler then + handler = assert( + self:_resolve_handler(method), + string.format('not found: %q request handler for client %q.', method, self.name) + ) + end + -- Ensure pending didChange notifications are sent so that the server doesn't operate on a stale state + changetracking.flush(self, bufnr) + local version = lsp.util.buf_versions[bufnr] + bufnr = resolve_bufnr(bufnr) + log.debug(self._log_prefix, 'client.request', self.id, method, params, handler, bufnr) + local success, request_id = self.rpc.request(method, params, function(err, result) + local context = { + method = method, + client_id = self.id, + bufnr = bufnr, + params = params, + version = version, + } + handler(err, result, context) + end, function(request_id) + local request = self.requests[request_id] + request.type = 'complete' + api.nvim_exec_autocmds('LspRequest', { + buffer = api.nvim_buf_is_valid(bufnr) and bufnr or nil, + modeline = false, + data = { client_id = self.id, request_id = request_id, request = request }, + }) + self.requests[request_id] = nil + end) + + if success and request_id then + local request = { type = 'pending', bufnr = bufnr, method = method } + self.requests[request_id] = request + api.nvim_exec_autocmds('LspRequest', { + buffer = bufnr, + modeline = false, + data = { client_id = self.id, request_id = request_id, request = request }, + }) + end + + return success, request_id +end + +-- TODO(lewis6991): duplicated from lsp.lua +local wait_result_reason = { [-1] = 'timeout', [-2] = 'interrupted', [-3] = 'error' } + +--- Concatenates and writes a list of strings to the Vim error buffer. +--- +--- @param ... string List to write to the buffer +local function err_message(...) + local message = table.concat(vim.tbl_flatten({ ... })) + if vim.in_fast_event() then + vim.schedule(function() + api.nvim_err_writeln(message) + api.nvim_command('redraw') + end) + else + api.nvim_err_writeln(message) + api.nvim_command('redraw') + end +end + +--- @private +--- Sends a request to the server and synchronously waits for the response. +--- +--- This is a wrapper around {client.request} +--- +--- @param method (string) LSP method name. +--- @param params (table) LSP request params. +--- @param timeout_ms (integer|nil) Maximum time in milliseconds to wait for +--- a result. Defaults to 1000 +--- @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 +--- 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 + local function _sync_handler(err, result) + request_result = { err = err, result = result } + end + + local success, request_id = self:_request(method, params, _sync_handler, bufnr) + if not success then + return nil + end + + local wait_result, reason = vim.wait(timeout_ms or 1000, function() + return request_result ~= nil + end, 10) + + if not wait_result then + if request_id then + self:_cancel_request(request_id) + end + return nil, wait_result_reason[reason] + end + return request_result +end + +--- @private +--- Sends a notification to an LSP server. +--- +--- @param method string LSP method name. +--- @param params table|nil LSP request params. +--- @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) + if method ~= ms.textDocument_didChange then + changetracking.flush(self) + end + + local client_active = self.rpc.notify(method, params) + + if client_active then + vim.schedule(function() + api.nvim_exec_autocmds('LspNotify', { + modeline = false, + data = { + client_id = self.id, + method = method, + params = params, + }, + }) + end) + end + + return client_active +end + +--- @private +--- Cancels a request with a given request id. +--- +--- @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) + validate({ id = { id, 'n' } }) + local request = self.requests[id] + if request and request.type == 'pending' then + request.type = 'cancel' + api.nvim_exec_autocmds('LspRequest', { + buffer = request.bufnr, + modeline = false, + data = { client_id = self.id, request_id = id, request = request }, + }) + end + return self.rpc.notify(ms.dollar_cancelRequest, { id = id }) +end + +--- @private +--- 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. +--- +--- @param force boolean|nil +function Client:_stop(force) + local rpc = self.rpc + + if rpc.is_closing() then + return + end + + if force or not self.initialized or self._graceful_shutdown_failed then + rpc.terminate() + return + end + + -- Sending a signal after a process has exited is acceptable. + rpc.request(ms.shutdown, nil, function(err, _) + if err == nil then + rpc.notify(ms.exit) + else + -- If there was an error in the shutdown request, then term to be safe. + rpc.terminate() + self._graceful_shutdown_failed = true + end + vim.lsp._watchfiles.cancel(self.id) + end) +end + +--- @private +--- Checks whether a client is stopped. +--- +--- @return boolean # true if client is stopped or in the process of being +--- stopped; false otherwise +function Client:_is_stopped() + return self.rpc.is_closing() +end + +--- @package +--- Execute a lsp command, either via client command function (if available) +--- or via workspace/executeCommand (if supported by the server) +--- +--- @param command lsp.Command +--- @param context? {bufnr: integer} +--- @param handler? lsp.Handler only called if a server command +function Client:_exec_cmd(command, context, handler) + context = vim.deepcopy(context or {}, true) --[[@as lsp.HandlerContext]] + context.bufnr = context.bufnr or api.nvim_get_current_buf() + context.client_id = self.id + local cmdname = command.command + local fn = self.commands[cmdname] or lsp.commands[cmdname] + if fn then + fn(command, context) + return + end + + local command_provider = self.server_capabilities.executeCommandProvider + local commands = type(command_provider) == 'table' and command_provider.commands or {} + if not vim.list_contains(commands, cmdname) then + vim.notify_once( + string.format( + 'Language server `%s` does not support command `%s`. This command may require a client extension.', + self.name, + cmdname + ), + vim.log.levels.WARN + ) + return + end + -- Not using command directly to exclude extra properties, + -- see https://github.com/python-lsp/python-lsp-server/issues/146 + local params = { + command = command.command, + arguments = command.arguments, + } + self.request(ms.workspace_executeCommand, params, handler, context.bufnr) +end + +--- @package +--- Default handler for the 'textDocument/didOpen' LSP notification. +--- +--- @param bufnr integer Number of the buffer, or 0 for current +function Client:_text_document_did_open_handler(bufnr) + changetracking.init(self, bufnr) + if not vim.tbl_get(self.server_capabilities, 'textDocumentSync', 'openClose') then + return + end + if not api.nvim_buf_is_loaded(bufnr) then + return + end + local filetype = vim.bo[bufnr].filetype + + local params = { + textDocument = { + version = 0, + uri = vim.uri_from_bufnr(bufnr), + languageId = self.get_language_id(bufnr, filetype), + text = lsp._buf_get_full_text(bufnr), + }, + } + self.notify(ms.textDocument_didOpen, params) + lsp.util.buf_versions[bufnr] = params.textDocument.version + + -- Next chance we get, we should re-do the diagnostics + vim.schedule(function() + -- Protect against a race where the buffer disappears + -- between `did_open_handler` and the scheduled function firing. + if api.nvim_buf_is_valid(bufnr) then + local namespace = lsp.diagnostic.get_namespace(self.id) + vim.diagnostic.show(namespace, bufnr) + end + end) +end + +--- @package +--- Runs the on_attach function from the client's config if it was defined. +--- @param bufnr integer Buffer number +function Client:_on_attach(bufnr) + self:_text_document_did_open_handler(bufnr) + + lsp._set_defaults(self, bufnr) + + api.nvim_exec_autocmds('LspAttach', { + buffer = bufnr, + modeline = false, + data = { client_id = self.id }, + }) + + self:_run_callbacks(self._on_attach_cbs, lsp.client_errors.ON_ATTACH_ERROR, self, bufnr) + + -- schedule the initialization of semantic tokens to give the above + -- on_attach and LspAttach callbacks the ability to schedule wrap the + -- opt-out (deleting the semanticTokensProvider from capabilities) + vim.schedule(function() + if vim.tbl_get(self.server_capabilities, 'semanticTokensProvider', 'full') then + lsp.semantic_tokens.start(bufnr, self.id) + end + end) + + self.attached_buffers[bufnr] = true +end + +--- @private +--- Logs the given error to the LSP log and to the error buffer. +--- @param code integer Error code +--- @param err any Error arguments +function Client:write_error(code, err) + local client_error = lsp.client_errors[code] --- @type string|integer + log.error(self._log_prefix, 'on_error', { code = client_error, err = err }) + err_message(self._log_prefix, ': Error ', client_error, ': ', vim.inspect(err)) +end + +--- @private +--- @param method string +--- @param opts? {bufnr: integer?} +function Client:_supports_method(method, opts) + local required_capability = lsp._request_name_to_capability[method] + -- if we don't know about the method, assume that the client supports it. + if not required_capability then + return true + end + if vim.tbl_get(self.server_capabilities, unpack(required_capability)) then + return true + end + if self.dynamic_capabilities:supports_registration(method) then + return self.dynamic_capabilities:supports(method, opts) + end + return false +end + +--- @private +--- Handles a notification sent by an LSP server by invoking the +--- corresponding handler. +--- +--- @param method string LSP method name +--- @param params table The parameters for that method. +function Client:_notification(method, params) + log.trace('notification', method, params) + local handler = self:_resolve_handler(method) + if handler then + -- Method name is provided here for convenience. + handler(nil, params, { method = method, client_id = self.id }) + end +end + +--- @private +--- Handles a request from an LSP server by invoking the corresponding handler. +--- +--- @param method (string) LSP method name +--- @param params (table) The parameters for that method +--- @return any result +--- @return lsp.ResponseError error code and message set in case an exception happens during the request. +function Client:_server_request(method, params) + log.trace('server_request', method, params) + local handler = self:_resolve_handler(method) + if handler then + log.trace('server_request: found handler for', method) + return handler(nil, params, { method = method, client_id = self.id }) + end + log.warn('server_request: no handler found for', method) + return nil, lsp.rpc_response_error(lsp.protocol.ErrorCodes.MethodNotFound) +end + +--- @private +--- Invoked when the client operation throws an error. +--- +--- @param code integer Error code +--- @param err any 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. +function Client:_on_error(code, err) + self:write_error(code, err) + if self._on_error_cb then + --- @type boolean, string + local status, usererr = pcall(self._on_error_cb, code, err) + if not status then + log.error(self._log_prefix, 'user on_error failed', { err = usererr }) + err_message(self._log_prefix, ' user on_error failed: ', tostring(usererr)) + end + end +end + +--- @private +--- Invoked on client exit. +--- +--- @param code integer) exit code of the process +--- @param signal integer the signal used to terminate (if any) +function Client:_on_exit(code, signal) + self:_run_callbacks( + self._on_exit_cbs, + lsp.client_errors.ON_EXIT_CALLBACK_ERROR, + code, + signal, + self.id + ) +end + +return Client diff --git a/runtime/lua/vim/lsp/codelens.lua b/runtime/lua/vim/lsp/codelens.lua index 9cccaa1d66..48c096c0c1 100644 --- a/runtime/lua/vim/lsp/codelens.lua +++ b/runtime/lua/vim/lsp/codelens.lua @@ -6,7 +6,7 @@ local M = {} --- bufnr → true|nil --- to throttle refreshes to at most one at a time -local active_refreshes = {} +local active_refreshes = {} --- @type table<integer,true> ---@type table<integer, table<integer, lsp.CodeLens[]>> --- bufnr -> client_id -> lenses @@ -48,7 +48,7 @@ local function execute_lens(lens, bufnr, client_id) local client = vim.lsp.get_client_by_id(client_id) assert(client, 'Client is required to execute lens, client_id=' .. client_id) - client._exec_cmd(lens.command, { bufnr = bufnr }, function(...) + client:_exec_cmd(lens.command, { bufnr = bufnr }, function(...) vim.lsp.handlers[ms.workspace_executeCommand](...) M.refresh() end) @@ -75,7 +75,7 @@ end function M.run() local line = api.nvim_win_get_cursor(0)[1] local bufnr = api.nvim_get_current_buf() - local options = {} + local options = {} --- @type {client: integer, lens: lsp.CodeLens}[] local lenses_by_client = lens_cache_by_buf[bufnr] or {} for client, lenses in pairs(lenses_by_client) do for _, lens in pairs(lenses) do @@ -111,7 +111,7 @@ end --- Clear the lenses --- ---@param client_id integer|nil filter by client_id. All clients if nil ----@param bufnr integer|nil filter by buffer. All buffers if nil +---@param bufnr integer|nil filter by buffer. All buffers if nil, 0 for current buffer function M.clear(client_id, bufnr) bufnr = bufnr and resolve_bufnr(bufnr) local buffers = bufnr and { bufnr } @@ -230,6 +230,7 @@ local function resolve_lenses(lenses, bufnr, client_id, callback) if lens.command then countdown() else + assert(client) client.request('codeLens/resolve', lens, function(_, result) if api.nvim_buf_is_loaded(bufnr) and result and result.command then lens.command = result.command @@ -257,10 +258,13 @@ end --- |lsp-handler| for the method `textDocument/codeLens` --- +---@param err lsp.ResponseError? +---@param result lsp.CodeLens[] +---@param ctx lsp.HandlerContext function M.on_codelens(err, result, ctx, _) if err then - active_refreshes[ctx.bufnr] = nil - local _ = log.error() and log.error('codelens', err) + active_refreshes[assert(ctx.bufnr)] = nil + log.error('codelens', err) return end @@ -270,30 +274,41 @@ function M.on_codelens(err, result, ctx, _) -- once resolved. M.display(result, ctx.bufnr, ctx.client_id) resolve_lenses(result, ctx.bufnr, ctx.client_id, function() - active_refreshes[ctx.bufnr] = nil + active_refreshes[assert(ctx.bufnr)] = nil M.display(result, ctx.bufnr, ctx.client_id) end) end ---- Refresh the codelens for the current buffer +--- @class vim.lsp.codelens.refresh.Opts +--- @inlinedoc +--- @field bufnr integer? filter by buffer. All buffers if nil, 0 for current buffer + +--- Refresh the lenses. --- --- It is recommended to trigger this using an autocmd or via keymap. --- --- Example: --- --- ```vim ---- autocmd BufEnter,CursorHold,InsertLeave <buffer> lua vim.lsp.codelens.refresh() +--- autocmd BufEnter,CursorHold,InsertLeave <buffer> lua vim.lsp.codelens.refresh({ bufnr = 0 }) --- ``` -function M.refresh() +--- +--- @param opts? vim.lsp.codelens.refresh.Opts Optional fields +function M.refresh(opts) + opts = opts or {} + local bufnr = opts.bufnr and resolve_bufnr(opts.bufnr) + local buffers = bufnr and { bufnr } + or vim.tbl_filter(api.nvim_buf_is_loaded, api.nvim_list_bufs()) local params = { textDocument = util.make_text_document_params(), } - local bufnr = api.nvim_get_current_buf() - if active_refreshes[bufnr] then - return + + for _, buf in ipairs(buffers) do + if not active_refreshes[buf] then + active_refreshes[buf] = true + vim.lsp.buf_request(buf, ms.textDocument_codeLens, params, M.on_codelens) + end end - active_refreshes[bufnr] = true - vim.lsp.buf_request(0, ms.textDocument_codeLens, params, M.on_codelens) end return M diff --git a/runtime/lua/vim/lsp/diagnostic.lua b/runtime/lua/vim/lsp/diagnostic.lua index b6f0cfa0b3..08cea13548 100644 --- a/runtime/lua/vim/lsp/diagnostic.lua +++ b/runtime/lua/vim/lsp/diagnostic.lua @@ -1,8 +1,4 @@ ----@brief lsp-diagnostic - -local util = require('vim.lsp.util') local protocol = require('vim.lsp.protocol') -local log = require('vim.lsp.log') local ms = protocol.Methods local api = vim.api @@ -24,7 +20,7 @@ end ---@param severity lsp.DiagnosticSeverity local function severity_lsp_to_vim(severity) if type(severity) == 'string' then - severity = protocol.DiagnosticSeverity[severity] + severity = protocol.DiagnosticSeverity[severity] --- @type integer end return severity end @@ -37,6 +33,10 @@ local function severity_vim_to_lsp(severity) return severity end +---@param lines string[]? +---@param lnum integer +---@param col integer +---@param offset_encoding string ---@return integer local function line_byte_from_position(lines, lnum, col, offset_encoding) if not lines or offset_encoding == 'utf-8' then @@ -46,12 +46,14 @@ local function line_byte_from_position(lines, lnum, col, offset_encoding) local line = lines[lnum + 1] local ok, result = pcall(vim.str_byteindex, line, col, offset_encoding == 'utf-16') if ok then - return result + return result --- @type integer end return col end +---@param bufnr integer +---@return string[]? local function get_buf_lines(bufnr) if vim.api.nvim_buf_is_loaded(bufnr) then return vim.api.nvim_buf_get_lines(bufnr, 0, -1, false) @@ -89,7 +91,7 @@ local function tags_lsp_to_vim(diagnostic, client_id) tags = tags or {} tags.deprecated = true else - log.info(string.format('Unknown DiagnosticTag %d from LSP client %d', tag, client_id)) + vim.lsp.log.info(string.format('Unknown DiagnosticTag %d from LSP client %d', tag, client_id)) end end return tags @@ -98,16 +100,17 @@ end ---@param diagnostics lsp.Diagnostic[] ---@param bufnr integer ---@param client_id integer ----@return Diagnostic[] +---@return vim.Diagnostic[] local function diagnostic_lsp_to_vim(diagnostics, bufnr, client_id) local buf_lines = get_buf_lines(bufnr) local client = vim.lsp.get_client_by_id(client_id) local offset_encoding = client and client.offset_encoding or 'utf-16' - ---@diagnostic disable-next-line:no-unknown + --- @param diagnostic lsp.Diagnostic + --- @return vim.Diagnostic return vim.tbl_map(function(diagnostic) - ---@cast diagnostic lsp.Diagnostic local start = diagnostic.range.start local _end = diagnostic.range['end'] + --- @type vim.Diagnostic return { lnum = start.line, col = line_byte_from_position(buf_lines, start.line, start.character, offset_encoding), @@ -131,12 +134,29 @@ local function diagnostic_lsp_to_vim(diagnostics, bufnr, client_id) end, diagnostics) end ---- @param diagnostics Diagnostic[] +--- @param diagnostic vim.Diagnostic +--- @return lsp.DiagnosticTag[]? +local function tags_vim_to_lsp(diagnostic) + if not diagnostic._tags then + return + end + + local tags = {} --- @type lsp.DiagnosticTag[] + if diagnostic._tags.unnecessary then + tags[#tags + 1] = protocol.DiagnosticTag.Unnecessary + end + if diagnostic._tags.deprecated then + tags[#tags + 1] = protocol.DiagnosticTag.Deprecated + end + return tags +end + +--- @param diagnostics vim.Diagnostic[] --- @return lsp.Diagnostic[] local function diagnostic_vim_to_lsp(diagnostics) - ---@diagnostic disable-next-line:no-unknown + ---@param diagnostic vim.Diagnostic + ---@return lsp.Diagnostic return vim.tbl_map(function(diagnostic) - ---@cast diagnostic Diagnostic return vim.tbl_extend('keep', { -- "keep" the below fields over any duplicate fields in diagnostic.user_data.lsp range = { @@ -153,6 +173,7 @@ local function diagnostic_vim_to_lsp(diagnostics) message = diagnostic.message, source = diagnostic.source, code = diagnostic.code, + tags = tags_vim_to_lsp(diagnostic), }, diagnostic.user_data and (diagnostic.user_data.lsp or {}) or {}) end, diagnostics) end @@ -198,6 +219,47 @@ function M.get_namespace(client_id, is_pull) end end +local function convert_severity(opt) + if type(opt) == 'table' and not opt.severity and opt.severity_limit then + vim.deprecate('severity_limit', '{min = severity} See vim.diagnostic.severity', '0.11') + opt.severity = { min = severity_lsp_to_vim(opt.severity_limit) } + end +end + +--- @param uri string +--- @param client_id? integer +--- @param diagnostics vim.Diagnostic[] +--- @param is_pull boolean +--- @param config? vim.diagnostic.Opts +local function handle_diagnostics(uri, client_id, diagnostics, is_pull, config) + local fname = vim.uri_to_fname(uri) + + if #diagnostics == 0 and vim.fn.bufexists(fname) == 0 then + return + end + + local bufnr = vim.fn.bufadd(fname) + if not bufnr then + return + end + + client_id = get_client_id(client_id) + local namespace = M.get_namespace(client_id, is_pull) + + if config then + --- @cast config table<string, table> + for _, opt in pairs(config) do + convert_severity(opt) + end + -- Persist configuration to ensure buffer reloads use the same + -- configuration. To make lsp.with configuration work (See :help + -- lsp-handler-configuration) + vim.diagnostic.config(config, namespace) + end + + vim.diagnostic.set(namespace, bufnr, diagnostic_lsp_to_vim(diagnostics, bufnr, client_id)) +end + --- |lsp-handler| for the method "textDocument/publishDiagnostics" --- --- See |vim.diagnostic.config()| for configuration options. Handler-specific @@ -223,40 +285,12 @@ end --- ) --- ``` --- ----@param config table Configuration table (see |vim.diagnostic.config()|). +---@param _ lsp.ResponseError? +---@param result lsp.PublishDiagnosticsParams +---@param ctx lsp.HandlerContext +---@param config? vim.diagnostic.Opts Configuration table (see |vim.diagnostic.config()|). function M.on_publish_diagnostics(_, result, ctx, config) - local client_id = ctx.client_id - local uri = result.uri - local fname = vim.uri_to_fname(uri) - local diagnostics = result.diagnostics - if #diagnostics == 0 and vim.fn.bufexists(fname) == 0 then - return - end - local bufnr = vim.fn.bufadd(fname) - - if not bufnr then - return - end - - client_id = get_client_id(client_id) - local namespace = M.get_namespace(client_id, false) - - if config then - for _, opt in pairs(config) do - if type(opt) == 'table' then - if not opt.severity and opt.severity_limit then - opt.severity = { min = severity_lsp_to_vim(opt.severity_limit) } - end - end - end - - -- Persist configuration to ensure buffer reloads use the same - -- configuration. To make lsp.with configuration work (See :help - -- lsp-handler-configuration) - vim.diagnostic.config(config, namespace) - end - - vim.diagnostic.set(namespace, bufnr, diagnostic_lsp_to_vim(diagnostics, bufnr, client_id)) + handle_diagnostics(result.uri, ctx.client_id, result.diagnostics, false, config) end --- |lsp-handler| for the method "textDocument/diagnostic" @@ -284,48 +318,16 @@ end --- ) --- ``` --- ----@param config table Configuration table (see |vim.diagnostic.config()|). +---@param _ lsp.ResponseError? +---@param result lsp.DocumentDiagnosticReport +---@param ctx lsp.HandlerContext +---@param config vim.diagnostic.Opts Configuration table (see |vim.diagnostic.config()|). function M.on_diagnostic(_, result, ctx, config) - local client_id = ctx.client_id - local uri = ctx.params.textDocument.uri - local fname = vim.uri_to_fname(uri) - - if result == nil then - return - end - - if result.kind == 'unchanged' then - return - end - - local diagnostics = result.items - if #diagnostics == 0 and vim.fn.bufexists(fname) == 0 then + if result == nil or result.kind == 'unchanged' then return end - local bufnr = vim.fn.bufadd(fname) - - if not bufnr then - return - end - - client_id = get_client_id(client_id) - - local namespace = M.get_namespace(client_id, true) - - if config then - for _, opt in pairs(config) do - if type(opt) == 'table' and not opt.severity and opt.severity_limit then - opt.severity = { min = severity_lsp_to_vim(opt.severity_limit) } - end - end - - -- Persist configuration to ensure buffer reloads use the same - -- configuration. To make lsp.with configuration work (See :help - -- lsp-handler-configuration) - vim.diagnostic.config(config, namespace) - end - vim.diagnostic.set(namespace, bufnr, diagnostic_lsp_to_vim(diagnostics, bufnr, client_id)) + handle_diagnostics(ctx.params.textDocument.uri, ctx.client_id, result.items, true, config) end --- Clear push diagnostics and diagnostic cache. @@ -335,7 +337,7 @@ end --- implementation so it's simply marked @private rather than @deprecated. --- ---@param client_id integer ----@param buffer_client_map table map of buffers to active clients +---@param buffer_client_map table<integer, table<integer, table>> map of buffers to active clients ---@private function M.reset(client_id, buffer_client_map) buffer_client_map = vim.deepcopy(buffer_client_map) @@ -356,34 +358,28 @@ end --- ---@param bufnr integer|nil The buffer number ---@param line_nr integer|nil The line number ----@param opts table|nil Configuration keys ---- - severity: (DiagnosticSeverity, default nil) ---- - Only return diagnostics with this severity. Overrides severity_limit ---- - severity_limit: (DiagnosticSeverity, default nil) ---- - Limit severity of diagnostics found. E.g. "Warning" means { "Error", "Warning" } will be valid. +---@param opts {severity?:lsp.DiagnosticSeverity}? +--- - severity: (lsp.DiagnosticSeverity) +--- - Only return diagnostics with this severity. ---@param client_id integer|nil the client id ---@return table Table with map of line number to list of diagnostics. --- Structured: { [1] = {...}, [5] = {.... } } ---@private function M.get_line_diagnostics(bufnr, line_nr, opts, client_id) - opts = opts or {} - if opts.severity then - opts.severity = severity_lsp_to_vim(opts.severity) - elseif opts.severity_limit then - opts.severity = { min = severity_lsp_to_vim(opts.severity_limit) } - end + convert_severity(opts) + local diag_opts = {} --- @type vim.diagnostic.GetOpts - if client_id then - opts.namespace = M.get_namespace(client_id, false) + if opts and opts.severity then + diag_opts.severity = severity_lsp_to_vim(opts.severity) end - if not line_nr then - line_nr = vim.api.nvim_win_get_cursor(0)[1] - 1 + if client_id then + diag_opts.namespace = M.get_namespace(client_id, false) end - opts.lnum = line_nr + diag_opts.lnum = line_nr or (api.nvim_win_get_cursor(0)[1] - 1) - return diagnostic_vim_to_lsp(vim.diagnostic.get(bufnr, opts)) + return diagnostic_vim_to_lsp(vim.diagnostic.get(bufnr, diag_opts)) end --- Clear diagnostics from pull based clients @@ -394,12 +390,13 @@ local function clear(bufnr) end end ----@class lsp.diagnostic.bufstate +---@class (private) lsp.diagnostic.bufstate ---@field enabled boolean Whether inlay hints are enabled for this buffer ---@type table<integer, lsp.diagnostic.bufstate> local bufstates = {} --- Disable pull diagnostics for a buffer +--- @param bufnr integer --- @private local function disable(bufnr) local bufstate = bufstates[bufnr] @@ -416,7 +413,7 @@ end local function _refresh(bufnr, opts) opts = opts or {} opts['bufnr'] = bufnr - util._refresh(ms.textDocument_diagnostic, opts) + vim.lsp.util._refresh(ms.textDocument_diagnostic, opts) end --- Enable pull diagnostics for a buffer @@ -440,7 +437,8 @@ function M._enable(bufnr) return end if bufstates[bufnr] and bufstates[bufnr].enabled then - _refresh(bufnr, { only_visible = true, client_id = opts.data.client_id }) + local client_id = opts.data.client_id --- @type integer? + _refresh(bufnr, { only_visible = true, client_id = client_id }) end end, group = augroup, diff --git a/runtime/lua/vim/lsp/handlers.lua b/runtime/lua/vim/lsp/handlers.lua index 6fde55cf04..daf4fec8d2 100644 --- a/runtime/lua/vim/lsp/handlers.lua +++ b/runtime/lua/vim/lsp/handlers.lua @@ -4,6 +4,7 @@ local ms = protocol.Methods local util = require('vim.lsp.util') local api = vim.api +--- @type table<string,lsp.Handler> local M = {} -- FIXME: DOC: Expose in vimdocs @@ -15,12 +16,12 @@ local function err_message(...) api.nvim_command('redraw') end ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_executeCommand +--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_executeCommand M[ms.workspace_executeCommand] = function(_, _, _, _) -- Error handling is done implicitly by wrapping all handlers; see end of this file end ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#progress +--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#progress ---@param result lsp.ProgressParams ---@param ctx lsp.HandlerContext M[ms.dollar_progress] = function(_, result, ctx) @@ -56,7 +57,7 @@ M[ms.dollar_progress] = function(_, result, ctx) }) end ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#window_workDoneProgress_create +--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#window_workDoneProgress_create ---@param result lsp.WorkDoneProgressCreateParams ---@param ctx lsp.HandlerContext M[ms.window_workDoneProgress_create] = function(_, result, ctx) @@ -69,7 +70,7 @@ M[ms.window_workDoneProgress_create] = function(_, result, ctx) return vim.NIL end ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#window_showMessageRequest +--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#window_showMessageRequest ---@param result lsp.ShowMessageRequestParams M[ms.window_showMessageRequest] = function(_, result) local actions = result.actions or {} @@ -105,11 +106,11 @@ M[ms.window_showMessageRequest] = function(_, result) end end ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#client_registerCapability +--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#client_registerCapability +--- @param result lsp.RegistrationParams M[ms.client_registerCapability] = function(_, result, ctx) local client_id = ctx.client_id - ---@type lsp.Client - local client = vim.lsp.get_client_by_id(client_id) + local client = assert(vim.lsp.get_client_by_id(client_id)) client.dynamic_capabilities:register(result.registrations) for bufnr, _ in pairs(client.attached_buffers) do @@ -120,7 +121,7 @@ M[ms.client_registerCapability] = function(_, result, ctx) local unsupported = {} for _, reg in ipairs(result.registrations) do if reg.method == ms.workspace_didChangeWatchedFiles then - require('vim.lsp._watchfiles').register(reg, ctx) + vim.lsp._watchfiles.register(reg, ctx) elseif not client.dynamic_capabilities:supports_registration(reg.method) then unsupported[#unsupported + 1] = reg.method end @@ -136,21 +137,22 @@ M[ms.client_registerCapability] = function(_, result, ctx) return vim.NIL end ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#client_unregisterCapability +--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#client_unregisterCapability +--- @param result lsp.UnregistrationParams M[ms.client_unregisterCapability] = function(_, result, ctx) local client_id = ctx.client_id - local client = vim.lsp.get_client_by_id(client_id) + local client = assert(vim.lsp.get_client_by_id(client_id)) client.dynamic_capabilities:unregister(result.unregisterations) for _, unreg in ipairs(result.unregisterations) do if unreg.method == ms.workspace_didChangeWatchedFiles then - require('vim.lsp._watchfiles').unregister(unreg, ctx) + vim.lsp._watchfiles.unregister(unreg, ctx) end end return vim.NIL end ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_applyEdit +--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_applyEdit M[ms.workspace_applyEdit] = function(_, workspace_edit, ctx) assert( workspace_edit, @@ -158,7 +160,7 @@ M[ms.workspace_applyEdit] = function(_, workspace_edit, ctx) ) -- TODO(ashkan) Do something more with label? local client_id = ctx.client_id - local client = vim.lsp.get_client_by_id(client_id) + local client = assert(vim.lsp.get_client_by_id(client_id)) if workspace_edit.label then print('Workspace edit', workspace_edit.label) end @@ -170,7 +172,16 @@ M[ms.workspace_applyEdit] = function(_, workspace_edit, ctx) } end ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_configuration +---@param table table e.g., { foo = { bar = "z" } } +---@param section string indicating the field of the table, e.g., "foo.bar" +---@return any|nil setting value read from the table, or `nil` not found +local function lookup_section(table, section) + local keys = vim.split(section, '.', { plain = true }) --- @type string[] + return vim.tbl_get(table, unpack(keys)) +end + +--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_configuration +--- @param result lsp.ConfigurationParams M[ms.workspace_configuration] = function(_, result, ctx) local client_id = ctx.client_id local client = vim.lsp.get_client_by_id(client_id) @@ -189,10 +200,13 @@ M[ms.workspace_configuration] = function(_, result, ctx) local response = {} for _, item in ipairs(result.items) do if item.section then - local value = util.lookup_section(client.config.settings, item.section) + local value = lookup_section(client.settings, item.section) -- For empty sections with no explicit '' key, return settings as is - if value == vim.NIL and item.section == '' then - value = client.config.settings or vim.NIL + if value == nil and item.section == '' then + value = client.settings + end + if value == nil then + value = vim.NIL end table.insert(response, value) end @@ -200,7 +214,7 @@ M[ms.workspace_configuration] = function(_, result, ctx) return response end ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_workspaceFolders +--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_workspaceFolders M[ms.workspace_workspaceFolders] = function(_, _, ctx) local client_id = ctx.client_id local client = vim.lsp.get_client_by_id(client_id) @@ -212,41 +226,42 @@ M[ms.workspace_workspaceFolders] = function(_, _, ctx) end M[ms.textDocument_publishDiagnostics] = function(...) - return require('vim.lsp.diagnostic').on_publish_diagnostics(...) + return vim.lsp.diagnostic.on_publish_diagnostics(...) end M[ms.textDocument_diagnostic] = function(...) - return require('vim.lsp.diagnostic').on_diagnostic(...) + return vim.lsp.diagnostic.on_diagnostic(...) end M[ms.textDocument_codeLens] = function(...) - return require('vim.lsp.codelens').on_codelens(...) + return vim.lsp.codelens.on_codelens(...) end M[ms.textDocument_inlayHint] = function(...) - return require('vim.lsp.inlay_hint').on_inlayhint(...) + return vim.lsp.inlay_hint.on_inlayhint(...) end ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_references +--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_references M[ms.textDocument_references] = function(_, result, ctx, config) if not result or vim.tbl_isempty(result) then vim.notify('No references found') - else - local client = vim.lsp.get_client_by_id(ctx.client_id) - config = config or {} - local title = 'References' - local items = util.locations_to_items(result, client.offset_encoding) + return + end - if config.loclist then - vim.fn.setloclist(0, {}, ' ', { title = title, items = items, context = ctx }) - api.nvim_command('lopen') - elseif config.on_list then - assert(type(config.on_list) == 'function', 'on_list is not a function') - config.on_list({ title = title, items = items, context = ctx }) - else - vim.fn.setqflist({}, ' ', { title = title, items = items, context = ctx }) - api.nvim_command('botright copen') - end + local client = assert(vim.lsp.get_client_by_id(ctx.client_id)) + config = config or {} + local title = 'References' + local items = util.locations_to_items(result, client.offset_encoding) + + if config.loclist then + vim.fn.setloclist(0, {}, ' ', { title = title, items = items, context = ctx }) + api.nvim_command('lopen') + elseif config.on_list then + assert(type(config.on_list) == 'function', 'on_list is not a function') + config.on_list({ title = title, items = items, context = ctx }) + else + vim.fn.setqflist({}, ' ', { title = title, items = items, context = ctx }) + api.nvim_command('botright copen') end end @@ -259,31 +274,32 @@ end --- ---@param map_result function `((resp, bufnr) -> list)` to convert the response ---@param entity string name of the resource used in a `not found` error message ----@param title_fn function Function to call to generate list title +---@param title_fn fun(ctx: lsp.HandlerContext): string Function to call to generate list title +---@return lsp.Handler local function response_to_list(map_result, entity, title_fn) return function(_, result, ctx, config) if not result or vim.tbl_isempty(result) then vim.notify('No ' .. entity .. ' found') + return + end + config = config or {} + local title = title_fn(ctx) + local items = map_result(result, ctx.bufnr) + + if config.loclist then + vim.fn.setloclist(0, {}, ' ', { title = title, items = items, context = ctx }) + api.nvim_command('lopen') + elseif config.on_list then + assert(type(config.on_list) == 'function', 'on_list is not a function') + config.on_list({ title = title, items = items, context = ctx }) else - config = config or {} - local title = title_fn(ctx) - local items = map_result(result, ctx.bufnr) - - if config.loclist then - vim.fn.setloclist(0, {}, ' ', { title = title, items = items, context = ctx }) - api.nvim_command('lopen') - elseif config.on_list then - assert(type(config.on_list) == 'function', 'on_list is not a function') - config.on_list({ title = title, items = items, context = ctx }) - else - vim.fn.setqflist({}, ' ', { title = title, items = items, context = ctx }) - api.nvim_command('botright copen') - end + vim.fn.setqflist({}, ' ', { title = title, items = items, context = ctx }) + api.nvim_command('botright copen') end end end ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_documentSymbol +--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_documentSymbol M[ms.textDocument_documentSymbol] = response_to_list( util.symbols_to_items, 'document symbols', @@ -293,45 +309,46 @@ M[ms.textDocument_documentSymbol] = response_to_list( end ) ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_symbol +--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_symbol M[ms.workspace_symbol] = response_to_list(util.symbols_to_items, 'symbols', function(ctx) return string.format("Symbols matching '%s'", ctx.params.query) end) ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_rename +--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_rename M[ms.textDocument_rename] = function(_, result, ctx, _) if not result then vim.notify("Language server couldn't provide rename result", vim.log.levels.INFO) return end - local client = vim.lsp.get_client_by_id(ctx.client_id) + local client = assert(vim.lsp.get_client_by_id(ctx.client_id)) util.apply_workspace_edit(result, client.offset_encoding) end ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_rangeFormatting +--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_rangeFormatting M[ms.textDocument_rangeFormatting] = function(_, result, ctx, _) if not result then return end - local client = vim.lsp.get_client_by_id(ctx.client_id) + local client = assert(vim.lsp.get_client_by_id(ctx.client_id)) util.apply_text_edits(result, ctx.bufnr, client.offset_encoding) end ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_formatting +--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_formatting M[ms.textDocument_formatting] = function(_, result, ctx, _) if not result then return end - local client = vim.lsp.get_client_by_id(ctx.client_id) + local client = assert(vim.lsp.get_client_by_id(ctx.client_id)) util.apply_text_edits(result, ctx.bufnr, client.offset_encoding) end ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_completion +--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_completion M[ms.textDocument_completion] = function(_, result, _, _) if vim.tbl_isempty(result or {}) then return end - local row, col = unpack(api.nvim_win_get_cursor(0)) + local cursor = api.nvim_win_get_cursor(0) + local row, col = cursor[1], cursor[2] local line = assert(api.nvim_buf_get_lines(0, row - 1, row, false)[1]) local line_to_cursor = line:sub(col + 1) local textMatch = vim.fn.match(line_to_cursor, '\\k*$') @@ -354,6 +371,9 @@ end --- ) --- ``` --- +---@param _ lsp.ResponseError? +---@param result lsp.Hover +---@param ctx lsp.HandlerContext ---@param config table Configuration table. --- - border: (default=nil) --- - Add borders to the floating window @@ -388,20 +408,21 @@ function M.hover(_, result, ctx, config) return util.open_floating_preview(contents, format, config) end ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_hover +--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_hover M[ms.textDocument_hover] = M.hover --- Jumps to a location. Used as a handler for multiple LSP methods. ---@param _ nil not used ---@param result (table) result of LSP method; a location or a list of locations. ----@param ctx (table) table containing the context of the request, including the method +---@param ctx (lsp.HandlerContext) table containing the context of the request, including the method +---@param config? vim.lsp.LocationOpts ---(`textDocument/definition` can return `Location` or `Location[]` local function location_handler(_, result, ctx, config) if result == nil or vim.tbl_isempty(result) then - local _ = log.info() and log.info(ctx.method, 'No location found') + log.info(ctx.method, 'No location found') return nil end - local client = vim.lsp.get_client_by_id(ctx.client_id) + local client = assert(vim.lsp.get_client_by_id(ctx.client_id)) config = config or {} @@ -427,13 +448,13 @@ local function location_handler(_, result, ctx, config) api.nvim_command('botright copen') end ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_declaration +--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_declaration M[ms.textDocument_declaration] = location_handler ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_definition +--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_definition M[ms.textDocument_definition] = location_handler ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_typeDefinition +--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_typeDefinition M[ms.textDocument_typeDefinition] = location_handler ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_implementation +--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_implementation M[ms.textDocument_implementation] = location_handler --- |lsp-handler| for the method "textDocument/signatureHelp". @@ -449,8 +470,9 @@ M[ms.textDocument_implementation] = location_handler --- ) --- ``` --- ----@param result table Response from the language server ----@param ctx table Client context +---@param _ lsp.ResponseError? +---@param result lsp.SignatureHelp Response from the language server +---@param ctx lsp.HandlerContext Client context ---@param config table Configuration table. --- - border: (default=nil) --- - Add borders to the floating window @@ -470,7 +492,7 @@ function M.signature_help(_, result, ctx, config) end return end - local client = vim.lsp.get_client_by_id(ctx.client_id) + local client = assert(vim.lsp.get_client_by_id(ctx.client_id)) local triggers = vim.tbl_get(client.server_capabilities, 'signatureHelpProvider', 'triggerCharacters') local ft = vim.bo[ctx.bufnr].filetype @@ -490,10 +512,10 @@ function M.signature_help(_, result, ctx, config) return fbuf, fwin end ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_signatureHelp +--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_signatureHelp M[ms.textDocument_signatureHelp] = M.signature_help ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_documentHighlight +--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_documentHighlight M[ms.textDocument_documentHighlight] = function(_, result, ctx, _) if not result then return @@ -506,21 +528,22 @@ M[ms.textDocument_documentHighlight] = function(_, result, ctx, _) util.buf_highlight_references(ctx.bufnr, result, client.offset_encoding) end ----@private +--- @private --- --- Displays call hierarchy in the quickfix window. --- ----@param direction `"from"` for incoming calls and `"to"` for outgoing calls ----@return function ---- `CallHierarchyIncomingCall[]` if {direction} is `"from"`, ---- `CallHierarchyOutgoingCall[]` if {direction} is `"to"`, -local make_call_hierarchy_handler = function(direction) +--- @param direction 'from'|'to' `"from"` for incoming calls and `"to"` for outgoing calls +--- @overload fun(direction:'from'): fun(_, result: lsp.CallHierarchyIncomingCall[]?) +--- @overload fun(direction:'to'): fun(_, result: lsp.CallHierarchyOutgoingCall[]?) +local function make_call_hierarchy_handler(direction) + --- @param result lsp.CallHierarchyIncomingCall[]|lsp.CallHierarchyOutgoingCall[] return function(_, result) if not result then return end local items = {} for _, call_hierarchy_call in pairs(result) do + --- @type lsp.CallHierarchyItem local call_hierarchy_item = call_hierarchy_call[direction] for _, range in pairs(call_hierarchy_call.fromRanges) do table.insert(items, { @@ -536,13 +559,14 @@ local make_call_hierarchy_handler = function(direction) end end ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#callHierarchy_incomingCalls +--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#callHierarchy_incomingCalls M[ms.callHierarchy_incomingCalls] = make_call_hierarchy_handler('from') ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#callHierarchy_outgoingCalls +--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#callHierarchy_outgoingCalls M[ms.callHierarchy_outgoingCalls] = make_call_hierarchy_handler('to') ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#window_logMessage +--- @see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#window_logMessage +--- @param result lsp.LogMessageParams M[ms.window_logMessage] = function(_, result, ctx, _) local message_type = result.type local message = result.message @@ -564,7 +588,8 @@ M[ms.window_logMessage] = function(_, result, ctx, _) return result end ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#window_showMessage +--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#window_showMessage +--- @param result lsp.ShowMessageParams M[ms.window_showMessage] = function(_, result, ctx, _) local message_type = result.type local message = result.message @@ -583,7 +608,8 @@ M[ms.window_showMessage] = function(_, result, ctx, _) return result end ---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#window_showDocument +--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#window_showDocument +--- @param result lsp.ShowDocumentParams M[ms.window_showDocument] = function(_, result, ctx, _) local uri = result.uri @@ -626,19 +652,25 @@ end ---@see https://microsoft.github.io/language-server-protocol/specification/#workspace_inlayHint_refresh M[ms.workspace_inlayHint_refresh] = function(err, result, ctx, config) - return require('vim.lsp.inlay_hint').on_refresh(err, result, ctx, config) + return vim.lsp.inlay_hint.on_refresh(err, result, ctx, config) +end + +---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#semanticTokens_refreshRequest +M[ms.workspace_semanticTokens_refresh] = function(err, result, ctx, _config) + return vim.lsp.semantic_tokens._refresh(err, result, ctx) end -- Add boilerplate error validation and logging for all of these. for k, fn in pairs(M) do M[k] = function(err, result, ctx, config) - local _ = log.trace() - and log.trace('default_handler', ctx.method, { + if log.trace() then + log.trace('default_handler', ctx.method, { err = err, result = result, ctx = vim.inspect(ctx), config = config, }) + end if err then -- LSP spec: diff --git a/runtime/lua/vim/lsp/health.lua b/runtime/lua/vim/lsp/health.lua index fe06006108..797a1097f9 100644 --- a/runtime/lua/vim/lsp/health.lua +++ b/runtime/lua/vim/lsp/health.lua @@ -1,13 +1,12 @@ local M = {} ---- Performs a healthcheck for LSP -function M.check() - local report_info = vim.health.info - local report_warn = vim.health.warn +local report_info = vim.health.info +local report_warn = vim.health.warn - local log = require('vim.lsp.log') +local function check_log() + local log = vim.lsp.log local current_log_level = log.get_level() - local log_level_string = log.levels[current_log_level] + local log_level_string = log.levels[current_log_level] ---@type string report_info(string.format('LSP log level : %s', log_level_string)) if current_log_level < log.levels.WARN then @@ -27,9 +26,11 @@ function M.check() local report_fn = (log_size / 1000000 > 100 and report_warn or report_info) report_fn(string.format('Log size: %d KB', log_size / 1000)) +end - local clients = vim.lsp.get_clients() +local function check_active_clients() vim.health.start('vim.lsp: Active Clients') + local clients = vim.lsp.get_clients() if next(clients) then for _, client in pairs(clients) do local attached_to = table.concat(vim.tbl_keys(client.attached_buffers or {}), ',') @@ -38,7 +39,7 @@ function M.check() '%s (id=%s, root_dir=%s, attached_to=[%s])', client.name, client.id, - vim.fn.fnamemodify(client.config.root_dir, ':~'), + vim.fn.fnamemodify(client.root_dir, ':~'), attached_to ) ) @@ -48,4 +49,33 @@ function M.check() end end +local function check_watcher() + vim.health.start('vim.lsp: File watcher') + local watchfunc = vim.lsp._watchfiles._watchfunc + assert(watchfunc) + local watchfunc_name --- @type string + if watchfunc == vim._watch.watch then + watchfunc_name = 'libuv-watch' + elseif watchfunc == vim._watch.watchdirs then + watchfunc_name = 'libuv-watchdirs' + elseif watchfunc == vim._watch.fswatch then + watchfunc_name = 'fswatch' + else + local nm = debug.getinfo(watchfunc, 'S').source + watchfunc_name = string.format('Custom (%s)', nm) + end + + report_info('File watch backend: ' .. watchfunc_name) + if watchfunc_name == 'libuv-watchdirs' then + report_warn('libuv-watchdirs has known performance issues. Consider installing fswatch.') + end +end + +--- Performs a healthcheck for LSP +function M.check() + check_log() + check_active_clients() + check_watcher() +end + return M diff --git a/runtime/lua/vim/lsp/inlay_hint.lua b/runtime/lua/vim/lsp/inlay_hint.lua index 4f7a3b0076..ec676ea97f 100644 --- a/runtime/lua/vim/lsp/inlay_hint.lua +++ b/runtime/lua/vim/lsp/inlay_hint.lua @@ -4,12 +4,12 @@ local ms = require('vim.lsp.protocol').Methods local api = vim.api local M = {} ----@class lsp.inlay_hint.bufstate +---@class (private) vim.lsp.inlay_hint.bufstate ---@field version? integer ----@field client_hint? table<integer, table<integer, lsp.InlayHint[]>> client_id -> (lnum -> hints) +---@field client_hints? table<integer, table<integer, lsp.InlayHint[]>> client_id -> (lnum -> hints) ---@field applied table<integer, integer> Last version of hints applied to this line ---@field enabled boolean Whether inlay hints are enabled for this buffer ----@type table<integer, lsp.inlay_hint.bufstate> +---@type table<integer, vim.lsp.inlay_hint.bufstate> local bufstates = {} local namespace = api.nvim_create_namespace('vim_lsp_inlayhint') @@ -17,13 +17,15 @@ local augroup = api.nvim_create_augroup('vim_lsp_inlayhint', {}) --- |lsp-handler| for the method `textDocument/inlayHint` --- Store hints for a specific buffer and client +---@param result lsp.InlayHint[]? +---@param ctx lsp.HandlerContext ---@private function M.on_inlayhint(err, result, ctx, _) if err then - local _ = log.error() and log.error('inlayhint', err) + log.error('inlayhint', err) return end - local bufnr = ctx.bufnr + local bufnr = assert(ctx.bufnr) if util.buf_versions[bufnr] ~= ctx.version then return end @@ -35,12 +37,12 @@ function M.on_inlayhint(err, result, ctx, _) if not bufstate or not bufstate.enabled then return end - if not (bufstate.client_hint and bufstate.version) then - bufstate.client_hint = vim.defaulttable() + if not (bufstate.client_hints and bufstate.version) then + bufstate.client_hints = vim.defaulttable() bufstate.version = ctx.version end - local hints_by_client = bufstate.client_hint - local client = vim.lsp.get_client_by_id(client_id) + local hints_by_client = bufstate.client_hints + local client = assert(vim.lsp.get_client_by_id(client_id)) local new_hints_by_lnum = vim.defaulttable() local num_unprocessed = #result @@ -52,6 +54,8 @@ function M.on_inlayhint(err, result, ctx, _) end local lines = api.nvim_buf_get_lines(bufnr, 0, -1, false) + ---@param position lsp.Position + ---@return integer local function pos_to_byte(position) local col = position.character if col > 0 then @@ -78,6 +82,7 @@ function M.on_inlayhint(err, result, ctx, _) end --- |lsp-handler| for the method `textDocument/inlayHint/refresh` +---@param ctx lsp.HandlerContext ---@private function M.on_refresh(err, _, ctx, _) if err then @@ -98,11 +103,14 @@ function M.on_refresh(err, _, ctx, _) return vim.NIL end ---- @class vim.lsp.inlay_hint.get.filter +--- Optional filters |kwargs|: +--- @class vim.lsp.inlay_hint.get.Filter +--- @inlinedoc --- @field bufnr integer? --- @field range lsp.Range? ---- + --- @class vim.lsp.inlay_hint.get.ret +--- @inlinedoc --- @field bufnr integer --- @field client_id integer --- @field inlay_hint lsp.InlayHint @@ -125,17 +133,8 @@ end --- }) --- ``` --- ---- @param filter vim.lsp.inlay_hint.get.filter? ---- Optional filters |kwargs|: ---- - bufnr (integer?): 0 for current buffer ---- - range (lsp.Range?) ---- +--- @param filter vim.lsp.inlay_hint.get.Filter? --- @return vim.lsp.inlay_hint.get.ret[] ---- Each list item is a table with the following fields: ---- - bufnr (integer) ---- - client_id (integer) ---- - inlay_hint (lsp.InlayHint) ---- --- @since 12 function M.get(filter) vim.validate({ filter = { filter, 'table', true } }) @@ -155,7 +154,7 @@ function M.get(filter) end local bufstate = bufstates[bufnr] - if not (bufstate and bufstate.client_hint) then + if not (bufstate and bufstate.client_hints) then return {} end @@ -178,7 +177,7 @@ function M.get(filter) --- @type vim.lsp.inlay_hint.get.ret[] local hints = {} for _, client in pairs(clients) do - local hints_by_lnum = bufstate.client_hint[client.id] + local hints_by_lnum = bufstate.client_hints[client.id] if hints_by_lnum then for lnum = range.start.line, range['end'].line do local line_hints = hints_by_lnum[lnum] or {} @@ -211,11 +210,11 @@ local function clear(bufnr) return end local bufstate = bufstates[bufnr] - local client_lens = (bufstate or {}).client_hint or {} - local client_ids = vim.tbl_keys(client_lens) + local client_lens = (bufstate or {}).client_hints or {} + local client_ids = vim.tbl_keys(client_lens) --- @type integer[] for _, iter_client_id in ipairs(client_ids) do if bufstate then - bufstate.client_hint[iter_client_id] = {} + bufstate.client_hints[iter_client_id] = {} end end api.nvim_buf_clear_namespace(bufnr, namespace, 0, -1) @@ -236,7 +235,7 @@ end --- Refresh inlay hints, only if we have attached clients that support it ---@param bufnr (integer) Buffer handle, or 0 for current ----@param opts? table Additional options to pass to util._refresh +---@param opts? vim.lsp.util._refresh.Opts Additional options to pass to util._refresh ---@private local function _refresh(bufnr, opts) opts = opts or {} @@ -312,7 +311,7 @@ api.nvim_set_decoration_provider(namespace, { if bufstate.version ~= util.buf_versions[bufnr] then return end - local hints_by_client = bufstate.client_hint + local hints_by_client = assert(bufstate.client_hints) for lnum = topline, botline do if bufstate.applied[lnum] ~= bufstate.version then @@ -321,14 +320,15 @@ api.nvim_set_decoration_provider(namespace, { local line_hints = hints_by_lnum[lnum] or {} for _, hint in pairs(line_hints) do local text = '' - if type(hint.label) == 'string' then - text = hint.label + local label = hint.label + if type(label) == 'string' then + text = label else - for _, part in ipairs(hint.label) do + for _, part in ipairs(label) do text = text .. part.value end end - local vt = {} + local vt = {} --- @type {[1]: string, [2]: string?}[] if hint.paddingLeft then vt[#vt + 1] = { ' ' } end @@ -360,7 +360,13 @@ function M.is_enabled(bufnr) return bufstates[bufnr] and bufstates[bufnr].enabled or false end ---- Enable/disable/toggle inlay hints for a buffer +--- Enables or disables inlay hints for a buffer. +--- +--- To "toggle", pass the inverse of `is_enabled()`: +--- +--- ```lua +--- vim.lsp.inlay_hint.enable(0, not vim.lsp.inlay_hint.is_enabled()) +--- ``` --- --- @param bufnr (integer|nil) Buffer handle, or 0 or nil for current --- @param enable (boolean|nil) true/nil to enable, false to disable diff --git a/runtime/lua/vim/lsp/log.lua b/runtime/lua/vim/lsp/log.lua index 6d2e0bc292..9f2bd71158 100644 --- a/runtime/lua/vim/lsp/log.lua +++ b/runtime/lua/vim/lsp/log.lua @@ -2,138 +2,144 @@ local log = {} +local log_levels = vim.log.levels + --- Log level dictionary with reverse lookup as well. --- --- Can be used to lookup the number from the name or the name from the number. --- Levels by name: "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "OFF" --- Level numbers begin with "TRACE" at 0 +--- @type table<string|integer, string|integer> --- @nodoc -log.levels = vim.deepcopy(vim.log.levels) +log.levels = vim.deepcopy(log_levels) -- Default log level is warn. -local current_log_level = log.levels.WARN +local current_log_level = log_levels.WARN + local log_date_format = '%F %H:%M:%S' -local format_func = function(arg) + +local function format_func(arg) return vim.inspect(arg, { newline = '' }) end -do - local function notify(msg, level) - if vim.in_fast_event() then - vim.schedule(function() - vim.notify(msg, level) - end) - else +local function notify(msg, level) + if vim.in_fast_event() then + vim.schedule(function() vim.notify(msg, level) - end + end) + else + vim.notify(msg, level) end +end + +local logfilename = vim.fs.joinpath(vim.fn.stdpath('log'), 'lsp.log') + +-- TODO: Ideally the directory should be created in open_logfile(), right +-- before opening the log file, but open_logfile() can be called from libuv +-- callbacks, where using fn.mkdir() is not allowed. +vim.fn.mkdir(vim.fn.stdpath('log'), 'p') + +--- Returns the log filename. +---@return string log filename +function log.get_filename() + return logfilename +end - local path_sep = vim.uv.os_uname().version:match('Windows') and '\\' or '/' - local function path_join(...) - return table.concat(vim.tbl_flatten({ ... }), path_sep) +--- @type file*?, string? +local logfile, openerr + +--- Opens log file. Returns true if file is open, false on error +local function open_logfile() + -- Try to open file only once + if logfile then + return true + end + if openerr then + return false end - local logfilename = path_join(vim.fn.stdpath('log'), 'lsp.log') - -- TODO: Ideally the directory should be created in open_logfile(), right - -- before opening the log file, but open_logfile() can be called from libuv - -- callbacks, where using fn.mkdir() is not allowed. - vim.fn.mkdir(vim.fn.stdpath('log'), 'p') + logfile, openerr = io.open(logfilename, 'a+') + if not logfile then + local err_msg = string.format('Failed to open LSP client log file: %s', openerr) + notify(err_msg, log_levels.ERROR) + return false + end - --- Returns the log filename. - ---@return string log filename - function log.get_filename() - return logfilename + local log_info = vim.uv.fs_stat(logfilename) + if log_info and log_info.size > 1e9 then + local warn_msg = string.format( + 'LSP client log is large (%d MB): %s', + log_info.size / (1000 * 1000), + logfilename + ) + notify(warn_msg) end - local logfile, openerr - --- Opens log file. Returns true if file is open, false on error - local function open_logfile() - -- Try to open file only once - if logfile then + -- Start message for logging + logfile:write(string.format('[START][%s] LSP logging initiated\n', os.date(log_date_format))) + return true +end + +for level, levelnr in pairs(log_levels) do + -- Also export the log level on the root object. + log[level] = levelnr + + -- Add a reverse lookup. + log.levels[levelnr] = level +end + +--- @param level string +--- @param levelnr integer +--- @return fun(...:any): boolean? +local function create_logger(level, levelnr) + return function(...) + if levelnr < current_log_level then + return false + end + local argc = select('#', ...) + if argc == 0 then return true end - if openerr then + if not open_logfile() then return false end - - logfile, openerr = io.open(logfilename, 'a+') - if not logfile then - local err_msg = string.format('Failed to open LSP client log file: %s', openerr) - notify(err_msg, vim.log.levels.ERROR) - return false + local info = debug.getinfo(2, 'Sl') + local header = string.format( + '[%s][%s] ...%s:%s', + level, + os.date(log_date_format), + info.short_src:sub(-16), + info.currentline + ) + local parts = { header } + for i = 1, argc do + local arg = select(i, ...) + table.insert(parts, arg == nil and 'nil' or format_func(arg)) end + assert(logfile) + logfile:write(table.concat(parts, '\t'), '\n') + logfile:flush() + end +end - local log_info = vim.uv.fs_stat(logfilename) - if log_info and log_info.size > 1e9 then - local warn_msg = string.format( - 'LSP client log is large (%d MB): %s', - log_info.size / (1000 * 1000), - logfilename - ) - notify(warn_msg) - end +-- If called without arguments, it will check whether the log level is +-- greater than or equal to this one. When called with arguments, it will +-- log at that level (if applicable, it is checked either way). - -- Start message for logging - logfile:write(string.format('[START][%s] LSP logging initiated\n', os.date(log_date_format))) - return true - end +--- @nodoc +log.debug = create_logger('DEBUG', log_levels.DEBUG) - for level, levelnr in pairs(log.levels) do - -- Also export the log level on the root object. - log[level] = levelnr - -- FIXME: DOC - -- Should be exposed in the vim docs. - -- - -- Set the lowercase name as the main use function. - -- If called without arguments, it will check whether the log level is - -- greater than or equal to this one. When called with arguments, it will - -- log at that level (if applicable, it is checked either way). - -- - -- Recommended usage: - -- ``` - -- local _ = log.warn() and log.warn("123") - -- ``` - -- - -- This way you can avoid string allocations if the log level isn't high enough. - if level ~= 'OFF' then - log[level:lower()] = function(...) - local argc = select('#', ...) - if levelnr < current_log_level then - return false - end - if argc == 0 then - return true - end - if not open_logfile() then - return false - end - local info = debug.getinfo(2, 'Sl') - local header = string.format( - '[%s][%s] ...%s:%s', - level, - os.date(log_date_format), - string.sub(info.short_src, #info.short_src - 15), - info.currentline - ) - local parts = { header } - for i = 1, argc do - local arg = select(i, ...) - if arg == nil then - table.insert(parts, 'nil') - else - table.insert(parts, format_func(arg)) - end - end - logfile:write(table.concat(parts, '\t'), '\n') - logfile:flush() - end - end - end -end +--- @nodoc +log.error = create_logger('ERROR', log_levels.ERROR) --- This is put here on purpose after the loop above so that it doesn't --- interfere with iterating the levels -vim.tbl_add_reverse_lookup(log.levels) +--- @nodoc +log.info = create_logger('INFO', log_levels.INFO) + +--- @nodoc +log.trace = create_logger('TRACE', log_levels.TRACE) + +--- @nodoc +log.warn = create_logger('WARN', log_levels.WARN) --- Sets the current log level. ---@param level (string|integer) One of `vim.lsp.log.levels` @@ -163,7 +169,7 @@ end --- Checks whether the level is sufficient for logging. ---@param level integer log level ----@returns (bool) true if would log, false if not +---@return bool : true if would log, false if not function log.should_log(level) return level >= current_log_level end diff --git a/runtime/lua/vim/lsp/protocol.lua b/runtime/lua/vim/lsp/protocol.lua index a7c3914834..599f02425e 100644 --- a/runtime/lua/vim/lsp/protocol.lua +++ b/runtime/lua/vim/lsp/protocol.lua @@ -1,24 +1,17 @@ --- Protocol for the Microsoft Language Server Protocol (mslsp) - -local protocol = {} +--- @diagnostic disable: duplicate-doc-alias ---[=[ ----@private ---- Useful for interfacing with: ---- https://github.com/microsoft/language-server-protocol/raw/gh-pages/_specifications/specification-3-14.md -function transform_schema_comments() - nvim.command [[silent! '<,'>g/\/\*\*\|\*\/\|^$/d]] - nvim.command [[silent! '<,'>s/^\(\s*\) \* \=\(.*\)/\1--\2/]] -end ----@private -function transform_schema_to_table() - transform_schema_comments() - nvim.command [[silent! '<,'>s/: \S\+//]] - nvim.command [[silent! '<,'>s/export const //]] - nvim.command [[silent! '<,'>s/export namespace \(\S*\)\s*{/protocol.\1 = {/]] - nvim.command [[silent! '<,'>s/namespace \(\S*\)\s*{/protocol.\1 = {/]] +---@param tbl table<string, string|number> +local function get_value_set(tbl) + local value_set = {} + for _, v in pairs(tbl) do + table.insert(value_set, v) + end + table.sort(value_set) + return value_set end ---]=] + +-- Protocol for the Microsoft Language Server Protocol (mslsp) +local protocol = {} local constants = { --- @enum lsp.DiagnosticSeverity @@ -313,10 +306,13 @@ local constants = { }, } -for k, v in pairs(constants) do - local tbl = vim.deepcopy(v) - vim.tbl_add_reverse_lookup(tbl) - protocol[k] = tbl +for k1, v1 in pairs(constants) do + local tbl = vim.deepcopy(v1, true) + for _, k2 in ipairs(vim.tbl_keys(tbl)) do + local v2 = tbl[k2] + tbl[v2] = k2 + end + protocol[k1] = tbl end --[=[ @@ -722,11 +718,7 @@ function protocol.make_client_capabilities() codeActionLiteralSupport = { codeActionKind = { - valueSet = (function() - local res = vim.tbl_values(constants.CodeActionKind) - table.sort(res) - return res - end)(), + valueSet = get_value_set(constants.CodeActionKind), }, }, isPreferredSupport = true, @@ -751,18 +743,18 @@ function protocol.make_client_capabilities() commitCharactersSupport = false, preselectSupport = false, deprecatedSupport = false, - documentationFormat = { protocol.MarkupKind.Markdown, protocol.MarkupKind.PlainText }, + documentationFormat = { constants.MarkupKind.Markdown, constants.MarkupKind.PlainText }, }, completionItemKind = { - valueSet = (function() - local res = {} - for k in ipairs(protocol.CompletionItemKind) do - if type(k) == 'number' then - table.insert(res, k) - end - end - return res - end)(), + valueSet = get_value_set(constants.CompletionItemKind), + }, + completionList = { + itemDefaults = { + 'editRange', + 'insertTextFormat', + 'insertTextMode', + 'data', + }, }, -- TODO(tjdevries): Implement this @@ -783,13 +775,13 @@ function protocol.make_client_capabilities() }, hover = { dynamicRegistration = true, - contentFormat = { protocol.MarkupKind.Markdown, protocol.MarkupKind.PlainText }, + contentFormat = { constants.MarkupKind.Markdown, constants.MarkupKind.PlainText }, }, signatureHelp = { dynamicRegistration = false, signatureInformation = { activeParameterSupport = true, - documentationFormat = { protocol.MarkupKind.Markdown, protocol.MarkupKind.PlainText }, + documentationFormat = { constants.MarkupKind.Markdown, constants.MarkupKind.PlainText }, parameterInformation = { labelOffsetSupport = true, }, @@ -804,15 +796,7 @@ function protocol.make_client_capabilities() documentSymbol = { dynamicRegistration = false, symbolKind = { - valueSet = (function() - local res = {} - for k in ipairs(protocol.SymbolKind) do - if type(k) == 'number' then - table.insert(res, k) - end - end - return res - end)(), + valueSet = get_value_set(constants.SymbolKind), }, hierarchicalDocumentSymbolSupport = true, }, @@ -823,15 +807,7 @@ function protocol.make_client_capabilities() publishDiagnostics = { relatedInformation = true, tagSupport = { - valueSet = (function() - local res = {} - for k in ipairs(protocol.DiagnosticTag) do - if type(k) == 'number' then - table.insert(res, k) - end - end - return res - end)(), + valueSet = get_value_set(constants.DiagnosticTag), }, dataSupport = true, }, @@ -843,15 +819,7 @@ function protocol.make_client_capabilities() symbol = { dynamicRegistration = false, symbolKind = { - valueSet = (function() - local res = {} - for k in ipairs(protocol.SymbolKind) do - if type(k) == 'number' then - table.insert(res, k) - end - end - return res - end)(), + valueSet = get_value_set(constants.SymbolKind), }, }, configuration = true, @@ -891,9 +859,9 @@ end --- Creates a normalized object describing LSP server capabilities. ---@param server_capabilities table Table of capabilities supported by the server ----@return table|nil Normalized table of capabilities +---@return lsp.ServerCapabilities|nil : Normalized table of capabilities function protocol.resolve_capabilities(server_capabilities) - local TextDocumentSyncKind = protocol.TextDocumentSyncKind + local TextDocumentSyncKind = protocol.TextDocumentSyncKind ---@type table<string|number, string|number> local textDocumentSync = server_capabilities.textDocumentSync if textDocumentSync == nil then -- Defaults if omitted. @@ -934,7 +902,7 @@ end -- Generated by gen_lsp.lua, keep at end of file. --- LSP method names. --- ----@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#metaModel +---@see https://microsoft.github.io/language-server-protocol/specification/#metaModel protocol.Methods = { --- A request to resolve the incoming calls for a given `CallHierarchyItem`. --- @since 3.16.0 @@ -1021,16 +989,14 @@ protocol.Methods = { --- `filterText`, `insertText`, and `textEdit`, must not be changed during resolve. textDocument_completion = 'textDocument/completion', --- A request to resolve the type definition locations of a symbol at a given text - --- document position. The request's parameter is of type [TextDocumentPositionParams] - --- (#TextDocumentPositionParams) the response is of type {@link Declaration} - --- or a typed array of {@link DeclarationLink} or a Thenable that resolves - --- to such. + --- document position. The request's parameter is of type {@link TextDocumentPositionParams} + --- the response is of type {@link Declaration} or a typed array of {@link DeclarationLink} + --- or a Thenable that resolves to such. textDocument_declaration = 'textDocument/declaration', --- A request to resolve the definition location of a symbol at a given text - --- document position. The request's parameter is of type [TextDocumentPosition] - --- (#TextDocumentPosition) the response is of either type {@link Definition} - --- or a typed array of {@link DefinitionLink} or a Thenable that resolves - --- to such. + --- document position. The request's parameter is of type {@link TextDocumentPosition} + --- the response is of either type {@link Definition} or a typed array of + --- {@link DefinitionLink} or a Thenable that resolves to such. textDocument_definition = 'textDocument/definition', --- The document diagnostic request definition. --- @since 3.17.0 @@ -1064,9 +1030,9 @@ protocol.Methods = { --- that resolves to such. textDocument_documentColor = 'textDocument/documentColor', --- Request to resolve a {@link DocumentHighlight} for a given - --- text document position. The request's parameter is of type [TextDocumentPosition] - --- (#TextDocumentPosition) the request response is of type [DocumentHighlight[]] - --- (#DocumentHighlight) or a Thenable that resolves to such. + --- text document position. The request's parameter is of type {@link TextDocumentPosition} + --- the request response is an array of type {@link DocumentHighlight} + --- or a Thenable that resolves to such. textDocument_documentHighlight = 'textDocument/documentHighlight', --- A request to provide document links textDocument_documentLink = 'textDocument/documentLink', @@ -1080,16 +1046,15 @@ protocol.Methods = { --- response is of type {@link FoldingRangeList} or a Thenable --- that resolves to such. textDocument_foldingRange = 'textDocument/foldingRange', - --- A request to to format a whole document. + --- A request to format a whole document. textDocument_formatting = 'textDocument/formatting', --- Request to request hover information at a given text document position. The request's --- parameter is of type {@link TextDocumentPosition} the response is of --- type {@link Hover} or a Thenable that resolves to such. textDocument_hover = 'textDocument/hover', --- A request to resolve the implementation locations of a symbol at a given text - --- document position. The request's parameter is of type [TextDocumentPositionParams] - --- (#TextDocumentPositionParams) the response is of type {@link Definition} or a - --- Thenable that resolves to such. + --- document position. The request's parameter is of type {@link TextDocumentPositionParams} + --- the response is of type {@link Definition} or a Thenable that resolves to such. textDocument_implementation = 'textDocument/implementation', --- A request to provide inlay hints in a document. The request's parameter is of --- type {@link InlayHintsParams}, the response is of type @@ -1100,6 +1065,7 @@ protocol.Methods = { --- type {@link InlineCompletionParams}, the response is of type --- {@link InlineCompletion InlineCompletion[]} or a Thenable that resolves to such. --- @since 3.18.0 + --- @proposed textDocument_inlineCompletion = 'textDocument/inlineCompletion', --- A request to provide inline values in a document. The request's parameter is of --- type {@link InlineValueParams}, the response is of type @@ -1155,9 +1121,8 @@ protocol.Methods = { textDocument_semanticTokens_range = 'textDocument/semanticTokens/range', textDocument_signatureHelp = 'textDocument/signatureHelp', --- A request to resolve the type definition locations of a symbol at a given text - --- document position. The request's parameter is of type [TextDocumentPositionParams] - --- (#TextDocumentPositionParams) the response is of type {@link Definition} or a - --- Thenable that resolves to such. + --- document position. The request's parameter is of type {@link TextDocumentPositionParams} + --- the response is of type {@link Definition} or a Thenable that resolves to such. textDocument_typeDefinition = 'textDocument/typeDefinition', --- A document will save notification is sent from the client to the server before --- the document is actually saved. @@ -1200,14 +1165,14 @@ protocol.Methods = { --- symbol's location. --- @since 3.17.0 workspaceSymbol_resolve = 'workspaceSymbol/resolve', - --- A request sent from the server to the client to modified certain resources. + --- A request sent from the server to the client to modify certain resources. workspace_applyEdit = 'workspace/applyEdit', --- A request to refresh all code actions --- @since 3.16.0 workspace_codeLens_refresh = 'workspace/codeLens/refresh', --- The 'workspace/configuration' request is sent from the server to the client to fetch a certain --- configuration setting. - --- This pull model replaces the old push model were the client signaled configuration change via an + --- This pull model replaces the old push model where the client signaled configuration change via an --- event. If the server still needs to react to configuration changes (since the server caches the --- result of `workspace/configuration` requests) the server should register for an empty configuration --- change event and empty the cache if such an event is received. @@ -1240,9 +1205,12 @@ protocol.Methods = { --- files were renamed from within the client. --- @since 3.16.0 workspace_didRenameFiles = 'workspace/didRenameFiles', - --- A request send from the client to the server to execute a command. The request might return + --- A request sent from the client to the server to execute a command. The request might return --- a workspace edit which the client will apply to the workspace. workspace_executeCommand = 'workspace/executeCommand', + --- @since 3.18.0 + --- @proposed + workspace_foldingRange_refresh = 'workspace/foldingRange/refresh', --- @since 3.17.0 workspace_inlayHint_refresh = 'workspace/inlayHint/refresh', --- @since 3.17.0 diff --git a/runtime/lua/vim/lsp/rpc.lua b/runtime/lua/vim/lsp/rpc.lua index 6ab5708721..984e4f040a 100644 --- a/runtime/lua/vim/lsp/rpc.lua +++ b/runtime/lua/vim/lsp/rpc.lua @@ -6,7 +6,7 @@ local validate, schedule, schedule_wrap = vim.validate, vim.schedule, vim.schedu local is_win = uv.os_uname().version:find('Windows') --- Checks whether a given path exists and is a directory. ----@param filename (string) path to check +---@param filename string path to check ---@return boolean local function is_dir(filename) local stat = uv.fs_stat(filename) @@ -15,34 +15,39 @@ end --- Embeds the given string into a table and correctly computes `Content-Length`. --- ----@param encoded_message (string) ----@return string containing encoded message and `Content-Length` attribute -local function format_message_with_content_length(encoded_message) +---@param message string +---@return string message with `Content-Length` attribute +local function format_message_with_content_length(message) return table.concat({ 'Content-Length: ', - tostring(#encoded_message), + tostring(#message), '\r\n\r\n', - encoded_message, + message, }) end +---@class (private) vim.lsp.rpc.Headers: {string: any} +---@field content_length integer + --- Parses an LSP Message's header --- ----@param header string: The header to parse. ----@return table # parsed headers +---@param header string The header to parse. +---@return vim.lsp.rpc.Headers#parsed headers local function parse_headers(header) assert(type(header) == 'string', 'header must be a string') + --- @type vim.lsp.rpc.Headers local headers = {} for line in vim.gsplit(header, '\r\n', { plain = true }) do if line == '' then break end + --- @type string?, string? local key, value = line:match('^%s*(%S+)%s*:%s*(.+)%s*$') if key then - key = key:lower():gsub('%-', '_') + key = key:lower():gsub('%-', '_') --- @type string headers[key] = value else - local _ = log.error() and log.error('invalid header line %q', line) + log.error('invalid header line %q', line) error(string.format('invalid header line %q', line)) end end @@ -73,15 +78,25 @@ local function request_parser_loop() -- be searching for. -- TODO(ashkan) I'd like to remove this, but it seems permanent :( local buffer_start = buffer:find(header_start_pattern) + if not buffer_start then + error( + string.format( + "Headers were expected, a different response was received. The server response was '%s'.", + buffer + ) + ) + end local headers = parse_headers(buffer:sub(buffer_start, start - 1)) local content_length = headers.content_length -- Use table instead of just string to buffer the message. It prevents -- a ton of strings allocating. -- ref. http://www.lua.org/pil/11.6.html + ---@type string[] local body_chunks = { buffer:sub(finish + 1) } local body_length = #body_chunks[1] -- Keep waiting for data until we have enough. while body_length < content_length do + ---@type string local chunk = coroutine.yield() or error('Expected more data for the body. The server may have died.') -- TODO hmm. table.insert(body_chunks, chunk) @@ -96,17 +111,17 @@ local function request_parser_loop() end local body = table.concat(body_chunks) -- Yield our data. - buffer = rest - .. ( - coroutine.yield(headers, body) - or error('Expected more data for the body. The server may have died.') - ) -- TODO hmm. + + --- @type string + local data = coroutine.yield(headers, body) + or error('Expected more data for the body. The server may have died.') + buffer = rest .. data else -- Get more data since we don't have enough. - buffer = buffer - .. ( - coroutine.yield() or error('Expected more data for the header. The server may have died.') - ) -- TODO hmm. + --- @type string + local data = coroutine.yield() + or error('Expected more data for the header. The server may have died.') + buffer = buffer .. data end end end @@ -115,7 +130,7 @@ local M = {} --- Mapping of error codes used by the client --- @nodoc -M.client_errors = { +local client_errors = { INVALID_SERVER_MESSAGE = 1, INVALID_SERVER_JSON = 2, NO_RESULT_CALLBACK_FOUND = 3, @@ -125,12 +140,17 @@ M.client_errors = { SERVER_RESULT_CALLBACK_ERROR = 7, } -M.client_errors = vim.tbl_add_reverse_lookup(M.client_errors) +--- @type table<string|integer, string|integer> +--- @nodoc +M.client_errors = vim.deepcopy(client_errors) +for k, v in pairs(client_errors) do + M.client_errors[v] = k +end --- Constructs an error message from an LSP error object. --- ----@param err (table) The error object ----@returns (string) The formatted error message +---@param err table The error object +---@return string error_message The formatted error message function M.format_rpc_error(err) validate({ err = { err, 't' }, @@ -138,7 +158,7 @@ function M.format_rpc_error(err) -- There is ErrorCodes in the LSP specification, -- but in ResponseError.code it is not used and the actual type is number. - local code + local code --- @type string if protocol.ErrorCodes[err.code] then code = string.format('code_name = %s,', protocol.ErrorCodes[err.code]) else @@ -157,13 +177,17 @@ function M.format_rpc_error(err) return table.concat(message_parts, ' ') end ---- Creates an RPC response object/table. +--- Creates an RPC response table `error` to be sent to the LSP response. +--- +---@param code integer RPC error code defined, see `vim.lsp.protocol.ErrorCodes` +---@param message? string arbitrary message to send to server +---@param data? any arbitrary data to send to server --- ----@param code integer RPC error code defined in `vim.lsp.protocol.ErrorCodes` ----@param message string|nil arbitrary message to send to server ----@param data any|nil arbitrary data to send to server +---@see lsp.ErrorCodes See `vim.lsp.protocol.ErrorCodes` +---@return lsp.ResponseError function M.rpc_response_error(code, message, data) -- TODO should this error or just pick a sane error (like InternalError)? + ---@type string local code_name = assert(protocol.ErrorCodes[code], 'Invalid RPC error code') return setmetatable({ code = code, @@ -174,52 +198,55 @@ function M.rpc_response_error(code, message, data) }) end -local default_dispatchers = {} - ----@private ---- Default dispatcher for notifications sent to an LSP server. ---- ----@param method (string) The invoked LSP method ----@param params (table): Parameters for the invoked LSP method -function default_dispatchers.notification(method, params) - local _ = log.debug() and log.debug('notification', method, params) -end - ----@private ---- Default dispatcher for requests sent to an LSP server. ---- ----@param method (string) The invoked LSP method ----@param params (table): Parameters for the invoked LSP method ----@return nil ----@return table `vim.lsp.protocol.ErrorCodes.MethodNotFound` -function default_dispatchers.server_request(method, params) - local _ = log.debug() and log.debug('server_request', method, params) - return nil, M.rpc_response_error(protocol.ErrorCodes.MethodNotFound) -end +--- Dispatchers for LSP message types. +--- @class vim.lsp.rpc.Dispatchers +--- @inlinedoc +--- @field notification fun(method: string, params: table) +--- @field server_request fun(method: string, params: table): any?, lsp.ResponseError? +--- @field on_exit fun(code: integer, signal: integer) +--- @field on_error fun(code: integer, err: any) + +--- @type vim.lsp.rpc.Dispatchers +local default_dispatchers = { + --- Default dispatcher for notifications sent to an LSP server. + --- + ---@param method string The invoked LSP method + ---@param params table Parameters for the invoked LSP method + notification = function(method, params) + log.debug('notification', method, params) + end, ----@private ---- Default dispatcher for when a client exits. ---- ----@param code (integer): Exit code ----@param signal (integer): Number describing the signal used to terminate (if ----any) -function default_dispatchers.on_exit(code, signal) - local _ = log.info() and log.info('client_exit', { code = code, signal = signal }) -end + --- Default dispatcher for requests sent to an LSP server. + --- + ---@param method string The invoked LSP method + ---@param params table Parameters for the invoked LSP method + ---@return any result (always nil for the default dispatchers) + ---@return lsp.ResponseError error `vim.lsp.protocol.ErrorCodes.MethodNotFound` + server_request = function(method, params) + log.debug('server_request', method, params) + return nil, M.rpc_response_error(protocol.ErrorCodes.MethodNotFound) + end, + + --- Default dispatcher for when a client exits. + --- + ---@param code integer Exit code + ---@param signal integer Number describing the signal used to terminate (if any) + on_exit = function(code, signal) + log.info('client_exit', { code = code, signal = signal }) + end, ----@private ---- Default dispatcher for client errors. ---- ----@param code (integer): Error code ----@param err (any): Details about the error ----any) -function default_dispatchers.on_error(code, err) - local _ = log.error() and log.error('client_error:', M.client_errors[code], err) -end + --- Default dispatcher for client errors. + --- + ---@param code integer Error code + ---@param err any Details about the error + on_error = function(code, err) + log.error('client_error:', M.client_errors[code], err) + end, +} ---@private function M.create_read_loop(handle_body, on_no_chunk, on_error) - local parse_chunk = coroutine.wrap(request_parser_loop) + local parse_chunk = coroutine.wrap(request_parser_loop) --[[@as fun(chunk: string?): vim.lsp.rpc.Headers?, string?]] parse_chunk() return function(err, chunk) if err then @@ -246,31 +273,32 @@ function M.create_read_loop(handle_body, on_no_chunk, on_error) end end ----@class RpcClient +---@class (private) vim.lsp.rpc.Client ---@field message_index integer ----@field message_callbacks table ----@field notify_reply_callbacks table ----@field transport table ----@field dispatchers table - ----@class RpcClient +---@field message_callbacks table<integer, function> dict of message_id to callback +---@field notify_reply_callbacks table<integer, function> dict of message_id to callback +---@field transport vim.lsp.rpc.Transport +---@field dispatchers vim.lsp.rpc.Dispatchers local Client = {} ---@private function Client:encode_and_send(payload) - local _ = log.debug() and log.debug('rpc.send', payload) + log.debug('rpc.send', payload) if self.transport.is_closing() then return false end - local encoded = vim.json.encode(payload) - self.transport.write(format_message_with_content_length(encoded)) + local jsonstr = assert( + vim.json.encode(payload), + string.format("Couldn't encode payload '%s'", vim.inspect(payload)) + ) + self.transport.write(format_message_with_content_length(jsonstr)) return true end ----@private +---@package --- Sends a notification to the LSP server. ----@param method (string) The invoked LSP method ----@param params (any): Parameters for the invoked LSP method +---@param method string The invoked LSP method +---@param params any Parameters for the invoked LSP method ---@return boolean `true` if notification could be sent, `false` if not function Client:notify(method, params) return self:encode_and_send({ @@ -291,14 +319,15 @@ function Client:send_response(request_id, err, result) }) end ----@private ---- Sends a request to the LSP server and runs {callback} upon response. +---@package +--- Sends a request to the LSP server and runs {callback} upon response. |vim.lsp.rpc.request()| --- ----@param method (string) The invoked LSP method ----@param params (table|nil) Parameters for the invoked LSP method ----@param callback fun(err: lsp.ResponseError|nil, result: any) Callback to invoke ----@param notify_reply_callback (function|nil) Callback to invoke as soon as a request is no longer pending ----@return boolean success, integer|nil request_id true, request_id if request could be sent, `false` if not +---@param method string The invoked LSP method +---@param params table? Parameters for the invoked LSP method +---@param callback fun(err?: lsp.ResponseError, result: any) Callback to invoke +---@param notify_reply_callback fun(message_id: integer)|nil Callback to invoke as soon as a request is no longer pending +---@return boolean success `true` if request could be sent, `false` if not +---@return integer? message_id if request could be sent, `nil` if not function Client:request(method, params, callback, notify_reply_callback) validate({ callback = { callback, 'f' }, @@ -318,18 +347,20 @@ function Client:request(method, params, callback, notify_reply_callback) if message_callbacks then message_callbacks[message_id] = schedule_wrap(callback) else - return false + return false, nil end if notify_reply_callback and notify_reply_callbacks then notify_reply_callbacks[message_id] = schedule_wrap(notify_reply_callback) end return result, message_id else - return false + return false, nil end end ----@private +---@package +---@param errkind integer +---@param ... any function Client:on_error(errkind, ...) assert(M.client_errors[errkind]) -- TODO what to do if this fails? @@ -337,6 +368,13 @@ function Client:on_error(errkind, ...) end ---@private +---@param errkind integer +---@param status boolean +---@param head any +---@param ... any +---@return boolean status +---@return any head +---@return any|nil ... function Client:pcall_handler(errkind, status, head, ...) if not status then self:on_error(errkind, head, ...) @@ -346,6 +384,12 @@ function Client:pcall_handler(errkind, status, head, ...) end ---@private +---@param errkind integer +---@param fn function +---@param ... any +---@return boolean status +---@return any head +---@return any|nil ... function Client:try_call(errkind, fn, ...) return self:pcall_handler(errkind, pcall(fn, ...)) end @@ -354,17 +398,17 @@ end -- time and log them. This would require storing the timestamp. I could call -- them with an error then, perhaps. ----@private +---@package function Client:handle_body(body) local ok, decoded = pcall(vim.json.decode, body, { luanil = { object = true } }) if not ok then self:on_error(M.client_errors.INVALID_SERVER_JSON, decoded) return end - local _ = log.debug() and log.debug('rpc.receive', decoded) + log.debug('rpc.receive', decoded) if type(decoded.method) == 'string' and decoded.id then - local err + local err --- @type lsp.ResponseError|nil -- Schedule here so that the users functions don't trigger an error and -- we can still use the result. schedule(function() @@ -376,11 +420,10 @@ function Client:handle_body(body) decoded.method, decoded.params ) - local _ = log.debug() - and log.debug( - 'server_request: callback result', - { status = status, result = result, err = err } - ) + log.debug( + 'server_request: callback result', + { status = status, result = result, err = err } + ) if status then if result == nil and err == nil then error( @@ -391,10 +434,12 @@ function Client:handle_body(body) ) end if err then + ---@cast err lsp.ResponseError assert( type(err) == 'table', 'err must be a table. Use rpc_response_error to help format errors.' ) + ---@type string local code_name = assert( protocol.ErrorCodes[err.code], 'Errors must use protocol.ErrorCodes. Use rpc_response_error to help format errors.' @@ -431,7 +476,7 @@ function Client:handle_body(body) if decoded.error then local mute_error = false if decoded.error.code == protocol.ErrorCodes.RequestCancelled then - local _ = log.debug() and log.debug('Received cancellation ack', decoded) + log.debug('Received cancellation ack', decoded) mute_error = true end @@ -457,7 +502,7 @@ function Client:handle_body(body) if decoded.error then decoded.error = setmetatable(decoded.error, { __tostring = M.format_rpc_error, - }) + }) --- @type table end self:try_call( M.client_errors.SERVER_RESULT_CALLBACK_ERROR, @@ -467,7 +512,7 @@ function Client:handle_body(body) ) else self:on_error(M.client_errors.NO_RESULT_CALLBACK_FOUND, decoded) - local _ = log.error() and log.error('No callback found for server response id ' .. result_id) + log.error('No callback found for server response id ' .. result_id) end elseif type(decoded.method) == 'string' then -- Notification @@ -483,7 +528,14 @@ function Client:handle_body(body) end end ----@return RpcClient +---@class (private) vim.lsp.rpc.Transport +---@field write fun(msg: string) +---@field is_closing fun(): boolean +---@field terminate fun() + +---@param dispatchers vim.lsp.rpc.Dispatchers +---@param transport vim.lsp.rpc.Transport +---@return vim.lsp.rpc.Client local function new_client(dispatchers, transport) local state = { message_index = 0, @@ -495,8 +547,17 @@ local function new_client(dispatchers, transport) return setmetatable(state, { __index = Client }) end ----@param client RpcClient +---@class vim.lsp.rpc.PublicClient +---@field request fun(method: string, params: table?, callback: fun(err: lsp.ResponseError|nil, result: any), notify_reply_callback: fun(integer)|nil):boolean,integer? see |vim.lsp.rpc.request()| +---@field notify fun(method: string, params: any):boolean see |vim.lsp.rpc.notify()| +---@field is_closing fun(): boolean +---@field terminate fun() + +---@param client vim.lsp.rpc.Client +---@return vim.lsp.rpc.PublicClient local function public_client(client) + ---@type vim.lsp.rpc.PublicClient + ---@diagnostic disable-next-line: missing-fields local result = {} ---@private @@ -512,17 +573,18 @@ local function public_client(client) --- Sends a request to the LSP server and runs {callback} upon response. --- ---@param method (string) The invoked LSP method - ---@param params (table|nil) Parameters for the invoked LSP method - ---@param callback fun(err: lsp.ResponseError | nil, result: any) Callback to invoke - ---@param notify_reply_callback (function|nil) Callback to invoke as soon as a request is no longer pending - ---@return boolean success, integer|nil request_id true, message_id if request could be sent, `false` if not + ---@param params (table?) Parameters for the invoked LSP method + ---@param callback fun(err: lsp.ResponseError|nil, result: any) Callback to invoke + ---@param notify_reply_callback fun(message_id: integer)|nil Callback to invoke as soon as a request is no longer pending + ---@return boolean success `true` if request could be sent, `false` if not + ---@return integer? message_id if request could be sent, `nil` if not function result.request(method, params, callback, notify_reply_callback) return client:request(method, params, callback, notify_reply_callback) end --- Sends a notification to the LSP server. ---@param method (string) The invoked LSP method - ---@param params (table|nil): Parameters for the invoked LSP method + ---@param params (table?) Parameters for the invoked LSP method ---@return boolean `true` if notification could be sent, `false` if not function result.notify(method, params) return client:notify(method, params) @@ -531,43 +593,46 @@ local function public_client(client) return result end +---@param dispatchers vim.lsp.rpc.Dispatchers? +---@return vim.lsp.rpc.Dispatchers local function merge_dispatchers(dispatchers) - if dispatchers then - local user_dispatchers = dispatchers - dispatchers = {} - for dispatch_name, default_dispatch in pairs(default_dispatchers) do - local user_dispatcher = user_dispatchers[dispatch_name] - if user_dispatcher then - if type(user_dispatcher) ~= 'function' then - error(string.format('dispatcher.%s must be a function', dispatch_name)) - end - -- server_request is wrapped elsewhere. - if - not (dispatch_name == 'server_request' or dispatch_name == 'on_exit') -- TODO this blocks the loop exiting for some reason. - then - user_dispatcher = schedule_wrap(user_dispatcher) - end - dispatchers[dispatch_name] = user_dispatcher - else - dispatchers[dispatch_name] = default_dispatch - end + if not dispatchers then + return default_dispatchers + end + ---@diagnostic disable-next-line: no-unknown + for name, fn in pairs(dispatchers) do + if type(fn) ~= 'function' then + error(string.format('dispatcher.%s must be a function', name)) end - else - dispatchers = default_dispatchers end - return dispatchers + ---@type vim.lsp.rpc.Dispatchers + local merged = { + notification = ( + dispatchers.notification and vim.schedule_wrap(dispatchers.notification) + or default_dispatchers.notification + ), + on_error = ( + dispatchers.on_error and vim.schedule_wrap(dispatchers.on_error) + or default_dispatchers.on_error + ), + on_exit = dispatchers.on_exit or default_dispatchers.on_exit, + server_request = dispatchers.server_request or default_dispatchers.server_request, + } + return merged end ---- Create a LSP RPC client factory that connects via TCP to the given host ---- and port +--- Create a LSP RPC client factory that connects via TCP to the given host and port. +--- +--- Return a function that can be passed to the `cmd` field for +--- |vim.lsp.start_client()| or |vim.lsp.start()|. --- ----@param host string ----@param port integer ----@return function +---@param host string host to connect to +---@param port integer port to connect to +---@return fun(dispatchers: vim.lsp.rpc.Dispatchers): vim.lsp.rpc.PublicClient function M.connect(host, port) return function(dispatchers) dispatchers = merge_dispatchers(dispatchers) - local tcp = uv.new_tcp() + local tcp = assert(uv.new_tcp()) local closing = false local transport = { write = function(msg) @@ -608,35 +673,84 @@ function M.connect(host, port) end end +--- Create a LSP RPC client factory that connects via named pipes (Windows) +--- or unix domain sockets (Unix) to the given pipe_path (file path on +--- Unix and name on Windows). +--- +--- Return a function that can be passed to the `cmd` field for +--- |vim.lsp.start_client()| or |vim.lsp.start()|. +--- +---@param pipe_path string file path of the domain socket (Unix) or name of the named pipe (Windows) to connect to +---@return fun(dispatchers: vim.lsp.rpc.Dispatchers): vim.lsp.rpc.PublicClient +function M.domain_socket_connect(pipe_path) + return function(dispatchers) + dispatchers = merge_dispatchers(dispatchers) + local pipe = + assert(uv.new_pipe(false), string.format('pipe with name %s could not be opened.', pipe_path)) + local closing = false + local transport = { + write = vim.schedule_wrap(function(msg) + pipe:write(msg) + end), + is_closing = function() + return closing + end, + terminate = function() + if not closing then + closing = true + pipe:shutdown() + pipe:close() + dispatchers.on_exit(0, 0) + end + end, + } + local client = new_client(dispatchers, transport) + pipe:connect(pipe_path, function(err) + if err then + vim.schedule(function() + vim.notify( + string.format('Could not connect to :%s, reason: %s', pipe_path, vim.inspect(err)), + vim.log.levels.WARN + ) + end) + return + end + local handle_body = function(body) + client:handle_body(body) + end + pipe:read_start(M.create_read_loop(handle_body, transport.terminate, function(read_err) + client:on_error(M.client_errors.READ_ERROR, read_err) + end)) + end) + + return public_client(client) + end +end + +--- Additional context for the LSP server process. +--- @class vim.lsp.rpc.ExtraSpawnParams +--- @inlinedoc +--- @field cwd? string Working directory for the LSP server process +--- @field detached? boolean Detach the LSP server process from the current process +--- @field env? table<string,string> Additional environment variables for LSP server process. See |vim.system()| + --- Starts an LSP server process and create an LSP RPC client object to --- interact with it. Communication with the spawned process happens via stdio. For --- communication via TCP, spawn a process manually and use |vim.lsp.rpc.connect()| --- ----@param cmd (string) Command to start the LSP server. ----@param cmd_args (table) List of additional string arguments to pass to {cmd}. ----@param dispatchers table|nil Dispatchers for LSP message types. Valid ----dispatcher names are: ---- - `"notification"` ---- - `"server_request"` ---- - `"on_error"` ---- - `"on_exit"` ----@param extra_spawn_params table|nil Additional context for the LSP ---- server process. May contain: ---- - {cwd} (string) Working directory for the LSP server process ---- - {env} (table) Additional environment variables for LSP server process ----@return table|nil Client RPC object, with these methods: ---- - `notify()` |vim.lsp.rpc.notify()| ---- - `request()` |vim.lsp.rpc.request()| ---- - `is_closing()` returns a boolean indicating if the RPC is closing. ---- - `terminate()` terminates the RPC client. -function M.start(cmd, cmd_args, dispatchers, extra_spawn_params) - if log.info() then - log.info('Starting RPC client', { cmd = cmd, args = cmd_args, extra = extra_spawn_params }) - end +--- @param cmd string[] Command to start the LSP server. +--- @param dispatchers? vim.lsp.rpc.Dispatchers +--- @param extra_spawn_params? vim.lsp.rpc.ExtraSpawnParams +--- @return vim.lsp.rpc.PublicClient? : Client RPC object, with these methods: +--- - `notify()` |vim.lsp.rpc.notify()| +--- - `request()` |vim.lsp.rpc.request()| +--- - `is_closing()` returns a boolean indicating if the RPC is closing. +--- - `terminate()` terminates the RPC client. +function M.start(cmd, dispatchers, extra_spawn_params) + log.info('Starting RPC client', { cmd = cmd, extra = extra_spawn_params }) validate({ - cmd = { cmd, 's' }, - cmd_args = { cmd_args, 't' }, + cmd = { cmd, 't' }, dispatchers = { dispatchers, 't', true }, }) @@ -671,8 +785,8 @@ function M.start(cmd, cmd_args, dispatchers, extra_spawn_params) end) local stderr_handler = function(_, chunk) - if chunk and log.error() then - log.error('rpc', cmd, 'stderr', chunk) + if chunk then + log.error('rpc', cmd[1], 'stderr', chunk) end end @@ -681,10 +795,7 @@ function M.start(cmd, cmd_args, dispatchers, extra_spawn_params) detached = extra_spawn_params.detached end - local cmd1 = { cmd } - vim.list_extend(cmd1, cmd_args) - - local ok, sysobj_or_err = pcall(vim.system, cmd1, { + local ok, sysobj_or_err = pcall(vim.system, cmd, { stdin = true, stdout = stdout_handler, stderr = stderr_handler, @@ -697,15 +808,16 @@ function M.start(cmd, cmd_args, dispatchers, extra_spawn_params) if not ok then local err = sysobj_or_err --[[@as string]] - local msg = string.format('Spawning language server with cmd: `%s` failed', cmd) + local sfx --- @type string if string.match(err, 'ENOENT') then - msg = msg - .. '. The language server is either not installed, missing from PATH, or not executable.' + sfx = '. The language server is either not installed, missing from PATH, or not executable.' else - msg = msg .. string.format(' with error message: %s', err) + sfx = string.format(' with error message: %s', err) end + local msg = + string.format('Spawning language server with cmd: `%s` failed%s', vim.inspect(cmd), sfx) vim.notify(msg, vim.log.levels.WARN) - return + return nil end sysobj = sysobj_or_err --[[@as vim.SystemObj]] diff --git a/runtime/lua/vim/lsp/semantic_tokens.lua b/runtime/lua/vim/lsp/semantic_tokens.lua index a5831c0beb..20ac0a125f 100644 --- a/runtime/lua/vim/lsp/semantic_tokens.lua +++ b/runtime/lua/vim/lsp/semantic_tokens.lua @@ -1,35 +1,34 @@ local api = vim.api local bit = require('bit') -local handlers = require('vim.lsp.handlers') local ms = require('vim.lsp.protocol').Methods local util = require('vim.lsp.util') local uv = vim.uv ---- @class STTokenRange +--- @class (private) STTokenRange --- @field line integer line number 0-based --- @field start_col integer start column 0-based --- @field end_col integer end column 0-based --- @field type string token type as string ---- @field modifiers table token modifiers as a set. E.g., { static = true, readonly = true } +--- @field modifiers table<string,boolean> token modifiers as a set. E.g., { static = true, readonly = true } --- @field marked boolean whether this token has had extmarks applied --- ---- @class STCurrentResult +--- @class (private) STCurrentResult --- @field version? integer document version associated with this result --- @field result_id? string resultId from the server; used with delta requests --- @field highlights? STTokenRange[] cache of highlight ranges for this document version --- @field tokens? integer[] raw token array as received by the server. used for calculating delta responses --- @field namespace_cleared? boolean whether the namespace was cleared for this result yet --- ---- @class STActiveRequest ---- @field request_id integer the LSP request ID of the most recent request sent to the server ---- @field version integer the document version associated with the most recent request +--- @class (private) STActiveRequest +--- @field request_id? integer the LSP request ID of the most recent request sent to the server +--- @field version? integer the document version associated with the most recent request --- ---- @class STClientState +--- @class (private) STClientState --- @field namespace integer --- @field active_request STActiveRequest --- @field current_result STCurrentResult ----@class STHighlighter +---@class (private) STHighlighter ---@field active table<integer, STHighlighter> ---@field bufnr integer ---@field augroup integer augroup for buffer events @@ -72,9 +71,11 @@ end --- Extracts modifier strings from the encoded number in the token array --- +---@param x integer +---@param modifiers_table table<integer,string> ---@return table<string, boolean> local function modifiers_from_number(x, modifiers_table) - local modifiers = {} + local modifiers = {} ---@type table<string,boolean> local idx = 1 while x > 0 do if bit.band(x, 1) == 1 then @@ -89,20 +90,24 @@ end --- Converts a raw token list to a list of highlight ranges used by the on_win callback --- +---@param data integer[] +---@param bufnr integer +---@param client vim.lsp.Client +---@param request STActiveRequest ---@return STTokenRange[] local function tokens_to_ranges(data, bufnr, client, request) local legend = client.server_capabilities.semanticTokensProvider.legend local token_types = legend.tokenTypes local token_modifiers = legend.tokenModifiers local lines = api.nvim_buf_get_lines(bufnr, 0, -1, false) - local ranges = {} + local ranges = {} ---@type STTokenRange[] local start = uv.hrtime() local ms_to_ns = 1000 * 1000 local yield_interval_ns = 5 * ms_to_ns local co, is_main = coroutine.running() - local line + local line ---@type integer? local start_char = 0 for i = 1, #data, 5 do -- if this function is called from the main coroutine, let it run to completion with no yield @@ -167,6 +172,7 @@ end --- ---@private ---@param bufnr integer +---@return STHighlighter function STHighlighter.new(bufnr) local self = setmetatable({}, { __index = STHighlighter }) @@ -221,7 +227,7 @@ function STHighlighter.new(bufnr) return self end ----@private +---@package function STHighlighter:destroy() for client_id, _ in pairs(self.client_state) do self:detach(client_id) @@ -231,7 +237,7 @@ function STHighlighter:destroy() STHighlighter.active[self.bufnr] = nil end ----@private +---@package function STHighlighter:attach(client_id) local state = self.client_state[client_id] if not state then @@ -244,7 +250,7 @@ function STHighlighter:attach(client_id) end end ----@private +---@package function STHighlighter:detach(client_id) local state = self.client_state[client_id] if state then @@ -267,7 +273,7 @@ end --- Finally, if the request was successful, the requestId and document version --- are saved to facilitate document synchronization in the response. --- ----@private +---@package function STHighlighter:send_request() local version = util.buf_versions[self.bufnr] @@ -303,7 +309,8 @@ function STHighlighter:send_request() -- look client up again using ctx.client_id instead of using a captured -- client object local c = vim.lsp.get_client_by_id(ctx.client_id) - local highlighter = STHighlighter.active[ctx.bufnr] + local bufnr = assert(ctx.bufnr) + local highlighter = STHighlighter.active[bufnr] if not err and c and highlighter then coroutine.wrap(STHighlighter.process_response)(highlighter, response, c, version) end @@ -328,6 +335,7 @@ end --- Finally, a redraw command is issued to force nvim to redraw the screen to --- pick up changed highlight tokens. --- +---@param response lsp.SemanticTokens|lsp.SemanticTokensDelta ---@private function STHighlighter:process_response(response, client, version) local state = self.client_state[client.id] @@ -348,15 +356,15 @@ function STHighlighter:process_response(response, client, version) -- if we have a response to a delta request, update the state of our tokens -- appropriately. if it's a full response, just use that - local tokens + local tokens ---@type integer[] local token_edits = response.edits if token_edits then table.sort(token_edits, function(a, b) return a.start < b.start end) - tokens = {} - local old_tokens = state.current_result.tokens + tokens = {} --- @type integer[] + local old_tokens = assert(state.current_result.tokens) local idx = 1 for _, token_edit in ipairs(token_edits) do vim.list_extend(tokens, old_tokens, idx, token_edit.start) @@ -404,7 +412,9 @@ end --- handler to avoid the "blink" that occurs due to the timing between the --- response handler and the actual redraw. --- ----@private +---@package +---@param topline integer +---@param botline integer function STHighlighter:on_win(topline, botline) for client_id, state in pairs(self.client_state) do local current_result = state.current_result @@ -450,7 +460,7 @@ function STHighlighter:on_win(topline, botline) end local ft = vim.bo[self.bufnr].filetype - local highlights = current_result.highlights + local highlights = assert(current_result.highlights) local first = lower_bound(highlights, topline, 1, #highlights + 1) local last = upper_bound(highlights, botline, first, #highlights + 1) - 1 @@ -480,7 +490,7 @@ end --- Reset the buffer's highlighting state and clears the extmark highlights. --- ----@private +---@package function STHighlighter:reset() for client_id, state in pairs(self.client_state) do api.nvim_buf_clear_namespace(self.bufnr, state.namespace, 0, -1) @@ -499,7 +509,7 @@ end --- in the on_win callback. The rest of the current results are saved --- in case the server supports delta requests. --- ----@private +---@package ---@param client_id integer function STHighlighter:mark_dirty(client_id) local state = self.client_state[client_id] @@ -521,7 +531,7 @@ function STHighlighter:mark_dirty(client_id) end end ----@private +---@package function STHighlighter:on_change() self:reset_timer() if self.debounce > 0 then @@ -562,7 +572,7 @@ local M = {} --- ---@param bufnr integer ---@param client_id integer ----@param opts (nil|table) Optional keyword arguments +---@param opts? table Optional keyword arguments --- - debounce (integer, default: 200): Debounce token requests --- to the server by the given number in milliseconds function M.start(bufnr, client_id, opts) @@ -636,6 +646,10 @@ function M.stop(bufnr, client_id) end end +--- @nodoc +--- @class STTokenRangeInspect : STTokenRange +--- @field client_id integer + --- Return the semantic token(s) at the given position. --- If called without arguments, returns the token under the cursor. --- @@ -643,13 +657,14 @@ end ---@param row integer|nil Position row (default cursor position) ---@param col integer|nil Position column (default cursor position) --- ----@return table|nil (table|nil) List of tokens at position. Each token has +---@return STTokenRangeInspect[]|nil (table|nil) List of tokens at position. Each token has --- the following fields: --- - line (integer) line number, 0-based --- - start_col (integer) start column, 0-based --- - end_col (integer) end column, 0-based --- - type (string) token type as string, e.g. "variable" --- - modifiers (table) token modifiers as a set. E.g., { static = true, readonly = true } +--- - client_id (integer) function M.get_at_pos(bufnr, row, col) if bufnr == nil or bufnr == 0 then bufnr = api.nvim_get_current_buf() @@ -665,13 +680,14 @@ function M.get_at_pos(bufnr, row, col) row, col = cursor[1] - 1, cursor[2] end - local tokens = {} + local tokens = {} --- @type STTokenRangeInspect[] for client_id, client in pairs(highlighter.client_state) do local highlights = client.current_result.highlights if highlights then local idx = lower_bound(highlights, row, 1, #highlights + 1) for i = idx, #highlights do local token = highlights[i] + --- @cast token STTokenRangeInspect if token.line > row then break @@ -712,6 +728,13 @@ function M.force_refresh(bufnr) end end +--- @class vim.lsp.semantic_tokens.highlight_token.Opts +--- @inlinedoc +--- +--- Priority for the applied extmark. +--- (Default: `vim.highlight.priorities.semantic_tokens + 3`) +--- @field priority? integer + --- Highlight a semantic token. --- --- Apply an extmark with a given highlight group for a semantic token. The @@ -720,11 +743,9 @@ end --- use inside |LspTokenUpdate| callbacks. ---@param token (table) a semantic token, found as `args.data.token` in |LspTokenUpdate|. ---@param bufnr (integer) the buffer to highlight ----@param client_id (integer) The ID of the |vim.lsp.client| +---@param client_id (integer) The ID of the |vim.lsp.Client| ---@param hl_group (string) Highlight group name ----@param opts (table|nil) Optional parameters. ---- - priority: (integer|nil) Priority for the applied extmark. Defaults ---- to `vim.highlight.priorities.semantic_tokens + 3` +---@param opts? vim.lsp.semantic_tokens.highlight_token.Opts Optional parameters: function M.highlight_token(token, bufnr, client_id, hl_group, opts) local highlighter = STHighlighter.active[bufnr] if not highlighter then @@ -747,6 +768,7 @@ function M.highlight_token(token, bufnr, client_id, hl_group, opts) }) end +--- @package --- |lsp-handler| for the method `workspace/semanticTokens/refresh` --- --- Refresh requests are sent by the server to indicate a project-wide change @@ -754,9 +776,7 @@ end --- invalidate the current results of all buffers and automatically kick off a --- new request for buffers that are displayed in a window. For those that aren't, a --- the BufWinEnter event should take care of it next time it's displayed. ---- ----@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#semanticTokens_refreshRequest -handlers[ms.workspace_semanticTokens_refresh] = function(err, _, ctx) +function M._refresh(err, _, ctx) if err then return vim.NIL end diff --git a/runtime/lua/vim/lsp/sync.lua b/runtime/lua/vim/lsp/sync.lua index ca01cdc08b..936579e003 100644 --- a/runtime/lua/vim/lsp/sync.lua +++ b/runtime/lua/vim/lsp/sync.lua @@ -53,13 +53,12 @@ local str_utf_end = vim.str_utf_end ---@param line string the line to index into ---@param byte integer the byte idx ---@param offset_encoding string utf-8|utf-16|utf-32|nil (default: utf-8) ---@returns integer the utf idx for the given encoding +---@return integer utf_idx for the given encoding local function byte_to_utf(line, byte, offset_encoding) -- convert to 0 based indexing for str_utfindex byte = byte - 1 - local utf_idx - local _ + local utf_idx, _ --- @type integer, integer -- Convert the byte range to utf-{8,16,32} and convert 1-based (lua) indexing to 0-based if offset_encoding == 'utf-16' then _, utf_idx = str_utfindex(line, byte) @@ -73,9 +72,11 @@ local function byte_to_utf(line, byte, offset_encoding) return utf_idx + 1 end +---@param line string +---@param offset_encoding string +---@return integer local function compute_line_length(line, offset_encoding) - local length - local _ + local length, _ --- @type integer, integer if offset_encoding == 'utf-16' then _, length = str_utfindex(line) elseif offset_encoding == 'utf-32' then @@ -94,7 +95,7 @@ end ---@return integer byte_idx of first change position ---@return integer char_idx of first change position local function align_end_position(line, byte, offset_encoding) - local char + local char --- @type integer -- If on the first byte, or an empty string: the trivial case if byte == 1 or #line == 0 then char = byte @@ -119,14 +120,19 @@ local function align_end_position(line, byte, offset_encoding) return byte, char end +---@class vim.lsp.sync.Range +---@field line_idx integer +---@field byte_idx integer +---@field char_idx integer + --- Finds the first line, byte, and char index of the difference between the previous and current lines buffer normalized to the previous codepoint. ----@param prev_lines table list of lines from previous buffer ----@param curr_lines table list of lines from current buffer +---@param prev_lines string[] list of lines from previous buffer +---@param curr_lines string[] list of lines from current buffer ---@param firstline integer firstline from on_lines, adjusted to 1-index ---@param lastline integer lastline from on_lines, adjusted to 1-index ---@param new_lastline integer new_lastline from on_lines, adjusted to 1-index ---@param offset_encoding string utf-8|utf-16|utf-32|nil (fallback to utf-8) ----@return table result table include line_idx, byte_idx, and char_idx of first change position +---@return vim.lsp.sync.Range result table include line_idx, byte_idx, and char_idx of first change position local function compute_start_range( prev_lines, curr_lines, @@ -135,14 +141,14 @@ local function compute_start_range( new_lastline, offset_encoding ) - local char_idx - local byte_idx + local char_idx --- @type integer? + local byte_idx --- @type integer? -- If firstline == lastline, no existing text is changed. All edit operations -- occur on a new line pointed to by lastline. This occurs during insertion of -- new lines(O), the new newline is inserted at the line indicated by -- new_lastline. if firstline == lastline then - local line_idx + local line_idx --- @type integer local line = prev_lines[firstline - 1] if line then line_idx = firstline - 1 @@ -198,15 +204,15 @@ end --- Normalized to the next codepoint. --- prev_end_range is the text range sent to the server representing the changed region. --- curr_end_range is the text that should be collected and sent to the server. --- ----@param prev_lines table list of lines ----@param curr_lines table list of lines ----@param start_range table +--- +---@param prev_lines string[] list of lines +---@param curr_lines string[] list of lines +---@param start_range vim.lsp.sync.Range +---@param firstline integer ---@param lastline integer ---@param new_lastline integer ---@param offset_encoding string ----@return integer|table end_line_idx and end_col_idx of range ----@return table|nil end_col_idx of range +---@return vim.lsp.sync.Range, vim.lsp.sync.Range local function compute_end_range( prev_lines, curr_lines, @@ -250,7 +256,7 @@ local function compute_end_range( -- Editing the same line -- If the byte offset is zero, that means there is a difference on the last byte (not newline) if prev_line_idx == curr_line_idx then - local max_length + local max_length --- @type integer if start_line_idx == prev_line_idx then -- Search until beginning of difference max_length = min( @@ -283,7 +289,7 @@ local function compute_end_range( local prev_end_range = { line_idx = prev_line_idx, byte_idx = prev_byte_idx, char_idx = prev_char_idx } - local curr_end_range + local curr_end_range ---@type vim.lsp.sync.Range -- Deletion event, new_range cannot be before start if curr_line_idx < start_line_idx then curr_end_range = { line_idx = start_line_idx, byte_idx = 1, char_idx = 1 } @@ -343,6 +349,12 @@ end -- codeunits for utf-32 -- Line endings count here as 2 chars for \r\n (dos), 1 char for \n (unix), and 1 char for \r (mac) -- These correspond to Windows, Linux/macOS (OSX and newer), and macOS (version 9 and prior) +---@param lines string[] +---@param start_range vim.lsp.sync.Range +---@param end_range vim.lsp.sync.Range +---@param offset_encoding string +---@param line_ending string +---@return integer local function compute_range_length(lines, start_range, end_range, offset_encoding, line_ending) local line_ending_length = #line_ending -- Single line case @@ -351,7 +363,7 @@ local function compute_range_length(lines, start_range, end_range, offset_encodi end local start_line = lines[start_range.line_idx] - local range_length + local range_length --- @type integer if start_line and #start_line > 0 then range_length = compute_line_length(start_line, offset_encoding) - start_range.char_idx @@ -387,7 +399,8 @@ end ---@param lastline integer line to begin search in old_lines for last difference ---@param new_lastline integer line to begin search in new_lines for last difference ---@param offset_encoding string encoding requested by language server ----@return table TextDocumentContentChangeEvent see https://microsoft.github.io/language-server-protocol/specification/#textDocumentContentChangeEvent +---@param line_ending string +---@return lsp.TextDocumentContentChangeEvent : see https://microsoft.github.io/language-server-protocol/specification/#textDocumentContentChangeEvent function M.compute_diff( prev_lines, curr_lines, diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index 32b220746f..f8e5b6a90d 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -3,7 +3,7 @@ local snippet = require('vim.lsp._snippet_grammar') local validate = vim.validate local api = vim.api local list_extend = vim.list_extend -local highlight = require('vim.highlight') +local highlight = vim.highlight local uv = vim.uv local npcall = vim.F.npcall @@ -180,6 +180,7 @@ local _str_byteindex_enc = M._str_byteindex_enc ---@param new_lines (table) list of strings to replace the original ---@return table The modified {lines} object function M.set_lines(lines, A, B, new_lines) + vim.deprecate('vim.lsp.util.set_lines()', 'nil', '0.12') -- 0-indexing to 1-indexing local i_0 = A[1] + 1 -- If it extends past the end, truncate it to the end. This is because the @@ -346,7 +347,7 @@ end ---@private ---@deprecated Use vim.lsp.status() or access client.progress directly function M.get_progress_messages() - vim.deprecate('vim.lsp.util.get_progress_messages', 'vim.lsp.status', '0.11.0') + vim.deprecate('vim.lsp.util.get_progress_messages()', 'vim.lsp.status()', '0.11') local new_messages = {} local progress_remove = {} @@ -418,6 +419,9 @@ function M.apply_text_edits(text_edits, bufnr, offset_encoding) if not next(text_edits) then return end + + assert(bufnr ~= 0, 'Explicit buffer number is required') + if not api.nvim_buf_is_loaded(bufnr) then vim.fn.bufload(bufnr) end @@ -456,7 +460,7 @@ function M.apply_text_edits(text_edits, bufnr, offset_encoding) -- save and restore local marks since they get deleted by nvim_buf_set_lines local marks = {} - for _, m in pairs(vim.fn.getmarklist(bufnr or vim.api.nvim_get_current_buf())) do + for _, m in pairs(vim.fn.getmarklist(bufnr)) do if m.mark:match("^'[a-z]$") then marks[m.mark:sub(2, 2)] = { m.pos[2], m.pos[3] - 1 } -- api-indexed end @@ -515,7 +519,7 @@ function M.apply_text_edits(text_edits, bufnr, offset_encoding) local max = api.nvim_buf_line_count(bufnr) -- no need to restore marks that still exist - for _, m in pairs(vim.fn.getmarklist(bufnr or vim.api.nvim_get_current_buf())) do + for _, m in pairs(vim.fn.getmarklist(bufnr)) do marks[m.mark:sub(2, 2)] = nil end -- restore marks @@ -547,12 +551,16 @@ end --- Can be used to extract the completion items from a --- `textDocument/completion` request, which may return one of --- `CompletionItem[]`, `CompletionList` or null. +--- +--- Note that this method doesn't apply `itemDefaults` to `CompletionList`s, and hence the returned +--- results might be incorrect. +--- ---@deprecated ---@param result table The result of a `textDocument/completion` request ---@return lsp.CompletionItem[] List of completion items ---@see https://microsoft.github.io/language-server-protocol/specification#textDocument_completion function M.extract_completion_items(result) - vim.deprecate('vim.lsp.util.extract_completion_items', nil, '0.11') + vim.deprecate('vim.lsp.util.extract_completion_items()', nil, '0.11') if type(result) == 'table' and result.items then -- result is a `CompletionList` return result.items @@ -570,6 +578,7 @@ end --- ---@param text_document_edit table: a `TextDocumentEdit` object ---@param index integer: Optional index of the edit, if from a list of edits (or nil, if not from a list) +---@param offset_encoding? string ---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocumentEdit function M.apply_text_document_edit(text_document_edit, index, offset_encoding) local text_document = text_document_edit.textDocument @@ -612,7 +621,7 @@ end ---@param input string unparsed snippet ---@return string parsed snippet function M.parse_snippet(input) - vim.deprecate('vim.lsp.util.parse_snippet', nil, '0.11') + vim.deprecate('vim.lsp.util.parse_snippet()', nil, '0.11') local ok, parsed = pcall(function() return snippet.parse(input) end) @@ -634,76 +643,129 @@ end ---@return table[] items ---@see complete-items function M.text_document_completion_list_to_complete_items(result, prefix) - vim.deprecate('vim.lsp.util.text_document_completion_list_to_complete_items', nil, '0.11') - return require('vim.lsp._completion')._lsp_to_complete_items(result, prefix) + vim.deprecate('vim.lsp.util.text_document_completion_list_to_complete_items()', nil, '0.11') + return vim.lsp._completion._lsp_to_complete_items(result, prefix) end ---- Like vim.fn.bufwinid except it works across tabpages. -local function bufwinid(bufnr) - for _, win in ipairs(api.nvim_list_wins()) do - if api.nvim_win_get_buf(win) == bufnr then - return win +local function path_components(path) + return vim.split(path, '/', { plain = true }) +end + +local function path_under_prefix(path, prefix) + for i, c in ipairs(prefix) do + if c ~= path[i] then + return false end end + return true end ---- Get list of buffers for a directory -local function get_dir_bufs(path) - path = path:gsub('([^%w])', '%%%1') +--- Get list of buffers whose filename matches the given path prefix (normalized full path) +---@return integer[] +local function get_bufs_with_prefix(prefix) + prefix = path_components(prefix) local buffers = {} for _, v in ipairs(vim.api.nvim_list_bufs()) do - local bufname = vim.api.nvim_buf_get_name(v):gsub('buffer://', '') - if bufname:find(path) then + local bname = vim.api.nvim_buf_get_name(v) + local path = path_components(vim.fs.normalize(bname, { expand_env = false })) + if path_under_prefix(path, prefix) then table.insert(buffers, v) end end return buffers end +local function escape_gsub_repl(s) + return (s:gsub('%%', '%%%%')) +end + +--- @class vim.lsp.util.rename.Opts +--- @inlinedoc +--- @field overwrite? boolean +--- @field ignoreIfExists? boolean + --- Rename old_fname to new_fname --- ----@param opts (table) --- overwrite? bool --- ignoreIfExists? bool +--- Existing buffers are renamed as well, while maintaining their bufnr. +--- +--- It deletes existing buffers that conflict with the renamed file name only when +--- * `opts` requests overwriting; or +--- * the conflicting buffers are not loaded, so that deleting thme does not result in data loss. +--- +--- @param old_fname string +--- @param new_fname string +--- @param opts? vim.lsp.util.rename.Opts Options: function M.rename(old_fname, new_fname, opts) opts = opts or {} - local target_exists = uv.fs_stat(new_fname) ~= nil - if target_exists and not opts.overwrite or opts.ignoreIfExists then - vim.notify('Rename target already exists. Skipping rename.') + local skip = not opts.overwrite or opts.ignoreIfExists + + local old_fname_full = vim.uv.fs_realpath(vim.fs.normalize(old_fname, { expand_env = false })) + if not old_fname_full then + vim.notify('Invalid path: ' .. old_fname, vim.log.levels.ERROR) return end - local oldbufs = {} - local win = nil - - if vim.fn.isdirectory(old_fname) == 1 then - oldbufs = get_dir_bufs(old_fname) - else - local oldbuf = vim.fn.bufadd(old_fname) - table.insert(oldbufs, oldbuf) - win = bufwinid(oldbuf) + local target_exists = uv.fs_stat(new_fname) ~= nil + if target_exists and skip then + vim.notify(new_fname .. ' already exists. Skipping rename.', vim.log.levels.ERROR) + return end - for _, b in ipairs(oldbufs) do - vim.fn.bufload(b) - -- The there may be pending changes in the buffer - api.nvim_buf_call(b, function() - vim.cmd('w!') + local buf_rename = {} ---@type table<integer, {from: string, to: string}> + local old_fname_pat = '^' .. vim.pesc(old_fname_full) + for b in + vim.iter(get_bufs_with_prefix(old_fname_full)):filter(function(b) + -- No need to care about unloaded or nofile buffers. Also :saveas won't work for them. + return api.nvim_buf_is_loaded(b) + and not vim.list_contains({ 'nofile', 'nowrite' }, vim.bo[b].buftype) end) + do + -- Renaming a buffer may conflict with another buffer that happens to have the same name. In + -- most cases, this would have been already detected by the file conflict check above, but the + -- conflicting buffer may not be associated with a file. For example, 'buftype' can be "nofile" + -- or "nowrite", or the buffer can be a normal buffer but has not been written to the file yet. + -- Renaming should fail in such cases to avoid losing the contents of the conflicting buffer. + local old_bname = vim.api.nvim_buf_get_name(b) + local new_bname = old_bname:gsub(old_fname_pat, escape_gsub_repl(new_fname)) + if vim.fn.bufexists(new_bname) == 1 then + local existing_buf = vim.fn.bufnr(new_bname) + if api.nvim_buf_is_loaded(existing_buf) and skip then + vim.notify( + new_bname .. ' already exists in the buffer list. Skipping rename.', + vim.log.levels.ERROR + ) + return + end + -- no need to preserve if such a buffer is empty + api.nvim_buf_delete(existing_buf, {}) + end + + buf_rename[b] = { from = old_bname, to = new_bname } end - local ok, err = os.rename(old_fname, new_fname) + local newdir = assert(vim.fs.dirname(new_fname)) + vim.fn.mkdir(newdir, 'p') + + local ok, err = os.rename(old_fname_full, new_fname) assert(ok, err) - if vim.fn.isdirectory(new_fname) == 0 then - local newbuf = vim.fn.bufadd(new_fname) - if win then - api.nvim_win_set_buf(win, newbuf) - end + local old_undofile = vim.fn.undofile(old_fname_full) + if uv.fs_stat(old_undofile) ~= nil then + local new_undofile = vim.fn.undofile(new_fname) + vim.fn.mkdir(assert(vim.fs.dirname(new_undofile)), 'p') + os.rename(old_undofile, new_undofile) end - for _, b in ipairs(oldbufs) do - api.nvim_buf_delete(b, {}) + for b, rename in pairs(buf_rename) do + -- Rename with :saveas. This does two things: + -- * Unset BF_WRITE_MASK, so that users don't get E13 when they do :write. + -- * Send didClose and didOpen via textDocument/didSave handler. + api.nvim_buf_call(b, function() + vim.cmd('keepalt saveas! ' .. vim.fn.fnameescape(rename.to)) + end) + -- Delete the new buffer with the old name created by :saveas. nvim_buf_delete and + -- :bwipeout are futile because the buffer will be added again somewhere else. + vim.cmd('bdelete! ' .. vim.fn.bufnr(rename.from)) end end @@ -745,7 +807,7 @@ end --- ---@param workspace_edit table `WorkspaceEdit` ---@param offset_encoding string utf-8|utf-16|utf-32 (required) ---see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_applyEdit +---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_applyEdit function M.apply_workspace_edit(workspace_edit, offset_encoding) if offset_encoding == nil then vim.notify_once( @@ -789,7 +851,7 @@ end --- Note that if the input is of type `MarkupContent` and its kind is `plaintext`, --- then the corresponding value is returned without further modifications. --- ----@param input (`MarkedString` | `MarkedString[]` | `MarkupContent`) +---@param input (lsp.MarkedString | lsp.MarkedString[] | lsp.MarkupContent) ---@param contents (table|nil) List of strings to extend with converted lines. Defaults to {}. ---@return string[] extended with lines of converted markdown. ---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_hover @@ -1055,7 +1117,7 @@ function M.show_document(location, offset_encoding, opts) vim.fn.settagstack(vim.fn.win_getid(), { items = items }, 't') end - local win = opts.reuse_win and bufwinid(bufnr) + local win = opts.reuse_win and vim.fn.win_findbuf(bufnr)[1] or focus and api.nvim_get_current_win() or create_window_without_focus() @@ -1068,7 +1130,7 @@ function M.show_document(location, offset_encoding, opts) -- location may be Location or LocationLink local range = location.range or location.targetSelectionRange if range then - --- Jump to new location (adjusting for encoding of characters) + -- Jump to new location (adjusting for encoding of characters) local row = range.start.line local col = get_line_byte_from_position(bufnr, range.start, offset_encoding) api.nvim_win_set_cursor(win, { row + 1, col }) @@ -1105,6 +1167,7 @@ end --- - for LocationLink, targetRange is shown (e.g., body of function definition) --- ---@param location table a single `Location` or `LocationLink` +---@param opts table ---@return integer|nil buffer id of float window ---@return integer|nil window id of float window function M.preview_location(location, opts) @@ -1218,6 +1281,7 @@ end --- --- If you want to open a popup with fancy markdown, use `open_floating_preview` instead --- +---@param bufnr integer ---@param contents table of lines to show in window ---@param opts table with optional fields --- - height of floating window @@ -1410,7 +1474,7 @@ function M.stylize_markdown(bufnr, contents, opts) return stripped end ---- @class lsp.util.NormalizeMarkdownOptions +--- @class (private) vim.lsp.util._normalize_markdown.Opts --- @field width integer Thematic breaks are expanded to this size. Defaults to 80. --- Normalizes Markdown input to a canonical form. @@ -1426,7 +1490,7 @@ end --- ---@private ---@param contents string[] ----@param opts? lsp.util.NormalizeMarkdownOptions +---@param opts? vim.lsp.util._normalize_markdown.Opts ---@return string[] table of lines containing normalized Markdown ---@see https://github.github.com/gfm function M._normalize_markdown(contents, opts) @@ -1497,7 +1561,7 @@ local function close_preview_autocmd(events, winnr, bufnrs) end end ----@internal +---@private --- Computes size of float needed to show contents (with optional wrapping) --- ---@param contents table of lines to show in window @@ -1573,24 +1637,50 @@ function M._make_floating_popup_size(contents, opts) return width, height end +--- @class vim.lsp.util.open_floating_preview.Opts +--- @inlinedoc +--- +--- Height of floating window +--- @field height? integer +--- +--- Width of floating window +--- @field width? integer +--- +--- Wrap long lines +--- (default: `true`) +--- @field wrap? boolean +--- +--- Character to wrap at for computing height when wrap is enabled +--- @field wrap_at? integer +--- +--- Maximal width of floating window +--- @field max_width? integer +--- +--- Maximal height of floating window +--- @field max_height? integer +--- +--- If a popup with this id is opened, then focus it +--- @field focus_id? string +--- +--- List of events that closes the floating window +--- @field close_events? table +--- +--- Make float focusable. +--- (default: `true`) +--- @field focusable? boolean +--- +--- If `true`, and if {focusable} is also `true`, focus an existing floating +--- window with the same {focus_id} +--- (default: `true`) +--- @field focus? boolean + --- Shows contents in a floating window. --- ---@param contents table of lines to show in window ---@param syntax string of syntax to set for opened buffer ----@param opts table with optional fields (additional keys are filtered with |vim.lsp.util.make_floating_popup_options()| ---- before they are passed on to |nvim_open_win()|) ---- - height: (integer) height of floating window ---- - width: (integer) width of floating window ---- - wrap: (boolean, default true) wrap long lines ---- - wrap_at: (integer) character to wrap at for computing height when wrap is enabled ---- - max_width: (integer) maximal width of floating window ---- - max_height: (integer) maximal height of floating window ---- - focus_id: (string) if a popup with this id is opened, then focus it ---- - close_events: (table) list of events that closes the floating window ---- - focusable: (boolean, default true) Make float focusable ---- - focus: (boolean, default true) If `true`, and if {focusable} ---- is also `true`, focus an existing floating window with the same ---- {focus_id} +---@param opts? vim.lsp.util.open_floating_preview.Opts with optional fields +--- (additional keys are filtered with |vim.lsp.util.make_floating_popup_options()| +--- before they are passed on to |nvim_open_win()|) ---@return integer bufnr of newly created float window ---@return integer winid of newly created float window preview window function M.open_floating_preview(contents, syntax, opts) @@ -1754,6 +1844,14 @@ local position_sort = sort_by_key(function(v) return { v.start.line, v.start.character } end) +---@class vim.lsp.util.locations_to_items.ret +---@inlinedoc +---@field filename string +---@field lnum integer 1-indexed line number +---@field col integer 1-indexed column +---@field text string +---@field user_data lsp.Location|lsp.LocationLink + --- Returns the items with the byte position calculated correctly and in sorted --- order, for display in quickfix and location lists. --- @@ -1763,10 +1861,10 @@ end) --- The result can be passed to the {list} argument of |setqflist()| or --- |setloclist()|. --- ----@param locations table list of `Location`s or `LocationLink`s +---@param locations lsp.Location[]|lsp.LocationLink[] ---@param offset_encoding string offset_encoding for locations utf-8|utf-16|utf-32 --- default to first client of buffer ----@return table list of items +---@return vim.lsp.util.locations_to_items.ret[] function M.locations_to_items(locations, offset_encoding) if offset_encoding == nil then vim.notify_once( @@ -1777,6 +1875,7 @@ function M.locations_to_items(locations, offset_encoding) end local items = {} + ---@type table<string, {start: lsp.Position, location: lsp.Location|lsp.LocationLink}[]> local grouped = setmetatable({}, { __index = function(t, k) local v = {} @@ -1791,6 +1890,7 @@ function M.locations_to_items(locations, offset_encoding) table.insert(grouped[uri], { start = range.start, location = d }) end + ---@type string[] local keys = vim.tbl_keys(grouped) table.sort(keys) -- TODO(ashkan) I wish we could do this lazily. @@ -1799,16 +1899,13 @@ function M.locations_to_items(locations, offset_encoding) table.sort(rows, position_sort) local filename = vim.uri_to_fname(uri) - -- list of row numbers - local uri_rows = {} + local line_numbers = {} for _, temp in ipairs(rows) do - local pos = temp.start - local row = pos.line - table.insert(uri_rows, row) + table.insert(line_numbers, temp.start.line) end -- get all the lines for this uri - local lines = get_lines(vim.uri_to_bufnr(uri), uri_rows) + local lines = get_lines(vim.uri_to_bufnr(uri), line_numbers) for _, temp in ipairs(rows) do local pos = temp.start @@ -1837,6 +1934,7 @@ end --- Converts symbols to quickfix list items. --- ---@param symbols table DocumentSymbol[] or SymbolInformation[] +---@param bufnr integer function M.symbols_to_items(symbols, bufnr) local function _symbols_to_items(_symbols, _items, _bufnr) for _, symbol in ipairs(_symbols) do @@ -1879,6 +1977,7 @@ end ---@param lines table list of lines to trim ---@return table trimmed list of lines function M.trim_empty_lines(lines) + vim.deprecate('vim.lsp.util.trim_empty_lines()', 'vim.split() with `trimempty`', '0.12') local start = 1 for i = 1, #lines do if lines[i] ~= nil and #lines[i] > 0 then @@ -1905,6 +2004,7 @@ end ---@param lines table list of lines ---@return string filetype or "markdown" if it was unchanged. function M.try_trim_markdown_code_blocks(lines) + vim.deprecate('vim.lsp.util.try_trim_markdown_code_blocks()', 'nil', '0.12') local language_id = lines[1]:match('^```(.*)') if language_id then local has_inner_code_fence = false @@ -2089,7 +2189,7 @@ end --- Creates a `DocumentFormattingParams` object for the current buffer and cursor position. --- ---@param options table|nil with valid `FormattingOptions` entries ----@return `DocumentFormattingParams` object +---@return lsp.DocumentFormattingParams object ---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_formatting function M.make_formatting_params(options) validate({ options = { options, 't', true } }) @@ -2106,8 +2206,8 @@ end --- Returns the UTF-32 and UTF-16 offsets for a position in a certain buffer. --- ---@param buf integer buffer number (0 for current) ----@param row 0-indexed line ----@param col 0-indexed byte offset in line +---@param row integer 0-indexed line +---@param col integer 0-indexed byte offset in line ---@param offset_encoding string utf-8|utf-16|utf-32 defaults to `offset_encoding` of first client of `buf` ---@return integer `offset_encoding` index of the character in line {row} column {col} in buffer {buf} function M.character_offset(buf, row, col, offset_encoding) @@ -2130,8 +2230,10 @@ end --- ---@param settings table language server settings ---@param section string indicating the field of the settings table ----@return table|string The value of settings accessed via section +---@return table|string|vim.NIL The value of settings accessed via section. `vim.NIL` if not found. +---@deprecated function M.lookup_section(settings, section) + vim.deprecate('vim.lsp.util.lookup_section()', 'vim.tbl_get() with `vim.split`', '0.12') for part in vim.gsplit(section, '.', { plain = true }) do settings = settings[part] if settings == nil then @@ -2170,16 +2272,16 @@ local function make_line_range_params(bufnr, start_line, end_line, offset_encodi } end ----@private ---- Request updated LSP information for a buffer. ---- ----@class lsp.util.RefreshOptions +---@class (private) vim.lsp.util._refresh.Opts ---@field bufnr integer? Buffer to refresh (default: 0) ---@field only_visible? boolean Whether to only refresh for the visible regions of the buffer (default: false) ---@field client_id? integer Client ID to refresh (default: all clients) --- + +---@private +--- Request updated LSP information for a buffer. +--- ---@param method string LSP method to call ----@param opts? lsp.util.RefreshOptions Options table +---@param opts? vim.lsp.util._refresh.Opts Options table function M._refresh(method, opts) opts = opts or {} local bufnr = opts.bufnr @@ -2228,6 +2330,6 @@ end M._get_line_byte_from_position = get_line_byte_from_position ---@nodoc -M.buf_versions = {} +M.buf_versions = {} ---@type table<integer,integer> return M |