Current event handling seems somewhat confusing. It is good to document
the intent, in order to be able to asses if the code is doing what is
intended.
Co-authored-by: mattn <mattn.jp@gmail.com>
Add :LspDocumentLink to list all document links in the quickfix list
and :LspDocumentLinkOpen to open the link on the current cursor line
in the browser or editor.
Workspace symbol search is slow with many symbols because vim locations
for all symbols are calculated when generating the quickpick list, even
though they are only required when selecting a symbol to open a location
Fix by delaying calculating the vim location until a symbol is selected.
Co-authored-by: mattn <mattn.jp@gmail.com>
complete() with an empty list discards items collected from the sources
listed in the 'complete' option and closes the completion menu. Skip the
call to keep them.
Co-authored-by: mattn <mattn.jp@gmail.com>
This fixes auto import for rust-analyzer >= 1.85.x. Without advertising
'detail' in resolveSupport, rust-analyzer does not generate
additionalTextEdits for auto imports.
Fixes#1595
When multiple listener changes accumulate and the full-text fallback
path is taken, getbufline() was called directly instead of going through
lsp#utils#buffer#_get_lines(). This bypassed the fixendofline handling,
producing text without a trailing newline. The LSP server would then
return formatted text with a proper trailing newline, causing an
unwanted newline to be appended on every save.
Use _get_lines() to match every other full-text send path.
Fixes#1658
When multiple listener_add callbacks fire before flush(), each change's
lnum/end references the buffer state at that point, but getbufline()
reads the final state. If a later change shifts lines, earlier changes
read wrong text.
For a single change, use the efficient listener path as before. When
multiple changes accumulate, fall back to sending full document text.
Also update s:file_content on the listener path to keep it current.
Fixes#1656
* cache getbufline and diff results per changedtick
When multiple LSP servers are registered for the same filetype,
s:text_changes() was calling getbufline(buf, 1, '$') and computing
diff once per server. For a 5000-line buffer with 3 servers, this
meant 3 full buffer reads and 3 O(n) diff loops per change event.
Cache both results keyed by changedtick so they are computed only
once regardless of the number of servers.
* use listener_add() for incremental text sync when available
When listener_add() is available (Vim 8.1.1320+), use it to track
buffer changes and build LSP contentChanges directly from the change
events. This avoids both getbufline() for the full buffer and the
O(n) diff computation in VimScript.
For a 5000-line buffer with 3 LSP servers:
- Before: 3x getbufline(5000 lines) + 3x diff loop = O(n * servers)
- After: listener gives exact change location, getbufline only for
changed lines, result cached across servers = O(changed lines)
Falls back to existing diff-based approach when listener_add() is
not available (neovim, older Vim).
* Do not allocate list
* Extract listener/cache logic into autoload/lsp/internal/listener.vim
Move listener_add integration and buffer cache logic out of lsp.vim
into a dedicated module to keep lsp.vim changes minimal.
* Revert split send to fix Vim 8.0 on Windows
Sending the LSP header and body as separate calls caused gopls to
exit on Vim 8.0 (Windows). Send as a single payload instead.
Use timer_start instead of feedkeys with \<C-r>= to call
on_complete_done_after. The feedkeys approach corrupts the typeahead
buffer when CTRL-k (digraph) is pressed while the popup menu is visible.
- Cache line content to avoid repeated getbufline() calls during position conversion
- Use add() instead of list concatenation for building highlight lists
- Track textprop types in a dictionary instead of filtering prop_type_list() each time
`insertReplaceSupport` is a client capability that was added to
LSP in 3.16.0. It allows the client to choose, when a completion
is done, whether the completion text is to insert at the cursor,
or is to replace some text under the cursor.
Closes#1631
Co-authored-by: mattn <mattn.jp@gmail.com>
It seems that we should be recording the current buffer, cursor position
and change tick before we wait to see if the float should be shown or
not. Otherwise, if any of the above change during the
`g:lsp_diagnostics_float_delay` our recording would be incorrect.
Co-authored-by: mattn <mattn.jp@gmail.com>
Use values() instead of items() where dictionary keys are not used in
iteration.
Co-authored-by: Prabir Shrestha <mail@prabir.me>
Co-authored-by: mattn <mattn.jp@gmail.com>
* Fix the structure of test response
* Add end positions for quickfix/loclist
* Add a function to make loc_range
---------
Co-authored-by: mattn <mattn.jp@gmail.com>
* Fix completion item text selection priority
According to the Language Server Protocol 3.17 specification:
- filterText is only used for filtering and sorting completion items
- When textEdit is provided, insertText must be ignored
* Fix filtering should be performed on filterText
If `filterText` exists, the filtering target has been changed from `word`.
The filter is defined as follows in the LSP specification:
```
A string that should be used when filtering a set of completion items.
When omitted the label is used as the filter text for this item.
```
* Fix remove unnecessary empty check condition
---------
Co-authored-by: mattn <mattn.jp@gmail.com>
* fix(text_edit): discarded change from the initial buffer
When multiple calls to apply_text_edits, the changes made to the current
buffer are discarded if the following text_edit concerns a file that
is not in the buffer list.
The problem comes from the _switch function, which executes `edit!` when
it detects that the target is not in the buffer list. If a change was
made to the current buffer before that, that change is discarded
(definition of `edit!`).
The fix consists of a different logic: when _switch detects that the
target is not in the buffer list, it calls `badd` prior to switching to
the buffer that has just been added. No more `edit!`, no more discarded
changes.
The added test fails without the patch in the _switch function.
* use better way to have a named buffer