Commit Graph

739 Commits

Author SHA1 Message Date
Yi Ming
40dc2d02a8 fix(lsp): ensure the codelens on the first line is visible 2026-03-08 11:32:50 +08:00
Yi Ming
378435968f fix(lsp): adjust codelens position based on the server-provided range 2026-03-08 10:42:38 +08:00
Lewis Russell
8bfb91accc fix(lsp): ignore stale codelens resolve responses (#38153) 2026-03-04 17:43:40 -08:00
Evgeni Chasnovski
f00abc6a56 fix(pack): ensure data spec is passed in events during lockfile sync #38139
Problem: During initial "bootstrap" via lockfile synchronization, the
  whole plugin specification is reconstructed from the lockfile data,
  ignoring potential user changes added in the first `vim.pack.add()`.
  This is enough in most situations since it is the only data needed
  for actual installation.

  However, this affects specification passed to `PackChanged[Pre]`
  events. In particular, `data` field is missing which can be a problem
  if there is a `PackChanged kind=install` hook that uses that field
  (like with some kind of `build` method used during install).
  And there might be different `version` set in `vim.pack.add()`.

Solution: Pass the `specs` input of the first `vim.pack.add()` down to
  lockfile synchronization and use it to reconstruct plugin
  specification for the to-be-installed plugin. If present among the
  user's `specs`, it is used but with forced `src` from the lockfile (as
  it is the one used during installation).

  Note that this still has a caveat when using separate
  `vim.pack.add()`, as only the specs from the first input (when the
  lockfile synchronization happens) is taken into account.
2026-03-03 19:16:24 -05:00
Tomas Slusny
45b4bbac28 feat(difftool): replace old "nvim -d" automatically #38057
Problem:
"nvim -d" doesn't leverage nvim.difftool.

Solution:
If nvim.difftool was enabled via :packadd, automatically
handle "nvim -d" on startup.

    nvim -c "packadd nvim.difftool" -d dir1/ dir2/
2026-02-28 11:03:44 -05:00
glepnir
3e8a4e1092 feat(lsp): show color preview in completion items #32138
Problem: Color completion items display as plain text without visual preview

Solution: Parse RGB/hex colors from documentation and render with colored symbol ■
2026-02-28 10:02:52 -05:00
Nicknamess96
c1e60f36f3 fix(difftool): don't reset quickfix list when closing quickfix window #38088
Closing the quickfix window previously triggered a WinClosed autocmd
that deleted all difftool autocmds and pushed an empty quickfix list,
making the difftool non-functional. Users who close the quickfix window
to gain screen real estate for viewing diffs had no way to continue
navigating entries.

Remove the qf_win tracking and its associated WinClosed autocmd so that
closing the quickfix window no longer tears down the difftool state.
Closing either diff window still performs full cleanup as before.

The BufWinEnter handler no longer passes with_qf to diff_files, so
navigating entries while the quickfix window is closed reuses the
existing diff layout without forcing a layout rebuild.

