All patches and comments are welcome. Please squash your changes to logical
commits before using git-format-patch and git-send-email to
patches@git.madduck.net.
If you'd read over the Git project's submission guidelines and adhered to them,
I'd be especially grateful.
5 Save g:ale_run_synchronously
6 Save g:ale_set_highlights
8 Save g:ale_set_quickfix
10 Save g:ale_exclude_highlights
11 Save b:ale_exclude_highlights
13 runtime autoload/ale/virtualtext.vim
14 runtime autoload/ale/highlight.vim
16 let g:ale_run_synchronously = 1
17 unlet! g:ale_run_synchronously_callbacks
18 let g:ale_set_highlights = 1
19 let g:ale_set_signs = 1
20 let g:ale_buffer_info = {}
22 " Disable features we don't need for these tests.
23 let g:ale_set_quickfix = 0
24 let g:ale_set_loclist = 0
25 let g:ale_echo_cursor = 0
26 let g:ale_exclude_highlights = []
27 let b:ale_exclude_highlights = []
29 function! GenerateResults(buffer, output)
52 let g:has_nvim_highlight = exists('*nvim_buf_add_highlight') && exists('*nvim_buf_clear_namespace')
53 let g:nvim_highlight_matches = {}
55 function! ale#highlight#nvim_buf_clear_namespace(buffer, ns_id, line_start, line_end) abort
57 throw 'nvim api behavior not supported'
60 let l:matches = get(g:nvim_highlight_matches, a:buffer, [])
63 \ {_, val -> val.pos1[0] < (a:line_start + 1) },
67 function! ale#highlight#nvim_buf_add_highlight(buffer, ns_id, hl_group, line, col_start, col_end) abort
69 throw 'nvim api behavior not supported'
72 let l:matches = get(g:nvim_highlight_matches, a:buffer, [])
73 let g:nvim_highlight_matches[a:buffer] = l:matches
76 \ 'group': a:hl_group,
78 \ 'pos1': [a:line + 1, a:col_start + 1, a:col_end - a:col_start],
81 call add(l:matches, l:new_match)
82 " sort by line number to emulate getmatches faithfully
83 call sort(l:matches, {m1, m2 -> m1.pos1[0] - m2.pos1[0]})
86 " We don't care what the IDs are, just that we have some matches.
87 " The IDs are generated.
88 function! GetMatchesWithoutIDs() abort
89 if g:has_nvim_highlight
90 return get(g:nvim_highlight_matches, bufnr(''), [])
92 let l:list = getmatches()
95 call remove(l:item, 'id')
102 function! GetLinkedGroup(grp) abort
103 return synIDattr(synIDtrans(hlID(a:grp)), 'name')
106 call ale#linter#Define('testft', {
108 \ 'executable': has('win32') ? 'cmd': 'echo',
109 \ 'command': has('win32') ? 'echo' : '/bin/sh -c ''echo''',
110 \ 'callback': 'GenerateResults',
112 highlight link SomeOtherGroup SpellBad
117 unlet! g:ale_run_synchronously_callbacks
120 unlet! g:has_nvim_highlight
121 unlet! g:nvim_highlight_matches
123 delfunction GenerateResults
124 call ale#linter#Reset()
126 call ale#sign#Clear()
127 if has('textprop') && has('popupwin')
128 call prop_type_delete('ale')
130 highlight clear SomeOtherGroup
132 runtime autoload/ale/highlight.vim
134 Given testft(A Javscript file with warnings/errors):
140 " Autoloading virtualtext.vim first should still properly initialize hl-groups
141 Execute(Loading virtualtext first does not break highlight groups):
144 \ GetLinkedGroup("ALEError")
147 \ GetLinkedGroup("ALEWarning")
149 Execute(Highlights should be set when a linter runs):
151 call ale#test#FlushJobs()
155 \ {'group': 'ALEError', 'priority': 10, 'pos1': [1, 1, 1]},
156 \ {'group': 'ALEWarning', 'priority': 10, 'pos1': [2, 1, 1]},
157 \ {'group': 'ALEError', 'priority': 10, 'pos1': [3, 5, 1]}
159 \ GetMatchesWithoutIDs()
161 " This test is important for preventing ALE from showing highlights for
163 Execute(Highlights set by ALE should be removed when buffer cleanup is done):
164 call ale#engine#InitBufferInfo(bufnr('%'))
166 call ale#highlight#SetHighlights(bufnr('%'), [
167 \ {'bufnr': bufnr('%'), 'type': 'E', 'lnum': 3, 'col': 2},
170 if !g:has_nvim_highlight
171 " This check doesn't work with the new API, for some reason.
173 \ [{'group': 'ALEError', 'priority': 10, 'pos1': [3, 2, 1]}],
174 \ GetMatchesWithoutIDs()
177 call ale#engine#Cleanup(bufnr('%'))
179 AssertEqual [], GetMatchesWithoutIDs()
181 Execute(Highlights should be cleared when buffers are hidden):
182 call ale#engine#InitBufferInfo(bufnr('%'))
183 " The second item should be ignored, as it has no column infomration.
184 let g:ale_buffer_info[bufnr('%')].loclist = [
185 \ {'bufnr': bufnr('%'), 'type': 'E', 'lnum': 3, 'col': 2},
186 \ {'bufnr': bufnr('%'), 'type': 'E', 'lnum': 4, 'col': 0},
188 call ale#highlight#SetHighlights(
190 \ g:ale_buffer_info[bufnr('%')].loclist
193 AssertEqual 1, len(GetMatchesWithoutIDs()), 'The highlights weren''t initially set!'
195 call ale#highlight#BufferHidden(bufnr('%'))
197 AssertEqual 0, len(GetMatchesWithoutIDs()), 'The highlights weren''t cleared!'
199 call ale#highlight#UpdateHighlights()
201 AssertEqual 1, len(GetMatchesWithoutIDs()), 'The highlights weren''t set again!'
203 Execute(Only ALE highlights should be restored when buffers are restored):
204 call ale#engine#InitBufferInfo(bufnr('%'))
205 let g:ale_buffer_info[bufnr('%')].loclist = [
206 \ {'bufnr': bufnr('%'), 'type': 'E', 'lnum': 3, 'col': 2},
208 call ale#highlight#SetHighlights(
210 \ g:ale_buffer_info[bufnr('%')].loclist
213 call matchaddpos('SomeOtherGroup', [[1, 1, 1]])
215 " We should have both highlights.
216 if g:has_nvim_highlight
217 " When the newer NeoVim API is used, we don't have to worry about
218 " other highlights, namespacing is available.
221 \ {'group': 'ALEError', 'priority': 10, 'pos1': [3, 2, 1]},
223 \ GetMatchesWithoutIDs()
227 \ {'group': 'ALEError', 'priority': 10, 'pos1': [3, 2, 1]},
228 \ {'group': 'SomeOtherGroup', 'priority': 10, 'pos1': [1, 1, 1]},
230 \ sort(GetMatchesWithoutIDs(), {m1, m2 -> m1.group < m2.group ? -1 : 1})
233 call ale#highlight#BufferHidden(bufnr('%'))
235 " We should remove our highlight, but not the other one.
236 if g:has_nvim_highlight
237 AssertEqual [], GetMatchesWithoutIDs()
241 \ {'group': 'SomeOtherGroup', 'priority': 10, 'pos1': [1, 1, 1]}
243 \ GetMatchesWithoutIDs()
246 call ale#highlight#UpdateHighlights()
248 " Our highlight should apper again.
249 if g:has_nvim_highlight
252 \ {'group': 'ALEError', 'priority': 10, 'pos1': [3, 2, 1]},
254 \ GetMatchesWithoutIDs()
258 \ {'group': 'ALEError', 'priority': 10, 'pos1': [3, 2, 1]},
259 \ {'group': 'SomeOtherGroup', 'priority': 10, 'pos1': [1, 1, 1]},
261 \ sort(GetMatchesWithoutIDs(), {m1, m2 -> m1.group < m2.group ? -1 : 1})
264 Execute(Highlight end columns should set an appropriate size):
265 call ale#highlight#SetHighlights(bufnr('%'), [
266 \ {'bufnr': bufnr('%'), 'type': 'E', 'lnum': 3, 'col': 2, 'end_col': 5},
267 \ {'bufnr': bufnr('%'), 'type': 'W', 'lnum': 4, 'col': 1, 'end_col': 5},
272 \ {'group': 'ALEError', 'priority': 10, 'pos1': [3, 2, 4]},
273 \ {'group': 'ALEWarning', 'priority': 10, 'pos1': [4, 1, 5]},
275 \ GetMatchesWithoutIDs()
277 Execute(Highlight end columns should set an appropriate size):
278 call ale#highlight#SetHighlights(bufnr('%'), [
279 \ {'bufnr': bufnr('%') - 1, 'type': 'E', 'lnum': 1, 'col': 1},
280 \ {'bufnr': bufnr('%'), 'type': 'E', 'lnum': 1, 'col': 1},
281 \ {'bufnr': bufnr('%'), 'type': 'E', 'lnum': 2, 'col': 1},
282 \ {'bufnr': bufnr('%'), 'type': 'E', 'sub_type': 'style', 'lnum': 3, 'col': 1},
283 \ {'bufnr': bufnr('%'), 'type': 'W', 'lnum': 4, 'col': 1},
284 \ {'bufnr': bufnr('%'), 'type': 'W', 'lnum': 5, 'col': 1},
285 \ {'bufnr': bufnr('%'), 'type': 'W', 'sub_type': 'style', 'lnum': 6, 'col': 1},
286 \ {'bufnr': bufnr('%'), 'type': 'I', 'lnum': 7, 'col': 1},
287 \ {'bufnr': bufnr('%') + 1, 'type': 'E', 'lnum': 1, 'col': 1},
292 \ {'group': 'ALEError', 'priority': 10, 'pos1': [1, 1, 1]},
293 \ {'group': 'ALEError', 'priority': 10, 'pos1': [2, 1, 1]},
294 \ {'group': 'ALEStyleError', 'priority': 10, 'pos1': [3, 1, 1]},
295 \ {'group': 'ALEWarning', 'priority': 10, 'pos1': [4, 1, 1]},
296 \ {'group': 'ALEWarning', 'priority': 10, 'pos1': [5, 1, 1]},
297 \ {'group': 'ALEStyleWarning', 'priority': 10, 'pos1': [6, 1, 1]},
298 \ {'group': 'ALEInfo', 'priority': 10, 'pos1': [7, 1, 1]},
300 \ GetMatchesWithoutIDs()
302 Execute(Highlighting should support errors spanning many lines):
304 \ {'bufnr': bufnr(''), 'type': 'E', 'lnum': 1, 'col': 1, 'end_lnum': 10, 'end_col': 3},
307 call ale#highlight#SetHighlights(bufnr(''), g:items)
309 if g:has_nvim_highlight
310 " The newer NeoVim highlight API produces different output.
313 \ {'group': 'ALEError', 'priority': 10, 'pos1': [1, 1, 1073741824]},
314 \ {'group': 'ALEError', 'priority': 10, 'pos1': [2, 1, 1073741824]},
315 \ {'group': 'ALEError', 'priority': 10, 'pos1': [3, 1, 1073741824]},
316 \ {'group': 'ALEError', 'priority': 10, 'pos1': [4, 1, 1073741824]},
317 \ {'group': 'ALEError', 'priority': 10, 'pos1': [5, 1, 1073741824]},
318 \ {'group': 'ALEError', 'priority': 10, 'pos1': [6, 1, 1073741824]},
319 \ {'group': 'ALEError', 'priority': 10, 'pos1': [7, 1, 1073741824]},
320 \ {'group': 'ALEError', 'priority': 10, 'pos1': [8, 1, 1073741824]},
321 \ {'group': 'ALEError', 'priority': 10, 'pos1': [9, 1, 1073741824]},
322 \ {'group': 'ALEError', 'priority': 10, 'pos1': [10, 1, 3]},
324 \ GetMatchesWithoutIDs()
326 " We should set 2 highlights for the item, as we can only add 8 at a time.
330 \ 'group': 'ALEError', 'priority': 10, 'pos1': [1, 1, 1073741824],
331 \ 'pos2': [2], 'pos3': [3], 'pos4': [4], 'pos5': [5], 'pos6': [6],
332 \ 'pos7': [7], 'pos8': [8],
335 \ 'group': 'ALEError', 'priority': 10,
336 \ 'pos1': [9], 'pos2': [10, 1, 3]
339 \ GetMatchesWithoutIDs()
342 Execute(Highlights should always be cleared when the buffer highlight list is empty):
343 if g:has_nvim_highlight
344 " The newer API uses namespacing. We'll emulate it here.
345 call ale#highlight#nvim_buf_add_highlight(
355 \ [{'group': 'ALEError', 'priority': 10, 'pos1': [1, 1, 1]}],
356 \ GetMatchesWithoutIDs()
358 " Add our highlights and something else.
359 call matchaddpos('ALEError', [[1, 1, 1]])
360 call matchaddpos('SomeOtherGroup', [[1, 1, 1]])
364 \ {'group': 'ALEError', 'priority': 10, 'pos1': [1, 1, 1]},
365 \ {'group': 'SomeOtherGroup', 'priority': 10, 'pos1': [1, 1, 1]},
367 \ GetMatchesWithoutIDs()
371 " Set the List we use for holding highlights for buffers.
372 let b:ale_highlight_items = []
374 " Call the function for updating the highlights called when buffers
375 " are entered, or when problems are presented.
376 call ale#highlight#UpdateHighlights()
378 " Check that we remove our highlights.
379 if g:has_nvim_highlight
380 AssertEqual [], GetMatchesWithoutIDs()
383 \ [{'group': 'SomeOtherGroup', 'priority': 10, 'pos1': [1, 1, 1]}],
384 \ GetMatchesWithoutIDs()
387 Execute(Highlights should be hidden when excluded):
388 let b:ale_exclude_highlights = ['ig.*ore', 'nope']
390 call ale#highlight#SetHighlights(bufnr('%'), [
391 \ {'bufnr': bufnr('%'), 'type': 'E', 'lnum': 1, 'col': 1, 'text': 'hello'},
392 \ {'bufnr': bufnr('%'), 'type': 'E', 'lnum': 2, 'col': 1, 'text': 'ignore'},
393 \ {'bufnr': bufnr('%'), 'type': 'E', 'lnum': 3, 'col': 1, 'text': 'nope'},
394 \ {'bufnr': bufnr('%'), 'type': 'E', 'lnum': 4, 'col': 1, 'text': 'world'},
399 \ {'group': 'ALEError', 'priority': 10, 'pos1': [1, 1, 1]},
400 \ {'group': 'ALEError', 'priority': 10, 'pos1': [4, 1, 1]},
402 \ GetMatchesWithoutIDs()
404 Execute(Highlights should be cleared when ALE is disabled):
405 let g:ale_enabled = 1
406 call ale#highlight#SetHighlights(bufnr(''), [
407 \ {'bufnr': bufnr(''), 'type': 'E', 'lnum': 1, 'col': 1, 'end_lnum': 10, 'end_col': 3},
410 let g:ale_enabled = 0
411 call ale#highlight#UpdateHighlights()
413 AssertEqual [], GetMatchesWithoutIDs()
415 let g:ale_enabled = 1
416 call ale#highlight#SetHighlights(bufnr(''), [
417 \ {'bufnr': bufnr(''), 'type': 'E', 'lnum': 1, 'col': 1, 'end_lnum': 10, 'end_col': 3},
420 let b:ale_enabled = 0
421 call ale#highlight#UpdateHighlights()
423 AssertEqual [], GetMatchesWithoutIDs()
425 Execute(Line highlights should be set when signs are disabled):
426 " This will mess with your settings, but it needs to be tested.
427 " We need to match highlights case-insensitively when removing them.
428 hi link aleerrorline spellbad
430 let g:ale_set_signs = 0
432 call ale#highlight#SetHighlights(bufnr(''), [
433 \ {'bufnr': bufnr(''), 'type': 'E', 'lnum': 1, 'col': 1},
434 \ {'bufnr': bufnr(''), 'type': 'W', 'lnum': 2, 'col': 1},
435 \ {'bufnr': bufnr(''), 'type': 'I', 'lnum': 3, 'col': 1},
438 if g:has_nvim_highlight
439 " The output is different with the newer NeoVIM highlight API.
442 \ {'group': 'ALEError', 'priority': 10, 'pos1': [1, 1, 1]},
443 \ {'group': 'ALEErrorLine', 'priority': 10, 'pos1': [1, 1, 1073741824]},
444 \ {'group': 'ALEWarning', 'priority': 10, 'pos1': [2, 1, 1]},
445 \ {'group': 'ALEWarningLine', 'priority': 10, 'pos1': [2, 1, 1073741824]},
446 \ {'group': 'ALEInfo', 'priority': 10, 'pos1': [3, 1, 1]},
447 \ {'group': 'ALEInfoLine', 'priority': 10, 'pos1': [3, 1, 1073741824]}
449 \ GetMatchesWithoutIDs()
453 \ {'group': 'ALEError', 'priority': 10, 'pos1': [1, 1, 1]},
454 \ {'group': 'ALEWarning', 'priority': 10, 'pos1': [2, 1, 1]},
455 \ {'group': 'ALEInfo', 'priority': 10, 'pos1': [3, 1, 1]},
456 \ {'group': 'aleerrorline', 'priority': 10, 'pos1': [1]},
457 \ {'group': 'ALEWarningLine', 'priority': 10, 'pos1': [2]},
458 \ {'group': 'ALEInfoLine', 'priority': 10, 'pos1': [3]},
460 \ GetMatchesWithoutIDs()
463 " All of the highlights should be removed.
464 call ale#highlight#RemoveHighlights()
465 AssertEqual [], GetMatchesWithoutIDs()