From 5572208af7f0930a2531f905fbc5f5a9c6973b68 Mon Sep 17 00:00:00 2001 From: Yegappan Lakshmanan Date: Sat, 15 Jan 2022 22:54:35 -0800 Subject: [PATCH] Add support for peeking symbol definition, declaration, implementation and type definition --- autoload/handlers.vim | 72 ++++++++++++++++++++++++++++-------------- autoload/lsp.vim | 16 +++++----- autoload/lspserver.vim | 31 ++++++++++++------ doc/lsp.txt | 33 +++++++++++++++++++ plugin/lsp.vim | 24 ++++++++------ 5 files changed, 126 insertions(+), 50 deletions(-) diff --git a/autoload/handlers.vim b/autoload/handlers.vim index 3a1b9b9..b13b691 100644 --- a/autoload/handlers.vim +++ b/autoload/handlers.vim @@ -105,11 +105,14 @@ enddef def s:processDefDeclReply(lspserver: dict, req: dict, reply: dict): void if reply.result->empty() util.WarnMsg("Error: definition is not found") - # pop the tag stack - var tagstack: dict = gettagstack() - if tagstack.length > 0 - settagstack(winnr(), {curidx: tagstack.length}, 't') + if !lspserver.peekDefDecl + # pop the tag stack + var tagstack: dict = gettagstack() + if tagstack.length > 0 + settagstack(winnr(), {curidx: tagstack.length}, 't') + endif endif + lspserver.peekDefDecl = false return endif @@ -120,32 +123,55 @@ def s:processDefDeclReply(lspserver: dict, req: dict, reply: dict location = reply.result endif var fname = util.LspUriToFile(location.uri) - var wid = fname->bufwinid() - if wid != -1 - wid->win_gotoid() + if lspserver.peekDefDecl + # open the definition/declaration in the preview window and highlight the + # matching symbol + exe 'pedit ' .. fname + var cur_wid = win_getid() + wincmd P + var pvwbuf = bufnr() + setcursorcharpos(location.range.start.line + 1, + location.range.start.character + 1) + silent! matchdelete(101) + var pos: list = [] + var start_col: number + var end_col: number + start_col = util.GetLineByteFromPos(pvwbuf, location.range.start) + 1 + end_col = util.GetLineByteFromPos(pvwbuf, location.range.end) + 1 + pos->add(location.range.start.line + 1) + pos->extend([start_col, end_col - start_col]) + matchaddpos('Search', [pos], 10, 101) + win_gotoid(cur_wid) else - var bnr: number = fname->bufnr() - if bnr != -1 - if &modified || &buftype != '' - exe 'sbuffer ' .. bnr - else - exe 'buf ' .. bnr - endif + # jump to the file and line containing the symbol + var wid = fname->bufwinid() + if wid != -1 + wid->win_gotoid() else - if &modified || &buftype != '' - # if the current buffer has unsaved changes, then open the file in a - # new window - exe 'split ' .. fname + var bnr: number = fname->bufnr() + if bnr != -1 + if &modified || &buftype != '' + exe 'sbuffer ' .. bnr + else + exe 'buf ' .. bnr + endif else - exe 'edit ' .. fname + if &modified || &buftype != '' + # if the current buffer has unsaved changes, then open the file in a + # new window + exe 'split ' .. fname + else + exe 'edit ' .. fname + endif endif endif - endif - # Set the previous cursor location mark - setpos("'`", getcurpos()) - setcursorcharpos(location.range.start.line + 1, + # Set the previous cursor location mark + setpos("'`", getcurpos()) + setcursorcharpos(location.range.start.line + 1, location.range.start.character + 1) + endif redraw! + lspserver.peekDefDecl = false enddef # process the 'textDocument/signatureHelp' reply from the LSP server diff --git a/autoload/lsp.vim b/autoload/lsp.vim index fdaa0eb..bd29f2c 100644 --- a/autoload/lsp.vim +++ b/autoload/lsp.vim @@ -157,7 +157,7 @@ def lsp#showServers() enddef # Go to a definition using "textDocument/definition" LSP request -def lsp#gotoDefinition() +def lsp#gotoDefinition(peek: bool) var ftype: string = &filetype if ftype == '' || @% == '' return @@ -173,11 +173,11 @@ def lsp#gotoDefinition() return endif - lspserver.gotoDefinition() + lspserver.gotoDefinition(peek) enddef # Go to a declaration using "textDocument/declaration" LSP request -def lsp#gotoDeclaration() +def lsp#gotoDeclaration(peek: bool) var ftype: string = &filetype if ftype == '' return @@ -193,11 +193,11 @@ def lsp#gotoDeclaration() return endif - lspserver.gotoDeclaration() + lspserver.gotoDeclaration(peek) enddef # Go to a type definition using "textDocument/typeDefinition" LSP request -def lsp#gotoTypedef() +def lsp#gotoTypedef(peek: bool) var ftype: string = &filetype if ftype == '' return @@ -213,11 +213,11 @@ def lsp#gotoTypedef() return endif - lspserver.gotoTypeDef() + lspserver.gotoTypeDef(peek) enddef # Go to a implementation using "textDocument/implementation" LSP request -def lsp#gotoImplementation() +def lsp#gotoImplementation(peek: bool) var ftype: string = &filetype if ftype == '' return @@ -233,7 +233,7 @@ def lsp#gotoImplementation() return endif - lspserver.gotoImplementation() + lspserver.gotoImplementation(peek) enddef # Show the signature using "textDocument/signatureHelp" LSP method diff --git a/autoload/lspserver.vim b/autoload/lspserver.vim index 32601c6..814b919 100644 --- a/autoload/lspserver.vim +++ b/autoload/lspserver.vim @@ -413,7 +413,7 @@ enddef # Request: "textDocument/definition" # Param: DefinitionParams -def s:gotoDefinition(lspserver: dict): void +def s:gotoDefinition(lspserver: dict, peek: bool): void # Check whether LSP server supports jumping to a definition if !lspserver.caps->has_key('definitionProvider') || !lspserver.caps.definitionProvider @@ -421,7 +421,10 @@ def s:gotoDefinition(lspserver: dict): void return endif - util.PushCursorToTagStack() + if !peek + util.PushCursorToTagStack() + endif + lspserver.peekDefDecl = peek var req = lspserver.createRequest('textDocument/definition') # interface DefinitionParams # interface TextDocumentPositionParams @@ -431,7 +434,7 @@ enddef # Request: "textDocument/declaration" # Param: DeclarationParams -def s:gotoDeclaration(lspserver: dict): void +def s:gotoDeclaration(lspserver: dict, peek: bool): void # Check whether LSP server supports jumping to a declaration if !lspserver.caps->has_key('declarationProvider') || !lspserver.caps.declarationProvider @@ -439,7 +442,10 @@ def s:gotoDeclaration(lspserver: dict): void return endif - util.PushCursorToTagStack() + if !peek + util.PushCursorToTagStack() + endif + lspserver.peekDefDecl = peek var req = lspserver.createRequest('textDocument/declaration') # interface DeclarationParams @@ -451,7 +457,7 @@ enddef # Request: "textDocument/typeDefinition" # Param: TypeDefinitionParams -def s:gotoTypeDef(lspserver: dict): void +def s:gotoTypeDef(lspserver: dict, peek: bool): void # Check whether LSP server supports jumping to a type definition if !lspserver.caps->has_key('typeDefinitionProvider') || !lspserver.caps.typeDefinitionProvider @@ -459,7 +465,10 @@ def s:gotoTypeDef(lspserver: dict): void return endif - util.PushCursorToTagStack() + if !peek + util.PushCursorToTagStack() + endif + lspserver.peekDefDecl = peek var req = lspserver.createRequest('textDocument/typeDefinition') # interface TypeDefinitionParams @@ -471,7 +480,7 @@ enddef # Request: "textDocument/implementation" # Param: ImplementationParams -def s:gotoImplementation(lspserver: dict): void +def s:gotoImplementation(lspserver: dict, peek: bool): void # Check whether LSP server supports jumping to a implementation if !lspserver.caps->has_key('implementationProvider') || !lspserver.caps.implementationProvider @@ -479,7 +488,10 @@ def s:gotoImplementation(lspserver: dict): void return endif - util.PushCursorToTagStack() + if !peek + util.PushCursorToTagStack() + endif + lspserver.peekDefDecl = peek var req = lspserver.createRequest('textDocument/implementation') # interface ImplementationParams @@ -839,7 +851,8 @@ export def NewLspServer(path: string, args: list): dict completionTriggerChars: [], diagsMap: {}, workspaceSymbolPopup: 0, - workspaceSymbolQuery: '' + workspaceSymbolQuery: '', + peekDefDecl: false } # Add the LSP server functions lspserver->extend({ diff --git a/doc/lsp.txt b/doc/lsp.txt index 2976c7b..49fb602 100644 --- a/doc/lsp.txt +++ b/doc/lsp.txt @@ -73,6 +73,14 @@ The following commands are provided: :LspGotoDeclaration Go to the declaration of the symbol under cursor :LspGotoTypeDef Go to the type definition of the symbol under cursor :LspGotoImpl Go to the implementation of the symbol under cursor +:LspPeekDefinition Open the definition of the symbol under cursor in the + preview window. +:LspPeekDeclaration Open the declaration of the symbol under cursor in the + preview window. +:LspPeekTypeDef Open the type definition of the symbol under cursor in + the preview window. +:LspPeekImpl Open the implementation of the symbol under cursor in + the preview window. :LspShowSignature Display the signature of the symbol under cursor. :LspDiagShow Display the diagnostics messages from the LSP server for the current buffer in a location list. @@ -233,6 +241,31 @@ diagnostic messages, you can add the following line to your .vimrc file: |:LspGotoDefinition| command. Note that not all the LSP servers support this feature. + *:LspPeekDefinition* +:LspPeekDefinition Displays the line where the symbol under the cursor is + defined in the |preview-window|. The symbol is + highlighted in the preview window. + + *:LspPeekDeclaration* +:LspPeekDeclaration Displays the line where the symbol under the + cursor is declared in the |preview-window|. The + behavior of this command is similar to the + |:LspPeekDefinition| command. + + *:LspPeekTypeDef* +:LspPeekTypeDef Displays the line where the type of the symbol under + the cursor is defined in the |preview-window|. The + behavior of this command is similar to the + |:LspPeekDefinition| command. Note that not all the + LSP servers support this feature. + + *:LspPeekImpl* +:LspPeekImpl Displays the implementation of the symbol under the + cursor in the |preview-window|. The behavior of this + command is similar to the |:LspPeekDefinition| + command. Note that not all the LSP servers support + this feature. + *:LspShowSignature* :LspShowSignature Displays the signature of the symbol (e.g. a function or method) before the cursor in a popup. diff --git a/plugin/lsp.vim b/plugin/lsp.vim index 8683e63..133415c 100644 --- a/plugin/lsp.vim +++ b/plugin/lsp.vim @@ -20,10 +20,14 @@ augroup END " LSP commands command! -nargs=0 -bar LspShowServers call lsp#showServers() command! -nargs=1 -bar LspSetTrace call lsp#setTraceServer() -command! -nargs=0 -bar LspGotoDefinition call lsp#gotoDefinition() -command! -nargs=0 -bar LspGotoDeclaration call lsp#gotoDeclaration() -command! -nargs=0 -bar LspGotoTypeDef call lsp#gotoTypedef() -command! -nargs=0 -bar LspGotoImpl call lsp#gotoImplementation() +command! -nargs=0 -bar LspGotoDefinition call lsp#gotoDefinition(v:false) +command! -nargs=0 -bar LspGotoDeclaration call lsp#gotoDeclaration(v:false) +command! -nargs=0 -bar LspGotoTypeDef call lsp#gotoTypedef(v:false) +command! -nargs=0 -bar LspGotoImpl call lsp#gotoImplementation(v:false) +command! -nargs=0 -bar LspPeekDefinition call lsp#gotoDefinition(v:true) +command! -nargs=0 -bar LspPeekDeclaration call lsp#gotoDeclaration(v:true) +command! -nargs=0 -bar LspPeekTypeDef call lsp#gotoTypedef(v:true) +command! -nargs=0 -bar LspPeekImpl call lsp#gotoImplementation(v:true) command! -nargs=0 -bar LspShowSignature call lsp#showSignature() command! -nargs=0 -bar LspDiagShow call lsp#showDiagnostics() command! -nargs=0 -bar LspDiagCurrent call lsp#showCurrentDiag() @@ -49,10 +53,10 @@ command! -nargs=1 -bar -complete=dir LspWorkspaceRemoveFolder call lsp#removeWor " Add the GUI menu entries if has('gui_running') - anoremenu L&sp.Goto.Definition :call lsp#gotoDefinition() - anoremenu L&sp.Goto.Declaration :call lsp#gotoDeclaration() - anoremenu L&sp.Goto.Implementation :call lsp#gotoImplementation() - anoremenu L&sp.Goto.TypeDef :call lsp#gotoTypedef() + anoremenu L&sp.Goto.Definition :call lsp#gotoDefinition(v:false) + anoremenu L&sp.Goto.Declaration :call lsp#gotoDeclaration(v:false) + anoremenu L&sp.Goto.Implementation :call lsp#gotoImplementation(v:false) + anoremenu L&sp.Goto.TypeDef :call lsp#gotoTypedef(v:false) anoremenu L&sp.Show\ Signature :call lsp#showSignature() anoremenu L&sp.Show\ References :call lsp#showReferences() @@ -77,9 +81,9 @@ if has('gui_running') if &mousemodel =~ 'popup' anoremenu PopUp.L&sp.Go\ to\ Definition - \ :call lsp#gotoDefinition() + \ :call lsp#gotoDefinition(v:false) anoremenu PopUp.L&sp.Go\ to\ Declaration - \ :call lsp#gotoDeclaration() + \ :call lsp#gotoDeclaration(v:false) anoremenu Popup.L&sp.Find\ All\ References \ :call lsp#showReferences() anoremenu PopUp.L&sp.Show\ Detail -- 2.48.1