@@ -527,75 +527,76 @@ impl LanguageClient {
527
527
} ) ?;
528
528
529
529
if !self . get_config ( |c| c. is_nvim ) ? {
530
- // Clear old highlights.
531
- let ids = self . get_state ( |state| state. highlight_match_ids . clone ( ) ) ?;
532
- self . vim ( ) ?
533
- . rpcclient
534
- . notify ( "s:MatchDelete" , json ! ( [ ids] ) ) ?;
535
-
536
- // Group diagnostics by severity so we can highlight them
537
- // in a single call.
538
- let mut match_groups: HashMap < _ , Vec < _ > > = HashMap :: new ( ) ;
539
-
540
- for dn in diagnostics {
541
- let severity = dn. severity . unwrap_or ( DiagnosticSeverity :: Hint ) . to_int ( ) ?;
542
- match_groups
543
- . entry ( severity)
544
- . or_insert_with ( Vec :: new)
545
- . push ( dn) ;
546
- }
530
+ // this needs to be in this locked block so that notifications that arrive too close to
531
+ // each other do not have the chance to cause any race conditions.
532
+ self . update_state ( |state| {
533
+ // Clear old highlights.
534
+ let ids = state. highlight_match_ids . clone ( ) ;
535
+ state. vim . rpcclient . notify ( "s:MatchDelete" , json ! ( [ ids] ) ) ?;
536
+
537
+ // Group diagnostics by severity so we can highlight them
538
+ // in a single call.
539
+ let mut match_groups: HashMap < _ , Vec < _ > > = HashMap :: new ( ) ;
540
+
541
+ for dn in diagnostics {
542
+ let severity = dn. severity . unwrap_or ( DiagnosticSeverity :: Hint ) . to_int ( ) ?;
543
+ match_groups
544
+ . entry ( severity)
545
+ . or_insert_with ( Vec :: new)
546
+ . push ( dn) ;
547
+ }
547
548
548
- let mut new_match_ids = Vec :: new ( ) ;
549
+ let mut new_match_ids = Vec :: new ( ) ;
549
550
550
- for ( severity, dns) in match_groups {
551
- let hl_group = diagnostics_display
552
- . get ( & severity)
553
- . ok_or_else ( || anyhow ! ( "Failed to get display" ) ) ?
554
- . texthl
555
- . clone ( ) ;
556
- let ranges: Vec < Vec < _ > > = dns
557
- . iter ( )
558
- . flat_map ( |dn| {
559
- if dn. range . start . line == dn. range . end . line {
560
- let length = dn. range . end . character - dn. range . start . character ;
561
- // Vim line numbers are 1 off
562
- // `matchaddpos` expects an array of [line, col, length]
563
- // for each match.
564
- vec ! [ vec![
565
- dn. range. start. line + 1 ,
566
- dn. range. start. character + 1 ,
567
- length,
568
- ] ]
569
- } else {
570
- let mut middle_lines: Vec < _ > = ( dn. range . start . line + 1
571
- ..dn. range . end . line )
572
- . map ( |l| vec ! [ l + 1 ] )
573
- . collect ( ) ;
574
- let start_line = vec ! [
575
- dn. range. start. line + 1 ,
576
- dn. range. start. character + 1 ,
577
- 999_999 , //Clear to the end of the line
578
- ] ;
579
- let end_line =
580
- vec ! [ dn. range. end. line + 1 , 1 , dn. range. end. character + 1 ] ;
581
- middle_lines. push ( start_line) ;
582
- // For a multi-ringe range ending at the exact start of the last line,
583
- // don't highlight the first character of the last line.
584
- if dn. range . end . character > 0 {
585
- middle_lines. push ( end_line) ;
551
+ for ( severity, dns) in match_groups {
552
+ let hl_group = diagnostics_display
553
+ . get ( & severity)
554
+ . ok_or_else ( || anyhow ! ( "Failed to get display" ) ) ?
555
+ . texthl
556
+ . clone ( ) ;
557
+ let ranges: Vec < Vec < _ > > = dns
558
+ . iter ( )
559
+ . flat_map ( |dn| {
560
+ if dn. range . start . line == dn. range . end . line {
561
+ let length = dn. range . end . character - dn. range . start . character ;
562
+ // Vim line numbers are 1 off
563
+ // `matchaddpos` expects an array of [line, col, length]
564
+ // for each match.
565
+ vec ! [ vec![
566
+ dn. range. start. line + 1 ,
567
+ dn. range. start. character + 1 ,
568
+ length,
569
+ ] ]
570
+ } else {
571
+ let mut middle_lines: Vec < _ > = ( dn. range . start . line + 1
572
+ ..dn. range . end . line )
573
+ . map ( |l| vec ! [ l + 1 ] )
574
+ . collect ( ) ;
575
+ let start_line = vec ! [
576
+ dn. range. start. line + 1 ,
577
+ dn. range. start. character + 1 ,
578
+ 999_999 , //Clear to the end of the line
579
+ ] ;
580
+ let end_line =
581
+ vec ! [ dn. range. end. line + 1 , 1 , dn. range. end. character + 1 ] ;
582
+ middle_lines. push ( start_line) ;
583
+ // For a multi-ringe range ending at the exact start of the last line,
584
+ // don't highlight the first character of the last line.
585
+ if dn. range . end . character > 0 {
586
+ middle_lines. push ( end_line) ;
587
+ }
588
+ middle_lines
586
589
}
587
- middle_lines
588
- }
589
- } )
590
- . collect ( ) ;
590
+ } )
591
+ . collect ( ) ;
592
+
593
+ let match_id = state
594
+ . vim
595
+ . rpcclient
596
+ . call ( "matchaddpos" , json ! ( [ hl_group, ranges] ) ) ?;
597
+ new_match_ids. push ( match_id) ;
598
+ }
591
599
592
- let match_id = self
593
- . vim ( ) ?
594
- . rpcclient
595
- . call ( "matchaddpos" , json ! ( [ hl_group, ranges] ) ) ?;
596
- new_match_ids. push ( match_id) ;
597
- }
598
- self . update_state ( |state| {
599
600
state. highlight_match_ids = new_match_ids;
600
601
Ok ( ( ) )
601
602
} ) ?;
0 commit comments