endif
enddef
+# process the 'textDocument/references' reply from the LSP server
+def LSPprocessReferencesReply(ftype: string, reply: dict<any>): void
+ if type(reply.result) == v:t_none || reply.result->len() == 0
+ echomsg 'Error: No references found'
+ return
+ endif
+
+ # create a quickfix list with the location of the references
+ var locations: list<dict<any>> = reply.result
+ var qflist: list<dict<any>> = []
+ for loc in locations
+ var fname: string = loc.uri[7:]
+ var text: string = fname->getbufline(loc.range.start.line + 1)[0]
+ ->trim("\t ", 1)
+ qflist->add({'filename': fname,
+ 'lnum': loc.range.start.line + 1,
+ 'col': loc.range.start.character + 1,
+ 'text': text})
+ endfor
+ call setqflist([], ' ', {'title': 'Language Server', 'items': qflist})
+ var save_winid = win_getid()
+ copen
+ win_gotoid(save_winid)
+enddef
+
# Process varous reply messages from the LSP server
def lsp#process_reply(ftype: string, req: dict<any>, reply: dict<any>): void
if req.method == 'initialize'
LSPprocessInitializeReply(ftype, reply)
- elseif req.method == 'textDocument/definition' || req.method == 'textDocument/declaration'
+ elseif req.method == 'textDocument/definition'
+ || req.method == 'textDocument/declaration'
+ || req.method == 'textDocument/typeDefinition'
+ || req.method == 'textDocument/implementation'
LSPprocessDefDeclReply(reply)
elseif req.method == 'textDocument/signatureHelp'
LSPprocessSignaturehelpReply(reply)
LSPprocessCompletionReply(ftype, reply)
elseif req.method == 'textDocument/hover'
LSPprocessHoverReply(ftype, reply)
+ elseif req.method == 'textDocument/references'
+ LSPprocessReferencesReply(ftype, reply)
else
echomsg "Error: Unsupported reply received from LSP server: " .. string(reply)
endif
enddef
# Send a "initialize" LSP request
-def lsp#init_server(ftype: string): number
+def lsp#init_server(ftype: string)
var req = lsp#create_reqmsg(ftype, 'initialize')
# interface 'InitializeParams'
req.params->extend(initparams)
LSPsendto_server(ftype, req)
- return 1
enddef
# Send a "initialized" LSP notification
enddef
# Goto a definition using "textDocument/definition" LSP request
-def lsp#goto_definition(fname: string, ftype: string, lnum: number, col: number)
+def lsp#gotoDefinition(fname: string, ftype: string, lnum: number, col: number)
if fname == '' || ftype == ''
return
endif
return
endif
+ # Check whether LSP server supports jumping to a definition
+ if !lsp_servers[ftype].caps->has_key('definitionProvider')
+ || !lsp_servers[ftype].caps.definitionProvider
+ echomsg "Error: LSP server does not support jumping to a definition"
+ return
+ endif
+
var req = lsp#create_reqmsg(ftype, 'textDocument/definition')
# interface DefinitionParams
enddef
# Goto a declaration using "textDocument/declaration" LSP request
-def lsp#goto_declaration(fname: string, ftype: string, lnum: number, col: number)
+def lsp#gotoDeclaration(fname: string, ftype: string, lnum: number, col: number)
if fname == '' || ftype == ''
return
endif
return
endif
+ # Check whether LSP server supports jumping to a declaration
+ if !lsp_servers[ftype].caps->has_key('declarationProvider')
+ || !lsp_servers[ftype].caps.declarationProvider
+ echomsg "Error: LSP server does not support jumping to a declaration"
+ return
+ endif
+
var req = lsp#create_reqmsg(ftype, 'textDocument/declaration')
# interface DeclarationParams
LSPsendto_server(ftype, req)
enddef
+# Go to a type definition using "textDocument/typeDefinition" LSP request
+def lsp#gotoTypedef(fname: string, ftype: string, lnum: number, col: number)
+ if fname == '' || ftype == ''
+ return
+ endif
+ if !lsp_servers->has_key(ftype)
+ echomsg 'Error: LSP server for "' .. ftype .. '" filetype is not found'
+ return
+ endif
+ if !lsp_servers[ftype].running
+ echomsg 'Error: LSP server for "' .. ftype .. '" filetype is not running'
+ return
+ endif
+
+ # Check whether LSP server supports jumping to a type definition
+ if !lsp_servers[ftype].caps->has_key('typeDefinitionProvider')
+ || !lsp_servers[ftype].caps.typeDefinitionProvider
+ echomsg "Error: LSP server does not support jumping to a type definition"
+ return
+ endif
+
+ var req = lsp#create_reqmsg(ftype, 'textDocument/typeDefinition')
+
+ # interface TypeDefinitionParams
+ # interface TextDocumentPositionParams
+ # interface TextDocumentIdentifier
+ req.params->extend({'textDocument': {'uri': 'file://' .. fname}})
+ # interface Position
+ req.params->extend({'position': {'line': lnum, 'character': col}})
+
+ LSPsendto_server(ftype, req)
+enddef
+
+# Go to a implementation using "textDocument/implementation" LSP request
+def lsp#gotoImplementation(fname: string, ftype: string, lnum: number, col: number)
+ if fname == '' || ftype == ''
+ return
+ endif
+ if !lsp_servers->has_key(ftype)
+ echomsg 'Error: LSP server for "' .. ftype .. '" filetype is not found'
+ return
+ endif
+ if !lsp_servers[ftype].running
+ echomsg 'Error: LSP server for "' .. ftype .. '" filetype is not running'
+ return
+ endif
+
+ # Check whether LSP server supports jumping to a type definition
+ if !lsp_servers[ftype].caps->has_key('implementationProvider')
+ || !lsp_servers[ftype].caps.implementationProvider
+ echomsg "Error: LSP server does not support jumping to an implementation"
+ return
+ endif
+
+ var req = lsp#create_reqmsg(ftype, 'textDocument/implementation')
+
+ # interface ImplementationParams
+ # interface TextDocumentPositionParams
+ # interface TextDocumentIdentifier
+ req.params->extend({'textDocument': {'uri': 'file://' .. fname}})
+ # interface Position
+ req.params->extend({'position': {'line': lnum, 'character': col}})
+
+ LSPsendto_server(ftype, req)
+enddef
+
# Show the signature using "textDocument/signatureHelp" LSP method
# Invoked from an insert-mode mapping, so return an empty string.
def lsp#showSignature(): string
diag.message = diag.message->substitute("\n\\+", "\n", 'g')
msgs->extend(split(diag.message, "\n"))
endfor
- setqflist([], ' ', {'lines': msgs})
+ setqflist([], ' ', {'lines': msgs, 'title': 'Language Server'})
cwindow
enddef
return
endif
+ # Check whether LSP server supports getting hover information
+ if !lsp_servers[ftype].caps->has_key('hoverProvider')
+ || !lsp_servers[ftype].caps.hoverProvider
+ return
+ endif
+
var fname = expand('%:p')
if fname == ''
return
LSPsendto_server(ftype, req)
enddef
+def lsp#showReferences()
+ var ftype = &filetype
+ if ftype == ''
+ return
+ endif
+
+ if !lsp_servers->has_key(ftype)
+ echomsg 'Error: LSP server for "' .. ftype .. '" filetype is not found'
+ return
+ endif
+ if !lsp_servers[ftype].running
+ echomsg 'Error: LSP server for "' .. ftype .. '" filetype is not running'
+ return
+ endif
+
+ # Check whether LSP server supports getting reference information
+ if !lsp_servers[ftype].caps->has_key('referencesProvider')
+ || !lsp_servers[ftype].caps.referencesProvider
+ return
+ endif
+
+ var fname = expand('%:p')
+ if fname == ''
+ return
+ endif
+ var lnum = line('.') - 1
+ var col = col('.') - 1
+
+ var req = lsp#create_reqmsg(ftype, 'textDocument/references')
+ # interface ReferenceParams
+ # interface TextDocumentPositionParams
+ # interface TextDocumentIdentifier
+ req.params->extend({'textDocument': {'uri': 'file://' .. fname}})
+ # interface Position
+ req.params->extend({'position': {'line': lnum, 'character': col}})
+ req.params->extend({'context': {'includeDeclaration': v:true}})
+
+ LSPsendto_server(ftype, req)
+enddef
+
# vim: shiftwidth=2 sts=2 expandtab