Skip to content

Commit 4c5464a

Browse files
authored
Merge pull request #2652 from bhcleek/text-properties
highlight using text properties instead of matchaddpos() when possible
2 parents 810e4b9 + e427e96 commit 4c5464a

File tree

4 files changed

+108
-42
lines changed

4 files changed

+108
-42
lines changed

autoload/go/guru.vim

+2-2
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,7 @@ function! s:same_ids_highlight(exit_val, output, mode) abort
477477
let l:matches = add(l:matches, [str2nr(pos[-2]), str2nr(pos[-1]), str2nr(poslen)])
478478
endfor
479479

480-
call go#util#MatchAddPos('goSameId', l:matches)
480+
call go#util#HighlightPositions('goSameId', l:matches)
481481

482482
if go#config#AutoSameids()
483483
" re-apply SameIds at the current cursor position at the time the buffer
@@ -492,7 +492,7 @@ endfunction
492492
" ClearSameIds returns 0 when it removes goSameId groups and non-zero if no
493493
" goSameId groups are found.
494494
function! go#guru#ClearSameIds() abort
495-
let l:cleared = go#util#ClearGroupFromMatches('goSameId')
495+
let l:cleared = go#util#ClearHighlights('goSameId')
496496

497497
if !l:cleared
498498
return 1

autoload/go/lsp.vim

+32-32
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,9 @@ function! s:newlsp() abort
248248
endif
249249

250250
for l:diag in l:data.diagnostics
251+
" TODO(bc): cache the raw diagnostics when they're not for the
252+
" current buffer so that they can be processed when it is the
253+
" current buffer and highlight the areas of concern.
251254
let [l:error, l:matchpos] = s:errorFromDiagnostic(l:diag, l:bufname, l:fname)
252255
let l:diagnostics = add(l:diagnostics, l:error)
253256

@@ -1189,45 +1192,42 @@ function! s:errorFromDiagnostic(diagnostic, bufname, fname) abort
11891192
endfunction
11901193

11911194
function! s:highlightMatches(errorMatches, warningMatches) abort
1192-
" TODO(bc): use text properties instead of matchaddpos
1193-
if exists("*matchaddpos")
1194-
" set buffer variables for errors and warnings to zero values
1195-
let b:go_diagnostic_matches = {'errors': [], 'warnings': []}
1196-
1197-
if hlexists('goDiagnosticError')
1198-
" clear the old matches just before adding the new ones to keep flicker
1199-
" to a minimum.
1200-
call go#util#ClearGroupFromMatches('goDiagnosticError')
1201-
if go#config#HighlightDiagnosticErrors()
1202-
let b:go_diagnostic_matches.errors = copy(a:errorMatches)
1203-
call go#util#MatchAddPos('goDiagnosticError', a:errorMatches)
1204-
endif
1195+
" set buffer variables for errors and warnings to zero values
1196+
let b:go_diagnostic_matches = {'errors': [], 'warnings': []}
1197+
1198+
if hlexists('goDiagnosticError')
1199+
" clear the old matches just before adding the new ones to keep flicker
1200+
" to a minimum.
1201+
call go#util#ClearHighlights('goDiagnosticError')
1202+
if go#config#HighlightDiagnosticErrors()
1203+
let b:go_diagnostic_matches.errors = copy(a:errorMatches)
1204+
call go#util#HighlightPositions('goDiagnosticError', a:errorMatches)
12051205
endif
1206+
endif
12061207

