Fix #626 - Automatically use cargo check and cargo check --all-targets for cargo versions that are new enough

This commit is contained in:
w0rp 2017-11-05 18:37:44 +00:00
parent caed406e16
commit 7b5108d934
4 changed files with 190 additions and 8 deletions

View file

@ -1,7 +1,10 @@
" Author: Daniel Schemala <istjanichtzufassen@gmail.com> " Author: Daniel Schemala <istjanichtzufassen@gmail.com>
" Description: rustc invoked by cargo for rust files " Description: rustc invoked by cargo for rust files
let g:ale_rust_cargo_use_check = get(g:, 'ale_rust_cargo_use_check', 0) call ale#Set('rust_cargo_use_check', 1)
call ale#Set('rust_cargo_check_all_targets', 1)
let s:version_cache = {}
function! ale_linters#rust#cargo#GetCargoExecutable(bufnr) abort function! ale_linters#rust#cargo#GetCargoExecutable(bufnr) abort
if ale#path#FindNearestFile(a:bufnr, 'Cargo.toml') isnot# '' if ale#path#FindNearestFile(a:bufnr, 'Cargo.toml') isnot# ''
@ -13,18 +16,70 @@ function! ale_linters#rust#cargo#GetCargoExecutable(bufnr) abort
endif endif
endfunction endfunction
function! ale_linters#rust#cargo#GetCommand(buffer) abort function! ale_linters#rust#cargo#VersionCheck(buffer) abort
let l:command = ale#Var(a:buffer, 'rust_cargo_use_check') if has_key(s:version_cache, 'cargo')
return ''
endif
return 'cargo --version'
endfunction
function! s:GetVersion(executable, output) abort
let l:version = get(s:version_cache, a:executable, [])
for l:match in ale#util#GetMatches(a:output, '\v\d+\.\d+\.\d+')
let l:version = ale#semver#Parse(l:match[0])
let s:version_cache[a:executable] = l:version
endfor
return l:version
endfunction
function! s:CanUseCargoCheck(buffer, version) abort
" Allow `cargo check` to be disabled.
if !ale#Var(a:buffer, 'rust_cargo_use_check')
return 0
endif
return !empty(a:version)
\ && ale#semver#GreaterOrEqual(a:version, [0, 17, 0])
endfunction
function! s:CanUseAllTargets(buffer, version) abort
if !ale#Var(a:buffer, 'rust_cargo_use_check')
return 0
endif
if !ale#Var(a:buffer, 'rust_cargo_check_all_targets')
return 0
endif
return !empty(a:version)
\ && ale#semver#GreaterOrEqual(a:version, [0, 22, 0])
endfunction
function! ale_linters#rust#cargo#GetCommand(buffer, version_output) abort
let l:version = s:GetVersion('cargo', a:version_output)
let l:command = s:CanUseCargoCheck(a:buffer, l:version)
\ ? 'check' \ ? 'check'
\ : 'build' \ : 'build'
let l:all_targets = s:CanUseAllTargets(a:buffer, l:version)
\ ? ' --all-targets'
\ : ''
return 'cargo ' . l:command . ' --frozen --message-format=json -q' return 'cargo '
\ . l:command
\ . l:all_targets
\ . ' --frozen --message-format=json -q'
endfunction endfunction
call ale#linter#Define('rust', { call ale#linter#Define('rust', {
\ 'name': 'cargo', \ 'name': 'cargo',
\ 'executable_callback': 'ale_linters#rust#cargo#GetCargoExecutable', \ 'executable_callback': 'ale_linters#rust#cargo#GetCargoExecutable',
\ 'command_callback': 'ale_linters#rust#cargo#GetCommand', \ 'command_chain': [
\ {'callback': 'ale_linters#rust#cargo#VersionCheck'},
\ {'callback': 'ale_linters#rust#cargo#GetCommand'},
\ ],
\ 'callback': 'ale#handlers#rust#HandleRustErrors', \ 'callback': 'ale#handlers#rust#HandleRustErrors',
\ 'output_stream': 'both', \ 'output_stream': 'both',
\ 'lint_file': 1, \ 'lint_file': 1,

View file

@ -41,10 +41,22 @@ cargo *ale-rust-cargo*
g:ale_rust_cargo_use_check *g:ale_rust_cargo_use_check* g:ale_rust_cargo_use_check *g:ale_rust_cargo_use_check*
*b:ale_rust_cargo_use_check* *b:ale_rust_cargo_use_check*
Type: |Number| Type: |Number|
Default: `0` Default: `1`
When set to `1`, this option will cause ALE to use "cargo check" instead of When set to `1`, this option will cause ALE to use `cargo check` instead of
"cargo build". "cargo check" is supported since version 1.16.0 of Rust. `cargo build` . `cargo check` is supported since version 1.16.0 of Rust.
ALE will never use `cargo check` when the version of `cargo` is less than
0.17.0.
g:ale_rust_cargo_check_all_targets *g:ale_rust_cargo_check_all_targets*
*b:ale_rust_cargo_check_all_targets*
Type: |Number|
Default: `1`
When set to `1`, ALE will set the `--all-targets` option when `cargo check`
is used. See |g:ale_rust_cargo_use_check|,
=============================================================================== ===============================================================================

