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

Renaming bug "Buffer X newer than edits" #12970

Closed
sharksforarms opened this issue Sep 23, 2020 · 10 comments
Closed

Renaming bug "Buffer X newer than edits" #12970

sharksforarms opened this issue Sep 23, 2020 · 10 comments
Assignees
Labels
bug issues reporting wrong behavior lsp

Comments

@sharksforarms
Copy link
Sponsor

  • nvim --version:
NVIM v0.5.0-709-g4f8d98e58-dirty
Build type: RelWithDebInfo
LuaJIT 2.1.0-beta3
Compilation: /usr/bin/cc -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1 -O2 -g -Og -g -Wall -Wextra -pedantic -Wno-unused-parameter -Wstrict-prototypes -std=gnu99 -Wshadow -Wconversion -Wmissing-prototypes -Wimplicit-fallthrough -Wvla -fstack-protector-strong -fno-common -fdiagnostics-color=always -DINCLUDE_GENERATED_DECLARATIONS -D_GNU_SOURCE -DNVIM_MSGPACK_HAS_FLOAT32 -DNVIM_UNIBI_HAS_VAR_FROM -DMIN_LOG_LEVEL=3 -I/home/sharks/source/neovim/build/config -I/home/sharks/source/neovim/src -I/home/sharks/source/neovim/.deps/usr/include -I/usr/include -I/home/sharks/source/neovim/build/src/nvim/auto -I/home/sharks/source/neovim/build/include
Compiled by sharks@sharks

Features: +acl +iconv +tui
See ":help feature-compile"

   system vimrc file: "$VIM/sysinit.vim"
  fall-back for $VIM: "/usr/local/share/nvim"

Run :checkhealth for more info
  • language server name/version: rust-analyzer --version "rust-analyzer e70cf70"
  • Operating system/version: Ubuntu 20.04
nvim -c ":checkhealth nvim nvim_lsp"

health#nvim#check

Configuration

  • OK: no issues found

Performance

  • OK: Build type: RelWithDebInfo

Remote Plugins

  • OK: Up to date

