import './buffer.vim' as buf
import './util.vim'
+# [bnr] = {
+# serverDiagnostics: {
+# lspServer1Id: [diag, diag, diag]
+# lspServer2Id: [diag, diag, diag]
+# },
+# serverDiagnosticsByLnum: {
+# lspServer1Id: { [lnum]: [diag, diag diag] },
+# lspServer2Id: { [lnum]: [diag, diag diag] },
+# },
+# sortedDiagnostics: [lspServer1.diags, ...lspServer2.diags]->sort()
+# }
+var diagsMap: dict<dict<any>> = {}
+
# Initialize the signs and the text property type used for diagnostics.
export def InitOnce()
# Signs used for LSP diagnostics
enddef
# Remove the diagnostics stored for buffer 'bnr'
-export def DiagRemoveFile(lspserver: dict<any>, bnr: number)
- if lspserver.diagsMap->has_key(bnr)
- lspserver.diagsMap->remove(bnr)
+export def DiagRemoveFile(bnr: number)
+ if diagsMap->has_key(bnr)
+ diagsMap->remove(bnr)
endif
enddef
prop_remove({type: 'LspDiagInlineHint', bufnr: bnr, all: true})
endif
- if !lspserver.diagsMap->has_key(bnr) ||
- lspserver.diagsMap[bnr].sortedDiagnostics->empty()
+ if !diagsMap->has_key(bnr) ||
+ diagsMap[bnr].sortedDiagnostics->empty()
return
endif
var signs: list<dict<any>> = []
- var diags = lspserver.diagsMap[bnr].sortedDiagnostics
+ var diags: list<dict<any>> = diagsMap[bnr].sortedDiagnostics
for diag in diags
# TODO: prioritize most important severity if there are multiple diagnostics
# from the same line
return
endif
- if bnr == -1 || !lspserver.diagsMap->has_key(bnr)
+ if bnr == -1 || !diagsMap->has_key(bnr)
return
endif
# process a diagnostic notification message from the LSP server
# Notification: textDocument/publishDiagnostics
# Param: PublishDiagnosticsParams
-export def DiagNotification(lspserver: dict<any>, uri: string, diags: list<dict<any>>): void
+export def DiagNotification(lspserver: dict<any>, uri: string, newDiags: list<dict<any>>): void
var fname: string = util.LspUriToFile(uri)
var bnr: number = fname->bufnr()
if bnr == -1
# TODO: Is the buffer (bnr) always a loaded buffer? Should we load it here?
var lastlnum: number = bnr->getbufinfo()[0].linecount
+
# store the diagnostic for each line separately
- var diagByLnum: dict<list<dict<any>>> = {}
+ var diagsByLnum: dict<list<dict<any>>> = {}
+
var diagWithinRange: list<dict<any>> = []
- for diag in diags
+ for diag in newDiags
if diag.range.start.line + 1 > lastlnum
# Make sure the line number is a valid buffer line number
diag.range.start.line = lastlnum - 1
endif
var lnum = diag.range.start.line + 1
- if !diagByLnum->has_key(lnum)
- diagByLnum[lnum] = []
+ if !diagsByLnum->has_key(lnum)
+ diagsByLnum[lnum] = []
endif
- diagByLnum[lnum]->add(diag)
+ diagsByLnum[lnum]->add(diag)
diagWithinRange->add(diag)
endfor
- # sort the diagnostics by line number and column number
- var sortedDiags = SortDiags(diagWithinRange)
+ var serverDiags: dict<list<any>> = diagsMap->has_key(bnr) ?
+ diagsMap[bnr].serverDiagnostics : {}
+ serverDiags[lspserver.id] = diagWithinRange
- lspserver.diagsMap->extend({
- [$'{bnr}']: {
- sortedDiagnostics: sortedDiags,
- diagnosticsByLnum: diagByLnum
- }
- })
+ var serverDiagsByLnum: dict<dict<list<any>>> = diagsMap->has_key(bnr) ?
+ diagsMap[bnr].serverDiagnosticsByLnum : {}
+ serverDiagsByLnum[lspserver.id] = diagsByLnum
+
+ # store the diagnostic for each line separately
+ var joinedServerDiags: list<dict<any>> = []
+ for diags in serverDiags->values()
+ for diag in diags
+ joinedServerDiags->add(diag)
+ endfor
+ endfor
+
+ var sortedDiags = SortDiags(joinedServerDiags)
+
+ diagsMap[bnr] = {
+ sortedDiagnostics: sortedDiags,
+ serverDiagnosticsByLnum: serverDiagsByLnum,
+ serverDiagnostics: serverDiags
+ }
ProcessNewDiags(lspserver, bnr)
var hintCount = 0
var bnr: number = bufnr()
- if lspserver.diagsMap->has_key(bnr)
- var diags = lspserver.diagsMap[bnr].sortedDiagnostics
+ if diagsMap->has_key(bnr)
+ var diags = diagsMap[bnr].sortedDiagnostics
for diag in diags
var severity = diag->get('severity', -1)
if severity == 1
LspQfId = 0
endif
- if !lspserver.diagsMap->has_key(bnr) ||
- lspserver.diagsMap[bnr].sortedDiagnostics->empty()
+ if !diagsMap->has_key(bnr) ||
+ diagsMap[bnr].sortedDiagnostics->empty()
if LspQfId != 0
setloclist(0, [], 'r', {id: LspQfId, items: []})
endif
var qflist: list<dict<any>> = []
var text: string
- var diags = lspserver.diagsMap[bnr].sortedDiagnostics
+ var diags = diagsMap[bnr].sortedDiagnostics
for diag in diags
text = diag.message->substitute("\n\\+", "\n", 'g')
qflist->add({filename: fname,
# Get all diagnostics from the LSP server for a particular line in a file
export def GetDiagsByLine(lspserver: dict<any>, bnr: number, lnum: number): list<dict<any>>
- if lspserver.diagsMap->has_key(bnr)
- var diagsbyLnum = lspserver.diagsMap[bnr].diagnosticsByLnum
- if diagsbyLnum->has_key(lnum)
- return diagsbyLnum[lnum]->sort((a, b) => {
- return a.range.start.character - b.range.start.character
- })
- endif
+ if !diagsMap->has_key(bnr)
+ return []
endif
- return []
+
+ var diags: list<dict<any>> = []
+
+ var serverDiagsByLnum = diagsMap[bnr].serverDiagnosticsByLnum
+
+ for diagsByLnum in serverDiagsByLnum->values()
+ if diagsByLnum->has_key(lnum)
+ diags->extend(diagsByLnum[lnum])
+ endif
+ endfor
+
+ return diags->sort((a, b) => {
+ return a.range.start.character - b.range.start.character
+ })
enddef
# Utility function to do the actual jump
endif
var bnr: number = bufnr()
- if !lspserver.diagsMap->has_key(bnr) ||
- lspserver.diagsMap[bnr].sortedDiagnostics->empty()
+ if !diagsMap->has_key(bnr) ||
+ diagsMap[bnr].sortedDiagnostics->empty()
util.WarnMsg($'No diagnostic messages found for {fname}')
return
endif
- var diags = lspserver.diagsMap[bnr].sortedDiagnostics
+ var diags = diagsMap[bnr].sortedDiagnostics
if which == 'first'
JumpDiag(diags[0])