Commit Graph
107 Commits
Author SHA1 Message Date
glepnir 2a344d8c84 fix(lsp): snippet is not expanded when resolve races the user #41774
Problem:
on_complete_done() defers clear_word() and the snippet expansion until
completionItem/resolve answers, and drops both when 'changedtick' moved
meanwhile. Typing right after accepting leaves the plain word in the
buffer.

Solution:
Expand before requesting, and anchor the resolved edits with an extmark
instead of gating them on 'changedtick'.
2026-09-11 07:49:57 -04:00
Lewis Russell d039f19af5 build: enable more EmmyLua checks
Enable checks for unused code, deprecated calls, return types, and
annotations.

Fix the warnings and replace the deprecated highlight function. Keep
exceptions where old APIs are still needed or the checker gets it wrong.

AI-assisted
2026-09-09 22:31:58 +01:00
glepnir 0a844adc13 fix(lsp): newlines in the completion word from insertText #41801
Problem:
A textEdit is cut to its first line but an insertText is not, so its
newlines reach the |complete-items| word.

Solution:
Cut it the same way.
2026-09-09 08:04:23 -04:00
Lewis Russell 65ef6fdaee build: replace LuaLS with EmmyLua
Problem: LuaLS struggles with the generics used in Nvim's runtime,
requiring broad diagnostic suppressions. Indexing is also slow.

Solution: Use EmmyLua for type checks in the build and CI. It offers
more sophisticated type checking, substantially better support for
generics, and much better flow analysis.

Correct the affected annotations. Use `@internal`, supported directly by
EmmyLua, instead of `@nodoc` for shared internal declarations, and
support it in the help parser.

AI-assisted
2026-09-07 15:33:22 +01:00
glepnir 937f835a3e feat(lsp): support dynamic registration of completionProvider #41748
Problem:
dynamicRegistration is declared false, and completionProvider is read
from server_capabilities only.

Solution:
Declare it, and prefer registerOptions per field.
2026-09-07 09:53:35 -04:00
glepnir 2a382ffb61 fix(lsp): completion overwrites text before the word boundary #41463
Problem:
One item with an edit range before the word boundary changes the start
column for all items. For tsserver `str.`, completing `str.char` can
become `strcharAt` and break filtering.

Solution:
Prepend the missing text and filter on it.
2026-08-24 06:14:49 -04:00
glepnir 2c5f37f6af fix(lsp): empty filterText/sortText/insertText not treated as unset #41421
Problem:
Empty string is falsy, so the spec's label fallback applies, but there only checks
for nil. An empty filterText drops the item, an empty sortText sorts it
first, and an empty insertText leaves the word empty.

Solution:
Treat empty string as unset.
2026-08-22 07:40:17 -04:00
glepnir 3fa5904cf2 fix(lsp): multibyte fragment treated as commit char #41019
Problem:
commit_chars_str() reads a 0x80-0xBF byte as a 2-byte lead, so
"\xA9x" makes "x" a commit character. nvim_get_hl() returns
a dict, so `#` on it is 0 whether or not the group exists

Solution:
use vim.str_utf_end() and drop entries that are not one whole
character. use next check dict length.
2026-07-28 08:39:03 -04:00
446b9d8c55 docs: misc, remove some old help tags #40214
- Remove old help tags: they add noise to cmdline completion.

Co-authored-by: acehinnnqru <acehinnnqru@gmail.com>
Co-authored-by: KangaZero <samuelyongw@gmail.com>
Co-authored-by: Simone Ragusa <hi@interrato.dev>
Co-authored-by: Chinmay Dalal <~chinmay/public-inbox@lists.sr.ht>
Co-authored-by: coyaSONG <66289470+coyaSONG@users.noreply.github.com>
Co-authored-by: Olivia Kinnear <git@superatomic.dev>
2026-07-18 04:29:51 -04:00
glepnir 9fae7234f6 feat(completion): support completionList.applyKind #40769
Problem: values from completionList.itemDefaults always replace the
item's own commitCharacters and data. Since 3.18 a server can ask for
them to be merged instead.

Solution: Handle CompletionList.applyKind and advertise applyKindSupport.
Drop itemDefaults once folded into the items: get_items() runs twice on
the same result and a Merge isn't idempotent.

https://microsoft.github.io/language-server-protocol/specifications/lsp/3.18/specification/#completionItemApplyKinds
2026-07-17 21:07:01 -04:00
glepnir 5ce9e74f13 feat(completion): commitCharacters #38417
Problem: LSP completion commitCharacters are not handled. Typing a
commit character (e.g. `.`, `(`, `;`) while a completion item is
selected does not accept the item first.

