3 # Functions related to handling LSP diagnostics.
5 import './options.vim' as opt
6 import './buffer.vim' as buf
10 # serverDiagnostics: {
11 # lspServer1Id: [diag, diag, diag]
12 # lspServer2Id: [diag, diag, diag]
14 # serverDiagnosticsByLnum: {
15 # lspServer1Id: { [lnum]: [diag, diag diag] },
16 # lspServer2Id: { [lnum]: [diag, diag diag] },
18 # sortedDiagnostics: [lspServer1.diags, ...lspServer2.diags]->sort()
20 var diagsMap: dict<dict<any>> = {}
22 # Initialize the signs and the text property type used for diagnostics.
24 # Signs and their highlight groups used for LSP diagnostics
26 {name: 'LspDiagLine', default: true, linksto: 'NONE'},
27 {name: 'LspDiagSignErrorText', default: true, linksto: 'ErrorMsg'},
28 {name: 'LspDiagSignWarningText', default: true, linksto: 'Search'},
29 {name: 'LspDiagSignInfoText', default: true, linksto: 'Pmenu'},
30 {name: 'LspDiagSignHintText', default: true, linksto: 'Question'}
35 text: opt.lspOptions.diagSignErrorText,
36 texthl: 'LspDiagSignErrorText',
40 name: 'LspDiagWarning',
41 text: opt.lspOptions.diagSignWarningText,
42 texthl: 'LspDiagSignWarningText',
47 text: opt.lspOptions.diagSignInfoText,
48 texthl: 'LspDiagSignInfoText',
53 text: opt.lspOptions.diagSignHintText,
54 texthl: 'LspDiagSignHintText',
59 # Diag inline highlight groups and text property types
61 {name: 'LspDiagInlineError', default: true, linksto: 'SpellBad'},
62 {name: 'LspDiagInlineWarning', default: true, linksto: 'SpellCap'},
63 {name: 'LspDiagInlineInfo', default: true, linksto: 'SpellRare'},
64 {name: 'LspDiagInlineHint', default: true, linksto: 'SpellLocal'}
67 var override = &cursorline
68 && &cursorlineopt =~ '\<line\>\|\<screenline\>\|\<both\>'
70 prop_type_add('LspDiagInlineError',
71 {highlight: 'LspDiagInlineError',
74 prop_type_add('LspDiagInlineWarning',
75 {highlight: 'LspDiagInlineWarning',
78 prop_type_add('LspDiagInlineInfo',
79 {highlight: 'LspDiagInlineInfo',
82 prop_type_add('LspDiagInlineHint',
83 {highlight: 'LspDiagInlineHint',
87 # Diag virtual text highlight groups and text property types
89 {name: 'LspDiagVirtualTextError', default: true, linksto: 'SpellBad'},
90 {name: 'LspDiagVirtualTextWarning', default: true, linksto: 'SpellCap'},
91 {name: 'LspDiagVirtualTextInfo', default: true, linksto: 'SpellRare'},
92 {name: 'LspDiagVirtualTextHint', default: true, linksto: 'SpellLocal'},
94 prop_type_add('LspDiagVirtualTextError',
95 {highlight: 'LspDiagVirtualTextError', override: true})
96 prop_type_add('LspDiagVirtualTextWarning',
97 {highlight: 'LspDiagVirtualTextWarning', override: true})
98 prop_type_add('LspDiagVirtualTextInfo',
99 {highlight: 'LspDiagVirtualTextInfo', override: true})
100 prop_type_add('LspDiagVirtualTextHint',
101 {highlight: 'LspDiagVirtualTextHint', override: true})
103 autocmd_add([{group: 'LspOptionsChanged',
106 cmd: 'LspDiagsOptionsChanged()'}])
109 if opt.lspOptions.aleSupport
110 opt.lspOptions.autoHighlightDiags = false
115 pattern: 'ALEWantResults',
116 cmd: 'AleHook(g:ale_want_results_buffer)'
122 # Initialize the diagnostics features for the buffer 'bnr'
123 export def BufferInit(lspserver: dict<any>, bnr: number)
124 if opt.lspOptions.showDiagInBalloon
125 :set ballooneval balloonevalterm
126 setbufvar(bnr, '&balloonexpr', 'g:LspDiagExpr()')
130 # Function to sort the diagnostics in ascending order based on the line and
132 def DiagsSortFunc(a: dict<any>, b: dict<any>): number
133 var a_start: dict<number> = a.range.start
134 var b_start: dict<number> = b.range.start
135 var linediff: number = a_start.line - b_start.line
137 return a_start.character - b_start.character
142 # Sort diagnostics ascending based on line and character offset
143 def SortDiags(diags: list<dict<any>>): list<dict<any>>
144 return diags->sort(DiagsSortFunc)
147 # Remove the diagnostics stored for buffer "bnr"
148 export def DiagRemoveFile(bnr: number)
149 if diagsMap->has_key(bnr)
150 diagsMap->remove(bnr)
154 def DiagSevToSignName(severity: number): string
155 var typeMap: list<string> = ['LspDiagError', 'LspDiagWarning',
156 'LspDiagInfo', 'LspDiagHint']
160 return typeMap[severity - 1]
163 def DiagSevToInlineHLName(severity: number): string
164 var typeMap: list<string> = [
165 'LspDiagInlineError',
166 'LspDiagInlineWarning',
171 return 'LspDiagInlineHint'
173 return typeMap[severity - 1]
176 def DiagSevToVirtualTextHLName(severity: number): string
177 var typeMap: list<string> = [
178 'LspDiagVirtualTextError',
179 'LspDiagVirtualTextWarning',
180 'LspDiagVirtualTextInfo',
181 'LspDiagVirtualTextHint'
184 return 'LspDiagVirtualTextHint'
186 return typeMap[severity - 1]
189 def DiagSevToSymbolText(severity: number): string
190 var lspOpts = opt.lspOptions
191 var typeMap: list<string> = [
192 lspOpts.diagSignErrorText,
193 lspOpts.diagSignWarningText,
194 lspOpts.diagSignInfoText,
195 lspOpts.diagSignHintText
198 return lspOpts.diagSignHintText
200 return typeMap[severity - 1]
203 # Remove signs and text properties for diagnostics in buffer
204 def RemoveDiagVisualsForBuffer(bnr: number, all: bool = false)
205 var lspOpts = opt.lspOptions
206 if lspOpts.showDiagWithSign || all
207 # Remove all the existing diagnostic signs
208 sign_unplace('LSPDiag', {buffer: bnr})
211 if lspOpts.showDiagWithVirtualText || all
212 # Remove all the existing virtual text
213 prop_remove({type: 'LspDiagVirtualTextError', bufnr: bnr, all: true})
214 prop_remove({type: 'LspDiagVirtualTextWarning', bufnr: bnr, all: true})
215 prop_remove({type: 'LspDiagVirtualTextInfo', bufnr: bnr, all: true})
216 prop_remove({type: 'LspDiagVirtualTextHint', bufnr: bnr, all: true})
219 if lspOpts.highlightDiagInline || all
220 # Remove all the existing virtual text
221 prop_remove({type: 'LspDiagInlineError', bufnr: bnr, all: true})
222 prop_remove({type: 'LspDiagInlineWarning', bufnr: bnr, all: true})
223 prop_remove({type: 'LspDiagInlineInfo', bufnr: bnr, all: true})
224 prop_remove({type: 'LspDiagInlineHint', bufnr: bnr, all: true})
228 # Refresh the placed diagnostics in buffer "bnr"
229 # This inline signs, inline props, and virtual text diagnostics
230 export def DiagsRefresh(bnr: number, all: bool = false)
231 var lspOpts = opt.lspOptions
232 if !lspOpts.autoHighlightDiags
236 :silent! bnr->bufload()
238 RemoveDiagVisualsForBuffer(bnr, all)
240 if !diagsMap->has_key(bnr) ||
241 diagsMap[bnr].sortedDiagnostics->empty()
245 # Initialize default/fallback properties for diagnostic virtual text:
246 var diag_align: string = 'above'
247 var diag_wrap: string = 'truncate'
248 var diag_symbol: string = '┌─'
250 if lspOpts.diagVirtualTextAlign == 'below'
252 diag_wrap = 'truncate'
254 elseif lspOpts.diagVirtualTextAlign == 'after'
260 var signs: list<dict<any>> = []
261 var diags: list<dict<any>> = diagsMap[bnr].sortedDiagnostics
262 var inlineHLprops: list<list<list<number>>> = [[], [], [], [], []]
264 # TODO: prioritize most important severity if there are multiple
265 # diagnostics from the same line
266 var d_range = diag.range
267 var d_start = d_range.start
268 var d_end = d_range.end
269 var lnum = d_start.line + 1
270 if lspOpts.showDiagWithSign
271 signs->add({id: 0, buffer: bnr, group: 'LSPDiag',
272 lnum: lnum, name: DiagSevToSignName(diag.severity),
273 priority: 10 - diag.severity})
277 if lspOpts.highlightDiagInline
278 var propLocation: list<number> = [
279 lnum, util.GetLineByteFromPos(bnr, d_start) + 1,
280 d_end.line + 1, util.GetLineByteFromPos(bnr, d_end) + 1
282 inlineHLprops[diag.severity]->add(propLocation)
285 if lspOpts.showDiagWithVirtualText
287 var symbol: string = diag_symbol
289 if diag_align == 'after'
291 symbol = DiagSevToSymbolText(diag.severity)
293 var charIdx = util.GetCharIdxWithoutCompChar(bnr, d_start)
296 padding = strdisplaywidth(getline(lnum)[ : charIdx - 1])
300 prop_add(lnum, 0, {bufnr: bnr,
301 type: DiagSevToVirtualTextHLName(diag.severity),
302 text: $'{symbol} {diag.message}',
303 text_align: diag_align,
304 text_wrap: diag_wrap,
305 text_padding_left: padding})
307 catch /E966\|E964/ # Invalid lnum | Invalid col
308 # Diagnostics arrive asynchronously and the document changed while they
309 # were in transit. Ignore this as new once will arrive shortly.
313 if lspOpts.highlightDiagInline
315 if !inlineHLprops[i]->empty()
317 prop_add_list({bufnr: bnr, type: DiagSevToInlineHLName(i)},
319 catch /E966\|E964/ # Invalid lnum | Invalid col
325 if lspOpts.showDiagWithSign
326 signs->sign_placelist()
330 # Sends diagnostics to Ale
331 def SendAleDiags(bnr: number, timerid: number)
332 if !diagsMap->has_key(bnr)
336 # Convert to Ale's diagnostics format (:h ale-loclist-format)
337 ale#other_source#ShowResults(bnr, 'lsp',
338 diagsMap[bnr].sortedDiagnostics->mapnew((_, v) => {
339 return {text: v.message,
340 lnum: v.range.start.line + 1,
341 col: util.GetLineByteFromPos(bnr, v.range.start) + 1,
342 end_lnum: v.range.end.line + 1,
343 end_col: util.GetLineByteFromPos(bnr, v.range.end) + 1,
344 type: "EWIH"[v.severity - 1]}
349 # Hook called when Ale wants to retrieve new diagnostics
350 def AleHook(bnr: number)
351 ale#other_source#StartChecking(bnr, 'lsp')
352 timer_start(0, function('SendAleDiags', [bnr]))
355 # New LSP diagnostic messages received from the server for a file.
356 # Update the signs placed in the buffer for this file
357 export def ProcessNewDiags(bnr: number)
358 DiagsUpdateLocList(bnr)
360 var lspOpts = opt.lspOptions
361 if lspOpts.aleSupport
362 SendAleDiags(bnr, -1)
365 if bnr == -1 || !diagsMap->has_key(bnr)
369 var curmode: string = mode()
370 if curmode == 'i' || curmode == 'R' || curmode == 'Rv'
371 # postpone placing signs in insert mode and replace mode. These will be
372 # placed after the user returns to Normal mode.
373 setbufvar(bnr, 'LspDiagsUpdatePending', true)
380 # process a diagnostic notification message from the LSP server
381 # Notification: textDocument/publishDiagnostics
382 # Param: PublishDiagnosticsParams
383 export def DiagNotification(lspserver: dict<any>, uri: string, diags_arg: list<dict<any>>): void
384 # Diagnostics are disabled for this server?
385 var diagSupported = lspserver.features->get('diagnostics', true)
390 var fname: string = util.LspUriToFile(uri)
391 var bnr: number = fname->bufnr()
393 # Is this condition possible?
397 var newDiags: list<dict<any>> = diags_arg
399 if lspserver.needOffsetEncoding
400 # Decode the position encoding in all the diags
401 newDiags->map((_, dval) => {
402 lspserver.decodeRange(bnr, dval.range)
407 if lspserver.processDiagHandler != null_function
408 newDiags = lspserver.processDiagHandler(diags_arg)
411 # TODO: Is the buffer (bnr) always a loaded buffer? Should we load it here?
412 var lastlnum: number = bnr->getbufinfo()[0].linecount
414 # store the diagnostic for each line separately
415 var diagsByLnum: dict<list<dict<any>>> = {}
417 var diagWithinRange: list<dict<any>> = []
419 var d_start = diag.range.start
420 if d_start.line + 1 > lastlnum
421 # Make sure the line number is a valid buffer line number
422 d_start.line = lastlnum - 1
425 var lnum = d_start.line + 1
426 if !diagsByLnum->has_key(lnum)
427 diagsByLnum[lnum] = []
429 diagsByLnum[lnum]->add(diag)
431 diagWithinRange->add(diag)
434 var serverDiags: dict<list<any>> = diagsMap->has_key(bnr) ?
435 diagsMap[bnr].serverDiagnostics : {}
436 serverDiags[lspserver.id] = diagWithinRange
438 var serverDiagsByLnum: dict<dict<list<any>>> = diagsMap->has_key(bnr) ?
439 diagsMap[bnr].serverDiagnosticsByLnum : {}
440 serverDiagsByLnum[lspserver.id] = diagsByLnum
442 # store the diagnostic for each line separately
443 var joinedServerDiags: list<dict<any>> = []
444 for diags in serverDiags->values()
445 joinedServerDiags->extend(diags)
448 var sortedDiags = SortDiags(joinedServerDiags)
451 sortedDiagnostics: sortedDiags,
452 serverDiagnosticsByLnum: serverDiagsByLnum,
453 serverDiagnostics: serverDiags
458 # Notify user scripts that diags has been updated
459 if exists('#User#LspDiagsUpdated')
460 :doautocmd <nomodeline> User LspDiagsUpdated
464 # get the count of error in the current buffer
465 export def DiagsGetErrorCount(bnr: number): dict<number>
466 var diagSevCount: list<number> = [0, 0, 0, 0, 0]
467 if diagsMap->has_key(bnr)
468 var diags = diagsMap[bnr].sortedDiagnostics
470 var severity = diag->get('severity', 0)
471 diagSevCount[severity] += 1
476 Error: diagSevCount[1],
477 Warn: diagSevCount[2],
478 Info: diagSevCount[3],
479 Hint: diagSevCount[4]
483 # Map the LSP DiagnosticSeverity to a quickfix type character
484 def DiagSevToQfType(severity: number): string
485 var typeMap: list<string> = ['E', 'W', 'I', 'N']
491 return typeMap[severity - 1]
494 # Update the location list window for the current window with the diagnostic
496 # Returns true if diagnostics is not empty and false if it is empty.
497 def DiagsUpdateLocList(bnr: number, calledByCmd: bool = false): bool
498 var fname: string = bnr->bufname()->fnamemodify(':p')
503 var LspQfId: number = bnr->getbufvar('LspQfId', 0)
504 if LspQfId == 0 && !opt.lspOptions.autoPopulateDiags && !calledByCmd
505 # Diags location list is not present. Create the location list only if
506 # the 'autoPopulateDiags' option is set or the ":LspDiag show" command is
511 if LspQfId != 0 && getloclist(0, {id: LspQfId}).id != LspQfId
512 # Previously used location list for the diagnostics is gone
516 if !diagsMap->has_key(bnr) ||
517 diagsMap[bnr].sortedDiagnostics->empty()
519 setloclist(0, [], 'r', {id: LspQfId, items: []})
524 var qflist: list<dict<any>> = []
527 var diags = diagsMap[bnr].sortedDiagnostics
529 var d_range = diag.range
530 var d_start = d_range.start
531 var d_end = d_range.end
532 text = diag.message->substitute("\n\\+", "\n", 'g')
533 qflist->add({filename: fname,
534 lnum: d_start.line + 1,
535 col: util.GetLineByteFromPos(bnr, d_start) + 1,
536 end_lnum: d_end.line + 1,
537 end_col: util.GetLineByteFromPos(bnr, d_end) + 1,
539 type: DiagSevToQfType(diag.severity)})
543 var props = {title: 'Language Server Diagnostics', items: qflist}
548 setloclist(0, [], op, props)
550 setbufvar(bnr, 'LspQfId', getloclist(0, {id: 0}).id)
556 # Display the diagnostic messages from the LSP server for the current buffer
558 export def ShowAllDiags(): void
559 var bnr: number = bufnr()
560 if !DiagsUpdateLocList(bnr, true)
561 util.WarnMsg($'No diagnostic messages found for {@%}')
565 var save_winid = win_getid()
566 # make the diagnostics error list the active one and open it
567 var LspQfId: number = bnr->getbufvar('LspQfId', 0)
568 var LspQfNr: number = getloclist(0, {id: LspQfId, nr: 0}).nr
569 exe $':{LspQfNr} lhistory'
571 if !opt.lspOptions.keepFocusInDiags
572 save_winid->win_gotoid()
576 # Display the message of "diag" in a popup window right below the position in
577 # the diagnostic message.
578 def ShowDiagInPopup(diag: dict<any>)
579 var d_start = diag.range.start
580 var dlnum = d_start.line + 1
581 var ltext = dlnum->getline()
582 var dlcol = ltext->byteidxcomp(d_start.character) + 1
584 var lastline = line('$')
586 # The line number is outside the last line in the file.
590 # The column is outside the last character in line.
591 dlcol = ltext->len() + 1
593 var d = screenpos(0, dlnum, dlcol)
595 # If the diag position cannot be converted to Vim lnum/col, then use
596 # the current cursor position
597 d = {row: line('.'), col: col('.')}
600 # Display a popup right below the diagnostics position
601 var msg = diag.message->split("\n")
602 var msglen = msg->reduce((acc, val) => max([acc, val->strcharlen()]), 0)
605 ppopts.pos = 'topleft'
606 ppopts.line = d.row + 1
617 popup_create(msg, ppopts)
620 # Display the "diag" message in a popup or in the status message area
621 def DisplayDiag(diag: dict<any>)
622 if opt.lspOptions.showDiagInPopup
623 # Display the diagnostic message in a popup window.
624 ShowDiagInPopup(diag)
626 # Display the diagnostic message in the status message area
631 # Show the diagnostic message for the current line
632 export def ShowCurrentDiag(atPos: bool)
633 var bnr: number = bufnr()
634 var lnum: number = line('.')
635 var col: number = charcol('.')
636 var diag: dict<any> = GetDiagByPos(bnr, lnum, col, atPos)
638 util.WarnMsg($'No diagnostic messages found for current {atPos ? "position" : "line"}')
644 # Show the diagnostic message for the current line without linebreak
645 export def ShowCurrentDiagInStatusLine()
646 var bnr: number = bufnr()
647 var lnum: number = line('.')
648 var col: number = charcol('.')
649 var diag: dict<any> = GetDiagByPos(bnr, lnum, col)
651 # 15 is a enough length not to cause line break
652 var max_width = &columns - 15
654 if diag->has_key('code')
655 code = $'[{diag.code}] '
657 var msgNoLineBreak = code .. substitute(substitute(diag.message, "\n", ' ', ''), "\\n", ' ', '')
658 :echo msgNoLineBreak[ : max_width]
664 # Get the diagnostic from the LSP server for a particular line and character
666 export def GetDiagByPos(bnr: number, lnum: number, col: number,
667 atPos: bool = false): dict<any>
668 var diags_in_line = GetDiagsByLine(bnr, lnum)
670 for diag in diags_in_line
672 var startCharIdx = util.GetCharIdxWithoutCompChar(bnr, r.start)
673 var endCharIdx = util.GetCharIdxWithoutCompChar(bnr, r.end)
675 if col >= startCharIdx + 1 && col < endCharIdx + 1
678 elseif col <= startCharIdx + 1
683 # No diagnostic to the right of the position, return the last one instead
684 if !atPos && diags_in_line->len() > 0
685 return diags_in_line[-1]
691 # Get all diagnostics from the LSP server for a particular line in a file
692 export def GetDiagsByLine(bnr: number, lnum: number, lspserver: dict<any> = null_dict): list<dict<any>>
693 if !diagsMap->has_key(bnr)
697 var diags: list<dict<any>> = []
699 var serverDiagsByLnum = diagsMap[bnr].serverDiagnosticsByLnum
701 if lspserver == null_dict
702 for diagsByLnum in serverDiagsByLnum->values()
703 if diagsByLnum->has_key(lnum)
704 diags->extend(diagsByLnum[lnum])
708 if !serverDiagsByLnum->has_key(lspserver.id)
711 if serverDiagsByLnum[lspserver.id]->has_key(lnum)
712 diags = serverDiagsByLnum[lspserver.id][lnum]
716 return diags->sort((a, b) => {
717 return a.range.start.character - b.range.start.character
721 # Utility function to do the actual jump
722 def JumpDiag(diag: dict<any>)
723 var startPos: dict<number> = diag.range.start
724 setcursorcharpos(startPos.line + 1,
725 util.GetCharIdxWithoutCompChar(bufnr(), startPos) + 1)
727 if !opt.lspOptions.showDiagWithVirtualText
733 # jump to the next/previous/first diagnostic message in the current buffer
734 export def LspDiagsJump(which: string, a_count: number = 0): void
735 var fname: string = expand('%:p')
739 var bnr: number = bufnr()
741 if !diagsMap->has_key(bnr) ||
742 diagsMap[bnr].sortedDiagnostics->empty()
743 util.WarnMsg($'No diagnostic messages found for {fname}')
747 var diags = diagsMap[bnr].sortedDiagnostics
759 # Find the entry just before the current line (binary search)
760 var count = a_count > 1 ? a_count : 1
761 var curlnum: number = line('.')
762 var curcol: number = charcol('.')
763 for diag in (which == 'next' || which == 'here') ?
764 diags : diags->copy()->reverse()
765 var d_start = diag.range.start
766 var lnum = d_start.line + 1
767 var col = util.GetCharIdxWithoutCompChar(bnr, d_start) + 1
768 if (which == 'next' && (lnum > curlnum || lnum == curlnum && col > curcol))
769 || (which == 'prev' && (lnum < curlnum || lnum == curlnum
771 || (which == 'here' && (lnum == curlnum && col >= curcol))
773 # Skip over as many diags as "count" dictates
784 # If [count] exceeded the remaining diags
785 if which == 'next' && a_count > 1 && a_count != count
790 # If [count] exceeded the previous diags
791 if which == 'prev' && a_count > 1 && a_count != count
797 util.WarnMsg('No more diagnostics found on this line')
799 util.WarnMsg('No more diagnostics found')
803 # Return the sorted diagnostics for buffer "bnr". Default is the current
804 # buffer. A copy of the diagnostics is returned so that the caller can modify
806 export def GetDiagsForBuf(bnr: number = bufnr()): list<dict<any>>
807 if !diagsMap->has_key(bnr) ||
808 diagsMap[bnr].sortedDiagnostics->empty()
812 return diagsMap[bnr].sortedDiagnostics->deepcopy()
815 # Return the diagnostic text from the LSP server for the current mouse line to
816 # display in a balloon
817 def g:LspDiagExpr(): any
818 if !opt.lspOptions.showDiagInBalloon
822 var diagsInfo: list<dict<any>> =
823 GetDiagsByLine(v:beval_bufnr, v:beval_lnum)
824 if diagsInfo->empty()
825 # No diagnostic for the current cursor location
828 var diagFound: dict<any> = {}
829 for diag in diagsInfo
831 var startcol = util.GetLineByteFromPos(v:beval_bufnr, r.start) + 1
832 var endcol = util.GetLineByteFromPos(v:beval_bufnr, r.end) + 1
833 if v:beval_col >= startcol && v:beval_col < endcol
838 if diagFound->empty()
839 # mouse is outside of the diagnostics range
843 # return the found diagnostic
844 return diagFound.message->split("\n")
847 # Track the current diagnostics auto highlight enabled/disabled state. Used
848 # when the "autoHighlightDiags" option value is changed.
849 var save_autoHighlightDiags = opt.lspOptions.autoHighlightDiags
850 var save_highlightDiagInline = opt.lspOptions.highlightDiagInline
851 var save_showDiagWithSign = opt.lspOptions.showDiagWithSign
852 var save_showDiagWithVirtualText = opt.lspOptions.showDiagWithVirtualText
854 # Enable the LSP diagnostics highlighting
855 export def DiagsHighlightEnable()
856 opt.lspOptions.autoHighlightDiags = true
857 save_autoHighlightDiags = true
858 for binfo in getbufinfo({bufloaded: true})
859 if diagsMap->has_key(binfo.bufnr)
860 DiagsRefresh(binfo.bufnr)
865 # Disable the LSP diagnostics highlighting in all the buffers
866 export def DiagsHighlightDisable()
867 # turn off all diags highlight
868 opt.lspOptions.autoHighlightDiags = false
869 save_autoHighlightDiags = false
870 for binfo in getbufinfo()
871 if diagsMap->has_key(binfo.bufnr)
872 RemoveDiagVisualsForBuffer(binfo.bufnr)
877 # Some options are changed. If 'autoHighlightDiags' option is changed, then
878 # either enable or disable diags auto highlight.
879 export def LspDiagsOptionsChanged()
880 if save_autoHighlightDiags && !opt.lspOptions.autoHighlightDiags
881 DiagsHighlightDisable()
882 elseif !save_autoHighlightDiags && opt.lspOptions.autoHighlightDiags
883 DiagsHighlightEnable()
886 if save_highlightDiagInline != opt.lspOptions.highlightDiagInline
887 || save_showDiagWithSign != opt.lspOptions.showDiagWithSign
888 || save_showDiagWithVirtualText != opt.lspOptions.showDiagWithVirtualText
889 save_highlightDiagInline = opt.lspOptions.highlightDiagInline
890 save_showDiagWithSign = opt.lspOptions.showDiagWithSign
891 save_showDiagWithVirtualText = opt.lspOptions.showDiagWithVirtualText
892 for binfo in getbufinfo({bufloaded: true})
893 if diagsMap->has_key(binfo.bufnr)
894 DiagsRefresh(binfo.bufnr, true)
900 # vim: tabstop=8 shiftwidth=2 softtabstop=2