aboutsummaryrefslogtreecommitdiff
path: root/runtime/lua/vim/lsp/client.lua
Commit message (Collapse)AuthorAge
* fix(lua): enable param-type-mismatch diagnosticLewis Russell2026-09-28
| | | | | | | | | Problem: Argument type mismatches are excluded from EmmyLua checks. Solution: Correct runtime annotations and calls, document local checker workarounds, and enable the diagnostic. AI-assisted
* fix(lua): enable unnecessary-assert diagnosticLewis Russell2026-09-28
| | | | AI-assisted
* fix(lua): enable assignment type checking in runtime codeLewis Russell2026-09-25
| | | | | | | | | | | Enable EmmyLua's assign-type-mismatch diagnostic after correcting the runtime annotations and assignments it flags. Correct option, tuple, and return types, and use separate locals when a value changes representation. Add guards and narrow casts where needed so the runtime passes the stricter check. Regenerate the affected docs. AI-assisted
* fix(lua): enable nil-safety diagnostics in runtime codeLewis Russell2026-09-25
| | | | | | | | | | | | Enable EmmyLua's need-check-nil diagnostic and resolve nullable values through more precise types, explicit invariants, and guards for missing runtime state. Keep analyzer-specific workarounds local and update the affected API documentation. Exclude the bundled re.lua from analysis so its nil-check warnings do not fail CI. AI-assisted
* perf(lua): share compatible file watchersLewis Russell2026-09-24
| | | | | | | | | | | | | | | | | | Problem: LSP servers can register identical file watchers before removing old registrations. Each registration creates another watcher tree, making setup and teardown expensive in large workspaces. Solution: Move glob compilation into vim._watch and accept rules for multiple roots alongside existing single-path and LPeg inputs. Share compatible backends until their last subscription is cancelled. Ref: #23291 AI-assisted
* fix(lua): add missing param annotations (#41911)Lewis Russell2026-09-15
|
* build: enable more EmmyLua checksLewis Russell2026-09-09
| | | | | | | | | | 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
* build: enable more EmmyLua checksLewis Russell2026-09-08
| | | | | | | | | | | | | | | | - call-non-callable - missing-fields - redefined-label - redefined-local - undefined-field - unreachable-code Promote redefined-local and unreachable-code to warnings. Fix DOS line-ending handling for multiline semantic tokens, and support intersection types in the help parser. AI-assisted
* build: replace LuaLS with EmmyLuaLewis Russell2026-09-07
| | | | | | | | | | | | | | | 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
* fix(lsp): ignore (and log once) invalid documentSelector globs #41055Rocco Vaccone2026-08-04
| | | | | | | | | | | | | Problem: Client:_get_registrations() errors if a documentSelector pattern is not a valid glob (e.g. "**/**.dart" from dartls). The error discards already-matched registrations and propagates to supports_method() and the client/registerCapability handler, disabling capabilities unrelated to the offending pattern. Solution: Skip invalid globs. Treat them as non-matching, and log once per client. (Similar approach was taken for filewatcher globs: 4d9e5acfb5ee081b5b0761205c8a8c36ed7e49e5)
* feat(options): lua closure/function optionsJustin M. Keyes2026-07-31
| | | | | | | | | | | | | | | Problem: Cannot assign Lua functions/closures to "func" ('completefunc', 'tagfun', …) or "expr" ('foldexpr', 'indentexpr', …) options. Solution: - Store "func"/"expr" options as `Callback` instead of string. - Delete oceans of copy-pasted code. - BREAKING: LuaRef returned via RPC/Vimscript is now represented as `"<Lua N: file:line>"` (like what `:map` shows) instead of `nil`. - Note: `man.vim` still uses `v:lua` string, bc it's a vimscript ftplugin. Helped-by: Lewis Russell <lewis6991@gmail.com>
* fix(lsp): clear push diagnostics on detach #40634Oleh Volynets2026-07-08
| | | | | | | | | Problem: when an LS client detaches from the buffer, only pull diagnostics are cleared via capability framework. Push diagnostics remain stuck even when client stops/restarts. Solution: clear push diagnostics on client detach. ref #33864
* feat(lsp): convert inlay_hint to capability framework #40569jdrouhard2026-07-05
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Problem: Inlay hints used separate global and per-buffer bufstates tables and bespoke global autocmds for managing the inlay hint state across buffers and clients, duplicating the lifecycle logic already provided by the Capability framework. This caused inconsistencies in how client state was handled and inlay hint state lifecycle was managed compared to other LSP features. Solution: Replace the ad-hoc bufstate tracking and global autocmds in vim.lsp.inlay_hint with a proper InlayHint subclass of Capability. This also refactors the way inlay hint state is managed and fixes bugs I found while doing this: 1. For each line with inlay hints, the list of the hints along with whether they have been applied is stored in a current result on the client state. This allows the on_win decorator to clear all inlay hints for an old document version once, and then re-add the new version's hints line-by-line as they are drawn to the screen, modeling the semantic tokens module. 2. It fixes problems with mixing results from multiple clients attached to the buffer by fully moving each client's state to its own table. Previously, only the most recent document version used to populate a line's inlay hints was stored, but there was no distinction for which client the hints may have come from. (Fixes #36318) 3. It fixes the workspace/inlayHint/refresh server->client notification behavior. Previously it would only re-request inlay hints for buffers currently displayed in a window but would not invalidate them in non-displayed buffers (or provide any mechanism for those buffers to re-request at a later time). Model semantic token module here again by invalidating all buffers, and adding a BufWinEnter autocmd to refresh hints. 4. Add a mechanism to cancel in-flight requests if a new request for a newer document version is made before the last one returned 5. Handle stale results by simply dropping them.
* docs(lsp): document rpc Client request/notify as fields #40573Barrett Ruth2026-07-04
| | | | | | | | | | Problem: `request()` and `notify()` are methods of the object returned by `vim.lsp.rpc.start()`/`connect()`, but were rendered with module-level helptags (`vim.lsp.rpc.request()`, `vim.lsp.rpc.notify()`) (erroneously implying module functions that do not exist). Solution: Mark the wrappers `@private` and describe them on `vim.lsp.rpc.Client` instead.
* refactor(lsp): convert diagnostics to capability framework #40433jdrouhard2026-06-26
| | | | | | | | | | | | | | | | | | | | | | | | | Problem: Diagnostic tracking used a separate bufstates table and manual LspDetach/LspNotify autocmd management via _enable()/_refresh(), duplicating the lifecycle logic already provided by the Capability framework. This caused inconsistencies in how client attach/detach and buffer teardown were handled compared to other LSP features. Solution: Replace the ad-hoc bufstate tracking and _enable/_refresh pattern in vim.lsp.diagnostic with a proper Diagnostics subclass of Capability. This cleans up a few random places in the main lsp module and client module that were poking the diagnostics. It also fixes some pre-existing bugs and inconsistencies that were discovered: - Refresh diagnostics immediately on attach instead of lazily by the first didOpen/didChange notification - Fix Capability.active lookup in M.enable() to key by it_bufnr instead of the filter bufnr - Set lsp defaults before calling the _text_document_did_open_handler in Client:on_attach() so defaults are there before any lsp notification occurs - Log (and return early) on any error from a diagnostic request result instead of only returning early for server cancelled errors
* fix(lsp): use root_dir as cmd CWD #40331Barrett Ruth2026-06-26
| | | | | | | | | | | | Problem: cmd given as string[] always starts using Nvim's CWD, which is arbitrary. Solution: If cmd_cwd is not given, use root_dir as CWD. BREAKING CHANGE: LSP commands given as string arrays now use `root_dir` as the process working directory when `cmd_cwd` is unset. Co-authored-by: Justin M. Keyes <justinkz@gmail.com>
* fix(lsp): fire LspNotify didChange autocmds after undo/redo #40404jdrouhard2026-06-25
| | | | | | | | | | | Problem: LspNotify autocmds were not being triggered for didChange requests when being used during undo/redo (and possibly other) actions. autocmds are blocked when calling on_lines() callbacks while doing the undo/redo action. Solution: Defer firing the autocmd until after the action is complete. This is closer to what existed before, but now there's a check in the deferred function to only fire the autocmd if the client is still active and the buffer is still attached, if applicable.
* fix(lsp): make LspNotify more robust #40332jdrouhard2026-06-20
| | | | | | | | | | | | | | | | | | | | | | | | | | | Problem: LspNotify never passed a buffer when executing the autocmds, so buffer-local LspNotify autocmd subscriptions didn't have the correct buf in the event metadata. It was also wrapped in a schedule() so the actual autocmd was delayed until after the event loop. This could result in the wrong buffer receiving the notification if multiple LspNotify autocmds with buffer filters were added. Only the "latest" one would actually receive non-buffer-filtered autocmds, not the matching one. It also caused listeners to receive the notification "out of sync" with when the notification is actually sent. If a buffer is being deleted (which fires a textDocument/didClose notification), the notification is scheduled and fired after the buffer is already gone. Solution: For LSP notifications that pertain to a particular buffer, set it when executing the LspNotify autocmds so the callback functions that are filtered on that buffer will get the correct notifications and the metadata buf field will be correct. Additionally, there is no need to wrap the LspNotify callback in vim.schedule when it can be called inline when the notification to the rpc server is fired. This is tested by removing now-unnecessary autocmds from semantic tokens (InsertEnter and BufWinEnter should no longer be necessary now that requests are fired by LspNotify). Without this fix, simply modifying a buffer doesn't actually trigger LspNotify correctly, and the test for that fails.
* refactor(lsp): refactor linked_editing_range to use vim.lsp._capability (#40327)jdrouhard2026-06-19
| | | | | | | Problem: linked_editing_range was still doing most of the capability boilerplate itself. Solution: refactor it to make use of the common Capability framework for handling enabling, disabling, etc.
* build(docs): lint more quasi-keysets #39654Justin M. Keyes2026-05-07
| | | | | | | | | Problem: Linter missed backtick and double-quote keynames in the quasi-keyset of the `nvim_create_user_command` docstring. Solution: Update the linter to check backtick-surrounded and quote-surrounded key names.
* 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.
* 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): 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.
* docs: misc #39045Justin M. Keyes2026-04-18
|
* test: lint naming conventions #39117Justin M. Keyes2026-04-16
| | | | | | | | | | | | Problem: Naming conventions are not automatically checked. Solution: Add a check to the doc generator. Eventually we should extract this somehow, but that will require refactoring the doc generator... Note: this also checks non-public functions, basically anything that passes through `gen_eval_files.lua` and `gen_vimdoc.lua`. And that's a good thing.
* 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(api): rename buffer to buf #35330Jordan2026-04-08
| | | | | | | | | | | | 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>
* refactor(lsp): remove implicit rpc error tostring #38707Yi Ming2026-04-02
| | | | | | | | | | | | | | | | | | Problem: LSP error responses implicitly rely on a custom `__tostring` function (`vim.lsp.rpc.format_rpc_error`) for formatting. This causes errors that are not created via `vim.lsp.rpc.error` to behave inconsistently with those that are. Furthermore, we usually use `log.error` to print these errors, which uses `vim.inspect` under the hood, so the custom `__tostring` provides little benefit. This increases the difficulty of refactoring the code, as it tightly couples RPC error handling with the LSP. Solution: Convert every potential `__tostring` call to an explicit one. Since we don't describe this behavior in the documentation, this should not be a breaking change.
* docs: misc #38584Justin M. Keyes2026-04-01
|
* Merge #38560 refactor vim.lsp.rpcJustin M. Keyes2026-04-01
|\
| * refactor(lsp): merge `vim.lsp.rpc.Client` and `vim.lsp.rpc.PublicClient`Yi Ming2026-03-30
| |
* | docs: fix syntax errors in examples #38606skewb1k2026-03-30
|/
* feat(lua): replace `buffer` with `buf` in vim.keymap.set/del #38360skewb1k2026-03-21
| | | | | | The `buffer` option remains functional but is now undocumented. Providing both will raise an error. Since providing `buf` was disallowed before, there is no code that will break due to using `buffer` alongside `buf`.
* fix(lsp): handle providers without subcapabilitiestris2032026-03-19
| | | | | | | | | Previously, the LSP client assumed all providers had subcapabilities, which could cause issues when a provider did not. This change adds a check for the presence of subcapabilities before attempting to access them, ensuring correct handling of both cases. This improves compatibility with servers that register providers without additional capabilities.
* refactor(lsp): replace _provider_value_get with _provider_foreachtris2032026-03-19
| | | | | | | | Introduce _provider_foreach to iterate over all matching provider capabilities for a given LSP method, handling both static and dynamic registrations. Update diagnostic logic and tests to use the new iteration approach, simplifying capability access and improving consistency across features.
* feat(lsp): migrate `document_color` to capability framework (#38344)Maria Solano2026-03-18
| | | | | * feat(lsp): migrate `document_color` to capability framework * feat(lsp): use `vim.Range` in `document_color` module
* refactor: integer functions, optimize asserts #34112Lewis Russell2026-03-12
| | | | | | | | | | | | 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
* docs: api, messages, lsp, trustJustin M. Keyes2026-03-11
| | | | | gen_vimdoc.lua: In prepare for the upcoming release, comment-out the "Experimental" warning for prerelease features.
* refactor(lsp): centralize provider capability resolution #37221Tristan Knight2026-02-14
| | | | | | | | - 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.
* feat(lsp): support range + full semantic token requests #37611jdrouhard2026-02-03
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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
* fix(lsp): avoid scheduling client deletion before LspNotify #37685Yi Ming2026-02-03
| | | | | | | | | | | | Problem: `Client.on_exit` runs `Client._on_detach` and the client removal logic within two separate `vim.schedule` sequentially. However, since `Client._on_detach` executes `LspNotify` inside `vim.schedule`, this causes `LspNotify` to be executed after the client removal, which is scheduled first. At that point, a valid `Client` can no longer be retrieved within the autocmd callback. Solution: Put the client deletion inside the `vim.schedule` call.
* fix(types): add missing @return annotationsJosh Cooper2026-01-28
|
* feat(lsp): semantic token range improvements #37451jdrouhard2026-01-27
| | | | | | | | | | | | | | | | | | | | * 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
* docs: misc (#37281)zeertzjq2026-01-12
| | | | | | | Close #37289 Close #37348 Co-authored-by: Marc Jakobi <marc@jakobi.dev> Co-authored-by: Anton Kesy <anton@kesy.de>
* docs: misc (#37280)zeertzjq2026-01-07
| | | | | | | | | | | | | | | | | | | | Close #36806 Close #36812 Close #37003 Close #37016 Close #37038 Close #37039 Close #37157 Close #37185 Close #37213 Co-authored-by: saroj_r <sarojregmi.official@gmail.com> Co-authored-by: Olivia Kinnear <git@superatomic.dev> Co-authored-by: Igor <igorlfs@ufmg.br> Co-authored-by: Justin Roberts <JustinEdwardLeo@gmail.com> Co-authored-by: "Mike J. McGuirk" <mike.j.mcguirk@gmail.com> Co-authored-by: Aymen Hafeez <49293546+aymenhafeez@users.noreply.github.com> Co-authored-by: Peter Cardenas <16930781+PeterCardenas@users.noreply.github.com> Co-authored-by: DrNayak2306 <dhruvgnk.work@gmail.com>
* fix(lsp): `:lsp restart` restarts on client exit #37125Olivia Kinnear2026-01-02
| | | | | | | | | | | | | | Problem: `:lsp restart` detects when a client has exited by using the `LspDetach` autocommand. This works correctly in common cases, but breaks when restarting a client which is not attached to any buffer. It also breaks if a client is detached in between `:lsp restart` and the actual stopping of the client. Solution: Move restart logic into `vim/lsp/client.lua`, so it can hook in to `_on_exit()`. The public `on_exit` callback cannot be used for this, as `:lsp restart` needs to ensure the restart only happens once, even if the command is run multiple times on the same client.
* fix(lsp): improve dynamic registration handling #37161Tristan Knight2026-01-02
| | | | | | | | Work on #37166 - Dynamic Registration Tracking via Provider - Supports_Method - Multiple Registrations - RegistrationOptions may dictate support for a method
* fix(lsp): correct capability checks for dynamic registration (#36932)Tristan Knight2025-12-15
| | | | | | Refactor capability checks in Client:_supports_registration and Client:supports_method to properly handle dynamicRegistration and unknown methods. Now, dynamic capabilities are checked before assuming support for unknown methods, ensuring more accurate LSP feature detection.
* docs: miscJustin M. Keyes2025-12-06
| | | | | | fix https://github.com/neovim/neovim.github.io/issues/419 Co-authored-by: Rob Pilling <robpilling@