terminal

  • INFO: key_backspace (kbs) terminfo entry: key_backspace=\177
  • INFO: key_dc (kdch1) terminfo entry: key_dc=\E[3~
  • INFO: $COLORTERM='truecolor'

tmux

  • OK: escape-time: 0
  • INFO: Checking stuff
  • OK: focus-events: on
  • INFO: $TERM: xterm-256color
  • INFO: default-terminal: screen-256color
  • ERROR: $TERM differs from the tmux default-terminal setting. Colors might look wrong.
    • ADVICE:
      • $TERM may have been set by some rc (.bashrc, .zshrc, ...).

health#nvim_lsp#check

Checking language server protocol configuration

  • INFO: clangd: configuration checked.
  • INFO: rust_analyzer: configuration checked.
  • INFO: pyls: configuration checked.
  • INFO: gopls: configuration checked.
lsp.log

[ DEBUG ] 2020-09-23T14:22:40-0400 ] /usr/local/share/nvim/runtime/lua/vim/lsp.lua:640 ] "LSP[rust_analyzer]" "client.request" 1 "textDocument/rename" { newName = "my_var", position = { character = 8, line = 1 }, textDocument = { uri = "file:///tmp/tester/src/main.rs" }} <function 1> 1
[ DEBUG ] 2020-09-23T14:22:40-0400 ] /usr/local/share/nvim/runtime/lua/vim/lsp/rpc.lua:361 ] "rpc.send.payload" { id = 5, jsonrpc = "2.0", method = "textDocument/rename", params = { newName = "my_var", position = { character = 8, line = 1 }, textDocument = { uri = "file:///tmp/tester/src/main.rs" } }}
[ DEBUG ] 2020-09-23T14:22:40-0400 ] /usr/local/share/nvim/runtime/lua/vim/lsp/rpc.lua:462 ] "decoded" { id = 5, jsonrpc = "2.0", result = { documentChanges = { { edits = { { newText = "my_var", range = { end = { character = 9, line = 1 }, start = { character = 8, line = 1 } } } }, textDocument = { uri = "file:///tmp/tester/src/main.rs", version = 0 } }, { edits = { { newText = "my_var", range = { end = { character = 13, line = 3 }, start = { character = 12, line = 3 } } } }, textDocument = { uri = "file:///tmp/tester/src/main.rs", version = 0 } } } }}
[ DEBUG ] 2020-09-23T14:22:40-0400 ] /usr/local/share/nvim/runtime/lua/vim/lsp/callbacks.lua:332 ] "default_callback" "textDocument/rename" { bufnr = 1, client_id = 1, params = { documentChanges = { { edits = { { newText = "my_var", range = { end = { character = 9, line = 1 }, start = { character = 8, line = 1 } } } }, textDocument = { uri = "file:///tmp/tester/src/main.rs", version = 0 } }, { edits = { { newText = "my_var", range = { end = { character = 13, line = 3 }, start = { character = 12, line = 3 } } } }, textDocument = { uri = "file:///tmp/tester/src/main.rs", version = 0 } } } }}
[ DEBUG ] 2020-09-23T14:22:40-0400 ] /usr/local/share/nvim/runtime/lua/vim/lsp.lua:765 ] "on_lines bufnr: 1, changedtick: 4, firstline: 1, lastline: 2, new_lastline: 2, old_byte_size: 20, old_utf32_size: 20, old_utf16_size: 20" { ' let my_var = "test";' }
[ DEBUG ] 2020-09-23T14:22:40-0400 ] /usr/local/share/nvim/runtime/lua/vim/lsp/rpc.lua:361 ] "rpc.send.payload" { jsonrpc = "2.0", method = "textDocument/didChange", params = { contentChanges = { { text = 'fn main() {\n let my_var = "test";\n\n let b = a;\n println!("b: {}", b);\n}\n' } }, textDocument = { uri = "file:///tmp/tester/src/main.rs", version = 4 } }}
[ DEBUG ] 2020-09-23T14:22:40-0400 ] /usr/local/share/nvim/runtime/lua/vim/lsp.lua:640 ] "LSP[rust_analyzer]" "client.request" 1 "rust-analyzer/inlayHints" { textDocument = { uri = "file:///tmp/tester/src/main.rs" }} <function 1> 1
[ DEBUG ] 2020-09-23T14:22:40-0400 ] /usr/local/share/nvim/runtime/lua/vim/lsp/rpc.lua:361 ] "rpc.send.payload" { id = 6, jsonrpc = "2.0", method = "rust-analyzer/inlayHints", params = { textDocument = { uri = "file:///tmp/tester/src/main.rs" } }}
[ DEBUG ] 2020-09-23T14:22:40-0400 ] /usr/local/share/nvim/runtime/lua/vim/lsp/rpc.lua:462 ] "decoded" { jsonrpc = "2.0", method = "textDocument/publishDiagnostics", params = { diagnostics = {}, uri = "file:///tmp/tester/src/main.rs", version = 4 }}
[ DEBUG ] 2020-09-23T14:22:40-0400 ] /usr/local/share/nvim/runtime/lua/vim/lsp/rpc.lua:462 ] "decoded" { id = 6, jsonrpc = "2.0", result = { { kind = "TypeHint", label = "&str", range = { end = { character = 14, line = 1 }, start = { character = 8, line = 1 } } } }}
[ DEBUG ] 2020-09-23T14:22:40-0400 ] /usr/local/share/nvim/runtime/lua/vim/lsp.lua:434 ] "notification" "textDocument/publishDiagnostics" { diagnostics = {}, uri = "file:///tmp/tester/src/main.rs", version = 4}
[ DEBUG ] 2020-09-23T14:22:42-0400 ] /usr/local/share/nvim/runtime/lua/vim/lsp.lua:640 ] "LSP[rust_analyzer]" "client.request" 1 "rust-analyzer/inlayHints" { textDocument = { uri = "file:///tmp/tester/src/main.rs" }} <function 1> 1
[ DEBUG ] 2020-09-23T14:22:42-0400 ] /usr/local/share/nvim/runtime/lua/vim/lsp/rpc.lua:361 ] "rpc.send.payload" { id = 7, jsonrpc = "2.0", method = "rust-analyzer/inlayHints", params = { textDocument = { uri = "file:///tmp/tester/src/main.rs" } }}
[ DEBUG ] 2020-09-23T14:22:42-0400 ] /usr/local/share/nvim/runtime/lua/vim/lsp/rpc.lua:462 ] "decoded" { id = 7, jsonrpc = "2.0", result = { { kind = "TypeHint", label = "&str", range = { end = { character = 14, line = 1 }, start = { character = 8, line = 1 } } } }}
[ DEBUG ] 2020-09-23T14:22:42-0400 ] /usr/local/share/nvim/runtime/lua/vim/lsp.lua:640 ] "LSP[rust_analyzer]" "client.request" 1 "rust-analyzer/inlayHints" { textDocument = { uri = "file:///tmp/tester/src/main.rs" }} <function 1> 1
[ DEBUG ] 2020-09-23T14:22:42-0400 ] /usr/local/share/nvim/runtime/lua/vim/lsp/rpc.lua:361 ] "rpc.send.payload" { id = 8, jsonrpc = "2.0", method = "rust-analyzer/inlayHints", params = { textDocument = { uri = "file:///tmp/tester/src/main.rs" } }}
[ DEBUG ] 2020-09-23T14:22:42-0400 ] /usr/local/share/nvim/runtime/lua/vim/lsp/rpc.lua:462 ] "decoded" { id = 8, jsonrpc = "2.0", result = { { kind = "TypeHint", label = "&str", range = { end = { character = 14, line = 1 }, start = { character = 8, line = 1 } } } }}
[ DEBUG ] 2020-09-23T14:22:42-0400 ] /usr/local/share/nvim/runtime/lua/vim/lsp.lua:640 ] "LSP[rust_analyzer]" "client.request" 1 "rust-analyzer/inlayHints" { textDocument = { uri = "file:///tmp/tester/src/main.rs" }} <function 1> 1
[ DEBUG ] 2020-09-23T14:22:42-0400 ] /usr/local/share/nvim/runtime/lua/vim/lsp/rpc.lua:361 ] "rpc.send.payload" { id = 9, jsonrpc = "2.0", method = "rust-analyzer/inlayHints", params = { textDocument = { uri = "file:///tmp/tester/src/main.rs" } }}
[ DEBUG ] 2020-09-23T14:22:42-0400 ] /usr/local/share/nvim/runtime/lua/vim/lsp/rpc.lua:462 ] "decoded" { id = 9, jsonrpc = "2.0", result = { { kind = "TypeHint", label = "&str", range = { end = { character = 14, line = 1 }, start = { character = 8, line = 1 } } } }}
[ DEBUG ] 2020-09-23T14:22:43-0400 ] /usr/local/share/nvim/runtime/lua/vim/lsp.lua:640 ] "LSP[rust_analyzer]" "client.request" 1 "rust-analyzer/inlayHints" { textDocument = { uri = "file:///tmp/tester/src/main.rs" }} <function 1> 1
[ DEBUG ] 2020-09-23T14:22:43-0400 ] /usr/local/share/nvim/runtime/lua/vim/lsp/rpc.lua:361 ] "rpc.send.payload" { id = 10, jsonrpc = "2.0", method = "rust-analyzer/inlayHints", params = { textDocument = { uri = "file:///tmp/tester/src/main.rs" } }}
[ DEBUG ] 2020-09-23T14:22:43-0400 ] /usr/local/share/nvim/runtime/lua/vim/lsp/rpc.lua:462 ] "decoded" { id = 10, jsonrpc = "2.0", result = { { kind = "TypeHint", label = "&str", range = { end = { character = 14, line = 1 }, start = { character = 8, line = 1 } } } }}
[ DEBUG ] 2020-09-23T14:22:43-0400 ] /usr/local/share/nvim/runtime/lua/vim/lsp.lua:765 ] "on_lines bufnr: 1, changedtick: 5, firstline: 3, lastline: 4, new_lastline: 4, old_byte_size: 15, old_utf32_size: 15, old_utf16_size: 15" { " let b = a; " }
[ DEBUG ] 2020-09-23T14:22:43-0400 ] /usr/local/share/nvim/runtime/lua/vim/lsp/rpc.lua:361 ] "rpc.send.payload" { jsonrpc = "2.0", method = "textDocument/didChange", params = { contentChanges = { { text = 'fn main() {\n let my_var = "test";\n\n let b = a; \n println!("b: {}", b);\n}\n' } }, textDocument = { uri = "file:///tmp/tester/src/main.rs", version = 5 } }}
[ DEBUG ] 2020-09-23T14:22:43-0400 ] /usr/local/share/nvim/runtime/lua/vim/lsp/rpc.lua:462 ] "decoded" { jsonrpc = "2.0", method = "textDocument/publishDiagnostics", params = { diagnostics = {}, uri = "file:///tmp/tester/src/main.rs", version = 5 }}
[ DEBUG ] 2020-09-23T14:22:43-0400 ] /usr/local/share/nvim/runtime/lua/vim/lsp.lua:434 ] "notification" "textDocument/publishDiagnostics" { diagnostics = {}, uri = "file:///tmp/tester/src/main.rs", version = 5}
[ DEBUG ] 2020-09-23T14:22:43-0400 ] /usr/local/share/nvim/runtime/lua/vim/lsp.lua:765 ] "on_lines bufnr: 1, changedtick: 6, firstline: 3, lastline: 4, new_lastline: 4, old_byte_size: 16, old_utf32_size: 16, old_utf16_size: 16" { " let b = a; ?" }
[ DEBUG ] 2020-09-23T14:22:43-0400 ] /usr/local/share/nvim/runtime/lua/vim/lsp/rpc.lua:361 ] "rpc.send.payload" { jsonrpc = "2.0", method = "textDocument/didChange", params = { contentChanges = { { text = 'fn main() {\n let my_var = "test";\n\n let b = a; ?\n println!("b: {}", b);\n}\n' } }, textDocument = { uri = "file:///tmp/tester/src/main.rs", version = 6 } }}
[ DEBUG ] 2020-09-23T14:22:43-0400 ] /usr/local/share/nvim/runtime/lua/vim/lsp/rpc.lua:462 ] "decoded" { jsonrpc = "2.0", method = "textDocument/publishDiagnostics", params = { diagnostics = { { message = "Syntax Error: expected expression", range = { end = { character = 15, line = 3 }, start = { character = 15, line = 3 } }, severity = 1, source = "rust-analyzer" }, { message = "Syntax Error: expected SEMICOLON", range = { end = { character = 16, line = 3 }, start = { character = 16, line = 3 } }, severity = 1, source = "rust-analyzer" } }, uri = "file:///tmp/tester/src/main.rs", version = 6 }}
[ DEBUG ] 2020-09-23T14:22:43-0400 ] /usr/local/share/nvim/runtime/lua/vim/lsp.lua:434 ] "notification" "textDocument/publishDiagnostics" { diagnostics = { { message = "Syntax Error: expected expression", range = { end = { character = 15, line = 3 }, start = { character = 15, line = 3 } }, severity = 1, source = "rust-analyzer" }, { message = "Syntax Error: expected SEMICOLON", range = { end = { character = 16, line = 3 }, start = { character = 16, line = 3 } }, severity = 1, source = "rust-analyzer" } }, uri = "file:///tmp/tester/src/main.rs", version = 6}
[ DEBUG ] 2020-09-23T14:22:44-0400 ] /usr/local/share/nvim/runtime/lua/vim/lsp.lua:765 ] "on_lines bufnr: 1, changedtick: 7, firstline: 3, lastline: 4, new_lastline: 4, old_byte_size: 17, old_utf32_size: 17, old_utf16_size: 17" { " let b = a; ??" }
[ DEBUG ] 2020-09-23T14:22:44-0400 ] /usr/local/share/nvim/runtime/lua/vim/lsp/rpc.lua:361 ] "rpc.send.payload" { jsonrpc = "2.0", method = "textDocument/didChange", params = { contentChanges = { { text = 'fn main() {\n let my_var = "test";\n\n let b = a; ??\n println!("b: {}", b);\n}\n' } }, textDocument = { uri = "file:///tmp/tester/src/main.rs", version = 7 } }}
[ DEBUG ] 2020-09-23T14:22:44-0400 ] /usr/local/share/nvim/runtime/lua/vim/lsp/rpc.lua:462 ] "decoded" { jsonrpc = "2.0", method = "textDocument/publishDiagnostics", params = { diagnostics = { { message = "Syntax Error: expected expression", range = { end = { character = 15, line = 3 }, start = { character = 15, line = 3 } }, severity = 1, source = "rust-analyzer" }, { message = "Syntax Error: expected SEMICOLON", range = { end = { character = 16, line = 3 }, start = { character = 16, line = 3 } }, severity = 1, source = "rust-analyzer" }, { message = "Syntax Error: expected expression", range = { end = { character = 16, line = 3 }, start = { character = 16, line = 3 } }, severity = 1, source = "rust-analyzer" }, { message = "Syntax Error: expected SEMICOLON", range = { end = { character = 17, line = 3 }, start = { character = 17, line = 3 } }, severity = 1, source = "rust-analyzer" } }, uri = "file:///tmp/tester/src/main.rs", version = 7 }}
[ DEBUG ] 2020-09-23T14:22:44-0400 ] /usr/local/share/nvim/runtime/lua/vim/lsp.lua:434 ] "notification" "textDocument/publishDiagnostics" { diagnostics = { { message = "Syntax Error: expected expression", range = { end = { character = 15, line = 3 }, start = { character = 15, line = 3 } }, severity = 1, source = "rust-analyzer" }, { message = "Syntax Error: expected SEMICOLON", range = { end = { character = 16, line = 3 }, start = { character = 16, line = 3 } }, severity = 1, source = "rust-analyzer" }, { message = "Syntax Error: expected expression", range = { end = { character = 16, line = 3 }, start = { character = 16, line = 3 } }, severity = 1, source = "rust-analyzer" }, { message = "Syntax Error: expected SEMICOLON", range = { end = { character = 17, line = 3 }, start = { character = 17, line = 3 } }, severity = 1, source = "rust-analyzer" } }, uri = "file:///tmp/tester/src/main.rs", version = 7}

