summaryrefslogtreecommitdiff
path: root/autoload
diff options
context:
space:
mode:
authorw0rp <devw0rp@gmail.com>2019-04-07 14:58:06 +0100
committerw0rp <devw0rp@gmail.com>2019-04-07 14:58:06 +0100
commit3bebcb5d48a7150f5a318952ee309acb67fb376d (patch)
tree97edd84badca566894fd4c4f10c2a786df2fe079 /autoload
parentcdf89f8269aec31d0dfddf3a2769027d72d38155 (diff)
downloadale-3bebcb5d48a7150f5a318952ee309acb67fb376d.zip
#2132 - Replace command_chain and chain_with with ale#command#Run
Diffstat (limited to 'autoload')
-rw-r--r--autoload/ale/assert.vim172
-rw-r--r--autoload/ale/c.vim14
-rw-r--r--autoload/ale/command.vim52
-rw-r--r--autoload/ale/d.vim4
-rw-r--r--autoload/ale/fixers/eslint.vim24
-rw-r--r--autoload/ale/fixers/prettier.vim23
-rw-r--r--autoload/ale/fixers/prettier_eslint.vim34
-rw-r--r--autoload/ale/node.vim2
-rw-r--r--autoload/ale/semver.vim49
9 files changed, 250 insertions, 124 deletions
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/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/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/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/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