]> Sergey Matveev's repositories - vim-lsp.git/commitdiff
Add support for peeking symbol definition, declaration, implementation and type defin...
authorYegappan Lakshmanan <yegappan@yahoo.com>
Sun, 16 Jan 2022 06:54:35 +0000 (22:54 -0800)
committerYegappan Lakshmanan <yegappan@yahoo.com>
Sun, 16 Jan 2022 06:54:35 +0000 (22:54 -0800)
autoload/handlers.vim
autoload/lsp.vim
autoload/lspserver.vim
doc/lsp.txt
plugin/lsp.vim

index 3a1b9b940596e2ca5715d2389d25e8ffc4a53e76..b13b691fc135df50ed950cf97fde99bf5dd62abd 100644 (file)
@@ -105,11 +105,14 @@ enddef
 def s:processDefDeclReply(lspserver: dict<any>, req: dict<any>, reply: dict<any>): void
   if reply.result->empty()
     util.WarnMsg("Error: definition is not found")
-    # pop the tag stack
-    var tagstack: dict<any> = gettagstack()
-    if tagstack.length > 0
-      settagstack(winnr(), {curidx: tagstack.length}, 't')
+    if !lspserver.peekDefDecl
+      # pop the tag stack
+      var tagstack: dict<any> = 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<any>, req: dict<any>, reply: dict<any>
     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<number> = []
+    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
index fdaa0eb5a160edacf00bf6d2ada9d891e612c4d5..bd29f2c99cd35ab31e9e2d7a52319b90f443a474 100644 (file)
@@ -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
index 32601c6b4ae3eafdcc51a2794dd75c814d371c13..814b9194733a986b36c6684fcb3fdcd05d4b18c6 100644 (file)
@@ -413,7 +413,7 @@ enddef
 
 # Request: "textDocument/definition"
 # Param: DefinitionParams
-def s:gotoDefinition(lspserver: dict<any>): void
+def s:gotoDefinition(lspserver: dict<any>, 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<any>): 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<any>): void
+def s:gotoDeclaration(lspserver: dict<any>, 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<any>): 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<any>): void
+def s:gotoTypeDef(lspserver: dict<any>, 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<any>): 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<any>): void
+def s:gotoImplementation(lspserver: dict<any>, 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<any>): 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<string>): dict<any>
     completionTriggerChars: [],
     diagsMap: {},
     workspaceSymbolPopup: 0,
-    workspaceSymbolQuery: ''
+    workspaceSymbolQuery: '',
+    peekDefDecl: false
   }
   # Add the LSP server functions
   lspserver->extend({
index 2976c7b3acf5e2004e4fb62454159e60b930f8db..49fb602ea0f857065002f0ac197b351844c416d6 100644 (file)
@@ -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.
index 8683e639089068d7879f39e45e49bb0d3b81f521..133415c17838494c744e21e3fc9485809950bf4f 100644 (file)
@@ -20,10 +20,14 @@ augroup END
 " LSP commands
 command! -nargs=0 -bar LspShowServers call lsp#showServers()
 command! -nargs=1 -bar LspSetTrace call lsp#setTraceServer(<q-args>)
-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 <silent> L&sp.Goto.Definition :call lsp#gotoDefinition()<CR>
-  anoremenu <silent> L&sp.Goto.Declaration :call lsp#gotoDeclaration()<CR>
-  anoremenu <silent> L&sp.Goto.Implementation :call lsp#gotoImplementation()<CR>
-  anoremenu <silent> L&sp.Goto.TypeDef :call lsp#gotoTypedef()<CR>
+  anoremenu <silent> L&sp.Goto.Definition :call lsp#gotoDefinition(v:false)<CR>
+  anoremenu <silent> L&sp.Goto.Declaration :call lsp#gotoDeclaration(v:false)<CR>
+  anoremenu <silent> L&sp.Goto.Implementation :call lsp#gotoImplementation(v:false)<CR>
+  anoremenu <silent> L&sp.Goto.TypeDef :call lsp#gotoTypedef(v:false)<CR>
 
   anoremenu <silent> L&sp.Show\ Signature :call lsp#showSignature()<CR>
   anoremenu <silent> L&sp.Show\ References :call lsp#showReferences()<CR>
@@ -77,9 +81,9 @@ if has('gui_running')
 
   if &mousemodel =~ 'popup'
     anoremenu <silent> PopUp.L&sp.Go\ to\ Definition
-         \ :call lsp#gotoDefinition()<CR>
+         \ :call lsp#gotoDefinition(v:false)<CR>
     anoremenu <silent> PopUp.L&sp.Go\ to\ Declaration
-         \ :call lsp#gotoDeclaration()<CR>
+         \ :call lsp#gotoDeclaration(v:false)<CR>
     anoremenu <silent> Popup.L&sp.Find\ All\ References
          \ :call lsp#showReferences()<CR>
     anoremenu <silent> PopUp.L&sp.Show\ Detail