| Commit message (Collapse) | Author | Age |
| |
|
|
|
|
|
|
|
|
|
|
| |
Problem:
Accepting an item from another completion source raises an error when its
user_data.nvim table does not contain LSP metadata.
Solution:
Retrieve and guard the nested LSP metadata before accessing its fields.
Cover acceptance of a foreign completion item without LSP metadata.
AI-assisted
|
| |
|
|
|
|
|
|
|
|
|
|
| |
Problem:
An empty snippet insertText falls back to the label during selection, but
acceptance clears that label and expands an empty string.
Solution:
Require nonempty insertText before expanding a snippet without textEdit.
Extend the omnifunc acceptance fixture with an empty snippet insertion.
AI-assisted
|
| |
|
|
|
|
|
|
|
|
|
|
| |
Problem:
A completion list default edit range can replace the explicit range of an
InsertReplaceEdit, filtering out valid items or changing their replacement.
Solution:
Only synthesize a default text edit when the completion item has none.
Extend the existing itemDefaults test for explicit edits with both range variants.
AI-assisted
|
| |
|
|
|
|
|
|
|
|
|
|
| |
Problem:
Snippet completion words and previews prefer insertText even when textEdit
is present, although the actual expansion uses textEdit.newText.
Solution:
Use the text edit before the fallback insertion text in both selectors.
Extend the existing precedence test to check the snippet word and preview.
AI-assisted
|
| |
|
|
|
|
|
|
|
|
|
|
| |
Problem: Repeated default fields and field-by-field assertions obscure
the values that each functional test is meant to check.
Solution: Add eq_partial() to check selected record fields while
preserving list length and order. Use local helpers to fill fixed
expected defaults where tests need full equality. Keep explicit absence
checks and test-specific values at the call sites.
AI-assisted
|
| |
|
|
|
|
|
|
|
| |
Problem:
vim.lsp.completion.get() always asks every client that has completion
enabled in the buffer, so a mapping cannot ask just some of them.
Solution:
Add a "client_id" option that limits the request to the given client,
or clients if it is a list.
|
| |
|
|
|
|
|
|
|
|
|
| |
Problem:
After an LSP client restart, the completion reload callback can use an old
client ID:
autoread: :checktime failed for buffer 17: Vim:Lua callback:
...ed-95df8c0/share/nvim/runtime/lua/vim/lsp/completion.lua:1315: invalid client ID
Solution:
Use the completion augroup for `BufUnload` cleanup.
|
| |
|
|
|
|
|
|
|
|
|
| |
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'.
|
| |
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
| |
Problem:
A server that supports dynamic registration must not also declare
completionProvider at initialize, so server_capabilities.completionProvider
is nil for anything reading it directly.
Solution:
Do not advertise it by default. A client that follows a registration can
declare it itself.
|
| |
|
|
|
|
|
|
| |
Problem:
dynamicRegistration is declared false, and completionProvider is read
from server_capabilities only.
Solution:
Declare it, and prefer registerOptions per field.
|
| |
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Problem:
With the addition of the `:help al` text object, you can now easily
format the whole buffer with `gqal`. However, `vim.lsp.formatexpr` only
uses `textDocument/rangeFormatting` which some language servers (like
gopls) don't support.
Solution:
- Fall back to `textDocument/formatting` if the whole buffer is being formatted
and the server doesn't support `textDocument/rangeFormatting`.
- In theory, these two methods should return the same response if the whole
buffer is being formatted, but I preserved the existing behaviour of
prioritising `textDocument/rangeFormatting` in case that does not hold (i.e.
LS bug).
- Also: `vim.lsp.formatexpr` had no tests at all, so actually add tests for it.
|
| |
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Problem:
The magic globals `it`, `describe`, etc., are more trouble than they are
worth.
- Hooking into `after_each` requires `getfenv()` hacks.
- They confuse luals/emmylua, because the top-level `.luarc.json` isn't
merged with `test/.luarc.json` (apparently a luals limitation?)
- They totally defeat discoverability because the user just has to
"know" about the various magic symbols.
So they harm DX, which means they serve no purpose at all.
Solution:
- Expose the test API from `testutil`, so tests can call `t.it()`,
`t.describe()`, etc., in the conventional way.
- Drop `getfenv()` hacks.
- Drop the `setfenv()` injection in `load_chunk`.
- Drop `test/_meta.lua`.
|
| |
|
|
|
|
|
|
|
|
|
| |
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
|
| |
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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`.
|
| |
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
| |
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
|
| |
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
| |
docs: lsp, options
- revert bogus change to `_meta/builtin_types.lua` from 3a4a66017b74
Close #38991
Co-authored-by: David Mejorado <david.mejorado@gmail.com>
|
| |
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
(#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.
|
| |
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
| |
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
|
| |
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
| | |
|
| |
|
|
|
| |
gen_vimdoc.lua: In prepare for the upcoming release, comment-out the
"Experimental" warning for prerelease features.
|
| |
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
| |
Problem:
LSP completion does not show snippet preview.
Solution:
Show snippet preview if 'completeopt' includes popup.
|
| |
|
|
|
| |
Problem: Color completion items display as plain text without visual preview
Solution: Parse RGB/hex colors from documentation and render with colored symbol ■
|
| |
|
|
|
|
| |
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
|
| |
|
|
|
|
|
| |
Problem:
Tests are using some deprecated functions.
Solution:
Replace with command, pcall_err, etc.
|
| |
|
|
|
| |
Problem: LspDetach didn't clean up stale client refs in triggers table.
Solution: create LspDetach autocmd and call disable_completion.
|
| |
|
|
|
|
|
| |
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
|
| |
|
|
|
|
|
|
|
|
|
| |
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 }`
|
| |
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
| |
Problem:
Server start boundary can be emptied by response provided by next client.
Solution:
Don't empty it when extending the result list.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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
|
| |
|
|
|
|
|
| |
Problem: When fuzzy is enabled and the prefix is not empty,
items are not sorted by fuzzy score before calling fn.complete.
Solution: Use matchfuzzypos to get the scores and sort the items
by fuzzy score before calling fn.complete.
|