:LspOutline|Show the list of symbols defined in the current file in a separate window.
:LspFormat|Format the current file using the LSP server.
:{range}LspFormat|Format the specified range of lines.
-:LspCalledBy|Display the list of symbols called by the current symbol. (NOT IMPLEMENTED YET).
-:LspCalling|Display the list of symbols calling the current symbol (NOT IMPLEMENTED YET).
+:LspCalledBy|Display the list of symbols called by the current symbol.
+:LspCalling|Display the list of symbols calling the current symbol.
: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
--- /dev/null
+vim9script
+
+# Functions for dealing with call hierarchy (incoming/outgoing calls)
+
+var util = {}
+if has('patch-8.2.4019')
+ import './util.vim' as util_import
+
+ util.WarnMsg = util_import.WarnMsg
+ util.LspUriToFile = util_import.LspUriToFile
+ util.GetLineByteFromPos = util_import.GetLineByteFromPos
+else
+ import {WarnMsg,
+ LspUriToFile,
+ GetLineByteFromPos} from './util.vim'
+
+ util.WarnMsg = WarnMsg
+ util.LspUriToFile = LspUriToFile
+ util.GetLineByteFromPos = GetLineByteFromPos
+endif
+
+def s:createLoclistWithCalls(calls: list<dict<any>>, incoming: bool)
+ var qflist: list<dict<any>> = []
+
+ for item in calls
+ var fname: string
+ if incoming
+ fname = util.LspUriToFile(item.from.uri)
+ else
+ fname = util.LspUriToFile(item.to.uri)
+ endif
+ var bnr: number = fname->bufnr()
+ if bnr == -1
+ bnr = fname->bufadd()
+ endif
+ if !bnr->bufloaded()
+ bnr->bufload()
+ endif
+
+ var name: string
+ if incoming
+ name = item.from.name
+ else
+ name = item.to.name
+ endif
+
+ if incoming
+ for r in item.fromRanges
+ var text: string =
+ bnr->getbufline(r.start.line + 1)[0]->trim("\t ", 1)
+ qflist->add({filename: fname,
+ lnum: r.start.line + 1,
+ col: util.GetLineByteFromPos(bnr, r.start) + 1,
+ text: name .. ': ' .. text})
+ endfor
+ else
+ var pos: dict<any> = item.to.range.start
+ var text: string = bnr->getbufline(pos.line + 1)[0]->trim("\t ", 1)
+ qflist->add({filename: fname,
+ lnum: item.to.range.start.line + 1,
+ col: util.GetLineByteFromPos(bnr, pos) + 1,
+ text: name .. ': ' .. text})
+ endif
+ endfor
+ var save_winid = win_getid()
+ setloclist(0, [], ' ', {title: 'Incoming Calls', items: qflist})
+ lopen
+ save_winid->win_gotoid()
+enddef
+
+export def IncomingCalls(calls: list<dict<any>>)
+ if calls->empty()
+ util.WarnMsg('No incoming calls')
+ return
+ endif
+
+ s:createLoclistWithCalls(calls, true)
+enddef
+
+export def OutgoingCalls(calls: list<dict<any>>)
+ if calls->empty()
+ util.WarnMsg('No outgoing calls')
+ return
+ endif
+
+ s:createLoclistWithCalls(calls, false)
+enddef
+
+# vim: shiftwidth=2 softtabstop=2
var textedit = {}
var symbol = {}
var codeaction = {}
+var callhier = {}
if has('patch-8.2.4019')
import './lspoptions.vim' as opt_import
import './textedit.vim' as textedit_import
import './symbol.vim' as symbol_import
import './codeaction.vim' as codeaction_import
+ import './callhierarchy.vim' as callhierarchy_import
opt.lspOptions = opt_import.lspOptions
util.WarnMsg = util_import.WarnMsg
symbol.ShowReferences = symbol_import.ShowReferences
symbol.GotoSymbol = symbol_import.GotoSymbol
codeaction.ApplyCodeAction = codeaction_import.ApplyCodeAction
+ callhier.IncomingCalls = callhierarchy_import.IncomingCalls
+ callhier.OutgoingCalls = callhierarchy_import.OutgoingCalls
else
import lspOptions from './lspoptions.vim'
import {WarnMsg,
import {ApplyTextEdits, ApplyWorkspaceEdit} from './textedit.vim'
import {ShowReferences, GotoSymbol} from './symbol.vim'
import ApplyCodeAction from './codeaction.vim'
+ import {IncomingCalls, OutgoingCalls} from './callhierarchy.vim'
opt.lspOptions = lspOptions
util.WarnMsg = WarnMsg
symbol.ShowReferences = ShowReferences
symbol.GotoSymbol = GotoSymbol
codeaction.ApplyCodeAction = ApplyCodeAction
+ callhier.IncomingCalls = IncomingCalls
+ callhier.OutgoingCalls = OutgoingCalls
endif
# process the 'initialize' method reply from the LSP server
# Result: CallHierarchyItem[] | null
def s:processPrepareCallHierarchy(lspserver: dict<any>, req: dict<any>, reply: dict<any>)
if reply.result->empty()
+ if lspserver.callHierarchyType == 'incoming'
+ util.WarnMsg('No incoming calls')
+ else
+ util.WarnMsg('No outgoing calls')
+ endif
return
endif
- var items: list<string> = ['Select a Call Hierarchy Item:']
- for i in range(reply.result->len())
- items->add(printf("%d. %s", i + 1, reply.result[i].name))
- endfor
- var choice = inputlist(items)
- if choice < 1 || choice > items->len()
- return
+ var choice: number = 1
+ if reply.result->len() > 1
+ var items: list<string> = ['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
- echomsg reply.result[choice - 1]
+ if lspserver.callHierarchyType == 'incoming'
+ LspGetIncomingCalls(reply.result[choice - 1])
+ else
+ LspGetOutgoingCalls(reply.result[choice - 1])
+ endif
+enddef
+
+# process the 'callHierarchy/incomingCalls' reply from the LSP server
+# Result: CallHierarchyIncomingCall[] | null
+def s:processIncomingCalls(lspserver: dict<any>, req: dict<any>, reply: dict<any>)
+ callhier.IncomingCalls(reply.result)
+enddef
+
+# process the 'callHierarchy/outgoingCalls' reply from the LSP server
+# Result: CallHierarchyOutgoingCall[] | null
+def s:processOutgoingCalls(lspserver: dict<any>, req: dict<any>, reply: dict<any>)
+ callhier.OutgoingCalls(reply.result)
enddef
# Process various reply messages from the LSP server
'textDocument/foldingRange': function('s:processFoldingRangeReply'),
'workspace/executeCommand': function('s:processWorkspaceExecuteReply'),
'workspace/symbol': function('s:processWorkspaceSymbolReply'),
- 'textDocument/prepareCallHierarchy': function('s:processPrepareCallHierarchy')
+ 'textDocument/prepareCallHierarchy': function('s:processPrepareCallHierarchy'),
+ 'callHierarchy/incomingCalls': function('s:processIncomingCalls'),
+ 'callHierarchy/outgoingCalls': function('s:processOutgoingCalls')
}
if lsp_reply_handlers->has_key(req.method)
return
endif
+ lspserver.callHierarchyType = 'incoming'
var fname: string = @%
- lspserver.incomingCalls(fname)
+ lspserver.prepareCallHierarchy(fname)
enddef
+def g:LspGetIncomingCalls(item: dict<any>)
+ var lspserver: dict<any> = s:curbufGetServerChecked()
+ if lspserver->empty()
+ return
+ endif
+
+ lspserver.incomingCalls(item)
+enddef
+
+def g:LspGetOutgoingCalls(item: dict<any>)
+ var lspserver: dict<any> = s: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()
- :echomsg 'Error: Not implemented yet'
+ var lspserver: dict<any> = s:curbufGetServerChecked()
+ if lspserver->empty()
+ return
+ endif
+
+ lspserver.callHierarchyType = 'outgoing'
+ var fname: string = @%
+ lspserver.prepareCallHierarchy(fname)
enddef
# Rename a symbol
outlineWinSize: 20,
# Open outline window on right side
outlineOnRight: false,
- # Suppress diagnostic hover from appearing when the mouse is over the line instead of the signature
+ # Suppress diagnostic hover from appearing when the mouse is over the line
+ # instead of the signature
noDiagHoverOnLine: true,
# Show a diagnostic message on a status line
showDiagOnStatusLine: false,
lspserver.sendMessage(req)
enddef
-# Request: "callHierarchy/incomingCalls"
-# Param: CallHierarchyIncomingCallsParams
-def s:incomingCalls(lspserver: dict<any>, fname: string)
- # Check whether LSP server supports incoming calls
+# Request: "textDocument/prepareCallHierarchy"
+# Param: CallHierarchyPrepareParams
+def s:prepareCallHierarchy(lspserver: dict<any>, 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")
lspserver.sendMessage(req)
enddef
+# Request: "callHierarchy/incomingCalls"
+# Param: CallHierarchyItem
+def s:incomingCalls(lspserver: dict<any>, hierItem: dict<any>)
+ # 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
+ endif
+
+ var req = lspserver.createRequest('callHierarchy/incomingCalls')
+
+ # interface CallHierarchyIncomingCallsParams
+ # interface CallHierarchyItem
+ req.params->extend({item: hierItem})
+ lspserver.sendMessage(req)
+enddef
+
+# Request: "callHierarchy/outgoingCalls"
+# Param: CallHierarchyItem
+def s:outgoingCalls(lspserver: dict<any>, hierItem: dict<any>)
+ # 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
+ endif
+
+ var req = lspserver.createRequest('callHierarchy/outgoingCalls')
+
+ # interface CallHierarchyOutgoingCallsParams
+ # interface CallHierarchyItem
+ req.params->extend({item: hierItem})
+ lspserver.sendMessage(req)
+enddef
+
# Request: "textDocument/rename"
# Param: RenameParams
def s:renameSymbol(lspserver: dict<any>, newName: string)
diagsMap: {},
workspaceSymbolPopup: 0,
workspaceSymbolQuery: '',
- peekSymbol: false
+ peekSymbol: false,
+ callHierarchyType: ''
}
# Add the LSP server functions
lspserver->extend({
docHighlight: function('s:docHighlight', [lspserver]),
getDocSymbols: function('s:getDocSymbols', [lspserver]),
textDocFormat: function('s:textDocFormat', [lspserver]),
+ prepareCallHierarchy: function('s:prepareCallHierarchy', [lspserver]),
incomingCalls: function('s:incomingCalls', [lspserver]),
+ outgoingCalls: function('s:outgoingCalls', [lspserver]),
renameSymbol: function('s:renameSymbol', [lspserver]),
codeAction: function('s:codeAction', [lspserver]),
workspaceQuery: function('s:workspaceQuerySymbols', [lspserver]),
Author: Yegappan Lakshmanan (yegappan AT yahoo DOT com)
For Vim version 8.2.2342 and above
-Last change: Jan 21, 2022
+Last change: Feb 2, 2022
==============================================================================
*lsp-license*
:LspFormat Format the current file using the LSP server.
:{range}LspFormat Format the specified range of lines.
:LspCalledBy Display the list of symbols called by the current
- symbol. (NOT IMPLEMENTED YET).
+ symbol in a new location list.
:LspCalling Display the list of symbols calling the current symbol
- (NOT IMPLEMENTED YET).
+ in a new location list.
:LspRename Rename the current symbol
:LspCodeAction Apply the code action supplied by the LSP server to
the diagnostic in the current line.
file using the LSP server.
*:LspCalledBy*
-:LspCalledBy Display the list of symbols called by the current
- symbol. (NOT IMPLEMENTED YET).
+:LspCalledBy Creates a new location list with the location of
+ the list of symbols called by the current symbol.
*:LspCalling*
-:LspCalling Display the list of symbols calling the current symbol
- (NOT IMPLEMENTED YET).
+:LspCalling Creates a new location list with the location of the
+ list of symbols calling the current symbol.
*:LspRename*
:LspRename Rename the current symbol. You will be prompted to