Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 40 additions & 14 deletions autoload/lsp/buffer.vim
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ export def BufLspServerSet(bnr: number, lspserver: dict<any>)
if !bufnrToServers->has_key(bnr)
bufnrToServers[bnr] = []
endif

bufnrToServers[bnr]->add(lspserver)
enddef

Expand Down Expand Up @@ -135,12 +134,30 @@ enddef

# Returns the LSP servers for the buffer "bnr". Returns an empty list if the
# servers are not found.
export def BufLspServersGet(bnr: number): list<dict<any>>
export def BufLspServersGet(bnr: number, feature: string = null_string): list<dict<any>>
if !bufnrToServers->has_key(bnr)
return []
endif

return bufnrToServers[bnr]
if feature == null_string
return bufnrToServers[bnr]
else
var SupportedCheckFn = SupportedCheckFns[feature]
var possibleLSPs: list<dict<any>> = []
for lspserver in bufnrToServers[bnr]
if !lspserver.ready || !SupportedCheckFn(lspserver)
continue
endif
possibleLSPs->add(lspserver)
endfor

var servers: list<dict<any>> = []
for lspserver in possibleLSPs
# var has_feature: bool = lspserver.features->get(feature, false)
servers->add(lspserver)
endfor
return servers
endif
enddef

# Returns the LSP server for the current buffer with the optionally "feature".
Expand All @@ -151,16 +168,22 @@ enddef

# Returns the LSP servers for the current buffer. Returns an empty list if the
# servers are not found.
export def CurbufGetServers(): list<dict<any>>
return BufLspServersGet(bufnr())
export def CurbufGetServers(feature: string = null_string): list<dict<any>>
return BufLspServersGet(bufnr(), feature)
enddef

export def BufHasLspServer(bnr: number): bool
var lspserver = BufLspServerGet(bnr)

export def BufHasLspServer(bnr: number, id: number): bool
var lspserver = BufLspServerGetById(bnr, id)
return !lspserver->empty()
enddef

# Returns the LSP server for the current buffer, given the server id
# and with the optionally "feature" if it is running and is ready.
export def CurbufGetServerByIdChecked(id: number, feature: string = null_string): dict<any>
var lspserver = BufLspServerGetById(bufnr(), id)
return CurbufGetServerChecks(lspserver, feature)
enddef

# Returns the LSP server for the current buffer with the optinally "feature" if
# it is running and is ready.
# Returns an empty dict if the server is not found or is not ready.
Expand All @@ -169,26 +192,29 @@ export def CurbufGetServerChecked(feature: string = null_string): dict<any>
if fname->empty() || &filetype->empty()
return {}
endif

var lspserver: dict<any> = CurbufGetServer(feature)
if lspserver->empty()
return CurbufGetServerChecks(lspserver, feature)
enddef

# Runs checks of the LSP
export def CurbufGetServerChecks(lspServer: dict<any>, feature: string = null_string): dict<any>
if lspServer->empty()
if feature == null_string
util.ErrMsg($'Language server for "{&filetype}" file type is not found')
else
util.ErrMsg($'Language server for "{&filetype}" file type supporting "{feature}" feature is not found')
endif
return {}
endif
if !lspserver.running
if !lspServer.running
util.ErrMsg($'Language server for "{&filetype}" file type is not running')
return {}
endif
if !lspserver.ready
if !lspServer.ready
util.ErrMsg($'Language server for "{&filetype}" file type is not ready')
return {}
endif

return lspserver
return lspServer
enddef

# vim: tabstop=8 shiftwidth=2 softtabstop=2
97 changes: 48 additions & 49 deletions autoload/lsp/completion.vim
Original file line number Diff line number Diff line change
Expand Up @@ -543,36 +543,37 @@ enddef
# Insert mode completion handler. Used when 24x7 completion is enabled
# (default).
def LspComplete()
var lspserver: dict<any> = buf.CurbufGetServer('completion')
if lspserver->empty() || !lspserver.running || !lspserver.ready
return
endif
var lspservers: list<dict<any>> = buf.CurbufGetServers('completion')
for lspserver in lspservers
if lspserver->empty() || !lspserver.running || !lspserver.ready
return
endif

var [triggerKind, triggerChar] = GetTriggerAttributes(lspserver)
if triggerKind < 0
return
endif
var [triggerKind, triggerChar] = GetTriggerAttributes(lspserver)
if triggerKind < 0
return
endif

# first send all the changes in the current buffer to the LSP server
listener_flush()
# first send all the changes in the current buffer to the LSP server
listener_flush()

# initiate a request to LSP server to get list of completions
lspserver.getCompletion(triggerKind, triggerChar)
# initiate a request to LSP server to get list of completions
lspserver.getCompletion(triggerKind, triggerChar)
endfor
enddef

# Lazy complete documentation handler
def LspResolve()
var lspserver: dict<any> = buf.CurbufGetServerChecked('completion')
def LspResolve(servId: number)
var lspserver: dict<any> = buf.CurbufGetServerByIdChecked(servId, 'completion')
if lspserver->empty()
return
return
endif

