autoload/lsp/diag.vim | 2 +- autoload/lsp/lsp.vim | 17 +++++++++++++++++ autoload/lsp/lspserver.vim | 10 ++++++---- plugin/lsp.vim | 1 + test/clangd_tests.vim | 25 +++++++++++++++++++++++++ diff --git a/autoload/lsp/diag.vim b/autoload/lsp/diag.vim index 583c020664513b0e77a2592db5f7605fe59eb41a..263c07c8d35a826432362fb9a39f3c3f4c6bb59b 100644 --- a/autoload/lsp/diag.vim +++ b/autoload/lsp/diag.vim @@ -208,7 +208,7 @@ enddef # Refresh the placed diagnostics in buffer "bnr" # This inline signs, inline props, and virtual text diagnostics -def DiagsRefresh(bnr: number) +export def DiagsRefresh(bnr: number) :silent! bnr->bufload() RemoveDiagVisualsForBuffer(bnr) diff --git a/autoload/lsp/lsp.vim b/autoload/lsp/lsp.vim index 7b9ed6808a4182ab0b197e259a1cd2940ccc9e9c..66387ca3051a5e3b52c2bb8e62d8fe3d056181d0 100644 --- a/autoload/lsp/lsp.vim +++ b/autoload/lsp/lsp.vim @@ -529,6 +529,23 @@ buf.BufLspServerRemove(bnr, lspserver) endfor enddef +# Buffer 'bnr' is loaded in a window, send the latest buffer contents to the +# language servers. +export def BufferLoadedInWin(bnr: number) + var lspservers: list> = buf.BufLspServersGet(bnr) + if lspservers->empty() + # No language servers for this buffer + return + endif + for lspserver in lspservers + if !lspserver->empty() && lspserver.ready + lspserver.textdocDidChange(bnr, 0, 0, 0, []) + endif + endfor + # Refresh the displayed diags visuals + diag.DiagsRefresh(bnr) +enddef + # Stop all the LSP servers export def StopAllServers() for lspserver in LSPServers diff --git a/autoload/lsp/lspserver.vim b/autoload/lsp/lspserver.vim index 4366d7334d95520d6b21d06640b5b29d48bc83af..4ae40198bd0045fb3dd480c22ad85f342bde307f 100644 --- a/autoload/lsp/lspserver.vim +++ b/autoload/lsp/lspserver.vim @@ -543,7 +543,8 @@ var params = { textDocument: { uri: util.LspBufnrToUri(bnr), languageId: ftype, - version: 1, + # Use Vim 'changedtick' as the LSP document version number + version: bnr->getbufvar('changedtick'), text: bnr->getbufline(1, '$')->join("\n") .. "\n" } } @@ -570,7 +571,7 @@ changes: list>): void # Notification: 'textDocument/didChange' # Params: DidChangeTextDocumentParams - var changeset: list> + # var changeset: list> ##### FIXME: Sending specific buffer changes to the LSP server doesn't ##### work properly as the computed line range numbers is not correct. @@ -608,14 +609,15 @@ # var range: dict> = {'start': {'line': start_lnum, 'character': start_col}, 'end': {'line': end_lnum, 'character': end_col}} # changeset->add({'range': range, 'text': lines}) # endfor - changeset->add({text: bnr->getbufline(1, '$')->join("\n") .. "\n"}) var params = { textDocument: { uri: util.LspBufnrToUri(bnr), # Use Vim 'changedtick' as the LSP document version number version: bnr->getbufvar('changedtick') }, - contentChanges: changeset + contentChanges: [ + {text: bnr->getbufline(1, '$')->join("\n") .. "\n"} + ] } lspserver.sendNotification('textDocument/didChange', params) enddef diff --git a/plugin/lsp.vim b/plugin/lsp.vim index 2de7df5b1bcd39d0171d92e3cec8433f860c3ffd..382ae49e49edcc5c925a008a6250c0e8a314a34c 100644 --- a/plugin/lsp.vim +++ b/plugin/lsp.vim @@ -49,6 +49,7 @@ autocmd BufNewFile,BufReadPost,FileType * lsp.AddFile(expand('')->str2nr()) # Note that when BufWipeOut is invoked, the current buffer may be different # from the buffer getting wiped out. autocmd BufWipeOut * lsp.RemoveFile(expand('')->str2nr()) + autocmd BufWinEnter * lsp.BufferLoadedInWin(expand('')->str2nr()) augroup END # TODO: Is it needed to shutdown all the LSP servers when exiting Vim? diff --git a/test/clangd_tests.vim b/test/clangd_tests.vim index 68d074bb1e1aa93f3f1f1432386abdb1a47a3da0..5ad93b7b3b1ab2bfc6200d20456fd3e1007b7708 100644 --- a/test/clangd_tests.vim +++ b/test/clangd_tests.vim @@ -1548,6 +1548,31 @@ :%bw! enddef +# Test for reloading a modified buffer with diags +def g:Test_ReloadBufferWithDiags() + var lines: list =<< trim END + void ReloadBufferFunc1(void) + { + int a: + } + END + writefile(lines, 'Xreloadbuffer.c') + :silent! edit Xreloadbuffer.c + g:WaitForServerFileLoad(1) + var signs = sign_getplaced('%', {group: '*'})[0].signs + assert_equal(3, signs[0].lnum) + append(0, ['', '']) + signs = sign_getplaced('%', {group: '*'})[0].signs + assert_equal(5, signs[0].lnum) + :edit! + sleep 200m + signs = sign_getplaced('%', {group: '*'})[0].signs + assert_equal(3, signs[0].lnum) + + :%bw! + delete('Xreloadbuffer.c') +enddef + # Test for the :LspServer command. def g:Test_LspServer() new a.raku