diff options
Diffstat (limited to 'runtime/lua/vim')
33 files changed, 810 insertions, 731 deletions
diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua index 4e39abb2be..d14007312e 100644 --- a/runtime/lua/vim/_editor.lua +++ b/runtime/lua/vim/_editor.lua @@ -190,6 +190,7 @@ function vim._os_proc_children(ppid) return children end +--- @nodoc --- @class vim.inspect.Opts --- @field depth? integer --- @field newline? string @@ -454,7 +455,7 @@ vim.cmd = setmetatable({}, { end, }) ---- @class vim.var_accessor +--- @class (private) vim.var_accessor --- @field [string] any --- @field [integer] vim.var_accessor @@ -1048,7 +1049,7 @@ function vim.deprecate(name, alternative, version, plugin, backtrace) -- e.g., when planned to be removed in version = '0.12' (soft-deprecated since 0.10-dev), -- show warnings since 0.11, including 0.11-dev (hard_deprecated_since = 0.11-dev). if plugin == 'Nvim' then - local current_version = vim.version() ---@type Version + local current_version = vim.version() ---@type vim.Version local removal_version = assert(vim.version.parse(version)) local is_hard_deprecated ---@type boolean diff --git a/runtime/lua/vim/_inspector.lua b/runtime/lua/vim/_inspector.lua index 9a073c32c4..a19d40c50d 100644 --- a/runtime/lua/vim/_inspector.lua +++ b/runtime/lua/vim/_inspector.lua @@ -1,8 +1,18 @@ ----@class InspectorFilter ----@field syntax boolean include syntax based highlight groups (defaults to true) ----@field treesitter boolean include treesitter based highlight groups (defaults to true) ----@field extmarks boolean|"all" include extmarks. When `all`, then extmarks without a `hl_group` will also be included (defaults to true) ----@field semantic_tokens boolean include semantic token highlights (defaults to true) +--- @class vim._inspector.Filter +--- @inlinedoc +--- +--- Include syntax based highlight groups (defaults to true) +--- @field syntax boolean +--- +--- Include treesitter based highlight groups (defaults to true) +--- @field treesitter boolean +--- +--- Include extmarks. When `all`, then extmarks without a `hl_group` will also be included. +--- (default: true) +--- @field extmarks boolean|"all" +--- +--- Include semantic token highlights (defaults to true) +--- @field semantic_tokens boolean local defaults = { syntax = true, treesitter = true, @@ -17,11 +27,7 @@ local defaults = { ---@param bufnr? integer defaults to the current buffer ---@param row? integer row to inspect, 0-based. Defaults to the row of the current cursor ---@param col? integer col to inspect, 0-based. Defaults to the col of the current cursor ----@param filter? InspectorFilter (table) a table with key-value pairs to filter the items ---- - syntax (boolean): include syntax based highlight groups (defaults to true) ---- - treesitter (boolean): include treesitter based highlight groups (defaults to true) ---- - extmarks (boolean|"all"): include extmarks. When `all`, then extmarks without a `hl_group` will also be included (defaults to true) ---- - semantic_tokens (boolean): include semantic tokens (defaults to true) +---@param filter? vim._inspector.Filter Table with key-value pairs to filter the items ---@return {treesitter:table,syntax:table,extmarks:table,semantic_tokens:table,buffer:integer,col:integer,row:integer} (table) a table with the following key-value pairs. Items are in "traversal order": --- - treesitter: a list of treesitter captures --- - syntax: a list of syntax groups @@ -139,7 +145,7 @@ end ---@param bufnr? integer defaults to the current buffer ---@param row? integer row to inspect, 0-based. Defaults to the row of the current cursor ---@param col? integer col to inspect, 0-based. Defaults to the col of the current cursor ----@param filter? InspectorFilter (table) see |vim.inspect_pos()| +---@param filter? vim._inspector.Filter (table) see |vim.inspect_pos()| function vim.show_pos(bufnr, row, col, filter) local items = vim.inspect_pos(bufnr, row, col, filter) diff --git a/runtime/lua/vim/_meta/builtin.lua b/runtime/lua/vim/_meta/builtin.lua index 472162ecc1..4831989e1a 100644 --- a/runtime/lua/vim/_meta/builtin.lua +++ b/runtime/lua/vim/_meta/builtin.lua @@ -61,6 +61,7 @@ error('Cannot require a meta file') --- --- </pre> +---@nodoc ---@class vim.NIL ---@type vim.NIL diff --git a/runtime/lua/vim/_meta/lpeg.lua b/runtime/lua/vim/_meta/lpeg.lua index 202c99f18c..1ce40f3340 100644 --- a/runtime/lua/vim/_meta/lpeg.lua +++ b/runtime/lua/vim/_meta/lpeg.lua @@ -21,6 +21,7 @@ error('Cannot require a meta file') vim.lpeg = {} +--- @nodoc --- @class vim.lpeg.Pattern --- @operator unm: vim.lpeg.Pattern --- @operator add(vim.lpeg.Pattern): vim.lpeg.Pattern @@ -167,6 +168,7 @@ function vim.lpeg.S(string) end --- @return vim.lpeg.Pattern function vim.lpeg.V(v) end +--- @nodoc --- @class vim.lpeg.Locale --- @field alnum userdata --- @field alpha userdata diff --git a/runtime/lua/vim/_meta/regex.lua b/runtime/lua/vim/_meta/regex.lua index ab403b97e7..595ad96319 100644 --- a/runtime/lua/vim/_meta/regex.lua +++ b/runtime/lua/vim/_meta/regex.lua @@ -12,6 +12,7 @@ --- @return vim.regex function vim.regex(re) end +--- @nodoc --- @class vim.regex local regex = {} -- luacheck: no unused diff --git a/runtime/lua/vim/_options.lua b/runtime/lua/vim/_options.lua index f1fed50c6d..bde9421552 100644 --- a/runtime/lua/vim/_options.lua +++ b/runtime/lua/vim/_options.lua @@ -797,6 +797,7 @@ end --- `vim.opt_global`. --- </pre> +--- @nodoc --- @class vim.Option local Option = {} -- luacheck: no unused diff --git a/runtime/lua/vim/diagnostic.lua b/runtime/lua/vim/diagnostic.lua index 49165c4db9..3979e5512c 100644 --- a/runtime/lua/vim/diagnostic.lua +++ b/runtime/lua/vim/diagnostic.lua @@ -2,18 +2,44 @@ local api, if_nil = vim.api, vim.F.if_nil local M = {} +--- *diagnostic-structure* +--- +--- Diagnostics use the same indexing as the rest of the Nvim API (i.e. 0-based +--- rows and columns). |api-indexing| --- @class vim.Diagnostic +--- +--- Buffer number --- @field bufnr? integer ---- @field lnum integer 0-indexed ---- @field end_lnum? integer 0-indexed ---- @field col integer 0-indexed ---- @field end_col? integer 0-indexed +--- +--- The starting line of the diagnostic (0-indexed) +--- @field lnum integer +--- +--- The final line of the diagnostic (0-indexed) +--- @field end_lnum? integer +--- +--- The starting column of the diagnostic (0-indexed) +--- @field col integer +--- +--- The final column of the diagnostic (0-indexed) +--- @field end_col? integer +--- +--- The severity of the diagnostic |vim.diagnostic.severity| --- @field severity? vim.diagnostic.Severity +--- +--- The diagnostic text --- @field message string +--- +--- The source of the diagnostic --- @field source? string +--- +--- The diagnostic code --- @field code? string|integer +--- --- @field _tags? { deprecated: boolean, unnecessary: boolean} +--- +--- Arbitrary data plugins or users can add --- @field user_data? any arbitrary data plugins can add +--- --- @field namespace? integer --- @class vim.diagnostic.Opts @@ -104,7 +130,7 @@ local global_diagnostic_options = { severity_sort = false, } ---- @class vim.diagnostic.Handler +--- @class (private) vim.diagnostic.Handler --- @field show? fun(namespace: integer, bufnr: integer, diagnostics: vim.Diagnostic[], opts?: vim.diagnostic.OptsResolved) --- @field hide? fun(namespace:integer, bufnr:integer) @@ -154,7 +180,7 @@ do }) end ---- @class vim.diagnostic._extmark +--- @class (private) vim.diagnostic._extmark --- @field [1] integer id --- @field [2] integer start --- @field [3] integer end @@ -1018,31 +1044,52 @@ function M.get_next_pos(opts) return { next.lnum, next.col } end +--- A table with the following keys: --- @class vim.diagnostic.GetOpts +--- @inlinedoc +--- +--- Limit diagnostics to the given namespace. --- @field namespace? integer +--- +--- Limit diagnostics to the given line number. --- @field lnum? integer +--- +--- See |diagnostic-severity|. --- @field severity? vim.diagnostic.SeverityFilter +--- Configuration table with the following keys: --- @class vim.diagnostic.GotoOpts : vim.diagnostic.GetOpts +--- @inlinedoc +--- +--- Only consider diagnostics from the given namespace. +--- @field namespace integer +--- +--- Cursor position as a (row, col) tuple. +--- See |nvim_win_get_cursor()|. Defaults to the current cursor position. --- @field cursor_position? {[1]:integer,[2]:integer} +--- +--- Whether to loop around file or not. Similar to 'wrapscan'. +--- (default: `true`) --- @field wrap? boolean +--- +--- See |diagnostic-severity|. +--- @field severity vim.diagnostic.Severity +--- +--- If "true", call |vim.diagnostic.open_float()| +--- after moving. If a table, pass the table as the {opts} parameter +--- to |vim.diagnostic.open_float()|. Unless overridden, the float will show +--- diagnostics at the new cursor position (as if "cursor" were passed to +--- the "scope" option). +--- (default: `true`) --- @field float? boolean|vim.diagnostic.Opts.Float +--- +--- Window ID +--- (default: `0`) --- @field win_id? integer --- Move to the next diagnostic. --- ----@param opts? vim.diagnostic.GotoOpts (table) Configuration table with the following keys: ---- - namespace: (integer) Only consider diagnostics from the given namespace. ---- - cursor_position: (cursor position) Cursor position as a (row, col) tuple. ---- See |nvim_win_get_cursor()|. Defaults to the current cursor position. ---- - wrap: (boolean, default true) Whether to loop around file or not. Similar to 'wrapscan'. ---- - severity: See |diagnostic-severity|. ---- - float: (boolean or table, default true) If "true", call |vim.diagnostic.open_float()| ---- after moving. If a table, pass the table as the {opts} parameter ---- to |vim.diagnostic.open_float()|. Unless overridden, the float will show ---- diagnostics at the new cursor position (as if "cursor" were passed to ---- the "scope" option). ---- - win_id: (number, default 0) Window ID +---@param opts? vim.diagnostic.GotoOpts function M.goto_next(opts) diagnostic_move_pos(opts, M.get_next_pos(opts)) end @@ -1789,38 +1836,54 @@ function M.reset(namespace, bufnr) end end +--- Configuration table with the following keys: --- @class vim.diagnostic.setqflist.Opts +--- @inlinedoc +--- +--- Only add diagnostics from the given namespace. --- @field namespace? integer +--- +--- Open quickfix list after setting. +--- (default: `true`) --- @field open? boolean +--- +--- Title of quickfix list. Defaults to "Diagnostics". --- @field title? string +--- +--- See |diagnostic-severity|. --- @field severity? vim.diagnostic.Severity --- Add all diagnostics to the quickfix list. --- ----@param opts? vim.diagnostic.setqflist.Opts (table) Configuration table with the following keys: ---- - namespace: (number) Only add diagnostics from the given namespace. ---- - open: (boolean, default true) Open quickfix list after setting. ---- - title: (string) Title of quickfix list. Defaults to "Diagnostics". ---- - severity: See |diagnostic-severity|. +---@param opts? vim.diagnostic.setqflist.Opts function M.setqflist(opts) set_list(false, opts) end +---Configuration table with the following keys: --- @class vim.diagnostic.setloclist.Opts +--- @inlinedoc +--- +--- Only add diagnostics from the given namespace. --- @field namespace? integer +--- +--- Window number to set location list for. +--- (default: `0`) +--- @field winnr? integer +--- +--- Open the location list after setting. +--- (default: `true`) --- @field open? boolean +--- +--- Title of the location list. Defaults to "Diagnostics". --- @field title? string +--- +--- See |diagnostic-severity|. --- @field severity? vim.diagnostic.Severity ---- @field winnr? integer --- Add buffer diagnostics to the location list. --- ----@param opts? vim.diagnostic.setloclist.Opts (table) Configuration table with the following keys: ---- - namespace: (number) Only add diagnostics from the given namespace. ---- - winnr: (number, default 0) Window number to set location list for. ---- - open: (boolean, default true) Open the location list after setting. ---- - title: (string) Title of the location list. Defaults to "Diagnostics". ---- - severity: See |diagnostic-severity|. +---@param opts? vim.diagnostic.setloclist.Opts function M.setloclist(opts) set_list(true, opts) end diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index e7971d8916..fba76f93b2 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -2082,6 +2082,7 @@ local function normalize_path(path, as_pattern) end --- @class vim.filetype.add.filetypes +--- @inlinedoc --- @field pattern? vim.filetype.mapping --- @field extension? vim.filetype.mapping --- @field filename? vim.filetype.mapping @@ -2170,7 +2171,7 @@ end --- } --- ``` --- ----@param filetypes vim.filetype.add.filetypes (table) A table containing new filetype maps (see example). +---@param filetypes vim.filetype.add.filetypes A table containing new filetype maps (see example). function M.add(filetypes) for k, v in pairs(filetypes.extension or {}) do extension[k] = v @@ -2272,8 +2273,23 @@ local function match_pattern(name, path, tail, pat) end --- @class vim.filetype.match.args +--- @inlinedoc +--- +--- Buffer number to use for matching. Mutually exclusive with {contents} --- @field buf? integer +--- +--- Filename to use for matching. When {buf} is given, +--- defaults to the filename of the given buffer number. The +--- file need not actually exist in the filesystem. When used +--- without {buf} only the name of the file is used for +--- filetype matching. This may result in failure to detect +--- the filetype in cases where the filename alone is not +--- enough to disambiguate the filetype. --- @field filename? string +--- +--- An array of lines representing file contents to use for +--- matching. Can be used with {filename}. Mutually exclusive +--- with {buf}. --- @field contents? string[] --- Perform filetype detection. @@ -2305,20 +2321,8 @@ end --- vim.filetype.match({ contents = {'#!/usr/bin/env bash'} }) --- ``` --- ----@param args vim.filetype.match.args (table) Table specifying which matching strategy to use. +---@param args vim.filetype.match.args Table specifying which matching strategy to use. --- Accepted keys are: ---- * buf (number): Buffer number to use for matching. Mutually exclusive with ---- {contents} ---- * filename (string): Filename to use for matching. When {buf} is given, ---- defaults to the filename of the given buffer number. The ---- file need not actually exist in the filesystem. When used ---- without {buf} only the name of the file is used for ---- filetype matching. This may result in failure to detect ---- the filetype in cases where the filename alone is not ---- enough to disambiguate the filetype. ---- * contents (table): An array of lines representing file contents to use for ---- matching. Can be used with {filename}. Mutually exclusive ---- with {buf}. ---@return string|nil # If a match was found, the matched filetype. ---@return function|nil # A function that modifies buffer state when called (for example, to set some --- filetype specific buffer variables). The function accepts a buffer number as diff --git a/runtime/lua/vim/fs.lua b/runtime/lua/vim/fs.lua index 0af5fc4f30..a47b35e991 100644 --- a/runtime/lua/vim/fs.lua +++ b/runtime/lua/vim/fs.lua @@ -147,11 +147,29 @@ function M.dir(path, opts) end) end ---- @class vim.fs.find.opts +--- @class vim.fs.find.Opts +--- @inlinedoc +--- +--- Path to begin searching from. If +--- omitted, the |current-directory| is used. --- @field path string +--- +--- Search upward through parent directories. +--- Otherwise, search through child directories (recursively). +--- (default: `false`) --- @field upward boolean +--- +--- Stop searching when this directory is reached. +--- The directory itself is not searched. --- @field stop string +--- +--- Find only items of the given type. +--- If omitted, all items that match {names} are included. --- @field type string +--- +--- Stop the search after finding this many matches. +--- Use `math.huge` to place no limit on the number of matches. +--- (default: `1`) --- @field limit number --- Find files or directories (or other items as specified by `opts.type`) in the given path. @@ -194,23 +212,10 @@ end --- - path: full path of the current item --- The function should return `true` if the given item is considered a match. --- ----@param opts (table) Optional keyword arguments: ---- - path (string): Path to begin searching from. If ---- omitted, the |current-directory| is used. ---- - upward (boolean, default false): If true, search ---- upward through parent directories. Otherwise, ---- search through child directories ---- (recursively). ---- - stop (string): Stop searching when this directory is ---- reached. The directory itself is not searched. ---- - type (string): Find only items of the given type. ---- If omitted, all items that match {names} are included. ---- - limit (number, default 1): Stop the search after ---- finding this many matches. Use `math.huge` to ---- place no limit on the number of matches. +---@param opts vim.fs.find.Opts Optional keyword arguments: ---@return (string[]) # Normalized paths |vim.fs.normalize()| of all matching items function M.find(names, opts) - opts = opts or {} --[[@as vim.fs.find.opts]] + opts = opts or {} vim.validate({ names = { names, { 's', 't', 'f' } }, path = { opts.path, 's', true }, @@ -318,6 +323,13 @@ function M.find(names, opts) return matches end +--- @class vim.fs.normalize.Opts +--- @inlinedoc +--- +--- Expand environment variables. +--- (default: `true`) +--- @field expand_env boolean + --- Normalize a path to a standard format. A tilde (~) character at the --- beginning of the path is expanded to the user's home directory and any --- backslash (\) characters are converted to forward slashes (/). Environment @@ -337,9 +349,8 @@ end --- ``` --- ---@param path (string) Path to normalize ----@param opts table|nil Options: ---- - expand_env: boolean Expand environment variables (default: true) ----@return (string) Normalized path +---@param opts? vim.fs.normalize.Opts +---@return (string) : Normalized path function M.normalize(path, opts) opts = opts or {} diff --git a/runtime/lua/vim/iter.lua b/runtime/lua/vim/iter.lua index 798428014d..09de969b5b 100644 --- a/runtime/lua/vim/iter.lua +++ b/runtime/lua/vim/iter.lua @@ -64,11 +64,13 @@ --- In addition to the |vim.iter()| function, the |vim.iter| module provides --- convenience functions like |vim.iter.filter()| and |vim.iter.totable()|. +---@nodoc ---@class IterMod ---@operator call:Iter local M = {} +---@nodoc ---@class Iter local Iter = {} Iter.__index = Iter @@ -77,6 +79,7 @@ Iter.__call = function(self) end --- Special case implementations for iterators on list tables. +---@nodoc ---@class ListIter : Iter ---@field _table table Underlying table data ---@field _head number Index to the front of a table iterator diff --git a/runtime/lua/vim/loader.lua b/runtime/lua/vim/loader.lua index 5f3da55544..0d708ca1eb 100644 --- a/runtime/lua/vim/loader.lua +++ b/runtime/lua/vim/loader.lua @@ -10,16 +10,37 @@ local M = {} ---@alias CacheHash {mtime: {nsec: integer, sec: integer}, size: integer, type?: uv.aliases.fs_stat_types} ---@alias CacheEntry {hash:CacheHash, chunk:string} ----@class ModuleFindOpts ----@field all? boolean Search for all matches (defaults to `false`) ----@field rtp? boolean Search for modname in the runtime path (defaults to `true`) ----@field patterns? string[] Patterns to use (defaults to `{"/init.lua", ".lua"}`) ----@field paths? string[] Extra paths to search for modname - ----@class ModuleInfo ----@field modpath string Path of the module ----@field modname string Name of the module ----@field stat? uv.uv_fs_t File stat of the module path +--- @class vim.loader.find.Opts +--- @inlinedoc +--- +--- Search for modname in the runtime path. +--- (default: `true`) +--- @field rtp? boolean +--- +--- Extra paths to search for modname +--- (default: `{}`) +--- @field paths? string[] +--- +--- List of patterns to use when searching for modules. +--- A pattern is a string added to the basename of the Lua module being searched. +--- (default: `{"/init.lua", ".lua"}`) +--- @field patterns? string[] +--- +--- Search for all matches. +--- (default: `false`) +--- @field all? boolean + +--- @class vim.loader.ModuleInfo +--- @inlinedoc +--- +--- Path of the module +--- @field modpath string +--- +--- Name of the module +--- @field modname string +--- +--- The fs_stat of the module path. Won't be returned for `modname="*"` +--- @field stat? uv.uv_fs_t ---@alias LoaderStats table<string, {total:number, time:number, [string]:number?}?> @@ -29,14 +50,14 @@ M.path = vim.fn.stdpath('cache') .. '/luac' ---@nodoc M.enabled = false ----@class Loader ----@field _rtp string[] ----@field _rtp_pure string[] ----@field _rtp_key string ----@field _hashes? table<string, CacheHash> +---@class (private) Loader +---@field private _rtp string[] +---@field private _rtp_pure string[] +---@field private _rtp_key string +---@field private _hashes? table<string, CacheHash> local Loader = { VERSION = 4, - ---@type table<string, table<string,ModuleInfo>> + ---@type table<string, table<string,vim.loader.ModuleInfo>> _indexed = {}, ---@type table<string, string[]> _topmods = {}, @@ -270,17 +291,8 @@ end --- Finds Lua modules for the given module name. ---@param modname string Module name, or `"*"` to find the top-level modules instead ----@param opts? ModuleFindOpts (table) Options for finding a module: ---- - rtp: (boolean) Search for modname in the runtime path (defaults to `true`) ---- - paths: (string[]) Extra paths to search for modname (defaults to `{}`) ---- - patterns: (string[]) List of patterns to use when searching for modules. ---- A pattern is a string added to the basename of the Lua module being searched. ---- (defaults to `{"/init.lua", ".lua"}`) ---- - all: (boolean) Return all matches instead of just the first one (defaults to `false`) ----@return ModuleInfo[] (table) A list of results with the following properties: ---- - modpath: (string) the path to the module ---- - modname: (string) the name of the module ---- - stat: (table|nil) the fs_stat of the module path. Won't be returned for `modname="*"` +---@param opts? vim.loader.find.Opts Options for finding a module: +---@return vim.loader.ModuleInfo[] function M.find(modname, opts) opts = opts or {} @@ -306,7 +318,7 @@ function M.find(modname, opts) patterns[p] = '/lua/' .. basename .. pattern end - ---@type ModuleInfo[] + ---@type vim.loader.ModuleInfo[] local results = {} -- Only continue if we haven't found anything yet or we want to find all @@ -472,12 +484,12 @@ function Loader.track(stat, f) end end ----@class ProfileOpts +---@class (private) vim.loader._profile.Opts ---@field loaders? boolean Add profiling to the loaders --- Debug function that wraps all loaders and tracks stats ---@private ----@param opts ProfileOpts? +---@param opts vim.loader._profile.Opts? function M._profile(opts) Loader.get_rtp = Loader.track('get_rtp', Loader.get_rtp) Loader.read = Loader.track('read', Loader.read) diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index 19497e40dc..8ebf4de3cb 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -108,12 +108,12 @@ function lsp._buf_get_line_ending(bufnr) end -- Tracks all clients created via lsp.start_client -local active_clients = {} --- @type table<integer,lsp.Client> +local active_clients = {} --- @type table<integer,vim.lsp.Client> local all_buffer_active_clients = {} --- @type table<integer,table<integer,true>> -local uninitialized_clients = {} --- @type table<integer,lsp.Client> +local uninitialized_clients = {} --- @type table<integer,vim.lsp.Client> ---@param bufnr? integer ----@param fn fun(client: lsp.Client, client_id: integer, bufnr: integer) +---@param fn fun(client: vim.lsp.Client, client_id: integer, bufnr: integer) local function for_each_buffer_client(bufnr, fn, restrict_client_ids) validate({ fn = { fn, 'f' }, @@ -200,105 +200,15 @@ local function once(fn) end end --- FIXME: DOC: Shouldn't need to use a dummy function --- ---- LSP client object. You can get an active client object via ---- |vim.lsp.get_client_by_id()| or |vim.lsp.get_clients()|. +--- @class vim.lsp.start.Opts +--- @inlinedoc --- ---- - Methods: ---- - request(method, params, [handler], bufnr) ---- Sends a request to the server. ---- This is a thin wrapper around {client.rpc.request} with some additional ---- checking. ---- If {handler} is not specified, If one is not found there, 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. +--- Predicate used to decide if a client should be re-used. Used on all +--- running clients. The default implementation re-uses a client if name and +--- root_dir matches. +--- @field reuse_client fun(client: vim.lsp.Client, config: table): boolean --- ---- - request_sync(method, params, timeout_ms, bufnr) ---- Sends a request to the server and synchronously waits for the response. ---- This is a wrapper around {client.request} ---- 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`. ---- ---- - notify(method, params) ---- Sends a notification to an LSP server. ---- Returns: a boolean to indicate if the notification was successful. If ---- it is false, then it will always be false (the client has shutdown). ---- ---- - cancel_request(id) ---- Cancels a request with a given request id. ---- Returns: same as `notify()`. ---- ---- - stop([force]) ---- 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. ---- ---- - is_stopped() ---- Checks whether a client is stopped. ---- Returns: true if the client is fully stopped. ---- ---- - on_attach(client, bufnr) ---- Runs the on_attach function from the client's config if it was defined. ---- Useful for buffer-local setup. ---- ---- - supports_method(method, [opts]): boolean ---- Checks if a client supports a given method. ---- Always returns true for unknown off-spec methods. ---- [opts] is a optional `{bufnr?: integer}` table. ---- Some language server capabilities can be file specific. ---- ---- - Members ---- - {id} (number): The id allocated to the client. ---- ---- - {name} (string): 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. ---- ---- - {rpc} (table): RPC client object, for low level interaction with the ---- client. See |vim.lsp.rpc.start()|. ---- ---- - {offset_encoding} (string): 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. ---- ---- - {handlers} (table): The handlers used by the client as described in |lsp-handler|. ---- ---- - {commands} (table): 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. ---- ---- - {requests} (table): 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. ---- ---- - {config} (table): Reference of the table that was passed by the user ---- to |vim.lsp.start_client()|. ---- ---- - {server_capabilities} (table): Response from the server sent on ---- `initialize` describing the server's capabilities. ---- ---- - {progress} A ring buffer (|vim.ringbuf()|) containing progress messages ---- sent by the server. ---- ---- - {settings} Map with language server specific settings. ---- See {config} in |vim.lsp.start_client()| ---- ---- - {flags} A table with flags for the client. See {config} in |vim.lsp.start_client()| -lsp.client = nil - ---- @class lsp.StartOpts ---- @field reuse_client fun(client: lsp.Client, config: table): boolean +--- Buffer handle to attach to if starting or re-using a client (0 for current). --- @field bufnr integer --- Create a new LSP client and start a language server or reuses an already @@ -337,17 +247,9 @@ lsp.client = nil --- Either use |:au|, |nvim_create_autocmd()| or put the call in a --- `ftplugin/<filetype_name>.lua` (See |ftplugin-name|) --- ----@param config lsp.ClientConfig Same configuration as documented in |vim.lsp.start_client()| ----@param opts lsp.StartOpts? Optional keyword arguments: ---- - reuse_client (fun(client: client, config: table): boolean) ---- Predicate used to decide if a client should be re-used. ---- Used on all running clients. ---- The default implementation re-uses a client if name ---- and root_dir matches. ---- - bufnr (number) ---- Buffer handle to attach to if starting or re-using a ---- client (0 for current). ----@return integer? client_id +--- @param config vim.lsp.ClientConfig Configuration for the server. +--- @param opts vim.lsp.start.Opts? Optional keyword arguments +--- @return integer? client_id function lsp.start(config, opts) opts = opts or {} local reuse_client = opts.reuse_client @@ -428,7 +330,7 @@ local function is_empty_or_default(bufnr, option) end ---@private ----@param client lsp.Client +---@param client vim.lsp.Client ---@param bufnr integer function lsp._set_defaults(client, bufnr) if @@ -482,7 +384,7 @@ local function reset_defaults(bufnr) end) end ---- @param client lsp.Client +--- @param client vim.lsp.Client local function on_client_init(client) local id = client.id uninitialized_clients[id] = nil @@ -552,121 +454,9 @@ local function on_client_exit(code, signal, client_id) end) end --- FIXME: DOC: Currently all methods on the `vim.lsp.client` object are --- documented twice: Here, and on the methods themselves (e.g. --- `client.request()`). This is a workaround for the vimdoc generator script --- not handling method names correctly. If you change the documentation on --- either, please make sure to update the other as well. --- --- Starts and initializes a client with the given configuration. ---- ---- Field `cmd` in {config} is required. ---- ----@param config (lsp.ClientConfig) Configuration for the server: ---- - cmd: (string[]|fun(dispatchers: table):table) 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()| ---- ---- - cmd_cwd: (string, default=|getcwd()|) Directory to launch ---- the `cmd` process. Not related to `root_dir`. ---- ---- - cmd_env: (table) Environment flags to pass to the LSP on ---- spawn. Must be specified using a table. ---- Non-string values are coerced to string. ---- Example: ---- ``` ---- { PORT = 8080; HOST = "0.0.0.0"; } ---- ``` ---- ---- - detached: (boolean, default true) 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. ---- ---- - workspace_folders: (table) 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. ---- ---- - capabilities: 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. ---- ---- - handlers: Map of language server method names to |lsp-handler| ---- ---- - settings: Map with language server specific settings. These are ---- returned to the language server if requested via `workspace/configuration`. ---- Keys are case-sensitive. ---- ---- - commands: 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. ---- ---- - init_options Values to pass in the initialization request ---- as `initializationOptions`. See `initialize` in the LSP spec. ---- ---- - name: (string, default=client-id) Name in log messages. ---- ---- - get_language_id: function(bufnr, filetype) -> language ID as string. ---- Defaults to the filetype. ---- ---- - offset_encoding: (default="utf-16") One of "utf-8", "utf-16", ---- or "utf-32" which is the encoding that the LSP server expects. Client does ---- not verify this is correct. ---- ---- - on_error: Callback with parameters (code, ...), 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. ---- ---- - before_init: Callback with parameters (initialize_params, config) ---- 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. ---- ---- - on_init: Callback (client, initialize_result) 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. ---- ---- - on_exit Callback (code, signal, client_id) invoked on client ---- exit. ---- - code: exit code of the process ---- - signal: number describing the signal used to terminate (if any) ---- - client_id: client handle ---- ---- - on_attach: Callback (client, bufnr) invoked when client ---- attaches to a buffer. ---- ---- - trace: ("off" | "messages" | "verbose" | nil) passed directly to the language ---- server in the initialize request. Invalid/empty values will default to "off" ---- ---- - flags: A table with flags for the client. The current (experimental) flags are: ---- - allow_incremental_sync (bool, default true): Allow using incremental sync for buffer edits ---- - debounce_text_changes (number, default 150): Debounce didChange ---- notifications to the server by the given number in milliseconds. No debounce ---- occurs if nil ---- - exit_timeout (number|boolean, default false): 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. ---- ---- - root_dir: (string) Directory where the LSP ---- server will base its workspaceFolders, rootUri, and rootPath ---- on initialization. ---- ----@return integer|nil client_id. |vim.lsp.get_client_by_id()| Note: client may not be +--- @param config vim.lsp.ClientConfig Configuration for the server. +--- @return integer|nil client_id |vim.lsp.get_client_by_id()| Note: client may not be --- fully initialized. Use `on_init` to do any actions once --- the client has been initialized. function lsp.start_client(config) @@ -927,7 +717,7 @@ end --- ---@param client_id integer client id --- ----@return (nil|lsp.Client) client rpc object +---@return (nil|vim.lsp.Client) client rpc object function lsp.get_client_by_id(client_id) return active_clients[client_id] or uninitialized_clients[client_id] end @@ -943,7 +733,7 @@ end --- Stops a client(s). --- ---- You can also use the `stop()` function on a |vim.lsp.client| object. +--- You can also use the `stop()` function on a |vim.lsp.Client| object. --- To stop all clients: --- --- ```lua @@ -953,7 +743,7 @@ end --- By default asks the server to shutdown, unless stop was requested --- already for this client, then force-shutdown is attempted. --- ----@param client_id integer|table id or |vim.lsp.client| object, or list thereof +---@param client_id integer|vim.lsp.Client id or |vim.lsp.Client| object, or list thereof ---@param force boolean|nil shutdown forcefully function lsp.stop_client(client_id, force) local ids = type(client_id) == 'table' and client_id or { client_id } @@ -968,28 +758,32 @@ function lsp.stop_client(client_id, force) end end ----@class vim.lsp.get_clients.filter ----@field id integer|nil Match clients by id ----@field bufnr integer|nil match clients attached to the given buffer ----@field name string|nil match clients by name ----@field method string|nil match client by supported method name +--- Key-value pairs used to filter the returned clients. +--- @class vim.lsp.get_clients.Filter +--- @inlinedoc +--- +--- Only return clients with the given id +--- @field id? integer +--- +--- Only return clients attached to this buffer +--- @field bufnr? integer +--- +--- Only return clients with the given name +--- @field name? string +--- +--- Only return clients supporting the given method +--- @field method? string --- Get active clients. --- ----@param filter vim.lsp.get_clients.filter|nil (table|nil) A table with ---- key-value pairs used to filter the returned clients. ---- The available keys are: ---- - id (number): Only return clients with the given id ---- - bufnr (number): Only return clients attached to this buffer ---- - name (string): Only return clients with the given name ---- - method (string): Only return clients supporting the given method ----@return lsp.Client[]: List of |vim.lsp.client| objects +---@param filter? vim.lsp.get_clients.Filter +---@return vim.lsp.Client[]: List of |vim.lsp.Client| objects function lsp.get_clients(filter) validate({ filter = { filter, 't', true } }) filter = filter or {} - local clients = {} --- @type lsp.Client[] + local clients = {} --- @type vim.lsp.Client[] local t = filter.bufnr and (all_buffer_active_clients[resolve_bufnr(filter.bufnr)] or {}) or active_clients @@ -1233,15 +1027,20 @@ function lsp.omnifunc(findstart, base) return vim.lsp._completion.omnifunc(findstart, base) end +--- @class vim.lsp.formatexpr.Opts +--- @inlinedoc +--- +--- The timeout period for the formatting request. +--- (default: 500ms). +--- @field timeout_ms integer + --- Provides an interface between the built-in client and a `formatexpr` function. --- --- Currently only supports a single client. This can be set via --- `setlocal formatexpr=v:lua.vim.lsp.formatexpr()` but will typically or in `on_attach` --- via `vim.bo[bufnr].formatexpr = 'v:lua.vim.lsp.formatexpr(#{timeout_ms:250})'`. --- ----@param opts table options for customizing the formatting expression which takes the ---- following optional keys: ---- * timeout_ms (default 500ms). The timeout period for the formatting request. +---@param opts? vim.lsp.formatexpr.Opts function lsp.formatexpr(opts) opts = opts or {} local timeout_ms = opts.timeout_ms or 500 @@ -1313,14 +1112,14 @@ function lsp.client_is_stopped(client_id) end --- Gets a map of client_id:client pairs for the given buffer, where each value ---- is a |vim.lsp.client| object. +--- is a |vim.lsp.Client| object. --- ---@param bufnr (integer|nil): Buffer handle, or 0 for current ---@return table result is table of (client_id, client) pairs ---@deprecated Use |vim.lsp.get_clients()| instead. function lsp.buf_get_clients(bufnr) vim.deprecate('vim.lsp.buf_get_clients()', 'vim.lsp.get_clients()', '0.12') - local result = {} --- @type table<integer,lsp.Client> + local result = {} --- @type table<integer,vim.lsp.Client> for _, client in ipairs(lsp.get_clients({ bufnr = resolve_bufnr(bufnr) })) do result[client.id] = client end diff --git a/runtime/lua/vim/lsp/_changetracking.lua b/runtime/lua/vim/lsp/_changetracking.lua index 3ecdec1659..b2be53269f 100644 --- a/runtime/lua/vim/lsp/_changetracking.lua +++ b/runtime/lua/vim/lsp/_changetracking.lua @@ -61,7 +61,7 @@ local state_by_group = setmetatable({}, { end, }) ----@param client lsp.Client +---@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 @@ -127,7 +127,7 @@ local function incremental_changes(state, encoding, bufnr, firstline, lastline, return incremental_change end ----@param client lsp.Client +---@param client vim.lsp.Client ---@param bufnr integer function M.init(client, bufnr) assert(client.offset_encoding, 'lsp client must have an offset_encoding') @@ -165,7 +165,7 @@ function M.init(client, bufnr) end end ---- @param client lsp.Client +--- @param client vim.lsp.Client --- @param bufnr integer --- @param name string --- @return string @@ -189,7 +189,7 @@ local function reset_timer(buf_state) end end ---- @param client lsp.Client +--- @param client vim.lsp.Client --- @param bufnr integer function M.reset_buf(client, bufnr) M.flush(client, bufnr) @@ -207,7 +207,7 @@ function M.reset_buf(client, bufnr) end end ---- @param client lsp.Client +--- @param client vim.lsp.Client function M.reset(client) local state = state_by_group[get_group(client)] if not state then @@ -350,7 +350,7 @@ function M.send_changes(bufnr, firstline, lastline, new_lastline) end --- Flushes any outstanding change notification. ----@param client lsp.Client +---@param client vim.lsp.Client ---@param bufnr? integer function M.flush(client, bufnr) local group = get_group(client) diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua index d2e92de083..377c8680c7 100644 --- a/runtime/lua/vim/lsp/buf.lua +++ b/runtime/lua/vim/lsp/buf.lua @@ -11,7 +11,7 @@ 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. @@ -31,7 +31,7 @@ end --- Checks whether the language servers attached to the current buffer are --- ready. --- ----@return boolean if server responds. +---@return boolean : if server responds. ---@deprecated function M.server_ready() vim.deprecate('vim.lsp.buf.server_ready()', nil, '0.10') @@ -57,35 +57,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 +--- +--- 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 --- ----@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. +--- 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 +115,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,45 +175,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: ---- ```lua ---- -- Never request typescript-language-server for formatting ---- vim.lsp.buf.format { ---- filter = function(client) return client.name ~= "tsserver" end ---- } ---- ``` ---- ---- - 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() @@ -229,8 +258,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 @@ -256,17 +284,22 @@ 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 + --- 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() @@ -386,8 +419,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() @@ -398,14 +430,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 @@ -425,8 +456,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) @@ -545,9 +578,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 @@ -582,16 +614,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. @@ -602,7 +654,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) @@ -647,14 +699,15 @@ 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 + 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 @@ -676,7 +729,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') @@ -726,29 +778,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) @@ -814,9 +844,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 index c1b41a7183..fcbaadbc57 100644 --- a/runtime/lua/vim/lsp/client.lua +++ b/runtime/lua/vim/lsp/client.lua @@ -6,38 +6,125 @@ local ms = lsp.protocol.Methods local changetracking = lsp._changetracking local validate = vim.validate ---- @alias vim.lsp.client.on_init_cb fun(client: lsp.Client, initialize_result: lsp.InitializeResult) ---- @alias vim.lsp.client.on_attach_cb fun(client: lsp.Client, bufnr: integer) +--- @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: lsp.ClientConfig) - ---- @class lsp.ClientConfig +--- @alias vim.lsp.client.before_init_cb fun(params: lsp.InitializeParams, config: vim.lsp.ClientConfig) + +--- @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. These are returned to the language server if +--- requested via `workspace/configuration`. Keys are case-sensitive. --- @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 ---- @field offset_encoding? 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? vim.lsp.client.before_init_cb +--- +--- 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<vim.lsp.client.on_init_cb> +--- +--- 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<vim.lsp.client.on_exit_cb> +--- +--- Callback invoked when client attaches to a buffer. --- @field on_attach? elem_or_list<vim.lsp.client.on_attach_cb> +--- +--- 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: +--- - allow_incremental_sync (bool, default true): Allow using incremental sync for buffer edits +--- - debounce_text_changes (number, default 150): Debounce didChange +--- notifications to the server by the given number in milliseconds. No debounce +--- occurs if nil +--- - exit_timeout (number|boolean, default false): 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. --- @field flags? table +--- +--- Directory where the LSP server will base its workspaceFolders, rootUri, and rootPath on initialization. --- @field root_dir? string ---- @class lsp.Client.Progress: vim.Ringbuf<{token: integer|string, value: any}> +--- @class vim.lsp.Client.Progress: vim.Ringbuf<{token: integer|string, value: any}> --- @field pending table<lsp.ProgressToken,lsp.LSPAny> ---- @class lsp.Client +--- @class vim.lsp.Client --- --- The id allocated to the client. --- @field id integer @@ -67,7 +154,7 @@ local validate = vim.validate --- --- copy of the table that was passed by the user --- to |vim.lsp.start_client()|. ---- @field config lsp.ClientConfig +--- @field config vim.lsp.ClientConfig --- --- Response from the server sent on --- initialize` describing the server's capabilities. @@ -75,7 +162,7 @@ local validate = vim.validate --- --- A ring buffer (|vim.ringbuf()|) containing progress messages --- sent by the server. ---- @field progress lsp.Client.Progress +--- @field progress vim.lsp.Client.Progress --- --- @field initialized true? --- @@ -239,7 +326,7 @@ local function default_get_language_id(_bufnr, filetype) end --- Validates a client configuration as given to |vim.lsp.start_client()|. ---- @param config lsp.ClientConfig +--- @param config vim.lsp.ClientConfig local function validate_config(config) validate({ config = { config, 't' }, @@ -285,7 +372,7 @@ local function get_trace(trace) end --- @param id integer ---- @param config lsp.ClientConfig +--- @param config vim.lsp.ClientConfig --- @return string local function get_name(id, config) local name = config.name @@ -328,8 +415,8 @@ local function ensure_list(x) end --- @package ---- @param config lsp.ClientConfig ---- @return lsp.Client? +--- @param config vim.lsp.ClientConfig +--- @return vim.lsp.Client? function Client.create(config) validate_config(config) @@ -337,7 +424,7 @@ function Client.create(config) local id = client_index local name = get_name(id, config) - --- @class lsp.Client + --- @class vim.lsp.Client local self = { id = id, config = config, @@ -370,7 +457,7 @@ function Client.create(config) --- - lsp.WorkDoneProgressBegin, --- - lsp.WorkDoneProgressReport (extended with title from Begin) --- - lsp.WorkDoneProgressEnd (extended with title from Begin) - progress = vim.ringbuf(50) --[[@as lsp.Client.Progress]], + progress = vim.ringbuf(50) --[[@as vim.lsp.Client.Progress]], --- @deprecated use client.progress instead messages = { name = name, messages = {}, progress = {}, status = {} }, @@ -421,6 +508,7 @@ function Client.create(config) return self end +--- @private --- @param cbs function[] --- @param error_id integer --- @param ... any @@ -698,7 +786,7 @@ function Client:_cancel_request(id) return self.rpc.notify(ms.dollar_cancelRequest, { id = id }) end ---- @nodoc +--- @private --- Stops a client, optionally with force. --- --- By default, it will just ask the - server to shutdown without force. If @@ -853,6 +941,7 @@ function Client:write_error(code, 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) diff --git a/runtime/lua/vim/lsp/codelens.lua b/runtime/lua/vim/lsp/codelens.lua index 7aed6f99e3..48c096c0c1 100644 --- a/runtime/lua/vim/lsp/codelens.lua +++ b/runtime/lua/vim/lsp/codelens.lua @@ -279,7 +279,8 @@ function M.on_codelens(err, result, ctx, _) end) end ---- @class vim.lsp.codelens.RefreshOptions +--- @class vim.lsp.codelens.refresh.Opts +--- @inlinedoc --- @field bufnr integer? filter by buffer. All buffers if nil, 0 for current buffer --- Refresh the lenses. @@ -292,8 +293,7 @@ end --- autocmd BufEnter,CursorHold,InsertLeave <buffer> lua vim.lsp.codelens.refresh({ bufnr = 0 }) --- ``` --- ---- @param opts? vim.lsp.codelens.RefreshOptions Table with the following fields: ---- - `bufnr` (integer|nil): filter by buffer. All buffers if nil, 0 for current buffer +--- @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) diff --git a/runtime/lua/vim/lsp/diagnostic.lua b/runtime/lua/vim/lsp/diagnostic.lua index 1fa67fc473..6156821093 100644 --- a/runtime/lua/vim/lsp/diagnostic.lua +++ b/runtime/lua/vim/lsp/diagnostic.lua @@ -390,7 +390,7 @@ 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 = {} diff --git a/runtime/lua/vim/lsp/handlers.lua b/runtime/lua/vim/lsp/handlers.lua index 781d720486..d816fb1482 100644 --- a/runtime/lua/vim/lsp/handlers.lua +++ b/runtime/lua/vim/lsp/handlers.lua @@ -412,6 +412,7 @@ M[ms.textDocument_hover] = M.hover ---@param _ nil not used ---@param result (table) result of LSP method; a location or a list of locations. ---@param ctx (lsp.HandlerContext) table containing the context of the request, including the method +---@param config? vim.lsp.buf.LocationOpts ---(`textDocument/definition` can return `Location` or `Location[]` local function location_handler(_, result, ctx, config) if result == nil or vim.tbl_isempty(result) then diff --git a/runtime/lua/vim/lsp/inlay_hint.lua b/runtime/lua/vim/lsp/inlay_hint.lua index 49dc35fdf6..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_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') @@ -103,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 @@ -130,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 } }) @@ -241,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? lsp.util.RefreshOptions 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 {} diff --git a/runtime/lua/vim/lsp/rpc.lua b/runtime/lua/vim/lsp/rpc.lua index e52c06a1bd..8e014b1063 100644 --- a/runtime/lua/vim/lsp/rpc.lua +++ b/runtime/lua/vim/lsp/rpc.lua @@ -26,7 +26,7 @@ local function format_message_with_content_length(message) }) end ----@class vim.lsp.rpc.Headers: {string: any} +---@class (private) vim.lsp.rpc.Headers: {string: any} ---@field content_length integer --- Parses an LSP Message's header @@ -193,7 +193,9 @@ function M.rpc_response_error(code, message, data) }) 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) @@ -266,8 +268,7 @@ function M.create_read_loop(handle_body, on_no_chunk, on_error) end end ----@private ----@class vim.lsp.rpc.Client +---@class (private) vim.lsp.rpc.Client ---@field message_index integer ---@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 @@ -522,7 +523,7 @@ function Client:handle_body(body) end end ----@class vim.lsp.rpc.Transport +---@class (private) vim.lsp.rpc.Transport ---@field write fun(msg: string) ---@field is_closing fun(): boolean ---@field terminate fun() @@ -721,32 +722,21 @@ function M.domain_socket_connect(pipe_path) end end ----@class vim.lsp.rpc.ExtraSpawnParams ----@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| +--- 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 dispatchers? vim.lsp.rpc.Dispatchers Dispatchers for LSP message types. ---- Valid dispatcher names are: ---- - `"notification"` ---- - `"server_request"` ---- - `"on_error"` ---- - `"on_exit"` ---- ----@param extra_spawn_params? vim.lsp.rpc.ExtraSpawnParams Additional context for the LSP ---- server process. May contain: ---- - {cwd} (string) Working directory for the LSP server process ---- - {detached?} (boolean) Detach the LSP server process from the current process. ---- Defaults to false on Windows and true otherwise. ---- - {env?} (table) Additional environment variables for LSP server process ---- ----@return vim.lsp.rpc.PublicClient? Client RPC object, with these methods: +--- @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. diff --git a/runtime/lua/vim/lsp/semantic_tokens.lua b/runtime/lua/vim/lsp/semantic_tokens.lua index fe8638bdfa..92546e8520 100644 --- a/runtime/lua/vim/lsp/semantic_tokens.lua +++ b/runtime/lua/vim/lsp/semantic_tokens.lua @@ -4,7 +4,7 @@ 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 @@ -12,23 +12,23 @@ local uv = vim.uv --- @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 +--- @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 @@ -92,7 +92,7 @@ end --- ---@param data integer[] ---@param bufnr integer ----@param client lsp.Client +---@param client vim.lsp.Client ---@param request STActiveRequest ---@return STTokenRange[] local function tokens_to_ranges(data, bufnr, client, request) @@ -646,6 +646,7 @@ function M.stop(bufnr, client_id) end end +--- @nodoc --- @class STTokenRangeInspect : STTokenRange --- @field client_id integer @@ -727,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 @@ -735,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 diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index 0553d39851..60d0f0cc83 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -675,13 +675,15 @@ local function get_bufs_with_prefix(prefix) return buffers end +--- @class vim.lsp.util.rename.Opts +--- @inlinedoc +--- @field overwrite? boolean +--- @field ignoreIfExists? boolean + --- Rename old_fname to new_fname ---- ----@param old_fname string ----@param new_fname string ----@param opts? table options ---- - overwrite? boolean ---- - ignoreIfExists? boolean +--- @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 skip = not opts.overwrite or opts.ignoreIfExists @@ -1450,7 +1452,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. @@ -1466,7 +1468,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) @@ -1537,7 +1539,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 @@ -1613,24 +1615,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) @@ -1794,7 +1822,8 @@ local position_sort = sort_by_key(function(v) return { v.start.line, v.start.character } end) ----@class vim.lsp.util.LocationItem +---@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 @@ -1813,7 +1842,7 @@ end) ---@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 vim.lsp.util.LocationItem[] 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( @@ -2221,16 +2250,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 diff --git a/runtime/lua/vim/secure.lua b/runtime/lua/vim/secure.lua index d29c356af3..3992eef78a 100644 --- a/runtime/lua/vim/secure.lua +++ b/runtime/lua/vim/secure.lua @@ -108,22 +108,25 @@ function M.read(path) return contents end ----@class vim.trust.opts ----@field action string ----@field path? string ----@field bufnr? integer +--- @class vim.trust.opts +--- @inlinedoc +--- +--- - `'allow'` to add a file to the trust database and trust it, +--- - `'deny'` to add a file to the trust database and deny it, +--- - `'remove'` to remove file from the trust database +--- @field action 'allow'|'deny'|'remove' +--- +--- Path to a file to update. Mutually exclusive with {bufnr}. +--- Cannot be used when {action} is "allow". +--- @field path? string +--- Buffer number to update. Mutually exclusive with {path}. +--- @field bufnr? integer --- Manage the trust database. --- --- The trust database is located at |$XDG_STATE_HOME|/nvim/trust. --- ----@param opts (table): ---- - action (string): "allow" to add a file to the trust database and trust it, ---- "deny" to add a file to the trust database and deny it, ---- "remove" to remove file from the trust database ---- - path (string|nil): Path to a file to update. Mutually exclusive with {bufnr}. ---- Cannot be used when {action} is "allow". ---- - bufnr (number|nil): Buffer number to update. Mutually exclusive with {path}. +---@param opts? vim.trust.opts ---@return boolean success true if operation was successful ---@return string msg full path if operation was successful, else error message function M.trust(opts) diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua index 83fdfede89..ec70630df3 100644 --- a/runtime/lua/vim/shared.lua +++ b/runtime/lua/vim/shared.lua @@ -65,8 +65,13 @@ function vim.deepcopy(orig, noref) end --- @class vim.gsplit.Opts ---- @field plain? boolean Use `sep` literally (as in string.find). ---- @field trimempty? boolean Discard empty segments at start and end of the sequence. +--- @inlinedoc +--- +--- Use `sep` literally (as in string.find). +--- @field plain? boolean +--- +--- Discard empty segments at start and end of the sequence. +--- @field trimempty? boolean --- Gets an |iterator| that splits a string at each instance of a separator, in "lazy" fashion --- (as opposed to |vim.split()| which is "eager"). @@ -96,10 +101,8 @@ end --- --- @param s string String to split --- @param sep string Separator or pattern ---- @param opts? vim.gsplit.Opts (table) Keyword arguments |kwargs|: ---- - plain: (boolean) Use `sep` literally (as in string.find). ---- - trimempty: (boolean) Discard empty segments at start and end of the sequence. ----@return fun():string|nil (function) Iterator over the split components +--- @param opts? vim.gsplit.Opts Keyword arguments |kwargs|: +--- @return fun():string|nil (function) Iterator over the split components function vim.gsplit(s, sep, opts) local plain --- @type boolean? local trimempty = false @@ -192,7 +195,7 @@ end --- ---@param s string String to split ---@param sep string Separator or pattern ----@param opts? table Keyword arguments |kwargs| accepted by |vim.gsplit()| +---@param opts? vim.gsplit.Opts Keyword arguments |kwargs|: ---@return string[] : List of split components function vim.split(s, sep, opts) local t = {} @@ -276,6 +279,9 @@ function vim.tbl_filter(func, t) end --- @class vim.tbl_contains.Opts +--- @inlinedoc +--- +--- `value` is a function reference to be checked (default false) --- @field predicate? boolean --- Checks if a table contains a given value, specified either directly or via @@ -294,8 +300,7 @@ end --- ---@param t table Table to check ---@param value any Value to compare or predicate function reference ----@param opts? vim.tbl_contains.Opts (table) Keyword arguments |kwargs|: ---- - predicate: (boolean) `value` is a function reference to be checked (default false) +---@param opts? vim.tbl_contains.Opts Keyword arguments |kwargs|: ---@return boolean `true` if `t` contains `value` function vim.tbl_contains(t, value, opts) vim.validate({ t = { t, 't' }, opts = { opts, 't', true } }) @@ -764,6 +769,7 @@ do ['userdata'] = 'userdata', } + --- @nodoc --- @class vim.validate.Spec {[1]: any, [2]: string|string[], [3]: boolean } --- @field [1] any Argument value --- @field [2] string|string[]|fun(v:any):boolean, string? Type name, or callable diff --git a/runtime/lua/vim/snippet.lua b/runtime/lua/vim/snippet.lua index 09b7576d97..5e60efa778 100644 --- a/runtime/lua/vim/snippet.lua +++ b/runtime/lua/vim/snippet.lua @@ -101,7 +101,7 @@ local function get_extmark_range(bufnr, extmark_id) return { mark[1], mark[2], mark[3].end_row, mark[3].end_col } end ---- @class vim.snippet.Tabstop +--- @class (private) vim.snippet.Tabstop --- @field extmark_id integer --- @field bufnr integer --- @field index integer @@ -177,7 +177,7 @@ function Tabstop:set_right_gravity(right_gravity) }) end ---- @class vim.snippet.Session +--- @class (private) vim.snippet.Session --- @field bufnr integer --- @field extmark_id integer --- @field tabstops table<integer, vim.snippet.Tabstop[]> diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index 9b69f95f54..61c5d66958 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -1,6 +1,6 @@ local api = vim.api ----@type table<integer,LanguageTree> +---@type table<integer,vim.treesitter.LanguageTree> local parsers = setmetatable({}, { __mode = 'v' }) local M = vim._defer_require('vim.treesitter', { @@ -30,7 +30,7 @@ M.minimum_language_version = vim._ts_get_minimum_language_version() ---@param lang string Language of the parser ---@param opts (table|nil) Options to pass to the created language tree --- ----@return LanguageTree object to use for parsing +---@return vim.treesitter.LanguageTree object to use for parsing function M._create_parser(bufnr, lang, opts) if bufnr == 0 then bufnr = vim.api.nvim_get_current_buf() @@ -80,7 +80,7 @@ end ---@param lang (string|nil) Filetype of this parser (default: buffer filetype) ---@param opts (table|nil) Options to pass to the created language tree --- ----@return LanguageTree object to use for parsing +---@return vim.treesitter.LanguageTree object to use for parsing function M.get_parser(bufnr, lang, opts) opts = opts or {} @@ -119,7 +119,7 @@ end ---@param lang string Language of this string ---@param opts (table|nil) Options to pass to the created language tree --- ----@return LanguageTree object to use for parsing +---@return vim.treesitter.LanguageTree object to use for parsing function M.get_string_parser(str, lang, opts) vim.validate({ str = { str, 'string' }, @@ -172,7 +172,7 @@ end ---to get the range with directives applied. ---@param node TSNode ---@param source integer|string|nil Buffer or string from which the {node} is extracted ----@param metadata TSMetadata|nil +---@param metadata vim.treesitter.query.TSMetadata|nil ---@return Range6 function M.get_range(node, source, metadata) if metadata and metadata.range then @@ -326,10 +326,21 @@ function M.get_captures_at_cursor(winnr) return captures end ---- @class vim.treesitter.GetNodeOpts +--- Optional keyword arguments: +--- @class vim.treesitter.get_node.Opts +--- @inlinedoc +--- +--- Buffer number (nil or 0 for current buffer) --- @field bufnr integer? +--- +--- 0-indexed (row, col) tuple. Defaults to cursor position in the +--- current window. Required if {bufnr} is not the current buffer --- @field pos { [1]: integer, [2]: integer }? +--- +--- Parser language. (default: from buffer filetype) --- @field lang string? +--- +--- Ignore injected languages (default true) --- @field ignore_injections boolean? --- Returns the smallest named node at the given position @@ -342,12 +353,7 @@ end --- vim.treesitter.get_parser(bufnr):parse(range) --- ``` --- ----@param opts vim.treesitter.GetNodeOpts? Optional keyword arguments: ---- - bufnr integer|nil Buffer number (nil or 0 for current buffer) ---- - pos table|nil 0-indexed (row, col) tuple. Defaults to cursor position in the ---- current window. Required if {bufnr} is not the current buffer ---- - lang string|nil Parser language. (default: from buffer filetype) ---- - ignore_injections boolean Ignore injected languages (default true) +---@param opts vim.treesitter.get_node.Opts? --- ---@return TSNode | nil Node at the given position function M.get_node(opts) diff --git a/runtime/lua/vim/treesitter/_query_linter.lua b/runtime/lua/vim/treesitter/_query_linter.lua index 6ec997eb4a..b91e8ac38d 100644 --- a/runtime/lua/vim/treesitter/_query_linter.lua +++ b/runtime/lua/vim/treesitter/_query_linter.lua @@ -45,7 +45,7 @@ local function guess_query_lang(buf) end --- @param buf integer ---- @param opts QueryLinterOpts|QueryLinterNormalizedOpts|nil +--- @param opts vim.treesitter.query.lint.Opts|QueryLinterNormalizedOpts|nil --- @return QueryLinterNormalizedOpts local function normalize_opts(buf, opts) opts = opts or {} @@ -122,7 +122,7 @@ local parse = vim.func._memoize(hash_parse, function(node, buf, lang) end) --- @param buf integer ---- @param match TSMatch +--- @param match vim.treesitter.query.TSMatch --- @param query Query --- @param lang_context QueryLinterLanguageContext --- @param diagnostics Diagnostic[] @@ -153,7 +153,7 @@ end --- @private --- @param buf integer Buffer to lint ---- @param opts QueryLinterOpts|QueryLinterNormalizedOpts|nil Options for linting +--- @param opts vim.treesitter.query.lint.Opts|QueryLinterNormalizedOpts|nil Options for linting function M.lint(buf, opts) if buf == 0 then buf = api.nvim_get_current_buf() diff --git a/runtime/lua/vim/treesitter/dev.lua b/runtime/lua/vim/treesitter/dev.lua index 4c8f6e466f..dc2a14d238 100644 --- a/runtime/lua/vim/treesitter/dev.lua +++ b/runtime/lua/vim/treesitter/dev.lua @@ -1,23 +1,21 @@ local api = vim.api ----@class TSDevModule local M = {} ----@private ----@class TSTreeView +---@class (private) vim.treesitter.dev.TSTreeView ---@field ns integer API namespace ----@field opts TSTreeViewOpts ----@field nodes TSP.Node[] ----@field named TSP.Node[] +---@field opts vim.treesitter.dev.TSTreeViewOpts +---@field nodes vim.treesitter.dev.Node[] +---@field named vim.treesitter.dev.Node[] local TSTreeView = {} ---@private ----@class TSTreeViewOpts +---@class (private) vim.treesitter.dev.TSTreeViewOpts ---@field anon boolean If true, display anonymous nodes. ---@field lang boolean If true, display the language alongside each node. ---@field indent number Number of spaces to indent nested lines. ----@class TSP.Node +---@class (private) vim.treesitter.dev.Node ---@field node TSNode Treesitter node ---@field field string? Node field ---@field depth integer Depth of this node in the tree @@ -25,7 +23,7 @@ local TSTreeView = {} --- inspector is drawn. ---@field lang string Source language of this node ----@class TSP.Injection +---@class (private) vim.treesitter.dev.Injection ---@field lang string Source language of this injection ---@field root TSNode Root node of the injection @@ -45,9 +43,9 @@ local TSTreeView = {} ---@param depth integer Current recursion depth ---@param field string|nil The field of the current node ---@param lang string Language of the tree currently being traversed ----@param injections table<string, TSP.Injection> Mapping of node ids to root nodes +---@param injections table<string, vim.treesitter.dev.Injection> Mapping of node ids to root nodes --- of injected language trees (see explanation above) ----@param tree TSP.Node[] Output table containing a list of tables each representing a node in the tree +---@param tree vim.treesitter.dev.Node[] Output table containing a list of tables each representing a node in the tree local function traverse(node, depth, field, lang, injections, tree) table.insert(tree, { node = node, @@ -73,7 +71,7 @@ end ---@param bufnr integer Source buffer number ---@param lang string|nil Language of source buffer --- ----@return TSTreeView|nil +---@return vim.treesitter.dev.TSTreeView|nil ---@return string|nil Error message, if any --- ---@package @@ -88,7 +86,7 @@ function TSTreeView:new(bufnr, lang) -- the primary tree that contains that root. Add a mapping from the node in the primary tree to -- the root in the child tree to the {injections} table. local root = parser:parse(true)[1]:root() - local injections = {} ---@type table<string, TSP.Injection> + local injections = {} ---@type table<string, vim.treesitter.dev.Injection> parser:for_each_tree(function(parent_tree, parent_ltree) local parent = parent_tree:root() @@ -109,7 +107,7 @@ function TSTreeView:new(bufnr, lang) local nodes = traverse(root, 0, nil, parser:lang(), injections, {}) - local named = {} ---@type TSP.Node[] + local named = {} ---@type vim.treesitter.dev.Node[] for _, v in ipairs(nodes) do if v.node:named() then named[#named + 1] = v @@ -120,7 +118,7 @@ function TSTreeView:new(bufnr, lang) ns = api.nvim_create_namespace('treesitter/dev-inspect'), nodes = nodes, named = named, - ---@type TSTreeViewOpts + ---@type vim.treesitter.dev.TSTreeViewOpts opts = { anon = false, lang = false, @@ -171,7 +169,7 @@ end --- Updates the cursor position in the inspector to match the node under the cursor. --- ---- @param treeview TSTreeView +--- @param treeview vim.treesitter.dev.TSTreeView --- @param lang string --- @param source_buf integer --- @param inspect_buf integer @@ -278,7 +276,7 @@ end --- The node number is dependent on whether or not anonymous nodes are displayed. --- ---@param i integer Node number to get ----@return TSP.Node +---@return vim.treesitter.dev.Node ---@package function TSTreeView:get(i) local t = self.opts.anon and self.nodes or self.named @@ -287,7 +285,7 @@ end --- Iterate over all of the nodes in this View. --- ----@return (fun(): integer, TSP.Node) Iterator over all nodes in this View +---@return (fun(): integer, vim.treesitter.dev.Node) Iterator over all nodes in this View ---@return table ---@return integer ---@package @@ -295,22 +293,31 @@ function TSTreeView:iter() return ipairs(self.opts.anon and self.nodes or self.named) end ---- @class InspectTreeOpts ---- @field lang string? The language of the source buffer. If omitted, the ---- filetype of the source buffer is used. ---- @field bufnr integer? Buffer to draw the tree into. If omitted, a new ---- buffer is created. ---- @field winid integer? Window id to display the tree buffer in. If omitted, ---- a new window is created with {command}. ---- @field command string? Vimscript command to create the window. Default ---- value is "60vnew". Only used when {winid} is nil. ---- @field title (string|fun(bufnr:integer):string|nil) Title of the window. If a ---- function, it accepts the buffer number of the source ---- buffer as its only argument and should return a string. +--- @class vim.treesitter.dev.inspect_tree.Opts +--- @inlinedoc +--- +--- The language of the source buffer. If omitted, the filetype of the source +--- buffer is used. +--- @field lang string? +--- +--- Buffer to draw the tree into. If omitted, a new buffer is created. +--- @field bufnr integer? +--- +--- Window id to display the tree buffer in. If omitted, a new window is +--- created with {command}. +--- @field winid integer? +--- +--- Vimscript command to create the window. Default value is "60vnew". +--- Only used when {winid} is nil. +--- @field command string? +--- +--- Title of the window. If a function, it accepts the buffer number of the +--- source buffer as its only argument and should return a string. +--- @field title (string|fun(bufnr:integer):string|nil) --- @private --- ---- @param opts InspectTreeOpts? +--- @param opts vim.treesitter.dev.inspect_tree.Opts? function M.inspect_tree(opts) vim.validate({ opts = { opts, 't', true }, diff --git a/runtime/lua/vim/treesitter/highlighter.lua b/runtime/lua/vim/treesitter/highlighter.lua index 8fb591bc46..388680259a 100644 --- a/runtime/lua/vim/treesitter/highlighter.lua +++ b/runtime/lua/vim/treesitter/highlighter.lua @@ -4,9 +4,9 @@ local Range = require('vim.treesitter._range') local ns = api.nvim_create_namespace('treesitter/highlighter') ----@alias vim.treesitter.highlighter.Iter fun(end_line: integer|nil): integer, TSNode, TSMetadata +---@alias vim.treesitter.highlighter.Iter fun(end_line: integer|nil): integer, TSNode, vim.treesitter.query.TSMetadata ----@class vim.treesitter.highlighter.Query +---@class (private) vim.treesitter.highlighter.Query ---@field private _query vim.treesitter.Query? ---@field private lang string ---@field private hl_cache table<integer,integer> @@ -52,22 +52,23 @@ function TSHighlighterQuery:query() return self._query end ----@class vim.treesitter.highlighter.State +---@class (private) vim.treesitter.highlighter.State ---@field tstree TSTree ---@field next_row integer ---@field iter vim.treesitter.highlighter.Iter? ---@field highlighter_query vim.treesitter.highlighter.Query +---@nodoc ---@class vim.treesitter.highlighter ---@field active table<integer,vim.treesitter.highlighter> ---@field bufnr integer ----@field orig_spelloptions string +---@field private orig_spelloptions string --- A map of highlight states. --- This state is kept during rendering across each line update. ----@field _highlight_states vim.treesitter.highlighter.State[] ----@field _queries table<string,vim.treesitter.highlighter.Query> ----@field tree LanguageTree ----@field redraw_count integer +---@field private _highlight_states vim.treesitter.highlighter.State[] +---@field private _queries table<string,vim.treesitter.highlighter.Query> +---@field tree vim.treesitter.LanguageTree +---@field private redraw_count integer local TSHighlighter = { active = {}, } @@ -78,7 +79,7 @@ TSHighlighter.__index = TSHighlighter --- --- Creates a highlighter for `tree`. --- ----@param tree LanguageTree parser object to use for highlighting +---@param tree vim.treesitter.LanguageTree parser object to use for highlighting ---@param opts (table|nil) Configuration of the highlighter: --- - queries table overwrite queries used by the highlighter ---@return vim.treesitter.highlighter Created highlighter object diff --git a/runtime/lua/vim/treesitter/language.lua b/runtime/lua/vim/treesitter/language.lua index 0f6d5ecbd0..78c73c698c 100644 --- a/runtime/lua/vim/treesitter/language.lua +++ b/runtime/lua/vim/treesitter/language.lua @@ -56,10 +56,17 @@ function M.require_language(lang, path, silent, symbol_name) return true end ----@class vim.treesitter.language.RequireLangOpts ----@field path? string ----@field silent? boolean +---@class vim.treesitter.language.add.Opts +---@inlinedoc +--- +---Default filetype the parser should be associated with. +---(Default: {lang}) ---@field filetype? string|string[] +--- +---Optional path the parser is located at +---@field path? string +--- +---Internal symbol name for the language to load ---@field symbol_name? string --- Load parser with name {lang} @@ -67,13 +74,8 @@ end --- Parsers are searched in the `parser` runtime directory, or the provided {path} --- ---@param lang string Name of the parser (alphanumerical and `_` only) ----@param opts (table|nil) Options: ---- - filetype (string|string[]) Default filetype the parser should be associated with. ---- Defaults to {lang}. ---- - path (string|nil) Optional path the parser is located at ---- - symbol_name (string|nil) Internal symbol name for the language to load +---@param opts? vim.treesitter.language.add.Opts Options: function M.add(lang, opts) - ---@cast opts vim.treesitter.language.RequireLangOpts opts = opts or {} local path = opts.path local filetype = opts.filetype or lang diff --git a/runtime/lua/vim/treesitter/languagetree.lua b/runtime/lua/vim/treesitter/languagetree.lua index d01da8be71..2f1aa36d18 100644 --- a/runtime/lua/vim/treesitter/languagetree.lua +++ b/runtime/lua/vim/treesitter/languagetree.lua @@ -67,10 +67,11 @@ local TSCallbackNames = { on_child_removed = 'child_removed', } ----@class LanguageTree +---@nodoc +---@class vim.treesitter.LanguageTree ---@field private _callbacks table<TSCallbackName,function[]> Callback handlers ---@field package _callbacks_rec table<TSCallbackName,function[]> Callback handlers (recursive) ----@field private _children table<string,LanguageTree> Injected languages +---@field private _children table<string,vim.treesitter.LanguageTree> Injected languages ---@field private _injection_query Query Queries defining injected languages ---@field private _injections_processed boolean ---@field private _opts table Options @@ -89,7 +90,9 @@ local TSCallbackNames = { ---@field private _logfile? file* local LanguageTree = {} ----@class LanguageTreeOpts +---Optional arguments: +---@class vim.treesitter.LanguageTree.new.Opts +---@inlinedoc ---@field queries table<string,string> -- Deprecated ---@field injections table<string,string> @@ -102,14 +105,11 @@ LanguageTree.__index = LanguageTree --- ---@param source (integer|string) Buffer or text string to parse ---@param lang string Root language of this tree ----@param opts (table|nil) Optional arguments: ---- - injections table Map of language to injection query strings. Overrides the ---- built-in runtime file searching for language injections. +---@param opts vim.treesitter.LanguageTree.new.Opts? ---@param parent_lang? string Parent language name of this tree ----@return LanguageTree parser object +---@return vim.treesitter.LanguageTree parser object function LanguageTree.new(source, lang, opts, parent_lang) language.add(lang) - ---@type LanguageTreeOpts opts = opts or {} if source == 0 then @@ -118,7 +118,7 @@ function LanguageTree.new(source, lang, opts, parent_lang) local injections = opts.injections or {} - --- @type LanguageTree + --- @type vim.treesitter.LanguageTree local self = { _source = source, _lang = lang, @@ -194,7 +194,7 @@ local function tcall(f, ...) end ---@private ----@vararg any +---@param ... any function LanguageTree:_log(...) if not self._logger then return @@ -464,7 +464,7 @@ end --- add recursion yourself if needed. --- Invokes the callback for each |LanguageTree| and its children recursively --- ----@param fn fun(tree: LanguageTree, lang: string) +---@param fn fun(tree: vim.treesitter.LanguageTree, lang: string) ---@param include_self boolean|nil Whether to include the invoking tree in the results function LanguageTree:for_each_child(fn, include_self) vim.deprecate('LanguageTree:for_each_child()', 'LanguageTree:children()', '0.11') @@ -481,7 +481,7 @@ end --- --- Note: This includes the invoking tree's child trees as well. --- ----@param fn fun(tree: TSTree, ltree: LanguageTree) +---@param fn fun(tree: TSTree, ltree: vim.treesitter.LanguageTree) function LanguageTree:for_each_tree(fn) for _, tree in pairs(self._trees) do fn(tree, self) @@ -498,7 +498,7 @@ end --- ---@private ---@param lang string Language to add. ----@return LanguageTree injected +---@return vim.treesitter.LanguageTree injected function LanguageTree:add_child(lang) if self._children[lang] then self:remove_child(lang) @@ -668,7 +668,7 @@ end ---@param node TSNode ---@param source string|integer ----@param metadata TSMetadata +---@param metadata vim.treesitter.query.TSMetadata ---@param include_children boolean ---@return Range6[] local function get_node_ranges(node, source, metadata, include_children) @@ -702,13 +702,14 @@ local function get_node_ranges(node, source, metadata, include_children) return ranges end ----@class TSInjectionElem +---@nodoc +---@class vim.treesitter.languagetree.InjectionElem ---@field combined boolean ---@field regions Range6[][] ----@alias TSInjection table<string,table<integer,TSInjectionElem>> +---@alias vim.treesitter.languagetree.Injection table<string,table<integer,vim.treesitter.languagetree.InjectionElem>> ----@param t table<integer,TSInjection> +---@param t table<integer,vim.treesitter.languagetree.Injection> ---@param tree_index integer ---@param pattern integer ---@param lang string @@ -783,7 +784,7 @@ end --- Extract injections according to: --- https://tree-sitter.github.io/tree-sitter/syntax-highlighting#language-injection ---@param match table<integer,TSNode[]> ----@param metadata TSMetadata +---@param metadata vim.treesitter.query.TSMetadata ---@return string?, boolean, Range6[] function LanguageTree:_get_injection(match, metadata) local ranges = {} ---@type Range6[] @@ -836,7 +837,7 @@ function LanguageTree:_get_injections() return {} end - ---@type table<integer,TSInjection> + ---@type table<integer,vim.treesitter.languagetree.Injection> local injections = {} for index, tree in pairs(self._trees) do @@ -1150,7 +1151,7 @@ end --- Gets the appropriate language that contains {range}. --- ---@param range Range4 `{ start_line, start_col, end_line, end_col }` ----@return LanguageTree Managing {range} +---@return vim.treesitter.LanguageTree Managing {range} function LanguageTree:language_for_range(range) for _, child in pairs(self._children) do if child:contains(range) then diff --git a/runtime/lua/vim/treesitter/query.lua b/runtime/lua/vim/treesitter/query.lua index 57272dbd60..6c7f713fd7 100644 --- a/runtime/lua/vim/treesitter/query.lua +++ b/runtime/lua/vim/treesitter/query.lua @@ -3,6 +3,7 @@ local language = require('vim.treesitter.language') local M = {} +---@nodoc ---Parsed query, see |vim.treesitter.query.parse()| --- ---@class vim.treesitter.Query @@ -31,6 +32,7 @@ function Query.new(lang, ts_query) return self end +---@nodoc ---Information for Query, see |vim.treesitter.query.parse()| ---@class vim.treesitter.QueryInfo --- @@ -296,7 +298,7 @@ end --- handling the "any" vs "all" semantics. They are called from the --- predicate_handlers table with the appropriate arguments for each predicate. local impl = { - --- @param match TSMatch + --- @param match vim.treesitter.query.TSMatch --- @param source integer|string --- @param predicate any[] --- @param any boolean @@ -331,7 +333,7 @@ local impl = { return not any end, - --- @param match TSMatch + --- @param match vim.treesitter.query.TSMatch --- @param source integer|string --- @param predicate any[] --- @param any boolean @@ -371,7 +373,7 @@ local impl = { end, }) - --- @param match TSMatch + --- @param match vim.treesitter.query.TSMatch --- @param source integer|string --- @param predicate any[] --- @param any boolean @@ -394,7 +396,7 @@ local impl = { end end)(), - --- @param match TSMatch + --- @param match vim.treesitter.query.TSMatch --- @param source integer|string --- @param predicate any[] --- @param any boolean @@ -421,12 +423,13 @@ local impl = { end, } ----@class TSMatch +---@nodoc +---@class vim.treesitter.query.TSMatch ---@field pattern? integer ---@field active? boolean ---@field [integer] TSNode[] ----@alias TSPredicate fun(match: TSMatch, pattern: integer, source: integer|string, predicate: any[]): boolean +---@alias TSPredicate fun(match: vim.treesitter.query.TSMatch, pattern: integer, source: integer|string, predicate: any[]): boolean -- Predicate handler receive the following arguments -- (match, pattern, bufnr, predicate) @@ -534,13 +537,14 @@ local predicate_handlers = { predicate_handlers['vim-match?'] = predicate_handlers['match?'] predicate_handlers['any-vim-match?'] = predicate_handlers['any-match?'] ----@class TSMetadata +---@nodoc +---@class vim.treesitter.query.TSMetadata ---@field range? Range ---@field conceal? string ----@field [integer] TSMetadata +---@field [integer] vim.treesitter.query.TSMetadata ---@field [string] integer|string ----@alias TSDirective fun(match: TSMatch, _, _, predicate: (string|integer)[], metadata: TSMetadata) +---@alias TSDirective fun(match: vim.treesitter.query.TSMatch, _, _, predicate: (string|integer)[], metadata: vim.treesitter.query.TSMetadata) -- Predicate handler receive the following arguments -- (match, pattern, bufnr, predicate) @@ -767,7 +771,7 @@ local function is_directive(name) end ---@private ----@param match TSMatch +---@param match vim.treesitter.query.TSMatch ---@param pattern integer ---@param source integer|string function Query:match_preds(match, pattern, source) @@ -806,8 +810,8 @@ function Query:match_preds(match, pattern, source) end ---@private ----@param match TSMatch ----@param metadata TSMetadata +---@param match vim.treesitter.query.TSMatch +---@param metadata vim.treesitter.query.TSMetadata function Query:apply_directives(match, pattern, source, metadata) local preds = self.info.patterns[pattern] @@ -871,7 +875,7 @@ end ---@param start? integer Starting line for the search. Defaults to `node:start()`. ---@param stop? integer Stopping line for the search (end-exclusive). Defaults to `node:end_()`. --- ----@return (fun(end_line: integer|nil): integer, TSNode, TSMetadata): +---@return (fun(end_line: integer|nil): integer, TSNode, vim.treesitter.query.TSMetadata): --- capture id, capture node, metadata function Query:iter_captures(node, source, start, stop) if type(source) == 'number' and source == 0 then @@ -880,7 +884,7 @@ function Query:iter_captures(node, source, start, stop) start, stop = value_or_node_range(start, stop, node) - local raw_iter = node:_rawquery(self.query, true, start, stop) ---@type fun(): integer, TSNode, TSMatch + local raw_iter = node:_rawquery(self.query, true, start, stop) ---@type fun(): integer, TSNode, vim.treesitter.query.TSMatch local function iter(end_line) local capture, captured_node, match = raw_iter() local metadata = {} @@ -952,7 +956,7 @@ function Query:iter_matches(node, source, start, stop, opts) start, stop = value_or_node_range(start, stop, node) - local raw_iter = node:_rawquery(self.query, false, start, stop, opts) ---@type fun(): integer, TSMatch + local raw_iter = node:_rawquery(self.query, false, start, stop, opts) ---@type fun(): integer, vim.treesitter.query.TSMatch local function iter() local pattern, match = raw_iter() local metadata = {} @@ -982,9 +986,16 @@ function Query:iter_matches(node, source, start, stop, opts) return iter end ----@class QueryLinterOpts ----@field langs (string|string[]|nil) ----@field clear (boolean) +--- Optional keyword arguments: +--- @class vim.treesitter.query.lint.Opts +--- @inlinedoc +--- +--- Language(s) to use for checking the query. +--- If multiple languages are specified, queries are validated for all of them +--- @field langs? string|string[] +--- +--- Just clear current lint errors +--- @field clear boolean --- Lint treesitter queries using installed parser, or clear lint errors. --- @@ -999,10 +1010,7 @@ end --- of the query file, e.g., if the path ends in `/lua/highlights.scm`, the parser for the --- `lua` language will be used. ---@param buf (integer) Buffer handle ----@param opts? QueryLinterOpts (table) Optional keyword arguments: ---- - langs (string|string[]|nil) Language(s) to use for checking the query. ---- If multiple languages are specified, queries are validated for all of them ---- - clear (boolean) if `true`, just clear current lint errors +---@param opts? vim.treesitter.query.lint.Opts function M.lint(buf, opts) if opts and opts.clear then vim.treesitter._query_linter.clear(buf) diff --git a/runtime/lua/vim/version.lua b/runtime/lua/vim/version.lua index 09a6fa825b..f97e81273e 100644 --- a/runtime/lua/vim/version.lua +++ b/runtime/lua/vim/version.lua @@ -54,7 +54,8 @@ local M = {} ----@class Version +---@nodoc +---@class vim.Version ---@field [1] number ---@field [2] number ---@field [3] number @@ -111,7 +112,7 @@ function Version:__newindex(key, value) end end ----@param other Version +---@param other vim.Version function Version:__eq(other) for i = 1, 3 do if self[i] ~= other[i] then @@ -132,7 +133,7 @@ function Version:__tostring() return ret end ----@param other Version +---@param other vim.Version function Version:__lt(other) for i = 1, 3 do if self[i] > other[i] then @@ -144,7 +145,7 @@ function Version:__lt(other) return -1 == cmp_prerel(self.prerelease, other.prerelease) end ----@param other Version +---@param other vim.Version function Version:__le(other) return self < other or self == other end @@ -153,9 +154,9 @@ end --- --- Creates a new Version object, or returns `nil` if `version` is invalid. --- ---- @param version string|number[]|Version +--- @param version string|number[]|vim.Version --- @param strict? boolean Reject "1.0", "0-x", "3.2a" or other non-conforming version strings ---- @return Version? +--- @return vim.Version? function M._version(version, strict) -- Adapted from https://github.com/folke/lazy.nvim if type(version) == 'table' then if version.major then @@ -203,7 +204,7 @@ end ---TODO: generalize this, move to func.lua --- ----@generic T: Version +---@generic T: vim.Version ---@param versions T[] ---@return T? function M.last(versions) @@ -216,14 +217,15 @@ function M.last(versions) return last end ----@class VersionRange ----@field from Version ----@field to? Version +---@class vim.VersionRange +---@inlinedoc +---@field from vim.Version +---@field to? vim.Version local VersionRange = {} --- @private --- ----@param version string|Version +---@param version string|vim.Version function VersionRange:has(version) if type(version) == 'string' then ---@diagnostic disable-next-line: cast-local-type @@ -272,6 +274,7 @@ end --- @see # https://github.com/npm/node-semver#ranges --- --- @param spec string Version range "spec" +--- @return vim.VersionRange function M.range(spec) -- Adapted from https://github.com/folke/lazy.nvim if spec == '*' or spec == '' then return setmetatable({ from = M.parse('0.0.0') }, { __index = VersionRange }) @@ -300,8 +303,8 @@ function M.range(spec) -- Adapted from https://github.com/folke/lazy.nvim local semver = M.parse(version) if semver then - local from = semver --- @type Version? - local to = vim.deepcopy(semver, true) --- @type Version? + local from = semver --- @type vim.Version? + local to = vim.deepcopy(semver, true) --- @type vim.Version? ---@diagnostic disable: need-check-nil if mods == '' or mods == '=' then to.patch = to.patch + 1 @@ -340,7 +343,7 @@ function M.range(spec) -- Adapted from https://github.com/folke/lazy.nvim end end ----@param v string|Version +---@param v string|vim.Version ---@return string local function create_err_msg(v) if type(v) == 'string' then @@ -369,8 +372,8 @@ end --- --- @note Per semver, build metadata is ignored when comparing two otherwise-equivalent versions. --- ----@param v1 Version|number[]|string Version object. ----@param v2 Version|number[]|string Version to compare with `v1`. +---@param v1 vim.Version|number[]|string Version object. +---@param v2 vim.Version|number[]|string Version to compare with `v1`. ---@return integer -1 if `v1 < v2`, 0 if `v1 == v2`, 1 if `v1 > v2`. function M.cmp(v1, v2) local v1_parsed = assert(M._version(v1), create_err_msg(v1)) @@ -385,40 +388,40 @@ function M.cmp(v1, v2) end ---Returns `true` if the given versions are equal. See |vim.version.cmp()| for usage. ----@param v1 Version|number[]|string ----@param v2 Version|number[]|string +---@param v1 vim.Version|number[]|string +---@param v2 vim.Version|number[]|string ---@return boolean function M.eq(v1, v2) return M.cmp(v1, v2) == 0 end ---Returns `true` if `v1 <= v2`. See |vim.version.cmp()| for usage. ----@param v1 Version|number[]|string ----@param v2 Version|number[]|string +---@param v1 vim.Version|number[]|string +---@param v2 vim.Version|number[]|string ---@return boolean function M.le(v1, v2) return M.cmp(v1, v2) <= 0 end ---Returns `true` if `v1 < v2`. See |vim.version.cmp()| for usage. ----@param v1 Version|number[]|string ----@param v2 Version|number[]|string +---@param v1 vim.Version|number[]|string +---@param v2 vim.Version|number[]|string ---@return boolean function M.lt(v1, v2) return M.cmp(v1, v2) == -1 end ---Returns `true` if `v1 >= v2`. See |vim.version.cmp()| for usage. ----@param v1 Version|number[]|string ----@param v2 Version|number[]|string +---@param v1 vim.Version|number[]|string +---@param v2 vim.Version|number[]|string ---@return boolean function M.ge(v1, v2) return M.cmp(v1, v2) >= 0 end ---Returns `true` if `v1 > v2`. See |vim.version.cmp()| for usage. ----@param v1 Version|number[]|string ----@param v2 Version|number[]|string +---@param v1 vim.Version|number[]|string +---@param v2 vim.Version|number[]|string ---@return boolean function M.gt(v1, v2) return M.cmp(v1, v2) == 1 @@ -438,7 +441,7 @@ end --- - strict (boolean): Default false. If `true`, no coercion is attempted on --- input not conforming to semver v2.0.0. If `false`, `parse()` attempts to --- coerce input such as "1.0", "0-x", "tmux 3.2a" into valid versions. ----@return Version? parsed_version Version object or `nil` if input is invalid. +---@return vim.Version? parsed_version Version object or `nil` if input is invalid. function M.parse(version, opts) assert(type(version) == 'string', create_err_msg(version)) opts = opts or { strict = false } @@ -447,9 +450,9 @@ end setmetatable(M, { --- Returns the current Nvim version. - ---@return Version + ---@return vim.Version __call = function() - local version = vim.fn.api_info().version ---@type Version + local version = vim.fn.api_info().version ---@type vim.Version -- Workaround: vim.fn.api_info().version reports "prerelease" as a boolean. version.prerelease = version.prerelease and 'dev' or nil return setmetatable(version, Version) |