From 7a0d23f22945ad5fae62e72275d4ce683cb6be48 Mon Sep 17 00:00:00 2001 From: Yegappan Lakshmanan Date: Sat, 17 Jun 2023 14:42:39 -0700 Subject: [PATCH] Update diags location list when the diags for the buffer changes. Update comments --- autoload/lsp/buffer.vim | 10 ++++----- autoload/lsp/callhierarchy.vim | 4 ++-- autoload/lsp/codeaction.vim | 4 ++-- autoload/lsp/completion.vim | 10 ++++----- autoload/lsp/diag.vim | 23 ++++++++++++--------- autoload/lsp/handlers.vim | 4 ++-- autoload/lsp/lsp.vim | 6 +++--- autoload/lsp/lspserver.vim | 4 ++-- autoload/lsp/symbol.vim | 4 ++-- autoload/lsp/typehierarchy.vim | 5 +++-- autoload/lsp/util.vim | 17 ++++++++-------- doc/lsp.txt | 4 +++- test/clangd_tests.vim | 37 ++++++++++++++++++++++++++++++++-- 13 files changed, 87 insertions(+), 45 deletions(-) diff --git a/autoload/lsp/buffer.vim b/autoload/lsp/buffer.vim index 62d5915..2d39a19 100644 --- a/autoload/lsp/buffer.vim +++ b/autoload/lsp/buffer.vim @@ -84,7 +84,7 @@ export def BufLspServerGet(bnr: number, feature: string = null_string): dicthas_key(feature) && lspserver.features[feature] return lspserver @@ -102,7 +102,7 @@ export def BufLspServerGet(bnr: number, feature: string = null_string): dict if !bufnrToServers->has_key(bnr) @@ -118,7 +118,7 @@ export def BufLspServerGetById(bnr: number, id: number): dict return {} enddef -# Returns the LSP servers for the buffer 'bnr'. Returns an empty list if the +# Returns the LSP servers for the buffer "bnr". Returns an empty list if the # servers are not found. export def BufLspServersGet(bnr: number): list> if !bufnrToServers->has_key(bnr) @@ -128,7 +128,7 @@ export def BufLspServersGet(bnr: number): list> return bufnrToServers[bnr] enddef -# Returns the LSP server for the current buffer with the optionally 'feature'. +# Returns the LSP server for the current buffer with the optionally "feature". # Returns an empty dict if the server is not found. export def CurbufGetServer(feature: string = null_string): dict return BufLspServerGet(bufnr(), feature) @@ -146,7 +146,7 @@ export def BufHasLspServer(bnr: number): bool return !lspserver->empty() enddef -# Returns the LSP server for the current buffer with the optinally 'feature' if +# Returns the LSP server for the current buffer with the optinally "feature" if # it is running and is ready. # Returns an empty dict if the server is not found or is not ready. export def CurbufGetServerChecked(feature: string = null_string): dict diff --git a/autoload/lsp/callhierarchy.vim b/autoload/lsp/callhierarchy.vim index e91d08b..aa2ed40 100644 --- a/autoload/lsp/callhierarchy.vim +++ b/autoload/lsp/callhierarchy.vim @@ -12,7 +12,7 @@ def CallHierarchyItemJump() util.JumpToLspLocation(item, '') enddef -# Refresh the call hierarchy tree for the symbol at index 'idx'. +# Refresh the call hierarchy tree for the symbol at index "idx". def CallHierarchyTreeItemRefresh(idx: number) var treeItem: dict = w:LspCallHierItemMap[idx] @@ -22,7 +22,7 @@ def CallHierarchyTreeItemRefresh(idx: number) endif if !treeItem->has_key('children') - # First time retrieving the children for the item at index 'idx' + # First time retrieving the children for the item at index "idx" var lspserver = buf.BufLspServerGet(w:LspBufnr) if lspserver->empty() || !lspserver.running return diff --git a/autoload/lsp/codeaction.vim b/autoload/lsp/codeaction.vim index 3f103e7..9aa9c9a 100644 --- a/autoload/lsp/codeaction.vim +++ b/autoload/lsp/codeaction.vim @@ -30,8 +30,8 @@ export def HandleCodeAction(lspserver: dict, selAction: dict) # textDocument/codeAction can return either Command[] or CodeAction[]. # If it is a CodeAction, it can have either an edit, a command or both. # Edits should be executed first. - # Both Command and CodeAction interfaces has 'command' member - # so we should check 'command' type - for Command it will be 'string' + # Both Command and CodeAction interfaces has "command" member + # so we should check "command" type - for Command it will be "string" if selAction->has_key('edit') || (selAction->has_key('command') && selAction.command->type() == v:t_dict) # selAction is a CodeAction instance, apply edit and command diff --git a/autoload/lsp/completion.vim b/autoload/lsp/completion.vim index e7fd324..711f198 100644 --- a/autoload/lsp/completion.vim +++ b/autoload/lsp/completion.vim @@ -39,13 +39,13 @@ var defaultKinds: dict = { 'Buffer': 'B', } -# Returns true if omni-completion is enabled for filetype 'ftype'. +# Returns true if omni-completion is enabled for filetype "ftype". # Otherwise, returns false. def LspOmniComplEnabled(ftype: string): bool return ftypeOmniCtrlMap->get(ftype, false) enddef -# Enables or disables omni-completion for filetype 'fype' +# Enables or disables omni-completion for filetype "fype" export def OmniComplSet(ftype: string, enabled: bool) ftypeOmniCtrlMap->extend({[ftype]: enabled}) enddef @@ -96,7 +96,7 @@ def LspCompleteItemKindChar(kind: number): string return kindValue enddef -# Remove all the snippet placeholders from 'str' and return the value. +# Remove all the snippet placeholders from "str" and return the value. # Based on a similar function in the vim-lsp plugin. def MakeValidWord(str_arg: string): string var str = str_arg->substitute('\$[0-9]\+\|\${\%(\\.\|[^}]\)\+}', '', 'g') @@ -596,8 +596,8 @@ def LspResolve() endif enddef -# If the completion popup documentation window displays 'markdown' content, -# then set the 'filetype' to 'lspgfm'. +# If the completion popup documentation window displays "markdown" content, +# then set the 'filetype' to "lspgfm". def LspSetPopupFileType() var item = v:event.completed_item if !item->has_key('user_data') || item.user_data->empty() diff --git a/autoload/lsp/diag.vim b/autoload/lsp/diag.vim index 9eaa30c..97556d7 100644 --- a/autoload/lsp/diag.vim +++ b/autoload/lsp/diag.vim @@ -99,7 +99,7 @@ def SortDiags(diags: list>): list> }) enddef -# Remove the diagnostics stored for buffer 'bnr' +# Remove the diagnostics stored for buffer "bnr" export def DiagRemoveFile(bnr: number) if diagsMap->has_key(bnr) diagsMap->remove(bnr) @@ -160,7 +160,7 @@ def RemoveDiagVisualsForBuffer(bnr: number) endif enddef -# Refresh the placed diagnostics in buffer 'bnr' +# Refresh the placed diagnostics in buffer "bnr" # This inline signs, inline props, and virtual text diagnostics def DiagsRefresh(bnr: number) bnr->bufload() @@ -266,9 +266,7 @@ enddef # New LSP diagnostic messages received from the server for a file. # Update the signs placed in the buffer for this file export def ProcessNewDiags(bnr: number) - if opt.lspOptions.autoPopulateDiags - DiagsUpdateLocList(bnr) - endif + DiagsUpdateLocList(bnr) if opt.lspOptions.aleSupport SendAleDiags(bnr, -1) @@ -417,14 +415,21 @@ enddef # Update the location list window for the current window with the diagnostic # messages. # Returns true if diagnostics is not empty and false if it is empty. -def DiagsUpdateLocList(bnr: number): bool +def DiagsUpdateLocList(bnr: number, calledByCmd: bool = false): bool var fname: string = bnr->bufname()->fnamemodify(':p') if fname->empty() return false endif var LspQfId: number = bnr->getbufvar('LspQfId', 0) + if LspQfId->empty() && !opt.lspOptions.autoPopulateDiags && !calledByCmd + # If a location list for the diagnostics was not opened previously, + # and 'autoPopulateDiags' is set to false, then do nothing. + return false + endif + if !LspQfId->empty() && getloclist(0, {id: LspQfId}).id != LspQfId + # Previously used location list for the diagnostics is gone LspQfId = 0 endif @@ -468,7 +473,7 @@ enddef # Display the diagnostic messages from the LSP server for the current buffer # in a location list export def ShowAllDiags(): void - if !DiagsUpdateLocList(bufnr()) + if !DiagsUpdateLocList(bufnr(), true) util.WarnMsg($'No diagnostic messages found for {@%}') return endif @@ -484,7 +489,7 @@ export def ShowAllDiags(): void endif enddef -# Display the message of 'diag' in a popup window right below the position in +# Display the message of "diag" in a popup window right below the position in # the diagnostic message. def ShowDiagInPopup(diag: dict) var dlnum = diag.range.start.line + 1 @@ -527,7 +532,7 @@ def ShowDiagInPopup(diag: dict) popup_create(msg, ppopts) enddef -# Display the 'diag' message in a popup or in the status message area +# Display the "diag" message in a popup or in the status message area def DisplayDiag(diag: dict) if opt.lspOptions.showDiagInPopup # Display the diagnostic message in a popup window. diff --git a/autoload/lsp/handlers.vim b/autoload/lsp/handlers.vim index e213c16..9a04cb6 100644 --- a/autoload/lsp/handlers.vim +++ b/autoload/lsp/handlers.vim @@ -97,8 +97,8 @@ export def ProcessNotif(lspserver: dict, reply: dict): void '$/progress', '$/status/report', '$/status/show', - # PHP intelephense server sends the 'indexingStarted' and - # 'indexingEnded' notifications which is not in the LSP specification. + # PHP intelephense server sends the "indexingStarted" and + # "indexingEnded" notifications which is not in the LSP specification. 'indexingStarted', 'indexingEnded', # Java language server sends the 'language/status' notification which is diff --git a/autoload/lsp/lsp.vim b/autoload/lsp/lsp.vim index 8c3859f..b66d9f3 100644 --- a/autoload/lsp/lsp.vim +++ b/autoload/lsp/lsp.vim @@ -168,7 +168,7 @@ export def ShowAllServers() :setlocal nomodifiable enddef -# Create a new window containing the buffer 'bname' or if the window is +# Create a new window containing the buffer "bname" or if the window is # already present then jump to it. def OpenScratchWindow(bname: string) var wid = bufwinid(bname) @@ -254,7 +254,7 @@ def ShowServer(arg: string) endif enddef -# Get LSP server running status for filetype 'ftype' +# Get LSP server running status for filetype "ftype" # Return true if running, or false if not found or not running export def ServerRunning(ftype: string): bool if ftypeServerMap->has_key(ftype) @@ -701,7 +701,7 @@ export def AddServer(serverList: list>) enddef # The LSP server is considered ready when the server capabilities are -# received ('initialize' LSP reply message) +# received ("initialize" LSP reply message) export def ServerReady(): bool var fname: string = @% if fname->empty() diff --git a/autoload/lsp/lspserver.vim b/autoload/lsp/lspserver.vim index 78d8141..8ccf2f5 100644 --- a/autoload/lsp/lspserver.vim +++ b/autoload/lsp/lspserver.vim @@ -91,7 +91,7 @@ def StartServer(lspserver: dict, bnr: number): number return 0 enddef -# process the 'initialize' method reply from the LSP server +# process the "initialize" method reply from the LSP server # Result: InitializeResult def ServerInitReply(lspserver: dict, initResult: dict): void if initResult->empty() @@ -148,7 +148,7 @@ def ServerInitReply(lspserver: dict, initResult: dict): void endif enddef -# Request: 'initialize' +# Request: "initialize" # Param: InitializeParams def InitServer(lspserver: dict, bnr: number) # interface 'InitializeParams' diff --git a/autoload/lsp/symbol.vim b/autoload/lsp/symbol.vim index 761ef18..177c761 100644 --- a/autoload/lsp/symbol.vim +++ b/autoload/lsp/symbol.vim @@ -426,8 +426,8 @@ def SymbolFilterCB(lspserver: dict, id: number, key: string): bool return false enddef -# Display the file specified by LSP 'LocationLink' in a popup window and -# highlight the range in 'location'. +# Display the file specified by LSP "LocationLink" in a popup window and +# highlight the range in "location". def PeekSymbolLocation(lspserver: dict, location: dict) var [uri, range] = util.LspLocationParse(location) var fname = util.LspUriToFile(uri) diff --git a/autoload/lsp/typehierarchy.vim b/autoload/lsp/typehierarchy.vim index 0464ec8..8786b1b 100644 --- a/autoload/lsp/typehierarchy.vim +++ b/autoload/lsp/typehierarchy.vim @@ -5,7 +5,7 @@ vim9script import './util.vim' import './symbol.vim' -# Parse the type hierarchy in 'typeHier' and displays a tree of type names +# Parse the type hierarchy in "typeHier" and displays a tree of type names # in the current buffer. This function is called recursively to display the # super/sub type hierarchy. # @@ -135,7 +135,8 @@ def TypeHierPopupCallback(lspserver: dict, typeUriMap: list>, util.JumpToLspLocation(typeUriMap[selIdx - 1], '') enddef -# Show the super or sub type hierarchy items 'types' as a tree in a popup window +# Show the super or sub type hierarchy items "types" as a tree in a popup +# window export def ShowTypeHierarchy(lspserver: dict, isSuper: bool, types: dict) if lspserver.typeHierPopup->winbufnr() != -1 diff --git a/autoload/lsp/util.vim b/autoload/lsp/util.vim index 708e8b8..a63953c 100644 --- a/autoload/lsp/util.vim +++ b/autoload/lsp/util.vim @@ -154,7 +154,7 @@ export def LspBufnrToUri(bnr: number): string return LspFileToUri(bnr->bufname()) enddef -# Returns the byte number of the specified LSP position in buffer 'bnr'. +# Returns the byte number of the specified LSP position in buffer "bnr". # LSP's line and characters are 0-indexed. # Vim's line and columns are 1-indexed. # Returns a zero-indexed column. @@ -253,9 +253,9 @@ export def PushCursorToTagStack() }]}, 't') enddef -# Jump to the LSP 'location'. The 'location' contains the file name, line +# Jump to the LSP "location". The "location" contains the file name, line # number and character number. The user specified window command modifiers -# (e.g. topleft) are in 'cmdmods'. +# (e.g. topleft) are in "cmdmods". export def JumpToLspLocation(location: dict, cmdmods: string) var [uri, range] = LspLocationParse(location) var fname = LspUriToFile(uri) @@ -300,7 +300,8 @@ export def JumpToLspLocation(location: dict, cmdmods: string) GetCharIdxWithoutCompChar(bufnr(), range.start) + 1) enddef -# 'indexof' is to new to use it, use this instead. +# indexof() function is not present in older Vim 9 versions. So use this +# function. export def Indexof(list: list, CallbackFn: func(number, any): bool): number var ix = 0 for val in list @@ -313,12 +314,12 @@ export def Indexof(list: list, CallbackFn: func(number, any): bool): number enddef # Find the nearest root directory containing a file or directory name from the -# list of names in 'files' starting with the directory 'startDir'. +# list of names in "files" starting with the directory "startDir". # Based on a similar implementation in the vim-lsp plugin. -# Searches upwards starting with the directory 'startDir'. +# Searches upwards starting with the directory "startDir". # If a file name ends with '/' or '\', then it is a directory name, otherwise # it is a file name. -# Returns '' if none of the file and directory names in 'files' can be found +# Returns '' if none of the file and directory names in "files" can be found # in one of the parent directories. export def FindNearestRootDir(startDir: string, files: list): string var foundDirs: dict = {} @@ -349,7 +350,7 @@ export def FindNearestRootDir(startDir: string, files: list): string return b->len() - a->len() }) - # choose the longest matching path (the nearest directory from 'startDir') + # choose the longest matching path (the nearest directory from "startDir") return sortedList[0] enddef diff --git a/doc/lsp.txt b/doc/lsp.txt index bd774c4..55d0995 100644 --- a/doc/lsp.txt +++ b/doc/lsp.txt @@ -1183,7 +1183,9 @@ the current line. The |:LspDiagShow| command creates a new location list with the current list of diagnostics for the current buffer. To automatically add the diagnostics messages to the location list, you can set the 'autoPopulateDiags' option to -true. By default this option is set to false. +true.  By default this option is set to false.  When new diagnostics are +received for a buffer, if a location list with the diagnostics is already +present, then it is refreshed with the new diagnostics. When using GUI Vim or in a terminal Vim with 'ballooneval' option set, when the mouse is moved over the diagnostic sign displayed in the sign column, then diff --git a/test/clangd_tests.vim b/test/clangd_tests.vim index 62a832e..cc375af 100644 --- a/test/clangd_tests.vim +++ b/test/clangd_tests.vim @@ -369,6 +369,41 @@ def g:Test_LspProcessDiagHandler() :%bw! enddef +# Diag location list should be automatically updated when the list of diags +# changes. +def g:Test_DiagLocListAutoUpdate() + :silent! edit XdiagLocListAutoUpdate.c + :sleep 200m + setloclist(0, [], 'f') + var lines: list =<< trim END + int i: + int j; + END + setline(1, lines) + var bnr = bufnr() + g:WaitForServerFileLoad(1) + :redraw! + + :LspDiagShow + assert_equal(1, line('$')) + wincmd w + setline(2, 'int j:') + redraw! + g:WaitForDiags(2) + wincmd w + assert_equal(2, line('$')) + wincmd w + deletebufline('', 1, '$') + redraw! + g:WaitForDiags(0) + wincmd w + assert_equal([''], getline(1, '$')) + :lclose + + setloclist(0, [], 'f') + :%bw! +enddef + # Test that the client have been able to configure the server to speak utf-32 def g:Test_UnicodeColumnCalc() :silent! edit XUnicodeColumn.c @@ -1068,8 +1103,6 @@ def g:Test_LspHover() popup_clear() :%bw! - - enddef # Test for :LspShowSignature -- 2.48.1