Commit Graph

1349 Commits

Author SHA1 Message Date
Evgeni Chasnovski
b05675bccc backport: opts.scope in vim.ui.input (#39906)
feat(ui): vim.ui.input(opts.scope) #39570

Problem: There is no way for a `vim.ui.input` caller to indicate for
  which scope the input is. As in "This input is for something at cursor
  scope". This information can be useful for `vim.ui.input`
  implementation to tweak its behavior and presentation:
  - Show different floating window depending on the scope. For example:
    - Near cursor for "cursor" scope.
    - At line start for "line" scope.
    - In window corner for "buffer" and "window" scopes.
    - In whole editor corner for "tabpage", "editor", "project" scopes.
  - Navigate through history only for inputs with the same scope.

Solution: Document new `opts.scope` for `vim.ui.input`. Use it in the
  codebase.
2026-05-20 08:44:03 +00:00
Justin M. Keyes
1999c09953 backport build(docs): lint more quasi-keysets (#39656)
Problem:
Linter missed backtick and double-quote keynames in the quasi-keyset of
the `nvim_create_user_command` docstring.

Solution:
Update the linter to check backtick-surrounded and quote-surrounded key
names.
2026-05-07 17:32:50 +00:00
Justin M. Keyes
b982adfe10 docs: misc, rename "tabpage" 2026-05-07 12:03:02 +02:00
Tristan Knight
8919b02eba fix(lsp): dynamic registration for off-spec method #39544
Problem:
LSP clients previously did not handle dynamic registration for off-spec methods

Solution:
Update the client logic to assume support for dynamic registration when
the method is unknown. Adjust the registration provider fallback and
enhance tests to verify correct behaviour for unknown methods and their
registration options. This improves compatibility with servers using
custom dynamic registrations.

AI-assisted: OpenCode
(cherry picked from commit 344d984ed2)
2026-05-02 10:54:42 +08:00
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
4ee47a56ec docs: misc 2026-04-30 02:08:19 +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
Justin M. Keyes
d735ce36ec docs: sort quasi-keysets 2026-04-26 22:02:34 +02: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
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
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]
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
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
Jaehwang Jung
5907307662 fix(lsp): skip codelens refresh redraw for deleted buffer #39193
Problem:
After on_refresh() sends a textDocument/codeLens request, the buffer may
be deleted before the response arrives. The response callback then tries
to redraw that deleted buffer and raises Invalid buffer id error.

Solution:
Check buffer validity before redrawing.

AI-assisted: Codex
Co-authored-by: Yi Ming <ofseed@foxmail.com>
(cherry picked from commit 97caa88972)
2026-04-18 22:34:59 +00:00
glepnir
34cbfeca9c fix(lsp): show CompletionItem.detail in info popup #38904
Problem: completionItem/resolve response's `detail` field is silently
dropped. Only `documentation` is shown in the popup.

Solution: Prepend `detail` as a fenced code block before `documentation`
in the info popup, skipping if documentation already contains it.

(cherry picked from commit b351afb1b1)
2026-04-18 20:42:42 +00:00
Justin M. Keyes
a1712503d8 backport test: lint naming conventions (#39124)
test: lint naming conventions

Problem:
Naming conventions are not automatically checked.

Solution:
Add a check to the doc generator. Eventually we should extract this
somehow, but that will require refactoring the doc generator...

Note: this also checks non-public functions, basically anything that
passes through `gen_eval_files.lua` and `gen_vimdoc.lua`. And that's
a good thing.
2026-04-16 14:29:50 +00:00
Luis Calle
efc136850d refactor(lsp): fix typing for LSP methods #39099
Problem
Some variables use the wrong type (ClientToServer instead of ServerToClient)
and some use vaguer types that could be more strict.

Solution
Use the correct types.

(cherry picked from commit 530cfa1323)
2026-04-16 08:23:06 +00:00
Justin M. Keyes
099489b985 backport: refactor: update usages of deprecated "buffer" param #39090 2026-04-15 19:46:07 +00:00
Justin M. Keyes
df0f88a5a9 refactor(api): rename "window" to "win" (positional parameters) #39083
continues d0af4cd909.

This commit renames positional parameters. This is only "cosmetic", but
is intended to make it extra clear which name is preferred, since people
often copy existing code despite the guidelines in `:help dev-naming`.

(cherry picked from commit 71ac4db335)
2026-04-15 18:12:34 +00:00
Justin M. Keyes
ccba8a8f2d docs: lsp, options, api
- revert bogus change to `_meta/builtin_types.lua` from 3a4a66017b

Co-authored-by: David Mejorado <david.mejorado@gmail.com>
2026-04-14 13:27:29 +02:00
Lars Debor
6250019537 fix(lsp): show_document can't position cursor past EOL in insert-mode #38566
Problem: vim.lsp.util.show_document insert mode is unable
to set the cursor after the target character position if the target character
is at end of line.

Solution: Move cursor after the target character (in append position)
in this case.

(cherry picked from commit 891bb0e6ce)
2026-04-12 16:40:51 +00:00
Emilv2
fe09c71c34 fix(lsp): send didOpen on save to all clients+groups #37454
Problem: _get_and_set_name edits the name for the whole group,
thus only one client per group gets the didOpen message.

Solution: move the logic to _changetracking and loop over every
client per group.

(cherry picked from commit 37eb1b9979)
2026-04-12 15:20:42 +00:00
glepnir
18b1ff81a3 fix(lsp): check stale context in hover/signature callback #38724
Problem: hover/signature callback lacked consistency checks, so slow LSP servers
could open a float after the cursor had already moved away.

Solution: guard the callback with buf validity, buf version, and cursor
position checks before opening the float. Also fix table capacity calculation.

(cherry picked from commit af9a72d8c1)
2026-04-11 15:38:28 +00:00
Justin M. Keyes
ed47b27ad4 backport: feat(api): rename buffer to buf (#38899)
feat(api): rename buffer to buf

Problem:
`:help dev-name-common` states that "buf" should be used instead of
"buffer" but there are cases where buffer is mentioned in the lua API.

Solution:
- Rename occurrences of "buffer" to "buf" for consistency with the
  documentation.
- Support (but deprecate) "buffer" for backwards compatibility.

Co-authored-by: Jordan <46637683+JordanllHarper@users.noreply.github.com>
2026-04-09 01:23:13 +00:00
Justin M. Keyes
cc0a4a653c Merge pull request #38894 backports 2026-04-08 18:12:01 -04:00
glepnir
7ffee0dfbf fix(lsp): apply_text_edits causes unwanted BufDelete events #38778
Problem:
Since 2f6d1d3c88, `apply_text_edits`
unconditionally sets `buflisted=true`, causing spurious BufDelete events
if plugins restore the original 'buflisted' state on unlisted buffers:
65ef6cec1c/src/nvim/option.c (L2159-L2169)

Solution:
- Don't set 'buflisted' in `apply_text_edits`. Set it more narrowly, in
  `apply_workspace_edit` where the semantics requires affected buffers
  to be visible to the user.
- Also skip setting 'buflisted' if it would not be changed, to avoid
  redundant `OptionSet` events.

(cherry picked from commit 6473d007e7)
2026-04-08 21:58:27 +00:00
Justin M. Keyes
47e3efed99 refactor(filetype): move _get_known_filetypes, return a Set #38886
- `_get_known_filetypes` may be useful for other internal code, so move
  it to an internal function.
- Use a set instead of a list, for performance.
2026-04-08 23:26:07 +02:00
neovim-backports[bot]
df726644b8 fix(lsp): check filetype registry in health (#38885)
fix(health): misleading warnings re filetypes registered w/ vim.filetype.add() #38867

Problem:
`:checkhealth vim.lsp` validates configured filetypes against
`getcompletion('', 'filetype')`. This only reflects runtime support
files.

This causes false warnings in `:checkhealth vim.lsp` for configured
filetypes that are known to the Lua filetype registry, including
values added with `vim.filetype.add()` and built-in registry-only
filetypes.

Solution:
Build the healthcheck's known-filetype set from both
`getcompletion('', 'filetype')` and `vim.filetype.inspect()`.

(cherry picked from commit 20a3254ad4)

Co-authored-by: Barrett Ruth <62671086+barrettruth@users.noreply.github.com>
2026-04-08 17:24:15 -04:00
Maria Solano
c76bbd0a54 fix(diagnostics)!: restore is_pull namespace argument #38698
Problem:
The current LSP diagnostic implementation can't differ between a pull
diagnostic with no identifier and a set of diagnostics provided via push
diagnostics.

"Anonymous pull providers" are expected by the protocol https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#diagnosticOptions
, depending on how the capability was registered:
- Dynamic registrations have an identifier.
- Static registrations will not.

Solution:
Restore the `is_pull` argument removed in
https://github.com/neovim/neovim/pull/37938, keeping the identifier of
pull diagnostic collections.

(cherry picked from commit 665ebce569)
2026-04-08 20:46:16 +00:00
Luis Calle
0a3add979a feat(vim.pos)!: require buf param on vim.pos, vim.range #38665
Problem: `buf` is optional even though its needed to perform conversions
and the ordering of `(buf, row, col)` is not consistent.

Solution: make `buf` mandatory on `vim.range` and `vim.pos` and enforce
the `buf, row, col` ordering

(cherry picked from commit 01be30f638)
2026-04-06 16:19:43 +00:00
Yi Ming
c692e848e9 fix(lsp): do not respond to codelens refresh if a request is already scheduled (#38801)
(cherry picked from commit 909fc0b992)
2026-04-05 21:15:28 +00:00
Justin M. Keyes
0142453543 backport: docs: misc #38692 2026-04-01 17:08:38 -04:00
Yi Ming
8f7cbf6d66 fix(lsp): use winresetview() to avoid switching to normal mode (#38641)
(cherry picked from commit e31bfb81ce)
2026-03-31 16:54:30 +00:00
skewb1k
edf4f5689d docs: fix syntax errors in examples #38606
(cherry picked from commit 2dce2af768)
2026-03-30 16:33:20 +00:00
Maria Solano
f2764a596d fix(lsp): reset document color processed version on clear (#38582)
(cherry picked from commit 92a667c07f)
2026-03-30 01:37:09 +00:00
Marcus Caisey
2eb14c54bc fix(lsp): highlight snippet preview when server can't completionItem/resolve (#38534)
Problem:
The snippet preview is not being highlighted by treesitter for
completion items from servers which don't support
`completionItem/resolve` (like gopls). This was broken by #38428.

Solution:
Call `update_popup_window` after updating the completion item with the
snippet preview.

I've added assertions to the `selecting an item triggers
completionItem/resolve + (snippet) preview` test case which covers the
snippet preview being shown since no tests failed when I removed the
`nvim__complete_set` call which actually populates the preview on this
codepath.
2026-03-29 14:48:11 -07:00
Justin M. Keyes
d9d3822a7b docs: misc #38532
Close #38431
Close #38521
Close #38530

Co-authored-by: tayheau <thopsore@pasteur.fr>
Co-authored-by: zeertzjq <zeertzjq@outlook.com>
Co-authored-by: Olivia Kinnear <git@superatomic.dev>
2026-03-29 11:56:37 -04:00
Luis Calle
f3c2eb49ba feat: extend vim.Pos, vim.Range #36397
Problem:
Using nested `vim.Pos` objects to represent each `vim.Range` object
requires 3 tables for each `vim.Range`, which may be undesirable in
performance critical code. Using key-value tables performs worse than
using array-like tables (lists).

Solution:
Use array-like indices for the internal fields of both `vim.Pos` and
`vim.Range` objects. Use a metatable to allow users to access them like
if they were key-value tables.

---

Problem:
The `vim.Pos` conversion interface for `extmark` indexing does not take
into account the difference in how a position on top of a newline is
represented in `vim.Pos` and `extmark`.
- `vim.Pos`: for a newline at the end of row `n`, `row` takes the value
  `n + 1` and `col` takes the value `0`.
- `extmark`: for a newline at the end of for `n`, `row` takes the value
  `n` and `col` takes the value `#row_text`.

Solution:
Handle this in the `extmark` interface.

---

Problem:
Not all `to_xxx` interfaces have wrapping objects like `to_lsp`.

Solution:
Return unwrapped values in `to_xxx` interfaces where it makes sense.
Accept unwrapped values in "from" interfaces where it makes sense.

---

Problem:
`start` and `end` positions have different semantics, so they can't be
compared. `vim.Range` relies on comparing the `end` and `start` of two
ranges to decide which one is greater, which doesn't work as expected
because this of the different semantics.

For example, for the ranges:

    local a = {
      start = { row = 0, col = 22, },
      end_ = { row = 0, col = 24, },
    }
    local b = {
      start = { row = 0, col = 17, },
      end_ = { row = 0, col = 22, },
    }

in this code:

    local foo, bar = "foo",  "bar"
    --               |---||-|
    --                 b  a

The range `b` is smaller than the range `a`, but the current
implementation compares `b._end` (`col = 22`) and `a.start` (`col = 22`)
and concludes that, since `b.col` is not smaller than `a.col`, `b`
should be greater than `a`.

Solution:
- Use a `to_inclusive_pos` to normalize end positions inside of
  `vim.Range` whenever a comparison between a start and an end position
  is necessary.
2026-03-29 11:22:40 -04:00
Maria Solano
9c5d8b475e docs(lsp): add init_options to Copilot example #38502
Problem:
When following this example from our docs the Copilot LSP won't attach.

Solution:
Add `init_options` as done by [`nvim-lspconfig`](1a6d692067/lsp/copilot.lua (L112-L121)).
2026-03-27 12:33:31 -04:00
Tristan Knight
7c3df3e2ea fix(lsp): get_namespace signature (#38449)
Problem: Since the change to `pull_id` in #37938 we used the
deprecated signature internally

Solution: Don't
2026-03-23 15:42:47 -07:00
glepnir
f2d0b06ecb fix(lsp): completion word includes leading space from label #38435
Problem: clangd prepends a space/bullet indicator to label. With
labelDetailsSupport enabled, the signature moves to labelDetails,
making label shorter. This flips the length comparison in
get_completion_word, causing it to use item.label directly and
insert the indicator into the buffer.

Solution: only prefer filterText over label when label starts with non-keyword
character in get_completion_word fallback branch.
2026-03-23 11:02:30 -04:00
glepnir
4ed597389c fix(lsp): snippet preview blocked completionItem/resolve request #38428
Problem: Generating snippet preview in get_doc() populated the
documentation field before resolve, so the resolve request was
never sent.

Solution: Move snippet preview logic into on_completechanged and
the resolve callback so it no longer blocks the resolve request.
2026-03-23 07:57:36 -04:00
KrrishJain
0db8efcbe4 fix(lsp): restore virtual document color visibility (#38407)
Problem: Default swatch unicode character got lost.

Solution: Put it back where it belongs.

---------

Co-authored-by: vnadgaonkar-spec <vnadgaonkar@gmail.com>
Co-authored-by: Christian Clason <ch.clason+github@icloud.com>
2026-03-22 00:34:44 +01:00
glepnir
cc518cf9ba feat(lsp): support CompletionItem.labelDetails #38403
Problem: CompletionItem.labelDetails is ignored, losing
function signatures and module info in the completion menu.

Solution: Append labelDetails.detail to abbr and use
labelDetails.description for menu with fallback to item.detail.

https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#completionItemLabelDetails
2026-03-21 19:07:26 -04:00
skewb1k
4d3a67cd62 feat(lua): replace buffer with buf in vim.keymap.set/del #38360
The `buffer` option remains functional but is now undocumented.
Providing both will raise an error. Since providing `buf` was disallowed
before, there is no code that will break due to using `buffer` alongside
`buf`.
2026-03-21 12:00:06 -04:00
Sergei Slipchenko
7a5e9ef0aa fix(lsp/diagnostic): use diagnostic provider identifier for code actions #38401
Problem:
f9b2189b28 started using namespaces
for pull diagnostics that look like this `<id>:<identifier>`.
`vim.lsp.buf.codeaction` passes `true` instead of an identifier
to `vim.lsp.diagnostic.get_namespace`, resulting in a namespace that
looks like `<id>:nil`. The end result is that none of the diagnostics are
passed to `textDocument/codeAction` request. Because of that server
might not send any code actions back. For example, eslint lsp responds
with an empty list of actions if it receives no diagnostics.

Solution:
use `_provider_foreach` to collect diagnostics from all `identifiers`
and use that identifier to get a namespace instead of `true`.
2026-03-21 09:38:11 -04:00