Steps to reproduce using nvim -u NORC

nvim -u NORC

Actual behaviour

Peek 2020-09-23 13-57

Note: It prints out the print() from here:

print("Buffer ", text_document.uri, " newer than edits.")

Expected behaviour

Renaming all occurences in buffer.

Note, if I comment out the return from util.lua above, it seems to work properly.

@non25
Copy link

non25 commented Mar 2, 2021

Having the same problem with svelte-language-server, but interestingly tsserver code-actions work just fine. 🤔

Every code action from svelte-language-server say this stuff "Buffer X newer than edits".

Edit: It looks like some language servers just don't pass version number back. tsserver sends it, well-behaved.
I've printed both M.buf_versions[bufnr] and text_document.version. The right one is 0 for svelte-language-server.

@tjdevries
Copy link
Contributor

This still happens with even the most up-to-date neovim?

And to be clear, svelte-language-server always passes back 0? Perhaps we should just ignore the version if it is equal to 0.

@non25
Copy link

non25 commented Mar 10, 2021

And to be clear, svelte-language-server always passes back 0?

According to this piece of code I think yes:
sveltejs/language-tools#851 (comment)

This still happens with even the most up-to-date neovim?

Here's related logic, which didn't change, so I guess it should still happen.

-- `VersionedTextDocumentIdentifier`s version may be null
-- https://microsoft.github.io/language-server-protocol/specification#versionedTextDocumentIdentifier
if should_check_version and (text_document.version
and M.buf_versions[bufnr]
and M.buf_versions[bufnr] > text_document.version) then
print("Buffer ", text_document.uri, " newer than edits.")
return
end

