prop_type_add('LspTextRef', {'highlight': 'Search'})
prop_type_add('LspReadRef', {'highlight': 'DiffChange'})
prop_type_add('LspWriteRef', {'highlight': 'DiffDelete'})
+
set ballooneval balloonevalterm
lspInitializedOnce = true
enddef
lspserver.outgoingCalls(@%)
enddef
+# Display the type hierarchy for the current symbol. Direction is 0 for
+# sub types and 1 for super types.
+export def TypeHierarchy(direction: number)
+ var lspserver: dict<any> = buf.CurbufGetServerChecked()
+ if lspserver->empty()
+ return
+ endif
+
+ lspserver.typeHierarchy(direction)
+enddef
+
# Rename a symbol
# Uses LSP "textDocument/rename" request
export def Rename()
import './signature.vim'
import './codeaction.vim'
import './callhierarchy.vim' as callhier
+import './typehierarchy.vim' as typehier
# LSP server standard output handler
def Output_cb(lspserver: dict<any>, chan: channel, msg: any): void
lspserver.isCallHierarchyProvider = false
endif
+ # typeHierarchyProvider
+ if lspserver.caps->has_key('typeHierarchyProvider')
+ lspserver.isTypeHierarchyProvider = true
+ else
+ lspserver.isTypeHierarchyProvider = false
+ endif
+
# renameProvider
if lspserver.caps->has_key('renameProvider')
if lspserver.caps.renameProvider->type() == v:t_bool
callhier.OutgoingCalls(reply.result)
enddef
+# Request: "textDocument/typehierarchy"
+# Support the clangd version of type hierarchy retrieval method.
+# The method described in the LSP 3.17.0 standard is not supported as clangd
+# doesn't support that method.
+def TypeHiearchy(lspserver: dict<any>, direction: number)
+ # Check whether LSP server supports type hierarchy
+ if !lspserver.isTypeHierarchyProvider
+ util.ErrMsg("Error: LSP server does not support type hierarchy")
+ return
+ endif
+
+ # interface TypeHierarchy
+ # interface TextDocumentPositionParams
+ var param: dict<any>
+ param = GetLspTextDocPosition()
+ # 0: children, 1: parent, 2: both
+ param.direction = direction
+ param.resolve = 5
+ var reply = lspserver.rpc('textDocument/typeHierarchy', param)
+ if reply->empty() || reply.result->empty()
+ util.WarnMsg('No type hierarchy available')
+ return
+ endif
+
+ typehier.ShowTypeHierarchy(lspserver, direction == 1, reply.result)
+enddef
+
# Request: "textDocument/rename"
# Param: RenameParams
def RenameSymbol(lspserver: dict<any>, newName: string)
omniCompletePending: false,
completionTriggerChars: [],
signaturePopup: -1,
+ typeHierPopup: -1,
+ typeHierFilePopup: -1,
diagsMap: {},
workspaceSymbolPopup: -1,
workspaceSymbolQuery: '',
textDocFormat: function(TextDocFormat, [lspserver]),
incomingCalls: function(IncomingCalls, [lspserver]),
outgoingCalls: function(OutgoingCalls, [lspserver]),
+ typeHierarchy: function(TypeHiearchy, [lspserver]),
renameSymbol: function(RenameSymbol, [lspserver]),
codeAction: function(CodeAction, [lspserver]),
workspaceQuery: function(WorkspaceQuerySymbols, [lspserver]),
# Display or peek symbol references in a location list
export def ShowReferences(lspserver: dict<any>, refs: list<dict<any>>, peekSymbol: bool)
- if refs->empty()
- util.WarnMsg('Error: No references found')
- return
- endif
-
# create a location list with the location of the references
var qflist: list<dict<any>> = []
for loc in refs
win_execute(pwid, cmds, 'silent!')
enddef
-# Jump to the symbol in file 'fname' at 'location'. The user specified
-# window command modifiers (e.g. topleft) are in 'cmdmods'.
-def JumpToSymbolLocation(lspserver: dict<any>, fname: string,
- location: dict<any>, cmdmods: string)
- # jump to the file and line containing the symbol
- if cmdmods == ''
- var bnr: number = fname->bufnr()
- if bnr != bufnr()
- var wid = fname->bufwinid()
- if wid != -1
- wid->win_gotoid()
- else
- if bnr != -1
- # Reuse an existing buffer. If the current buffer has unsaved changes
- # and 'hidden' is not set or if the current buffer is a special
- # buffer, then open the buffer in a new window.
- if (&modified && !&hidden) || &buftype != ''
- exe $'sbuffer {bnr}'
- else
- exe $'buf {bnr}'
- endif
- else
- if (&modified && !&hidden) || &buftype != ''
- # if the current buffer has unsaved changes and 'hidden' is not set,
- # or if the current buffer is a special buffer, then open the file
- # in a new window
- exe $'split {fname}'
- else
- exe $'edit {fname}'
- endif
- endif
- endif
- endif
- else
- exe $'{cmdmods} split {fname}'
- endif
- # Set the previous cursor location mark. Instead of using setpos(), m' is
- # used so that the current location is added to the jump list.
- normal m'
- setcursorcharpos(location.range.start.line + 1,
- location.range.start.character + 1)
-enddef
-
# Jump to the definition, declaration or implementation of a symbol.
# Also, used to peek at the definition, declaration or implementation of a
# symbol.
else
# Save the current cursor location in the tag stack.
util.PushCursorToTagStack()
- JumpToSymbolLocation(lspserver, fname, location, cmdmods)
+ util.JumpToLspLocation(fname, location, cmdmods)
endif
enddef
--- /dev/null
+vim9script
+
+# Functions for dealing with type hierarchy (super types/sub types)
+
+import './util.vim'
+import './symbol.vim'
+
+# 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.
+#
+# Returns the line number where the next type name should be added.
+def TypeTreeGenerate(super: bool, typeHier: dict<any>, pfx_arg: string,
+ typeTree: list<string>, typeUriMap: list<dict<any>>)
+
+ var itemHasChildren = false
+ if super
+ if typeHier->has_key('parents') && !typeHier.parents->empty()
+ itemHasChildren = true
+ endif
+ else
+ if typeHier->has_key('children') && !typeHier.children->empty()
+ itemHasChildren = true
+ endif
+ endif
+
+ var itemBranchPfx: string
+ if itemHasChildren
+ itemBranchPfx = '▾ '
+ else
+ itemBranchPfx = pfx_arg->empty() ? '' : ' '
+ endif
+
+ var typestr: string
+ var kindstr = symbol.SymbolKindToName(typeHier.kind)
+ if kindstr != ''
+ typestr = $'{pfx_arg}{itemBranchPfx}{typeHier.name} ({kindstr[0]})'
+ else
+ typestr = $'{pfx_arg}{itemBranchPfx}{typeHier.name}'
+ endif
+ typeTree->add(typestr)
+ typeUriMap->add(typeHier)
+
+ # last item to process
+ if !itemHasChildren
+ return
+ endif
+
+ var items: list<dict<any>>
+ items = super ? typeHier.parents : typeHier.children
+
+ for item in items
+ TypeTreeGenerate(super, item, pfx_arg .. '| ', typeTree, typeUriMap)
+ endfor
+enddef
+
+# Display a popup with the file containing a type and highlight the line and
+# the type name.
+def UpdateTypeHierFileInPopup(lspserver: dict<any>, typeUriMap: list<dict<any>>)
+ if lspserver.typeHierPopup->winbufnr() == -1
+ return
+ endif
+
+ lspserver.typeHierFilePopup->popup_close()
+
+ var n = line('.', lspserver.typeHierPopup) - 1
+ var fname: string = util.LspUriToFile(typeUriMap[n].uri)
+
+ var bnr = fname->bufadd()
+ if bnr == 0
+ return
+ endif
+
+ var popupAttr = {
+ title: $"{fname->fnamemodify(':t')} ({fname->fnamemodify(':h')})",
+ wrap: false,
+ fixed: true,
+ minheight: 10,
+ maxheight: 10,
+ minwidth: winwidth(0) - 38,
+ maxwidth: winwidth(0) - 38,
+ cursorline: true,
+ border: [],
+ line: 'cursor+1',
+ col: 1
+ }
+ lspserver.typeHierFilePopup = popup_create(bnr, popupAttr)
+ var cmds =<< trim eval END
+ [{typeUriMap[n].range.start.line + 1}, 1]->cursor()
+ normal! z.
+ END
+ win_execute(lspserver.typeHierFilePopup, cmds)
+ lspserver.typeHierFilePopup->clearmatches()
+ var start_col = util.GetLineByteFromPos(bnr,
+ typeUriMap[n].selectionRange.start) + 1
+ var end_col = util.GetLineByteFromPos(bnr, typeUriMap[n].selectionRange.end)
+ var pos = [[typeUriMap[n].selectionRange.start.line + 1,
+ start_col, end_col - start_col + 1]]
+ matchaddpos('Search', pos, 10, -1, {window: lspserver.typeHierFilePopup})
+enddef
+
+def TypeHierPopupFilter(lspserver: dict<any>, typeUriMap: list<dict<any>>,
+ popupID: number, key: string): bool
+ popupID->popup_filter_menu(key)
+ if lspserver.typeHierPopup->winbufnr() == -1
+ # popup is closed
+ if lspserver.typeHierFilePopup->winbufnr() != -1
+ lspserver.typeHierFilePopup->popup_close()
+ endif
+ lspserver.typeHierFilePopup = -1
+ lspserver.typeHierPopup = -1
+ else
+ UpdateTypeHierFileInPopup(lspserver, typeUriMap)
+ endif
+
+ return true
+enddef
+
+def TypeHierPopupCallback(lspserver: dict<any>, typeUriMap: list<dict<any>>,
+ popupID: number, selIdx: number)
+ if lspserver.typeHierFilePopup->winbufnr() != -1
+ lspserver.typeHierFilePopup->popup_close()
+ endif
+ lspserver.typeHierFilePopup = -1
+ lspserver.typeHierPopup = -1
+
+ if selIdx <= 0
+ # popup is canceled
+ return
+ endif
+
+ var item = typeUriMap[selIdx - 1]
+ var fname = util.LspUriToFile(item.uri)
+ # Save the current cursor location in the tag stack.
+ util.PushCursorToTagStack()
+ util.JumpToLspLocation(fname, item, '')
+enddef
+
+# Show the super or sub type hierarchy items 'types' as a tree in a popup window
+export def ShowTypeHierarchy(lspserver: dict<any>, super: bool, types: dict<any>)
+
+ if lspserver.typeHierPopup->winbufnr() != -1
+ # If the type hierarchy popup window is already present, close it.
+ lspserver.typeHierPopup->popup_close()
+ endif
+
+ var typeTree: list<string>
+ var typeUriMap: list<dict<any>>
+
+ # Generate a tree of the type hierarchy items
+ TypeTreeGenerate(super, types, '', typeTree, typeUriMap)
+
+ # Display a popup window with the type hierarchy tree and a popup window for
+ # the file.
+ var popupAttr = {
+ title: $'{super ? "Super" : "Sub"}Type Hierarchy',
+ wrap: 0,
+ pos: 'topleft',
+ line: 'cursor+1',
+ col: winwidth(0) - 34,
+ minheight: 10,
+ maxheight: 10,
+ minwidth: 30,
+ maxwidth: 30,
+ mapping: false,
+ fixed: 1,
+ filter: function(TypeHierPopupFilter, [lspserver, typeUriMap]),
+ callback: function(TypeHierPopupCallback, [lspserver, typeUriMap])
+ }
+ lspserver.typeHierPopup = popup_menu(typeTree, popupAttr)
+ UpdateTypeHierFileInPopup(lspserver, typeUriMap)
+enddef
+
+# vim: tabstop=8 shiftwidth=2 softtabstop=2
}]}, 't')
enddef
+# Jump to the LSP 'location' in file 'fname'. The user specified
+# window command modifiers (e.g. topleft) are in 'cmdmods'.
+export def JumpToLspLocation(fname: string, location: dict<any>,
+ cmdmods: string)
+ # jump to the file and line containing the symbol
+ if cmdmods == ''
+ var bnr: number = fname->bufnr()
+ if bnr != bufnr()
+ var wid = fname->bufwinid()
+ if wid != -1
+ wid->win_gotoid()
+ else
+ if bnr != -1
+ # Reuse an existing buffer. If the current buffer has unsaved changes
+ # and 'hidden' is not set or if the current buffer is a special
+ # buffer, then open the buffer in a new window.
+ if (&modified && !&hidden) || &buftype != ''
+ exe $'sbuffer {bnr}'
+ else
+ exe $'buf {bnr}'
+ endif
+ else
+ if (&modified && !&hidden) || &buftype != ''
+ # if the current buffer has unsaved changes and 'hidden' is not set,
+ # or if the current buffer is a special buffer, then open the file
+ # in a new window
+ exe $'split {fname}'
+ else
+ exe $'edit {fname}'
+ endif
+ endif
+ endif
+ endif
+ else
+ exe $'{cmdmods} split {fname}'
+ endif
+ # Set the previous cursor location mark. Instead of using setpos(), m' is
+ # used so that the current location is added to the jump list.
+ normal m'
+ setcursorcharpos(location.range.start.line + 1,
+ location.range.start.character + 1)
+enddef
+
# vim: tabstop=8 shiftwidth=2 softtabstop=2
Author: Yegappan Lakshmanan (yegappan AT yahoo DOT com)
For Vim version 9.0 and above
-Last change: Oct 30, 2022
+Last change: Nov 19, 2022
==============================================================================
*lsp-license*
The following commands are provided:
-:LspShowServers Display the list of registered LSP servers
-:LspGotoDefinition Go to the definition of the symbol under cursor
-: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 a
- popup window.
-:LspPeekDeclaration Open the declaration of the symbol under cursor in a
- popup window.
-:LspPeekTypeDef Open the type definition of the symbol under cursor in
- a popup window.
-:LspPeekImpl Open the implementation of the symbol under cursor in
- a popup 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.
+:LspCodeAction Apply the code action supplied by the LSP server to
+ the diagnostic in the current line.
+:LspDiagCurrent Display the diagnostic message for the current line.
:LspDiagFirst Jump to the first diagnostic message for the current
buffer.
+:LspDiagHighlightDisable
+ Disable highlighting lines with a diagnostic message
+ for the current Vim session.
+:LspDiagHighlightEnable Enable highlighting lines with a diagnostic message
+ for the current Vim session.
:LspDiagNext Jump to the next diagnostic message for the current
buffer after the current line.
:LspDiagPrev Jump to the previous diagnostic message for the current
buffer before the current line.
-:LspDiagCurrent Display the diagnostic message for the current line.
-:LspDiagHighlightEnable Enable highlighting lines with a diagnostic message
- for the current Vim session.
-:LspDiagHighlightDisable
- Disable highlighting lines with a diagnostic message
- for the current Vim session.
-:LspShowReferences Display the list of references to the keyword under
- cursor in a new location list.
-:LspPeekReferences Display the list of references to the keyword under
- cursor in a location list associated with the preview
- window.
-:LspSwitchSourceHeader Switch between source and header files.
-:LspHighlight Highlight all the matches for the keyword under cursor
-:LspHighlightClear Clear all the matches highlighted by :LspHighlight
-:LspOutline Show the list of symbols defined in the current file
- in a separate window.
+:LspDiagShow Display the diagnostics messages from the LSP server
+ for the current buffer in a location list.
+:LspFold Fold the current file
:LspFormat Format the current file using the LSP server.
:{range}LspFormat Format the specified range of lines.
+:LspGotoDeclaration Go to the declaration of the symbol under cursor
+:LspGotoDefinition Go to the definition of the symbol under cursor
+:LspGotoImpl Go to the implementation of the symbol under cursor
+:LspGotoTypeDef Go to the type definition of the symbol under cursor
+:LspHighlight Highlight all the matches for the keyword under cursor
+:LspHighlightClear Clear all the matches highlighted by :LspHighlight
:LspIncomingCalls Display the list of symbols calling the current symbol
in a new location list.
:LspOutgoingCalls Display the list of symbols called by the current
symbol in a new location list.
+:LspOutline Show the list of symbols defined in the current file
+ in a separate window.
+:LspPeekDeclaration Open the declaration of the symbol under cursor in a
+ popup window.
+:LspPeekDefinition Open the definition of the symbol under cursor in a
+ popup window.
+:LspPeekImpl Open the implementation of the symbol under cursor in
+ a popup window.
+:LspPeekReferences Display the list of references to the keyword under
+ cursor in a location list associated with the preview
+ window.
+:LspPeekTypeDef Open the type definition of the symbol under cursor in
+ a popup window.
:LspRename Rename the current symbol
-:LspCodeAction Apply the code action supplied by the LSP server to
- the diagnostic in the current line.
-:LspSymbolSearch Perform a workspace wide search for a symbol
:LspSelectionExpand Expand the current symbol range visual selection
:LspSelectionShrink Shrink the current symbol range visual selection
-:LspFold Fold the current file
+:LspServerRestart Restart the LSP server for the current buffer.
+:LspShowReferences Display the list of references to the keyword under
+ cursor in a new location list.
+:LspShowServers Display the list of registered LSP servers
+:LspShowServerCapabilities
+ Display the list of capabilities of a LSP server.
+:LspShowSignature Display the signature of the symbol under cursor.
+:LspSubTypeHierarchy Display the sub type hierarchy in a popup window.
+:LspSuperTypeHierarchy Display the super type hierarchy in a popup window.
+:LspSwitchSourceHeader Switch between source and header files.
+:LspSymbolSearch Perform a workspace wide search for a symbol
:LspWorkspaceAddFolder {folder}
Add a folder to the workspace
-:LspWorkspaceRemoveFolder {folder}
- Remove a folder from the workspace
:LspWorkspaceListFolders
Show the list of folders in the workspace
-:LspShowServerCapabilities
- Display the list of capabilities of a LSP server.
-:LspServerRestart Restart the LSP server for the current buffer.
+:LspWorkspaceRemoveFolder {folder}
+ Remove a folder from the workspace
==============================================================================
4. Configuration *lsp-configuration*
You can enter a new search pattern to do a workspace
wide symbol search.
+ *:LspSuperTypeHierarchy*
+:LspSuperTypeHierarchy Show the super type hierarchy for the symbol under the
+ cursor in a popup window. The file containing the
+ type is shown in another popup window. You can jump
+ to the location where a type is defined by browsing the
+ popup menu and selecting an entry.
+
+ *:LspSubTypeHierarchy*
+:LspSubTypeHierarchy Show the sub type hierarchy for the symbol under the
+ cursor in a popup window. The file containing the
+ type is shown in another popup window. You can jump
+ to the location where a type is defined by browsing the
+ popup menu and selecting an entry.
+
*:LspHover*
:LspHover Show the documentation for the symbol under the cursor
in a popup window. If you want to show the symbol
command! -nargs=0 -bar -range=% LspFormat lsp.TextDocFormat(<range>, <line1>, <line2>)
command! -nargs=0 -bar LspOutgoingCalls lsp.OutgoingCalls()
command! -nargs=0 -bar LspIncomingCalls lsp.IncomingCalls()
+command! -nargs=0 -bar LspSuperTypeHierarchy lsp.TypeHierarchy(1)
+command! -nargs=0 -bar LspSubTypeHierarchy lsp.TypeHierarchy(0)
command! -nargs=0 -bar LspRename lsp.Rename()
command! -nargs=0 -bar -range LspCodeAction lsp.CodeAction(<line1>, <line2>)
command! -nargs=? -bar LspSymbolSearch lsp.SymbolSearch(<q-args>)