diff --git a/autoload/ale/cleanup.vim b/autoload/ale/cleanup.vim index 40a8a359..0a1cd391 100644 --- a/autoload/ale/cleanup.vim +++ b/autoload/ale/cleanup.vim @@ -2,10 +2,6 @@ " Description: Utility functions related to cleaning state. function! ale#cleanup#Buffer(buffer) abort - if has_key(g:ale_buffer_loclist_map, a:buffer) - call remove(g:ale_buffer_loclist_map, a:buffer) - endif - if has_key(g:ale_buffer_info, a:buffer) " When buffers are removed, clear all of the jobs. for l:job in get(g:ale_buffer_info[a:buffer], 'job_list', []) diff --git a/autoload/ale/cursor.vim b/autoload/ale/cursor.vim index a20212c1..7f490339 100644 --- a/autoload/ale/cursor.vim +++ b/autoload/ale/cursor.vim @@ -46,12 +46,12 @@ function! ale#cursor#EchoCursorWarning(...) abort let l:buffer = bufnr('%') - if !has_key(g:ale_buffer_loclist_map, l:buffer) + if !has_key(g:ale_buffer_info, l:buffer) return endif let l:pos = getcurpos() - let l:loclist = g:ale_buffer_loclist_map[l:buffer] + let l:loclist = g:ale_buffer_info[l:buffer].loclist let l:index = ale#util#BinarySearch(l:loclist, l:pos[1], l:pos[2]) if l:index >= 0 diff --git a/autoload/ale/engine.vim b/autoload/ale/engine.vim index 5a257505..9af1f536 100644 --- a/autoload/ale/engine.vim +++ b/autoload/ale/engine.vim @@ -26,6 +26,7 @@ function! ale#engine#InitBufferInfo(buffer) abort \ 'job_list': [], \ 'should_reset': 1, \ 'dummy_sign_set': 0, + \ 'loclist': [], \} endif endfunction @@ -121,28 +122,28 @@ function! s:HandleExit(job) abort " Set the flag for resetting the loclist to 0 again, so we won't " empty the list later. let g:ale_buffer_info[l:buffer].should_reset = 0 - let g:ale_buffer_loclist_map[l:buffer] = [] + let g:ale_buffer_info[l:buffer].loclist = [] endif " Add the loclist items from the linter. - call extend(g:ale_buffer_loclist_map[l:buffer], l:linter_loclist) + call extend(g:ale_buffer_info[l:buffer].loclist, l:linter_loclist) " Sort the loclist again. " We need a sorted list so we can run a binary search against it " for efficient lookup of the messages in the cursor handler. - call sort(g:ale_buffer_loclist_map[l:buffer], 'ale#util#LocItemCompare') + call sort(g:ale_buffer_info[l:buffer].loclist, 'ale#util#LocItemCompare') if g:ale_set_loclist - call setloclist(0, g:ale_buffer_loclist_map[l:buffer]) + call setloclist(0, g:ale_buffer_info[l:buffer].loclist) endif if g:ale_set_signs - call ale#sign#SetSigns(l:buffer, g:ale_buffer_loclist_map[l:buffer]) + call ale#sign#SetSigns(l:buffer, g:ale_buffer_info[l:buffer].loclist) endif if exists('*ale#statusline#Update') " Don't load/run if not already loaded. - call ale#statusline#Update(l:buffer, g:ale_buffer_loclist_map[l:buffer]) + call ale#statusline#Update(l:buffer, g:ale_buffer_info[l:buffer].loclist) endif " Call user autocommands. This allows users to hook into ALE's lint cycle. @@ -281,6 +282,15 @@ function! ale#engine#Invoke(buffer, linter) abort endif endfunction +" Given a buffer number, return the warnings and errors for a given buffer. +function! ale#engine#GetLoclist(buffer) abort + if !has_key(g:ale_buffer_info, a:buffer) + return [] + endif + + return g:ale_buffer_info[a:buffer].loclist +endfunction + " This function can be called with a timeout to wait for all jobs to finish. " If the jobs to not finish in the given number of milliseconds, " an exception will be thrown. diff --git a/autoload/ale/statusline.vim b/autoload/ale/statusline.vim index 48b4d687..c01dd34d 100644 --- a/autoload/ale/statusline.vim +++ b/autoload/ale/statusline.vim @@ -27,7 +27,7 @@ function! s:SetupCount(buffer) abort " Cache is cold, so manually ask for an update. if !has_key(g:ale_buffer_info[a:buffer], 'count') - call ale#statusline#Update(a:buffer, get(g:ale_buffer_loclist_map, a:buffer, [])) + call ale#statusline#Update(a:buffer, g:ale_buffer_info[a:buffer].loclist) endif return 1 diff --git a/doc/ale.txt b/doc/ale.txt index c879a98b..ca558f26 100644 --- a/doc/ale.txt +++ b/doc/ale.txt @@ -145,23 +145,6 @@ g:ale_linter_aliases *g:ale_linter_aliases* different set of linters from the type it is being mapped to. -g:ale_buffer_loclist_map *g:ale_buffer_loclist_map* - - Type: |Dictionary| - Default: `{}` - - This variable is used internally by ALE for tracking the warnings and - errors for a particular buffer. The dictionary maps a buffer number to - a |List| of |Dictionary| items in the format accepted by |setqflist()|, - with a minor addition of a `linter_name` for each object which describes - the linter which reported the warnings and errors. (A buffer may run - multiple linters in combination on the same filetype.) - - NOTE: This variable should not be modified outside of the plugin itself, - but can be read in other plugins whenever information about the current - errors and warnings ALE is reporting is needed. - - g:ale_lint_on_text_changed *g:ale_lint_on_text_changed* Type: |Number| @@ -556,6 +539,13 @@ ale#Queue(delay) *ale#Queue()* again from the same buffer +ale#engine#GetLoclist(buffer) *ale#engine#GetLoclist()* + + Given a buffer number, this function will rerurn the list of warnings and + errors reported by ALE for a given buffer in the format accepted by + |setqflist()|. + + ale#linter#Define(filetype, linter) *ale#linter#Define()* Given a |String| for a filetype and a |Dictionary| Describing a linter configuration, add a linter for the given filetype. The dictionaries each diff --git a/plugin/ale.vim b/plugin/ale.vim index 7e88f688..289a9d94 100644 --- a/plugin/ale.vim +++ b/plugin/ale.vim @@ -22,9 +22,8 @@ if !s:ale_has_required_features finish endif -" Globals - -let g:ale_buffer_loclist_map = {} +" This global variable is used internally by ALE for tracking information for +" each buffer which linters are being run against. let g:ale_buffer_info = {} " User Configuration diff --git a/test/test_alelint_autocmd.vader b/test/test_alelint_autocmd.vader index 86772b61..22fe1935 100644 --- a/test/test_alelint_autocmd.vader +++ b/test/test_alelint_autocmd.vader @@ -7,11 +7,14 @@ Before: After: augroup! VaderTest + let g:ale_buffer_info = {} Given vim (Some vimscript): set nocompatible + Execute (Lint it): call ale#Lint() call ale#engine#WaitForJobs(2000) + Then (Autocommands should have run): AssertEqual g:success, 1 diff --git a/test/test_cleanup.vader b/test/test_cleanup.vader index a700d6b5..ec2b38aa 100644 --- a/test/test_cleanup.vader +++ b/test/test_cleanup.vader @@ -1,9 +1,5 @@ Before: let g:buffer = bufnr('%') - let g:ale_buffer_loclist_map = { - \ g:buffer : [], - \ 10347: [], - \} let g:ale_buffer_info = { \ g:buffer : {}, @@ -12,10 +8,8 @@ Before: After: unlet! g:buffer - let g:ale_buffer_loclist_map = {} let g:ale_buffer_info = {} Execute('ALE globals should be cleared when the buffer is closed.'): :q! - AssertEqual {10347: []}, g:ale_buffer_loclist_map AssertEqual {10347: {}}, g:ale_buffer_info diff --git a/test/test_cursor_warnings.vader b/test/test_cursor_warnings.vader index 364db4bc..b12f2451 100644 --- a/test/test_cursor_warnings.vader +++ b/test/test_cursor_warnings.vader @@ -1,17 +1,18 @@ Before: - let g:ale_buffer_loclist_map = { - \ bufnr('%'): [ - \ { - \ 'lnum': 1, - \ 'bufnr': bufnr('%'), - \ 'vcol': 0, - \ 'linter_name': 'eslint', - \ 'nr': -1, - \ 'type': 'E', - \ 'col': 10, - \ 'text': 'Missing semicolon. (semi)' - \ }, - \ { + let g:ale_buffer_info = { + \ bufnr('%'): { + \ 'loclist': [ + \ { + \ 'lnum': 1, + \ 'bufnr': bufnr('%'), + \ 'vcol': 0, + \ 'linter_name': 'eslint', + \ 'nr': -1, + \ 'type': 'E', + \ 'col': 10, + \ 'text': 'Missing semicolon. (semi)' + \ }, + \ { \ 'lnum': 2, \ 'bufnr': bufnr('%'), \ 'vcol': 0, @@ -20,8 +21,8 @@ Before: \ 'type': 'W', \ 'col': 10, \ 'text': 'Infix operators must be spaced. (space-infix-ops)' - \ }, - \ { + \ }, + \ { \ 'lnum': 2, \ 'bufnr': bufnr('%'), \ 'vcol': 0, @@ -30,14 +31,15 @@ Before: \ 'type': 'E', \ 'col': 15, \ 'text': 'Missing radix parameter (radix)' - \ } - \ ], + \ } + \ ], + \ }, \} After: unlet! g:output unlet! g:lines - let g:ale_buffer_loclist_map = {} + let g:ale_buffer_info = {} Given javascript(A Javscript file with warnings/errors): var x = 3 diff --git a/test/test_get_loclist.vader b/test/test_get_loclist.vader new file mode 100644 index 00000000..14696998 --- /dev/null +++ b/test/test_get_loclist.vader @@ -0,0 +1,31 @@ +Before: + let g:loclist = [ + \ { + \ 'lnum': 1, + \ 'bufnr': bufnr('%'), + \ 'vcol': 0, + \ 'linter_name': 'eslint', + \ 'nr': -1, + \ 'type': 'E', + \ 'col': 10, + \ 'text': 'Missing semicolon. (semi)' + \ }, + \ { + \ 'lnum': 2, + \ 'bufnr': bufnr('%'), + \ 'vcol': 0, + \ 'linter_name': 'eslint', + \ 'nr': -1, + \ 'type': 'W', + \ 'col': 10, + \ 'text': 'Infix operators must be spaced. (space-infix-ops)' + \ }, + \] + let g:ale_buffer_info = {'1': {'loclist': g:loclist}} + +After: + unlet g:loclist + let g:ale_buffer_info = {} + +Execute(GetLoclist should return the loclist): + AssertEqual g:loclist, ale#engine#GetLoclist(1) diff --git a/test/test_linting_sets_signs.vader b/test/test_linting_sets_signs.vader index 1f323fe8..e96e490b 100644 --- a/test/test_linting_sets_signs.vader +++ b/test/test_linting_sets_signs.vader @@ -26,7 +26,6 @@ Before: After: sign unplace * - let g:ale_buffer_loclist_map = {} let g:ale_buffer_info = {} delfunction g:CollectSigns unlet g:actual_sign_list diff --git a/test/test_linting_updates_loclist.vader b/test/test_linting_updates_loclist.vader index 920a4e46..06f11d8b 100644 --- a/test/test_linting_updates_loclist.vader +++ b/test/test_linting_updates_loclist.vader @@ -3,15 +3,35 @@ Given javascript (Some JavaScript with problems): var y = 3 Before: - let g:ale_buffer_loclist_map = {} - let g:expected_data = {bufnr('%'): [{'lnum': 1, 'bufnr': bufnr('%'), 'vcol': 0, 'linter_name': 'eslint', 'nr': -1, 'type': 'W', 'col': 10, 'text': 'Infix operators must be spaced. [Warning/space-infix-ops]'}, {'lnum': 2, 'bufnr': bufnr('%'), 'vcol': 0, 'linter_name': 'eslint', 'nr': -1, 'type': 'E', 'col': 10, 'text': 'Missing semicolon. [Error/semi]'}]} + let g:expected_data = [ + \ { + \ 'lnum': 1, + \ 'bufnr': bufnr('%'), + \ 'vcol': 0, + \ 'linter_name': 'eslint', + \ 'nr': -1, + \ 'type': 'W', + \ 'col': 10, + \ 'text': 'Infix operators must be spaced. [Warning/space-infix-ops]', + \ }, + \ { + \ 'lnum': 2, + \ 'bufnr': bufnr('%'), + \ 'vcol': 0, + \ 'linter_name': 'eslint', + \ 'nr': -1, + \ 'type': 'E', + \ 'col': 10, + \ 'text': 'Missing semicolon. [Error/semi]', + \ } + \] After: - let g:ale_buffer_loclist_map = {} unlet g:expected_data Execute(The loclist should be updated after linting is done): call ale#Lint() call ale#engine#WaitForJobs(2000) - AssertEqual g:expected_data, g:ale_buffer_loclist_map + AssertEqual ['' . bufnr('%')], keys(g:ale_buffer_info) + AssertEqual g:expected_data, g:ale_buffer_info[bufnr('%')].loclist diff --git a/test/test_statusline.vader b/test/test_statusline.vader index 43245e97..05e60479 100644 --- a/test/test_statusline.vader +++ b/test/test_statusline.vader @@ -1,9 +1,7 @@ Before: - let g:ale_buffer_loclist_map = {} let g:ale_statusline_format = ['%sE', '%sW', 'OKIE'] After: - let g:ale_buffer_loclist_map = {} let g:ale_buffer_info = {} Execute (Count should be 0 when data is empty): @@ -20,19 +18,22 @@ Execute (The count should be correct after an update): AssertEqual [0, 0], ale#statusline#Count(44) Execute (Count should be match the loclist): - let g:ale_buffer_info = {bufnr('%'): {}} - let g:ale_buffer_loclist_map = {bufnr('%'): [ - \ { - \ 'lnum': 1, - \ 'bufnr': 1, - \ 'vcol': 0, - \ 'linter_name': 'testlinter', - \ 'nr': -1, - \ 'type': 'E', - \ 'col': 1, - \ 'text': 'Test Error', - \ }, - \]} + let g:ale_buffer_info = { + \ bufnr('%'): { + \ 'loclist': [ + \ { + \ 'lnum': 1, + \ 'bufnr': 1, + \ 'vcol': 0, + \ 'linter_name': 'testlinter', + \ 'nr': -1, + \ 'type': 'E', + \ 'col': 1, + \ 'text': 'Test Error', + \ }, + \ ], + \ }, + \} AssertEqual [1, 0], ale#statusline#Count(bufnr('%')) Execute (Output should be empty for non-existant buffer):