diff --git a/autoload/ale/debugging.vim b/autoload/ale/debugging.vim index f32e4308..34c13770 100644 --- a/autoload/ale/debugging.vim +++ b/autoload/ale/debugging.vim @@ -214,10 +214,15 @@ function! ale#debugging#Info() abort " This must be done after linters are loaded. let l:variable_list = s:GetLinterVariables(l:filetype, l:enabled_names) + let l:fixers = ale#fix#registry#SuggestedFixers(l:filetype) + let l:fixers = uniq(sort(l:fixers[0] + l:fixers[1])) + let l:fixers_string = join(map(copy(l:fixers), '"\n " . v:val'), '') + call s:Echo(' Current Filetype: ' . l:filetype) call s:Echo('Available Linters: ' . string(l:all_names)) call s:EchoLinterAliases(l:all_linters) call s:Echo(' Enabled Linters: ' . string(l:enabled_names)) + call s:Echo(' Suggested Fixers: ' . l:fixers_string) call s:Echo(' Linter Variables:') call s:Echo('') call s:EchoLinterVariables(l:variable_list) diff --git a/autoload/ale/fix/registry.vim b/autoload/ale/fix/registry.vim index e99b8d2e..dec762a2 100644 --- a/autoload/ale/fix/registry.vim +++ b/autoload/ale/fix/registry.vim @@ -345,8 +345,7 @@ function! ale#fix#registry#CompleteFixers(ArgLead, CmdLine, CursorPos) abort return filter(ale#fix#registry#GetApplicableFixers(&filetype), 'v:val =~? a:ArgLead') endfunction -" Suggest functions to use from the registry. -function! ale#fix#registry#Suggest(filetype) abort +function! ale#fix#registry#SuggestedFixers(filetype) abort let l:type_list = split(a:filetype, '\.') let l:filetype_fixer_list = [] @@ -372,6 +371,15 @@ function! ale#fix#registry#Suggest(filetype) abort endif endfor + return [l:filetype_fixer_list, l:generic_fixer_list] +endfunction + +" Suggest functions to use from the registry. +function! ale#fix#registry#Suggest(filetype) abort + let l:suggested = ale#fix#registry#SuggestedFixers(a:filetype) + let l:filetype_fixer_list = l:suggested[0] + let l:generic_fixer_list = l:suggested[1] + let l:filetype_fixer_header = !empty(l:filetype_fixer_list) \ ? ['Try the following fixers appropriate for the filetype:', ''] \ : [] diff --git a/test/test_ale_info.vader b/test/test_ale_info.vader index 75078607..39a2a85a 100644 --- a/test/test_ale_info.vader +++ b/test/test_ale_info.vader @@ -57,6 +57,14 @@ Before: let g:ale_fixers = {} let g:ale_linter_aliases = {} let g:ale_buffer_info = {} + let g:fixer_lines = [ + \ ' Suggested Fixers: ', + \ ' ''foo'' - Fix things the foo way', + \] + let g:variables_lines = [ + \ ' Linter Variables:', + \ '', + \] let g:globals_lines = [ \ ' Global Variables:', \ '', @@ -129,6 +137,9 @@ Before: call ale#test#SetDirectory('/testplugin/test') + call ale#fix#registry#Clear() + call ale#fix#registry#Add('foo', 'x', [], 'Fix things the foo way') + After: Restore @@ -138,6 +149,8 @@ After: unlet! b:ale_history unlet! b:ale_linters unlet! g:output + unlet! g:fixer_lines + unlet! g:variables_lines unlet! g:globals_string unlet! g:command_header unlet! g:ale_testft_testlinter1_foo @@ -148,16 +161,21 @@ After: delfunction CheckInfo call ale#test#RestoreDirectory() + call ale#fix#registry#ResetToDefaults() Given nolintersft (Empty buffer with no linters): Execute (ALEInfo with no linters should return the right output): - call CheckInfo([ - \ ' Current Filetype: nolintersft', - \ 'Available Linters: []', - \ ' Enabled Linters: []', - \ ' Linter Variables:', - \ '', - \] + g:globals_lines + g:command_header) + call CheckInfo( + \ [ + \ ' Current Filetype: nolintersft', + \ 'Available Linters: []', + \ ' Enabled Linters: []', + \ ] + \ + g:fixer_lines + \ + g:variables_lines + \ + g:globals_lines + \ + g:command_header + \) Given (Empty buffer with no filetype): Execute (ALEInfo should return buffer-local global ALE settings): @@ -169,48 +187,64 @@ Execute (ALEInfo should return buffer-local global ALE settings): \ index(g:globals_lines, 'let g:ale_linters = {}') + 1 \) - call CheckInfo([ - \ ' Current Filetype: ', - \ 'Available Linters: []', - \ ' Enabled Linters: []', - \ ' Linter Variables:', - \ '', - \] + g:globals_lines + g:command_header) + call CheckInfo( + \ [ + \ ' Current Filetype: ', + \ 'Available Linters: []', + \ ' Enabled Linters: []', + \ ] + \ + g:fixer_lines + \ + g:variables_lines + \ + g:globals_lines + \ + g:command_header + \) Given (Empty buffer with no filetype): Execute (ALEInfo with no filetype should return the right output): - call CheckInfo([ - \ ' Current Filetype: ', - \ 'Available Linters: []', - \ ' Enabled Linters: []', - \ ' Linter Variables:', - \ '', - \] + g:globals_lines + g:command_header) + call CheckInfo( + \ [ + \ ' Current Filetype: ', + \ 'Available Linters: []', + \ ' Enabled Linters: []', + \ ] + \ + g:fixer_lines + \ + g:variables_lines + \ + g:globals_lines + \ + g:command_header + \) Given testft (Empty buffer): Execute (ALEInfo with a single linter should return the right output): call ale#linter#Define('testft', g:testlinter1) - call CheckInfo([ - \ ' Current Filetype: testft', - \ 'Available Linters: [''testlinter1'']', - \ ' Enabled Linters: [''testlinter1'']', - \ ' Linter Variables:', - \ '', - \] + g:globals_lines + g:command_header) + call CheckInfo( + \ [ + \ ' Current Filetype: testft', + \ 'Available Linters: [''testlinter1'']', + \ ' Enabled Linters: [''testlinter1'']', + \ ] + \ + g:fixer_lines + \ + g:variables_lines + \ + g:globals_lines + \ + g:command_header + \) Given testft (Empty buffer): Execute (ALEInfo with two linters should return the right output): call ale#linter#Define('testft', g:testlinter1) call ale#linter#Define('testft', g:testlinter2) - call CheckInfo([ - \ ' Current Filetype: testft', - \ 'Available Linters: [''testlinter1'', ''testlinter2'']', - \ ' Enabled Linters: [''testlinter1'', ''testlinter2'']', - \ ' Linter Variables:', - \ '', - \] + g:globals_lines + g:command_header) + call CheckInfo( + \ [ + \ ' Current Filetype: testft', + \ 'Available Linters: [''testlinter1'', ''testlinter2'']', + \ ' Enabled Linters: [''testlinter1'', ''testlinter2'']', + \ ] + \ + g:fixer_lines + \ + g:variables_lines + \ + g:globals_lines + \ + g:command_header + \) Given testft (Empty buffer): Execute (ALEInfo should calculate enabled linters correctly): @@ -221,39 +255,51 @@ Execute (ALEInfo should calculate enabled linters correctly): let g:globals_lines[index(g:globals_lines, 'let g:ale_linters = {}')] \ = 'let g:ale_linters = {''testft'': [''testlinter2'']}' - call CheckInfo([ - \ ' Current Filetype: testft', - \ 'Available Linters: [''testlinter1'', ''testlinter2'']', - \ ' Enabled Linters: [''testlinter2'']', - \ ' Linter Variables:', - \ '', - \] + g:globals_lines + g:command_header) + call CheckInfo( + \ [ + \ ' Current Filetype: testft', + \ 'Available Linters: [''testlinter1'', ''testlinter2'']', + \ ' Enabled Linters: [''testlinter2'']', + \ ] + \ + g:fixer_lines + \ + g:variables_lines + \ + g:globals_lines + \ + g:command_header + \) Given testft (Empty buffer): Execute (ALEInfo should only return linters for current filetype): call ale#linter#Define('testft', g:testlinter1) call ale#linter#Define('testft2', g:testlinter2) - call CheckInfo([ - \ ' Current Filetype: testft', - \ 'Available Linters: [''testlinter1'']', - \ ' Enabled Linters: [''testlinter1'']', - \ ' Linter Variables:', - \ '', - \] + g:globals_lines + g:command_header) + call CheckInfo( + \ [ + \ ' Current Filetype: testft', + \ 'Available Linters: [''testlinter1'']', + \ ' Enabled Linters: [''testlinter1'']', + \ ] + \ + g:fixer_lines + \ + g:variables_lines + \ + g:globals_lines + \ + g:command_header + \) Given testft.testft2 (Empty buffer with two filetypes): Execute (ALEInfo with compound filetypes should return linters for both of them): call ale#linter#Define('testft', g:testlinter1) call ale#linter#Define('testft2', g:testlinter2) - call CheckInfo([ - \ ' Current Filetype: testft.testft2', - \ 'Available Linters: [''testlinter1'', ''testlinter2'']', - \ ' Enabled Linters: [''testlinter1'', ''testlinter2'']', - \ ' Linter Variables:', - \ '', - \] + g:globals_lines + g:command_header) + call CheckInfo( + \ [ + \ ' Current Filetype: testft.testft2', + \ 'Available Linters: [''testlinter1'', ''testlinter2'']', + \ ' Enabled Linters: [''testlinter1'', ''testlinter2'']', + \ ] + \ + g:fixer_lines + \ + g:variables_lines + \ + g:globals_lines + \ + g:command_header + \) Given testft.testft2 (Empty buffer with two filetypes): Execute (ALEInfo should return appropriately named global variables): @@ -265,17 +311,24 @@ Execute (ALEInfo should return appropriately named global variables): call ale#linter#Define('testft', g:testlinter1) call ale#linter#Define('testft2', g:testlinter2) - call CheckInfo([ - \ ' Current Filetype: testft.testft2', - \ 'Available Linters: [''testlinter1'', ''testlinter2'']', - \ ' Enabled Linters: [''testlinter1'', ''testlinter2'']', - \ ' Linter Variables:', - \ '', - \ 'let g:ale_testft2_testlinter2_bar = {''x'': ''y''}', - \ 'let g:ale_testft2_testlinter2_foo = 123', - \ 'let g:ale_testft_testlinter1_bar = [''abc'']', - \ 'let g:ale_testft_testlinter1_foo = ''abc''', - \] + g:globals_lines + g:command_header) + call CheckInfo( + \ [ + \ ' Current Filetype: testft.testft2', + \ 'Available Linters: [''testlinter1'', ''testlinter2'']', + \ ' Enabled Linters: [''testlinter1'', ''testlinter2'']', + \ ] + \ + g:fixer_lines + \ + [ + \ ' Linter Variables:', + \ '', + \ 'let g:ale_testft2_testlinter2_bar = {''x'': ''y''}', + \ 'let g:ale_testft2_testlinter2_foo = 123', + \ 'let g:ale_testft_testlinter1_bar = [''abc'']', + \ 'let g:ale_testft_testlinter1_foo = ''abc''', + \ ] + \ + g:globals_lines + \ + g:command_header + \) Execute (ALEInfoToFile should write to a file correctly): if filereadable(g:dir . '/ale-info-test-file') @@ -292,17 +345,24 @@ Execute (ALEInfoToFile should write to a file correctly): execute 'ALEInfoToFile ' . fnameescape(g:dir . '/ale-info-test-file') - AssertEqual [ - \ ' Current Filetype: testft.testft2', - \ 'Available Linters: [''testlinter1'', ''testlinter2'']', - \ ' Enabled Linters: [''testlinter1'', ''testlinter2'']', - \ ' Linter Variables:', - \ '', - \ 'let g:ale_testft2_testlinter2_bar = {''x'': ''y''}', - \ 'let g:ale_testft2_testlinter2_foo = 123', - \ 'let g:ale_testft_testlinter1_bar = [''abc'']', - \ 'let g:ale_testft_testlinter1_foo = ''abc''', - \] + g:globals_lines + g:command_header, readfile(g:dir . '/ale-info-test-file') + AssertEqual + \ [ + \ ' Current Filetype: testft.testft2', + \ 'Available Linters: [''testlinter1'', ''testlinter2'']', + \ ' Enabled Linters: [''testlinter1'', ''testlinter2'']', + \ ] + \ + g:fixer_lines + \ + [ + \ ' Linter Variables:', + \ '', + \ 'let g:ale_testft2_testlinter2_bar = {''x'': ''y''}', + \ 'let g:ale_testft2_testlinter2_foo = 123', + \ 'let g:ale_testft_testlinter1_bar = [''abc'']', + \ 'let g:ale_testft_testlinter1_foo = ''abc''', + \ ] + \ + g:globals_lines + \ + g:command_header, + \ readfile(g:dir . '/ale-info-test-file') Given testft.testft2 (Empty buffer with two filetypes): Execute (ALEInfo should buffer-local linter variables): @@ -312,15 +372,22 @@ Execute (ALEInfo should buffer-local linter variables): call ale#linter#Define('testft', g:testlinter1) call ale#linter#Define('testft2', g:testlinter2) - call CheckInfo([ - \ ' Current Filetype: testft.testft2', - \ 'Available Linters: [''testlinter1'', ''testlinter2'']', - \ ' Enabled Linters: [''testlinter1'', ''testlinter2'']', - \ ' Linter Variables:', - \ '', - \ 'let g:ale_testft2_testlinter2_foo = 123', - \ 'let b:ale_testft2_testlinter2_foo = 456', - \] + g:globals_lines + g:command_header) + call CheckInfo( + \ [ + \ ' Current Filetype: testft.testft2', + \ 'Available Linters: [''testlinter1'', ''testlinter2'']', + \ ' Enabled Linters: [''testlinter1'', ''testlinter2'']', + \ ] + \ + g:fixer_lines + \ + [ + \ ' Linter Variables:', + \ '', + \ 'let g:ale_testft2_testlinter2_foo = 123', + \ 'let b:ale_testft2_testlinter2_foo = 456', + \ ] + \ + g:globals_lines + \ + g:command_header + \) Given testft.testft2 (Empty buffer with two filetypes): Execute (ALEInfo should output linter aliases): @@ -333,18 +400,25 @@ Execute (ALEInfo should output linter aliases): call ale#linter#Define('testft', g:testlinter1) call ale#linter#Define('testft2', g:testlinter2) - call CheckInfo([ - \ ' Current Filetype: testft.testft2', - \ 'Available Linters: [''testlinter1'', ''testlinter2'']', - \ ' Linter Aliases:', - \ '''testlinter1'' -> [''testftalias1'', ''testftalias2'']', - \ '''testlinter2'' -> [''testftalias3'', ''testftalias4'']', - \ ' Enabled Linters: [''testlinter1'', ''testlinter2'']', - \ ' Linter Variables:', - \ '', - \ 'let g:ale_testft2_testlinter2_foo = 123', - \ 'let b:ale_testft2_testlinter2_foo = 456', - \] + g:globals_lines + g:command_header) + call CheckInfo( + \ [ + \ ' Current Filetype: testft.testft2', + \ 'Available Linters: [''testlinter1'', ''testlinter2'']', + \ ' Linter Aliases:', + \ '''testlinter1'' -> [''testftalias1'', ''testftalias2'']', + \ '''testlinter2'' -> [''testftalias3'', ''testftalias4'']', + \ ' Enabled Linters: [''testlinter1'', ''testlinter2'']', + \ ] + \ + g:fixer_lines + \ + [ + \ ' Linter Variables:', + \ '', + \ 'let g:ale_testft2_testlinter2_foo = 123', + \ 'let b:ale_testft2_testlinter2_foo = 456', + \ ] + \ + g:globals_lines + \ + g:command_header + \) Given testft.testft2 (Empty buffer with two filetypes): Execute (ALEInfo should return command history): @@ -356,17 +430,22 @@ Execute (ALEInfo should return command history): call ale#linter#Define('testft', g:testlinter1) call ale#linter#Define('testft2', g:testlinter2) - call CheckInfo([ + call CheckInfo( + \ [ \ ' Current Filetype: testft.testft2', \ 'Available Linters: [''testlinter1'', ''testlinter2'']', \ ' Enabled Linters: [''testlinter1'', ''testlinter2'']', - \ ' Linter Variables:', - \ '', - \] + g:globals_lines + g:command_header + [ - \ '', - \ '(started) ''first command''', - \ '(started) [''/bin/bash'', ''\c'', ''last command'']', - \]) + \ ] + \ + g:fixer_lines + \ + g:variables_lines + \ + g:globals_lines + \ + g:command_header + \ + [ + \ '', + \ '(started) ''first command''', + \ '(started) [''/bin/bash'', ''\c'', ''last command'']', + \ ] + \) Given testft.testft2 (Empty buffer with two filetypes): Execute (ALEInfo command history should print exit codes correctly): @@ -378,17 +457,22 @@ Execute (ALEInfo command history should print exit codes correctly): call ale#linter#Define('testft', g:testlinter1) call ale#linter#Define('testft2', g:testlinter2) - call CheckInfo([ + call CheckInfo( + \ [ \ ' Current Filetype: testft.testft2', \ 'Available Linters: [''testlinter1'', ''testlinter2'']', \ ' Enabled Linters: [''testlinter1'', ''testlinter2'']', - \ ' Linter Variables:', - \ '', - \] + g:globals_lines + g:command_header + [ - \ '', - \ '(finished - exit code 0) ''first command''', - \ '(finished - exit code 1) [''/bin/bash'', ''\c'', ''last command'']', - \]) + \ ] + \ + g:fixer_lines + \ + g:variables_lines + \ + g:globals_lines + \ + g:command_header + \ + [ + \ '', + \ '(finished - exit code 0) ''first command''', + \ '(finished - exit code 1) [''/bin/bash'', ''\c'', ''last command'']', + \ ] + \) Given testft.testft2 (Empty buffer with two filetypes): Execute (ALEInfo command history should print command output if logging is on): @@ -421,31 +505,36 @@ Execute (ALEInfo command history should print command output if logging is on): call ale#linter#Define('testft', g:testlinter1) call ale#linter#Define('testft2', g:testlinter2) - call CheckInfo([ + call CheckInfo( + \ [ \ ' Current Filetype: testft.testft2', \ 'Available Linters: [''testlinter1'', ''testlinter2'']', \ ' Enabled Linters: [''testlinter1'', ''testlinter2'']', - \ ' Linter Variables:', - \ '', - \] + g:globals_lines + g:command_header + [ - \ '', - \ '(finished - exit code 0) ''first command''', - \ '', - \ '<<>>', - \ 'some', - \ 'first command output', - \ '<<>>', - \ '', - \ '(finished - exit code 1) [''/bin/bash'', ''\c'', ''last command'']', - \ '', - \ '<<>>', - \ 'different second command output', - \ '<<>>', - \ '', - \ '(finished - exit code 0) ''command with no output''', - \ '', - \ '<<>>', - \]) + \ ] + \ + g:fixer_lines + \ + g:variables_lines + \ + g:globals_lines + \ + g:command_header + \ + [ + \ '', + \ '(finished - exit code 0) ''first command''', + \ '', + \ '<<>>', + \ 'some', + \ 'first command output', + \ '<<>>', + \ '', + \ '(finished - exit code 1) [''/bin/bash'', ''\c'', ''last command'']', + \ '', + \ '<<>>', + \ 'different second command output', + \ '<<>>', + \ '', + \ '(finished - exit code 0) ''command with no output''', + \ '', + \ '<<>>', + \ ] + \) Execute (ALEInfo should include executable checks in the history): call ale#linter#Define('testft', g:testlinter1) @@ -454,18 +543,23 @@ Execute (ALEInfo should include executable checks in the history): call ale#engine#IsExecutable(bufnr(''), 'TheresNoWayThisIsExecutable') call ale#engine#IsExecutable(bufnr(''), 'TheresNoWayThisIsExecutable') - call CheckInfo([ + call CheckInfo( + \ [ \ ' Current Filetype: testft.testft2', \ 'Available Linters: [''testlinter1'']', \ ' Enabled Linters: [''testlinter1'']', - \ ' Linter Variables:', - \ '', - \] + g:globals_lines + g:command_header + [ - \ '', - \ '(executable check - success) ' . (has('win32') ? 'cmd' : 'echo'), - \ '(executable check - failure) TheresNoWayThisIsExecutable', - \ '(executable check - failure) TheresNoWayThisIsExecutable', - \]) + \ ] + \ + g:fixer_lines + \ + g:variables_lines + \ + g:globals_lines + \ + g:command_header + \ + [ + \ '', + \ '(executable check - success) ' . (has('win32') ? 'cmd' : 'echo'), + \ '(executable check - failure) TheresNoWayThisIsExecutable', + \ '(executable check - failure) TheresNoWayThisIsExecutable', + \ ] + \) Execute (The option for caching failing executable checks should work): let g:ale_cache_executable_check_failures = 1 @@ -478,17 +572,22 @@ Execute (The option for caching failing executable checks should work): call ale#engine#IsExecutable(bufnr(''), 'TheresNoWayThisIsExecutable') call ale#engine#IsExecutable(bufnr(''), 'TheresNoWayThisIsExecutable') - call CheckInfo([ + call CheckInfo( + \ [ \ ' Current Filetype: testft.testft2', \ 'Available Linters: [''testlinter1'']', \ ' Enabled Linters: [''testlinter1'']', - \ ' Linter Variables:', - \ '', - \] + g:globals_lines + g:command_header + [ - \ '', - \ '(executable check - success) ' . (has('win32') ? 'cmd' : 'echo'), - \ '(executable check - failure) TheresNoWayThisIsExecutable', - \]) + \ ] + \ + g:fixer_lines + \ + g:variables_lines + \ + g:globals_lines + \ + g:command_header + \ + [ + \ '', + \ '(executable check - success) ' . (has('win32') ? 'cmd' : 'echo'), + \ '(executable check - failure) TheresNoWayThisIsExecutable', + \ ] + \) Given testft (Empty buffer): Execute (LSP errors for a linter should be outputted): @@ -500,9 +599,9 @@ Execute (LSP errors for a linter should be outputted): \ ' Current Filetype: testft', \ 'Available Linters: [''testlinter1'']', \ ' Enabled Linters: [''testlinter1'']', - \ ' Linter Variables:', - \ '', \ ] + \ + g:fixer_lines + \ + g:variables_lines \ + g:globals_lines \ + [ \ ' LSP Error Messages:', @@ -524,9 +623,9 @@ Execute (LSP errors for other linters shouldn't appear): \ ' Current Filetype: testft', \ 'Available Linters: [''testlinter1'']', \ ' Enabled Linters: [''testlinter1'']', - \ ' Linter Variables:', - \ '', \ ] + \ + g:fixer_lines + \ + g:variables_lines \ + g:globals_lines \ + g:command_header \)