aboutsummaryrefslogtreecommitdiff
path: root/test/functional/plugin/lsp/inline_completion_spec.lua
Commit message (Collapse)AuthorAge
* fix(lsp): advance inline completion range over matching input #41434Étienne Robert2026-08-24
| | | | | | | | | | | | | | | Problem: `Completor:accept()` applies the item against the range the server answered with. Characters typed after the request but before accepting lie inside neither that range nor the replacement, so they are left behind by the insertion: typing `a` after `foob` and accepting `foobar` within the 200 ms debounce yields `foobara`. Solution: Grow the item's range over the characters typed since the request, so that `accept()` replaces them. Only while the candidate still matches, decided by the longest common prefix `show()` already computes, so input that contradicts it is left alone. Snippet items are unaffected, since `accept()` ignores the range for them.
* fix(lsp): clamp inline completion range to the line on accept #41435Étienne Robert2026-08-24
| | | | | | | | | | | | | | | | | | Problem: `Completor:accept()` hands the item's range straight to `nvim_buf_set_text()`. That range is resolved when the response arrives, so text deleted before accepting (backspacing within the 200 ms debounce) leaves the range end past what is left of the line, and the accept aborts with `Invalid 'end_col': out of range`. 18d6436 fixed the same staleness in `Completor:show()`, which drops an item once its range *start* falls outside the buffer. That guard does not cover the range end, and `accept()` was never given one, so this is a hole left by that fix rather than a regression of it. Solution: Clamp the end of the range to the end of the line before writing. The start needs no clamp: `show()` dropped the item one event loop tick earlier if it had gone out of range.
* test(harness): migrate away from magic globalsJustin M. Keyes2026-07-21
| | | | | | | | | | | | | | | | | | | | | 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`.
* feat: extend vim.Pos, vim.Range #36397Luis Calle2026-03-29
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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.
* fix(lsp): don't overlay insertion-style inline completions (#36477)Riley Bruins2025-11-09
| | | | | | | | | | | | | | | * feat(lua): `Range:is_empty()` to check vim.range emptiness * fix(lsp): don't overlay insertion-style inline completions **Problem:** Some servers commonly respond with an empty inline completion range which acts as a position where text should be inserted. However, the inline completion module assumes that all responses with a range are deletions + insertions that thus require an `overlay` display style. This causes an incorrect preview, because the virtual text should have the `inline` display style (to reflect that this is purely an insertion). **Solution:** Only use `overlay` for non-empty replacement ranges.
* fix(lsp): avoid automatic request after leaving insert mode (#35767)zeertzjq2025-09-15
| | | | | | | | | | | | | | | | | This also fixes the following warning in tests with ASAN or TSAN: -------- Running tests from test/functional/plugin/lsp/inline_completion_spec.lua RUN T4604 vim.lsp.inline_completion enable() requests or abort when entered/left insert mode: 225.00 ms OK RUN T4605 vim.lsp.inline_completion get() applies the current candidate: 212.00 ms OK nvim took 2013 milliseconds to exit after last test This indicates a likely problem with the test even if it passed! RUN T4606 vim.lsp.inline_completion get() accepts on_accept callback: 212.00 ms OK RUN T4607 vim.lsp.inline_completion select() selects the next candidate: 220.00 ms OK -------- 4 tests from test/functional/plugin/lsp/inline_completion_spec.lua (3437.00 ms total) -------- Running tests from test/functional/plugin/lsp/linked_editing_range_spec.lua nvim took 2011 milliseconds to exit after last test This indicates a likely problem with the test even if it passed!
* test(lsp): fix flakiness in inline completion test (#35676)zeertzjq2025-09-08
| | | | | The flakiness happens because get() uses vim.schedule(), and a following key may be processed before the scheduled event. Use poke_eventloop() to ensure that the scheduled event is processed.
* feat(lsp): vim.lsp.inline_completion on_accept #35507Yi Ming2025-09-01
|
* feat(lsp): support `textDocument/inlineCompletion`Yi Ming2025-08-25