From 59f8c35a2fcfbc032de6115da0d5ab0bd38db035 Mon Sep 17 00:00:00 2001 From: w0rp Date: Tue, 16 Apr 2019 13:33:29 +0100 Subject: [PATCH] Fix #1930 - Finish ale_fix_on_save_ignore * Implementation had a bug * Documentation added * Tests added --- autoload/ale/fix.vim | 12 ++-- doc/ale.txt | 40 +++++++++++ test/fix/test_ale_fix_ignore.vader | 110 +++++++++++++++++++++++++++++ 3 files changed, 156 insertions(+), 6 deletions(-) create mode 100644 test/fix/test_ale_fix_ignore.vader diff --git a/autoload/ale/fix.vim b/autoload/ale/fix.vim index f5a3c0c2..92ae3e14 100644 --- a/autoload/ale/fix.vim +++ b/autoload/ale/fix.vim @@ -270,14 +270,14 @@ endfunction function! s:IgnoreFixers(callback_list, filetype, config) abort if type(a:config) is v:t_list let l:ignore_list = a:config + else + let l:ignore_list = [] + + for l:part in split(a:filetype , '\.') + call extend(l:ignore_list, get(a:config, l:part, [])) + endfor endif - let l:ignore_list = [] - - for l:part in split(a:filetype , '\.') - call extend(l:ignore_list, get(a:config, l:part, [])) - endfor - call filter(a:callback_list, 'index(l:ignore_list, v:val) < 0') endfunction diff --git a/doc/ale.txt b/doc/ale.txt index 9971d355..3b194cb0 100644 --- a/doc/ale.txt +++ b/doc/ale.txt @@ -309,6 +309,9 @@ by default. |g:ale_fix_on_save| - Fix files when they are saved. +Fixers can be disabled on save with |g:ale_fix_on_save_ignore|. They will +still be run when you manually run |ALEFix|. + =============================================================================== 5. Language Server Protocol Support *ale-lsp* @@ -770,6 +773,43 @@ b:ale_fix_on_save *b:ale_fix_on_save* Fixing files can be disabled or enabled for individual buffers by setting `b:ale_fix_on_save` to `0` or `1`. + Some fixers can be excluded from being run automatically when you save files + with the |g:ale_fix_on_save_ignore| setting. + + +g:ale_fix_on_save_ignore *g:ale_fix_on_save_ignore* +b:ale_fix_on_save_ignore *b:ale_fix_on_save_ignore* + + Type: |Dictionary| or |List| + Default: `{}` + + Given a |Dictionary| mapping filetypes to |Lists| of fixers to ignore, or + just a |List| of fixers to ignore, exclude those fixers from being run + automatically when files are saved. + + You can disable some fixers in your ftplugin file: > + + " Disable fixers 'b' and 'c' when fixing on safe for this buffer. + let b:ale_fix_on_save_ignore = ['b', 'c'] + " Alternatively, define ignore lists for different filetypes. + let b:ale_fix_on_save_ignore = {'foo': ['b'], 'bar': ['c']} +< + You can disable some fixers globally per filetype like so: > + + let g:ale_fixers = {'foo': ['a', 'b'], 'bar': ['c', 'd']} + let g:ale_fix_on_save = 1 + " For filetype `foo.bar`, only fixers 'b' and 'd' will be run on save. + let g:ale_fix_on_save_ignore = {'foo': ['a'], 'bar': ['c']} + " Alternatively, disable these fixers on save for all filetypes. + let g:ale_fix_on_save_ignore = ['a', 'c'] +< + You can ignore fixers based on matching |Funcref| values too: > + + let g:AddBar = {buffer, lines -> lines + ['bar']} + let g:ale_fixers = {'foo': g:AddBar} + " The lambda fixer will be ignored, as it will be found in the ignore list. + let g:ale_fix_on_save_ignore = [g:AddBar] +< g:ale_history_enabled *g:ale_history_enabled* diff --git a/test/fix/test_ale_fix_ignore.vader b/test/fix/test_ale_fix_ignore.vader new file mode 100644 index 00000000..5eb9b9ab --- /dev/null +++ b/test/fix/test_ale_fix_ignore.vader @@ -0,0 +1,110 @@ +Before: + Save g:ale_fixers + Save g:ale_fix_on_save + Save g:ale_fix_on_save_ignore + + let g:ale_fix_on_save = 1 + let g:ale_fixers = {'abc': ['a', 'b'], 'xyz': ['c', 'd']} + unlet! b:ale_fixers + unlet! b:ale_fix_on_save_ignore + + function FixerA(buffer, lines) abort + return a:lines + ['a'] + endfunction + + function FixerB(buffer, lines) abort + return a:lines + ['b'] + endfunction + + function FixerC(buffer, lines) abort + return a:lines + ['c'] + endfunction + + function FixerD(buffer, lines) abort + return a:lines + ['d'] + endfunction + + set filetype=abc.xyz + let g:test_filename = tempname() + execute 'noautocmd silent file ' . fnameescape(g:test_filename) + + call ale#fix#registry#Add('a', 'FixerA', ['abc'], '') + call ale#fix#registry#Add('b', 'FixerB', ['abc'], '') + call ale#fix#registry#Add('c', 'FixerC', ['xyz'], '') + call ale#fix#registry#Add('d', 'FixerD', ['xyz'], '') + +After: + Restore + + if exists('g:test_filename') && filereadable(g:test_filename) + call delete(g:test_filename) + endif + + unlet! b:ale_fixers + unlet! b:ale_fix_on_save_ignore + unlet! g:test_filename + + delfunction FixerA + delfunction FixerB + delfunction FixerC + delfunction FixerD + + call ale#fix#registry#ResetToDefaults() + +Given abc.xyz (An empty file): +Execute(Ignoring with a filetype in a global Dictionary should work): + let g:ale_fix_on_save_ignore = {'abc': ['b'], 'xyz': ['c']} + + call ale#events#SaveEvent(bufnr('')) + + AssertEqual ['', 'a', 'd'], getline(1, '$') + +Execute(Ignoring with a filetype in a global List should work): + let g:ale_fix_on_save_ignore = ['b', 'c'] + + call ale#events#SaveEvent(bufnr('')) + + AssertEqual ['', 'a', 'd'], getline(1, '$') + +Execute(Ignoring with a filetype in a local Dictionary should work): + let g:ale_fix_on_save_ignore = {'abc': ['b'], 'xyz': ['c']} + " The local Dictionary should entirely replace the global one. + let b:ale_fix_on_save_ignore = {'abc': ['b']} + + call ale#events#SaveEvent(bufnr('')) + + AssertEqual ['', 'a', 'c', 'd'], getline(1, '$') + +Execute(Ignoring with a filetype in a local List should work): + let g:ale_fix_on_save_ignore = {'abc': ['b'], 'xyz': ['c']} + " The local List should entirely replace the global Dictionary. + let b:ale_fix_on_save_ignore = ['b'] + + call ale#events#SaveEvent(bufnr('')) + + AssertEqual ['', 'a', 'c', 'd'], getline(1, '$') + +Execute(Ignoring functions by reference with a Dictionary should work): + let g:ale_fixers = { + \ 'abc': [function('FixerA'), function('FixerB')], + \ 'xyz': [function('FixerC'), function('FixerD')], + \} + let b:ale_fix_on_save_ignore = { + \ 'abc': [function('FixerB')], + \ 'xyz': [function('FixerC')], + \} + + call ale#events#SaveEvent(bufnr('')) + + AssertEqual ['', 'a', 'd'], getline(1, '$') + +Execute(Ignoring functions by reference with a List should work): + let g:ale_fixers = { + \ 'abc': [function('FixerA'), function('FixerB')], + \ 'xyz': [function('FixerC'), function('FixerD')], + \} + let b:ale_fix_on_save_ignore = [function('FixerB'), function('FixerC')] + + call ale#events#SaveEvent(bufnr('')) + + AssertEqual ['', 'a', 'd'], getline(1, '$')