Before: function! GenerateResults(buffer, output) return [ \ { \ 'lnum': 1, \ 'col': 1, \ 'type': 'E', \ 'text': 'foo', \ }, \ { \ 'lnum': 2, \ 'col': 1, \ 'type': 'W', \ 'text': 'bar', \ }, \ { \ 'lnum': 3, \ 'col': 5, \ 'type': 'E', \ 'text': 'wat', \ }, \] endfunction call ale#linter#Define('testft', { \ 'name': 'x', \ 'executable': 'echo', \ 'command': 'echo', \ 'callback': 'GenerateResults', \}) highlight link SomeOtherGroup SpellBad After: unlet! g:items delfunction GenerateResults call ale#linter#Reset() let g:ale_buffer_info = {} call clearmatches() highlight clear SomeOtherGroup Given testft(A Javscript file with warnings/errors): foo bar baz wat line four Execute(Highlights should be set when a linter runs): call ale#Lint() call ale#engine#WaitForJobs(2000) AssertEqual \ [ \ {'group': 'ALEError', 'id': 4, 'priority': 10, 'pos1': [1, 1, 1]}, \ {'group': 'ALEWarning', 'id': 5, 'priority': 10, 'pos1': [2, 1, 1]}, \ {'group': 'ALEError', 'id': 6, 'priority': 10, 'pos1': [3, 5, 1]} \ ], \ getmatches() AssertEqual [[4], [5], [6]], map(copy(g:ale_buffer_info[bufnr('')].loclist), 'v:val.match_id_list') Execute(Existing highlights should be kept): call matchaddpos('ALEError', [[1, 2, 1]], 10, 347) call matchaddpos('ALEWarning', [[2, 2, 1]], 10, 348) call ale#highlight#SetHighlights(bufnr('%'), [ \ {'bufnr': bufnr('%'), 'match_id_list': [347], 'type': 'E', 'lnum': 1, 'col': 2}, \ {'bufnr': bufnr('%'), 'match_id_list': [348], 'type': 'W', 'lnum': 2, 'col': 2}, \ {'bufnr': bufnr('%'), 'type': 'E', 'lnum': 3, 'col': 2}, \ {'bufnr': bufnr('%'), 'type': 'W', 'lnum': 4, 'col': 1}, \]) AssertEqual \ [ \ {'group': 'ALEError', 'id': 347, 'priority': 10, 'pos1': [1, 2, 1]}, \ {'group': 'ALEWarning', 'id': 348, 'priority': 10, 'pos1': [2, 2, 1]}, \ {'group': 'ALEError', 'id': 7, 'priority': 10, 'pos1': [3, 2, 1]}, \ {'group': 'ALEWarning', 'id': 8, 'priority': 10, 'pos1': [4, 1, 1]}, \ ], \ getmatches() " This test is important for preventing ALE from showing highlights for " the wrong files. Execute(Highlights set by ALE should be removed when buffer cleanup is done): call ale#engine#InitBufferInfo(bufnr('%')) call ale#highlight#SetHighlights(bufnr('%'), [ \ {'bufnr': bufnr('%'), 'type': 'E', 'lnum': 3, 'col': 2}, \]) AssertEqual \ [{'group': 'ALEError', 'id': 9, 'priority': 10, 'pos1': [3, 2, 1]}], \ getmatches() call ale#cleanup#Buffer(bufnr('%')) AssertEqual [], getmatches() Execute(Highlights should be cleared when buffers are hidden): call ale#engine#InitBufferInfo(bufnr('%')) let g:ale_buffer_info[bufnr('%')].loclist = [ \ {'bufnr': bufnr('%'), 'type': 'E', 'lnum': 3, 'col': 2}, \] call ale#highlight#SetHighlights( \ bufnr('%'), \ g:ale_buffer_info[bufnr('%')].loclist \) AssertEqual 1, len(getmatches()), 'The highlights weren''t initially set!' call ale#highlight#BufferHidden(bufnr('%')) AssertEqual 0, len(getmatches()), 'The highlights weren''t cleared!' call ale#highlight#UpdateHighlights() AssertEqual 1, len(getmatches()), 'The highlights weren''t set again!' Execute(Only ALE highlights should be restored when buffers are restored): call ale#engine#InitBufferInfo(bufnr('%')) let g:ale_buffer_info[bufnr('%')].loclist = [ \ {'bufnr': bufnr('%'), 'type': 'E', 'lnum': 3, 'col': 2}, \] call ale#highlight#SetHighlights( \ bufnr('%'), \ g:ale_buffer_info[bufnr('%')].loclist \) call matchaddpos('SomeOtherGroup', [[1, 1, 1]]) " We should have one more match here. AssertEqual 2, len(getmatches()), 'The highlights weren''t initially set!' call ale#highlight#BufferHidden(bufnr('%')) AssertEqual 0, len(getmatches()), 'The highlights weren''t cleared!' call ale#highlight#UpdateHighlights() " Only our matches should appear again. AssertEqual 1, len(getmatches()), 'The highlights weren''t set again!' Execute(Higlight end columns should set an appropriate size): call ale#highlight#SetHighlights(bufnr('%'), [ \ {'bufnr': bufnr('%'), 'type': 'E', 'lnum': 3, 'col': 2, 'end_col': 5}, \ {'bufnr': bufnr('%'), 'type': 'W', 'lnum': 4, 'col': 1, 'end_col': 5}, \]) AssertEqual \ [ \ {'group': 'ALEError', 'id': 15, 'priority': 10, 'pos1': [3, 2, 4]}, \ {'group': 'ALEWarning', 'id': 16, 'priority': 10, 'pos1': [4, 1, 5]}, \ ], \ getmatches() Execute(Higlight end columns should set an appropriate size): call ale#highlight#SetHighlights(bufnr('%'), [ \ {'bufnr': bufnr('%'), 'type': 'E', 'lnum': 1, 'col': 1}, \ {'bufnr': bufnr('%'), 'type': 'E', 'lnum': 2, 'col': 1}, \ {'bufnr': bufnr('%'), 'type': 'E', 'sub_type': 'style', 'lnum': 3, 'col': 1}, \ {'bufnr': bufnr('%'), 'type': 'W', 'lnum': 4, 'col': 1}, \ {'bufnr': bufnr('%'), 'type': 'W', 'lnum': 5, 'col': 1}, \ {'bufnr': bufnr('%'), 'type': 'W', 'sub_type': 'style', 'lnum': 6, 'col': 1}, \ {'bufnr': bufnr('%'), 'type': 'I', 'lnum': 7, 'col': 1}, \]) AssertEqual \ [ \ {'group': 'ALEError', 'id': 17, 'priority': 10, 'pos1': [1, 1, 1]}, \ {'group': 'ALEError', 'id': 18, 'priority': 10, 'pos1': [2, 1, 1]}, \ {'group': 'ALEStyleError', 'id': 19, 'priority': 10, 'pos1': [3, 1, 1]}, \ {'group': 'ALEWarning', 'id': 20, 'priority': 10, 'pos1': [4, 1, 1]}, \ {'group': 'ALEWarning', 'id': 21, 'priority': 10, 'pos1': [5, 1, 1]}, \ {'group': 'ALEStyleWarning', 'id': 22, 'priority': 10, 'pos1': [6, 1, 1]}, \ {'group': 'ALEInfo', 'id': 23, 'priority': 10, 'pos1': [7, 1, 1]}, \ ], \ getmatches() Execute(Highlighting should support errors spanning many lines): let g:items = [ \ {'bufnr': bufnr(''), 'type': 'E', 'lnum': 1, 'col': 1, 'end_lnum': 10, 'end_col': 3}, \] call ale#highlight#SetHighlights(bufnr(''), g:items) " We should set 2 highlights for the item, as we can only add 8 at a time. AssertEqual \ [ \ { \ 'group': 'ALEError', 'id': 24, 'priority': 10, 'pos1': [1, 1, 1073741824], \ 'pos2': [2], 'pos3': [3], 'pos4': [4], 'pos5': [5], 'pos6': [6], \ 'pos7': [7], 'pos8': [8], \ }, \ { \ 'group': 'ALEError', 'id': 25, 'priority': 10, \ 'pos1': [9], 'pos2': [10, 1, 3] \ }, \ ], \ getmatches() AssertEqual [[24, 25]], map(copy(g:items), 'v:val.match_id_list')