I feel like lsp should return same version back, or higher version.
I've commented version-checking logic to be able to use autoimports, which are pretty important to me. 🤔

@tjdevries
Copy link
Contributor

Instead of commenting it out, you could probably just do something like this anywhere in your config:

vim.lsp.util.apply_text_document_edit = function(text_document_edit, index)
  local text_document = text_document_edit.textDocument
  local bufnr = vim.uri_to_bufnr(text_document.uri)

  vim.lsp.util.apply_text_edits(text_document_edit.edits, bufnr)
end

This way you don't have to have a custom patch to override the thing :)

@tjdevries
Copy link
Contributor

I'm not sure what we should do about adding cases to handle misbehaving clients... it's possible we could pass in the client id and allow you to set a flag that could ignore this, but that seems kind of overkill for them not following the spec correctly :/ I'm not sure of the right move forward.

@mfussenegger
Copy link
Member

And to be clear, svelte-language-server always passes back 0? Perhaps we should just ignore the version if it is equal to 0.

jdtls has the same bug, which led to workarounds:

Still waiting on a response in the upstream repository.

@mfussenegger
Copy link
Member

The eclipse.jdt.ls maintainers responsed and agree that it's a bug in the server. I now also left a comment in the svelte issue.

I think the current check within neovim makes sense and we should keep it instead of adding a workaround for servers who don't follow the spec.

