diff --git a/autoload/ale/engine.vim b/autoload/ale/engine.vim index 59ba0fc..828f846 100644 --- a/autoload/ale/engine.vim +++ b/autoload/ale/engine.vim @@ -50,7 +50,11 @@ function! ale#engine#InitBufferInfo(buffer) abort \ 'temporary_directory_list': [], \ 'history': [], \} + + return 1 endif + + return 0 endfunction " Return 1 if ALE is busy checking a given buffer @@ -408,8 +412,9 @@ function! ale#engine#FixLocList(buffer, linter_name, loclist) abort if l:item.lnum < 1 " When errors appear before line 1, put them at line 1. let l:item.lnum = 1 - elseif l:item.lnum > l:last_line_number + elseif l:item.bufnr == a:buffer && l:item.lnum > l:last_line_number " When errors go beyond the end of the file, put them at the end. + " This is only done for the current buffer. let l:item.lnum = l:last_line_number endif @@ -701,6 +706,35 @@ function! s:RemoveProblemsForDisabledLinters(buffer, linters) abort \) endfunction +function! s:AddProblemsFromOtherBuffers(buffer, linters) abort + let l:filename = expand('#' . a:buffer . ':p') + let l:loclist = [] + let l:name_map = {} + + " Build a map of the active linters. + for l:linter in a:linters + let l:name_map[l:linter.name] = 1 + endfor + + " Find the items from other buffers, for the linters that are enabled. + for l:info in values(g:ale_buffer_info) + for l:item in l:info.loclist + if has_key(l:item, 'filename') + \&& l:item.filename is# l:filename + \&& has_key(l:name_map, l:item.linter_name) + call add(l:loclist, l:item) + endif + endfor + endfor + + if !empty(l:loclist) + call sort(l:loclist, function('ale#util#LocItemCompareWithText')) + call uniq(l:loclist, function('ale#util#LocItemCompareWithText')) + + call ale#engine#SetResults(a:buffer, l:loclist) + endif +endfunction + " Run a linter for a buffer. " " Returns 1 if the linter was successfully run. @@ -720,7 +754,7 @@ endfunction function! ale#engine#RunLinters(buffer, linters, should_lint_file) abort " Initialise the buffer information if needed. - call ale#engine#InitBufferInfo(a:buffer) + let l:new_buffer = ale#engine#InitBufferInfo(a:buffer) call s:StopCurrentJobs(a:buffer, a:should_lint_file) call s:RemoveProblemsForDisabledLinters(a:buffer, a:linters) @@ -745,6 +779,8 @@ function! ale#engine#RunLinters(buffer, linters, should_lint_file) abort " disabled, or ALE itself is disabled. if l:can_clear_results call ale#engine#SetResults(a:buffer, []) + elseif l:new_buffer + call s:AddProblemsFromOtherBuffers(a:buffer, a:linters) endif endfunction diff --git a/autoload/ale/list.vim b/autoload/ale/list.vim index 6fe17d3..25920ce 100644 --- a/autoload/ale/list.vim +++ b/autoload/ale/list.vim @@ -20,25 +20,6 @@ function! s:ShouldOpen(buffer) abort return l:val is 1 || (l:val is# 'on_save' && l:saved) endfunction -" A comparison function for de-duplicating loclist items for quickfix. -function! ale#list#TextLocItemCompare(left, right) abort - let l:cmp_val = ale#util#LocItemCompare(a:left, a:right) - - if l:cmp_val - return l:cmp_val - endif - - if a:left.text < a:right.text - return -1 - endif - - if a:left.text > a:right.text - return 1 - endif - - return 0 -endfunction - function! ale#list#GetCombinedList() abort let l:list = [] @@ -46,8 +27,8 @@ function! ale#list#GetCombinedList() abort call extend(l:list, l:info.loclist) endfor - call sort(l:list, function('ale#list#TextLocItemCompare')) - call uniq(l:list, function('ale#list#TextLocItemCompare')) + call sort(l:list, function('ale#util#LocItemCompareWithText')) + call uniq(l:list, function('ale#util#LocItemCompareWithText')) return l:list endfunction diff --git a/autoload/ale/util.vim b/autoload/ale/util.vim index 969a19d..fd53842 100644 --- a/autoload/ale/util.vim +++ b/autoload/ale/util.vim @@ -21,6 +21,8 @@ function! ale#util#GetFunction(string_or_ref) abort return a:string_or_ref endfunction +" Compare two loclist items for ALE, sorted by their buffers, filenames, and +" line numbers and column numbers. function! ale#util#LocItemCompare(left, right) abort if a:left.bufnr < a:right.bufnr return -1 @@ -59,6 +61,27 @@ function! ale#util#LocItemCompare(left, right) abort return 0 endfunction +" Compare two loclist items, including the text for the items. +" +" This function can be used for de-duplicating lists. +function! ale#util#LocItemCompareWithText(left, right) abort + let l:cmp_value = ale#util#LocItemCompare(a:left, a:right) + + if l:cmp_value + return l:cmp_value + endif + + if a:left.text < a:right.text + return -1 + endif + + if a:left.text > a:right.text + return 1 + endif + + return 0 +endfunction + " This function will perform a binary search and a small sequential search " on the list to find the last problem in the buffer and line which is " on or before the column. The index of the problem will be returned. diff --git a/test/test_setting_problems_found_in_previous_buffers.vader b/test/test_setting_problems_found_in_previous_buffers.vader new file mode 100644 index 0000000..262b9d1 --- /dev/null +++ b/test/test_setting_problems_found_in_previous_buffers.vader @@ -0,0 +1,60 @@ +Before: + Save g:ale_buffer_info + Save &filetype + + " Set up items in other buffers which should set in this one. + let g:ale_buffer_info = {} + call ale#engine#InitBufferInfo(bufnr('') + 1) + let g:ale_buffer_info[bufnr('') + 1].loclist = + \ ale#engine#FixLocList(bufnr('') + 1, 'linter_one', [ + \ {'lnum': 1, 'filename': expand('%:p'), 'text': 'foo'}, + \ {'lnum': 2, 'filename': expand('%:p'), 'text': 'bar'}, + \ {'lnum': 2, 'text': 'ignore this one'}, + \ ]) + call ale#engine#InitBufferInfo(bufnr('') + 2) + let g:ale_buffer_info[bufnr('') + 2].loclist = + \ ale#engine#FixLocList(bufnr('') + 2, 'linter_two', [ + \ {'lnum': 1, 'filename': expand('%:p'), 'text': 'foo'}, + \ {'lnum': 3, 'filename': expand('%:p'), 'text': 'baz'}, + \ {'lnum': 5, 'text': 'ignore this one'}, + \ ]) + + call ale#linter#Define('foobar', { + \ 'name': 'linter_one', + \ 'callback': 'WhoCares', + \ 'executable': 'echo', + \ 'command': 'echo', + \ 'lint_file': 1, + \}) + call ale#linter#Define('foobar', { + \ 'name': 'linter_two', + \ 'callback': 'WhoCares', + \ 'executable': 'echo', + \ 'command': 'echo', + \}) + +After: + call ale#engine#Cleanup(bufnr('')) + Restore + call ale#linter#Reset() + + " Items and markers, etc. + call setloclist(0, []) + call clearmatches() + sign unplace * + +Given foobar(A file with some lines): + foo + bar + baz + +Execute(Problems found from previously opened buffers should be set when linting for the first time): + call ale#engine#RunLinters(bufnr(''), ale#linter#Get(&filetype), 0) + + AssertEqual + \ [ + \ {'lnum': 1, 'bufnr': bufnr(''), 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': 'E', 'pattern': '', 'text': 'foo'}, + \ {'lnum': 2, 'bufnr': bufnr(''), 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': 'E', 'pattern': '', 'text': 'bar'}, + \ {'lnum': 3, 'bufnr': bufnr(''), 'col': 0, 'valid': 1, 'vcol': 0, 'nr': -1, 'type': 'E', 'pattern': '', 'text': 'baz'}, + \ ], + \ getloclist(0)