Solution: Store commit characters as a flat string in complete-items.
Check it before completion stops, accept the match and let
the character be inserted normally.
2026-07-15 19:08:37 -04:00
Justin M. Keyes 9982f6e0e4 refactor(api): omit optional param 2026-07-13 19:44:15 +02:00
XiaowenHu96 ce718e31f4 feat(api): add nvim_win_resize()
Ref #6645

Problem:
When a window is resized it takes space from the window right/below first,
and only falls back to the window left/above when there is no more room.
Sometimes a user wants the space to come from a specific direction.

Solution:
Add nvim_win_resize(win, width, height, {anchor}) which resizes a window
with a choosable anchor edge, letting a window grow leftwards or upwards
by taking space from the window to the left or above first. The default
anchor reproduces nvim_win_set_width()/nvim_win_set_height().
2026-07-05 21:47:34 +08:00
glepnir 02b7415324 fix(lsp): requery empty isIncomplete completion lists #40100
Problem:
an empty `{ isIncomplete = true, items = {} }` ends completion
instead of requerying.

Solution:
keep isIncomplete on empty lists and retrigger on keypress while incomplete.
Reset on <C-e> so it doesn't immediately re-query.
2026-06-15 18:29:27 -04:00
cbadc4f164 docs: misc, lsp
Problem:
This doc on `vim.lsp.completion.get()`:

    --- Used by the default LSP |omnicompletion| provider |vim.lsp.omnifunc()|, thus |i_CTRL-X_CTRL-O|
    --- invokes this in LSP-enabled buffers. Use CTRL-Y to select an item from the completion menu.
    --- |complete_CTRL-Y|

...makes two wrong claims:

1. "Used by the default LSP omnicompletion provider vim.lsp.omnifunc()"
    - `_omnifunc` does not call `M.get()`, it calls the internal `trigger()` directly.
2. "thus |i_CTRL-X_CTRL-O| invokes this in LSP-enabled buffers"
    - The two paths use different client sets:
        - `M.get()` reads `buf_handles[bufnr].clients` (clients
          explicitly registered via `vim.lsp.completion.enable(true, ...)`).
        - `_omnifunc` reads `lsp.get_clients({method='textDocument/completion'})` (every
          completion client, regardless of `enable()`).

Solution:
Update docs.

Co-authored-by: Koichi Shiraishi <zchee.io@gmail.com>
Co-authored-by: y9san9 / Alex Sokol <y9san9@gmail.com>
Co-authored-by: adv0r <>
2026-06-03 12:27:30 +02:00
Marcus Caisey c75365d22a refactor(lsp): centralise complete item info generation logic
Problem:
The logic for generating the complete item `info` is spread across
`_lsp_to_complete_items`, the `CompleteChanged` event handler, and
`CompletionResolver:request`. This has previously caused the `info`
shown for resolved (via `completionItem/resolve`) and unresolved items
to differ.

Solution:
Centralise the logic in a new `complete_item_info` function which is now
solely responsible for determining:
1. The `info` to show.
2. The markup kind of the `info`.
3. Whether the `info` is complete.

This simplifies the interaction between the 3 functions mentioned in the
problem:
- `_lsp_to_complete_items` calls `complete_item_info` and passes along
  the markup kind and whether the item needs resolving via the complete
  item's `user_data`.
- The `CompleteChanged` consumes the markup kind and whether the
  item needs resolving from the complete item's `user_data`.
- `CompletionResolver:request`, like `_lsp_to_complete_items` calls
  `complete_item_info` again and updates the current `info` if it's
  changed.
2026-05-21 18:22:13 +01:00
Marcus Caisey d6d03716cf fix(lsp): show detail in popup when server can't completionItem/resolve
Problem:
`CompletionItem.detail` is only shown in the info popup if the server
supports `completionItem/resolve`.

Solution:
If the server doesn't support `completionItem/resolve`, prepend the
complete item `info` with `CompletionItem.detail` in a fenced codeblock,
same as we do when the server supports `completionItem/resolve`.

To ensure that completion items are displayed in the same way,
regardless of whether the server supports `completionItem/resolve`, i've
extracted out the test logic from the `selecting an item triggers
completionItem/resolve + (snippet) preview` case so that we can run the
same tests against a server which supports `completionItem/resolve` and
one which doesn't. Hopefully this should prevent the two behaviours
diverging again.
2026-05-21 18:22:13 +01:00
Marcus Caisey ce7df01391 fix(lsp): resolve CompletionItem if resolvable fields aren't populated
Problem:
If `CompletionItem.documentation` is populated but `detail` is not, then
`detail` is not resolved.

Solution:
Ensure that we resolve a `CompletionItem` if either `detail` or
`documentation` are not populated.

