diff options
Diffstat (limited to 'autoload')
-rw-r--r-- | autoload/ale.vim | 24 | ||||
-rw-r--r-- | autoload/ale/assert.vim | 172 | ||||
-rw-r--r-- | autoload/ale/c.vim | 14 | ||||
-rw-r--r-- | autoload/ale/command.vim | 52 | ||||
-rw-r--r-- | autoload/ale/cursor.vim | 2 | ||||
-rw-r--r-- | autoload/ale/d.vim | 4 | ||||
-rw-r--r-- | autoload/ale/engine.vim | 20 | ||||
-rw-r--r-- | autoload/ale/engine/ignore.vim | 6 | ||||
-rw-r--r-- | autoload/ale/fix.vim | 4 | ||||
-rw-r--r-- | autoload/ale/fixers/eslint.vim | 24 | ||||
-rw-r--r-- | autoload/ale/fixers/prettier.vim | 23 | ||||
-rw-r--r-- | autoload/ale/fixers/prettier_eslint.vim | 34 | ||||
-rw-r--r-- | autoload/ale/handlers/redpen.vim | 4 | ||||
-rw-r--r-- | autoload/ale/linter.vim | 10 | ||||
-rw-r--r-- | autoload/ale/list.vim | 2 | ||||
-rw-r--r-- | autoload/ale/lsp/message.vim | 2 | ||||
-rw-r--r-- | autoload/ale/node.vim | 2 | ||||
-rw-r--r-- | autoload/ale/path.vim | 9 | ||||
-rw-r--r-- | autoload/ale/references.vim | 16 | ||||
-rw-r--r-- | autoload/ale/semver.vim | 49 | ||||
-rw-r--r-- | autoload/ale/swift.vim | 13 |
21 files changed, 335 insertions, 151 deletions
diff --git a/autoload/ale.vim b/autoload/ale.vim index 5aa5fbfc..a887834b 100644 --- a/autoload/ale.vim +++ b/autoload/ale.vim @@ -8,6 +8,7 @@ let g:ale_echo_msg_info_str = get(g:, 'ale_echo_msg_info_str', 'Info') let g:ale_echo_msg_warning_str = get(g:, 'ale_echo_msg_warning_str', 'Warning') " Ignoring linters, for disabling some, or ignoring LSP diagnostics. let g:ale_linters_ignore = get(g:, 'ale_linters_ignore', {}) +let g:ale_disable_lsp = get(g:, 'ale_disable_lsp', 0) let s:lint_timer = -1 let s:getcmdwintype_exists = exists('*getcmdwintype') @@ -42,6 +43,11 @@ function! ale#ShouldDoNothing(buffer) abort return 1 endif + " Do nothing for diff buffers. + if getbufvar(a:buffer, '&diff') + return 1 + endif + " Do nothing for blacklisted files. if index(get(g:, 'ale_filetype_blacklist', []), l:filetype) >= 0 return 1 @@ -90,8 +96,9 @@ function! s:Lint(buffer, should_lint_file, timer_id) abort " Apply ignore lists for linters only if needed. let l:ignore_config = ale#Var(a:buffer, 'linters_ignore') + let l:disable_lsp = ale#Var(a:buffer, 'disable_lsp') let l:linters = !empty(l:ignore_config) - \ ? ale#engine#ignore#Exclude(l:filetype, l:linters, l:ignore_config) + \ ? ale#engine#ignore#Exclude(l:filetype, l:linters, l:ignore_config, l:disable_lsp) \ : l:linters " Tell other sources that they can start checking the buffer now. @@ -149,12 +156,19 @@ function! ale#Queue(delay, ...) abort endif endfunction -let g:ale_has_override = get(g:, 'ale_has_override', {}) +let s:current_ale_version = [2, 4, 0] -" Call has(), but check a global Dictionary so we can force flags on or off -" for testing purposes. +" A function used to check for ALE features in files outside of the project. function! ale#Has(feature) abort - return get(g:ale_has_override, a:feature, has(a:feature)) + let l:match = matchlist(a:feature, '\c\v^ale-(\d+)\.(\d+)(\.(\d+))?$') + + if !empty(l:match) + let l:version = [l:match[1] + 0, l:match[2] + 0, l:match[4] + 0] + + return ale#semver#GTE(s:current_ale_version, l:version) + endif + + return 0 endfunction " Given a buffer number and a variable name, look for that variable in the diff --git a/autoload/ale/assert.vim b/autoload/ale/assert.vim index 6c2586a6..ed90792d 100644 --- a/autoload/ale/assert.vim +++ b/autoload/ale/assert.vim @@ -1,7 +1,7 @@ -let s:chain_results = [] +let s:command_output = [] -function! ale#assert#WithChainResults(...) abort - let s:chain_results = a:000 +function! ale#assert#GivenCommandOutput(...) abort + let s:command_output = a:000 endfunction function! s:GetLinter() abort @@ -19,6 +19,39 @@ function! s:GetLinter() abort return l:filetype_linters[0] endfunction +function! s:FormatExe(command, executable) abort + return substitute(a:command, '%e', '\=ale#Escape(a:executable)', 'g') +endfunction + +function! s:ProcessDeferredCommands(initial_result) abort + let l:result = a:initial_result + let l:command_index = 0 + let l:command = [] + + while ale#command#IsDeferred(l:result) + call add(l:command, s:FormatExe(l:result.command, l:result.executable)) + + if get(g:, 'ale_run_synchronously_emulate_commands') + " Don't run commands, but simulate the results. + let l:Callback = g:ale_run_synchronously_callbacks[0] + let l:output = get(s:command_output, l:command_index, []) + call l:Callback(0, l:output) + unlet g:ale_run_synchronously_callbacks + + let l:command_index += 1 + else + " Run the commands in the shell, synchronously. + call ale#test#FlushJobs() + endif + + let l:result = l:result.value + endwhile + + call add(l:command, l:result) + + return l:command +endfunction + " Load the currently loaded linter for a test case, and check that the command " matches the given string. function! ale#assert#Linter(expected_executable, expected_command) abort @@ -31,47 +64,20 @@ function! ale#assert#Linter(expected_executable, expected_command) abort let l:executable = l:executable.value endwhile - if has_key(l:linter, 'command_chain') - let l:callbacks = map(copy(l:linter.command_chain), 'v:val.callback') - - " If the expected command is a string, just check the last one. - if type(a:expected_command) is v:t_string - if len(l:callbacks) is 1 - let l:command = call(l:callbacks[0], [l:buffer]) - else - let l:input = get(s:chain_results, len(l:callbacks) - 2, []) - let l:command = call(l:callbacks[-1], [l:buffer, l:input]) - endif - else - let l:command = [] - let l:chain_index = 0 - - for l:Callback in l:callbacks - if l:chain_index is 0 - call add(l:command, call(l:Callback, [l:buffer])) - else - let l:input = get(s:chain_results, l:chain_index - 1, []) - call add(l:command, call(l:Callback, [l:buffer, l:input])) - endif - - let l:chain_index += 1 - endfor - endif - else - let l:command = ale#linter#GetCommand(l:buffer, l:linter) + let l:command = s:ProcessDeferredCommands( + \ ale#linter#GetCommand(l:buffer, l:linter), + \) - while ale#command#IsDeferred(l:command) - call ale#test#FlushJobs() - let l:command = l:command.value - endwhile + if type(a:expected_command) isnot v:t_list + let l:command = l:command[-1] endif if type(l:command) is v:t_string " Replace %e with the escaped executable, so tests keep passing after " linters are changed to use %e. - let l:command = substitute(l:command, '%e', '\=ale#Escape(l:executable)', 'g') + let l:command = s:FormatExe(l:command, l:executable) elseif type(l:command) is v:t_list - call map(l:command, 'substitute(v:val, ''%e'', ''\=ale#Escape(l:executable)'', ''g'')') + call map(l:command, 's:FormatExe(v:val, l:executable)') endif AssertEqual @@ -79,6 +85,17 @@ function! ale#assert#Linter(expected_executable, expected_command) abort \ [l:executable, l:command] endfunction +function! ale#assert#Fixer(expected_result) abort + let l:buffer = bufnr('') + let l:result = s:ProcessDeferredCommands(s:FixerFunction(l:buffer)) + + if type(a:expected_result) isnot v:t_list + let l:result = l:result[-1] + endif + + AssertEqual a:expected_result, l:result +endfunction + function! ale#assert#LinterNotExecuted() abort let l:buffer = bufnr('') let l:linter = s:GetLinter() @@ -128,7 +145,7 @@ function! ale#assert#LSPAddress(expected_address) abort endfunction function! ale#assert#SetUpLinterTestCommands() abort - command! -nargs=+ WithChainResults :call ale#assert#WithChainResults(<args>) + command! -nargs=+ GivenCommandOutput :call ale#assert#GivenCommandOutput(<args>) command! -nargs=+ AssertLinter :call ale#assert#Linter(<args>) command! -nargs=0 AssertLinterNotExecuted :call ale#assert#LinterNotExecuted() command! -nargs=+ AssertLSPOptions :call ale#assert#LSPOptions(<args>) @@ -138,6 +155,11 @@ function! ale#assert#SetUpLinterTestCommands() abort command! -nargs=+ AssertLSPAddress :call ale#assert#LSPAddress(<args>) endfunction +function! ale#assert#SetUpFixerTestCommands() abort + command! -nargs=+ GivenCommandOutput :call ale#assert#GivenCommandOutput(<args>) + command! -nargs=+ AssertFixer :call ale#assert#Fixer(<args>) +endfunction + " A dummy function for making sure this module is loaded. function! ale#assert#SetUpLinterTest(filetype, name) abort " Set up a marker so ALE doesn't create real random temporary filenames. @@ -179,14 +201,21 @@ function! ale#assert#SetUpLinterTest(filetype, name) abort endif call ale#assert#SetUpLinterTestCommands() + + let g:ale_run_synchronously = 1 + let g:ale_run_synchronously_emulate_commands = 1 endfunction function! ale#assert#TearDownLinterTest() abort unlet! g:ale_create_dummy_temporary_file - let s:chain_results = [] - - if exists(':WithChainResults') - delcommand WithChainResults + unlet! g:ale_run_synchronously + unlet! g:ale_run_synchronously_callbacks + unlet! g:ale_run_synchronously_emulate_commands + unlet! g:ale_run_synchronously_command_results + let s:command_output = [] + + if exists(':GivenCommandOutput') + delcommand GivenCommandOutput endif if exists(':AssertLinter') @@ -229,3 +258,62 @@ function! ale#assert#TearDownLinterTest() abort call ale#semver#ResetVersionCache() endif endfunction + +function! ale#assert#SetUpFixerTest(filetype, name) abort + " Set up a marker so ALE doesn't create real random temporary filenames. + let g:ale_create_dummy_temporary_file = 1 + + let l:function_name = ale#fix#registry#GetFunc(a:name) + let s:FixerFunction = function(l:function_name) + + let l:prefix = 'ale_' . a:filetype . '_' . a:name + let b:filter_expr = 'v:val[: len(l:prefix) - 1] is# l:prefix' + + for l:key in filter(keys(g:), b:filter_expr) + execute 'Save g:' . l:key + unlet g:[l:key] + endfor + + for l:key in filter(keys(b:), b:filter_expr) + unlet b:[l:key] + endfor + + execute 'runtime autoload/ale/fixers/' . a:name . '.vim' + + if !exists('g:dir') + call ale#test#SetDirectory('/testplugin/test/fixers') + endif + + call ale#assert#SetUpFixerTestCommands() + + let g:ale_run_synchronously = 1 + let g:ale_run_synchronously_emulate_commands = 1 +endfunction + +function! ale#assert#TearDownFixerTest() abort + unlet! g:ale_create_dummy_temporary_file + unlet! g:ale_run_synchronously + unlet! g:ale_run_synchronously_callbacks + unlet! g:ale_run_synchronously_emulate_commands + unlet! g:ale_run_synchronously_command_results + let s:command_output = [] + unlet! s:FixerFunction + + if exists('g:dir') + call ale#test#RestoreDirectory() + endif + + Restore + + if exists('*ale#semver#ResetVersionCache') + call ale#semver#ResetVersionCache() + endif + + if exists(':GivenCommandOutput') + delcommand GivenCommandOutput + endif + + if exists(':AssertFixer') + delcommand AssertFixer + endif +endfunction diff --git a/autoload/ale/c.vim b/autoload/ale/c.vim index d759b25a..eeb512ba 100644 --- a/autoload/ale/c.vim +++ b/autoload/ale/c.vim @@ -284,6 +284,20 @@ function! ale#c#GetMakeCommand(buffer) abort return '' endfunction +function! ale#c#RunMakeCommand(buffer, Callback) abort + let l:command = ale#c#GetMakeCommand(a:buffer) + + if empty(l:command) + return a:Callback(a:buffer, []) + endif + + return ale#command#Run( + \ a:buffer, + \ l:command, + \ {b, output -> a:Callback(a:buffer, output)}, + \) +endfunction + " Given a buffer number, search for a project root, and output a List " of directories to include based on some heuristics. " diff --git a/autoload/ale/command.vim b/autoload/ale/command.vim index 33ce577c..1bbc4f4c 100644 --- a/autoload/ale/command.vim +++ b/autoload/ale/command.vim @@ -329,30 +329,46 @@ function! ale#command#Run(buffer, command, Callback, ...) abort " " The `_deferred_job_id` is used for both checking the type of object, and " for checking the job ID and status. - let l:result = {'_deferred_job_id': l:job_id} + " + " The original command here is used in tests. + let l:result = { + \ '_deferred_job_id': l:job_id, + \ 'executable': get(l:options, 'executable', ''), + \ 'command': a:command, + \} if get(g:, 'ale_run_synchronously') == 1 && l:job_id - " Run a command synchronously if this test option is set. - call extend(l:line_list, systemlist( - \ type(l:command) is v:t_list - \ ? join(l:command[0:1]) . ' ' . ale#Escape(l:command[2]) - \ : l:command - \)) - - " Don't capture output when the callbacks aren't set. - if !has_key(l:job_options, 'out_cb') - \&& !has_key(l:job_options, 'err_cb') - let l:line_list = [] - endif - if !exists('g:ale_run_synchronously_callbacks') let g:ale_run_synchronously_callbacks = [] endif - call add( - \ g:ale_run_synchronously_callbacks, - \ {-> l:job_options.exit_cb(l:job_id, v:shell_error)} - \) + if get(g:, 'ale_run_synchronously_emulate_commands', 0) + call add( + \ g:ale_run_synchronously_callbacks, + \ {exit_code, output -> [ + \ extend(l:line_list, output), + \ l:job_options.exit_cb(l:job_id, exit_code), + \ ]} + \) + else + " Run a command synchronously if this test option is set. + call extend(l:line_list, systemlist( + \ type(l:command) is v:t_list + \ ? join(l:command[0:1]) . ' ' . ale#Escape(l:command[2]) + \ : l:command + \)) + + " Don't capture output when the callbacks aren't set. + if !has_key(l:job_options, 'out_cb') + \&& !has_key(l:job_options, 'err_cb') + let l:line_list = [] + endif + + call add( + \ g:ale_run_synchronously_callbacks, + \ {-> l:job_options.exit_cb(l:job_id, v:shell_error)} + \) + endif endif return l:result diff --git a/autoload/ale/cursor.vim b/autoload/ale/cursor.vim index eea8ffe6..8c331c5c 100644 --- a/autoload/ale/cursor.vim +++ b/autoload/ale/cursor.vim @@ -25,7 +25,7 @@ function! ale#cursor#TruncatedEcho(original_message) abort let l:cursor_position = getpos('.') " The message is truncated and saved to the history. - setlocal shortmess+=T + silent! setlocal shortmess+=T try exec "norm! :echomsg l:message\n" diff --git a/autoload/ale/d.vim b/autoload/ale/d.vim index 0e232203..2cbfda0d 100644 --- a/autoload/ale/d.vim +++ b/autoload/ale/d.vim @@ -1,6 +1,10 @@ " Author: Auri <me@aurieh.me> " Description: Functions for integrating with D linters. +function! otherproject#util#Double(x) abort + return a:x * 2 +endfunction + function! ale#d#FindDUBConfig(buffer) abort " Find a DUB configuration file in ancestor paths. " The most DUB-specific names will be tried first. diff --git a/autoload/ale/engine.vim b/autoload/ale/engine.vim index 340f6913..6b312b4f 100644 --- a/autoload/ale/engine.vim +++ b/autoload/ale/engine.vim @@ -107,24 +107,36 @@ endfunction " Register a temporary file to be managed with the ALE engine for " a current job run. function! ale#engine#ManageFile(buffer, filename) abort - " TODO: Emit deprecation warning here later. + if !get(g:, 'ale_ignore_2_4_warnings') + execute 'echom ''ale#engine#ManageFile is deprecated. Use `let g:ale_ignore_2_4_warnings = 1` to disable this message.''' + endif + call ale#command#ManageFile(a:buffer, a:filename) endfunction " Same as the above, but manage an entire directory. function! ale#engine#ManageDirectory(buffer, directory) abort - " TODO: Emit deprecation warning here later. + if !get(g:, 'ale_ignore_2_4_warnings') + execute 'echom ''ale#engine#ManageDirectory is deprecated. Use `let g:ale_ignore_2_4_warnings = 1` to disable this message.''' + endif + call ale#command#ManageDirectory(a:buffer, a:directory) endfunction function! ale#engine#CreateFile(buffer) abort - " TODO: Emit deprecation warning here later. + if !get(g:, 'ale_ignore_2_4_warnings') + execute 'echom ''ale#engine#CreateFile is deprecated. Use `let g:ale_ignore_2_4_warnings = 1` to disable this message.''' + endif + return ale#command#CreateFile(a:buffer) endfunction " Create a new temporary directory and manage it in one go. function! ale#engine#CreateDirectory(buffer) abort - " TODO: Emit deprecation warning here later. + if !get(g:, 'ale_ignore_2_4_warnings') + execute 'echom ''ale#engine#CreateDirectory is deprecated. Use `let g:ale_ignore_2_4_warnings = 1` to disable this message.''' + endif + return ale#command#CreateDirectory(a:buffer) endfunction diff --git a/autoload/ale/engine/ignore.vim b/autoload/ale/engine/ignore.vim index 2db2c6c1..80574656 100644 --- a/autoload/ale/engine/ignore.vim +++ b/autoload/ale/engine/ignore.vim @@ -22,7 +22,7 @@ function! ale#engine#ignore#GetList(filetype, config) abort endfunction " Given a List of linter descriptions, exclude the linters to be ignored. -function! ale#engine#ignore#Exclude(filetype, all_linters, config) abort +function! ale#engine#ignore#Exclude(filetype, all_linters, config, disable_lsp) abort let l:names_to_remove = ale#engine#ignore#GetList(a:filetype, a:config) let l:filtered_linters = [] @@ -37,6 +37,10 @@ function! ale#engine#ignore#Exclude(filetype, all_linters, config) abort endif endfor + if a:disable_lsp && has_key(l:linter, 'lsp') && l:linter.lsp isnot# '' + let l:should_include = 0 + endif + if l:should_include call add(l:filtered_linters, l:linter) endif diff --git a/autoload/ale/fix.vim b/autoload/ale/fix.vim index b8674606..c0f05611 100644 --- a/autoload/ale/fix.vim +++ b/autoload/ale/fix.vim @@ -117,6 +117,10 @@ function! s:HandleExit(job_info, buffer, job_output, data) abort let l:input = a:job_info.input endif + if l:ChainCallback isnot v:null && !get(g:, 'ale_ignore_2_4_warnings') + execute 'echom ''chain_with is deprecated. Use `let g:ale_ignore_2_4_warnings = 1` to disable this message.''' + endif + let l:next_index = l:ChainCallback is v:null \ ? a:job_info.callback_index + 1 \ : a:job_info.callback_index diff --git a/autoload/ale/fixers/eslint.vim b/autoload/ale/fixers/eslint.vim index ea5b2a63..0f57cba6 100644 --- a/autoload/ale/fixers/eslint.vim +++ b/autoload/ale/fixers/eslint.vim @@ -3,15 +3,15 @@ function! ale#fixers#eslint#Fix(buffer) abort let l:executable = ale#handlers#eslint#GetExecutable(a:buffer) + let l:command = ale#node#Executable(a:buffer, l:executable) + \ . ' --version' - let l:command = ale#semver#HasVersion(l:executable) - \ ? '' - \ : ale#node#Executable(a:buffer, l:executable) . ' --version' - - return { - \ 'command': l:command, - \ 'chain_with': 'ale#fixers#eslint#ApplyFixForVersion', - \} + return ale#semver#RunWithVersionCheck( + \ a:buffer, + \ l:executable, + \ l:command, + \ function('ale#fixers#eslint#ApplyFixForVersion'), + \) endfunction function! ale#fixers#eslint#ProcessFixDryRunOutput(buffer, output) abort @@ -33,10 +33,8 @@ function! ale#fixers#eslint#ProcessEslintDOutput(buffer, output) abort return a:output endfunction -function! ale#fixers#eslint#ApplyFixForVersion(buffer, version_output) abort +function! ale#fixers#eslint#ApplyFixForVersion(buffer, version) abort let l:executable = ale#handlers#eslint#GetExecutable(a:buffer) - let l:version = ale#semver#GetVersion(l:executable, a:version_output) - let l:config = ale#handlers#eslint#FindConfig(a:buffer) if empty(l:config) @@ -44,7 +42,7 @@ function! ale#fixers#eslint#ApplyFixForVersion(buffer, version_output) abort endif " Use --fix-to-stdout with eslint_d - if l:executable =~# 'eslint_d$' && ale#semver#GTE(l:version, [3, 19, 0]) + if l:executable =~# 'eslint_d$' && ale#semver#GTE(a:version, [3, 19, 0]) return { \ 'command': ale#node#Executable(a:buffer, l:executable) \ . ' --stdin-filename %s --stdin --fix-to-stdout', @@ -53,7 +51,7 @@ function! ale#fixers#eslint#ApplyFixForVersion(buffer, version_output) abort endif " 4.9.0 is the first version with --fix-dry-run - if ale#semver#GTE(l:version, [4, 9, 0]) + if ale#semver#GTE(a:version, [4, 9, 0]) return { \ 'command': ale#node#Executable(a:buffer, l:executable) \ . ' --stdin-filename %s --stdin --fix-dry-run --format=json', diff --git a/autoload/ale/fixers/prettier.vim b/autoload/ale/fixers/prettier.vim index 0f99ae97..b7f0ecd7 100644 --- a/autoload/ale/fixers/prettier.vim +++ b/autoload/ale/fixers/prettier.vim @@ -15,16 +15,12 @@ function! ale#fixers#prettier#GetExecutable(buffer) abort endfunction function! ale#fixers#prettier#Fix(buffer) abort - let l:executable = ale#fixers#prettier#GetExecutable(a:buffer) - - let l:command = ale#semver#HasVersion(l:executable) - \ ? '' - \ : ale#Escape(l:executable) . ' --version' - - return { - \ 'command': l:command, - \ 'chain_with': 'ale#fixers#prettier#ApplyFixForVersion', - \} + return ale#semver#RunWithVersionCheck( + \ a:buffer, + \ ale#fixers#prettier#GetExecutable(a:buffer), + \ '%e --version', + \ function('ale#fixers#prettier#ApplyFixForVersion'), + \) endfunction function! ale#fixers#prettier#ProcessPrettierDOutput(buffer, output) abort @@ -38,10 +34,9 @@ function! ale#fixers#prettier#ProcessPrettierDOutput(buffer, output) abort return a:output endfunction -function! ale#fixers#prettier#ApplyFixForVersion(buffer, version_output) abort +function! ale#fixers#prettier#ApplyFixForVersion(buffer, version) abort let l:executable = ale#fixers#prettier#GetExecutable(a:buffer) let l:options = ale#Var(a:buffer, 'javascript_prettier_options') - let l:version = ale#semver#GetVersion(l:executable, a:version_output) let l:parser = '' " Append the --parser flag depending on the current filetype (unless it's @@ -50,7 +45,7 @@ function! ale#fixers#prettier#ApplyFixForVersion(buffer, version_output) abort " Mimic Prettier's defaults. In cases without a file extension or " filetype (scratch buffer), Prettier needs `parser` set to know how " to process the buffer. - if ale#semver#GTE(l:version, [1, 16, 0]) + if ale#semver#GTE(a:version, [1, 16, 0]) let l:parser = 'babel' else let l:parser = 'babylon' @@ -94,7 +89,7 @@ function! ale#fixers#prettier#ApplyFixForVersion(buffer, version_output) abort endif " 1.4.0 is the first version with --stdin-filepath - if ale#semver#GTE(l:version, [1, 4, 0]) + if ale#semver#GTE(a:version, [1, 4, 0]) return { \ 'command': ale#path#BufferCdString(a:buffer) \ . ale#Escape(l:executable) diff --git a/autoload/ale/fixers/prettier_eslint.vim b/autoload/ale/fixers/prettier_eslint.vim index bc0caadd..1e66f49e 100644 --- a/autoload/ale/fixers/prettier_eslint.vim +++ b/autoload/ale/fixers/prettier_eslint.vim @@ -2,13 +2,9 @@ " w0rp <devw0rp@gmail.com>, morhetz (Pavel Pertsev) <morhetz@gmail.com> " Description: Integration between Prettier and ESLint. -function! ale#fixers#prettier_eslint#SetOptionDefaults() abort - call ale#Set('javascript_prettier_eslint_executable', 'prettier-eslint') - call ale#Set('javascript_prettier_eslint_use_global', get(g:, 'ale_use_global_executables', 0)) - call ale#Set('javascript_prettier_eslint_options', '') -endfunction - -call ale#fixers#prettier_eslint#SetOptionDefaults() +call ale#Set('javascript_prettier_eslint_executable', 'prettier-eslint') +call ale#Set('javascript_prettier_eslint_use_global', get(g:, 'ale_use_global_executables', 0)) +call ale#Set('javascript_prettier_eslint_options', '') function! ale#fixers#prettier_eslint#GetExecutable(buffer) abort return ale#node#FindExecutable(a:buffer, 'javascript_prettier_eslint', [ @@ -18,26 +14,20 @@ function! ale#fixers#prettier_eslint#GetExecutable(buffer) abort endfunction function! ale#fixers#prettier_eslint#Fix(buffer) abort - let l:executable = ale#fixers#prettier_eslint#GetExecutable(a:buffer) - - let l:command = ale#semver#HasVersion(l:executable) - \ ? '' - \ : ale#Escape(l:executable) . ' --version' - - return { - \ 'command': l:command, - \ 'chain_with': 'ale#fixers#prettier_eslint#ApplyFixForVersion', - \} + return ale#semver#RunWithVersionCheck( + \ a:buffer, + \ ale#fixers#prettier_eslint#GetExecutable(a:buffer), + \ '%e --version', + \ function('ale#fixers#prettier_eslint#ApplyFixForVersion'), + \) endfunction -function! ale#fixers#prettier_eslint#ApplyFixForVersion(buffer, version_output) abort +function! ale#fixers#prettier_eslint#ApplyFixForVersion(buffer, version) abort let l:options = ale#Var(a:buffer, 'javascript_prettier_eslint_options') let l:executable = ale#fixers#prettier_eslint#GetExecutable(a:buffer) - let l:version = ale#semver#GetVersion(l:executable, a:version_output) - " 4.2.0 is the first version with --eslint-config-path - let l:config = ale#semver#GTE(l:version, [4, 2, 0]) + let l:config = ale#semver#GTE(a:version, [4, 2, 0]) \ ? ale#handlers#eslint#FindConfig(a:buffer) \ : '' let l:eslint_config_option = !empty(l:config) @@ -45,7 +35,7 @@ function! ale#fixers#prettier_eslint#ApplyFixForVersion(buffer, version_output) \ : '' " 4.4.0 is the first version with --stdin-filepath - if ale#semver#GTE(l:version, [4, 4, 0]) + if ale#semver#GTE(a:version, [4, 4, 0]) return { \ 'command': ale#path#BufferCdString(a:buffer) \ . ale#Escape(l:executable) diff --git a/autoload/ale/handlers/redpen.vim b/autoload/ale/handlers/redpen.vim index 84e331ed..195057ca 100644 --- a/autoload/ale/handlers/redpen.vim +++ b/autoload/ale/handlers/redpen.vim @@ -4,10 +4,10 @@ function! ale#handlers#redpen#HandleRedpenOutput(buffer, lines) abort " Only one file was passed to redpen. So response array has only one " element. - let l:res = json_decode(join(a:lines))[0] + let l:res = get(ale#util#FuzzyJSONDecode(a:lines, []), 0, {}) let l:output = [] - for l:err in l:res.errors + for l:err in get(l:res, 'errors', []) let l:item = { \ 'text': l:err.message, \ 'type': 'W', diff --git a/autoload/ale/linter.vim b/autoload/ale/linter.vim index 4937a6d7..273778c7 100644 --- a/autoload/ale/linter.vim +++ b/autoload/ale/linter.vim @@ -32,7 +32,7 @@ let s:default_ale_linter_aliases = { " NOTE: Update the g:ale_linters documentation when modifying this. let s:default_ale_linters = { \ 'csh': ['shell'], -\ 'elixir': ['credo', 'dialyxir', 'dogma', 'elixir-ls'], +\ 'elixir': ['credo', 'dialyxir', 'dogma'], \ 'go': ['gofmt', 'golint', 'go vet'], \ 'hack': ['hack'], \ 'help': [], @@ -340,7 +340,13 @@ function! ale#linter#PreProcess(filetype, linter) abort throw '`aliases` must be a List of String values' endif - " TODO: Emit deprecation warnings for deprecated options later. + for l:key in filter(keys(l:obj), 'v:val[-9:] is# ''_callback'' || v:val is# ''command_chain''') + if !get(g:, 'ale_ignore_2_4_warnings') + execute 'echom l:key . '' is deprecated. Use `let g:ale_ignore_2_4_warnings = 1` to disable this message.''' + endif + + break + endfor return l:obj endfunction diff --git a/autoload/ale/list.vim b/autoload/ale/list.vim index 3417575c..63d97f35 100644 --- a/autoload/ale/list.vim +++ b/autoload/ale/list.vim @@ -115,7 +115,7 @@ function! s:SetListsImpl(timer_id, buffer, loclist) abort let l:open_type = '' if ale#Var(a:buffer, 'list_vertical') == 1 - let l:open_type = 'vert ' + let l:open_type = 'vert rightbelow ' endif if g:ale_set_quickfix diff --git a/autoload/ale/lsp/message.vim b/autoload/ale/lsp/message.vim index 646dbd20..4ad94c4b 100644 --- a/autoload/ale/lsp/message.vim +++ b/autoload/ale/lsp/message.vim @@ -159,7 +159,7 @@ function! ale#lsp#message#Hover(buffer, line, column) abort endfunction function! ale#lsp#message#DidChangeConfiguration(buffer, config) abort - return [0, 'workspace/didChangeConfiguration', { + return [1, 'workspace/didChangeConfiguration', { \ 'settings': a:config, \}] endfunction diff --git a/autoload/ale/node.vim b/autoload/ale/node.vim index f75280b7..69060122 100644 --- a/autoload/ale/node.vim +++ b/autoload/ale/node.vim @@ -32,7 +32,7 @@ endfunction " " The executable is only prefixed for Windows machines function! ale#node#Executable(buffer, executable) abort - if ale#Has('win32') && a:executable =~? '\.js$' + if has('win32') && a:executable =~? '\.js$' let l:node = ale#Var(a:buffer, 'windows_node_executable_path') return ale#Escape(l:node) . ' ' . ale#Escape(a:executable) diff --git a/autoload/ale/path.vim b/autoload/ale/path.vim index ca3afc52..60d42eb5 100644 --- a/autoload/ale/path.vim +++ b/autoload/ale/path.vim @@ -205,10 +205,13 @@ function! ale#path#FromURI(uri) abort let l:encoded_path = a:uri endif + let l:path = ale#uri#Decode(l:encoded_path) + " If the path is like /C:/foo/bar, it should be C:\foo\bar instead. - if l:encoded_path =~# '^/[a-zA-Z]:' - let l:encoded_path = substitute(l:encoded_path[1:], '/', '\\', 'g') + if has('win32') && l:path =~# '^/[a-zA-Z][:|]' + let l:path = substitute(l:path[1:], '/', '\\', 'g') + let l:path = l:path[0] . ':' . l:path[2:] endif - return ale#uri#Decode(l:encoded_path) + return l:path endfunction diff --git a/autoload/ale/references.vim b/autoload/ale/references.vim index 0e88afe2..b9725e1e 100644 --- a/autoload/ale/references.vim +++ b/autoload/ale/references.vim @@ -49,13 +49,15 @@ function! ale#references#HandleLSPResponse(conn_id, response) abort let l:result = get(a:response, 'result', []) let l:item_list = [] - for l:response_item in l:result - call add(l:item_list, { - \ 'filename': ale#path#FromURI(l:response_item.uri), - \ 'line': l:response_item.range.start.line + 1, - \ 'column': l:response_item.range.start.character + 1, - \}) - endfor + if type(l:result) is v:t_list + for l:response_item in l:result + call add(l:item_list, { + \ 'filename': ale#path#FromURI(l:response_item.uri), + \ 'line': l:response_item.range.start.line + 1, + \ 'column': l:response_item.range.start.character + 1, + \}) + endfor + endif if empty(l:item_list) call ale#util#Execute('echom ''No references found.''') diff --git a/autoload/ale/semver.vim b/autoload/ale/semver.vim index 5f1b46fc..e3eb49c0 100644 --- a/autoload/ale/semver.vim +++ b/autoload/ale/semver.vim @@ -5,31 +5,52 @@ function! ale#semver#ResetVersionCache() abort let s:version_cache = {} endfunction +function! ale#semver#ParseVersion(version_lines) abort + for l:line in a:version_lines + let l:match = matchlist(l:line, '\v(\d+)\.(\d+)(\.(\d+))?') + + if !empty(l:match) + return [l:match[1] + 0, l:match[2] + 0, l:match[4] + 0] + endif + endfor + + return [] +endfunction + " Given an executable name and some lines of output, which can be empty, " parse the version from the lines of output, or return the cached version " triple [major, minor, patch] " " If the version cannot be found, an empty List will be returned instead. -function! ale#semver#GetVersion(executable, version_lines) abort +function! s:GetVersion(executable, version_lines) abort let l:version = get(s:version_cache, a:executable, []) + let l:parsed_version = ale#semver#ParseVersion(a:version_lines) - for l:line in a:version_lines - let l:match = matchlist(l:line, '\v(\d+)\.(\d+)(\.(\d+))?') - - if !empty(l:match) - let l:version = [l:match[1] + 0, l:match[2] + 0, l:match[4] + 0] - let s:version_cache[a:executable] = l:version - - break - endif - endfor + if !empty(l:parsed_version) + let l:version = l:parsed_version + let s:version_cache[a:executable] = l:version + endif return l:version endfunction -" Return 1 if the semver version has been cached for a given executable. -function! ale#semver#HasVersion(executable) abort - return has_key(s:version_cache, a:executable) +function! ale#semver#RunWithVersionCheck(buffer, executable, command, Callback) abort + if empty(a:executable) + return '' + endif + + let l:cache = s:version_cache + + if has_key(s:version_cache, a:executable) + return a:Callback(a:buffer, s:version_cache[a:executable]) + endif + + return ale#command#Run( + \ a:buffer, + \ a:command, + \ {_, output -> a:Callback(a:buffer, s:GetVersion(a:executable, output))}, + \ {'output_stream': 'both', 'executable': a:executable} + \) endfunction " Given two triples of integers [major, minor, patch], compare the triples diff --git a/autoload/ale/swift.vim b/autoload/ale/swift.vim new file mode 100644 index 00000000..b31b8dc5 --- /dev/null +++ b/autoload/ale/swift.vim @@ -0,0 +1,13 @@ +" Author: Dan Loman <https://github.com/namolnad> +" Description: Functions for integrating with Swift tools + +" Find the nearest dir containing a Package.swift file and assume it is the root of the Swift project. +function! ale#swift#FindProjectRoot(buffer) abort + let l:swift_config = ale#path#FindNearestFile(a:buffer, 'Package.swift') + + if !empty(l:swift_config) + return fnamemodify(l:swift_config, ':h') + endif + + return '' +endfunction |