You can install this plugin directly from github using the following steps:
```
- $ mkdir -p $HOME/.vim/pack/downloads/lsp
- $ cd $HOME/.vim/packa/downloads/lsp
+ $ mkdir -p $HOME/.vim/pack/downloads/opt/lsp
+ $ cd $HOME/.vim/pack/downloads/opt/lsp
$ git clone https://github.com/yegappan/lsp
```
-or you can use any one of the Vim plugin managers (dein.vim, pathogen, vam, vim-plug, volt, Vundle, etc.) to install and manage this plugin.
+After installing the plugin using the above steps, add the following line to
+your $HOME/.vimrc file:
+
+```
+ packadd lsp
+```
+
+You can also install and manage this plugin using any one of the Vim plugin managers (dein.vim, pathogen, vam, vim-plug, volt, Vundle, etc.).
You will also need to install one or more language servers corresponding to the programming languages that you are using. Refer to the https://langserver.org/ page for the list of available language servers.
var signs: list<dict<any>> = []
for [lnum, diag] in lspserver.diagsMap[bnr]->items()
- signs->add({id: 0, buffer: str2nr(bnr), group: 'LSPDiag',
+ signs->add({id: 0, buffer: bnr, group: 'LSPDiag',
lnum: str2nr(lnum),
name: s:lspDiagSevToSignName(diag.severity)})
endfor
return
endif
- var result: dict<any> = reply.result[0]
- var file = LspUriToFile(result.uri)
- var wid = file->bufwinid()
+ var location: dict<any>
+ if reply.result->type() == v:t_list
+ location = reply.result[0]
+ else
+ location = reply.result
+ endif
+ var fname = LspUriToFile(location.uri)
+ var wid = fname->bufwinid()
if wid != -1
wid->win_gotoid()
else
- exe 'split ' .. file
+ var bnr: number = fname->bufnr()
+ if bnr != -1
+ if &modified || &buftype != ''
+ exe 'sb ' .. bnr
+ else
+ exe 'buf ' .. bnr
+ endif
+ else
+ 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
# Set the previous cursor location mark
setpos("'`", getcurpos())
- setcursorcharpos(result.range.start.line + 1,
- result.range.start.character + 1)
+ setcursorcharpos(location.range.start.line + 1,
+ location.range.start.character + 1)
redraw!
enddef
return
endif
- var sig: dict<any> = result.signatures[result.activeSignature]
+ var sigidx: number = 0
+ if result->has_key('activeSignature')
+ sigidx = result.activeSignature
+ endif
+
+ var sig: dict<any> = result.signatures[sigidx]
var text = sig.label
var hllen = 0
var startcol = 0
return
endif
+ if mode() != 'i' && mode() != 'R' && mode() != 'Rv'
+ # If not in insert or replace mode, then don't start the completion
+ return
+ endif
+
if completeItems->len() == 1
&& matchstr(getline('.'), completeItems[0].word .. '\>') != ''
# only one complete match. No need to show the completion popup
symbols->copy()->mapnew('v:val.name'))
enddef
+# process the 'textDocument/prepareCallHierarchy' reply from the LSP server
+# Result: CallHierarchyItem[] | null
+def s:processPrepareCallHierarchy(lspserver: dict<any>, req: dict<any>, reply: dict<any>)
+ if reply.result->empty()
+ 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
+ endif
+
+ echomsg reply.result[choice - 1]
+enddef
+
# Process various reply messages from the LSP server
export def ProcessReply(lspserver: dict<any>, req: dict<any>, reply: dict<any>): void
var lsp_reply_handlers: dict<func> =
'textDocument/selectionRange': function('s:processSelectionRangeReply'),
'textDocument/foldingRange': function('s:processFoldingRangeReply'),
'workspace/executeCommand': function('s:processWorkspaceExecuteReply'),
- 'workspace/symbol': function('s:processWorkspaceSymbolReply')
+ 'workspace/symbol': function('s:processWorkspaceSymbolReply'),
+ 'textDocument/prepareCallHierarchy': function('s:processPrepareCallHierarchy')
}
if lsp_reply_handlers->has_key(req.method)
# Display all the locations where the current symbol is called from.
# Uses LSP "callHierarchy/incomingCalls" request
def lsp#incomingCalls()
- :echomsg 'Error: Not implemented yet'
+ var ftype = &filetype
+ if ftype == ''
+ return
+ endif
+
+ var lspserver: dict<any> = s:lspGetServer(ftype)
+ if lspserver->empty()
+ ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not found')
+ return
+ endif
+ if !lspserver.running
+ ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not running')
+ return
+ endif
+
+ var fname = @%
+ if fname == ''
+ return
+ endif
+
+ lspserver.incomingCalls(fname)
enddef
# Display all the symbols used by the current symbol.
var clientCaps: dict<any> = {
workspace: {
workspaceFolders: true,
- applyEdit: true,
+ applyEdit: true
},
textDocument: {
foldingRange: {lineFoldingOnly: true},
var curdir: string = getcwd()
initparams.rootPath = curdir
initparams.rootUri = LspFileToUri(curdir)
- initparams.workspaceFolders = {
+ initparams.workspaceFolders = [{
name: fnamemodify(curdir, ':t'),
uri: LspFileToUri(curdir)
- }
+ }]
initparams.trace = 'off'
initparams.capabilities = clientCaps
req.params->extend(initparams)
vtdid.uri = LspBufnrToUri(bnr)
# Use Vim 'changedtick' as the LSP document version number
vtdid.version = bnr->getbufvar('changedtick')
- notif.params->extend({textDocument: vtdid})
+
# interface TextDocumentContentChangeEvent
var changeset: list<dict<any>>
# var range: dict<dict<number>> = {'start': {'line': start_lnum, 'character': start_col}, 'end': {'line': end_lnum, 'character': end_col}}
# changeset->add({'range': range, 'text': lines})
# endfor
+
changeset->add({text: getbufline(bnr, 1, '$')->join("\n") .. "\n"})
- notif.params->extend({contentChanges: changeset})
+ notif.params->extend({textDocument: vtdid, contentChanges: changeset})
lspserver.sendMessage(notif)
enddef
lspserver.sendMessage(req)
enddef
+# Request: "callHierarchy/incomingCalls"
+# Param: CallHierarchyIncomingCallsParams
+def s:incomingCalls(lspserver: dict<any>, fname: string)
+ # Check whether LSP server supports incoming calls
+ if !lspserver.caps->has_key('callHierarchyProvider')
+ || !lspserver.caps.callHierarchyProvider
+ ErrMsg("Error: LSP server does not support call hierarchy")
+ return
+ endif
+
+ var req = lspserver.createRequest('textDocument/prepareCallHierarchy')
+
+ # interface CallHierarchyPrepareParams
+ # interface TextDocumentPositionParams
+ req.params->extend(s:getLspTextDocPosition())
+ lspserver.sendMessage(req)
+enddef
+
# Request: "textDocument/rename"
# Param: RenameParams
def s:renameSymbol(lspserver: dict<any>, newName: string)
docHighlight: function('s:docHighlight', [lspserver]),
getDocSymbols: function('s:getDocSymbols', [lspserver]),
textDocFormat: function('s:textDocFormat', [lspserver]),
+ incomingCalls: function('s:incomingCalls', [lspserver]),
renameSymbol: function('s:renameSymbol', [lspserver]),
codeAction: function('s:codeAction', [lspserver]),
workspaceQuery: function('s:workspaceQuerySymbols', [lspserver]),