I've also removed `detail` from the popup menu since otherwise it will
be populated in both the popup menu and the info popup after the
`CompletionItem` has been resolved. I think the info popup is the best
place for it anyway as when there is a completion item with a long popup
menu entry (when `detail` is a medium/long function signature for
instance), the whole popup menu gets widened and this steals horizontal
space that could be used to display the `documentation`. Now with
`detail` and `documentation` in the info popup, they share the same
horizontal space. This also aligns with how VSCode, nvim-cmp, blink.cmp,
and mini.nvim display `detail`.
2026-05-21 18:15:14 +01:00
Marcus Caisey 10a53e7637 fix(lsp): generate snippet preview from resolved textEdit.newText
Problem:
When a resolved `CompletionItem` with kind `Snippet` populates
`textEdit` instead of `insertText`, the contents are not previewed.

Solution:
Generate the snippet preview from `textEdit.newText` as well.
2026-05-21 17:47:08 +01:00
Justin M. Keyes 9aa4608401 refactor: introduce nvim_on internally #39883
Problem:
`nvim_create_autocmd` is too verbose and its `callback` requires extra
"nesting".

Solution:
Introduce `nvim_on`. Start using it internally. Then we can get a feel
for how it should look before making it public.
2026-05-20 17:33:01 -04:00
glepnir 3ffe29d679 fix(lsp): preserve trigger chars on completion #39850
Problem:
After 767fbd8, typing trigger chars would open completion but the
chars were removed.

Solution:
Use filterText fallback so selected item respects typed trigger chars.
2026-05-18 05:25:41 -04:00
glepnir 767fbd88ff fix(lsp): fallback to filterText for non-matching PlainText items #39695
Problem:
PlainText completion items used `textEdit.newText` or `insertText` as
the completion word even when they did not match the typed prefix. This
could break popup completion behavior like 'completeopt+=longest'.

Solution:
Fall back to `filterText` when `newText` or `insertText` does not match
the typed prefix.
2026-05-17 11:58:49 -04:00
Olivia Kinnear fcd1d97265 feat(lua)!: vim.isnil, vim.nonnil, deprecate vim.F #39495 2026-05-06 08:15:00 -04:00
Olivia Kinnear 1799aaebda fix(lsp): util.lua attempt to concatenate userdata #39225
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`.
2026-04-28 19:17:44 -04:00
glepnir b9431b340f fix(lsp): show meaningful error on invalid completion response #39445
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
2026-04-28 10:18:37 -04:00
glepnir b351afb1b1 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.
2026-04-18 15:43:20 -04:00
glepnir 53a29dce0e feat(completion): completeopt=preselect, LSP CompletionItem.preselect #36613
Problem: 
LSP CompletionItem.preselect is not supported.
https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#completionClientCapabilities

Solution:
- Add "preselect" field to complete-items and "preselect" flag
  to 'completeopt'.
- Set preselectSupport=true in LSP client capabilities.
2026-04-13 05:59:07 -04:00
JordanandJustin M. Keyes 3a4a66017b feat(api): rename buffer to buf #35330
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: Justin M. Keyes <justinkz@gmail.com>
2026-04-08 20:34:47 -04: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
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
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
Mathias Fussenegger 507cd63418 fix(lsp): handle completion/resolve response arriving after on_insert_leave
If a user accepts completion and immediately exits insert mode, it
could happen that `Context.cursor` was nil by the time the
`completion/resolve` response arrives, leading to an error.
2026-03-20 17:20:08 +01:00
286b78de9b docs: misc, terminal
Close #38319
Close #38348

Co-authored-by: zeertzjq <zeertzjq@outlook.com>
Co-authored-by: Barrett Ruth <br.barrettruth@gmail.com>
2026-03-18 20:40:20 +01: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
Justin M. Keyes 017d8aa298 refactor: rename _ensure_integer => _assert_integer 2026-03-13 20:32:01 +01:00
Lewis Russell ce1154048b refactor: integer functions, optimize asserts #34112
refactor(lua): add integer coercion helpers

Add vim._tointeger() and vim._ensure_integer(), including optional base
support, and switch integer-only tonumber()/assert call sites in the Lua
runtime to use them.

This also cleans up related integer parsing in LSP, health, loader, URI,
tohtml, and Treesitter code.

supported by AI
2026-03-12 11:04:05 -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
glepnir 145548a24a feat(lsp): show snippet preview if completeopt=popup #32553
Problem:
LSP completion does not show snippet preview.

Solution:
Show snippet preview if 'completeopt' includes popup.
2026-03-10 14:34:58 -04: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
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
Maria Solano 6fe68abdf5 fix(lsp): use entire line as completion word (#37949) 2026-02-18 11:40:34 -08: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
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
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