View file

@ -0,0 +1,115 @@
Before:
Save g:ale_rust_cargo_use_check
Save g:ale_rust_cargo_check_all_targets
unlet! g:ale_rust_cargo_use_check
unlet! g:ale_cargo_check_all_targets
runtime ale_linters/rust/cargo.vim
call ale#test#SetDirectory('/testplugin/test/command_callback')
let g:suffix = ' --frozen --message-format=json -q'
After:
Restore
unlet! g:suffix
call ale#test#RestoreDirectory()
call ale#linter#Reset()
Execute(An empty string should be returned for the cargo executable when there's no Cargo.toml file):
AssertEqual
\ '',
\ ale_linters#rust#cargo#GetCargoExecutable(bufnr(''))
Execute(The executable should be returned when there is a Cargo.toml file):
call ale#test#SetFilename('cargo_paths/test.rs')
AssertEqual
\ 'cargo',
\ ale_linters#rust#cargo#GetCargoExecutable(bufnr(''))
Execute(The VersionCheck function should return the --version command):
AssertEqual
\ 'cargo --version',
\ ale_linters#rust#cargo#VersionCheck(bufnr(''))
Execute(The default command should be correct):
AssertEqual
\ 'cargo build' . g:suffix,
\ ale_linters#rust#cargo#GetCommand(bufnr(''), [])
Execute(`cargo check` should be used when the version is new enough):
AssertEqual
\ 'cargo check' . g:suffix,
\ ale_linters#rust#cargo#GetCommand(bufnr(''), [
\ 'cargo 0.17.0 (3423351a5 2017-10-06)',
\ ])
" We should cache the version check
AssertEqual
\ 'cargo check' . g:suffix,
\ ale_linters#rust#cargo#GetCommand(bufnr(''), [])
AssertEqual '', ale_linters#rust#cargo#VersionCheck(bufnr(''))
Execute(`cargo build` should be used when cargo is too old):
AssertEqual
\ 'cargo build' . g:suffix,
\ ale_linters#rust#cargo#GetCommand(bufnr(''), [
\ 'cargo 0.16.0 (3423351a5 2017-10-06)',
\ ])
" We should cache the version check
AssertEqual
\ 'cargo build' . g:suffix,
\ ale_linters#rust#cargo#GetCommand(bufnr(''), [])
AssertEqual '', ale_linters#rust#cargo#VersionCheck(bufnr(''))
Execute(`cargo build` should be used when g:ale_rust_cargo_use_check is set to 0):
let g:ale_rust_cargo_use_check = 0
AssertEqual
\ 'cargo build' . g:suffix,
\ ale_linters#rust#cargo#GetCommand(bufnr(''), [
\ 'cargo 0.24.0 (3423351a5 2017-10-06)',
\ ])
" We should cache the version check
AssertEqual
\ 'cargo build' . g:suffix,
\ ale_linters#rust#cargo#GetCommand(bufnr(''), [])
AssertEqual '', ale_linters#rust#cargo#VersionCheck(bufnr(''))
Execute(`cargo check --all-targets` should be used when the version is new enough):
AssertEqual
\ 'cargo check --all-targets' . g:suffix,
\ ale_linters#rust#cargo#GetCommand(bufnr(''), [
\ 'cargo 0.22.0 (3423351a5 2017-10-06)',
\ ])
" We should cache the version check
AssertEqual
\ 'cargo check --all-targets' . g:suffix,
\ ale_linters#rust#cargo#GetCommand(bufnr(''), [])
AssertEqual '', ale_linters#rust#cargo#VersionCheck(bufnr(''))
Execute(--all-targets should not be used when g:ale_rust_cargo_check_all_targets is set to 0):
let g:ale_rust_cargo_check_all_targets = 0
AssertEqual
\ 'cargo check' . g:suffix,
\ ale_linters#rust#cargo#GetCommand(bufnr(''), [
\ 'cargo 0.22.0 (3423351a5 2017-10-06)',
\ ])
" We should cache the version check
AssertEqual
\ 'cargo check' . g:suffix,
\ ale_linters#rust#cargo#GetCommand(bufnr(''), [])
AssertEqual '', ale_linters#rust#cargo#VersionCheck(bufnr(''))