return
endif
+ var curmode: string = mode()
+ if curmode == 'i' || curmode == 'R' || curmode == 'Rv'
+ # postpone placing signs in insert mode and replace mode. These will be
+ # placed after the user returns to Normal mode.
+ b:LspDiagsUpdatePending = true
+ return
+ endif
+
# Remove all the existing diagnostic signs
sign_unplace('LSPDiag', {buffer: bnr})
return
endif
- # Find the start column for the completion
+ # Find the start column for the completion. If any of the entries returned
+ # by the LSP server has a starting position, then use that.
var start_col: number = 0
for item in items
if item->has_key('textEdit')
endif
endfor
+ # LSP server didn't return a starting position for completion, search
+ # backwards from the current cursor position for a non-keyword character.
if start_col == 0
var line: string = getline('.')
var start = col('.') - 1
if !bnr->bufloaded()
bnr->bufload()
endif
- bnr->setbufvar('&buflisted', v:true)
+ bnr->setbufvar('&buflisted', true)
var start_line: number = 4294967295 # 2 ^ 32
var finish_line: number = -1
updated_edits->add({A: [start_row, start_col],
B: [end_row, end_col],
- lines: e.newText->split("\n", v:true)})
+ lines: e.newText->split("\n", true)})
endfor
# Reverse sort the edit operations by descending line and column numbers so
# if the buffer is empty, appending lines before the first line adds an
# extra empty line at the end. Delete the empty line after appending the
# lines.
- var dellastline: bool = v:false
+ var dellastline: bool = false
if start_line == 0 && bnr->getbufinfo()[0].linecount == 1 &&
bnr->getbufline(1)[0] == ''
- dellastline = v:true
+ dellastline = true
endif
# Append the updated lines
endif
s:applyWorkspaceEdit(workspaceEditParams.edit)
# TODO: Need to return the proper result of the edit operation
- lspserver.sendResponse(request, {applied: v:true}, v:null)
+ lspserver.sendResponse(request, {applied: true}, v:null)
enddef
def s:processUnsupportedReq(lspserver: dict<any>, request: dict<any>)
lsp_server_trace,
ClearTraceLogs,
GetLineByteFromPos} from './util.vim'
+import {LspDiagsUpdated} from './buf.vim'
# Needs Vim 8.2.2342 and higher
if v:version < 802 || !has('patch-8.2.2342')
def lsp#enableServerTrace()
ClearTraceLogs()
- lsp_server_trace = v:true
+ lsp_server_trace = true
enddef
# Show information about all the LSP servers
return diagInfo.message
enddef
+# Called after leaving insert mode. Used to process diag messages (if any)
+def lsp#leftInsertMode()
+ if !exists('b:LspDiagsUpdatePending')
+ return
+ endif
+ :unlet b:LspDiagsUpdatePending
+
+ var ftype: string = &filetype
+ if ftype == ''
+ return
+ endif
+
+ var lspserver: dict<any> = s:lspGetServer(ftype)
+ if lspserver->empty() || !lspserver.running
+ return
+ endif
+ LspDiagsUpdated(lspserver, bufnr())
+enddef
+
# A new buffer is opened. If LSP is supported for this buffer, then add it
def lsp#addFile(bnr: number): void
if bufnrToServer->has_key(bnr)
# autocmd for insert mode completion
exe 'autocmd SafeState <buffer=' .. bnr
.. '> if mode() == "i" | call lsp#complete() | endif'
+ exe 'autocmd InsertLeave <buffer=' .. bnr .. '> call lsp#leftInsertMode()'
# map characters that trigger signature help
if lspserver.caps->has_key('signatureHelpProvider')
# clear the symbol reference highlight
def lsp#docHighlightClear()
- prop_remove({'type': 'LspTextRef', 'all': v:true}, 1, line('$'))
- prop_remove({'type': 'LspReadRef', 'all': v:true}, 1, line('$'))
- prop_remove({'type': 'LspWriteRef', 'all': v:true}, 1, line('$'))
+ prop_remove({'type': 'LspTextRef', 'all': true}, 1, line('$'))
+ prop_remove({'type': 'LspReadRef', 'all': true}, 1, line('$'))
+ prop_remove({'type': 'LspWriteRef', 'all': true}, 1, line('$'))
enddef
# jump to a symbol selected in the outline window
endif
if range_args > 0
- lspserver.textDocFormat(fname, v:true, line1, line2)
+ lspserver.textDocFormat(fname, true, line1, line2)
else
- lspserver.textDocFormat(fname, v:false, 0, 0)
+ lspserver.textDocFormat(fname, false, 0, 0)
endif
enddef
lspserver.workspaceSymbolQuery = query
if key_handled
- return v:true
+ return true
endif
return popupID->popup_filter_menu(key)
# LSP server standard output handler
def s:output_cb(lspserver: dict<any>, chan: channel, msg: string): void
- TraceLog(v:false, msg)
+ TraceLog(false, msg)
lspserver.data = lspserver.data .. msg
lspserver.processMessages()
enddef
# LSP server error output handler
def s:error_cb(lspserver: dict<any>, chan: channel, emsg: string,): void
- TraceLog(v:true, emsg)
+ TraceLog(true, emsg)
enddef
# LSP server exit callback
def s:exit_cb(lspserver: dict<any>, job: job, status: number): void
WarnMsg("LSP server exited with status " .. status)
lspserver.job = v:none
- lspserver.running = v:false
+ lspserver.running = false
lspserver.requests = {}
enddef
sleep 10m
lspserver.job = job
- lspserver.running = v:true
+ lspserver.running = true
lspserver.initServer()
# client capabilities (ClientCapabilities)
var clientCaps: dict<any> = {
workspace: {
- workspaceFolders: v:true,
- applyEdit: v:true,
+ workspaceFolders: true,
+ applyEdit: true,
},
textDocument: {
- foldingRange: {lineFoldingOnly: v:true},
+ foldingRange: {lineFoldingOnly: true},
completion: {
completionItem: {
documentationFormat: ['plaintext', 'markdown'],
- snippetSupport: v:false
+ snippetSupport: false
},
completionItemKind: {valueSet: range(1, 25)}
},
contentFormat: ['plaintext', 'markdown']
},
documentSymbol: {
- hierarchicalDocumentSymbolSupport: v:true,
+ hierarchicalDocumentSymbolSupport: true,
symbolKind: {valueSet: range(1, 25)}
},
},
lspserver.job->job_stop()
lspserver.job = v:none
- lspserver.running = v:false
+ lspserver.running = false
lspserver.requests = {}
return 0
enddef
# interface ReferenceParams
# interface TextDocumentPositionParams
req.params->extend(s:getLspTextDocPosition())
- req.params->extend({context: {includeDeclaration: v:true}})
+ req.params->extend({context: {includeDeclaration: true}})
lspserver.sendMessage(req)
enddef
# interface FormattingOptions
var fmtopts: dict<any> = {
tabSize: tabsz,
- insertSpaces: &expandtab ? v:true : v:false,
+ insertSpaces: &expandtab ? true : false,
}
req.params->extend({options: fmtopts})
if rangeFormat
var lspserver: dict<any> = {
path: path,
args: args,
- running: v:false,
+ running: false,
job: v:none,
data: '',
nextID: 1,
else
lsp_log_dir = $TEMP .. '\\'
endif
-export var lsp_server_trace: bool = v:false
+export var lsp_server_trace: bool = false
-# Log a message from the LSP server. stderr is v:true for logging messages
-# from the standard error and v:false for stdout.
+# Log a message from the LSP server. stderr is true for logging messages
+# from the standard error and false for stdout.
export def TraceLog(stderr: bool, msg: string)
if !lsp_server_trace
return
export def LspFileToUri(fname: string): string
var uri: string = fnamemodify(fname, ':p')
- var on_windows: bool = v:false
+ var on_windows: bool = false
if uri =~? '^\a:'
- on_windows = v:true
+ on_windows = true
endif
if on_windows
var bnr: number = bufnr()
:LspShowReferences
:sleep 1
- var qfl: list<dict<any>> = getqflist()
+ var qfl: list<dict<any>> = getloclist(0)
assert_equal('quickfix', getwinvar(winnr('$'), '&buftype'))
assert_equal(bnr, qfl[0].bufnr)
assert_equal(3, qfl->len())
cursor(1, 5)
:LspShowReferences
:sleep 1
- qfl = getqflist()
+ qfl = getloclist()
assert_equal(1, qfl->len())
assert_equal([1, 5], [qfl[0].lnum, qfl[0].col])
->map("v:val->substitute('^def <SNR>\\d\\+_', '', '')")
for f in fns
v:errors = []
- exe f
+ try
+ exe f
+ catch
+ echomsg "Error: Test " .. f .. " failed with exception " .. v:exception
+ endtry
if v:errors->len() != 0
new Lsp-Test-Results
setline(1, ["Error: Test " .. f .. " failed"]->extend(v:errors))