1207-
if hlexists('goDiagnosticWarning')
1208-
" clear the old matches just before adding the new ones to keep flicker
1209-
" to a minimum.
1210-
call go#util#ClearGroupFromMatches('goDiagnosticWarning')
1211-
if go#config#HighlightDiagnosticWarnings()
1212-
let b:go_diagnostic_matches.warnings = copy(a:warningMatches)
1213-
call go#util#MatchAddPos('goDiagnosticWarning', a:warningMatches)
1214-
endif
1208+
if hlexists('goDiagnosticWarning')
1209+
" clear the old matches just before adding the new ones to keep flicker
1210+
" to a minimum.
1211+
call go#util#ClearHighlights('goDiagnosticWarning')
1212+
if go#config#HighlightDiagnosticWarnings()
1213+
let b:go_diagnostic_matches.warnings = copy(a:warningMatches)
1214+
call go#util#HighlightPositions('goDiagnosticWarning', a:warningMatches)
12151215
endif
1216-
1217-
" re-apply matches at the time the buffer is displayed in a new window or
1218-
" redisplayed in an existing window: e.g. :edit,
1219-
augroup vim-go-diagnostics
1220-
autocmd! * <buffer>
1221-
autocmd BufWinEnter <buffer> nested call s:highlightMatches(b:go_diagnostic_matches.errors, b:go_diagnostic_matches.warnings)
1222-
augroup end
12231216
endif
1217+
1218+
" re-apply matches at the time the buffer is displayed in a new window or
1219+
" redisplayed in an existing window: e.g. :edit,
1220+
augroup vim-go-diagnostics
1221+
autocmd! * <buffer>
1222+
autocmd BufWinEnter <buffer> nested call s:highlightMatches(b:go_diagnostic_matches.errors, b:go_diagnostic_matches.warnings)
1223+
augroup end
12241224
endfunction
12251225

1226-
" ClearDiagnosticsMatches removes all goDiagnosticError and
1226+
" ClearDiagnosticsHighlights removes all goDiagnosticError and
12271227
" goDiagnosticWarning matches.
1228-
function! go#lsp#ClearDiagnosticMatches() abort
1229-
call go#util#ClearGroupFromMatches('goDiagnosticError')
1230-
call go#util#ClearGroupFromMatches('goDiagnosticWarning')
1228+
function! go#lsp#ClearDiagnosticHighlights() abort
1229+
call go#util#ClearHighlights('goDiagnosticError')
1230+
call go#util#ClearHighlights('goDiagnosticWarning')
12311231
endfunction
12321232

12331233
" restore Vi compatibility settings

autoload/go/util.vim

+60-6
Original file line numberDiff line numberDiff line change
@@ -551,11 +551,17 @@ function! go#util#SetEnv(name, value) abort
551551
return function('go#util#SetEnv', [a:name, l:oldvalue], l:state)
552552
endfunction
553553

554-
function! go#util#ClearGroupFromMatches(group) abort
555-
if !exists("*matchaddpos")
556-
return 0
554+
function! go#util#ClearHighlights(group) abort
555+
if exists('*prop_remove')
556+
return prop_remove({'type': a:group, 'all': 1})
557557
endif
558558

559+
if exists("*matchaddpos")
560+
return s:clear_group_from_matches(a:group)
561+
endif
562+
endfunction
563+
564+
function! s:clear_group_from_matches(group) abort
559565
let l:cleared = 0
560566

561567
let m = getmatches()
@@ -589,9 +595,57 @@ endfunction
589595
function! s:noop(...) abort dict
590596
endfunction
591597