@mjlbach
Copy link
Contributor

mjlbach commented Apr 13, 2021

If this happens for any additional servers, the policy should be to report upstream and add a mitigation in nvim-lspconfig like neovim/nvim-lspconfig@486f72a. I agree with TJ that we shouldn't add any mitigations in core for misbehaving servers.

@mjlbach mjlbach closed this as completed Apr 13, 2021
mfussenegger added a commit to mfussenegger/neovim that referenced this issue Apr 14, 2021
There were a couple of reports of "Buffer X newer than edits" problems.
We first assumed that it is incorrect for a server to send 0 as a
version - and stated that they should send a `null` instead, given that
in the specification the `textDocument` of a `TextDocumentEdit` is a
`OptionalVersionedTextDocumentIdentifier`.

But it turns out that this was a change in 3.16, and in 3.15 and earlier
versions of the specification it was a `VersionedTextDocumentIdentifier`
and language servers didn't have a better option than sending `0` if
they don't keep track of the version numbers.

So this changes the version check to always accept `0` values.

See

- neovim#12970
- neovim#14256
- haskell/haskell-language-server#1727
@hendrikbursian
Copy link

hendrikbursian commented Jun 27, 2022

Notice the workaround tjdevries provided would now be the following:

vim.lsp.util.apply_text_document_edit = function(text_document_edit, index, offset_encoding)
    local text_document = text_document_edit.textDocument
    local bufnr = vim.uri_to_bufnr(text_document.uri)
    if offset_encoding == nil then
        vim.notify_once('apply_text_document_edit must be called with valid offset encoding', vim.log.levels.WARN)
    end

    vim.lsp.util.apply_text_edits(text_document_edit.edits, bufnr, offset_encoding)
end

Notice the the 3rd parameter.

@Holi0317
Copy link

I am trying to make a patch/hotfix/workaround on volar lspconfig as their textDocument.version is not implemented correctly. vuejs/language-tools#1490

Following the commit mentioned by @mjlbach, I have tried adding the handler in both setup.handlers in init.lua and default_config.handlers but seems nvim.lsp is not picking up my override. Line 11 calls to vim.alert which should throw an error but nothing was reported in console when I trigger code action.

The gist below is the minimal configuration for volar setup plus attempt on patching it.

https://gist.github.com/Holi0317/74ebabbd14fdd76ac3bf68360ae75527

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug issues reporting wrong behavior lsp
Projects
None yet
Development

No branches or pull requests

7 participants