Commit Graph

36150 Commits

Author SHA1 Message Date
Matthew Hughes
20a2398877 docs: Update instructions for debugging LSP (#39527)
docs: update instructions for debugging LSP

Previously, it was suggested to set:

    vim.lsp.log.set_format_func(vim.inspect)

This made sense before f72c13341a, when
`format_func` was called once per argument being logged, but since that
commit it's called with the log level followed by the other args, so the
suggested setting would call `vim.inspect(log_level, ....)` which would
just print the human readable name of the current log level and no other
details, for example with this set I saw in my logs:

    "DEBUG""DEBUG""DEBUG""DEBUG"

Instead just rely on the default formatter, which will:

> ... log the level, date, source and line number of the
caller, followed by the arguments.

(cherry picked from commit 578727c25e)
2026-04-30 22:05:37 +00:00
Justin M. Keyes
4b424a06c5 backport fix(lsp): send didClose, didOpen when languageId changes (#39519)
fix(lsp): send didClose, didOpen when languageId changes

Problem:
If a buffer's filetype changes after the LSP client has already
attached (e.g. from json to jsonc via a modeline), but the client
supports both filetypes, it stays attached. It does not notify the
server of the new languageId, causing the server to incorrectly process
the file using the old languageId.

Solution:
Save the languageId used during textDocument/didOpen, and send
textDocument/didClose + textDocument/didOpen when buffer's languageId
changed.

Lsp spec:
0003fb53f1/_specifications/lsp/3.18/textDocument/didOpen.md (L5)
> If the language id of a document changes, the client
> needs to send a textDocument/didClose to the server followed by a
> textDocument/didOpen with the new language id if the server handles
> the new language id as well.

AI-assisted: Gemini 3.1 Pro

Co-authored-by: phanium <91544758+phanen@users.noreply.github.com>
2026-04-30 13:09:55 +00:00
Justin M. Keyes
d147d0434d Merge pull request #39512 from justinmk/release
backports
2026-04-29 20:30:32 -04:00
Justin M. Keyes
4ee47a56ec docs: misc 2026-04-30 02:08:19 +02:00
Till Bungert
822778f7e5 fix(excmd): use realtime for v:starttime, :uptime #39425
Problem:
`v:starttime`, `:uptime` use a monotonic high-resolution timer. This
only works as long as the timer keeps running (if the computer is
suspended the timer is paused). This is somewhat unintuitive, and
doesn't match the behavior of the `uptime` shell command.

Solution:
Implement `os_realtime` to get the real time since the
epoch in nanoseconds.
2026-04-29 23:41:41 +02:00
Olivia Kinnear
c9ca59ad28 backport: fix(lsp): util.lua attempt to concatenate userdata #39510
Problem:
Error when querying document symbols using python-lsp-server:

    lsp/util.lua:1955: attempt to concatenate field 'containerName' (a userdata value)

Solution:
Check for `vim.NIL`.

(cherry picked from commit 1799aaebda)
2026-04-29 16:13:47 -04:00
neovim-backports[bot]
378f5f49b3 backport: fix(lsp): show meaningful error on invalid completion response (#39476)
Problem: vim.NIL is truthy in Lua, so `#(result.items or result)`
crashes on `#vim.NIL` when servers return null.

Solution: skip spec-allowed result=null silently, raise an error
on items=null with the server name.

https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_completion
(cherry picked from commit b9431b340f)

Co-authored-by: glepnir <glephunter@gmail.com>
2026-04-28 11:27:50 -04:00
neovim-backports[bot]
24a4bf20c0 backport: fix(termdebug): fix evaluate display with gdb pretty print (#39475)
Calling `set print pretty on` in GDB will:

> Cause GDB to print structures in an indented format with one member
per line

However, `termdebug` just renders the newlines as raw `\n` characters.
This is a regression of[1]. Glancing through the history it looks to
have been caused by cd1b14f027 which
removed the output splitting when displaying the eval results, so this
changes adds that behaviour back.

As a quick reproduction/test, compile the following C program:

```c

struct Foo {
    char *name;
};

int main(void) {
    struct Foo f = {"hello"};
    printf("%s\n", f.name);

    return 0;
}
```

Then launch `nvim` and run:

    :Termdebug main
    :Gdb
    (gdb) set print pretty on
    (gdb) break main
    (gdb) run
    :Source

Place the cursor on the `f` variable and call `:Evaluate`. Before this change:

![](https://github.com/user-attachments/assets/51318e1e-9cdd-43ab-aa35-4aaad1d9f65f)

With this change:

![](https://github.com/user-attachments/assets/33874679-21b4-4d07-98ef-c2c9e9d19dd6)

Link: https://github.com/neovim/neovim/issues/10020 [1]
(cherry picked from commit c06e3d6f81)

Co-authored-by: Matthew Hughes <matthewhughes934@gmail.com>
2026-04-28 11:25:53 -04:00
zeertzjq
34bf0472ab fix(marks): don't use spell decorations from other lines (#39441)
Spell decorations from other lines aren't relevant to the current line.
Also, decor_redraw_col() can only go forward, while spell navigation
needs to go both forward and backward.

(cherry picked from commit 46c83ce321)
2026-04-27 23:36:36 +00:00
Yi Ming
96d5dd4107 perf(vim.pos): use numeric index internally #39447
(cherry picked from commit d40875a2f8)
2026-04-27 18:26:02 +00:00
Justin M. Keyes
0f6f5cd0a7 Merge pull request #39428 from justinmk/release
backport
2026-04-26 16:30:12 -04:00
Justin M. Keyes
d735ce36ec docs: sort quasi-keysets 2026-04-26 22:02:34 +02:00
Justin M. Keyes
b1b489b316 build(docs): sort/lint class fields and keysets
Problem:
Fields (key names) in classes, keysets, and quasi-keysets are ordered
randomly, which adds friction when reading docs.

Solution:
- Sort class fields and keysets when generating docs.
- Add a lint check for quasi-keysets (keysets defined as unstructured
  markdown lists within a docstring).
2026-04-26 22:00:11 +02:00
Justin M. Keyes
534b1a8e7e docs: vim.ui.select, misc
(cherry picked from commit d960ae6760)
2026-04-26 19:45:57 +00:00
Justin M. Keyes
e77e260d36 docs: lsp.CodeActionContext, nested @inlinedoc
- fix https://github.com/neovim/neovim/issues/39208
- fix generation of neste `@inlinedoc` classes

(cherry picked from commit 825bfba789)
2026-04-26 19:45:57 +00:00
Justin M. Keyes
fb56d50032 fix(eval): writestring() handling of null #39328
Problem:
- write_blob, write_string dereference args which may be NULL.
- `writefile(v:_null_blob, …)` fails.

Solution:
- Fix the annotation.
- Handle null blob.

Co-authored-by: zeertzjq <zeertzjq@outlook.com>
(cherry picked from commit 6d0cdcd605)
2026-04-26 14:27:11 +00:00
Justin M. Keyes
35a5ac9aa6 Merge pull request #39419 from justinmk/release
backports
2026-04-26 07:40:27 -04:00
Luis Calle
2ec758f403 fix(vim.range): validate arguments on all cases #39415 2026-04-26 12:41:06 +02:00
Luis Calle
49efe692f3 feat(vim.pos): accept buf=0 for current buf #39414 2026-04-26 12:41:06 +02:00
Yi Ming
828a35b14f feat(docs): render class dot members as module functions
AI-assisted: Codex
2026-04-26 12:39:45 +02:00
Yi Ming
b6ccf44aef revert: "docs: vim.range, vim.pos #38869"
This reverts commit c530fd8e75.
2026-04-26 12:39:45 +02:00
Barrett Ruth
53d34ba719 ci(news): only rerun on ci:skip-news label changes #39399
Problem: The news workflow reruns on unrelated label events.

Solution: Only reevaluate the job when the changed label is
`ci:skip-news`.

(cherry picked from commit 1aeaa61bcf)
2026-04-25 22:15:48 +00:00
Justin M. Keyes
26678ebbd8 backport: docs: misc (#39395) 2026-04-25 13:51:22 -04:00
neovim-backports[bot]
cf17575b7b backport: docs(vim.ui): document an interface for vim.ui.select preview (#39401)
Problem: Plugins may want to have a way to show more details about items
  when using `vim.ui.select`. This is a fairly common problem that
  prompts plugin authors to implement dedicated sources/pickers for
  fuzzy picker plugins that are popular at the moment.

Solution: Document a way for `vim.ui.select` to provide preview:
  - `vim.ui.select` users can provide `opts.preview_item` function that
    creates/uses a buffer and its contents at certain position to show
    more details about an item.
  - `vim.ui.select` implementations may use `opts.preview_item` in the
    way they see fit (like show the buffer in a separate/same window
    interactively/on-demand or do nothing) if they have a way to show
    more information about an item.
(cherry picked from commit c44df255aa)

Co-authored-by: Evgeni Chasnovski <evgeni.chasnovski@gmail.com>
2026-04-25 13:48:07 -04:00
Yi Ming
5e6c8d4edf fix(lsp): check window is still valid after async request #39396
Problem:
Since `foldclose` is async, it must wait for the request to return before actually executing, at which point the original window may no longer be valid.

Solution:
Check whether the window is valid before actually performing `foldclose`.

(cherry picked from commit 775c7d1b53)
2026-04-25 16:55:31 +00:00
zeertzjq
f0baa18043 fix(channel): stack-buffer-overflow with exit during connection (#39387)
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.
(cherry picked from commit 4ed2e66d2e)
2026-04-25 12:38:20 +00:00
zeertzjq
e5114d03b5 test: add finally() to meta file (#39388)
(cherry picked from commit df8cf0ed25)
2026-04-25 10:10:25 +00:00
Tristan Knight
aedbae4ab6 fix(lsp): handle self-mapped methods in supports_method #39383
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.

(cherry picked from commit f83d0b9653)
2026-04-24 23:19:16 +00:00
neovim-backports[bot]
e5d6d2e769 backport: fix(api): leak preview callback LuaRef in nvim_create_user_command (#39377)
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:`.

(cherry picked from commit 393f687503)

Co-authored-by: Barrett Ruth <62671086+barrettruth@users.noreply.github.com>
2026-04-24 17:27:46 -04:00
neovim-backports[bot]
4df16ecdb9 backport: fix(api): LuaRef leak in nvim_set_keymap on LHS too long (>=66 bytes) (#39376)
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.

(cherry picked from commit 58aad59e1c)

Co-authored-by: Barrett Ruth <62671086+barrettruth@users.noreply.github.com>
2026-04-24 17:27:14 -04:00
Justin M. Keyes
3c45cb3bf6 Merge pull request #39371 from justinmk/release
backport test: curbuf initialized in describe-block
2026-04-24 15:00:08 -04:00
Justin M. Keyes
3b69e3d0cf test: fix merge conflict 2026-04-24 20:18:19 +02:00
glepnir
3d923bfa50 test: curbuf initialized in describe-block
Problem: curbuf was initialized at describe-block load time
before any Nvim session existed.

Solution: Replace with 0 directly at call sites.
2026-04-24 15:33:31 +02:00
Barrett Ruth
654c964d1a fix(trust): hash unchanged empty buffers as empty files #39027
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.

(cherry picked from commit 0a8218a2b4)
2026-04-23 23:38:56 +00:00
neovim-backports[bot]
0bd6e62509 fix(lsp): malformed edit if apply_text_edits() is called twice (#39347)
Problem:
Use vim.lsp.util.apply_text_edits to re-apply the same textedit causes
an incorrect edit, because apply_text_edits silently modifies the
parameter.

Solution:
- Avoid changing `text_edit._index`.
- Document this fun feature.

Helped-by: Riley Bruins <ribru17@hotmail.com>
Helped-by: Yi Ming <ofseed@foxmail.com>

(cherry picked from commit 790a8be5f3)

Co-authored-by: geril07 <62308020+geril07@users.noreply.github.com>
Co-authored-by: Justin M. Keyes <justinkz@gmail.com>
2026-04-23 19:24:04 -04:00
Barrett Ruth
c4d3a3d363 fix(lsp): filter code_action diagnostics to the cursor #38988
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.

(cherry picked from commit ecb8402197)
2026-04-23 23:07:26 +00:00
Ashley Hauck
93dc301781 fix(lsp): callHierarchy/outgoingCalls ranges are relative to caller, not 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)

(cherry picked from commit 7e006b06c4)
2026-04-23 23:07:07 +00:00
Barrett Ruth
39e8c584d5 fix(terminal): memory leak in pending TermRequest StringBuilder #39333
Problem: Destroying a terminal with pending `TermRequest` events leaks
memory.

Solution: Make `emit_termrequest` the sole owner of its `pending_send`
allocation.

(cherry picked from commit 19ef632dec)
2026-04-23 23:05:20 +00:00
Justin M. Keyes
bc288ee3e9 Merge pull request #39356 from justinmk/release
backports
2026-04-23 17:47:27 -04:00
Justin M. Keyes
f945aa451b refactor(test): deduplicate trust tests 2026-04-23 23:01:15 +02:00
atusy
27d01f2dbb fix(lsp): handle null id in JSON-RPC responses
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-23 23:00:25 +02:00
phanium
731f9743e2 fix(lua): don't strip debuginfo in precompile module #39191
Problem:
debug.getinfo on bytecode module/func don't give you detail source info.

Solution:
- Use `loadstring`+`string.dump` to replace LUAC_PRG(`luac`/`luajit -b`)
- `string.dump(…,false)` to generate non-strip version bytecode
- `loadstring(…,fname)` to specify the full source name

BEFORE:

    $ nvim --clean +'=debug.getinfo(vim.fn.maparg("]<Space>", "n", 0, 1).callback, "Sl")' --headless +q
    {
      currentline = -1,
      lastlinedefined = 456,
      linedefined = 452,
      short_src = "?",
      source = "=?",
      what = "Lua"
    }

AFTER:

    $ nvim --clean +'=debug.getinfo(vim.fn.maparg("]<Space>", "n", 0, 1).callback, "Sl")' --headless +q
    {
      currentline = -1,
      lastlinedefined = 456,
      linedefined = 452,
      short_src = "/home/xx/b/neovim/runtime/lua/vim/_core/defaults.lua",
      source = "@/home/xx/b/neovim/runtime/lua/vim/_core/defaults.lua",
      what = "Lua"
    }

(cherry picked from commit 398f2c108d)
2026-04-23 17:06:31 +00:00
Evgeni Chasnovski
dd95e434e3 fix(pack): only use tags that strictly comply with semver spec #39342
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.

(cherry picked from commit f8c94bb8cf)
2026-04-23 15:55:14 +00:00
zeertzjq
a76bcbe3b8 vim-patch:partial:9.2.0315: missing bound-checks (#39334)
Problem:  missing bound-checks
Solution: Add defensive guards against potential buffer overflow
          (Yasuhiro Matsumoto)

Add bounds checking and integer overflow guards across multiple files
as a defensive measure. While these code paths are unlikely to be
exploitable in practice, the guards prevent undefined behavior in
edge cases.

- libvterm/vterm.c: use heap tmpbuffer instead of stack buffer in
  vsprintf() fallback path
- channel.c: validate len in channel_consume() before mch_memmove()
- spell.c: use long instead of int for addlen to avoid signed overflow
  in size_t subtraction
- alloc.c: add SIZE_MAX overflow check in ga_grow_inner() before
  itemsize multiplication
- list.c: add overflow check before count * sizeof(listitem_T)
- popupwin.c: add overflow check before width * height allocation
- insexpand.c: add overflow check before compl_num_bests multiplication
- regexp_bt.c: replace sprintf() with vim_snprintf() in regprop()
- spellfile.c: use SIZE_MAX instead of LONG_MAX for allocation overflow
  check

closes: vim/vim#19904

8d23fcb603

Co-authored-by: Yasuhiro Matsumoto <mattn.jp@gmail.com>
(cherry picked from commit a4ad469fb1)
2026-04-23 06:05:29 +00:00
Justin M. Keyes
14eea10ec5 ci: drop cirrus #39321
Problem:
cirrus will shutdown soon, and we are running out of minutes anyway,
which causes ci failures.

Solution:
Drop cirrus config.

(cherry picked from commit 82198d0a66)
2026-04-22 23:01:00 +00:00
Justin M. Keyes
b46688feee backport feat(treesitter): expand selection to sibling node (#39323)
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.

Co-authored-by: altermo <107814000+altermo@users.noreply.github.com>
2026-04-22 21:40:12 +00:00
Justin M. Keyes
fd1b193d51 feat(:restart): v:starttime, v:exitreason #39319 2026-04-22 18:58:47 +00:00
Barrett Ruth
c407e3e67b feat(eval): treat Lua string as "blob" in writefile() #39098
Problem:
vim.fn.writefile() treats Lua strings as Vimscript strings instead of a "binary clean" string.

Solution:
Treat Lua-originated strings as blob data.

(cherry picked from commit fb6aeaba2d)
2026-04-22 17:56:29 +00:00
glepnir
915880d252 fix(shada): bdelete'd buffers not stored in oldfiles #39070
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()`.

(cherry picked from commit 496374e951)
2026-04-22 17:39:22 +00:00
Justin M. Keyes
a612ada984 build: version bump 2026-04-22 16:10:37 +02:00