fix(lsp): send didOpen if name changes on write (#19583)

`:saveas newName` changes the name of an existing buffer.
Due to the buffer re-use it skips the lsp attach phase and immediately
sends a `didSave` notification to the server.
Servers get confused about this, because they expect a `didOpen`
notification first.

Closes https://github.com/neovim/neovim/issues/18688
This commit is contained in:
Mathias Fußenegger
2022-08-01 22:32:53 +02:00
committed by GitHub
parent 711ef4eac9
commit e99de3f12f
3 changed files with 91 additions and 5 deletions

View File

@@ -371,7 +371,9 @@ do
state_by_client[client.id] = state
end
if not state.buffers[bufnr] then
local buf_state = {}
local buf_state = {
name = api.nvim_buf_get_name(bufnr),
}
state.buffers[bufnr] = buf_state
if use_incremental_sync then
buf_state.lines = nvim_buf_get_lines(bufnr, 0, -1, true)
@@ -381,6 +383,15 @@ do
end
end
---@private
function changetracking._get_and_set_name(client, bufnr, name)
local state = state_by_client[client.id] or {}
local buf_state = (state.buffers or {})[bufnr]
local old_name = buf_state.name
buf_state.name = name
return old_name
end
---@private
function changetracking.reset_buf(client, bufnr)
changetracking.flush(client, bufnr)
@@ -1405,6 +1416,19 @@ local function text_document_did_save_handler(bufnr)
local uri = vim.uri_from_bufnr(bufnr)
local text = once(buf_get_full_text)
for_each_buffer_client(bufnr, function(client)
local name = api.nvim_buf_get_name(bufnr)
local old_name = changetracking._get_and_set_name(client, bufnr, name)
if old_name and name ~= old_name then
client.notify('textDocument/didOpen', {
textDocument = {
version = 0,
uri = uri,
languageId = client.config.get_language_id(bufnr, vim.bo[bufnr].filetype),
text = buf_get_full_text(bufnr),
},
})
util.buf_versions[bufnr] = 0
end
local save_capability = vim.tbl_get(client.server_capabilities, 'textDocumentSync', 'save')
if save_capability then
local included_text