From d039f19af54e73e1f076c29f1cb412c14612da07 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 9 Sep 2026 13:04:46 +0100 Subject: [PATCH] build: enable more EmmyLua checks Enable checks for unused code, deprecated calls, return types, and annotations. Fix the warnings and replace the deprecated highlight function. Keep exceptions where old APIs are still needed or the checker gets it wrong. AI-assisted --- .emmyrc.json | 33 ++++++++++------- runtime/doc/lsp.txt | 3 ++ runtime/lua/coxpcall.lua | 13 +++++++ runtime/lua/man.lua | 4 +-- runtime/lua/vim/_core/editor.lua | 6 ++-- runtime/lua/vim/_core/ex_cmd.lua | 4 +-- runtime/lua/vim/_core/help.lua | 2 +- runtime/lua/vim/_core/options.lua | 15 ++++---- runtime/lua/vim/_core/shared.lua | 1 + runtime/lua/vim/_core/system.lua | 2 ++ runtime/lua/vim/_core/table.lua | 5 +-- runtime/lua/vim/_core/ui2.lua | 2 +- runtime/lua/vim/_inspector.lua | 2 ++ runtime/lua/vim/diagnostic/_float.lua | 26 ++++++++++---- runtime/lua/vim/diagnostic/_shared.lua | 2 ++ runtime/lua/vim/filetype.lua | 2 +- runtime/lua/vim/fs.lua | 2 +- runtime/lua/vim/health/health.lua | 2 ++ runtime/lua/vim/iter.lua | 14 ++++---- runtime/lua/vim/loader.lua | 4 ++- runtime/lua/vim/lsp/_capability.lua | 6 ++-- runtime/lua/vim/lsp/_folding_range.lua | 6 ++-- runtime/lua/vim/lsp/buf.lua | 2 +- runtime/lua/vim/lsp/client.lua | 10 +++--- runtime/lua/vim/lsp/codelens.lua | 2 ++ runtime/lua/vim/lsp/completion.lua | 24 +++++++------ runtime/lua/vim/lsp/diagnostic.lua | 8 ++--- runtime/lua/vim/lsp/handlers.lua | 17 +++++++++ runtime/lua/vim/lsp/linked_editing_range.lua | 2 +- runtime/lua/vim/lsp/on_type_formatting.lua | 8 +++-- runtime/lua/vim/lsp/semantic_tokens.lua | 5 +-- runtime/lua/vim/lsp/sync.lua | 4 +-- runtime/lua/vim/lsp/util.lua | 36 ++++++++++--------- runtime/lua/vim/pack.lua | 8 ++--- runtime/lua/vim/pack/_lsp.lua | 4 +-- runtime/lua/vim/pos/_util.lua | 2 +- runtime/lua/vim/treesitter.lua | 2 +- runtime/lua/vim/treesitter/_range.lua | 4 +++ runtime/lua/vim/treesitter/dev.lua | 3 +- runtime/lua/vim/treesitter/language.lua | 2 +- runtime/lua/vim/treesitter/languagetree.lua | 6 ++++ runtime/lua/vim/treesitter/query.lua | 8 ++--- .../pack/dist/opt/nvim.tohtml/lua/tohtml.lua | 2 ++ test/functional/treesitter/query_spec.lua | 4 +-- 44 files changed, 202 insertions(+), 117 deletions(-) diff --git a/.emmyrc.json b/.emmyrc.json index 4c6df27e51..758dd8ecf9 100644 --- a/.emmyrc.json +++ b/.emmyrc.json @@ -28,29 +28,27 @@ "disable": [ "annotation-usage-error", "assign-type-mismatch", - "await-in-sync", "code-style-check", - "deprecated", - "global-in-non-module", "incomplete-signature-doc", - "invert-if", "iter-variable-reassign", - "missing-global-doc", "need-check-nil", - "non-literal-expressions-in-assert", "param-type-mismatch", - "preferred-local-alias", - "return-type-mismatch", - "unknown-doc-tag", "unnecessary-assert", - "unnecessary-if", - "unused" + "unnecessary-if" ], "severity": { + "deprecated": "warning", "duplicate-require": "warning", + "preferred-local-alias": "warning", "redefined-local": "warning", - "unreachable-code": "warning" - } + "unreachable-code": "warning", + "unused": "warning" + }, + "enables": [ + "missing-global-doc", + "non-literal-expressions-in-assert", + "unknown-doc-tag" + ] }, "codeAction": { "insertSpace": true @@ -58,5 +56,14 @@ "strict": { "typeCall": true, "arrayIndex": true + }, + "doc": { + "knownTags": [ + "brief", + "inlinedoc", + "nodoc", + "note", + "since" + ] } } diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt index 854222650f..ceb1212967 100644 --- a/runtime/doc/lsp.txt +++ b/runtime/doc/lsp.txt @@ -2187,6 +2187,9 @@ get({filter}) *vim.lsp.codelens.get()* • {client_id}? (`integer`, default: all) Client ID, or nil for all. + Overloads: ~ + • `fun(filter: integer): lsp.CodeLens[]` + Return: ~ (`table[]`) A list of objects with the following fields: • {client_id} (`integer`) diff --git a/runtime/lua/coxpcall.lua b/runtime/lua/coxpcall.lua index 23ea023f0c..bdd57095e7 100644 --- a/runtime/lua/coxpcall.lua +++ b/runtime/lua/coxpcall.lua @@ -48,6 +48,7 @@ local running = coroutine.running --- @type table local coromap = setmetatable({}, { __mode = "k" }) +--- @async local function handleReturnValue(err, co, status, ...) if not status then return false, err(debug.traceback(co, (...)), ...) @@ -59,6 +60,7 @@ local function handleReturnValue(err, co, status, ...) end end +--- @async function performResume(err, co, ...) return handleReturnValue(err, co, coroutine.resume(co, ...)) end @@ -68,6 +70,10 @@ local function id(trace, ...) return trace end +--- @param f function +--- @param err function +--- @param ... any +--- @return boolean, any... function _G.coxpcall(f, err, ...) local current = running() if not current then @@ -87,6 +93,8 @@ function _G.coxpcall(f, err, ...) co = coroutine.create(newf) end coromap[co] = current + -- This branch only runs inside a coroutine. + --- @diagnostic disable-next-line: await-in-sync return performResume(err, co, ...) end end @@ -109,7 +117,12 @@ end -- Implements pcall with coroutines ------------------------------------------------------------------------------- +--- @param f function +--- @param ... any +--- @return boolean, any... function _G.copcall(f, ...) + -- EmmyLua does not distribute the union of xpcall return tuples. + --- @diagnostic disable-next-line: return-type-mismatch return coxpcall(f, id, ...) end diff --git a/runtime/lua/man.lua b/runtime/lua/man.lua index 84dfd0e7f4..f07c1dfe46 100644 --- a/runtime/lua/man.lua +++ b/runtime/lua/man.lua @@ -385,8 +385,8 @@ end --- (try `:Man 3 App::CLI`). Also on linux, name seems to be case-insensitive. --- So for `:Man PRIntf`, we still want the name of the buffer to be 'printf'. --- @param path string ---- @return string name ---- @return string sect +--- @return string? name +--- @return string? sect local function parse_path(path) local tail = vim.fs.basename(path) if diff --git a/runtime/lua/vim/_core/editor.lua b/runtime/lua/vim/_core/editor.lua index 12b772d047..7d44718785 100644 --- a/runtime/lua/vim/_core/editor.lua +++ b/runtime/lua/vim/_core/editor.lua @@ -535,10 +535,10 @@ do local function make_dict_accessor(scope, handle) vim.validate('scope', scope, 'string') local mt = {} - function mt:__newindex(k, v) + function mt.__newindex(_, k, v) return vim._setvar(scope, handle or 0, k, v) end - function mt:__index(k) + function mt.__index(_, k) if handle == nil and type(k) == 'number' then return make_dict_accessor(scope, k) end @@ -926,7 +926,7 @@ function vim.str_utfindex(s, encoding, index, strict_indexing) if encoding == 'utf-8' then local len = #s - return index <= len and index or (strict_indexing and error('index out of range') or len) + return (index <= len and index or (strict_indexing and error('index out of range') or len)) --[[@as integer]] end local col32, col16 = vim._str_utfindex(s, index) --[[@as integer?,integer?]] local col = encoding == 'utf-16' and col16 or col32 diff --git a/runtime/lua/vim/_core/ex_cmd.lua b/runtime/lua/vim/_core/ex_cmd.lua index 5187dade61..695e6affa2 100644 --- a/runtime/lua/vim/_core/ex_cmd.lua +++ b/runtime/lua/vim/_core/ex_cmd.lua @@ -216,7 +216,7 @@ function M.ex_log(eap) else path = fs.joinpath(log_dir, filename .. '.log') end - if not vim.uv.fs_stat(path) then + if not uv.fs_stat(path) then util.echo_err(N_('E5200: No such log file: %s'):format(path)) return end @@ -229,7 +229,7 @@ end --- @return string[] completions function M.log_complete() local names = { 'nvim' } --- @type string[] - for file, type in vim.fs.dir(log_dir, { depth = math.huge }) do + for file, type in fs.dir(log_dir, { depth = math.huge }) do local name, matches = file:gsub('%.log$', '') if matches ~= 0 and type == 'file' and name ~= 'nvim' then names[#names + 1] = name diff --git a/runtime/lua/vim/_core/help.lua b/runtime/lua/vim/_core/help.lua index 7223959352..b957621244 100644 --- a/runtime/lua/vim/_core/help.lua +++ b/runtime/lua/vim/_core/help.lua @@ -249,7 +249,7 @@ end --- ---@return string? resolved The resolved help tag, or nil if no match found function M.resolve_tag() - local tag = vim.fn.expand('') + local tag = vim.fn.expand('') --[[@as string]] if not tag or tag == '' then return nil end diff --git a/runtime/lua/vim/_core/options.lua b/runtime/lua/vim/_core/options.lua index 3bcf54ffd5..75e71aaf3c 100644 --- a/runtime/lua/vim/_core/options.lua +++ b/runtime/lua/vim/_core/options.lua @@ -295,7 +295,7 @@ local function create_option_accessor(scope) end, append = function(self, right) - vim.api.nvim_set_option_value(self._name, right, { operation = 'append', scope = scope }) + api.nvim_set_option_value(self._name, right, { operation = 'append', scope = scope }) end, __infix = function(self, right, operation) @@ -315,7 +315,7 @@ local function create_option_accessor(scope) end return make_option( self._name, - vim.api.nvim_set_option_value( + api.nvim_set_option_value( self._name, right, { operation = operation, scope = scope, dry_run = true } @@ -329,7 +329,7 @@ local function create_option_accessor(scope) end, prepend = function(self, right) - vim.api.nvim_set_option_value(self._name, right, { operation = 'prepend', scope = scope }) + api.nvim_set_option_value(self._name, right, { operation = 'prepend', scope = scope }) end, __pow = function(self, right) @@ -337,7 +337,7 @@ local function create_option_accessor(scope) end, remove = function(self, right) - vim.api.nvim_set_option_value(self._name, right, { operation = 'remove', scope = scope }) + api.nvim_set_option_value(self._name, right, { operation = 'remove', scope = scope }) end, __sub = function(self, right) @@ -479,6 +479,7 @@ local Option = {} -- luacheck: no unused --- end --- ``` ---@return string|integer|boolean|nil value of option +---@diagnostic disable-next-line: unused used for gen_vimdoc function Option:get() end --- Append a value to string-style options. See |:set+=| @@ -490,7 +491,7 @@ function Option:get() end --- vim.opt.formatoptions = vim.opt.formatoptions + 'j' --- ``` ---@param value string Value to append ----@diagnostic disable-next-line:unused-local used for gen_vimdoc +---@diagnostic disable-next-line:unused used for gen_vimdoc function Option:append(value) end -- luacheck: no unused --- Prepend a value to string-style options. See |:set^=| @@ -502,7 +503,7 @@ function Option:append(value) end -- luacheck: no unused --- vim.opt.wildignore = vim.opt.wildignore ^ '*.o' --- ``` ---@param value string Value to prepend ----@diagnostic disable-next-line:unused-local used for gen_vimdoc +---@diagnostic disable-next-line:unused used for gen_vimdoc function Option:prepend(value) end -- luacheck: no unused --- Remove a value from string-style options. See |:set-=| @@ -514,7 +515,7 @@ function Option:prepend(value) end -- luacheck: no unused --- vim.opt.wildignore = vim.opt.wildignore - '*.pyc' --- ``` ---@param value string Value to remove ----@diagnostic disable-next-line:unused-local used for gen_vimdoc +---@diagnostic disable-next-line:unused used for gen_vimdoc function Option:remove(value) end -- luacheck: no unused --- @nodoc diff --git a/runtime/lua/vim/_core/shared.lua b/runtime/lua/vim/_core/shared.lua index d4c33d4b8a..4be64e2373 100644 --- a/runtime/lua/vim/_core/shared.lua +++ b/runtime/lua/vim/_core/shared.lua @@ -1680,6 +1680,7 @@ end --- @return T[] function vim._ensure_list(x) if type(x) == 'table' then + --- @cast x T[] return x end return { x } diff --git a/runtime/lua/vim/_core/system.lua b/runtime/lua/vim/_core/system.lua index d804b04dfe..a1e44e0408 100644 --- a/runtime/lua/vim/_core/system.lua +++ b/runtime/lua/vim/_core/system.lua @@ -147,6 +147,8 @@ function SystemObj:wait(timeout) end, nil, true) end + -- TODO: A short timeout can leave result nil even after sending SIGKILL. + ---@diagnostic disable-next-line: return-type-mismatch return state.result end diff --git a/runtime/lua/vim/_core/table.lua b/runtime/lua/vim/_core/table.lua index d039a25e41..4fb16d7cb5 100644 --- a/runtime/lua/vim/_core/table.lua +++ b/runtime/lua/vim/_core/table.lua @@ -5,17 +5,14 @@ local has_clear, clear = pcall(require, 'table.clear') local M = {} if not has_new then - ---@diagnostic disable-next-line: unused-local - new = function(narr, nrec) + new = function(_narr, _nrec) return {} end end if not has_clear then clear = function(tab) - ---@diagnostic disable-next-line: no-unknown for k in pairs(tab) do - ---@diagnostic disable-next-line: no-unknown tab[k] = nil end end diff --git a/runtime/lua/vim/_core/ui2.lua b/runtime/lua/vim/_core/ui2.lua index 219a703fe8..699490dd98 100644 --- a/runtime/lua/vim/_core/ui2.lua +++ b/runtime/lua/vim/_core/ui2.lua @@ -195,7 +195,7 @@ function M.enable(opts) M.cfg.msg.targets = type(M.cfg.msg.targets) == 'table' and M.cfg.msg.targets or { default = M.cfg.msg.targets } M.cfg.msg.targets.default = M.cfg.msg.targets.default or 'cmd' - if #vim.api.nvim_list_uis() == 0 then + if #api.nvim_list_uis() == 0 then return -- Don't prevent stdout messaging when no UIs are attached. end diff --git a/runtime/lua/vim/_inspector.lua b/runtime/lua/vim/_inspector.lua index 2ae357a700..5e0a518acb 100644 --- a/runtime/lua/vim/_inspector.lua +++ b/runtime/lua/vim/_inspector.lua @@ -56,6 +56,8 @@ function vim.inspect_pos(buf, row, col, filter) row, col = cursor[1] - 1, cursor[2] end buf = vim._resolve_bufnr(buf) + ---@cast row integer + ---@cast col integer local results = { treesitter = {}, --- @type table[] diff --git a/runtime/lua/vim/diagnostic/_float.lua b/runtime/lua/vim/diagnostic/_float.lua index aa41cdd38e..f7331b3c56 100644 --- a/runtime/lua/vim/diagnostic/_float.lua +++ b/runtime/lua/vim/diagnostic/_float.lua @@ -5,6 +5,8 @@ local store = require('vim.diagnostic._store') --- @class (private) vim.diagnostic._float local M = {} +local float_ns = api.nvim_create_namespace('nvim.diagnostic.float') + local severity = vim.diagnostic.severity --- @type table @@ -263,19 +265,31 @@ function M.open(opts, ...) end end, { buf = float_bufnr, remap = false }) - --- @diagnostic disable-next-line: deprecated - local add_highlight = api.nvim_buf_add_highlight - + -- The preview may trim empty lines or reuse an older buffer, so highlight ranges + -- can extend past its contents. Use strict = false to tolerate this. for i, hl in ipairs(highlights) do local line = lines[i] local prefix_len = hl.prefix and hl.prefix.length or 0 local suffix_len = hl.suffix and hl.suffix.length or 0 if prefix_len > 0 then - add_highlight(float_bufnr, -1, hl.prefix.hlname, i - 1, 0, prefix_len) + api.nvim_buf_set_extmark(float_bufnr, float_ns, i - 1, 0, { + hl_group = hl.prefix.hlname, + end_col = prefix_len, + strict = false, + }) end - add_highlight(float_bufnr, -1, hl.hlname, i - 1, prefix_len, #line - suffix_len) + api.nvim_buf_set_extmark(float_bufnr, float_ns, i - 1, prefix_len, { + hl_group = hl.hlname, + end_col = #line - suffix_len, + strict = false, + }) if suffix_len > 0 then - add_highlight(float_bufnr, -1, hl.suffix.hlname, i - 1, #line - suffix_len, -1) + api.nvim_buf_set_extmark(float_bufnr, float_ns, i - 1, #line - suffix_len, { + hl_group = hl.suffix.hlname, + end_row = i, + end_col = 0, + strict = false, + }) end end diff --git a/runtime/lua/vim/diagnostic/_shared.lua b/runtime/lua/vim/diagnostic/_shared.lua index 177cc61b32..2e504d5d68 100644 --- a/runtime/lua/vim/diagnostic/_shared.lua +++ b/runtime/lua/vim/diagnostic/_shared.lua @@ -58,6 +58,8 @@ function M.get_logical_pos(diagnostic) return diagnostic.lnum, diagnostic.col, diagnostic.end_lnum, diagnostic.end_col, true end + -- Diagnostic extmarks always have an end position. + ---@cast extmark [integer, integer, {end_row: integer, end_col: integer, invalid?: boolean}] return extmark[1], extmark[2], extmark[3].end_row, extmark[3].end_col, not extmark[3].invalid end diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index 2ba238085e..80af785617 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -109,7 +109,7 @@ end --- @return table function M._get_known_filetypes() local known = {} --- @type table - for _, ft in ipairs(vim.fn.getcompletion('', 'filetype')) do + for _, ft in ipairs(fn.getcompletion('', 'filetype')) do known[ft] = true end local registry = vim.filetype.inspect() diff --git a/runtime/lua/vim/fs.lua b/runtime/lua/vim/fs.lua index c412e9d714..7af6825bff 100644 --- a/runtime/lua/vim/fs.lua +++ b/runtime/lua/vim/fs.lua @@ -276,7 +276,7 @@ local function fs_scandir_next(fs, path) end if etype == nil then - local stat = vim.uv.fs_lstat(M.joinpath(path, name)) + local stat = uv.fs_lstat(M.joinpath(path, name)) -- Workaround #39612 https://github.com/luvit/luv/issues/660 etype = stat and stat.type or 'unknown' end diff --git a/runtime/lua/vim/health/health.lua b/runtime/lua/vim/health/health.lua index 8ba44a748a..969b1e06aa 100644 --- a/runtime/lua/vim/health/health.lua +++ b/runtime/lua/vim/health/health.lua @@ -801,6 +801,8 @@ local function check_sysinfo() local encoded_body = vim.uri_encode(body) --- @type string local issue_url = 'https://github.com/neovim/neovim/issues/new?type=Bug&body=' .. encoded_body + --- Opens the prefilled issue from the checkhealth winbar. + ---@diagnostic disable-next-line: global-in-non-module _G.nvim_health_bugreport_open = function() vim.ui.open(issue_url) end diff --git a/runtime/lua/vim/iter.lua b/runtime/lua/vim/iter.lua index f81c43b3bf..9a195307c8 100644 --- a/runtime/lua/vim/iter.lua +++ b/runtime/lua/vim/iter.lua @@ -276,7 +276,7 @@ function Iter:unique(key) end --- @nodoc ---- @diagnostic disable-next-line:unused-local +--- @diagnostic disable-next-line:unused function Iter:flatten(depth) error('flatten() requires an array-like table') end @@ -629,7 +629,7 @@ function IterArray:next() end --- @nodoc ---- @diagnostic disable-next-line: unused-local +--- @diagnostic disable-next-line: unused function Iter:rev() error('rev() requires an array-like table') end @@ -743,7 +743,7 @@ function Iter:find(f) end --- @nodoc ---- @diagnostic disable-next-line:unused-local +--- @diagnostic disable-next-line:unused function Iter:rfind(f) error('rfind() requires an array-like table') end @@ -866,7 +866,7 @@ function IterArray:take(n) end --- @nodoc ---- @diagnostic disable-next-line: unused-local +--- @diagnostic disable-next-line: unused function Iter:pop() error('pop() requires an array-like table') end @@ -894,7 +894,7 @@ function IterArray:pop() end --- @nodoc ---- @diagnostic disable-next-line: unused-local +--- @diagnostic disable-next-line: unused function Iter:rpeek() error('rpeek() requires an array-like table') end @@ -1003,7 +1003,7 @@ function IterArray:skip(n) end --- @nodoc ---- @diagnostic disable-next-line:unused-local +--- @diagnostic disable-next-line:unused function Iter:rskip(n) error('rskip() requires an array-like table') end @@ -1064,7 +1064,7 @@ function Iter:nth(n) end --- @nodoc ---- @diagnostic disable-next-line:unused-local +--- @diagnostic disable-next-line:unused function Iter:slice(first, last) error('slice() requires an array-like table') end diff --git a/runtime/lua/vim/loader.lua b/runtime/lua/vim/loader.lua index 2ab8d451a2..e819229583 100644 --- a/runtime/lua/vim/loader.lua +++ b/runtime/lua/vim/loader.lua @@ -437,7 +437,8 @@ function M.enable(enable) M.enabled = enable if enable then - vim.fn.mkdir(vim.fs.abspath(M.path), 'p') + vim.fn.mkdir(fs.abspath(M.path), 'p') + ---@diagnostic disable-next-line: global-in-non-module _G.loadfile = loadfile_cached -- add Lua loader table.insert(loaders, 2, loader_cached) @@ -451,6 +452,7 @@ function M.enable(enable) end end else + ---@diagnostic disable-next-line: global-in-non-module _G.loadfile = _loadfile for l = #loaders, 1, -1 do local loader = loaders[l] diff --git a/runtime/lua/vim/lsp/_capability.lua b/runtime/lua/vim/lsp/_capability.lua index 977c1ab355..55f83e5ba5 100644 --- a/runtime/lua/vim/lsp/_capability.lua +++ b/runtime/lua/vim/lsp/_capability.lua @@ -118,18 +118,18 @@ end --- Callback invoked when textDocument/didClose is sent for a client. ---@param client_id integer ----@diagnostic disable-next-line: unused-local +---@diagnostic disable-next-line: unused function M:on_close(client_id) end --- Callback invoked when textDocument/didChange or textDocument/didOpen is sent for a client. ---@param client_id integer ----@diagnostic disable-next-line: unused-local +---@diagnostic disable-next-line: unused function M:on_change(client_id) end --- Callback invoked on every redraw. ---@param topline integer ---@param botline integer ----@diagnostic disable-next-line: unused-local +---@diagnostic disable-next-line: unused function M:on_win(topline, botline) end ---@param name vim.lsp.capability.Name diff --git a/runtime/lua/vim/lsp/_folding_range.lua b/runtime/lua/vim/lsp/_folding_range.lua index 9f85be9eae..e1d9042ba9 100644 --- a/runtime/lua/vim/lsp/_folding_range.lua +++ b/runtime/lua/vim/lsp/_folding_range.lua @@ -254,7 +254,7 @@ function State:on_attach(client_id) self:refresh(client_id) end ----@params client_id integer +---@param client_id integer function State:on_detach(client_id) self.client_state[client_id] = nil self:evaluate() @@ -275,7 +275,7 @@ end ---@param kind lsp.FoldingRangeKind ---@param winid integer -function State:foldclose(kind, winid) +function State.foldclose(_, kind, winid) vim._with({ win = winid }, function() local bufnr = api.nvim_win_get_buf(winid) local row_kinds = State.active[bufnr].row_kinds @@ -395,7 +395,7 @@ function M.foldtext(lnum) local row = lnum - 1 local state = State.active[bufnr] local lang = state and state.lang - local line = vim.fn.getline(lnum) + local line = vim.fn.getline(lnum) --[[@as string]] if not lang then return line end ---@cast state -nil diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua index 0eca0bc420..c6b44ab0cd 100644 --- a/runtime/lua/vim/lsp/buf.lua +++ b/runtime/lua/vim/lsp/buf.lua @@ -36,7 +36,7 @@ local function ctx_is_valid(ctx) not bufnr or not api.nvim_buf_is_valid(bufnr) or api.nvim_get_current_buf() ~= bufnr - or vim.lsp.util.buf_versions[bufnr] ~= ctx.version + or lsp.util.buf_versions[bufnr] ~= ctx.version then return false end diff --git a/runtime/lua/vim/lsp/client.lua b/runtime/lua/vim/lsp/client.lua index 984447720c..401d39042c 100644 --- a/runtime/lua/vim/lsp/client.lua +++ b/runtime/lua/vim/lsp/client.lua @@ -989,7 +989,7 @@ end --- Get provider for a method to be registered dynamically. --- @param method vim.lsp.protocol.Method | vim.lsp.protocol.Method.Registration -function Client:_registration_provider(method) +function Client._registration_provider(_, method) return lsp.protocol._request_name_to_registration_provider[method] or method end @@ -1224,7 +1224,7 @@ function Client:on_attach(bufnr) -- schedule the initialization of capabilities to give the above on_attach and LspAttach callbacks -- the ability to enable or disable them vim.schedule(function() - if not vim.api.nvim_buf_is_valid(bufnr) then + if not api.nvim_buf_is_valid(bufnr) then return end for _, Capability in pairs(lsp._capability.all) do @@ -1456,7 +1456,7 @@ function Client:_on_detach(bufnr) end end - vim.diagnostic.reset(vim.lsp.diagnostic.get_namespace(self.id, false), bufnr) + vim.diagnostic.reset(lsp.diagnostic.get_namespace(self.id, false), bufnr) changetracking.reset_buf(self, bufnr) @@ -1468,10 +1468,10 @@ end --- Reset defaults set by `set_defaults`. --- Must only be called if the last client attached to a buffer exits. local function reset_defaults(bufnr) - if vim.bo[bufnr].tagfunc == vim.lsp.tagfunc then + if vim.bo[bufnr].tagfunc == lsp.tagfunc then vim.bo[bufnr].tagfunc = nil end - if vim.bo[bufnr].omnifunc == vim.lsp.omnifunc then + if vim.bo[bufnr].omnifunc == lsp.omnifunc then vim.bo[bufnr].omnifunc = nil end if vim.bo[bufnr].formatexpr == 'v:lua.vim.lsp.formatexpr()' then diff --git a/runtime/lua/vim/lsp/codelens.lua b/runtime/lua/vim/lsp/codelens.lua index ebcdef0b1e..89c8877b2d 100644 --- a/runtime/lua/vim/lsp/codelens.lua +++ b/runtime/lua/vim/lsp/codelens.lua @@ -297,6 +297,7 @@ end --- ---@param filter? vim.lsp.codelens.get.Filter ---@return vim.lsp.codelens.get.Result[] +---@overload fun(filter: integer): lsp.CodeLens[] function M.get(filter) if type(filter) == 'number' then vim.deprecate( @@ -316,6 +317,7 @@ function M.get(filter) result = vim.list_extend(result, row_lenses.lenses) end end + ---@diagnostic disable-next-line: return-type-mismatch return result end diff --git a/runtime/lua/vim/lsp/completion.lua b/runtime/lua/vim/lsp/completion.lua index 00f224b590..b092a71120 100644 --- a/runtime/lua/vim/lsp/completion.lua +++ b/runtime/lua/vim/lsp/completion.lua @@ -145,7 +145,7 @@ local compute_new_average = exp_avg(10, 10) --- --- @param last_request_time integer? --- @param current_rtt_ms number ---- @return integer +--- @return number local function adaptive_debounce(last_request_time, current_rtt_ms) if not last_request_time then return current_rtt_ms @@ -298,6 +298,7 @@ local function get_items(result) return result.items else -- Else just return the items as they are. + ---@cast result lsp.CompletionItem[] return result end end @@ -308,7 +309,7 @@ end ---@return lsp.MarkupKind local function get_doc(item) local doc = item.documentation - local default_kind = vim.lsp.protocol.MarkupKind.Markdown + local default_kind = protocol.MarkupKind.Markdown if not doc then return '', default_kind end @@ -349,11 +350,11 @@ end ---@return string? kind text or "■" for colors ---@return string? highlight group for colors local function generate_kind(item) - if not lsp.protocol.CompletionItemKind[item.kind] then + if not protocol.CompletionItemKind[item.kind] then return 'Unknown' end - if item.kind ~= lsp.protocol.CompletionItemKind.Color then - return lsp.protocol.CompletionItemKind[item.kind] + if item.kind ~= protocol.CompletionItemKind.Color then + return protocol.CompletionItemKind[item.kind] --[[@as string]] end local doc = get_doc(item) if #doc == 0 then @@ -575,6 +576,7 @@ function M._lsp_to_complete_items( local hl_group = '' if + ---@diagnostic disable-next-line: deprecated item.deprecated or vim.list_contains((item.tags or {}), protocol.CompletionTag.Deprecated) then @@ -786,7 +788,7 @@ end --- @param kind? string local function update_popup_window(winid, bufnr, kind) if winid and api.nvim_win_is_valid(winid) and bufnr and api.nvim_buf_is_valid(bufnr) then - if kind == lsp.protocol.MarkupKind.Markdown then + if kind == protocol.MarkupKind.Markdown then vim.wo[winid].conceallevel = 2 vim.treesitter.start(bufnr, kind) end @@ -856,9 +858,9 @@ end --- @return boolean, table Validity of the request and the completion info function CompletionResolver:is_valid() local cmp_info = vim.fn.complete_info({ 'selected', 'completed' }) - return vim.api.nvim_buf_is_valid(self.bufnr) - and vim.api.nvim_get_current_buf() == self.bufnr - and vim.startswith(vim.api.nvim_get_mode().mode, 'i') + return api.nvim_buf_is_valid(self.bufnr) + and api.nvim_get_current_buf() == self.bufnr + and vim.startswith(api.nvim_get_mode().mode, 'i') and vim.fn.pumvisible() ~= 0 and (vim.tbl_get(cmp_info, 'completed', 'word') or '') == self.word, cmp_info @@ -887,7 +889,7 @@ function CompletionResolver:request(bufnr, param, selected_word) self:cancel_pending_requests() local client_id = vim.tbl_get(cmp_info.completed, 'user_data', 'nvim', 'lsp', 'client_id') - local client = client_id and vim.lsp.get_client_by_id(client_id) + local client = client_id and lsp.get_client_by_id(client_id) -- completionItem/resolve is not registrable, so supports_method() would -- only see the static capability. if not client or not completion_options(client, bufnr).resolveProvider then @@ -917,7 +919,7 @@ function CompletionResolver:request(bufnr, param, selected_word) local info, kind = complete_item_info(result) if info ~= '' and info ~= cmp_info.completed.info then - local windata = vim.api.nvim__complete_set(cmp_info.selected, { info = info }) + local windata = api.nvim__complete_set(cmp_info.selected, { info = info }) update_popup_window(windata.winid, windata.bufnr, kind) end end, bufnr) diff --git a/runtime/lua/vim/lsp/diagnostic.lua b/runtime/lua/vim/lsp/diagnostic.lua index 6f4cdbc693..388c632285 100644 --- a/runtime/lua/vim/lsp/diagnostic.lua +++ b/runtime/lua/vim/lsp/diagnostic.lua @@ -295,12 +295,12 @@ function M.on_diagnostic(error, result, ctx) if error ~= nil then if error.code == protocol.ErrorCodes.ServerCancelled then if error.data == nil or error.data.retriggerRequest ~= false then - local client = assert(lsp.get_client_by_id(ctx.client_id)) + local client = assert(lsp.get_client_by_id(client_id)) ---@diagnostic disable-next-line: param-type-mismatch client:request(ctx.method, ctx.params, nil, ctx.bufnr) end else - vim.lsp.log.error('diagnostics', error) + lsp.log.error('diagnostics', error) end return end @@ -354,7 +354,7 @@ end ---@package ---@param client_id integer Client ID to refresh function Diagnostics:refresh(client_id) - local client = vim.lsp.get_client_by_id(client_id) + local client = lsp.get_client_by_id(client_id) local method = 'textDocument/diagnostic' local clients = { client } @@ -389,7 +389,7 @@ function M.on_refresh(err, _, ctx) if err then return vim.NIL end - local client = vim.lsp.get_client_by_id(ctx.client_id) + local client = lsp.get_client_by_id(ctx.client_id) if client == nil then return vim.NIL end diff --git a/runtime/lua/vim/lsp/handlers.lua b/runtime/lua/vim/lsp/handlers.lua index 5bdd8cc01f..3163b1bc85 100644 --- a/runtime/lua/vim/lsp/handlers.lua +++ b/runtime/lua/vim/lsp/handlers.lua @@ -44,6 +44,7 @@ local function show_message_notification(params, ctx) end --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_executeCommand +---@diagnostic disable-next-line: deprecated RCS['workspace/executeCommand'] = function(_, _, _) -- Error handling is done implicitly by wrapping all handlers; see end of this file end @@ -120,6 +121,8 @@ RSC['window/showMessageRequest'] = function(_, params, ctx) coroutine.resume(co, choice or vim.NIL) end) end) + -- The coroutine.running() check above guards this yield. + ---@diagnostic disable-next-line: await-in-sync return coroutine.yield() else local option_strings = { params.message, '\nRequest Actions:' } @@ -259,11 +262,13 @@ NSC['textDocument/publishDiagnostics'] = function(...) end --- @private +---@diagnostic disable-next-line: deprecated RCS['textDocument/diagnostic'] = function(...) return vim.lsp.diagnostic.on_diagnostic(...) end --- @private +---@diagnostic disable-next-line: deprecated RCS['textDocument/inlayHint'] = function(...) return vim.lsp.inlay_hint.on_inlayhint(...) end @@ -304,6 +309,7 @@ end --- @deprecated remove in 0.13 --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_documentSymbol +---@diagnostic disable-next-line: deprecated RCS['textDocument/documentSymbol'] = response_to_list( util.symbols_to_items, 'document symbols', @@ -315,12 +321,14 @@ RCS['textDocument/documentSymbol'] = response_to_list( --- @deprecated remove in 0.13 --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_symbol +---@diagnostic disable-next-line: deprecated RCS['workspace/symbol'] = response_to_list(util.symbols_to_items, 'symbols', function(ctx) return string.format("Symbols matching '%s'", ctx.params.query) end) --- @deprecated remove in 0.13 --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_rename +---@diagnostic disable-next-line: deprecated RCS['textDocument/rename'] = function(_, result, ctx) if not result then vim.notify("Language server couldn't provide rename result", vim.log.levels.INFO) @@ -332,6 +340,7 @@ end --- @deprecated remove in 0.13 --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_rangeFormatting +---@diagnostic disable-next-line: deprecated RCS['textDocument/rangeFormatting'] = function(_, result, ctx) if not result then return @@ -342,6 +351,7 @@ end --- @deprecated remove in 0.13 --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_formatting +---@diagnostic disable-next-line: deprecated RCS['textDocument/formatting'] = function(_, result, ctx) if not result then return @@ -352,6 +362,7 @@ end --- @deprecated remove in 0.13 --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_completion +---@diagnostic disable-next-line: deprecated RCS['textDocument/completion'] = function(_, result, _) if vim.tbl_isempty(result or {}) then return @@ -495,6 +506,7 @@ RCS['textDocument/signatureHelp'] = M.signature_help --- @deprecated remove in 0.13 --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_documentHighlight +---@diagnostic disable-next-line: deprecated RCS['textDocument/documentHighlight'] = function(_, result, ctx) if not result then return @@ -547,10 +559,12 @@ end --- @deprecated remove in 0.13 --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#callHierarchy_incomingCalls +---@diagnostic disable-next-line: deprecated RCS['callHierarchy/incomingCalls'] = make_call_hierarchy_handler('from') --- @deprecated remove in 0.13 --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#callHierarchy_outgoingCalls +---@diagnostic disable-next-line: deprecated RCS['callHierarchy/outgoingCalls'] = make_call_hierarchy_handler('to') --- Displays type hierarchy in the quickfix window. @@ -584,10 +598,12 @@ end --- @deprecated remove in 0.13 --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#typeHierarchy_incomingCalls +---@diagnostic disable-next-line: deprecated RCS['typeHierarchy/subtypes'] = make_type_hierarchy_handler() --- @deprecated remove in 0.13 --- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#typeHierarchy_outgoingCalls +---@diagnostic disable-next-line: deprecated RCS['typeHierarchy/supertypes'] = make_type_hierarchy_handler() --- @see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#window_logMessage @@ -690,6 +706,7 @@ end --- @nodoc --- @type table +---@diagnostic disable-next-line: deprecated M = vim.tbl_extend('force', M, RSC, NSC, RCS) -- Add boilerplate error validation and logging for all of these. diff --git a/runtime/lua/vim/lsp/linked_editing_range.lua b/runtime/lua/vim/lsp/linked_editing_range.lua index 8d37c074dd..6b66caed0d 100644 --- a/runtime/lua/vim/lsp/linked_editing_range.lua +++ b/runtime/lua/vim/lsp/linked_editing_range.lua @@ -227,7 +227,7 @@ end ---@param enable boolean? `true` or `nil` to enable, `false` to disable. ---@param filter vim.lsp.capability.enable.Filter? function M.enable(enable, filter) - vim.lsp._capability.enable('linked_editing_range', enable, filter) + lsp._capability.enable('linked_editing_range', enable, filter) end return M diff --git a/runtime/lua/vim/lsp/on_type_formatting.lua b/runtime/lua/vim/lsp/on_type_formatting.lua index 67c6d012af..5221d62640 100644 --- a/runtime/lua/vim/lsp/on_type_formatting.lua +++ b/runtime/lua/vim/lsp/on_type_formatting.lua @@ -37,7 +37,7 @@ local function on_type_formatting(err, result, ctx) return end - local client = assert(vim.lsp.get_client_by_id(ctx.client_id)) + local client = assert(lsp.get_client_by_id(ctx.client_id)) util.apply_text_edits(result, ctx.bufnr, client.offset_encoding) end @@ -246,8 +246,10 @@ function M.enable(enable, filter) filter = filter or {} if filter.client_id then - local client = - assert(lsp.get_client_by_id(filter.client_id), 'Client not found for id ' .. filter.client_id) + local client = lsp.get_client_by_id(filter.client_id) + if not client then + error('Client not found for id ' .. filter.client_id) + end toggle_for_client(enable, client) else toggle_globally(enable) diff --git a/runtime/lua/vim/lsp/semantic_tokens.lua b/runtime/lua/vim/lsp/semantic_tokens.lua index 9951d39f25..4f50ebf27a 100644 --- a/runtime/lua/vim/lsp/semantic_tokens.lua +++ b/runtime/lua/vim/lsp/semantic_tokens.lua @@ -111,6 +111,7 @@ local function tokens_to_ranges(data, bufnr, client, request, ranges) -- If it's stale, we don't resume the coroutine so it'll be garbage collected. if version == util.buf_versions[bufnr] + ---@diagnostic disable-next-line: preferred-local-alias and request_id == request.request_id and api.nvim_buf_is_valid(bufnr) then @@ -457,7 +458,7 @@ end --- @return lsp.Range function STHighlighter:get_overscan_range() local wins = vim.fn.win_findbuf(self.bufnr) - local num_lines = vim.api.nvim_buf_line_count(self.bufnr) + local num_lines = api.nvim_buf_line_count(self.bufnr) local min_start, max_end = nil, nil for _, win in ipairs(wins) do @@ -775,7 +776,7 @@ end ---@private ---@param state STClientState -function STHighlighter:reset_timer(state) +function STHighlighter.reset_timer(_, state) local timer = state.timer if timer then state.timer = nil diff --git a/runtime/lua/vim/lsp/sync.lua b/runtime/lua/vim/lsp/sync.lua index 24a23183f8..7d3beef106 100644 --- a/runtime/lua/vim/lsp/sync.lua +++ b/runtime/lua/vim/lsp/sync.lua @@ -106,8 +106,8 @@ local function compute_start_range( ) position_encoding = position_encoding or 'utf-8' - local char_idx --- @type integer? - local byte_idx --- @type integer? + local char_idx --- @type integer + local byte_idx --- @type integer -- If firstline == lastline, no existing text is changed. All edit operations -- occur on a new line pointed to by lastline. This occurs during insertion of -- new lines(O), the new newline is inserted at the line indicated by diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index 7a8e8d6812..8abf66d4a8 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -70,6 +70,8 @@ local function get_border_size(opts) -- border specified as a list of border characters return e end + -- EmmyLua rejects `never` as a subtype of the declared string result. + ---@diagnostic disable-next-line: return-type-mismatch return border_error(border) end @@ -280,10 +282,10 @@ function M.apply_text_edits(text_edits, bufnr, position_encoding, change_annotat 'change_annotations must be provided for annotated text edits' ) - local annotation = assert( - change_annotations[text_edit.annotationId], - string.format('No change annotation found for ID: %s', text_edit.annotationId) - ) + local annotation = change_annotations[text_edit.annotationId] + if not annotation then + error(string.format('No change annotation found for ID: %s', text_edit.annotationId)) + end if annotation.needsConfirmation then confirmations[text_edit.annotationId] = (confirmations[text_edit.annotationId] or 0) + 1 @@ -365,7 +367,7 @@ function M.apply_text_document_edit( position_encoding, change_annotations ) - vim.validate('position_encoding', position_encoding, 'string') + validate('position_encoding', position_encoding, 'string') local text_document = text_document_edit.textDocument local bufnr = vim.uri_to_bufnr(text_document.uri) @@ -548,8 +550,8 @@ end ---@param position_encoding 'utf-8'|'utf-16'|'utf-32' (required) ---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_applyEdit function M.apply_workspace_edit(workspace_edit, position_encoding) - vim.validate('workspace_edit', workspace_edit, 'table') - vim.validate('position_encoding', position_encoding, 'string') + validate('workspace_edit', workspace_edit, 'table') + validate('position_encoding', position_encoding, 'string') if workspace_edit.documentChanges then for idx, change in ipairs(workspace_edit.documentChanges) do @@ -597,6 +599,7 @@ end --- Note that if the input is of type `MarkupContent` and its kind is `plaintext`, --- then the corresponding value is returned without further modifications. --- +---@diagnostic disable-next-line: deprecated ---@param input lsp.MarkedString|lsp.MarkedString[]|lsp.MarkupContent ---@param contents string[]? List of strings to extend with converted lines. Defaults to {}. ---@return string[] extended with lines of converted markdown. @@ -867,7 +870,7 @@ end ---@param opts? vim.lsp.util.show_document.Opts ---@return boolean `true` if succeeded function M.show_document(location, position_encoding, opts) - vim.validate('position_encoding', position_encoding, 'string') + validate('position_encoding', position_encoding, 'string') -- location may be Location or LocationLink local uri = location.uri or location.targetUri @@ -919,10 +922,10 @@ function M.show_document(location, position_encoding, opts) -- nvim_win_set_cursor clamps to last char at EOL. In insert mode the cursor -- should be past the last char (append position). - if vim.api.nvim_get_mode().mode == 'i' then + if api.nvim_get_mode().mode == 'i' then local line = api.nvim_buf_get_lines(bufnr, row, row + 1, false)[1] or '' if col >= #line then - vim.api.nvim_feedkeys(vim.keycode(''), 'n', false) + api.nvim_feedkeys(vim.keycode(''), 'n', false) end end end @@ -979,10 +982,10 @@ local function is_float(winnr) end ---Returns true if the line is empty or only contains whitespace. ----@param line string +---@param line string? ---@return boolean local function is_blank_line(line) - return line and line:match('^%s*$') + return line ~= nil and line:match('^%s*$') ~= nil end ---Returns true if the line corresponds to a Markdown thematic break. @@ -1131,7 +1134,7 @@ function M.stylize_markdown(bufnr, contents, opts) --- @param line string --- @param match {type:string,ft:string} - --- @return string + --- @return string? local function match_end(line, match) local pattern = matchers[match.type] return line:match(string.format('^%%s*%s%%s*$', pattern[3])) @@ -1733,7 +1736,7 @@ end) ---@param position_encoding 'utf-8'|'utf-16'|'utf-32' ---@return vim.quickfix.entry[] # See |setqflist()| for the format function M.locations_to_items(locations, position_encoding) - vim.validate('position_encoding', position_encoding, 'string') + validate('position_encoding', position_encoding, 'string') local items = {} --- @type vim.quickfix.entry[] @@ -1793,7 +1796,7 @@ end ---@param position_encoding 'utf-8'|'utf-16'|'utf-32' ---@return vim.quickfix.entry[] # See |setqflist()| for the format function M.symbols_to_items(symbols, bufnr, position_encoding) - vim.validate('position_encoding', position_encoding, 'string') + validate('position_encoding', position_encoding, 'string') bufnr = vim._resolve_bufnr(bufnr) @@ -1814,6 +1817,7 @@ function M.symbols_to_items(symbols, bufnr, position_encoding) if filename and range then local kind = protocol.SymbolKind[symbol.kind] or 'Unknown' + ---@diagnostic disable-next-line: deprecated local is_deprecated = not vim.isnil(symbol.deprecated or nil) or ( not vim.isnil(symbol.tags) @@ -1958,7 +1962,7 @@ end ---@return integer `position_encoding` index of the character in line {row} column {col} in buffer {buf} function M.character_offset(buf, row, col, position_encoding) vim.deprecate('vim.lsp.util.character_offset', 'vim.str_utfindex', '0.14') - vim.validate('position_encoding', position_encoding, 'string') + validate('position_encoding', position_encoding, 'string') local line = get_line(buf, row) return vim.str_utfindex(line, position_encoding, col, false) diff --git a/runtime/lua/vim/pack.lua b/runtime/lua/vim/pack.lua index 754224ec31..93832427b8 100644 --- a/runtime/lua/vim/pack.lua +++ b/runtime/lua/vim/pack.lua @@ -878,7 +878,7 @@ local function install_list(plug_list, confirm) trigger_events(plug_list, 'PackChangedPre', 'install') run_list(plug_list, do_install, 'Installing plugins') local installed = vim.tbl_filter(function(p) --- @param p vim.pack.Plug - return p.info.installed + return p.info.installed == true end, plug_list) trigger_events(installed, 'PackChanged', 'install') end @@ -1023,7 +1023,7 @@ local function lock_sync(confirm, specs) -- Compute installed plugins local plug_dir = get_plug_dir() - if vim.uv.fs_stat(plug_dir) == nil then + if uv.fs_stat(plug_dir) == nil then vim.fn.mkdir(plug_dir, 'p') end @@ -1351,7 +1351,7 @@ end --- @param bufnr integer --- @return table local function get_update_map(bufnr) - local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false) + local lines = api.nvim_buf_get_lines(bufnr, 0, -1, false) --- @type table, boolean local res, is_in_update = {}, false for _, l in ipairs(lines) do @@ -1383,7 +1383,7 @@ local function update_list(plug_list) run_list(plug_list, do_update, 'Applying updates') local updated = vim.tbl_filter(function(p) --- @param p vim.pack.Plug - return p.info.updated + return p.info.updated == true end, plug_list) trigger_events(updated, 'PackChanged', 'update') end diff --git a/runtime/lua/vim/pack/_lsp.lua b/runtime/lua/vim/pack/_lsp.lua index 223ede8197..3a289f8114 100644 --- a/runtime/lua/vim/pack/_lsp.lua +++ b/runtime/lua/vim/pack/_lsp.lua @@ -79,11 +79,11 @@ end --- @param line string Buffer line to find a link in --- @param pattern string Pattern matching link location and contents, like `'^Path: +()(.+)()$'` --- @param link_type "commit"|"path"|"src"|"tag" ---- @param lnum number Line number in a buffer +--- @param lnum integer Line number in a buffer --- @param src string Plugin source --- @return vim.pack.lsp.DocumentLink? # A link structure according to the LSP specification local function match_link(line, pattern, link_type, lnum, src) - --- @type number?, string?, number? + --- @type integer?, string?, integer? local from, match, to = line:match(pattern) if not (from and match and to) then return nil diff --git a/runtime/lua/vim/pos/_util.lua b/runtime/lua/vim/pos/_util.lua index 00bcce7654..c21a876145 100644 --- a/runtime/lua/vim/pos/_util.lua +++ b/runtime/lua/vim/pos/_util.lua @@ -94,7 +94,7 @@ function M.get_lines(buf, rows) end -- Get the data from the file. - local success, data = pcall(vim.fn.readblob, vim.api.nvim_buf_get_name(buf)) + local success, data = pcall(vim.fn.readblob, api.nvim_buf_get_name(buf)) if not success then return row_line end diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index ff9d903589..3df65f7f5e 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -199,7 +199,7 @@ end ---@param buf integer ---@param range Range ----@returns string +---@return string local function buf_range_get_text(buf, range) local start_row, start_col, end_row, end_col = M._range.unpack4(range) local append_newline = end_col == 0 and start_row ~= end_row diff --git a/runtime/lua/vim/treesitter/_range.lua b/runtime/lua/vim/treesitter/_range.lua index e6ee89d19e..ab322e8188 100644 --- a/runtime/lua/vim/treesitter/_range.lua +++ b/runtime/lua/vim/treesitter/_range.lua @@ -80,6 +80,8 @@ function M.intersection(r1, r2) if #r1 == 4 or #r2 == 4 then local rs = M.cmp_pos.le(r1[1], r1[2], r2[1], r2[2]) and r2 or r1 local re = M.cmp_pos.ge(r1[3], r1[4], r2[3], r2[4]) and r2 or r1 + -- This branch implements the Range4 overload. + ---@diagnostic disable-next-line: return-type-mismatch return { rs[1], rs[2], re[3], re[4] } end @@ -95,6 +97,8 @@ function M.unpack4(r) return r[1], 0, r[2], 0 end local off_1 = #r == 6 and 1 or 0 + -- EmmyLua does not narrow tuple fields from the range length. + ---@diagnostic disable-next-line: return-type-mismatch return r[1], r[2], r[3 + off_1], r[4 + off_1] end diff --git a/runtime/lua/vim/treesitter/dev.lua b/runtime/lua/vim/treesitter/dev.lua index aa50696238..228d434cdc 100644 --- a/runtime/lua/vim/treesitter/dev.lua +++ b/runtime/lua/vim/treesitter/dev.lua @@ -148,9 +148,8 @@ function TSTreeView:new(buf, lang) }, } - setmetatable(t, self) self.__index = self - return t + return setmetatable(t, self) end local decor_ns = api.nvim_create_namespace('nvim.treesitter.dev') diff --git a/runtime/lua/vim/treesitter/language.lua b/runtime/lua/vim/treesitter/language.lua index 2bf4d1048f..236cf1a6cb 100644 --- a/runtime/lua/vim/treesitter/language.lua +++ b/runtime/lua/vim/treesitter/language.lua @@ -2,7 +2,7 @@ local api = vim.api local M = {} ----@type table +---@type table local ft_to_lang = { help = 'vimdoc', checkhealth = 'vimdoc', diff --git a/runtime/lua/vim/treesitter/languagetree.lua b/runtime/lua/vim/treesitter/languagetree.lua index a956fc155f..765487bc05 100644 --- a/runtime/lua/vim/treesitter/languagetree.lua +++ b/runtime/lua/vim/treesitter/languagetree.lua @@ -412,6 +412,7 @@ end --- @return Range6[] changes --- @return integer no_regions_parsed --- @return number total_parse_time +--- @async function LanguageTree:_parse_regions(range, thread_state) local changes = {} local no_regions_parsed = 0 @@ -636,12 +637,15 @@ function LanguageTree:parse(range, on_parse) if on_parse then return self:_async_parse(range, on_parse) end + -- Without a timeout, parsing never yields. + ---@diagnostic disable-next-line: await-in-sync local trees, _ = self:_parse(range, {}) return trees end ---@param thread_state ParserThreadState ---@param time integer +---@async function LanguageTree:_subtract_time(thread_state, time) thread_state.timeout = thread_state.timeout and math.max(thread_state.timeout - time, 0) if thread_state.timeout == 0 then @@ -654,6 +658,7 @@ end --- @param thread_state ParserThreadState --- @return table trees --- @return boolean finished +--- @async function LanguageTree:_parse(range, thread_state) if self:is_valid(nil, type(range) == 'table' and range or nil) then self:_log('valid') @@ -1088,6 +1093,7 @@ end --- @param range Range|Range[]|true --- @param thread_state ParserThreadState --- @return table +--- @async function LanguageTree:_get_injections(range, thread_state) if not self._injection_query or #self._injection_query.captures == 0 then self._processed_injection_region = entire_document_range diff --git a/runtime/lua/vim/treesitter/query.lua b/runtime/lua/vim/treesitter/query.lua index 73d4ee7991..7e91baea9d 100644 --- a/runtime/lua/vim/treesitter/query.lua +++ b/runtime/lua/vim/treesitter/query.lua @@ -830,7 +830,7 @@ end ---@param captures table ---@param source integer|string ---@return boolean whether the predicates match -function Query:_match_predicates(predicates, pattern_i, captures, source) +function Query._match_predicates(predicates, pattern_i, captures, source) for _, predicate in ipairs(predicates) do local processed_name = predicate[1] local should_match = predicate[2] @@ -856,7 +856,7 @@ end ---@param source integer|string ---@param captures table ---@return vim.treesitter.query.TSMetadata metadata -function Query:_apply_directives(directives, pattern_i, captures, source) +function Query._apply_directives(_, directives, pattern_i, captures, source) ---@type vim.treesitter.query.TSMetadata local metadata = {} @@ -979,7 +979,7 @@ function Query:iter_captures(node, source, start_row, end_row, opts) local captures = match:captures() local predicates = processed_pattern.predicates - if not self:_match_predicates(predicates, pattern_i, captures, source) then + if not self._match_predicates(predicates, pattern_i, captures, source) then cursor:remove_match(match_id) local row, col = captured_node:range() @@ -1081,7 +1081,7 @@ function Query:iter_matches(node, source, start, stop, opts) local metadata = {} if processed_pattern then local predicates = processed_pattern.predicates - if not self:_match_predicates(predicates, pattern_i, captures, source) then + if not self._match_predicates(predicates, pattern_i, captures, source) then cursor:remove_match(match_id) return iter() -- tail call: try next match end diff --git a/runtime/pack/dist/opt/nvim.tohtml/lua/tohtml.lua b/runtime/pack/dist/opt/nvim.tohtml/lua/tohtml.lua index 09c9a24fa0..ef0e8eb504 100644 --- a/runtime/pack/dist/opt/nvim.tohtml/lua/tohtml.lua +++ b/runtime/pack/dist/opt/nvim.tohtml/lua/tohtml.lua @@ -243,6 +243,8 @@ local function cterm_to_hex(colorstr) cterm_color_cache = cterm_16_to_hex end end + -- EmmyLua retains the failed lookup narrowing after the cache is updated. + ---@diagnostic disable-next-line: return-type-mismatch return cterm_color_cache[color] end diff --git a/test/functional/treesitter/query_spec.lua b/test/functional/treesitter/query_spec.lua index f5de261d17..7aac113670 100644 --- a/test/functional/treesitter/query_spec.lua +++ b/test/functional/treesitter/query_spec.lua @@ -883,9 +883,9 @@ void ui_refresh(void) local query0 = vim.treesitter.query.parse('c', query) local match_preds = query0._match_predicates local called = 0 - function query0:_match_predicates(...) + function query0._match_predicates(...) called = called + 1 - return match_preds(self, ...) + return match_preds(...) end local parser = vim.treesitter.get_parser(0, 'c') local root = parser:parse()[1]:root()