Commit Graph

792 Commits

Author SHA1 Message Date
David Balatero
c9cb49358b test: unreliable pack_spec.after_each: "EBUSY: resource busy or locked" #39606
Problem:
`EBUSY` during cleanup:
Windows CI can intermittently fail `pack_spec.lua` with `EBUSY` while removing
`site/pack/core/opt/plugindirs`.

This can happen because:
- the test Nvim session may still be alive when `after_each()` removes the pack
  directory
- Windows does not allow removing a directory while another process still has an
  open handle below it
- startup-time `vim.pack.add()` performs a real `git clone`, so process and file
  handle release timing can vary on slower runners

Startup timeout:
The startup tests can also fail before cleanup because they wait for `_G.done`
with a fixed timeout. That timeout includes the time needed for startup to run
`vim.pack.add()` and finish the local clone.

Solution:
Close before cleanup:
Capture the pack, lockfile, and log paths while the test Nvim session is still
available, then call `n.check_close()` before removing the pack directory.

Extend Windows startup wait:
Increase the `_G.done` retry budget only on Windows so startup-time
`vim.pack.add()` has more time to finish on slower CI runners.

(cherry picked from commit 19a2ef5afa)
2026-05-05 18:33:31 +00: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
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
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
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
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
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
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
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
fleesk
6583833ee2 fix(pack): GIT_DIR/GIT_WORK_TREE env vars may interfere #39279
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.

