aboutsummaryrefslogtreecommitdiff
path: root/test/functional/plugin/lsp/semantic_tokens_spec.lua
Commit message (Collapse)AuthorAge
* test: simplify functional test expectationsLewis Russell2026-10-05
| | | | | | | | | | | | Problem: Repeated default fields and field-by-field assertions obscure the values that each functional test is meant to check. Solution: Add eq_partial() to check selected record fields while preserving list length and order. Use local helpers to fill fixed expected defaults where tests need full equality. Keep explicit absence checks and test-specific values at the call sites. 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
* feat(lsp): fallback to textDocument/formatting from vim.lsp.formatexpr #40079Marcus Caisey2026-08-18
| | | | | | | | | | | | | | | | Problem: With the addition of the `:help al` text object, you can now easily format the whole buffer with `gqal`. However, `vim.lsp.formatexpr` only uses `textDocument/rangeFormatting` which some language servers (like gopls) don't support. Solution: - Fall back to `textDocument/formatting` if the whole buffer is being formatted and the server doesn't support `textDocument/rangeFormatting`. - In theory, these two methods should return the same response if the whole buffer is being formatted, but I preserved the existing behaviour of prioritising `textDocument/rangeFormatting` in case that does not hold (i.e. LS bug). - Also: `vim.lsp.formatexpr` had no tests at all, so actually add tests for it.
* test(harness): migrate away from magic globalsJustin M. Keyes2026-07-21
| | | | | | | | | | | | | | | | | | | | | Problem: The magic globals `it`, `describe`, etc., are more trouble than they are worth. - Hooking into `after_each` requires `getfenv()` hacks. - They confuse luals/emmylua, because the top-level `.luarc.json` isn't merged with `test/.luarc.json` (apparently a luals limitation?) - They totally defeat discoverability because the user just has to "know" about the various magic symbols. So they harm DX, which means they serve no purpose at all. Solution: - Expose the test API from `testutil`, so tests can call `t.it()`, `t.describe()`, etc., in the conventional way. - Drop `getfenv()` hacks. - Drop the `setfenv()` injection in `load_chunk`. - Drop `test/_meta.lua`.
* 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.
* fix(lsp): multiline semantic token processing #40339jdrouhard2026-06-20
| | | | | | | | | | | | | Problem: When multiline semantic token support was introduced, the loop that finds the end line for a particular token didn't sanitize the token length sent back by the LSP server. If the server returned an overflowed length (near uint32 max), neovim would burn cpu and loop for an extremely long time while trying to find the "end line" represented by the massively large token, causing neovim to seemingly hang. Solution: Stop looping once the calculated end_line reaches the actual last line of the buffer. Fixes #36257
* feat(lsp): clean up semantic token initialization and debounce #40254jdrouhard2026-06-15
| | | | | | | | | | | | | | | | Problem: The refactor to use Capability left around some cruft and semi-broken configuration for debounce. Solution: Clean up now-unnecessary helper methods and simplify deprecated ones to pass through to the non-deprecated ones. `debounce` now defaults to 200 for all buffers but is overridable via the deprecated start() method, which continues to take the max value specified for any client attached to the buffer. If we wish to expose changing the debounce in a non-deprecated way, we will need to consider a "configuration" function, or even a bespoke method to set the debounce time on the main metaclass (or provide options to override for a particular buffer). General configuration of specific LSP features is an as-of-yet unsolved problem.
* feat(lsp): use LspNotify for semantic tokens #40224jdrouhard2026-06-14
| | | | | | | | | | | | | | | | | Problem: The semantic token module is using its own debounce timer for the buffer on_lines event. If its internal debounce is shorter than the changetracking module's debounce, it's possible for semantic token requests to fire for changed buffers before the textDocument/didChange notification is sent to the server. Solution: Trigger semantic token requests from the LspNotify autocmd when the method is the didChange or didOpen notifications, which enforces a strict happens-before relationship for the sync change notification followed by a semantic token request. Note: There is still an internal debounce mechanism in the semantic token module to handle other debouncing needs specific to its functionality, such as debouncing server refresh notifications and handling WinScrolled events when using range requests.
* docs: use "ev" convention in event-handlersJustin M. Keyes2026-03-12
| | | | | | | | | 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.
* test(lsp): flaky lsp/semantic_tokens_spec #38063zeertzjq2026-02-25
| | | | | | | | The wait added in #37853 doesn't seem to do anything as request is sent immediately on InsertLeave, and the number 4 also seems wrong. Instead, the actual cause for the flakiness that the feed() (and hence the buffer change) may arrive before the scheduled initialization of capabilities, causing there be only only one textDocument/semanticTokens/full request instead of two.
* test(lsp): wait up to 1 second to read messagesWayne Young2026-02-15
|
* 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
* 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
* feat(lsp): semanticTokens/range #36705Tristan Knight2025-11-30
| | | | | | | | | | | | Problem: Nvim supports `textDocument/semanticTokens/full` and `…/full/delta` already, but most servers don't support `…/full/delta` and Nvim will try to request and process full semantic tokens response on every buffer change. Even though the request is debounced, there is noticeable lag if the token response is large (in a big file). Solution: Support `textDocument/semanticTokens/range`, which requests semantic tokens for visible screen only.
* refactor(lsp): rename vim.lsp.semantic_tokens start/stop to enable()Yi Ming2025-07-13
|
* test(lsp): remove the deprecated `feed_command`Yi Ming2025-07-13
|
* feat(lsp): support multiline semantic tokens #34458Riley Bruins2025-06-13
|
* test(lsp): add a test for resetting the active request after receiving errorYi Ming2025-03-17
|
* feat(lsp): deprecate vim.lsp.start_client #31341Maria José Solano2024-12-04
| | | | | | | | Problem: LSP module has multiple "start" interfaces. Solution: - Enhance vim.lsp.start - Deprecate vim.lsp.start_client
* fix(tests): needing two calls to setup a screen is cringebfredl2024-11-14
| | | | | | | | | | Before calling "attach" a screen object is just a dummy container for (row, col) values whose purpose is to be sent as part of the "attach" function call anyway. Just create the screen in an attached state directly. Keep the complete (row, col, options) config together. It is still completely valid to later detach and re-attach as needed, including to another session.
* test: support upvalues in exec_luaLewis Russell2024-09-21
|
* refactor(lsp): use metatable for buf_versions (#29304)Ilia Choly2024-06-14
| | | | | | This reduces the number of nil checks around buf_versions usage Test changes were lifted from 5c33815 Co-authored-by: Mathias Fussenegger <f.mathias@zignar.net>
* fix(lsp): revert buf_versions deprecation/replacement (#29217)Mathias Fußenegger2024-06-07
| | | | | | | | | * Revert "fix(lsp): account for changedtick version gap on modified reset (#29170)" This reverts commit 2e6d295f799c27372e5c0c44727fa613c81717fd. * Revert "refactor(lsp): replace util.buf_versions with changedtick (#28943)" This reverts commit 5c33815448e11b514678f39cecc74e68131d4628.
* refactor(lsp): replace util.buf_versions with changedtick (#28943)Mathias Fußenegger2024-05-30
| | | | | | | `lsp.util.buf_versions` was already derived from changedtick (`on_lines` from `buf_attach` synced the version) As far as I can tell there is no need to keep track of the state in a separate table.
* fix(lsp): check if buffer was detached in on_init callback (#28914)Ilia Choly2024-05-23
| | | Co-authored-by: Jongwook Choi <wookayin@gmail.com>
* fix(lsp): semantic token functions allow "0" bufnr #28849Riley Bruins2024-05-21
| | | aligns with ":help dev-patterns"
* test: improve test conventionsdundargoc2024-04-23
| | | | | | | | | Specifically, functions that are run in the context of the test runner are put in module `test/testutil.lua` while the functions that are run in the context of the test session are put in `test/functional/testnvim.lua`. Closes https://github.com/neovim/neovim/issues/27004.
* refactor(test): inject after_each differentlyLewis Russell2024-04-10
|
* test: improve test conventionsdundargoc2024-04-08
| | | | Work on https://github.com/neovim/neovim/issues/27004.
* test: reduce `exec_lua` callsdundargoc2024-04-04
| | | | | | | | | | | | | | | | | | | | | `exec_lua` makes code slighly harder to read, so it's beneficial to remove it in cases where it's possible or convenient. Not all `exec_lua` calls should be removed even if the test passes as it changes the semantics of the test even if it happens to pass. From https://github.com/neovim/neovim/pull/28155#discussion_r1548185779: "Note for tests like this, which fundamentally are about conversion, you end up changing what conversion you are testing. Even if the result happens to be same (as they often are, as we like the rules to be consistent if possible), you are now testing the RPC conversion rules instead of the vim script to in-process lua conversion rules." From https://github.com/neovim/neovim/pull/28155#discussion_r1548190152: "A test like this specifies that the cursor is valid immediately and not after a separate cycle of normal (or an other input-processing) mode."
* fix(lsp): add missing LSP semantic token highlight linksCaleb Marshall2024-03-16
| | | | | | | | | | | | | Added the following LSP semantic token types to be linked to highlight groups by default: * @lsp.type.event * @lsp.type.keyword * @lsp.type.modifier * @lsp.type.number * @lsp.type.operator * @lsp.type.regexp * @lsp.type.string
* refactor: format test/*Justin M. Keyes2024-01-03
|
* test: avoid repeated screen lines in expected stateszeertzjq2023-12-09
| | | | | | This is the command invoked repeatedly to make the changes: :%s/^\(.*\)|\%(\*\(\d\+\)\)\?$\n\1|\%(\*\(\d\+\)\)\?$/\=submatch(1)..'|*'..(max([str2nr(submatch(2)),1])+max([str2nr(submatch(3)),1]))/g
* feat(highlight): Allow hyphens (-) in highlight group names (#24714)Gregory Anders2023-08-15
| | | Fixes: https://github.com/neovim/neovim/issues/23184
* test(lsp): fix unstable tests for semantic tokensjdrouhard2023-04-23
| | | | Add screen:expect() calls after insert() to make sure the screen has been drawn before we assert the state of the semantic tokens table
* docs: fix typosdundargoc2023-04-04
| | | | | | Co-authored-by: Gregory Anders <greg@gpanders.com> Co-authored-by: Raphael <glephunter@gmail.com> Co-authored-by: C.D. MacEachern <craig.daniel.maceachern@gmail.com> Co-authored-by: himanoa <matsunoappy@gmail.com>
* feat(lsp)!: add rule-based sem token highlighting (#22022)swarn2023-03-06
| | | | | | | | | | | | | feat(lsp)!: change semantic token highlighting Change the default highlights used, and add more highlights per token. Add an LspTokenUpdate event and a highlight_token function. :Inspect now shows any highlights applied by token highlighting rules, default or user-defined. BREAKING CHANGE: change the default highlight groups used by semantic token highlighting.
* perf(lsp): only redraw the windows containing LSP tokensbfredl2023-02-28
| | | | | | | | redraw! redraws the entire screen instead of just the windows with the buffer which were actually changed. I considered trying to calculating the range for the delta but it looks tricky. Could a follow-up.
* test(lsp): add a screen:expect() between insert() and feed_command() (#21577)zeertzjq2022-12-29
| | | | The insert() and feed_command() type a lot of text, with only one screen:expect() call after the feed_command() it may time out.
* fix(lsp): token_edit.data might be null on deletion (#21462)tiagovla2022-12-19
|
* feat(lsp): highlight semantic token modifiers (#21390)Christian Clason2022-12-12
| | | | | | | | Apply semantic token modifiers as separate extmarks with corresponding highlight groups (e.g., `@readonly`). This is a low-effort PR to enable the most common use cases (applying, e.g., italics or backgrounds on top of type highlights; language-specific fallbacks like `@global.lua` are also available). This can be replaced by more complicated selector-style themes later on.
* perf(lsp): update semantic tokens algorithm for parsing modifiers (#21383)jdrouhard2022-12-12
| | | | | | | | Instead of testing for every possible modifier type, only test bits up to the highest set in the token array. Saves many bit ops and comparisons when there are no modifiers or when the highest set bit is a lower bit than the highest possible in the legend on average. Can be further simplified when non-luaJIT gets the full bit module (see #21222)
* fix(lsp): ignore null responses for semanticTokens request (#21364)fsouza2022-12-10
| | | | | | | | The spec indicates that the response may be `null`, but it doesn't really say what a `null` response means. Since neovim raises an error if the response is `null`, I figured that ignoring it would be the safest bet. Co-authored-by: Mathias Fussenegger <f.mathias@zignar.net>
* fix(lsp): followup fixes for semantic tokens support (#21357)jdrouhard2022-12-09
| | | | | | | | | | | | | | | | 1. The algorithm for applying edits was slightly incorrect. It needs to preserve the original token list as the edits are applied instead of mutating it as it iterates. From the spec: Semantic token edits behave conceptually like text edits on documents: if an edit description consists of n edits all n edits are based on the same state Sm of the number array. They will move the number array from state Sm to Sm+1. 2. Schedule the semantic token engine start() call in the client._on_attach() function so that users who schedule_wrap() their config.on_attach() functions (like nvim-lspconfig does) can still disable semantic tokens by deleting the semanticTokensProvider from their server capabilities.
* feat(lsp): initial support for semantic token highlightingJohn Drouhard2022-12-08
* credit to @smolck and @theHamsta for their contributions in laying the groundwork for this feature and for their work on some of the helper utility functions and tests