aboutsummaryrefslogtreecommitdiff
path: root/runtime/lua/vim/lsp
Commit message (Collapse)AuthorAge
* fix(lsp): ignore completion items without LSP metadata #42401Volodymyr Chernetskyi3 days
| | | | | | | | | | | | 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
* fix(lsp): keep label fallback for empty snippet insertText #42402Volodymyr Chernetskyi3 days
| | | | | | | | | | | | 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
* fix(lsp): preserve explicit completion edit ranges #42399Volodymyr Chernetskyi3 days
| | | | | | | | | | | | 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
* fix(lsp): prefer textEdit for snippet completion text #42400Volodymyr Chernetskyi4 days
| | | | | | | | | | | | 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
* fix(health): handle percent signs in LSP reports #42396Volodymyr Chernetskyi4 days
| | | | | | | | | | | Problem: Active-feature report text is passed to string.format() without arguments. Percent signs in buffer or client names can raise an error or change the displayed text. Solution: Report the concatenated text without formatting it again. AI-assisted
* feat(lsp): support client_id in vim.lsp.completion.get() #42189glepnir2026-10-03
| | | | | | | | | 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.
* ci(lua): enable annotation and style checksLewis Russell2026-09-30
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Problem: - annotation-usage-error and code-style-check are disabled. - vim.inspect relies on a dummy self-assignment for docgen, and its help omits parameter and option details. - LuaLS fallback types obscure iterator inference. - Docgen hardcodes public function names and appends separately sorted files, leaving shared helpers under the inspector heading. Solution: - Enable annotation-usage-error and code-style-check, and fix misplaced annotations. - Document vim.inspect's callable module directly, removing the dummy assignment. Describe its parameters, option defaults and process callback. - Remove LuaLS iterator fallbacks, correct iterator signatures and check values that the improved inference identifies as optional. - Parse callable modules, require bindings and parent module references. Derive public names and inherited function docs from these links, including missing help for vim.async.semaphore() and vim.version(). - Export vim.lsp.tagfunc directly with lazy loading and document its implementation instead of maintaining a wrapper. - Group files in section_order, replacing append_only and merge_files. Merge declarations before sorting each section, placing shared helpers in the main vim section and keeping vim.inspect in alphabetical order. - Add basic parser coverage for callable modules and module links. AI-assisted
* Merge pull request #42134 from lewis6991/emmyluaLewis Russell2026-09-30
|\ | | | | fix(lua): enable param-type-mismatch diagnostic
| * 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(lsp): preserve completion state on buffer reload #42135Barrett Ruth2026-09-29
|/ | | | | | | | | | | 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.
* fix(lua): enable unnecessary-assert diagnosticLewis Russell2026-09-28
| | | | AI-assisted
* fix(lsp): preserve tag types to stabilize emmylua checks #42117Volodymyr Chernetskyi2026-09-27
| | | | | | | | | | | | | | | | Problem: EmmyLua widens singleton completion and symbol tags to integer during generic inference. Nested field checking can skip the resulting type mismatch depending on member iteration order, making lint flaky. Solution: Annotate both tag tables with their protocol types so get_value_set() preserves the singleton tag types without changing runtime behavior or disabling diagnostics. Validated with 1,000 consecutive full-runtime checks using EmmyLua 0.25.1 on macOS arm64. AI-assisted
* perf(lsp): read options once per completion response #42106glepnir2026-09-27
| | | | | | | | Problem: Converting completion items reads 'completeopt' through vim.opt, 'ignorecase' and 'smartcase' for every item. Solution: Read them once per response.
* 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(lsp): silently ignore unknown folding range kinds (#41964)Maria Solano2026-09-18
|
* fix(lua): add missing param annotations (#41911)Lewis Russell2026-09-15
|
* fix(lsp): snippet is not expanded when resolve races the user #41774glepnir2026-09-11
| | | | | | | | | | | 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'.
* feat(lsp): support timeout_ms for async formatting #41850Barrett Ruth2026-09-11
| | | | | | | | | Problem: `vim.lsp.buf.format()` does not support a timeout for asynchronous requests. Solution: Honor an explicit timeouts per client so formatting can continue. Do not permit a default value for async format requests.
* 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
* feat(lsp): support `workspace/foldingRange/refresh` #41780Volodymyr Chernetskyi2026-09-09
| | | | | | | | | | | Problem: Servers cannot request refreshing stale LSP folding ranges after a project-wide change. Solution: Advertise `workspace.foldingRange.refreshSupport` and re-request folding ranges for active buffers when handling `workspace/foldingRange/refresh`. AI-assisted
* fix(lsp): newlines in the completion word from insertText #41801glepnir2026-09-09
| | | | | | | | 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.
* feat(watch): add on_error callbackLewis Russell2026-09-09
| | | | | | | | | | | | | | Problem: Watcher failures are reported inconsistently, and callers cannot detect when a watcher is no longer usable. Solution: Route startup and event failures and unexpected inotifywait exits through an optional on_error callback. Log to nvim-watch.log by default. Ignore disappearing child directories and exits caused by cancellation. Let LSP log failures and notify once per message, using INFO for missing roots and ERROR otherwise, without interrupting registration. 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
* fix(lsp): completion dynamicRegistration breaks capability readers #41771glepnir2026-09-08
| | | | | | | | | | 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.
* fix(lsp): announce typeHierarchy and executeCommand capabilities #41762Volodymyr Chernetskyi2026-09-07
| | | | | | | | | | | Problem: Type hierarchy (#28388, #28467) and `workspace/executeCommand` (#11607) are implemented, but `textDocument.typeHierarchy` and `workspace.executeCommand` are missing from `make_client_capabilities()`. Solution: Declare both capabilities. AI-assisted
* fix(lsp): semantic tokens ignore 'fileformat' when sizing line endings #41733Volodymyr Chernetskyi2026-09-07
| | | | | | | | | | | | | | | | | | | | Problem: The eol_offset used to decode multiline semantic tokens is computed as vim.bo.fileformat[bufnr] == 'dos' and 2 or 1 which indexes the option value rather than the buffer, so it is never "dos" and the offset is always 1. A token that crosses a line boundary in a 'fileformat' of "dos" is then decoded one code unit short per line ending, and the highlight extends past the end of the token. Solution: Read the option with the buffer-scoped form, vim.bo[bufnr].fileformat. The existing multiline test covers both formats now. Its token length of 82 counts the line endings it spans, so the same token reaches four characters less far once the buffer is "dos". AI-assisted
* fix(lsp): show_document() reports a failed buffer load #41731Volodymyr Chernetskyi2026-09-07
| | | | | | | | | | | | | | Problem: vim.lsp.util.show_document() can fail to load the target buffer, most visibly with E325 when another process owns the file's swapfile and the user declines to open it. The Vim error escapes show_document() and surfaces inside whichever LSP handler called it, instead of being reported as a failure to show the document. Solution: Load the buffer up front with vim.fn.bufload(), before any of that state is touched, and report the error instead of raising. 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
* feat(lsp): support dynamic registration of completionProvider #41748glepnir2026-09-07
| | | | | | | | Problem: dynamicRegistration is declared false, and completionProvider is read from server_capabilities only. Solution: Declare it, and prefer registerOptions per field.
* fix(lsp): respect range in linewise visual mode #41636Volodymyr Chernetskyi2026-09-02
| | | | | | | | Problem: An explicitly passed `range` to `vim.lsp.buf.format()` in linewise visual mode is silently replaced by the selection. Solution: Parenthesise the mode check.
* fix(lsp): separate adjacent nested folding ranges #41428wrvsrx2026-08-31
| | | | | | | | | Problem: Folding range markers are overwritten while ranges are evaluated. A range ending on a row can hide another range starting there, and multiple nested ranges ending together emit only the innermost ending level. Solution: Track starts and the number of ends per row before emitting markers. Prefer starts on shared boundary rows and use the outermost level when nested ranges end together. AI-assisted
* fix(lsp): blank line before Content-Length breaks header parsing #41524Yanze Li2026-08-29
| | | | | | | | | | | | | | Problem: A blank line before the Content-Length header makes header parsing fail with "Content-Length not found in header". An LF in the 'name' state falls through to the 'invalid' state, which only return to 'name' at the *next* LF. That LF terminates the next line, so the line with Content-Length is swallowed. The same issue happens when a junk line is a partial match of the header name (e.g. "Cont\nContent-Length: ..."). Solution: When seeing an LF in the 'name' state, reset the cursor and stay in 'name' rather than entering 'invalid'.
* revert: "fix(lsp): do not expand $VAR in tagfunc filenames" #41489Justin M. Keyes2026-08-25
| | | revert c5cb0350a6dc578e6ca73eefdd58159e1e039cbf
* 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.
* fix(lsp): completion overwrites text before the word boundary #41463glepnir2026-08-24
| | | | | | | | | 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.
* docs: misc #41452Justin M. Keyes2026-08-23
| | | | | Co-authored-by: darkdi <rantovov5@gmail.com> Co-authored-by: Qiaoxi Guo <28090444+breadtitor@users.noreply.github.com> Co-authored-by: zaveshaa <zaveshaa@gmail.com>
* fix(lsp): do not expand $VAR in tagfunc filenames #41398Shubh2026-08-23
| | | | | | | | Problem: CTRL-] via lsp tagfunc passes URI paths through :tag, which expands \$VAR, so files like people_.\$personId.tsx fail with E429. Solution: fnameescape() the filename in tag items so \$ is treated as literal.
* fix(lsp): empty filterText/sortText/insertText not treated as unset #41421glepnir2026-08-22
| | | | | | | | | 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.
* feat(extmark): virt_lines can highlight until EOL #41289Goldpigg2026-08-18
|
* feat(fs): vim.fs.normalize{plain:boolean} #41127Olivia Kinnear2026-08-05
| | | | | | `opts.plain=true` does not expand tildes in addition to environment variables, unlike `opts.expand_env=false`. `opts.expand_env=false` is soft-deprecated.
* 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)
* fix(lsp): only send `didSave` to clients attached to the buffer (#41126)Maria Solano2026-08-03
|
* refactor: combine all visual_selection funcionsaltermo2026-08-01
|
* 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): multibyte fragment treated as commit char #41019glepnir2026-07-28
| | | | | | | | | | 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.
* feat(health): improvements to :checkhealth #40935Olivia Kinnear2026-07-24
| | | | | | | Changes: - Removed the blank line before the first healthcheck header. - Fixed a bug where the entire "Terminal" section of `vim.health` would not appear if the `infocmp` executable was not found. - Fixed a typo in `vim.lsp` when displaying the LSP log level.
* fix(lsp): guard linked_editing_range refresh on attach (#40888)Artem Krinitsyn2026-07-21
| | | | | | | | | | Problem: on_attach() calls refresh(), but there is no guarantee the attached buffer is the current buffer. This can make linked editing request handling assume the wrong window. Solution: Call refresh() only if the current buffer is attached. This keeps the initial highlighting behavior while avoiding making incorrect request.