Fixes #37388
2026-02-28 09:59:53 -05:00
Riccardo Mazzarini
ea5007b37f fix(lps): separate namespaces for pull/push diagnostics #37938
Problem:
Regression from b99cdd0:
Pull diagnostics (from `textDocument/diagnostic`) and push diagnostics
(from `textDocument/publishDiagnostics`) use the same namespace, which
is a problem when using language servers that publish two different sets
of diagnostics on push vs pull, like rust-analyzer (see
https://github.com/rust-lang/rust-analyzer/issues/18709#issuecomment-2551394047).

Solution:
Rename `is_pull` to `pull_id` which accepts a pull namespace instead of
just a boolean.
2026-02-26 12:05:30 -05:00
zeertzjq
e86ccdbeae test: remove remaining use of feed_command() in terminal/ (#38069)
Also deduplicate screen lines in some other tests.
2026-02-26 10:06:34 +08:00
zeertzjq
1983c70d10 test(lsp): flaky lsp/semantic_tokens_spec #38063
The wait added in #37853 doesn't seem to do anything as request is sent
immediately on InsertLeave, and the number 4 also seems wrong. Instead,
the actual cause for the flakiness that the feed() (and hence the buffer
change) may arrive before the scheduled initialization of capabilities,
causing there be only only one textDocument/semanticTokens/full request
instead of two.
2026-02-25 13:04:31 -05:00
glepnir
3115a18a80 refactor(test): lsp completion spec cleanup #38041
Problem: retry/feed/tbl_map patterns duplicated everywhere, detach check was a false negative

Solution: extract wait_for_pum/extract_word_abbr/word_sorter helpers,
fix assert_cleanup_after_detach with positive+negative pum confirmation
2026-02-24 09:20:58 -05:00
glepnir
5eb1c4df54 refactor(test): avoid deprecated functions #37017
Problem:
Tests are using some deprecated functions.

Solution:
Replace with command, pcall_err, etc.
2026-02-24 07:15:24 -05:00
glepnir
f90cd620c5 fix(lsp): vim.lsp.completion clean up triggers on client detach (#38009)
Problem: LspDetach didn't clean up stale client refs in triggers table.

Solution: create LspDetach autocmd and call disable_completion.
2026-02-22 11:43:32 -08:00
zeertzjq
e3d46a6337 test: start test runners in Xtest_xdg dir (#37964)
This is a better way to prevent parallel tests from interfering with
each other, as there are many ways files can be created and deleted in
tests, so enforcing different file names is hard.

Using $TMPDIR can also work in most cases, but 'backipskip' etc. have
special defaults for $TMPDIR.

Symlink runtime/, src/, test/ and README.md to Xtest_xdg dir to make
tests more convenient (and symlinking test/ is required for busted).

Also, use README.md instead of test/README.md in the Ex mode inccommand
test, as test/README.md no longer contains 'N' char.
2026-02-20 06:53:33 +08:00
zeertzjq
dec3c6fa34 test(lsp): fix fake LSP server timeout not working (#37970)
Problem:  Fake LSP server does not timeout or respond to SIGTERM as it
          does not run the event loop.
Solution: Instead of io.read(), use stdioopen()'s on_stdin callback to
          accumulate input and use vim.wait() to wait for input.

Also, in the test suite, don't stop a session when it's not running, as
calling uv.stop() outside uv.run() will instead cause the next uv.run()
to stop immediately, which cancels the next RPC request.
2026-02-19 10:38:14 -08:00
Bartłomiej Maryńczak
761fbc155a test(lsp): add entire-line completion word case (#37927)
Problem:
Multiword completion items used to be cut at a first word.

Solution:
Add a test that ensures this does not regress in the future
2026-02-18 13:13:38 -08:00
zeertzjq
496eca22b3 test: support running functionaltests in parallel by directory (#37918)
Define a CMake target for every subdirectory of test/functional that
contains functional tests, and a functionaltest_parallel target that
depends on all those targets, allowing multiple test runners to run in
parallel.

On CI, use at most 2 parallel test runners, as using more may increase
system load and make tests unstable.
2026-02-18 15:56:50 +08:00
Tristan Knight
13cf80deef fix(lsp): map all LSP methods to server capabilities (#37910) 2026-02-16 13:20:34 -08:00
Rahul Yedida
249f305bbc feat(defaults): per-platform 'guifont' default #37175
Problem:
Font rendering and kerning are subpar in GUIs.

Solution:
Set default 'guifont' based on common CSS fonts per:
https://github.com/system-fonts/modern-font-stacks#monospace-code
2026-02-16 09:05:23 -05:00
Tim Pope
a1895f024a fix(lsp): support workspace/configuation with no section #27510
The [spec for `workspace/configuration`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#workspace_configuration)
marks the `section` property of each item in `items` optional.
Therefore, I believe it violates the spec to skip over items without
a section, because then the length of the results won't match the length
of a valid `items` input. The spec does not elaborate on _what_ to
return in this case, but I don't think it would be controversial to say
that returning the full configuration, as done for an empty string, is
the most natural interpretation.

That empty string case, by the way, was initially [added in
response](5da124fc82)
to a real world implementation requesting it. I don't have a similar
real world implementation to point to for the omitted `section`, but
I would note that `getConfiguration()` from `vscode-languageserver-node`
[defaults to a request with no section](d859bb14d1/server/src/common/configuration.ts (L24-L26))
when called with no arguments. I surmise that this is intended as a way
to retrieve the full configuration.
2026-02-15 11:37:24 -05:00
Wayne Young
3eb8a2784e test(lsp): wait up to 1 second to read messages 2026-02-15 10:31:10 +00:00
Tristan Knight
b99cdd08de refactor(lsp): centralize provider capability resolution #37221
- Refactor LSP client to use unified provider-based capability lookup for
  diagnostics and other features.
- Introduce `_provider_value_get` to abstract capability retrieval,
  supporting both static and dynamic registrations.
- Update diagnostic handling and protocol mappings to leverage
  provider-centric logic.
2026-02-14 10:50:48 -05:00
Evgeni Chasnovski
539b8027a3 fix(pack): explicitly close confirmation window #37861
Problem: Executing `nvim_buf_delete()` does not guarantee that the
  window which shows the buffer is going to close after `:write` or
  `:quit`. In particular, if there is no listed buffer present.

Solution: Explicitly close the window that was created for confirmation
  buffer. Use `pcall` to catch cases when the window was already closed
  or when it is the last window.
2026-02-14 08:26:36 -05:00
Justin M. Keyes
858576777e docs: lsp, options, promptbuf
Close #37630
Close #37682
Close #37762
Close #37785

Co-authored-by: Daniel Schmitt <d.schmitt@lansoftware.de>
Co-authored-by: Duane Hilton <duane9@gmail.com>
Co-authored-by: NeOzay <colpaert.benoit@gmail.com>
Co-authored-by: Yi Ming <ofseed@foxmail.com>
Co-authored-by: "Justin M. Keyes" <justinkz@gmail.com>
2026-02-12 13:46:45 +01:00
phanium
9f77124b78 fix(lsp): error on omnifunc completion (#37790)
Problem:
After eaacdc9, complete with emmylua_ls error with:
runtime/lua/vim/lsp/completion.lua:586: attempt to get length of field
'items' (a nil value)

Solution:
Result can be CompletionItem[] according the spec:
> If a `CompletionItem[]` is provided, it is interpreted to be complete,
> so it is the same as `{ isIncomplete: false, items }`
2026-02-09 09:45:21 -08:00
Tomasz N
eaacdc9bdf fix(lsp): ignore empty response on trigger completion #37663
Problem:
Empty response affects server start boundary computed before.

Solution:
Ignore empty responses. This is mostly micro-optimization that avoids
extending existing results with empty responses.
2026-02-08 16:25:47 -05:00
GenchoXD
9c8d06e086 test(lsp/diagnostic): clearing diagnostics #37759
Problem:
Diagnostic lifecycle invariants (clearing on empty publish and buffer
deletion) were previously implicit and not directly covered by functional
tests, allowing regressions to go unnoticed.

Solution:
Add functional regression tests asserting that diagnostics are cleared
when an LSP server publishes an empty diagnostic set and when the
associated buffer is deleted. Assertions are scoped to the client
diagnostic namespace and use public diagnostic APIs only.
2026-02-08 16:22:13 -05:00
Mike J McGuirk
15ff454443 feat(lsp): display codelens as virtual lines, not virtual text #36469
Problem: Code lenses currently display as virtual text on the same line
and after the relevant item. While the spec does not say how lenses
should be rendered, above the line is most typical. For longer lines,
lenses rendered as virtual text can run off the side of the screen.

Solution: Display lenses as virtual lines above the text.

Closes https://github.com/neovim/neovim/issues/33923

Co-authored-by: Yi Ming <ofseed@foxmail.com>
2026-02-08 16:10:41 -05:00
Evgeni Chasnovski
0f73873d4f fix(pack): close confirmation buffer, not tabpage #37756 2026-02-08 09:15:16 -05:00
Justin M. Keyes
a124439559 test(lsp): retry "on_type_formatting enables formatting on type" #37711
FAILED   test/functional/plugin/lsp/on_type_formatting_spec.lua @ 59: vim.lsp.on_type_formatting enables formatting on type
    test/functional\plugin\lsp\on_type_formatting_spec.lua:65: retry() attempts: 1
    test/functional\plugin\lsp\on_type_formatting_spec.lua:66: Expected objects to be the same.
    Passed in:
    (table: 0x01772f47b6d8) {
      [1] = 'int main() {'
     *[2] = '  int hi = 5'
      [3] = '}' }
    Expected:
    (table: 0x017731aad3a8) {
      [1] = 'int main() {'
     *[2] = '  int hi = 5;'
      [3] = '}' }

    stack traceback:
            test\testutil.lua:89: in function 'retry'
            test/functional\plugin\lsp\on_type_formatting_spec.lua:65: in function <test/functional\plugin\lsp\on_type_formatting_spec.lua:59>
2026-02-05 00:03:06 +00:00
Tomasz N
90abd2613d fix(lsp): don't empty server start-boundary by next client response #37665
Problem:
Server start boundary can be emptied by response provided by next client.

Solution:
Don't empty it when extending the result list.
2026-02-03 15:30:05 -05:00
jdrouhard
9278f792c3 feat(lsp): support range + full semantic token requests #37611
From the LSP Spec:
> There are two uses cases where it can be beneficial to only compute
> semantic tokens for a visible range:
>
> - for faster rendering of the tokens in the user interface when a user
>   opens a file. In this use case, servers should also implement the
>   textDocument/semanticTokens/full request as well to allow for flicker
>   free scrolling and semantic coloring of a minimap.
> - if computing semantic tokens for a full document is too expensive,
>   servers can only provide a range call. In this case, the client might
>   not render a minimap correctly or might even decide to not show any
>   semantic tokens at all.

This commit unifies the usage of range and full/delta requests as
recommended by the LSP spec and aligns neovim with the way other LSP
clients use these request types for semantic tokens.

When a server supports range requests, neovim will simultaneously send a
range request and a full/delta request when first opening a file, and
will continue to issue range requests until a full response is
processed. At that point, range requests cease and full (or delta)
requests are used going forward. The range request should allow servers
to return a result faster for quicker highlighting of the file while it
works on the potentially more expensive full result. If a server decides
the full result is too expensive, it can just error out that request,
and neovim will continue to use range requests.

This commit also fixes and cleans up some other things:

- gen_lsp: registrationMethod or registrationOptions imply dynamic
  registration support
- move autocmd creation/deletion to on_attach/on_detach
- debounce requests due to server refresh notifications
- fix off by one issue in tokens_to_ranges() iteration
2026-02-03 13:16:12 -05:00
Yi Ming
965468fca1 feat(lsp): support workspace/codeLens/refresh 2026-02-03 22:25:21 +08:00
Yi Ming
fe23168e2b feat(lsp)!: reimplement textDocument/codeLens as decoration provider 2026-02-03 22:25:18 +08:00
Harsh Kapse
36db6ff2c1 fix(lsp): use LSP textEdit range for completion start boundary (#37491)
Previously, adjust_start_col returned nil when completion items had
different start position from lsp textEdit range
This caused the completion to fall back to \k*$ which ignores the
non-keyword characters

Changes:
- adjust_start_col: now returns the minimum start postion among all
items instead of nil
- _lsp_to_complete_items - normalizes the items by adding the gap between
  current and minimum start

Fixes: https://github.com/neovim/neovim/issues/37441
2026-01-30 15:34:42 +01:00
Evgeni Chasnovski
164cab405b test(pack): cover that events work when installing from the lockfile 2026-01-29 16:25:02 +02:00
Justin M. Keyes
75114fe7bb Merge #37428 vim.pack tests 2026-01-28 06:48:57 -05:00
phanium
fd45bc8cab fix: lsp.enable() don't work correctly inside FileType event #37538
Problem:
Two cases lsp.enable() won't work in the first FileType event
1. lsp.enable luals inside FileType or ftplugin/lua.lua, then:
```
nvim a.lua
```

2. lsp.enable luals inside FileType or ftplugin/lua.lua, then:
```
nvim -> :edit a.lua -> :mksession! | restart +qa! so Session.vim
```

Solution:
Currently `v:vim_did_enter` is used to detected two cases:
1. "maunally enabled" (lsp.enable() or `:lsp enable`)
2. "inside FileType event"

To detect 2. correctly we use did_filetype().
2026-01-27 17:59:36 -05:00
jdrouhard
8ed68fda50 feat(lsp): semantic token range improvements #37451
* cache all tokens from various range requests for a given document
  version
  - all new token highlights are merged with previous highlights to
    maintain order and the "marked" property
  - this allows the tokens to stop flickering once they've loaded once
    per document version
* abandon the processing coroutine if the request_id has changed instead
  of relying only on the document version
  - this will improve efficiency if a new range request is made while a
    previous one was processing its result
* apply new highlights from processing coroutine directly to the current
  result when the version hasn't changed
  - this allows new highlights to be immediately drawable once they've
    processed instead of waiting for the whole response to be processed
    at once
* rpc layer was changed to provide the request ID back in success
  callbacks, which is then provided as a request_id field on the handler
  context to lsp handlers
2026-01-27 08:56:52 -05:00
Evgeni Chasnovski
b4dd11cd5d test(pack): use a helper to vim.pack.add inside testnvim instance
Problem: A lot of test cases require executing `vim.pack.add()` inside
  `testnvim` instance to install and/or add plugins. This requires
  access to the information about tested repo sources (stored in a Lua
  variable inside a runner instance), so it needs to go
  `exec_lua(function() vim.pack.add({...}) end)` route, which in
  formatted form adds two more lines. Since it is very frequent, it pads
  test files with (mostly avoidable and unncessary) lines.

Solution: Add `vim_pack_add()` helper specifically to execute
  `vim.pack.add` inside `testnvim` instance. Use it where possible:
  usually when `vim.pack.add` is not a subject of the test. It is not
  quite doable for some cases, though:
  - When error in `vim.pack.add` is tested.
  - When specification includes `vim.version.range` (since `exec_lua`
    seems to not transfer necessary class metatables).

  This removes ~100 lines from the file at the cost of sometimes using
  `vim_pack_add` and sometimes having to reside to `vim.pack.add`.
  Which seems like a positive trade-off.

  This also allows making a more compact `exec_lua('vim.pack.update()')`
  instructions since `vim.pack.update` doesn't depend on the upvalues
  stored in test runner instance.
2026-01-16 18:49:14 +02:00
Evgeni Chasnovski
0232a63fa5 test(pack): make various small cleanups
Problem: `vim.pack` tests might benefit from a cleanup

Solution: Do the cleanup:
  - Use `t.retry` instead of full `vim.uv.sleep` to make tests quicker.
  - Use `pack_assert_content` helper for a common task of checking the
    content of a special Lua file inside an installed plugin. This is
    used as a proxy of installed plugin's state on the disk.
  - Use `([[...]]):format()` approach (instead of array of strings) in
    one more place. Should improve readability.
2026-01-16 18:31:53 +02:00
zeertzjq
cabf82be5a test(lsp/diagnostic_spec): fix creating unused clients (#37397)
Fix #36793

Also fix some `integer?` -> `integer` conversion warnings while at it.
2026-01-15 00:23:55 +00:00
Evgeni Chasnovski
bac4cde9cd fix(pack): actually checkout proper version of submodules
Problem: Installing plugin with submodules doesn't check out their
  state (due to `git clone --no-checkout` to not end up with default
  branch code in case of invalid `version`).

  Updating a plugin with submodules doesn't update their state.

Solution: Update `git_checkout` helper to account for submodules.
  Another approach would be `git checkout --recurse-submodules ...`,
  but that doesn't seem to allow `--filter=blob:none` for submodules,
  which is nice to have.

  Also make `git_clone` wrapper simpler since `--no-checkout` makes
  `--recurse-submodules` and `--also-filter-submodules` do nothing.
2026-01-12 22:57:38 +02:00
Evgeni Chasnovski
09edb145f5 test(pack): adjust add startup tests to just sleep with longer timeout
Problem: The `add` startup tests mock startup process which requires
  *some* amount of time to be done. Previous solution with `vim.wait`
  to wait just enough time to register that startup script has finished
  doesn't seem to work as intended (it just wait full time). Its timeout
  is also seems to be barely enough to pass on Windows CI. Which will be
  a problem with more `git` actions done on startup in the future/next
  commit.

Solution: Just sleep predetermined amount of time and explicitly check
  if startup script finished executing.
2026-01-12 22:30:56 +02:00
Evgeni Chasnovski
8f0b8a2c27 fix(pack): skip git stash during install
Problem: Installing plugin is done via `git clone --no-checkout ...`
  (to not end up with default branch code in case of invalid `version`).
  This leaves cloned repo in a state that `git stash` will actually add
  an entry to the stash list. Although not critical, better to not have
  that if possible.

Solution: explicitly skip `git stash` step in checkout during install.
2026-01-12 15:53:36 +02:00
zeertzjq
7a6e8d4430 docs: misc (#37281)
Close #37289
Close #37348

Co-authored-by: Marc Jakobi <marc@jakobi.dev>
Co-authored-by: Anton Kesy <anton@kesy.de>
2026-01-12 03:50:57 +00:00
Robert Muir
1629493f72 perf(lsp): avoid textDocument/definition requests during tag completion (#37260)
Problem:
vim.lsp.tagfunc looks for the presence of 'c' (cursor) flag and issues
sync textDocument/definition requests to all clients, otherwise
workspace/symbol requests. But 'c' flag can also be set during the
insert mode completion, e.g. with an empty tag completion query, the tag
func receives pattern of '\<\k\k' with flags 'cir'.

Solution:
check for 'i' (insert mode completion) flag and don't issue any LSP
requests, return vim.NIL for immediate fallback to tags.
2026-01-11 14:41:26 -08:00
Yochem van Rosmalen
f19653e370 fix(health): emit Progress message #37123
Problem:
The `"Running healthchecks..."` message doesn't inform the user much and
is a hack from before we got a way to emit actual progress messages.

Solution:
Use `nvim_echo` to emit progress messages showing the name of the report
that is currently running.
2026-01-09 17:00:09 -05:00
Tristan Knight
ed562c296a fix(lsp): improve dynamic registration handling #37161
Work on #37166 

- Dynamic Registration Tracking via Provider
- Supports_Method
    - Multiple Registrations
    - RegistrationOptions may dictate support for a method
2026-01-02 01:46:13 -05:00
altermo
170992c8d2 test(tohtml): test syntax, not just treesitter #37181 2025-12-31 18:00:05 -05:00