diff --git a/autoload/ale.vim b/autoload/ale.vim index 80ef3ee..b911c21 100644 --- a/autoload/ale.vim +++ b/autoload/ale.vim @@ -3,6 +3,7 @@ " Manages execution of linters when requested by autocommands let s:lint_timer = -1 +let s:queued_buffer_number = -1 let s:should_lint_file_for_buffer = {} " A function for checking various conditions whereby ALE just shouldn't @@ -50,6 +51,7 @@ function! ale#Queue(delay, ...) abort endif if a:delay > 0 + let s:queued_buffer_number = bufnr('%') let s:lint_timer = timer_start(a:delay, function('ale#Lint')) else call ale#Lint() @@ -61,8 +63,14 @@ function! ale#Lint(...) abort return endif - let l:buffer = bufnr('%') - let l:linters = ale#linter#Get(&filetype) + " Get the buffer number linting was queued for. + " or else take the current one. + let l:buffer = len(a:0) > 1 && a:1 == s:lint_timer + \ ? s:queued_buffer_number + \ : bufnr('%') + + " Use the filetype from the buffer + let l:linters = ale#linter#Get(getbufvar(l:buffer, '&filetype')) let l:should_lint_file = 0 " Check if we previously requested checking the file. diff --git a/autoload/ale/linter.vim b/autoload/ale/linter.vim index 8a33249..0515621 100644 --- a/autoload/ale/linter.vim +++ b/autoload/ale/linter.vim @@ -199,18 +199,26 @@ function! ale#linter#GetAll(filetypes) abort return l:combined_linters endfunction -function! ale#linter#ResolveFiletype(original_filetype) abort - " Try and get an aliased file type either from the user's Dictionary, or - " our default Dictionary, otherwise use the filetype as-is. - let l:filetype = get( +function! s:GetAliasedFiletype(original_filetype) abort + " Check for aliased filetypes first in a buffer variable, + " then the global variable, + " then in the default mapping, + " otherwise use the original filetype. + for l:dict in [ + \ get(b:, 'ale_linter_aliases', {}), \ g:ale_linter_aliases, - \ a:original_filetype, - \ get( - \ s:default_ale_linter_aliases, - \ a:original_filetype, - \ a:original_filetype - \ ) - \) + \ s:default_ale_linter_aliases, + \] + if has_key(l:dict, a:original_filetype) + return l:dict[a:original_filetype] + endif + endfor + + return a:original_filetype +endfunction + +function! ale#linter#ResolveFiletype(original_filetype) abort + let l:filetype = s:GetAliasedFiletype(a:original_filetype) if type(l:filetype) != type([]) return [l:filetype] @@ -219,26 +227,27 @@ function! ale#linter#ResolveFiletype(original_filetype) abort return l:filetype endfunction +function! s:GetLinterNames(original_filetype) abort + for l:dict in [ + \ get(b:, 'ale_linters', {}), + \ g:ale_linters, + \ s:default_ale_linters, + \] + if has_key(l:dict, a:original_filetype) + return l:dict[a:original_filetype] + endif + endfor + + return 'all' +endfunction + function! ale#linter#Get(original_filetypes) abort let l:combined_linters = [] " Handle dot-seperated filetypes. for l:original_filetype in split(a:original_filetypes, '\.') let l:filetype = ale#linter#ResolveFiletype(l:original_filetype) - - " Try and get a list of linters to run, using the original file type, - " not the aliased filetype. We have some linters to limit by default, - " and users may define their own list of linters to run. - let l:linter_names = get( - \ g:ale_linters, - \ l:original_filetype, - \ get( - \ s:default_ale_linters, - \ l:original_filetype, - \ 'all' - \ ) - \) - + let l:linter_names = s:GetLinterNames(l:original_filetype) let l:all_linters = ale#linter#GetAll(l:filetype) let l:filetype_linters = [] diff --git a/doc/ale.txt b/doc/ale.txt index 8f3476b..7f39196 100644 --- a/doc/ale.txt +++ b/doc/ale.txt @@ -364,7 +364,7 @@ g:ale_lint_on_insert_leave *g:ale_lint_on_insert_leave* g:ale_linter_aliases *g:ale_linter_aliases* - + *b:ale_linter_aliases* Type: |Dictionary| Default: `{}` @@ -399,8 +399,13 @@ g:ale_linter_aliases *g:ale_linter_aliases* Note that `html` itself was included as an alias. That is because aliases will override the original linters for the aliased filetepe. -g:ale_linters *g:ale_linters* + Linter aliases can be configured in each buffer with buffer-local variables. + ALE will first look for aliases for filetypes in the `b:ale_linter_aliases` + variable, then `g:ale_linter_aliases`, and then a default Dictionary. + +g:ale_linters *g:ale_linters* + *b:ale_linters* Type: |Dictionary| Default: `{}` @@ -434,6 +439,10 @@ g:ale_linters *g:ale_linters* let g:ale_linters = {'c': 'all'} < + Linters can be configured in each buffer with buffer-local variables. ALE + will first look for linters for filetypes in the `b:ale_linters` variable, + then `g:ale_linters`, and then a default Dictionary. + g:ale_max_buffer_history_size *g:ale_max_buffer_history_size* diff --git a/test/test_linter_retrieval.vader b/test/test_linter_retrieval.vader index 3f405a5..ecbae8d 100644 --- a/test/test_linter_retrieval.vader +++ b/test/test_linter_retrieval.vader @@ -5,6 +5,8 @@ Before: call ale#linter#Reset() let g:ale_linters = {} let g:ale_linter_aliases = {} + unlet! b:ale_linters + unlet! b:ale_linter_aliases Execute (Define a linter): call ale#linter#Define('testft', g:testlinter1) @@ -18,6 +20,22 @@ Execute (Define a couple linters, filtering one): Then (Only the configured linter should be returned): AssertEqual [g:testlinter1], ale#linter#Get('testft') +Execute (Define a couple linters, and set a buffer override): + call ale#linter#Define('testft', g:testlinter1) + call ale#linter#Define('testft', g:testlinter2) + let g:ale_linters = {'testft': ['testlinter1', 'testlinter2']} + let b:ale_linters = {'testft': ['testlinter1']} +Then (The buffer setting should be used): + AssertEqual [g:testlinter1], ale#linter#Get('testft') + +Execute (Define a couple linters, and set a buffer override for another filetype): + call ale#linter#Define('testft', g:testlinter1) + call ale#linter#Define('testft', g:testlinter2) + let g:ale_linters = {'testft': ['testlinter1']} + let b:ale_linters = {'testft2': ['testlinter1', 'testlinter2']} +Then (The global value should be used): + AssertEqual [g:testlinter1], ale#linter#Get('testft') + Execute (Define a linter for a filetype, and create a filetype alias): call ale#linter#Define('testft1', g:testlinter1) let g:ale_linter_aliases = {'testft2': 'testft1'} @@ -53,5 +71,24 @@ Execute (Alias a filetype to itself plus another one): Then (The original linters should still be there): AssertEqual [g:testlinter1, g:testlinter2], ale#linter#Get('testft1') +Execute (Set up aliases in the buffer): + call ale#linter#Define('testft1', g:testlinter1) + call ale#linter#Define('testft2', g:testlinter2) + let g:ale_linter_aliases = {'testft1': ['testft2']} + let b:ale_linter_aliases = {'testft1': ['testft1', 'testft2']} +Then (The buffer-local override should be used): + AssertEqual [g:testlinter1, g:testlinter2], ale#linter#Get('testft1') + +Execute (Set up aliases in the buffer for another filetype): + call ale#linter#Define('testft1', g:testlinter1) + call ale#linter#Define('testft2', g:testlinter2) + let g:ale_linter_aliases = {'testft1': ['testft1', 'testft2']} + " This is a key set for a differnt filetype. + " We should look for a key in this Dictionary first, and then check the + " global Dictionary. + let b:ale_linter_aliases = {'testft3': ['testft1']} +Then (The global value should be used): + AssertEqual [g:testlinter1, g:testlinter2], ale#linter#Get('testft1') + Execute (Try to load a linter from disk): AssertEqual [{'name': 'testlinter', 'output_stream': 'stdout', 'executable': 'testlinter', 'command': 'testlinter', 'callback': 'testCB', 'read_buffer': 1, 'lint_file': 0}], ale#linter#Get('testft')