(cherry picked from commit e53e728c92)
2026-04-22 09:24:45 +00:00
Justin M. Keyes
e767b4843b backport: refactor(test): drop deprecated exc_exec #39255 2026-04-21 16:22:05 +00:00
Justin M. Keyes
43398547ec backport docs: misc (#39206)
docs: misc


(cherry picked from commit 54398c5874)
2026-04-19 12:36:19 +00: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
55d3d1bbeb backport: test(lsp): extract buf/util parts from lsp_spec.lua (#39170)
test(lsp): extract buf/util parts from lsp_spec.lua

Problem:
`test/functional/plugin/lsp_spec.lua` had grown into a large catch-all file that mixed core LSP client lifecycle coverage, `vim.lsp.buf.*` behavior, and `vim.lsp.util.*` behavior in one place.

Solution:
Split the large tests into more focused test files without changing test coverage or intended behavior.

After this change, `lsp_spec.lua` is more focused on core LSP client/config/dynamic-registration behavior.

Co-authored-by: Yi Ming <ofseed@foxmail.com>
2026-04-18 03:01:28 +00:00
Evgeni Chasnovski
5f23c0a1cf test(pack): increase retry timeout for startup test #39125
Problem: Unreliable test on Windows which sometimes fails with too many
  failed retries.

Solution: Increase timeout in hopes that it will be enough to make it
  pass more frequently. This should not affect fast and already working
  platforms.
(cherry picked from commit df6a0827fb)
2026-04-16 15:18:20 +00:00
Justin M. Keyes
099489b985 backport: refactor: update usages of deprecated "buffer" param #39090 2026-04-15 19:46:07 +00:00
Evgeni Chasnovski
843cfd7295 test(pack): use n.rmdir() to delete directories #39046
Problem: using `vim.fs.rm(dir_path, { force = true, recursive = true })`
  can result in an error on Windows if the process has a handle to it.

Solution: Use `n.rmdir()` helper in cases when its possible side effects
  (like changing working directory) does not matter.
(cherry picked from commit b8a24bfadf)
2026-04-14 14:33:53 +00: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
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
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
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
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
Justin M. Keyes
0ac321a1d6 test: fix s390x failures
Problem:
failures in s390x CI.

Solution:
- runtime/lua/man.lua: parse_path() can return nil but 3 callers didn't handle it.
- skip some tests on s390x.

TODO:

- TODO: why "build/bin/xxd is not executable" on s390x?
- TODO: other failures, not addressed (see below).

OTHER FAILURES:

    FAILED   test/functional/treesitter/fold_spec.lua @ 87: treesitter foldexpr recomputes fold levels after lines are added/removed
    test/functional/treesitter/fold_spec.lua:95: Expected objects to be the same.
    Passed in:
    (table: 0x4013c18940) {
      [1] = '0'
      [2] = '0'
      [3] = '0'
     *[4] = '0'
      [5] = '0'
      ...
    Expected:
    (table: 0x4005acf900) {
      [1] = '0'
      [2] = '0'
      [3] = '>1'
     *[4] = '1'
      [5] = '1'
      ...

    stack traceback:
            (tail call): ?
            test/functional/treesitter/fold_spec.lua:95: in function <test/functional/treesitter/fold_spec.lua:87>

    FAILED   test/functional/treesitter/select_spec.lua @ 52: treesitter incremental-selection works
    test/functional/treesitter/select_spec.lua:63: Expected objects to be the same.
    Passed in:
    (string) 'bar(2)'
    Expected:
    (string) 'foo(1)'

    stack traceback:
            (tail call): ?
            test/functional/treesitter/select_spec.lua:63: in function <test/functional/treesitter/select_spec.lua:52>

    FAILED   test/functional/treesitter/select_spec.lua @ 69: treesitter incremental-selection repeat
    test/functional/treesitter/select_spec.lua:82: Expected objects to be the same.
    Passed in:
    (string) '2'
    Expected:
    (string) '4'

    stack traceback:
            (tail call): ?
            test/functional/treesitter/select_spec.lua:82: in function <test/functional/treesitter/select_spec.lua:69>

    FAILED   test/functional/treesitter/select_spec.lua @ 98: treesitter incremental-selection history
    test/functional/treesitter/select_spec.lua:111: Expected objects to be the same.
    Passed in:
    (string) 'bar(2)'
    Expected:
    (string) 'foo(1)'

    stack traceback:
            (tail call): ?
            test/functional/treesitter/select_spec.lua:111: in function <test/functional/treesitter/select_spec.lua:98>

    FAILED   test/functional/treesitter/select_spec.lua @ 186: treesitter incremental-selection with injections works
    test/functional/treesitter/select_spec.lua:201: Expected objects to be the same.
    Passed in:
    (string) 'lua'
    Expected:
    (string) 'foo'

    stack traceback:
            (tail call): ?
            test/functional/treesitter/select_spec.lua:201: in function <test/functional/treesitter/select_spec.lua:186>

    FAILED   test/functional/treesitter/select_spec.lua @ 216: treesitter incremental-selection with injections ignores overlapping nodes
    test/functional/treesitter/select_spec.lua:231: Expected objects to be the same.
    Passed in:
    (string) ' )'
    Expected:
    (string) ' foo('

    stack traceback:
            (tail call): ?
            test/functional/treesitter/select_spec.lua:231: in function <test/functional/treesitter/select_spec.lua:216>

    FAILED   test/functional/treesitter/select_spec.lua @ 307: treesitter incremental-selection with injections handles disjointed trees
    test/functional/treesitter/select_spec.lua:337: Expected objects to be the same.
    Passed in:
    (string) 'int'
    Expected:
    (string) '1}'

    stack traceback:
            (tail call): ?
            test/functional/treesitter/select_spec.lua:337: in function <test/functional/treesitter/select_spec.lua:307>

    ERROR    test/functional/treesitter/parser_spec.lua @ 562: treesitter parser API can run async parses with string parsers
    test/functional/treesitter/parser_spec.lua:565: attempt to index a nil value

    stack traceback:
            test/functional/testnvim/exec_lua.lua:124: in function <test/functional/testnvim/exec_lua.lua:105>
            (tail call): ?
            (tail call): ?
            test/functional/treesitter/parser_spec.lua:563: in function <test/functional/treesitter/parser_spec.lua:562>

    FAILED   test/functional/core/job_spec.lua @ 1157: jobs jobstop() kills entire process tree #6530
    test/functional/core/job_spec.lua:1244: retry() attempts: 94
    test/functional/core/job_spec.lua:1246: Expected objects to be the same.
    Passed in:
    (table: 0x401dd74b30) {
      [name] = 'sleep <defunct>'
      [pid] = 33579
      [ppid] = 1 }
    Expected:
    (userdata) 'vim.NIL'

    stack traceback:
            test/testutil.lua:89: in function 'retry'
            test/functional/core/job_spec.lua:1244: in function <test/functional/core/job_spec.lua:1157>
2026-03-29 13:36:56 +02:00
Evgeni Chasnovski
0fa96585dc fix(pack): set source in progress report #38511
Problem: Progress reports via `nvim_echo()` gained an ability to set
  `source` and `vim.pack` doesn't currently set one.

Solution: Set `source` to 'vim.pack'. Ideally, the title then can be
  something else more informative (like "update", "download", etc.), but
  it is used when showing progress messages. So it has to be "vim.pack"
  in this case.
2026-03-27 07:36:06 -04:00
Justin Mayhew
b02d1303b8 fix(pack): add trailing newline to lockfile #38469
Problem: JSON files should end with a trailing newline so that Unix
  tools work as expected, Git doesn't report "No newline at end of file"
  and to avoid noise in diffs from editors and other tools adding the
  missing newline.

Solution: Add trailing newline.
2026-03-24 13:23:17 -04:00
Justin M. Keyes
c01a8741f6 test(lsp): get_configs resolves only necessary configs 2026-03-24 00:14:55 +01: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
Justin M. Keyes
59eadebe33 fix(runtime)!: move "tohtml" to pack/dist/opt/ #34557
Problem:
The "tohtml" plugin is loaded by default.

Solution:
- Move it to `pack/dist/opt/nvim.tohtml/`, it is an "opt-in" plugin now.
- Document guidelines.
- Also revert the `plugin/` locations of `spellfile.lua` and `net.lua`.
  That idea was not worth the trouble, it will be too much re-education
  for too little gain.
2026-03-23 06:41:00 -04:00
Maria Solano
471213ee61 revert: "feat(lsp): add buftypes field to vim.lsp.Config" #38421
revert: "feat(lsp): add `buftypes` field to `vim.lsp.Config` (#38380)"

This reverts commit cfcdbcf638.
2026-03-22 13:33:11 -04:00
Barrett Ruth
cfcdbcf638 feat(lsp): add buftypes field to vim.lsp.Config (#38380)
Problem: `vim.lsp.enable()` skips buffers with `buftype` set, even when
`filetype` matches.

Solution: Add `buftypes` field to `vim.lsp.Config`.
2026-03-21 17:09:01 -07: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
tris203
c8d9ade16a refactor(lsp): replace _provider_value_get with _provider_foreach
Introduce _provider_foreach to iterate over all matching provider
capabilities for a given LSP method, handling both static and dynamic
registrations. Update diagnostic logic and tests to use the new
iteration approach, simplifying capability access and improving
consistency across features.
2026-03-19 17:51:21 +00:00
Olivia Kinnear
e406c4efd6 feat(lsp): vim.lsp.get_configs() #37237
Problem:
No way to iterate configs. Users need to reach
for `vim.lsp.config._configs`, an internal interface.

Solution:
Provide vim.lsp.get_configs().
Also indirectly improves :lsp enable/disable completion
by discarding invalid configs from completion.
2026-03-19 07:33:34 -04:00
Maria Solano
4430c9a424 feat(lsp): migrate document_color to capability framework (#38344)
* feat(lsp): migrate `document_color` to capability framework

* feat(lsp): use `vim.Range` in `document_color` module
2026-03-18 17:18:48 -07:00
Yi Ming
addd408b39 fix(lsp): redraw codelens after request completed #38352
Problem:
When code lens is enabled, `on_attach` is executed, but it does not trigger a redraw. Another event, eg, moving the cursor, is required to trigger a redraw and execute the decoration provider's `on_win`.

Solution:
Trigger a `redraw` after each request is completed.
2026-03-18 11:02:46 -04:00
glepnir
0da9827673 fix(lsp): respect documentation markup kind in completion preview #38338
Problem:
Completion preview always assumes plain text, ignoring LSP documentation "kind".

Solution:
Pass markup kind from completion item to info window, or fallback to PlainText.
2026-03-17 10:24:30 -04:00
glepnir
5653b25e9b fix(lsp): handle non-string documentation in completion items #38291
Problem: `get_doc` throws error with "attempt to get length of a userdata
value" when `item.documentation` is truthy but not a string (e.g. vim.NIL
from a JSON null).

Solution: Check `type(item.documentation)` before taking its length.
2026-03-14 05:20:34 -04:00
glepnir
3f10bb87ef fix(completion): wrong CompleteDone reason for auto-inserted sole match #38280
Problem: #38169 used compl_used_match to determine the CompleteDone
reason, but this fires too broadly, it also changes the reason to
"accept" when the popup was shown and the user dismissed it with <Esc>
or <Space>, breaking snippet completion with autocomplete.

Solution: Instead of checking compl_used_match in, check whether the pum
was never shown (compl_match_array == NULL) in ins_compl_stop().
When a match was inserted but the pum never displayed,
set the completed word so CompleteDone fires with reason "accept".
This keeps the "discard" reason intact when the user dismisses a visible
pum without confirming.
2026-03-13 06:13:58 -04:00
Justin M. Keyes
7ea148a1dc docs: use "ev" convention in event-handlers
Problem:
In autocmd examples, using "args" as the event-object name is vague and
may be confused with a user-command.

Solution:
Use "ev" as the conventional event-object name.
2026-03-12 11:12:56 +01:00
glepnir
f168d215cf fix(lsp): ensure augroup before querying autocmds #38254 2026-03-11 13:57:19 -04:00
Justin M. Keyes
b8a976afda docs: api, messages, lsp, trust
gen_vimdoc.lua: In prepare for the upcoming release, comment-out the
"Experimental" warning for prerelease features.
2026-03-11 18:00:18 +01:00
glepnir
63594ffa04 feat(lsp): do completionItem/resolve if completeopt=popup #32820
Problem:
No completionItem/resolve handler.

Solution:
If completeopt=popup is set, invoke completionItem/resolve when
a completion item is selected. Show resolved documentation in popup next
to the completion menu.
2026-03-11 05:48:31 -04:00
Commrade Goad
66066d0f6a fix(lua): extra CR (\r) in nvim -l output #38048
Problem:
`nvim -l` prints an extra `\r` to stdout:

    :=vim.system({'cmd', '/c',  "echo print(1) | nvim -l -"}, {}):wait()
    {
      code = 0,
      signal = 0,
      stderr = "1\r\r\n",
      stdout = ""
    }

Solution:
Check `headless_mode` in `msg_use_crlf`.

Co-authored-by: Justin M. Keyes <justinkz@gmail.com>
2026-03-10 19:01:45 -04:00