summaryrefslogtreecommitdiffstatshomepage
path: root/test/functional
AgeCommit message (Collapse)AuthorFiles
2026-04-25fix(channel): stack-buffer-overflow with exit during connection (#39387)zeertzjq1
Problem: When Nvim exits while connecting to a socket it leads to stack-buffer-overflow. Solution: Associate the handle with the Stream and use the Stream's internal_close_cb to update the "closed" status.
2026-04-24fix(lsp): handle self-mapped methods in supports_method #39383nightlyTristan Knight1
Problem: The LSP client incorrectly checks for server capabilities when determining support for self-mapped methods (e.g., 'shutdown'), which do not have corresponding capabilities in the server's response. This leads to false negatives when checking if such methods are supported. This was handled correctly for dynamic registrations, but not for static. Methods such as 'shutdown', do not have a related server capability and should be assumed to be supported. Solution: Update the `supports_method` logic to always return true for self-mapped methods.
2026-04-24feat(tui): restore 'ttyfast' to control tty requests #38699Kyle2
Problem: When running nvim on a remote machine over SSH, if there is high ping, then bg detection may not complete in time. This results in a warning every time nvim is started. #38648 Solution: Restore 'ttyfast' option and allow it to control whether or not bg detection is performed. Because this is during startup and before any user config or commands, we use the environment variable `NVIM_NOTTYFAST` to allow disabling `ttyfast` during initialization.
2026-04-24fix(api): leak preview callback LuaRef in nvim_create_user_command #39357Barrett Ruth1
Problem: Invalid `nvim_create_user_command` calls can leak the `preview` callback reference after Neovim has taken ownership of it. 1. build with {a,l}san 2. run: ```sh <path/to/nvim> --headless -u NONE --clean +'lua for i = 1, 100 do pcall(vim.api.nvim_create_user_command, "some very epic stuff" .. i, {}, -- NOTE: this is INVALID (not a function or string) { preview = function() end }) end vim.cmd("qa!") ' +qa ``` 3. see: ``` 100 lua references were leaked! ``` Solution: Clear `preview_luaref` in `err:`.
2026-04-24fix(api): LuaRef leak in nvim_set_keymap on LHS too long (>=66 bytes) #39351Barrett Ruth1
Problem: `nvim_set_keymap` leaks the `callback` `LuaRef` when the LHS is too long. Solution: Make `set_maparg_lhs_rhs` transfer `rhs_lua` to `MapArguments` up front so the caller always owns the ref.
2026-04-24fix(path): normalize path slashes on Windows #37729tao14
Problem: On Windows, path separators may become inconsistent for various reasons, which makes normalization quite painful. Solution: Normalize paths to `/` at the entry boundaries and always use it internally, converting back only in rare cases where `\` is really needed (e.g. cmd.exe/bat scripts?). This is the first commit in a series of incremental steps. Note: * some funcs won't respect shellslash. e.g. `expand/fnamemodify` * some funcs still respect shellslash, but will be updated in a follow PR. e.g. `ex_pwd/f_chdir/f_getcwd` * uv's built-in funcs always return `\`. e.g. `uv.cwd/uv.exepath` Co-authored-by: Justin M. Keyes <justinkz@gmail.com>
2026-04-24feat(api): nvim_echo(percent=nil) means "unknown" progress #39029Peter Cardenas1
Problem: No way to signal "unknown" or "indeterminate" progress percentage. Solution: Treat percent=nil as "indeterminate" percent.
2026-04-24test: curbuf initialized in describe-block #39365glepnir1
Problem: curbuf was initialized at describe-block load time before any Nvim session existed. Solution: Replace with 0 directly at call sites.
2026-04-24fix(lsp): more info in error msg, deduplicate test #39359Justin M. Keyes1
2026-04-24fix(trust): always use "/" slashes in filepaths #39355Justin M. Keyes3
Problem: We should not use "\" (backslashes) except where absolutely required. See references in https://github.com/neovim/neovim/pull/37729 Solution: There is no reason to use "\" slashes in the trust db, so don't.
2026-04-23fix(options): repair stale UI state after `:set all&` #39026Barrett Ruth2
Problem: `set all&` resets option values directly and leaves UI-derived state stale for `guicursor`, `laststatus`, and `showtabline`. Solution: Repair some of the stale UI state in the bulk reset path by reparsing `guicursor`, refreshing statusline state, and recomputing tabline/window rows.
2026-04-23feat(excmd): add :uptime command #39331Olivia Kinnear3
Problem Nvim marks its v:starttime, but there is no user-friendly way to get Nvim's uptime. Solution Add :uptime (based loosely on uptime(1)).
2026-04-23refactor(test): deduplicate trust tests #39354Justin M. Keyes2
2026-04-23fix(lsp): handle null id in JSON-RPC responses #38340atusy1
Problem: LSP spec allows response message to have a null request-id. This may happen when for example client sends unparseable request. https://github.com/microsoft/language-server-protocol/issues/196 Solution: Guard the server response branches against id=vim.NIL (json null), and handle error responses with null id by logging a warning and dispatching on error. Problem: CI (ubuntu asan, ubuntu tsan, windows) reports `uv_loop_close() hang?` from the two new null-id response tests. The leaked handle is the server-side accepted TCP socket created inside `server:listen` callback. The tests closed only the listener but not the accepted socket, so libuv could not finish shutting down the loop and each test session took ~2s extra to exit. Solution: Hoist the accepted socket to the outer `exec_lua` scope and close it at teardown before closing the listener. The close runs synchronously inside `exec_lua`, so the loop has time to dispose the handle before the session exits. * test(lsp): close accepted socket on read-loop exit/error Match the precedent in the handler test ("handler can return false as response") and the shared `_create_tcp_server` helper in `test/functional/plugin/lsp/testutil.lua`: close the accepted socket from inside the `create_read_loop` exit/error callbacks. The teardown close added in the previous commit remains as belt-and-suspenders, so the socket is disposed whether the server goes away first or the client does.
2026-04-23fix(trust): hash unchanged empty buffers as empty files #39027Barrett Ruth2
Problem: `vim.secure.trust()` hashes an unchanged empty buffer as a newline, so trusting an empty file by buffer never works. Solution: Hash unchanged empty-buffers `''` so buffer-based trust matches the on-disk empty file.
2026-04-23fix(pack): only use tags that strictly comply with semver spec #39342Evgeni Chasnovski1
Problem: Using `version=vim.version.range(...)` in plugin specification is meant to use semver-like tags. Whether a tag is semver-like was decided by a plain `vim.version.parse` which is not strict by default. This allowed treating tags like `nvim-0.6` (which is usually reserved for the latest revision compatible with Nvim<=0.6 version) like semver tags and resulted in confusing behavior (preferring `nvim-0.6` tag over `v0.2.2`, for example). Solution: Use `vim.version.range(x, { strict = true })` to decide if the tag name is semver-like or not. This allows tags like both `v1.2.3` and `1.2.3` while being consistent in what Nvim thinks is a semver string. This is technically not a breaking change since it was documented that only tags like `v<major>.<minor>.<patch>` will be recognized as semver.
2026-04-23Merge pull request #39339 from bfredl/reunificationbfredl1
fix(build.zig): reunify parser install path
2026-04-23fix(build.zig): reunify parser install pathbfredl1
Both for tests and for system wide install, $PREFIX/lib/nvim/parser is a valid path for tree-sitter parsers. This also brings the build.zig behavior in line with how we set up the paths in CMakeLists.txt
2026-04-23fix(lsp): callHierarchy/outgoingCalls ranges are relative to caller, not ↵Ashley Hauck1
callee #39336 Problem: The fromRanges field of the result of callHierarchy/outgoingCalls is documented as being relative to the caller. Using vim.lsp.buf.outgoing_calls() opened the qflist with an entry with the callee's filename, but the caller's line number. Solution: Open the qflist with the callers file (the bufnr from the request), rather than the callees (the uri from the resulting CallHierarchyItem)
2026-04-23fix(lsp): filter code_action diagnostics to the cursor #38988Barrett Ruth1
Problem: Cursor-position `vim.lsp.buf.code_action()` requests include all diagnostics on the current line, so unrelated same-line diagnostics affect the returned actions. Solution: Filter same-line diagnostics to the cursor position for cursor-position requests.
2026-04-23fix(terminal): memory leak in pending TermRequest StringBuilder #39333Barrett Ruth1
Problem: Destroying a terminal with pending `TermRequest` events leaks memory. Solution: Make `emit_termrequest` the sole owner of its `pending_send` allocation.
2026-04-22ci: drop cirrus #39321Justin M. Keyes4
Problem: cirrus will shutdown soon, and we are running out of minutes anyway, which causes ci failures. Solution: Drop cirrus config.
2026-04-22feat(treesitter): expand selection to sibling node #38938altermo1
Problem: Can't expand treesitter-incremental-selection to the next and previous sibling nodes. Solution: Pressing `]N` in visual mode will expand the selection to the next sibling node, and `[N` will do the same with the previous node.
2026-04-22feat(:restart): v:starttime, v:exitreason #39282Justin M. Keyes3
Problem: - The `ZR` feature makes it more obvious that we need some sort of flag so that an `ExitPre` / `QuitPre` / `VimLeave` handler can handle restarts differently than a normal exit. For example, it's common that users want `:mksession` on restart, but perhaps not on a normal exit. - Nvim has no way to report its "uptime". Solution: - Introduce `v:starttime` - Introduce `v:exitreason`
2026-04-22feat(eval): treat Lua string as "blob" in writefile() #39098Barrett Ruth1
Problem: vim.fn.writefile() treats Lua strings as Vimscript strings instead of a "binary clean" string. Solution: Treat Lua-originated strings as blob data.
2026-04-22fix(shada): bdelete'd buffers not stored in oldfiles #39070glepnir1
Problem: b98eefd added `!b_p_bl` to `ignore_buf()`, which also skips bdelete'd buffers since bdelete unsets `b_p_bl`. Solution: Check `b_p_initialized` together with `b_p_bl` so that bdelete'd buffers (which have b_p_initialized=false) are not filtered out. Keep `b_p_bl` check only in `shada_get_buflist()`.
2026-04-22perf(lsp): clear table by table.clear() #39222Yi Ming1
benchmark: https://gist.github.com/ofseed/6224529d77c016c36f7ab2f977059848 local rounds = tonumber(arg[1]) or 1000 local count = tonumber(arg[2]) or 1000 -- Load the table.clear function. local clear = require("table.clear") local function fill(t, n) for i = 1, n do t[i] = i end end local function bench_reassign(n_rounds, n_items) local t = {} local start = os.clock() for _ = 1, n_rounds do t = {} collectgarbage("collect") fill(t, n_items) end return os.clock() - start end local function bench_reassign_no_gc(n_rounds, n_items) local t = {} local start = os.clock() for _ = 1, n_rounds do t = {} fill(t, n_items) end return os.clock() - start end local function bench_clear(n_rounds, n_items) local t = {} local start = os.clock() for _ = 1, n_rounds do clear(t) fill(t, n_items) end return os.clock() - start end -- Warm up LuaJIT before the real benchmark. do local t = {} for _ = 1, 2000 do clear(t) fill(t, count) end end collectgarbage("collect") local reassign_time = bench_reassign(rounds, count) collectgarbage("collect") local reassign_no_gc_time = bench_reassign_no_gc(rounds, count) collectgarbage("collect") local clear_time = bench_clear(rounds, count) print(string.format("rounds=%d count=%d", rounds, count)) print(string.format("t = {} + GC : %.6f s", reassign_time)) print(string.format("t = {} : %.6f s", reassign_no_gc_time)) print(string.format("table.clear : %.6f s", clear_time)) print(string.format("vs + GC : %.2fx", reassign_time / clear_time)) print(string.format("vs no GC : %.2fx", reassign_no_gc_time / clear_time)) benchmark result: rounds=1000 count=1000 t = {} + GC : 0.022469 s t = {} : 0.002570 s table.clear : 0.000387 s vs + GC : 58.06x vs no GC : 6.64x `count` is how many items the table has, and `round` is how many rounds we fill the table, clear, and then refill it. `table = {}` is clear the table by resigning a new empty one, because this script does not run persistently like nvim so GC is not triggered, so I added another extreme control group that manually triggers GC.
2026-04-22fix(cmdline): avoid 'incsearch' recursion after redraw #39303luukvbaal1
Problem: A vim.ui_attach() callback that redraws to show a 'verbose' regex message during 'incsearch' results in recusive redrawing. Solution: Check that curwin was redrawn instead of just any window when determining if 'incsearch' highlighting was cleared.
2026-04-22fix(options): default 'titlestring' shows CWD #39233Nick Krichevsky2
Problem: In the default 'titlestring', if the containing directory is the CWD, it renders as "." Solution: Add `:p` to the titlestring.
2026-04-22fix(pack): GIT_DIR/GIT_WORK_TREE env vars may interfere #39279fleesk1
Problem: With GIT_DIR/GIT_WORK_TREE set, the LSP on the vim.pack.update() confirmation buffer does not show the correct git log on hover. Solution: Temporarily remove the git vars from the environment.
2026-04-22fix(cmd): ++p, ++edit should match "word" boundary #39146glepnir1
Problem: `:write ++patate foo` doesn't error out, instead it turns on mkdir_p and uses "atate foo" as the filename. Same with ++edit. The parser just does strncmp without checking what comes after. Solution: require the next char after the option name to not be a letter
2026-04-22vim-patch:9.2.0356: Cannot apply 'scrolloff' context lines at end of filezeertzjq1
Problem: Cannot apply 'scrolloff' context lines at end of file Solution: Add the 'scrolloffpad' option to keep 'scrolloff' context even when at the end of the file (McAuley Penney). closes: vim/vim#19040 https://github.com/vim/vim/commit/a414630393f81c9a5b8fa4d0fcc1287155f67751 Co-authored-by: McAuley Penney <jacobmpenney@gmail.com>
2026-04-22fix(incsearch): support `c_CTRL-{G,T}` with an offset (#39097)Barrett Ruth1
vim-patch:9.2.0374: c_CTRL-{G,T} does not handle offset Problem: c_CTRL-{G,T} does not handle offset, when cycling between matches Solution: Refactor parsing logic into parse_search_pattern_offset() and handle offsets, note: highlighting does not handle offsets yet (Barrett Ruth). fixes: vim/vim#19991 closes: vim/vim#19998 https://github.com/vim/vim/commit/c62342e5cfc339a87c1eb40ef34b2b31070d72a6
2026-04-22test(tui_spec): fix "Uncaught Error" with PUC Lua (#39288)zeertzjq1
RUN T339 TUI :restart ZR: Uncaught Error: test/client/uv_stream.lua:111: ECONNRESET stack traceback: [C]: in function 'error' test/client/uv_stream.lua:111: in function <test/client/uv_stream.lua:109> [C]: in function 'run' test/client/session.lua:240: in function '_run' test/client/session.lua:216: in function '_blocking_request' test/client/session.lua:117: in function 'request' ...t_xdg_terminal/test/functional/terminal/tui_spec.lua:223: in function <...t_xdg_terminal/test/functional/terminal/tui_spec.lua:215> [C]: in function 'pcall' test/testutil.lua:82: in function 'retry' ...t_xdg_terminal/test/functional/terminal/tui_spec.lua:215: in function 'assert_restarted' ...t_xdg_terminal/test/functional/terminal/tui_spec.lua:275: in function <...t_xdg_terminal/test/functional/terminal/tui_spec.lua:232> [C]: in function 'xpcall' /home/runner/work/neovim/neovim/test/harness.lua:693: in function 'run_callable' /home/runner/work/neovim/neovim/test/harness.lua:1008: in function 'run_test' /home/runner/work/neovim/neovim/test/harness.lua:1083: in function 'run_suite' /home/runner/work/neovim/neovim/test/harness.lua:1081: in function 'run_suite' /home/runner/work/neovim/neovim/test/harness.lua:1081: in function 'run_suite' /home/runner/work/neovim/neovim/test/harness.lua:1507: in function 'run_test_file' /home/runner/work/neovim/neovim/test/harness.lua:1577: in function 'run_iteration' /home/runner/work/neovim/neovim/test/harness.lua:1665: in function 'main' /home/runner/work/neovim/neovim/test/runner.lua:30: in main chunk -- Tests exited non-zero: 255 CMake Error at /home/runner/work/neovim/neovim/cmake/RunTests.cmake:135 (message): functional tests failed with error: 255
2026-04-21fix(messages): "progress" kind for busy messages #39280luukvbaal2
Problem: The "Scanning:" completion, bufwrite, and indent (there may be more) messages which indicate progress can use the "progress" kind for their msg_show event. Indent message does not have a kind. Solution: Emit these messages with the "progress" kind. Set the message id to the replaced kind so that a UI knows to replace it (and to provide a migration path in case a UI was distinguishing these messages for whatever reason).
2026-04-21Merge pull request #39076 from bfredl/zig0.16bfredl1
IT IS HAPPENING: Zig 0.16
2026-04-21fix(:restart): reuse --listen addr on Windows #38539Sanzhar Kuandyk2
Problem: On Windows, :restart cannot immediately reuse the canonical --listen address because named pipe release is asynchronous. Solution: Start the new Nvim server on a temporary address; in the new Nvim, retry serverstart() with the original ("canonical") address until it succeeds.
2026-04-21feat(normal): normal-mode ZR does :restartJustin M. Keyes1
Make it a normal-mode command instead of a default mapping.
2026-04-21fix(substitute): don't crash with very large count (#39272)zeertzjq1
2026-04-21fix(build): more changes to make zig 0.16.0 workbfredl1
2026-04-20refactor(test): drop deprecated exc_exec #39242Justin M. Keyes77
2026-04-20fix(ui2): don't dismiss expanded messages for non-typed key #39247luukvbaal1
Problem: Invalid check for non-typed key to dismiss expanded cmdline. Unable to delay the timer that removes a message from the msg window. Solution: Check for empty string instead of nil to determine whether a key is typed. Restart the timer if it expires while the user is in the msg window. Allow entering the msg window with a mouse click.
2026-04-20fix(ui2): ensure msg window is visible after closing tabLuuk van Baal1
Problem: After closing a tabpage while the msg window is showing a message, it is hidden while the msg window still contains a message. Solution: Unhide the msg window after entering a tabpage and it still contains a message. Co-authored-by: Linykq <yukunlin590@gmail.com>
2026-04-20fix(api): expose fg_indexed/bg_indexed in nvim_get_hl #39210glepnir1
Problem: fg_indexed/bg_indexed were dropped from nvim_get_hl output due to a wrong short_keys guard. HL_FG_INDEXED also wasn't cleared in hl_blend_attrs, and HLATTRS_DICT_SIZE was too small. Solution: Remove the short_keys guard, clear HL_FG_INDEXED in hl_blend_attrs, bump HLATTRS_DICT_SIZE to 24, and clarify docs that these flags mean rgb is an approximation of the cterm palette index.
2026-04-20Merge #39194 from justinmk/luavimfnJustin M. Keyes2
2026-04-20fix(smoothscroll): crash when resizing to textoff with showbreakJaehwang Jung1
vim-patch:9.2.0362: division by zero with smoothscroll and small windows Problem: Resizing a smoothscrolled wrapped window to its textoff width with 'showbreak' can leave wrapped continuation lines with zero text width. win_lbr_chartabsize() still runs the partial max_head_vcol calculation in that state and divides by width2, crashing during redraw. Solution: Skip that partial head calculation when the wrapped continuation width is zero, matching the other width2 guards in charset.c (Jaehwang Jung) closes: vim/vim#20012 AI-assisted: Codex https://github.com/vim/vim/commit/0e31fb024c846e36bb0d26d01ff179a0d1b3eae4
2026-04-19feat(options): add 'winpinned' to pin a window #39157luukvbaal2
Problem: - Unable to "pin" a window to prevent closing without specifically being targeted. - :fclose closes hidden windows (even before visible windows). Solution: - Add 'winpinned' window-local option. When set, window is skipped by :fclose and :only. Pin the ui2 cmdline window (which should always be visible), so that it is not closed by :only/fclose. - Skip over hidden (and pinned) windows with :fclose. Co-authored-by: glepnir <glephunter@gmail.com>
2026-04-20fix(excmd): nlua_call_excmd require() failure is a "lua_error"Justin M. Keyes2
Although `nlua_call_excmd` is semantically for implementing Ex-commands, the `require()` should never fail, so that's a "Lua error". But if the call itself fails (the later `semsg` call), that's an "Ex cmd" error.
2026-04-19fix(drawline): hang while redrawing diff filler above fold #39219Jaehwang Jung1
Problem: win_line() falls into infinite loop when a diff window has top filler above its first visible buffer line, that first visible buffer line is a closed fold, and the folded line uses normal non-empty foldtext. Solution: Allow flushing pending diff filler rows even when the underlying buffer line is folded with foldtext. AI-assisted: Codex Co-authored-by: zeertzjq <zeertzjq@outlook.com>
2026-04-19feat(events): trigger MarkSet autocmd in :delmarks #39156Ashley Hauck1
Problem: `api.nvim_buf_del_mark` already emits a `MarkSet` event with `col` and `line` set to 0. However, `:delmarks` currently emits no events. Solution: Change `:delmarks` to emit the same `col==line==0` event.