var item = v:event.completed_item
if item->has_key('user_data') && !item.user_data->empty()
if item.user_data->type() == v:t_dict && !item.user_data->has_key('documentation')
lspserver.resolveCompletion(item.user_data)
lspserver.resolveCompletion(item.user_data)
else
ShowCompletionDocumentation(item.user_data)
ShowCompletionDocumentation(item.user_data)
endif
endif
enddef
Expand Down Expand Up @@ -600,38 +601,37 @@ def LspSetPopupFileType()
enddef

# complete done handler (LSP server-initiated actions after completion)
def LspCompleteDone(bnr: number)
var lspserver: dict<any> = buf.BufLspServerGet(bnr, 'completion')
if lspserver->empty()
return
endif

if v:completed_item->type() != v:t_dict
return
endif
def LspCompleteDone(servId: number, bnr: number)
var lspserver: dict<any> = buf.BufLspServerGetById(bnr, servId)
if lspserver->empty()
return
endif

var completionData: any = v:completed_item->get('user_data', '')
if completionData->type() != v:t_dict
|| !opt.lspOptions.completionTextEdit
return
endif
if v:completed_item->type() != v:t_dict
return
endif

if !completionData->has_key('additionalTextEdits')
# Some language servers (e.g. typescript) delay the computation of the
# additional text edits. So try to resolve the completion item now to get
# the text edits.
completionData = lspserver.resolveCompletion(completionData, true)
endif
if !completionData->get('additionalTextEdits', {})->empty()
textedit.ApplyTextEdits(bnr, completionData.additionalTextEdits)
endif
var completionData: any = v:completed_item->get('user_data', '')
if completionData->type() != v:t_dict
|| !opt.lspOptions.completionTextEdit
return
endif

if completionData->has_key('command')
# Some language servers (e.g. haskell-language-server) want to apply
# additional commands after completion.
codeaction.DoCommand(lspserver, completionData.command)
endif
if !completionData->has_key('additionalTextEdits')
# Some language servers (e.g. typescript) delay the computation of the
# additional text edits. So try to resolve the completion item now to get
# the text edits.
completionData = lspserver.resolveCompletion(completionData, true)
endif
if !completionData->get('additionalTextEdits', {})->empty()
textedit.ApplyTextEdits(bnr, completionData.additionalTextEdits)
endif

if completionData->has_key('command')
# Some language servers (e.g. haskell-language-server) want to apply
# additional commands after completion.
codeaction.DoCommand(lspserver, completionData.command)
endif
enddef

# Initialize buffer-local completion options and autocmds
Expand Down Expand Up @@ -679,7 +679,7 @@ export def BufferInit(lspserver: dict<any>, bnr: number, ftype: string)
acmds->add({bufnr: bnr,
event: 'CompleteChanged',
group: 'LSPBufferAutocmds',
cmd: 'LspResolve()'})
cmd: $'LspResolve({lspserver.id})'})
endif

acmds->add({bufnr: bnr,
Expand All @@ -691,8 +691,7 @@ export def BufferInit(lspserver: dict<any>, bnr: number, ftype: string)
acmds->add({bufnr: bnr,
event: 'CompleteDone',
group: 'LSPBufferAutocmds',
cmd: $'LspCompleteDone({bnr})'})

cmd: $'LspCompleteDone({lspserver.id}, {bnr})'})
autocmd_add(acmds)
enddef

Expand Down
20 changes: 11 additions & 9 deletions autoload/lsp/lsp.vim
Original file line number Diff line number Diff line change
Expand Up @@ -412,10 +412,12 @@ def BufferInit(lspserverId: number, bnr: number): void
# It's only possible to initialize the features when the server
# capabilities of all the registered language servers for this file type
# are known.
var completionServer = buf.BufLspServerGet(bnr, 'completion')
if !completionServer->empty() && lspsrv.id == completionServer.id
completion.BufferInit(lspsrv, bnr, ftype)
endif
var completionServers = buf.BufLspServersGet(bnr, 'completion')
for compSrv in completionServers
if !compSrv->empty() && lspsrv.id == compSrv.id
completion.BufferInit(lspsrv, bnr, ftype)
endif
endfor

var signatureServer = buf.BufLspServerGet(bnr, 'signatureHelp')
if !signatureServer->empty() && lspsrv.id == signatureServer.id
Expand All @@ -441,11 +443,6 @@ enddef

# A new buffer is opened. If LSP is supported for this buffer, then add it
export def AddFile(bnr: number): void
if buf.BufHasLspServer(bnr)
# LSP server for this buffer is already initialized and running
return
endif

# Skip remote files
if util.LspUriRemote(bnr->bufname()->fnamemodify(':p'))
return
Expand All @@ -455,11 +452,16 @@ export def AddFile(bnr: number): void
if ftype->empty()
return
endif

var lspservers: list<dict<any>> = LspGetServers(bnr, ftype)
if lspservers->empty()
return
endif

for lspserver in lspservers
if buf.BufHasLspServer(bnr, lspserver.id)
continue
endif
if !lspserver.running
if !lspInitializedOnce
LspInitOnce()
Expand Down