Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug: Updating buffer (open, reload) creates duplicated server-side content when multiple LSP servers are enabled #1547

Open
rgoya opened this issue Apr 7, 2024 · 0 comments · May be fixed by #1548

Comments

@rgoya
Copy link

rgoya commented Apr 7, 2024

Summary

When loading or updating the contents of a file (e.g. :e), vim-lsp correctly sends the full content to the file to the first LSP registered server, but erroneously tells subsequent servers that the file has had changes. This causes the subsequent LSP servers to have a warped view of what the file contents are.

In some cases the only effect will be an overloaded list of diagnostics, (e.g. when no code actions are requested). In other cases, like requesting :LspDocumentFormat, the server will return its own warped version of the file, leaving the user with a buffer containing multiple copies of the actual content.

A suggested fix is provided in an accompanying PR (#1548)

Setup

Tell vim-lsp to start both ruff and pyright servers:

let g:lsp_settings_filetype_python = ['pyright-langserver', 'ruff-lsp']

The formatting step in the reproduction below will work only when ruff is assigned the second slot int he server list; however, the duplication of diagnostics should also show up for pyright if that is the one assigned the second slot.

Create a test file that will trigger some diagnostics for both servers. The following has unused imports (ruff fix), extra blank lines (ruff format) and unknown module (pyright):

import pandas


import numpi

Reproduce

The initial opening of the file correctly identifies the issues of the simple file:
image

Executing :e on the file once causes ruff to start hallucinating, while pyright is doing well:
image

And this continues as we reload the file:
image

Asking for :LspDocumentFormat, which is executed by ruff, results in a very different buffer, caused by ruff imposing its perceived reality onto the developer:
image

Debug

The offending line can be found in the function s:text_changes(buf, server_name) in the following line:

vim-lsp/autoload/lsp.vim

Lines 752 to 754 in f7ccf00

" When syncKind is Incremental and previous content is saved.
if l:sync_kind == 2 && has_key(s:file_content, a:buf)
" compute diff

When the first LSP server is being sent the data s:file_content does not have an entry for the buffer yet, and is correctly sent the full content:

vim-lsp/autoload/lsp.vim

Lines 765 to 768 in f7ccf00

let l:new_content = lsp#utils#buffer#_get_lines(a:buf)
let l:changes = {'text': join(l:new_content, "\n")}
call s:update_file_content(a:buf, a:server_name, l:new_content)
return [l:changes]

When the second LSP server is being sent the data, the condition is met and the diff is sent. However, the check is not making the distinction of which LSP server is actually being updated, a distinction that should be meade given the expected content of s:file_content:

" This hold previous content for each language servers to make
" DidChangeTextDocumentParams. The key is buffer numbers:
" {
" 1: {
" "golsp": [ "first-line", "next-line", ... ],
" "bingo": [ "first-line", "next-line", ... ]
" },
" 2: {
" "pylsp": [ "first-line", "next-line", ... ]
" }
" }
let s:file_content = {}

Fix

The fix seems to be simple, just add a statement to the condition statement to ensure the right server is being evaluated and updated, change:

vim-lsp/autoload/lsp.vim

Lines 752 to 754 in f7ccf00

" When syncKind is Incremental and previous content is saved.
if l:sync_kind == 2 && has_key(s:file_content, a:buf)
" compute diff

for:

   if l:sync_kind == 2 && has_key(s:file_content, a:buf) && has_key(s:file_content[a:buf], a:server_name)
@rgoya rgoya changed the title Updating buffer (open, reload) creates duplicated server-side content when multiple LSP servers are enabled. Bug: Updating buffer (open, reload) creates duplicated server-side content when multiple LSP servers are enabled Apr 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
1 participant