From a6341cf42eb4ca1087ed48f9ed4922f88dd5d9e2 Mon Sep 17 00:00:00 2001 From: Yegappan Lakshmanan Date: Fri, 14 Oct 2022 19:09:04 -0700 Subject: [PATCH] Use sync RPC for the LspIncomingCalls and LspOutgoingCalls commands. Add a test for the :LspIncomingCalls command. Use clangd-14 for github CI --- .github/workflows/unitests.yml | 2 +- autoload/lsp/handlers.vim | 60 ----------------------- autoload/lsp/lsp.vim | 27 +---------- autoload/lsp/lspserver.vim | 87 +++++++++++++++++++++------------- test/unit_tests.vim | 34 ++++++++++++- 5 files changed, 90 insertions(+), 120 deletions(-) diff --git a/.github/workflows/unitests.yml b/.github/workflows/unitests.yml index 1009b0a..eea4ac2 100644 --- a/.github/workflows/unitests.yml +++ b/.github/workflows/unitests.yml @@ -7,7 +7,7 @@ jobs: steps: - name: Install packages run: | - sudo apt update && sudo apt install -y clangd-12 + sudo apt update && sudo apt install -y clangd-14 - name: Setup Vim uses: rhysd/action-setup-vim@v1 id: vim diff --git a/autoload/lsp/handlers.vim b/autoload/lsp/handlers.vim index 5f808a5..bdb2a5b 100644 --- a/autoload/lsp/handlers.vim +++ b/autoload/lsp/handlers.vim @@ -55,11 +55,6 @@ def ProcessInitializeReply(lspserver: dict, req: dict, reply: dict, req: dict, reply: dict): void - return -enddef - # process the 'textDocument/signatureHelp' reply from the LSP server # Result: SignatureHelp | null def ProcessSignaturehelpReply(lspserver: dict, req: dict, reply: dict): void @@ -505,63 +500,11 @@ def ProcessWorkspaceSymbolReply(lspserver: dict, req: dict, reply: dic symbols->copy()->mapnew('v:val.name')) enddef -# process the 'textDocument/prepareCallHierarchy' reply from the LSP server -# Result: CallHierarchyItem[] | null -def ProcessPrepareCallHierarchy(lspserver: dict, req: dict, reply: dict) - if reply.result->empty() - if lspserver.callHierarchyType == 'incoming' - util.WarnMsg('No incoming calls') - else - util.WarnMsg('No outgoing calls') - endif - return - endif - - var choice: number = 1 - if reply.result->len() > 1 - var items: list = ['Select a Call Hierarchy Item:'] - for i in range(reply.result->len()) - items->add(printf("%d. %s", i + 1, reply.result[i].name)) - endfor - choice = inputlist(items) - if choice < 1 || choice > items->len() - return - endif - endif - - if lspserver.callHierarchyType == 'incoming' - g:LspGetIncomingCalls(reply.result[choice - 1]) - else - g:LspGetOutgoingCalls(reply.result[choice - 1]) - endif -enddef - -# process the 'callHierarchy/incomingCalls' reply from the LSP server -# Result: CallHierarchyIncomingCall[] | null -def ProcessIncomingCalls(lspserver: dict, req: dict, reply: dict) - if reply.result->empty() - return - endif - - callhier.IncomingCalls(reply.result) -enddef - -# process the 'callHierarchy/outgoingCalls' reply from the LSP server -# Result: CallHierarchyOutgoingCall[] | null -def ProcessOutgoingCalls(lspserver: dict, req: dict, reply: dict) - if reply.result->empty() - return - endif - - callhier.OutgoingCalls(reply.result) -enddef - # Process various reply messages from the LSP server export def ProcessReply(lspserver: dict, req: dict, reply: dict): void var lsp_reply_handlers: dict = { 'initialize': ProcessInitializeReply, - 'shutdown': ProcessShutdownReply, 'textDocument/signatureHelp': ProcessSignaturehelpReply, 'textDocument/completion': ProcessCompletionReply, 'textDocument/hover': ProcessHoverReply, @@ -571,9 +514,6 @@ export def ProcessReply(lspserver: dict, req: dict, reply: dict): 'textDocument/foldingRange': ProcessFoldingRangeReply, 'workspace/executeCommand': ProcessWorkspaceExecuteReply, 'workspace/symbol': ProcessWorkspaceSymbolReply, - 'textDocument/prepareCallHierarchy': ProcessPrepareCallHierarchy, - 'callHierarchy/incomingCalls': ProcessIncomingCalls, - 'callHierarchy/outgoingCalls': ProcessOutgoingCalls } if lsp_reply_handlers->has_key(req.method) diff --git a/autoload/lsp/lsp.vim b/autoload/lsp/lsp.vim index d1e1c0d..199a915 100644 --- a/autoload/lsp/lsp.vim +++ b/autoload/lsp/lsp.vim @@ -701,30 +701,9 @@ export def IncomingCalls() return endif - lspserver.callHierarchyType = 'incoming' - var fname: string = @% - lspserver.prepareCallHierarchy(fname) + lspserver.incomingCalls(@%) enddef -def g:LspGetIncomingCalls(item: dict) - var lspserver: dict = CurbufGetServerChecked() - if lspserver->empty() - return - endif - - lspserver.incomingCalls(item) -enddef - -def g:LspGetOutgoingCalls(item: dict) - var lspserver: dict = CurbufGetServerChecked() - if lspserver->empty() - return - endif - - lspserver.outgoingCalls(item) -enddef - - # Display all the symbols used by the current symbol. # Uses LSP "callHierarchy/outgoingCalls" request export def OutgoingCalls() @@ -733,9 +712,7 @@ export def OutgoingCalls() return endif - lspserver.callHierarchyType = 'outgoing' - var fname: string = @% - lspserver.prepareCallHierarchy(fname) + lspserver.outgoingCalls(@%) enddef # Rename a symbol diff --git a/autoload/lsp/lspserver.vim b/autoload/lsp/lspserver.vim index 8d9dc8e..82a9e7f 100644 --- a/autoload/lsp/lspserver.vim +++ b/autoload/lsp/lspserver.vim @@ -10,6 +10,7 @@ import './diag.vim' import './selection.vim' import './symbol.vim' import './textedit.vim' +import './callhierarchy.vim' as callhier # LSP server standard output handler def Output_cb(lspserver: dict, chan: channel, msg: any): void @@ -769,26 +770,34 @@ def TextDocFormat(lspserver: dict, fname: string, rangeFormat: bool, enddef # Request: "textDocument/prepareCallHierarchy" -# Param: CallHierarchyPrepareParams -def PrepareCallHierarchy(lspserver: dict, fname: string) - # Check whether LSP server supports call hierarchy - if !lspserver.caps->has_key('callHierarchyProvider') - || !lspserver.caps.callHierarchyProvider - util.ErrMsg("Error: LSP server does not support call hierarchy") - return +def PrepareCallHierarchy(lspserver: dict): dict + # interface CallHierarchyPrepareParams + # interface TextDocumentPositionParams + var param: dict + param = GetLspTextDocPosition() + var reply = lspserver.rpc('textDocument/prepareCallHierarchy', param) + if reply->empty() || reply.result->empty() + return {} endif - var req = lspserver.createRequest('textDocument/prepareCallHierarchy') + # Result: CallHierarchyItem[] | null + var choice: number = 1 + if reply.result->len() > 1 + var items: list = ['Select a Call Hierarchy Item:'] + for i in range(reply.result->len()) + items->add(printf("%d. %s", i + 1, reply.result[i].name)) + endfor + choice = inputlist(items) + if choice < 1 || choice > items->len() + return {} + endif + endif - # interface CallHierarchyPrepareParams - # interface TextDocumentPositionParams - req.params->extend(GetLspTextDocPosition()) - lspserver.sendMessage(req) + return reply.result[choice - 1] enddef # Request: "callHierarchy/incomingCalls" -# Param: CallHierarchyItem -def IncomingCalls(lspserver: dict, hierItem: dict) +def IncomingCalls(lspserver: dict, fname: string) # Check whether LSP server supports call hierarchy if !lspserver.caps->has_key('callHierarchyProvider') || !lspserver.caps.callHierarchyProvider @@ -796,21 +805,27 @@ def IncomingCalls(lspserver: dict, hierItem: dict) return endif - var req = lspserver.createRequest('callHierarchy/incomingCalls') + var reply = PrepareCallHierarchy(lspserver) + if reply->empty() + util.WarnMsg('No incoming calls') + return + endif - # interface CallHierarchyIncomingCallsParams - # interface CallHierarchyItem - req.params->extend({item: hierItem}) - lspserver.sendMessage(req) - if exists('g:LSPTest') && g:LSPTest - # When running LSP tests, make this a synchronous call - lspserver.waitForResponse(req) + # Request: "callHierarchy/incomingCalls" + # Param: CallHierarchyIncomingCallsParams + var param = {} + param.item = reply + reply = lspserver.rpc('callHierarchy/incomingCalls', param) + if reply->empty() || reply.result->empty() + util.WarnMsg('No incoming calls') + return endif + + callhier.IncomingCalls(reply.result) enddef # Request: "callHierarchy/outgoingCalls" -# Param: CallHierarchyItem -def OutgoingCalls(lspserver: dict, hierItem: dict) +def OutgoingCalls(lspserver: dict, fname: string) # Check whether LSP server supports call hierarchy if !lspserver.caps->has_key('callHierarchyProvider') || !lspserver.caps.callHierarchyProvider @@ -818,16 +833,23 @@ def OutgoingCalls(lspserver: dict, hierItem: dict) return endif - var req = lspserver.createRequest('callHierarchy/outgoingCalls') + var reply = PrepareCallHierarchy(lspserver) + if reply->empty() + util.WarnMsg('No outgoing calls') + return + endif - # interface CallHierarchyOutgoingCallsParams - # interface CallHierarchyItem - req.params->extend({item: hierItem}) - lspserver.sendMessage(req) - if exists('g:LSPTest') && g:LSPTest - # When running LSP tests, make this a synchronous call - lspserver.waitForResponse(req) + # Request: "callHierarchy/outgoingCalls" + # Param: CallHierarchyOutgoingCallsParams + var param = {} + param.item = reply + reply = lspserver.rpc('callHierarchy/outgoingCalls', param) + if reply->empty() || reply.result->empty() + util.WarnMsg('No outgoing calls') + return endif + + callhier.OutgoingCalls(reply.result) enddef # Request: "textDocument/rename" @@ -1120,7 +1142,6 @@ export def NewLspServer(path: string, args: list, isSync: bool, initiali docHighlight: function(DocHighlight, [lspserver]), getDocSymbols: function(GetDocSymbols, [lspserver]), textDocFormat: function(TextDocFormat, [lspserver]), - prepareCallHierarchy: function(PrepareCallHierarchy, [lspserver]), incomingCalls: function(IncomingCalls, [lspserver]), outgoingCalls: function(OutgoingCalls, [lspserver]), renameSymbol: function(RenameSymbol, [lspserver]), diff --git a/test/unit_tests.vim b/test/unit_tests.vim index cf5fb77..5489dfc 100644 --- a/test/unit_tests.vim +++ b/test/unit_tests.vim @@ -21,7 +21,7 @@ endif source ../plugin/lsp.vim var lspServers = [{ filetype: ['c', 'cpp'], - path: '/usr/bin/clangd-12', + path: '/usr/bin/clangd-14', args: ['--background-index', '--clang-tidy'] }] call LspAddServer(lspServers) @@ -672,6 +672,38 @@ def Test_LspShowSignature() :%bw! enddef +# Test for :LspIncomingCalls +def Test_LspIncomingCalls() + silent! edit Xtest.c + sleep 200m + var lines: list =<< trim END + void xFunc(void) + { + } + + void aFunc(void) + { + xFunc(); + } + + void bFunc(void) + { + xFunc(); + } + END + setline(1, lines) + :sleep 1 + cursor(1, 6) + :LspIncomingCalls + assert_equal(2, winnr('$')) + var l = getloclist(0) + assert_equal([7, 3], [l[0].lnum, l[0].col]) + assert_equal('aFunc: xFunc();', l[0].text) + assert_equal([12, 3], [l[1].lnum, l[1].col]) + assert_equal('bFunc: xFunc();', l[1].text) + :%bw! +enddef + def LspRunTests() :set nomore :set debug=beep -- 2.48.1