592-
" go#util#MatchAddPos works around matchaddpos()'s limit of only 8 positions
593-
" per call by calling matchaddpos() with no more than 8 positions per call.
594-
function! go#util#MatchAddPos(group, pos)
598+
" go#util#HighlightPositions highlights using text properties if possible and
599+
" falls back to matchaddpos() if necessary. It works around matchaddpos()'s
600+
" limit of only 8 positions per call by calling matchaddpos() with no more
601+
" than 8 positions per call.
602+
"
603+
" pos should be a list of 3 element lists. The lists should be [line, col,
604+
" length] as used by matchaddpos().
605+
function! go#util#HighlightPositions(group, pos) abort
606+
if exists('*prop_add')
607+
for l:pos in a:pos
608+
" use a single line prop by default
609+
let l:prop = {'type': a:group, 'length': l:pos[2]}
610+
611+
" specify end line and column if needed.
612+
let l:line = getline(l:pos[0])
613+
614+
" l:max is the 1-based index within the buffer of the first character after l:pos.
615+
let l:max = line2byte(l:pos[0]) + l:pos[1] + l:pos[2] - 1
616+
617+
if has('patch-8.2.115')
618+
" Use byte2line as long as 8.2.115 (which resolved
619+
" https://github.com/vim/vim/issues/5334) is available.
620+
let l:end_lnum = byte2line(l:max)
621+
622+
if l:pos[0] != l:end_lnum
623+
let l:end_col = l:max - line2byte(l:end_lnum)
624+
let l:prop = {'type': a:group, 'end_lnum': l:end_lnum, 'end_col': l:end_col}
625+
endif
626+
elseif l:pos[1] + l:pos[2] - 1 > len(l:line)
627+
let l:end_lnum = l:pos[0]
628+
let l:end_col = l:pos[1] + l:pos[2] - 1
629+
while line2byte(l:end_lnum+1) < l:max
630+
let l:end_lnum += 1
631+
let l:end_col -= line2byte(l:end_lnum)
632+
endwhile
633+
let l:prop = {'type': a:group, 'end_lnum': l:end_lnum, 'end_col': l:end_col}
634+
endif
635+
call prop_add(l:pos[0], l:pos[1], l:prop)
636+
endfor
637+
return
638+
endif
639+
640+
if exists('*matchaddpos')
641+
return s:matchaddpos(a:group, a:pos)
642+
endif
643+
endfunction
644+
645+
646+
" s:matchaddpos works around matchaddpos()'s limit of only 8 positions per
647+
" call by calling matchaddpos() with no more than 8 positions per call.
648+
function! s:matchaddpos(group, pos) abort
595649
let l:partitions = []
596650
let l:partitionsIdx = 0
597651
let l:posIdx = 0

ftplugin/go.vim

+14-2
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,18 @@ if get(g:, "go_textobj_enabled", 1)
7474
xnoremap <buffer> <silent> [[ :<c-u>call go#textobj#FunctionJump('v', 'prev')<cr>
7575
endif
7676

77+
if exists('*prop_type_add')
78+
if empty(prop_type_get('goSameId'))
79+
call prop_type_add('goSameId', {'highlight': 'goSameId'})
80+
endif
81+
if empty(prop_type_get('goDiagnosticError'))
82+
call prop_type_add('goDiagnosticError', {'highlight': 'goDiagnosticError'})
83+
endif
84+
if empty(prop_type_get('goDiagnosticWarning'))
85+
call prop_type_add('goDiagnosticWarning', {'highlight': 'goDiagnosticWarning'})
86+
endif
87+
endif
88+
7789
" Autocommands
7890
" ============================================================================
7991
"
@@ -117,10 +129,10 @@ augroup vim-go-buffer
117129
" clear diagnostics when the buffer is unloaded from its last window so that
118130
" loading another buffer (especially of a different filetype) in the same
119131
" window doesn't highlight th previously loaded buffer's diagnostics.
120-
autocmd BufWinLeave <buffer> call go#lsp#ClearDiagnosticMatches()
132+
autocmd BufWinLeave <buffer> call go#lsp#ClearDiagnosticHighlights()
121133
" clear diagnostics when a new buffer is loaded in the window so that the
122134
" previous buffer's diagnostcs aren't used.
123-
autocmd BufWinEnter <buffer> call go#lsp#ClearDiagnosticMatches()
135+
autocmd BufWinEnter <buffer> call go#lsp#ClearDiagnosticHighlights()
124136

125137
autocmd BufEnter <buffer>
126138
\ if go#config#AutodetectGopath() && !exists('b:old_gopath')

0 commit comments

Comments
 (0)