#653 Set problems from other buffers when buffers are first checked

This commit is contained in:
w0rp 2017-08-19 20:15:36 +01:00
parent b2d3764a18
commit 9d6883561c
4 changed files with 123 additions and 23 deletions

View File

@ -50,7 +50,11 @@ function! ale#engine#InitBufferInfo(buffer) abort
\ 'temporary_directory_list': [], \ 'temporary_directory_list': [],
\ 'history': [], \ 'history': [],
\} \}
return 1
endif endif
return 0
endfunction endfunction
" Return 1 if ALE is busy checking a given buffer " 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 if l:item.lnum < 1
" When errors appear before line 1, put them at line 1. " When errors appear before line 1, put them at line 1.
let l:item.lnum = 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. " 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 let l:item.lnum = l:last_line_number
endif endif
@ -701,6 +706,35 @@ function! s:RemoveProblemsForDisabledLinters(buffer, linters) abort
\) \)
endfunction 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. " Run a linter for a buffer.
" "
" Returns 1 if the linter was successfully run. " Returns 1 if the linter was successfully run.
@ -720,7 +754,7 @@ endfunction
function! ale#engine#RunLinters(buffer, linters, should_lint_file) abort function! ale#engine#RunLinters(buffer, linters, should_lint_file) abort
" Initialise the buffer information if needed. " 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:StopCurrentJobs(a:buffer, a:should_lint_file)
call s:RemoveProblemsForDisabledLinters(a:buffer, a:linters) 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. " disabled, or ALE itself is disabled.
if l:can_clear_results if l:can_clear_results
call ale#engine#SetResults(a:buffer, []) call ale#engine#SetResults(a:buffer, [])
elseif l:new_buffer
call s:AddProblemsFromOtherBuffers(a:buffer, a:linters)
endif endif
endfunction endfunction

View File

@ -20,25 +20,6 @@ function! s:ShouldOpen(buffer) abort
return l:val is 1 || (l:val is# 'on_save' && l:saved) return l:val is 1 || (l:val is# 'on_save' && l:saved)
endfunction 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 function! ale#list#GetCombinedList() abort
let l:list = [] let l:list = []
@ -46,8 +27,8 @@ function! ale#list#GetCombinedList() abort
call extend(l:list, l:info.loclist) call extend(l:list, l:info.loclist)
endfor endfor
call sort(l:list, function('ale#list#TextLocItemCompare')) call sort(l:list, function('ale#util#LocItemCompareWithText'))
call uniq(l:list, function('ale#list#TextLocItemCompare')) call uniq(l:list, function('ale#util#LocItemCompareWithText'))
return l:list return l:list
endfunction endfunction

View File

@ -21,6 +21,8 @@ function! ale#util#GetFunction(string_or_ref) abort
return a:string_or_ref return a:string_or_ref
endfunction 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 function! ale#util#LocItemCompare(left, right) abort
if a:left.bufnr < a:right.bufnr if a:left.bufnr < a:right.bufnr
return -1 return -1
@ -59,6 +61,27 @@ function! ale#util#LocItemCompare(left, right) abort
return 0 return 0
endfunction 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 " 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 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. " on or before the column. The index of the problem will be returned.

View File

@ -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)