aboutsummaryrefslogtreecommitdiff
path: root/test/functional/plugin
Commit message (Collapse)AuthorAge
...
* feat(pack): update `get()` to return revision of a pending updateEvgeni Chasnovski2026-05-17
| | | | | | | | | | | | Problem: No convenient way to programmatically get the revision that would be checked out after `vim.pack.update()` (with `offline=true`). Doing this manually requires resolving `spec.version` which is not trivial. This data can be useful for custom reporting of pending updates or third party confirmation step. Solution: Make `get()` include a new field for the revision that points at the state after applying pending update. This is also the same as the revision of resolved `spec.version`.
* feat(pack): update `get()` to take `rev` from actual repo if `info=true`Evgeni Chasnovski2026-05-17
| | | | | | | | | | | | Problem: `vim.pack.get()` always uses lockfile as the source for the `rev` field. This is fast, but may be misleading in case of a corrupted lockfile. Solution: Compute revision from Git repo on disk if `info=true` (default), use lockfile otherwise. This does increase execution time (as a result of one extra `git ...` call for every plugin), but `info=true` is already designed to be informative and not necessarily fast.
* feat(pack): :packupdate, :packdel commands #39693Olivia Kinnear2026-05-16
| | | | | | Define `:packupdate` and `:packdel` as separate commands instead of a unified `:pack {subcommand}` because the semantics between the two commands vary differently enough that it doesn't make sense to combine them. Additionally, `:pack! update/del` looks bad.
* fix(difftool): handle filenames containing spaces #39740Jackson Ludwig2026-05-14
| | | | | | | | | | | Problem: Using the `DiffTool` plugin (e.g. through `nvim -d ...` or `:DiffTool <file1> <file2>` fails if a space is in one of the paths. This occurs because the `diff` wraps the paths with quotes (`'`) if space characters are present, which the line diff regex fails to parse. Solution: Update regex to handle quoted paths by matching the string within the quotes, if it exists.
* refactor!: remove deprecated APIsYi Ming2026-05-11
|
* feat(logging): vim.log #38906Yi Ming2026-05-10
|
* fix(pack): suggest "delete" code action for active plugins #39678Evgeni Chasnovski2026-05-08
| | | | | | | | | | Problem: Trying to execute code action on an active plugin without updates leads to nothing. It is more useful if code actions "do something" on a bigger portion of the confirm buffer. Solution: Suggest "delete" code action even for active plugins. Trying to execute it will first show a confirmation buffer with relevant warning of why this might be not a good idea. Confirming will delete a plugin.
* fix(lsp): support nested workspace registrations #39574Tristan Knight2026-05-05
| | | | | | | | | | | Problem: Nested workspace capabilities like workspace.fileOperations.didCreate and workspace.textDocumentContent are not handled consistently for dynamic and static registration provider lookup. Solution: Generate explicit registration-provider mappings from the LSP metadata and use them when registering and querying capabilities. Add coverage for dynamic and static nested workspace registrations.
* test: unreliable pack_spec.after_each: "EBUSY: resource busy or locked" #39606David Balatero2026-05-05
| | | | | | | | | | | | | | | | | | | | | | | | | | | | 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.
* fix(lsp): dynamic registration for off-spec method #39544Tristan Knight2026-05-01
| | | | | | | | | | | | | 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
* fix(lsp): send didClose, didOpen when languageId changes #39499phanium2026-04-30
| | | | | | | | | | | | | | | | | | | | | | 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: https://github.com/microsoft/language-server-protocol/blob/0003fb53f18dc7a4ac7e51d0eb518deeea90fde5/_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
* fix(lsp): util.lua attempt to concatenate userdata #39225Olivia Kinnear2026-04-28
| | | | | | | | | 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`.
* fix(lsp): show meaningful error on invalid completion response #39445glepnir2026-04-28
| | | | | | | | | 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
* fix(lsp): handle relative='editor' in make_floating_popup_options() #39320Daigo Yamashita2026-04-26
| | | | | | | | | | | | | | | | | | Problem: With `vim.g.health = { style = 'float' }`, running `:checkhealth` from a `:help` buffer placed the float in the top-left corner instead of centered. make_floating_popup_options() picks the NW/NE/SW/SE anchor and the available height from cursor-relative metrics (winline(), wincol(), winheight()). When the caller passes relative='editor', those metrics are meaningless, so the function could flip to an 'E' anchor and clamp the float off-screen. Solution: When relative='editor', treat the whole editor area as available space (lines_above=0, lines_below=&lines, wincol=0). This makes the NW anchor the natural choice and keeps the float position stable regardless of where the cursor is in the current window. AI-assisted: Claude Code
* fix(util): add and use forge link computationEvgeni Chasnovski2026-04-25
| | | | | | | | Problem: There are many Git forges each with a different way of constructing permanent links to like commits and tags. Solution: Add a private utility function that computes these special links on the best effort basis.
* feat(pack): support `textDocument/documentLink` in confirmation bufferEvgeni Chasnovski2026-04-25
| | | | | | | | | | | | | | Problem: In `vim.pack.update()` confirmation buffer it might be useful to be able to use `gx` (open link at cursor) when cursor is on something like commit or tag. Solution: Add `textDocument/documentLink` method support for the in-process LSP. This may be used by LSP clients and makes `gx` automatically work. The shortcoming is that this requires tracking how to construct a URL from source and commit/tag. Currently only GitHub hosted repositories are supported.
* fix(lsp): handle self-mapped methods in supports_method #39383Tristan Knight2026-04-24
| | | | | | | | | | | | | | | 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.
* feat(tui): restore 'ttyfast' to control tty requests #38699Kyle2026-04-24
| | | | | | | | | | | | Problem: When running nvim on a remote machine over SSH, if there is high ping, then bg detection may not complete in time. This results in a warning every time nvim is started. #38648 Solution: Restore 'ttyfast' option and allow it to control whether or not bg detection is performed. Because this is during startup and before any user config or commands, we use the environment variable `NVIM_NOTTYFAST` to allow disabling `ttyfast` during initialization.
* test: curbuf initialized in describe-block #39365glepnir2026-04-24
| | | | | | Problem: curbuf was initialized at describe-block load time before any Nvim session existed. Solution: Replace with 0 directly at call sites.
* fix(lsp): more info in error msg, deduplicate test #39359Justin M. Keyes2026-04-24
|
* fix(lsp): handle null id in JSON-RPC responses #38340atusy2026-04-23
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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.
* fix(pack): only use tags that strictly comply with semver spec #39342Evgeni Chasnovski2026-04-23
| | | | | | | | | | | | | | | | | | 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.
* fix(lsp): callHierarchy/outgoingCalls ranges are relative to caller, not ↵Ashley Hauck2026-04-23
| | | | | | | | | | | | | 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)
* fix(lsp): filter code_action diagnostics to the cursor #38988Barrett Ruth2026-04-23
| | | | | | | 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.
* ci: drop cirrus #39321Justin M. Keyes2026-04-22
| | | | | | | | Problem: cirrus will shutdown soon, and we are running out of minutes anyway, which causes ci failures. Solution: Drop cirrus config.
* fix(pack): GIT_DIR/GIT_WORK_TREE env vars may interfere #39279fleesk2026-04-22
| | | | | | | | 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.
* refactor(test): drop deprecated exc_exec #39242Justin M. Keyes2026-04-20
|
* fix(lsp): show CompletionItem.detail in info popup #38904glepnir2026-04-18
| | | | | | | 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: misc #39045Justin M. Keyes2026-04-18
|
* fix(lsp): skip codelens refresh redraw for deleted buffer #39193Jaehwang Jung2026-04-18
| | | | | | | | | | | | 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>
* test(lsp): extract buf/util parts from lsp_spec.lua #39149Yi Ming2026-04-17
| | | | | | | | | 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.
* test(pack): increase retry timeout for startup test #39125Evgeni Chasnovski2026-04-16
| | | | | | | | 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.
* fix(lsp): set 'winfixbuf' in open_floating_preview() window #39058Raizento2026-04-15
| | | | | | | | | Problem: The window opened by `vim.lsp.util.open_floating_preview()` allows its buffer to be switched. Presumably that only happens by accident and is disorienting. Solution: Set 'winfixbuf' in the open_floating_preview() window.
* refactor: update usages of deprecated "buffer" param #39089Justin M. Keyes2026-04-15
|
* feat(lsp): highlight foldtext via treesitter #38789Yi Ming2026-04-15
| | | | | | | | | | Problem: To support `collapsedText`, which allows the LSP server to determine the content of the foldtext, we provided `vim.lsp.foldtext()`. However, such content does not have highlighting. Solution Treat the filetype of `collapsedText` as the filetype of the corresponding buffer and use tree-sitter to highlight it.
* test(pack): use n.rmdir() to delete directories #39046Evgeni Chasnovski2026-04-14
| | | | | | | 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.
* docs: lsp, options, api #38980Justin M. Keyes2026-04-14
| | | | | | | | | docs: lsp, options - revert bogus change to `_meta/builtin_types.lua` from 3a4a66017b74 Close #38991 Co-authored-by: David Mejorado <david.mejorado@gmail.com>
* feat(completion): completeopt=preselect, LSP CompletionItem.preselect #36613glepnir2026-04-13
| | | | | | | | | | 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.
* fix(lsp): show_document can't position cursor past EOL in insert-mode #38566Lars Debor2026-04-12
| | | | | | | | 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.
* fix(lsp): send didOpen on save to all clients+groups #37454Emilv22026-04-12
| | | | | | | 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.
* fix(lsp): apply_text_edits causes unwanted BufDelete events #38778glepnir2026-04-08
| | | | | | | | | | | | | | Problem: Since 2f6d1d3c887a87d9402137425b418dd12a904aac, `apply_text_edits` unconditionally sets `buflisted=true`, causing spurious BufDelete events if plugins restore the original 'buflisted' state on unlisted buffers: https://github.com/neovim/neovim/blob/65ef6cec1cb766334c59d3255595dfe523b11020/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.
* fix(diagnostics)!: restore `is_pull` namespace argument #38698Maria Solano2026-04-08
| | | | | | | | | | | | | | | | 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.
* fix(health): misleading warnings re filetypes registered w/ ↵Barrett Ruth2026-04-08
| | | | | | | | | | | | | | | | | 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()`.
* feat(lsp): respect 'switchbuf' for jump commands, drop `reuse_win` #38510Yi Ming2026-03-30
| | | | | | | | | | | | | | | | | | Problem: LSP jump operations such as `buf.definition`/`buf.type_definition` do not follow the 'switchbuf' option. Instead their behavior is controlled by `vim.lsp.LocationOpts.reuse_win`. When `reuse_win=true`, the effect is very similar to `set switchbuf=useopen`. Note that functions like `buf.definition` open the quickfix window when there are multiple results, and jumping between quickfix entries already follows 'switchbuf', so unifying the behavior is more intuitive. Solution: Follow the 'switchbuf' option and drop `reuse_win`. We can achieve this behavior by using :cfirst when the quickfix list has only one item, rather than customizing the jump logic as before.
* fix(lsp): highlight snippet preview when server can't completionItem/resolve ↵Marcus Caisey2026-03-29
| | | | | | | | | | | | | | | | | | (#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.
* 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.
* test: fix s390x failuresJustin M. Keyes2026-03-29
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |