summaryrefslogtreecommitdiffstatshomepage
path: root/test/functional/plugin/lsp_spec.lua
AgeCommit message (Collapse)AuthorFiles
2026-04-24fix(lsp): handle self-mapped methods in supports_method #39383nightlyTristan Knight1
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.
2026-04-24fix(lsp): more info in error msg, deduplicate test #39359Justin M. Keyes1
2026-04-23fix(lsp): handle null id in JSON-RPC responses #38340atusy1
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.
2026-04-17test(lsp): extract buf/util parts from lsp_spec.lua #39149Yi Ming1
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.
2026-04-15refactor: update usages of deprecated "buffer" param #39089Justin M. Keyes1
2026-04-12fix(lsp): show_document can't position cursor past EOL in insert-mode #38566Lars Debor1
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.
2026-04-12fix(lsp): send didOpen on save to all clients+groups #37454Emilv21
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.
2026-04-08fix(lsp): apply_text_edits causes unwanted BufDelete events #38778glepnir1
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.
2026-03-30feat(lsp): respect 'switchbuf' for jump commands, drop `reuse_win` #38510Yi Ming1
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.
2026-03-29test: fix s390x failuresJustin M. Keyes1
Problem: failures in s390x CI. Solution: - runtime/lua/man.lua: parse_path() can return nil but 3 callers didn't handle it. - skip some tests on s390x. TODO: - TODO: why "build/bin/xxd is not executable" on s390x? - TODO: other failures, not addressed (see below). OTHER FAILURES: FAILED test/functional/treesitter/fold_spec.lua @ 87: treesitter foldexpr recomputes fold levels after lines are added/removed test/functional/treesitter/fold_spec.lua:95: Expected objects to be the same. Passed in: (table: 0x4013c18940) { [1] = '0' [2] = '0' [3] = '0' *[4] = '0' [5] = '0' ... Expected: (table: 0x4005acf900) { [1] = '0' [2] = '0' [3] = '>1' *[4] = '1' [5] = '1' ... stack traceback: (tail call): ? test/functional/treesitter/fold_spec.lua:95: in function <test/functional/treesitter/fold_spec.lua:87> FAILED test/functional/treesitter/select_spec.lua @ 52: treesitter incremental-selection works test/functional/treesitter/select_spec.lua:63: Expected objects to be the same. Passed in: (string) 'bar(2)' Expected: (string) 'foo(1)' stack traceback: (tail call): ? test/functional/treesitter/select_spec.lua:63: in function <test/functional/treesitter/select_spec.lua:52> FAILED test/functional/treesitter/select_spec.lua @ 69: treesitter incremental-selection repeat test/functional/treesitter/select_spec.lua:82: Expected objects to be the same. Passed in: (string) '2' Expected: (string) '4' stack traceback: (tail call): ? test/functional/treesitter/select_spec.lua:82: in function <test/functional/treesitter/select_spec.lua:69> FAILED test/functional/treesitter/select_spec.lua @ 98: treesitter incremental-selection history test/functional/treesitter/select_spec.lua:111: Expected objects to be the same. Passed in: (string) 'bar(2)' Expected: (string) 'foo(1)' stack traceback: (tail call): ? test/functional/treesitter/select_spec.lua:111: in function <test/functional/treesitter/select_spec.lua:98> FAILED test/functional/treesitter/select_spec.lua @ 186: treesitter incremental-selection with injections works test/functional/treesitter/select_spec.lua:201: Expected objects to be the same. Passed in: (string) 'lua' Expected: (string) 'foo' stack traceback: (tail call): ? test/functional/treesitter/select_spec.lua:201: in function <test/functional/treesitter/select_spec.lua:186> FAILED test/functional/treesitter/select_spec.lua @ 216: treesitter incremental-selection with injections ignores overlapping nodes test/functional/treesitter/select_spec.lua:231: Expected objects to be the same. Passed in: (string) ' )' Expected: (string) ' foo(' stack traceback: (tail call): ? test/functional/treesitter/select_spec.lua:231: in function <test/functional/treesitter/select_spec.lua:216> FAILED test/functional/treesitter/select_spec.lua @ 307: treesitter incremental-selection with injections handles disjointed trees test/functional/treesitter/select_spec.lua:337: Expected objects to be the same. Passed in: (string) 'int' Expected: (string) '1}' stack traceback: (tail call): ? test/functional/treesitter/select_spec.lua:337: in function <test/functional/treesitter/select_spec.lua:307> ERROR test/functional/treesitter/parser_spec.lua @ 562: treesitter parser API can run async parses with string parsers test/functional/treesitter/parser_spec.lua:565: attempt to index a nil value stack traceback: test/functional/testnvim/exec_lua.lua:124: in function <test/functional/testnvim/exec_lua.lua:105> (tail call): ? (tail call): ? test/functional/treesitter/parser_spec.lua:563: in function <test/functional/treesitter/parser_spec.lua:562> FAILED test/functional/core/job_spec.lua @ 1157: jobs jobstop() kills entire process tree #6530 test/functional/core/job_spec.lua:1244: retry() attempts: 94 test/functional/core/job_spec.lua:1246: Expected objects to be the same. Passed in: (table: 0x401dd74b30) { [name] = 'sleep <defunct>' [pid] = 33579 [ppid] = 1 } Expected: (userdata) 'vim.NIL' stack traceback: test/testutil.lua:89: in function 'retry' test/functional/core/job_spec.lua:1244: in function <test/functional/core/job_spec.lua:1157>
2026-03-24test(lsp): get_configs resolves only necessary configsJustin M. Keyes1
2026-03-22revert: "feat(lsp): add `buftypes` field to `vim.lsp.Config`" #38421Maria Solano1
revert: "feat(lsp): add `buftypes` field to `vim.lsp.Config` (#38380)" This reverts commit cfcdbcf638b5957213b3c1a55d5d1b5659a2fb3e.
2026-03-21feat(lsp): add `buftypes` field to `vim.lsp.Config` (#38380)Barrett Ruth1
Problem: `vim.lsp.enable()` skips buffers with `buftype` set, even when `filetype` matches. Solution: Add `buftypes` field to `vim.lsp.Config`.
2026-03-19refactor(lsp): replace _provider_value_get with _provider_foreachtris2031
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.
2026-03-19feat(lsp): vim.lsp.get_configs() #37237Olivia Kinnear1
Problem: No way to iterate configs. Users need to reach for `vim.lsp.config._configs`, an internal interface. Solution: Provide vim.lsp.get_configs(). Also indirectly improves :lsp enable/disable completion by discarding invalid configs from completion.
2026-03-12docs: use "ev" convention in event-handlersJustin M. Keyes1
Problem: In autocmd examples, using "args" as the event-object name is vague and may be confused with a user-command. Solution: Use "ev" as the conventional event-object name.
2026-02-19test(lsp): fix fake LSP server timeout not working (#37970)zeertzjq1
Problem: Fake LSP server does not timeout or respond to SIGTERM as it does not run the event loop. Solution: Instead of io.read(), use stdioopen()'s on_stdin callback to accumulate input and use vim.wait() to wait for input. Also, in the test suite, don't stop a session when it's not running, as calling uv.stop() outside uv.run() will instead cause the next uv.run() to stop immediately, which cancels the next RPC request.
2026-02-16fix(lsp): map all LSP methods to server capabilities (#37910)Tristan Knight1
2026-02-15fix(lsp): support workspace/configuation with no section #27510Tim Pope1
The [spec for `workspace/configuration`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#workspace_configuration) marks the `section` property of each item in `items` optional. Therefore, I believe it violates the spec to skip over items without a section, because then the length of the results won't match the length of a valid `items` input. The spec does not elaborate on _what_ to return in this case, but I don't think it would be controversial to say that returning the full configuration, as done for an empty string, is the most natural interpretation. That empty string case, by the way, was initially [added in response](https://github.com/neovim/nvim-lspconfig/commit/5da124fc82c24592abc3a97c68363bb4e85e3c85) to a real world implementation requesting it. I don't have a similar real world implementation to point to for the omitted `section`, but I would note that `getConfiguration()` from `vscode-languageserver-node` [defaults to a request with no section](https://github.com/Microsoft/vscode-languageserver-node/blob/d859bb14d1bcb3923eecaf0ef587e55c48502ccc/server/src/common/configuration.ts#L24-L26) when called with no arguments. I surmise that this is intended as a way to retrieve the full configuration.
2026-02-14refactor(lsp): centralize provider capability resolution #37221Tristan Knight1
- 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.
2026-02-03feat(lsp)!: reimplement `textDocument/codeLens` as decoration providerYi Ming1
2026-01-27fix: lsp.enable() don't work correctly inside FileType event #37538phanium1
Problem: Two cases lsp.enable() won't work in the first FileType event 1. lsp.enable luals inside FileType or ftplugin/lua.lua, then: ``` nvim a.lua ``` 2. lsp.enable luals inside FileType or ftplugin/lua.lua, then: ``` nvim -> :edit a.lua -> :mksession! | restart +qa! so Session.vim ``` Solution: Currently `v:vim_did_enter` is used to detected two cases: 1. "maunally enabled" (lsp.enable() or `:lsp enable`) 2. "inside FileType event" To detect 2. correctly we use did_filetype().
2026-01-27feat(lsp): semantic token range improvements #37451jdrouhard1
* 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
2026-01-12docs: misc (#37281)zeertzjq1
Close #37289 Close #37348 Co-authored-by: Marc Jakobi <marc@jakobi.dev> Co-authored-by: Anton Kesy <anton@kesy.de>
2026-01-11perf(lsp): avoid textDocument/definition requests during tag completion (#37260)Robert Muir1
Problem: vim.lsp.tagfunc looks for the presence of 'c' (cursor) flag and issues sync textDocument/definition requests to all clients, otherwise workspace/symbol requests. But 'c' flag can also be set during the insert mode completion, e.g. with an empty tag completion query, the tag func receives pattern of '\<\k\k' with flags 'cir'. Solution: check for 'i' (insert mode completion) flag and don't issue any LSP requests, return vim.NIL for immediate fallback to tags.
2026-01-02fix(lsp): improve dynamic registration handling #37161Tristan Knight1
Work on #37166 - Dynamic Registration Tracking via Provider - Supports_Method - Multiple Registrations - RegistrationOptions may dictate support for a method
2025-12-15fix(lsp): correct capability checks for dynamic registration (#36932)Tristan Knight1
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.
2025-11-16feat(lsp): skip invalid header lines #36402tao1
Problem: Some servers write log to stdout and there's no way to avoid it. See https://github.com/neovim/neovim/pull/35743#pullrequestreview-3379705828 Solution: We can extract `content-length` field byte by byte and skip invalid lines via a simple state machine (name/colon/value/invalid), with minimal performance impact. I chose byte parsing here instead of pattern. Although it's a bit more complex, it provides more stable performance and allows for more accurate error info when needed. Here is a bench result and script: parse header1 by pattern: 59.52377ms 45 parse header1 by byte: 7.531128ms 45 parse header2 by pattern: 26.06936ms 45 parse header2 by byte: 5.235724ms 45 parse header3 by pattern: 9.348495ms 45 parse header3 by byte: 3.452389ms 45 parse header4 by pattern: 9.73156ms 45 parse header4 by byte: 3.638386ms 45 Script: ```lua local strbuffer = require('string.buffer') --- @param header string local function get_content_length(header) for line in header:gmatch('(.-)\r?\n') do if line == '' then break end local key, value = line:match('^%s*(%S+)%s*:%s*(%d+)%s*$') if key and key:lower() == 'content-length' then return assert(tonumber(value)) end end error('Content-Length not found in header: ' .. header) end --- @param header string local function get_content_length_by_byte(header) local state = 'name' local i, len = 1, #header local j, name = 1, 'content-length' local buf = strbuffer.new() local digit = true while i <= len do local c = header:byte(i) if state == 'name' then if c >= 65 and c <= 90 then -- lower case c = c + 32 end if (c == 32 or c == 9) and j == 1 then -- skip OWS for compatibility only elseif c == name:byte(j) then j = j + 1 elseif c == 58 and j == 15 then state = 'colon' else state = 'invalid' end elseif state == 'colon' then if c ~= 32 and c ~= 9 then -- skip OWS normally state = 'value' i = i - 1 end elseif state == 'value' then if c == 13 and header:byte(i + 1) == 10 then -- must end with \r\n local value = buf:get() return assert(digit and tonumber(value), 'value of Content-Length is not number: ' .. value) else buf:put(string.char(c)) end if c < 48 and c ~= 32 and c ~= 9 or c > 57 then digit = false end elseif state == 'invalid' then if c == 10 then -- reset for next line state, j = 'name', 1 end end i = i + 1 end error('Content-Length not found in header: ' .. header) end --- @param fn fun(header: string): number local function bench(label, header, fn, count) local start = vim.uv.hrtime() local value --- @type number for _ = 1, count do value = fn(header) end local elapsed = (vim.uv.hrtime() - start) / 1e6 print(label .. ':', elapsed .. 'ms', value) end -- header starting with log lines local header1 = 'WARN: no common words file defined for Khmer - this language might not be correctly auto-detected\nWARN: no common words file defined for Japanese - this language might not be correctly auto-detected\nContent-Length: 45 \r\n\r\n' -- header starting with content-type local header2 = 'Content-Type: application/json-rpc; charset=utf-8\r\nContent-Length: 45 \r\n' -- regular header local header3 = ' Content-Length: 45\r\n' -- regular header ending with content-type local header4 = ' Content-Length: 45 \r\nContent-Type: application/json-rpc; charset=utf-8\r\n' local count = 10000 collectgarbage('collect') bench('parse header1 by pattern', header1, get_content_length, count) collectgarbage('collect') bench('parse header1 by byte', header1, get_content_length_by_byte, count) collectgarbage('collect') bench('parse header2 by pattern', header2, get_content_length, count) collectgarbage('collect') bench('parse header2 by byte', header2, get_content_length_by_byte, count) collectgarbage('collect') bench('parse header3 by pattern', header3, get_content_length, count) collectgarbage('collect') bench('parse header3 by byte', header3, get_content_length_by_byte, count) collectgarbage('collect') bench('parse header4 by pattern', header4, get_content_length, count) collectgarbage('collect') bench('parse header4 by byte', header4, get_content_length_by_byte, count) ``` Also, I removed an outdated test https://github.com/neovim/neovim/blob/accd392f4d14a114e378f84dc15cb24bc34a370a/test/functional/plugin/lsp_spec.lua#L1950 and tweaked the boilerplate in two other tests for reusability while keeping the final assertions the same. https://github.com/neovim/neovim/blob/accd392f4d14a114e378f84dc15cb24bc34a370a/test/functional/plugin/lsp_spec.lua#L5704 https://github.com/neovim/neovim/blob/accd392f4d14a114e378f84dc15cb24bc34a370a/test/functional/plugin/lsp_spec.lua#L5721
2025-11-12fix(lsp): reuse_win prioritizes windows/tabs currently displayed #36486Toby She1
Problem: reuse_win will always jump to the first window containing the target buffer rather even if the buffer is displayed in the current window/tab Solution: check to see if the buffer is already displayed in the current window or any window of the current buffer
2025-11-10feat(lsp): deprecate `vim.lsp.stop_client` (#36459)Olivia Kinnear1
* feat(lsp): deprecate `vim.lsp.stop_client` * fix(tests): fix nil variable in diagnostic_spec.lua
2025-10-27fix(lsp): stop repeatedly resuming dead coroutine #35743tao1
Problem: Error extracting content-length causes all future coroutine resumes to fail. Solution: Replace coroutine.wrap with coroutine.create in create_read_loop so that we can check its status and catch any errors, allowing us to stop the lsp client and avoid repeatedly resuming the dead coroutine.
2025-10-14revert "fix(lsp): _get_workspace_folders does not handle root_dir() ↵Mathias Fußenegger1
function" #36183 This reverts commit 97ab24b9c7d9327740f0692f8076fed5737a52dc. See discussion in https://github.com/neovim/neovim/pull/36071
2025-10-15fix(lsp): "attempt to index nil config" #36189Justin M. Keyes1
Problem: If a client doesn't have a config then an error may be thrown. Probably caused by: 2f78ff816b03661b5f74d0624e973eaca0d64ef1 Lua callback: …/lsp.lua:442: attempt to index local 'config' (a nil value) stack traceback: …/lsp.lua:442: in function 'can_start' …/lsp.lua:479: in function 'lsp_enable_callback' …/lsp.lua:566: in function <…/lsp.lua:565> Solution: Not all clients necessarily have configs. - Handle `config=nil` in `can_start`. - If user "enables" an invalid name that happens to match a *client* name, don't auto-detach the client.
2025-10-11fix(lsp): _get_workspace_folders does not handle root_dir() function #36071atusy1
* fix(lsp): type of root_dir should be annotated with string|fun|nil * feat(lsp): support root_dir as function in _get_workspace_folders * feat(lsp): let checkhealth support root_dir() function Examples: vim.lsp: Active Clients ~ - lua_ls (id: 1) - Version: <Unknown> - Root directories: ~/foo/bar ~/dev/neovim Co-authored-by: Justin M. Keyes <justinkz@gmail.com>
2025-09-17test(lsp): make async format test work properly (#35794)zeertzjq1
Overriding vim.lsp.handlers['textDocument/formatting'] doesn't work here because fake_lsp_server_setup() uses a table with __index to specify client handlers, which takes priority over vim.lsp.handlers[], and as a result the overridden handler is never called, and the test ends before the vim.wait() even finishes. Instead, set a global variable from the handler that is actually reached (by vim.rpcrequest() from client handler), and avoid stopping the event loop too early.
2025-09-13fix(lsp): misleading logs in non-applicable filetypes #35749Justin M. Keyes1
Problem: LSP logs show misleading "cannot start" messages when editing a filetype NOT listed in the `config.filetypes` field. [ERROR][2025-09-13 18:55:56] …/runtime//lua/vim/lsp/log.lua:151 "cannot start cssls due to config error: …/runtime//lua/vim/lsp.lua:423: cmd: expected expected function or table with executable command, got table: 0x0104701b18. Info: vscode-css-language-server is not executable" Solution: - `can_start`: check `config.filetypes` before checking the rest of the config.
2025-08-27fix(lsp): don't treat MarkedString[] with language id as empty #35518Robert Muir1
Problem: Hover response of MarkedString[] where the first element contains a language identifier treated as empty. Solution: Fix empty check to handle case of MarkedString[] where the first element is a pair of a language and value.
2025-08-17refactor(tests): remove redundant test #35364Justin M. Keyes1
2025-08-17fix(api,lsp): call on_detach before wiping out the buffer #35355Jaehwang Jung1
Problem: Buffer-updates on_detach callback is invoked before buf_freeall(), which deletes autocmds of the buffer (via apply_autocmds(EVENT_BUFWIPEOUT, ...)). Due to this, buffer-local autocmds executed in on_detach (e.g., LspDetach) are not actually invoked. Solution: Call buf_updates_unload() before buf_freeall().
2025-08-06feat(lsp): improve signature help display #35190skewb1k1
- Add delimiter between function signature and documentation, matching hover formatting - Show title only if there are multiple clients or multiple signatures - Avoid duplicating the title inside the window if it's already shown in the border
2025-08-03fix(lsp): decode 'null' in server responses as vim.NIL #34849skewb1k1
Problem: Previously, 'null' value in LSP responses were decoded as 'nil'. This caused ambiguity for fields typed as '? | null' and led to loss of explicit 'null' values, particularly in 'data' parameters. Solution: Decode all JSON 'null' values as 'vim.NIL' and adjust handling where needed. This better aligns with the LSP specification, where 'null' and absent fields are distinct, and 'null' should not be used to represent missing values. This also enables proper validation of response messages to ensure that exactly one of 'result' or 'error' is present, as required by the JSON-RPC specification.
2025-07-22fix(lsp): support `containerName` in symbol requests #35029Riley Bruins1
The field is present for SymbolInformation and WorkspaceSymbol.
2025-07-20fix(lsp): show notification with empty hover response (#35014)Maria José Solano1
2025-07-06feat(lsp): handle deprecated document symbols (#34751)Maria José Solano1
2025-06-23feat(lsp): support annotated text edits (#34508)Maria José Solano1
2025-06-18feat(lsp): pass resolved config to cmd() #34550Julian Visser1
Problem: In LSP configs, the function form of `cmd()` cannot easily get the resolved root dir (workspace). One of the main use-cases of a dynamic `cmd()` is to be able to start a new server whose binary may be located *in the workspace* ([example](https://github.com/neovim/nvim-lspconfig/pull/3912)). Compare `reuse_client()`, which also receives the resolved config. Solution: Pass the resolved config to `cmd()`. Co-authored-by: Justin M. Keyes <justinkz@gmail.com>
2025-06-16feat(lsp): handle disabled code actions (#34453)Riley Bruins1
This commit also makes it so that disabled code actions are not displayed unless the trigger kind is "Invoked".
2025-06-09feat(lsp): workspace diagnostic support (#34262)Maria José Solano1
* refactor(lsp): remove underscore prefix from local variables * feat(lsp): workspace diagnostic support
2025-06-09feat(lsp): static registration support (#34371)Maria José Solano1
2025-06-01docs: news, intro, lsp, api #33687Justin M. Keyes1