Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Bartek thindil Jasicki 2020-06-07 09:26:06 +02:00
commit a5e7f2c8bb
98 changed files with 1937 additions and 492 deletions

View file

@ -1,5 +1,6 @@
--- ---
name: Report a bug name: Report a bug
labels: bug
about: Report a bug with ALE. about: Report a bug with ALE.
--- ---

View file

@ -1,5 +1,6 @@
--- ---
name: Suggest a new linter or fixer name: Suggest a new linter or fixer
labels: new tool
about: Suggest a new tool ALE can officially integrate with. about: Suggest a new tool ALE can officially integrate with.
--- ---

View file

@ -1,5 +1,6 @@
--- ---
name: Suggest an improvement name: Suggest an improvement
labels: enhancement
about: Suggest some way to improve ALE, or add a new feature. about: Suggest some way to improve ALE, or add a new feature.
--- ---

View file

@ -35,6 +35,10 @@ If you don't care about Language Server Protocol, ALE won't load any of the code
for working with it unless needed. One of ALE's general missions is that you for working with it unless needed. One of ALE's general missions is that you
won't pay for the features that you don't use. won't pay for the features that you don't use.
**Help Wanted:** If you would like to help maintain this plugin by managing the
many issues and pull requests that are submitted, please send the author an
email at [dev@w0rp.com](mailto:dev@w0rp.com?subject=Helping%20with%20ALE).
If you enjoy this plugin, feel free to contribute or check out the author's If you enjoy this plugin, feel free to contribute or check out the author's
other content at [w0rp.com](https://w0rp.com). other content at [w0rp.com](https://w0rp.com).

View file

@ -0,0 +1,4 @@
" Author: Ian2020 <https://github.com/Ian2020>
" Description: shellcheck linter for bats scripts.
call ale#handlers#shellcheck#DefineLinter('bats')

View file

@ -29,6 +29,6 @@ call ale#linter#Define('clojure', {
\ 'name': 'clj-kondo', \ 'name': 'clj-kondo',
\ 'output_stream': 'stdout', \ 'output_stream': 'stdout',
\ 'executable': 'clj-kondo', \ 'executable': 'clj-kondo',
\ 'command': 'clj-kondo --lint %t', \ 'command': 'clj-kondo --cache --lint %t',
\ 'callback': 'ale_linters#clojure#clj_kondo#HandleCljKondoFormat', \ 'callback': 'ale_linters#clojure#clj_kondo#HandleCljKondoFormat',
\}) \})

21
ale_linters/go/revive.vim Normal file
View file

@ -0,0 +1,21 @@
" Author: Penghui Liao <liaoishere@gmail.com>
" Description: Adds support for revive
call ale#Set('go_revive_executable', 'revive')
call ale#Set('go_revive_options', '')
function! ale_linters#go#revive#GetCommand(buffer) abort
let l:options = ale#Var(a:buffer, 'go_revive_options')
return ale#go#EnvString(a:buffer) . '%e'
\ . (!empty(l:options) ? ' ' . l:options : '')
\ . ' %t'
endfunction
call ale#linter#Define('go', {
\ 'name': 'revive',
\ 'output_stream': 'both',
\ 'executable': {b -> ale#Var(b, 'go_revive_executable')},
\ 'command': function('ale_linters#go#revive#GetCommand'),
\ 'callback': 'ale#handlers#unix#HandleAsWarning',
\})

View file

@ -5,5 +5,5 @@ call ale#linter#Define('graphql', {
\ 'name': 'eslint', \ 'name': 'eslint',
\ 'executable': function('ale#handlers#eslint#GetExecutable'), \ 'executable': function('ale#handlers#eslint#GetExecutable'),
\ 'command': function('ale#handlers#eslint#GetCommand'), \ 'command': function('ale#handlers#eslint#GetCommand'),
\ 'callback': 'ale#handlers#eslint#Handle', \ 'callback': 'ale#handlers#eslint#HandleJSON',
\}) \})

View file

@ -7,6 +7,7 @@ call ale#Set('java_eclipselsp_path', ale#path#Simplify($HOME . '/eclipse.jdt.ls'
call ale#Set('java_eclipselsp_config_path', '') call ale#Set('java_eclipselsp_config_path', '')
call ale#Set('java_eclipselsp_workspace_path', '') call ale#Set('java_eclipselsp_workspace_path', '')
call ale#Set('java_eclipselsp_executable', 'java') call ale#Set('java_eclipselsp_executable', 'java')
call ale#Set('java_eclipselsp_javaagent', '')
function! ale_linters#java#eclipselsp#Executable(buffer) abort function! ale_linters#java#eclipselsp#Executable(buffer) abort
return ale#Var(a:buffer, 'java_eclipselsp_executable') return ale#Var(a:buffer, 'java_eclipselsp_executable')
@ -100,12 +101,30 @@ function! ale_linters#java#eclipselsp#WorkspacePath(buffer) abort
return ale#path#Dirname(ale#java#FindProjectRoot(a:buffer)) return ale#path#Dirname(ale#java#FindProjectRoot(a:buffer))
endfunction endfunction
function! ale_linters#java#eclipselsp#Javaagent(buffer) abort
let l:rets = []
let l:raw = ale#Var(a:buffer, 'java_eclipselsp_javaagent')
if empty(l:raw)
return ''
endif
let l:jars = split(l:raw)
for l:jar in l:jars
call add(l:rets, ale#Escape('-javaagent:' . l:jar))
endfor
return join(l:rets, ' ')
endfunction
function! ale_linters#java#eclipselsp#Command(buffer, version) abort function! ale_linters#java#eclipselsp#Command(buffer, version) abort
let l:path = ale#Var(a:buffer, 'java_eclipselsp_path') let l:path = ale#Var(a:buffer, 'java_eclipselsp_path')
let l:executable = ale_linters#java#eclipselsp#Executable(a:buffer) let l:executable = ale_linters#java#eclipselsp#Executable(a:buffer)
let l:cmd = [ ale#Escape(l:executable), let l:cmd = [ ale#Escape(l:executable),
\ ale_linters#java#eclipselsp#Javaagent(a:buffer),
\ '-Declipse.application=org.eclipse.jdt.ls.core.id1', \ '-Declipse.application=org.eclipse.jdt.ls.core.id1',
\ '-Dosgi.bundles.defaultStartLevel=4', \ '-Dosgi.bundles.defaultStartLevel=4',
\ '-Declipse.product=org.eclipse.jdt.ls.core.product', \ '-Declipse.product=org.eclipse.jdt.ls.core.product',

View file

@ -6,6 +6,7 @@ let s:classpath_sep = has('unix') ? ':' : ';'
call ale#Set('java_javac_executable', 'javac') call ale#Set('java_javac_executable', 'javac')
call ale#Set('java_javac_options', '') call ale#Set('java_javac_options', '')
call ale#Set('java_javac_classpath', '') call ale#Set('java_javac_classpath', '')
call ale#Set('java_javac_sourcepath', '')
function! ale_linters#java#javac#RunWithImportPaths(buffer) abort function! ale_linters#java#javac#RunWithImportPaths(buffer) abort
let l:command = '' let l:command = ''
@ -40,10 +41,15 @@ endfunction
function! s:BuildClassPathOption(buffer, import_paths) abort function! s:BuildClassPathOption(buffer, import_paths) abort
" Filter out lines like [INFO], etc. " Filter out lines like [INFO], etc.
let l:class_paths = filter(a:import_paths[:], 'v:val !~# ''[''') let l:class_paths = filter(a:import_paths[:], 'v:val !~# ''[''')
call extend( let l:cls_path = ale#Var(a:buffer, 'java_javac_classpath')
\ l:class_paths,
\ split(ale#Var(a:buffer, 'java_javac_classpath'), s:classpath_sep), if !empty(l:cls_path) && type(l:cls_path) is v:t_string
\) call extend(l:class_paths, split(l:cls_path, s:classpath_sep))
endif
if !empty(l:cls_path) && type(l:cls_path) is v:t_list
call extend(l:class_paths, l:cls_path)
endif
return !empty(l:class_paths) return !empty(l:class_paths)
\ ? '-cp ' . ale#Escape(join(l:class_paths, s:classpath_sep)) \ ? '-cp ' . ale#Escape(join(l:class_paths, s:classpath_sep))
@ -79,6 +85,27 @@ function! ale_linters#java#javac#GetCommand(buffer, import_paths, meta) abort
endif endif
endif endif
let l:source_paths = []
let l:source_path = ale#Var(a:buffer, 'java_javac_sourcepath')
if !empty(l:source_path) && type(l:source_path) is v:t_string
let l:source_paths = split(l:source_path, s:classpath_sep)
endif
if !empty(l:source_path) && type(l:source_path) is v:t_list
let l:source_paths = l:source_path
endif
if !empty(l:source_paths)
for l:path in l:source_paths
let l:sp_path = ale#path#FindNearestDirectory(a:buffer, l:path)
if !empty(l:sp_path)
call add(l:sp_dirs, l:sp_path)
endif
endfor
endif
if !empty(l:sp_dirs) if !empty(l:sp_dirs)
let l:sp_option = '-sourcepath ' let l:sp_option = '-sourcepath '
\ . ale#Escape(join(l:sp_dirs, s:classpath_sep)) \ . ale#Escape(join(l:sp_dirs, s:classpath_sep))

View file

@ -7,6 +7,7 @@ call ale#Set('javascript_standard_options', '')
function! ale_linters#javascript#standard#GetExecutable(buffer) abort function! ale_linters#javascript#standard#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'javascript_standard', [ return ale#node#FindExecutable(a:buffer, 'javascript_standard', [
\ 'node_modules/standardx/bin/cmd.js',
\ 'node_modules/standard/bin/cmd.js', \ 'node_modules/standard/bin/cmd.js',
\ 'node_modules/semistandard/bin/cmd.js', \ 'node_modules/semistandard/bin/cmd.js',
\ 'node_modules/.bin/standard', \ 'node_modules/.bin/standard',

View file

@ -174,6 +174,7 @@ endfunction
call ale#linter#Define('kotlin', { call ale#linter#Define('kotlin', {
\ 'name': 'kotlinc', \ 'name': 'kotlinc',
\ 'executable': 'kotlinc', \ 'executable': 'kotlinc',
\ 'output_stream': 'stderr',
\ 'command': function('ale_linters#kotlin#kotlinc#RunWithImportPaths'), \ 'command': function('ale_linters#kotlin#kotlinc#RunWithImportPaths'),
\ 'callback': 'ale_linters#kotlin#kotlinc#Handle', \ 'callback': 'ale_linters#kotlin#kotlinc#Handle',
\ 'lint_file': 1, \ 'lint_file': 1,

View file

@ -12,6 +12,7 @@ endfunction
" https://rkeithhill.wordpress.com/2007/10/30/powershell-quicktip-preparsing-scripts-to-check-for-syntax-errors/ " https://rkeithhill.wordpress.com/2007/10/30/powershell-quicktip-preparsing-scripts-to-check-for-syntax-errors/
function! ale_linters#powershell#powershell#GetCommand(buffer) abort function! ale_linters#powershell#powershell#GetCommand(buffer) abort
let l:script = ['Param($Script); let l:script = ['Param($Script);
\ $ErrorView = "Normal";
\ trap {$_;continue} & { \ trap {$_;continue} & {
\ $Contents = Get-Content -Path $Script; \ $Contents = Get-Content -Path $Script;
\ $Contents = [string]::Join([Environment]::NewLine, $Contents); \ $Contents = [string]::Join([Environment]::NewLine, $Contents);

View file

@ -3,6 +3,7 @@
call ale#Set('python_mypy_executable', 'mypy') call ale#Set('python_mypy_executable', 'mypy')
call ale#Set('python_mypy_ignore_invalid_syntax', 0) call ale#Set('python_mypy_ignore_invalid_syntax', 0)
call ale#Set('python_mypy_show_notes', 1)
call ale#Set('python_mypy_options', '') call ale#Set('python_mypy_options', '')
call ale#Set('python_mypy_use_global', get(g:, 'ale_use_global_executables', 0)) call ale#Set('python_mypy_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('python_mypy_auto_pipenv', 0) call ale#Set('python_mypy_auto_pipenv', 0)
@ -18,6 +19,15 @@ endfunction
" The directory to change to before running mypy " The directory to change to before running mypy
function! s:GetDir(buffer) abort function! s:GetDir(buffer) abort
" If we find a directory with "mypy.ini" in it use that,
" else try and find the "python project" root, or failing
" that, run from the same folder as the current file
for l:path in ale#path#Upwards(expand('#' . a:buffer . ':p:h'))
if filereadable(l:path . '/mypy.ini')
return l:path
endif
endfor
let l:project_root = ale#python#FindProjectRoot(a:buffer) let l:project_root = ale#python#FindProjectRoot(a:buffer)
return !empty(l:project_root) return !empty(l:project_root)
@ -51,7 +61,16 @@ function! ale_linters#python#mypy#Handle(buffer, lines) abort
" Lines like these should be ignored below: " Lines like these should be ignored below:
" "
" file.py:4: note: (Stub files are from https://github.com/python/typeshed) " file.py:4: note: (Stub files are from https://github.com/python/typeshed)
let l:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+):?(\d+)?: (error|warning): (.+)$'
let l:types = 'error|warning'
if ale#Var(a:buffer, 'python_mypy_show_notes')
let l:types = 'error|warning|note'
endif
let l:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+):?(\d+)?: ('
\ . l:types
\ . '): (.+)$'
let l:output = [] let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:match in ale#util#GetMatches(a:lines, l:pattern)
@ -65,7 +84,7 @@ function! ale_linters#python#mypy#Handle(buffer, lines) abort
\ 'filename': ale#path#GetAbsPath(l:dir, l:match[1]), \ 'filename': ale#path#GetAbsPath(l:dir, l:match[1]),
\ 'lnum': l:match[2] + 0, \ 'lnum': l:match[2] + 0,
\ 'col': l:match[3] + 0, \ 'col': l:match[3] + 0,
\ 'type': l:match[4] is# 'error' ? 'E' : 'W', \ 'type': l:match[4] is# 'error' ? 'E' : (l:match[4] is# 'note' ? 'I': 'W'),
\ 'text': l:match[5], \ 'text': l:match[5],
\}) \})
endfor endfor

View file

@ -0,0 +1,24 @@
" Author: Jon Gjengset <jon@thesquareplanet.com>
" Description: The next generation language server for Rust
call ale#Set('rust_analyzer_executable', 'rust-analyzer')
call ale#Set('rust_analyzer_config', {})
function! ale_linters#rust#analyzer#GetCommand(buffer) abort
return '%e'
endfunction
function! ale_linters#rust#analyzer#GetProjectRoot(buffer) abort
let l:cargo_file = ale#path#FindNearestFile(a:buffer, 'Cargo.toml')
return !empty(l:cargo_file) ? fnamemodify(l:cargo_file, ':h') : ''
endfunction
call ale#linter#Define('rust', {
\ 'name': 'analyzer',
\ 'lsp': 'stdio',
\ 'lsp_config': {b -> ale#Var(b, 'rust_analyzer_config')},
\ 'executable': {b -> ale#Var(b, 'rust_analyzer_executable')},
\ 'command': function('ale_linters#rust#analyzer#GetCommand'),
\ 'project_root': function('ale_linters#rust#analyzer#GetProjectRoot'),
\})

View file

@ -32,6 +32,8 @@ function! ale_linters#scala#metals#GetProjectRoot(buffer) abort
\) \)
endif endif
endfor endfor
return ''
endfunction endfunction
function! ale_linters#scala#metals#GetCommand(buffer) abort function! ale_linters#scala#metals#GetCommand(buffer) abort

View file

@ -1,107 +1,4 @@
" Author: w0rp <devw0rp@gmail.com> " Author: w0rp <devw0rp@gmail.com>
" Description: This file adds support for using the shellcheck linter with " Description: shellcheck linter for shell scripts.
" shell scripts.
" This global variable can be set with a string of comma-separated error call ale#handlers#shellcheck#DefineLinter('sh')
" codes to exclude from shellcheck. For example:
"
" let g:ale_sh_shellcheck_exclusions = 'SC2002,SC2004'
call ale#Set('sh_shellcheck_exclusions', get(g:, 'ale_linters_sh_shellcheck_exclusions', ''))
call ale#Set('sh_shellcheck_executable', 'shellcheck')
call ale#Set('sh_shellcheck_dialect', 'auto')
call ale#Set('sh_shellcheck_options', '')
call ale#Set('sh_shellcheck_change_directory', 1)
function! ale_linters#sh#shellcheck#GetDialectArgument(buffer) abort
let l:shell_type = ale#handlers#sh#GetShellType(a:buffer)
if !empty(l:shell_type)
" Use the dash dialect for /bin/ash, etc.
if l:shell_type is# 'ash'
return 'dash'
endif
return l:shell_type
endif
" If there's no hashbang, try using Vim's buffer variables.
if getbufvar(a:buffer, 'is_bash', 0)
return 'bash'
elseif getbufvar(a:buffer, 'is_sh', 0)
return 'sh'
elseif getbufvar(a:buffer, 'is_kornshell', 0)
return 'ksh'
endif
return ''
endfunction
function! ale_linters#sh#shellcheck#GetCommand(buffer, version) abort
let l:options = ale#Var(a:buffer, 'sh_shellcheck_options')
let l:exclude_option = ale#Var(a:buffer, 'sh_shellcheck_exclusions')
let l:dialect = ale#Var(a:buffer, 'sh_shellcheck_dialect')
let l:external_option = ale#semver#GTE(a:version, [0, 4, 0]) ? ' -x' : ''
let l:cd_string = ale#Var(a:buffer, 'sh_shellcheck_change_directory')
\ ? ale#path#BufferCdString(a:buffer)
\ : ''
if l:dialect is# 'auto'
let l:dialect = ale_linters#sh#shellcheck#GetDialectArgument(a:buffer)
endif
return l:cd_string
\ . '%e'
\ . (!empty(l:dialect) ? ' -s ' . l:dialect : '')
\ . (!empty(l:options) ? ' ' . l:options : '')
\ . (!empty(l:exclude_option) ? ' -e ' . l:exclude_option : '')
\ . l:external_option
\ . ' -f gcc -'
endfunction
function! ale_linters#sh#shellcheck#Handle(buffer, lines) abort
let l:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+):(\d+)?:? ([^:]+): (.+) \[([^\]]+)\]$'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
if l:match[4] is# 'error'
let l:type = 'E'
elseif l:match[4] is# 'note'
let l:type = 'I'
else
let l:type = 'W'
endif
let l:item = {
\ 'lnum': str2nr(l:match[2]),
\ 'type': l:type,
\ 'text': l:match[5],
\ 'code': l:match[6],
\}
if !empty(l:match[3])
let l:item.col = str2nr(l:match[3])
endif
" If the filename is something like <stdin>, <nofile> or -, then
" this is an error for the file we checked.
if l:match[1] isnot# '-' && l:match[1][0] isnot# '<'
let l:item['filename'] = l:match[1]
endif
call add(l:output, l:item)
endfor
return l:output
endfunction
call ale#linter#Define('sh', {
\ 'name': 'shellcheck',
\ 'executable': {buffer -> ale#Var(buffer, 'sh_shellcheck_executable')},
\ 'command': {buffer -> ale#semver#RunWithVersionCheck(
\ buffer,
\ ale#Var(buffer, 'sh_shellcheck_executable'),
\ '%e --version',
\ function('ale_linters#sh#shellcheck#GetCommand'),
\ )},
\ 'callback': 'ale_linters#sh#shellcheck#Handle',
\})

View file

@ -0,0 +1,25 @@
" Author: OJFord <dev@ojford.com>
" Description: terraform-lsp integration for ALE (cf. https://github.com/juliosueiras/terraform-lsp)
call ale#Set('terraform_langserver_executable', 'terraform-lsp')
call ale#Set('terraform_langserver_options', '')
function! ale_linters#terraform#terraform_lsp#GetCommand(buffer) abort
return '%e'
\ . ale#Pad(ale#Var(a:buffer, 'terraform_langserver_options'))
endfunction
function! ale_linters#terraform#terraform_lsp#GetProjectRoot(buffer) abort
let l:tf_dir = ale#path#FindNearestDirectory(a:buffer, '.terraform')
return !empty(l:tf_dir) ? fnamemodify(l:tf_dir, ':h:h') : ''
endfunction
call ale#linter#Define('terraform', {
\ 'name': 'terraform_lsp',
\ 'lsp': 'stdio',
\ 'executable': {b -> ale#Var(b, 'terraform_langserver_executable')},
\ 'command': function('ale_linters#terraform#terraform_lsp#GetCommand'),
\ 'project_root': function('ale_linters#terraform#terraform_lsp#GetProjectRoot'),
\ 'language': 'terraform',
\})

View file

@ -0,0 +1,31 @@
" Author: Ahmed El Gabri <@ahmedelgabri>
" Description: standardjs for typescript files
call ale#Set('typescript_standard_executable', 'standard')
call ale#Set('typescript_standard_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('typescript_standard_options', '')
function! ale_linters#typescript#standard#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'typescript_standard', [
\ 'node_modules/standardx/bin/cmd.js',
\ 'node_modules/standard/bin/cmd.js',
\ 'node_modules/.bin/standard',
\])
endfunction
function! ale_linters#typescript#standard#GetCommand(buffer) abort
let l:executable = ale_linters#typescript#standard#GetExecutable(a:buffer)
let l:options = ale#Var(a:buffer, 'typescript_standard_options')
return ale#node#Executable(a:buffer, l:executable)
\ . (!empty(l:options) ? ' ' . l:options : '')
\ . ' --stdin %s'
endfunction
" standard uses eslint and the output format is the same
call ale#linter#Define('typescript', {
\ 'name': 'standard',
\ 'executable': function('ale_linters#typescript#standard#GetExecutable'),
\ 'command': function('ale_linters#typescript#standard#GetCommand'),
\ 'callback': 'ale#handlers#eslint#Handle',
\})

View file

@ -28,21 +28,30 @@ function! ale_linters#verilog#verilator#Handle(buffer, lines) abort
" %Warning-UNDRIVEN: test.v:3: Signal is not driven: clk " %Warning-UNDRIVEN: test.v:3: Signal is not driven: clk
" %Warning-UNUSED: test.v:4: Signal is not used: dout " %Warning-UNUSED: test.v:4: Signal is not used: dout
" %Warning-BLKSEQ: test.v:10: Blocking assignments (=) in sequential (flop or latch) block; suggest delayed assignments (<=). " %Warning-BLKSEQ: test.v:10: Blocking assignments (=) in sequential (flop or latch) block; suggest delayed assignments (<=).
let l:pattern = '^%\(Warning\|Error\)[^:]*:\([^:]\+\):\(\d\+\): \(.\+\)$' " Since version 4.032 (04/2020) verilator linter messages also contain the column number,
" and look like:
" %Error: /tmp/test.sv:3:1: syntax error, unexpected endmodule, expecting ';'
"
" to stay compatible with old versions of the tool, the column number is
" optional in the researched pattern
let l:pattern = '^%\(Warning\|Error\)[^:]*:\([^:]\+\):\(\d\+\):\(\d\+\)\?:\? \(.\+\)$'
let l:output = [] let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:match in ale#util#GetMatches(a:lines, l:pattern)
let l:line = l:match[3] + 0 let l:item = {
let l:type = l:match[1] is# 'Error' ? 'E' : 'W' \ 'lnum': str2nr(l:match[3]),
let l:text = l:match[4] \ 'text': l:match[5],
\ 'type': l:match[1] is# 'Error' ? 'E' : 'W',
\}
if !empty(l:match[4])
let l:item.col = str2nr(l:match[4])
endif
let l:file = l:match[2] let l:file = l:match[2]
if l:file =~# '_verilator_linted.v' if l:file =~# '_verilator_linted.v'
call add(l:output, { call add(l:output, l:item)
\ 'lnum': l:line,
\ 'text': l:text,
\ 'type': l:type,
\})
endif endif
endfor endfor

61
ale_linters/vim/vimls.vim Normal file
View file

@ -0,0 +1,61 @@
" Author: Jeffrey Lau - https://github.com/zoonfafer
" Description: Vim Language Server integration for ALE
call ale#Set('vim_vimls_executable', 'vim-language-server')
call ale#Set('vim_vimls_use_global', get(g:, 'ale_use_global_executables', 0))
call ale#Set('vim_vimls_config', {})
function! ale_linters#vim#vimls#GetProjectRoot(buffer) abort
let l:trigger_file_candidates = [
\ '.vimrc',
\ 'init.vim',
\]
for l:candidate in l:trigger_file_candidates
let l:trigger_file = fnamemodify(bufname(a:buffer), ':t')
if l:trigger_file is# l:candidate
return fnamemodify(
\ bufname(a:buffer),
\ ':h',
\)
endif
endfor
let l:trigger_dir_candidates = [
\ 'autoload',
\ 'plugin',
\ '.git',
\]
let l:path_upwards = ale#path#Upwards(fnamemodify(bufname(a:buffer), ':p:h'))
for l:path in l:path_upwards
for l:candidate in l:trigger_dir_candidates
let l:trigger_dir = ale#path#Simplify(
\ l:path . '/' . l:candidate,
\)
if isdirectory(l:trigger_dir)
return fnamemodify(
\ l:trigger_dir,
\ ':p:h:h',
\)
endif
endfor
endfor
return ''
endfunction
call ale#linter#Define('vim', {
\ 'name': 'vimls',
\ 'lsp': 'stdio',
\ 'lsp_config': {b -> ale#Var(b, 'vim_vimls_config')},
\ 'executable': {b -> ale#node#FindExecutable(b, 'vim_vimls', [
\ 'node_modules/.bin/vim-language-server',
\ ])},
\ 'command': '%e --stdio',
\ 'language': 'vim',
\ 'project_root': function('ale_linters#vim#vimls#GetProjectRoot'),
\})

View file

@ -258,9 +258,9 @@ function! ale#GetLocItemMessage(item, format_string) abort
" Replace special markers with certain information. " Replace special markers with certain information.
" \=l:variable is used to avoid escaping issues. " \=l:variable is used to avoid escaping issues.
let l:msg = substitute(l:msg, '\v\%([^\%]*)code([^\%]*)\%', l:code_repl, 'g')
let l:msg = substitute(l:msg, '\V%severity%', '\=l:severity', 'g') let l:msg = substitute(l:msg, '\V%severity%', '\=l:severity', 'g')
let l:msg = substitute(l:msg, '\V%linter%', '\=l:linter_name', 'g') let l:msg = substitute(l:msg, '\V%linter%', '\=l:linter_name', 'g')
let l:msg = substitute(l:msg, '\v\%([^\%]*)code([^\%]*)\%', l:code_repl, 'g')
" Replace %s with the text. " Replace %s with the text.
let l:msg = substitute(l:msg, '\V%s', '\=a:item.text', 'g') let l:msg = substitute(l:msg, '\V%s', '\=a:item.text', 'g')

View file

@ -1,4 +1,4 @@
" Author: Andrew Lee <andrewl@mbda.fun>. " Author: Andrew Lee <andrew.lambda@tuta.io>.
" Inspired by ale/gradle.vim by Michael Pardo <michael@michaelpardo.com> " Inspired by ale/gradle.vim by Michael Pardo <michael@michaelpardo.com>
" Description: Functions for working with Ant projects. " Description: Functions for working with Ant projects.

View file

@ -1,7 +1,7 @@
" Author: Jerko Steiner <jerko.steiner@gmail.com> " Author: Jerko Steiner <jerko.steiner@gmail.com>
" Description: Code action support for LSP / tsserver " Description: Code action support for LSP / tsserver
function! ale#code_action#HandleCodeAction(code_action) abort function! ale#code_action#HandleCodeAction(code_action, should_save) abort
let l:current_buffer = bufnr('') let l:current_buffer = bufnr('')
let l:changes = a:code_action.changes let l:changes = a:code_action.changes
@ -17,11 +17,14 @@ function! ale#code_action#HandleCodeAction(code_action) abort
for l:file_code_edit in l:changes for l:file_code_edit in l:changes
call ale#code_action#ApplyChanges( call ale#code_action#ApplyChanges(
\ l:file_code_edit.fileName, l:file_code_edit.textChanges) \ l:file_code_edit.fileName,
\ l:file_code_edit.textChanges,
\ a:should_save,
\ )
endfor endfor
endfunction endfunction
function! ale#code_action#ApplyChanges(filename, changes) abort function! ale#code_action#ApplyChanges(filename, changes, should_save) abort
let l:current_buffer = bufnr('') let l:current_buffer = bufnr('')
" The buffer is used to determine the fileformat, if available. " The buffer is used to determine the fileformat, if available.
let l:buffer = bufnr(a:filename) let l:buffer = bufnr(a:filename)
@ -106,10 +109,17 @@ function! ale#code_action#ApplyChanges(filename, changes) abort
call remove(l:lines, -1) call remove(l:lines, -1)
endif endif
if a:should_save
call ale#util#Writefile(l:buffer, l:lines, a:filename) call ale#util#Writefile(l:buffer, l:lines, a:filename)
else
call ale#util#SetBufferContents(l:buffer, l:lines)
endif
if l:is_current_buffer if l:is_current_buffer
if a:should_save
call ale#util#Execute(':e!') call ale#util#Execute(':e!')
endif
call setpos('.', [0, l:pos[0], l:pos[1], 0]) call setpos('.', [0, l:pos[0], l:pos[1], 0])
endif endif
endfunction endfunction

View file

@ -1,5 +1,6 @@
" Author: w0rp <devw0rp@gmail.com> " Author: w0rp <devw0rp@gmail.com>
" Description: Completion support for LSP linters " Description: Completion support for LSP linters
scriptencoding utf-8
" The omnicompletion menu is shown through a special Plug mapping which is " The omnicompletion menu is shown through a special Plug mapping which is
" only valid in Insert mode. This way, feedkeys() won't send these keys if you " only valid in Insert mode. This way, feedkeys() won't send these keys if you
@ -21,24 +22,101 @@ let s:timer_id = -1
let s:last_done_pos = [] let s:last_done_pos = []
" CompletionItemKind values from the LSP protocol. " CompletionItemKind values from the LSP protocol.
let s:LSP_COMPLETION_TEXT_KIND = 1 let g:ale_lsp_types = {
let s:LSP_COMPLETION_METHOD_KIND = 2 \ 1: 'text',
let s:LSP_COMPLETION_FUNCTION_KIND = 3 \ 2: 'method',
let s:LSP_COMPLETION_CONSTRUCTOR_KIND = 4 \ 3: 'function',
let s:LSP_COMPLETION_FIELD_KIND = 5 \ 4: 'constructor',
let s:LSP_COMPLETION_VARIABLE_KIND = 6 \ 5: 'field',
let s:LSP_COMPLETION_CLASS_KIND = 7 \ 6: 'variable',
let s:LSP_COMPLETION_INTERFACE_KIND = 8 \ 7: 'class',
let s:LSP_COMPLETION_MODULE_KIND = 9 \ 8: 'interface',
let s:LSP_COMPLETION_PROPERTY_KIND = 10 \ 9: 'module',
let s:LSP_COMPLETION_UNIT_KIND = 11 \ 10: 'property',
let s:LSP_COMPLETION_VALUE_KIND = 12 \ 11: 'unit',
let s:LSP_COMPLETION_ENUM_KIND = 13 \ 12: 'value',
let s:LSP_COMPLETION_KEYWORD_KIND = 14 \ 13: 'enum',
let s:LSP_COMPLETION_SNIPPET_KIND = 15 \ 14: 'keyword',
let s:LSP_COMPLETION_COLOR_KIND = 16 \ 15: 'snippet',
let s:LSP_COMPLETION_FILE_KIND = 17 \ 16: 'color',
let s:LSP_COMPLETION_REFERENCE_KIND = 18 \ 17: 'file',
\ 18: 'reference',
\ 19: 'folder',
\ 20: 'enum_member',
\ 21: 'constant',
\ 22: 'struct',
\ 23: 'event',
\ 24: 'operator',
\ 25: 'type_parameter',
\ }
" from https://github.com/microsoft/TypeScript/blob/29becf05012bfa7ba20d50b0d16813971e46b8a6/lib/protocol.d.ts#L2472
let g:ale_tsserver_types = {
\ 'warning': 'text',
\ 'keyword': 'keyword',
\ 'script': 'file',
\ 'module': 'module',
\ 'class': 'class',
\ 'local class': 'class',
\ 'interface': 'interface',
\ 'type': 'class',
\ 'enum': 'enum',
\ 'enum member': 'enum_member',
\ 'var': 'variable',
\ 'local var': 'variable',
\ 'function': 'function',
\ 'local function': 'function',
\ 'method': 'method',
\ 'getter': 'property',
\ 'setter': 'method',
\ 'property': 'property',
\ 'constructor': 'constructor',
\ 'call': 'method',
\ 'index': 'index',
\ 'construct': 'constructor',
\ 'parameter': 'parameter',
\ 'type parameter': 'type_parameter',
\ 'primitive type': 'unit',
\ 'label': 'text',
\ 'alias': 'class',
\ 'const': 'constant',
\ 'let': 'variable',
\ 'directory': 'folder',
\ 'external module name': 'text',
\ 'JSX attribute': 'parameter',
\ 'string': 'text'
\ }
" For compatibility reasons, we only use built in VIM completion kinds
" See :help complete-items for Vim completion kinds
let g:ale_completion_symbols = get(g:, 'ale_completion_symbols', {
\ 'text': 'v',
\ 'method': 'f',
\ 'function': 'f',
\ 'constructor': 'f',
\ 'field': 'm',
\ 'variable': 'v',
\ 'class': 't',
\ 'interface': 't',
\ 'module': 'd',
\ 'property': 'm',
\ 'unit': 'v',
\ 'value': 'v',
\ 'enum': 't',
\ 'keyword': 'v',
\ 'snippet': 'v',
\ 'color': 'v',
\ 'file': 'v',
\ 'reference': 'v',
\ 'folder': 'v',
\ 'enum_member': 'm',
\ 'constant': 'm',
\ 'struct': 't',
\ 'event': 'v',
\ 'operator': 'f',
\ 'type_parameter': 'p',
\ '<default>': 'v'
\ })
let s:LSP_INSERT_TEXT_FORMAT_PLAIN = 1 let s:LSP_INSERT_TEXT_FORMAT_PLAIN = 1
let s:LSP_INSERT_TEXT_FORMAT_SNIPPET = 2 let s:LSP_INSERT_TEXT_FORMAT_SNIPPET = 2
@ -183,6 +261,8 @@ function! s:ReplaceCompletionOptions() abort
if &l:completeopt =~# 'preview' if &l:completeopt =~# 'preview'
let &l:completeopt = 'menu,menuone,preview,noselect,noinsert' let &l:completeopt = 'menu,menuone,preview,noselect,noinsert'
elseif &l:completeopt =~# 'popup'
let &l:completeopt = 'menu,menuone,popup,noselect,noinsert'
else else
let &l:completeopt = 'menu,menuone,noselect,noinsert' let &l:completeopt = 'menu,menuone,noselect,noinsert'
endif endif
@ -278,6 +358,27 @@ function! ale#completion#GetAllTriggers() abort
return deepcopy(s:trigger_character_map) return deepcopy(s:trigger_character_map)
endfunction endfunction
function! ale#completion#GetCompletionKind(kind) abort
let l:lsp_symbol = get(g:ale_lsp_types, a:kind, '')
if !empty(l:lsp_symbol)
return l:lsp_symbol
endif
return get(g:ale_tsserver_types, a:kind, '')
endfunction
function! ale#completion#GetCompletionSymbols(kind) abort
let l:kind = ale#completion#GetCompletionKind(a:kind)
let l:symbol = get(g:ale_completion_symbols, l:kind, '')
if !empty(l:symbol)
return l:symbol
endif
return get(g:ale_completion_symbols, '<default>', 'v')
endfunction
function! s:CompletionStillValid(request_id) abort function! s:CompletionStillValid(request_id) abort
let [l:line, l:column] = getpos('.')[1:2] let [l:line, l:column] = getpos('.')[1:2]
@ -287,7 +388,6 @@ function! s:CompletionStillValid(request_id) abort
\&& b:ale_completion_info.line == l:line \&& b:ale_completion_info.line == l:line
\&& ( \&& (
\ b:ale_completion_info.column == l:column \ b:ale_completion_info.column == l:column
\ || b:ale_completion_info.source is# 'deoplete'
\ || b:ale_completion_info.source is# 'ale-omnifunc' \ || b:ale_completion_info.source is# 'ale-omnifunc'
\ || b:ale_completion_info.source is# 'ale-callback' \ || b:ale_completion_info.source is# 'ale-callback'
\) \)
@ -329,18 +429,10 @@ function! ale#completion#ParseTSServerCompletionEntryDetails(response) abort
call add(l:documentationParts, l:part.text) call add(l:documentationParts, l:part.text)
endfor endfor
if l:suggestion.kind is# 'className'
let l:kind = 'f'
elseif l:suggestion.kind is# 'parameterName'
let l:kind = 'f'
else
let l:kind = 'v'
endif
" See :help complete-items " See :help complete-items
let l:result = { let l:result = {
\ 'word': l:suggestion.name, \ 'word': l:suggestion.name,
\ 'kind': l:kind, \ 'kind': ale#completion#GetCompletionSymbols(l:suggestion.kind),
\ 'icase': 1, \ 'icase': 1,
\ 'menu': join(l:displayParts, ''), \ 'menu': join(l:displayParts, ''),
\ 'dup': g:ale_completion_tsserver_autoimport, \ 'dup': g:ale_completion_tsserver_autoimport,
@ -425,23 +517,6 @@ function! ale#completion#ParseLSPCompletions(response) abort
continue continue
endif endif
" See :help complete-items for Vim completion kinds
if !has_key(l:item, 'kind')
let l:kind = 'v'
elseif l:item.kind is s:LSP_COMPLETION_METHOD_KIND
let l:kind = 'm'
elseif l:item.kind is s:LSP_COMPLETION_CONSTRUCTOR_KIND
let l:kind = 'm'
elseif l:item.kind is s:LSP_COMPLETION_FUNCTION_KIND
let l:kind = 'f'
elseif l:item.kind is s:LSP_COMPLETION_CLASS_KIND
let l:kind = 'f'
elseif l:item.kind is s:LSP_COMPLETION_INTERFACE_KIND
let l:kind = 'f'
else
let l:kind = 'v'
endif
let l:doc = get(l:item, 'documentation', '') let l:doc = get(l:item, 'documentation', '')
if type(l:doc) is v:t_dict && has_key(l:doc, 'value') if type(l:doc) is v:t_dict && has_key(l:doc, 'value')
@ -450,7 +525,7 @@ function! ale#completion#ParseLSPCompletions(response) abort
call add(l:results, { call add(l:results, {
\ 'word': l:word, \ 'word': l:word,
\ 'kind': l:kind, \ 'kind': ale#completion#GetCompletionSymbols(get(l:item, 'kind', '')),
\ 'icase': 1, \ 'icase': 1,
\ 'menu': get(l:item, 'detail', ''), \ 'menu': get(l:item, 'detail', ''),
\ 'info': (type(l:doc) is v:t_string ? l:doc : ''), \ 'info': (type(l:doc) is v:t_string ? l:doc : ''),
@ -729,7 +804,9 @@ endfunction
function! ale#completion#HandleUserData(completed_item) abort function! ale#completion#HandleUserData(completed_item) abort
let l:source = get(get(b:, 'ale_completion_info', {}), 'source', '') let l:source = get(get(b:, 'ale_completion_info', {}), 'source', '')
if l:source isnot# 'ale-automatic' && l:source isnot# 'ale-manual' && l:source isnot# 'ale-callback' if l:source isnot# 'ale-automatic'
\&& l:source isnot# 'ale-manual'
\&& l:source isnot# 'ale-callback'
return return
endif endif
@ -746,7 +823,7 @@ function! ale#completion#HandleUserData(completed_item) abort
endif endif
for l:code_action in get(l:user_data, 'codeActions', []) for l:code_action in get(l:user_data, 'codeActions', [])
call ale#code_action#HandleCodeAction(l:code_action) call ale#code_action#HandleCodeAction(l:code_action, v:false)
endfor endfor
endfunction endfunction

View file

@ -5,6 +5,7 @@ let s:go_to_definition_map = {}
" Enable automatic updates of the tagstack " Enable automatic updates of the tagstack
let g:ale_update_tagstack = get(g:, 'ale_update_tagstack', 1) let g:ale_update_tagstack = get(g:, 'ale_update_tagstack', 1)
let g:ale_default_navigation = get(g:, 'ale_default_navigation', 'buffer')
" Used to get the definition map in tests. " Used to get the definition map in tests.
function! ale#definition#GetMap() abort function! ale#definition#GetMap() abort
@ -134,6 +135,10 @@ function! s:GoToLSPDefinition(linter, options, capability) abort
endfunction endfunction
function! ale#definition#GoTo(options) abort function! ale#definition#GoTo(options) abort
if !get(g:, 'ale_ignore_2_7_warnings') && has_key(a:options, 'deprecated_command')
execute 'echom '':' . a:options.deprecated_command . ' is deprecated. Use `let g:ale_ignore_2_7_warnings = 1` to disable this message.'''
endif
for l:linter in ale#linter#Get(&filetype) for l:linter in ale#linter#Get(&filetype)
if !empty(l:linter.lsp) if !empty(l:linter.lsp)
call s:GoToLSPDefinition(l:linter, a:options, 'definition') call s:GoToLSPDefinition(l:linter, a:options, 'definition')
@ -142,6 +147,10 @@ function! ale#definition#GoTo(options) abort
endfunction endfunction
function! ale#definition#GoToType(options) abort function! ale#definition#GoToType(options) abort
if !get(g:, 'ale_ignore_2_7_warnings') && has_key(a:options, 'deprecated_command')
execute 'echom '':' . a:options.deprecated_command . ' is deprecated. Use `let g:ale_ignore_2_7_warnings = 1` to disable this message.'''
endif
for l:linter in ale#linter#Get(&filetype) for l:linter in ale#linter#Get(&filetype)
if !empty(l:linter.lsp) if !empty(l:linter.lsp)
" TODO: handle typeDefinition for tsserver if supported by the " TODO: handle typeDefinition for tsserver if supported by the
@ -154,3 +163,33 @@ function! ale#definition#GoToType(options) abort
endif endif
endfor endfor
endfunction endfunction
function! ale#definition#GoToCommandHandler(command, ...) abort
let l:options = {}
if len(a:000) > 0
for l:option in a:000
if l:option is? '-tab'
let l:options.open_in = 'tab'
elseif l:option is? '-split'
let l:options.open_in = 'split'
elseif l:option is? '-vsplit'
let l:options.open_in = 'vsplit'
endif
endfor
endif
if !has_key(l:options, 'open_in')
let l:default_navigation = ale#Var(bufnr(''), 'default_navigation')
if index(['tab', 'split', 'vsplit'], l:default_navigation) >= 0
let l:options.open_in = l:default_navigation
endif
endif
if a:command is# 'type'
call ale#definition#GoToType(l:options)
else
call ale#definition#GoTo(l:options)
endif
endfunction

View file

@ -4,40 +4,15 @@ call ale#Set('fix_on_save_ignore', {})
" Vim doesn't let you modify hidden buffers. " Vim doesn't let you modify hidden buffers.
function! ale#fix#ApplyQueuedFixes(buffer) abort function! ale#fix#ApplyQueuedFixes(buffer) abort
let l:data = get(g:ale_fix_buffer_data, a:buffer, {'done': 0}) let l:data = get(g:ale_fix_buffer_data, a:buffer, {'done': 0})
let l:has_bufline_api = exists('*deletebufline') && exists('*setbufline')
if !l:data.done || (!l:has_bufline_api && a:buffer isnot bufnr('')) if !l:data.done || (!ale#util#HasBuflineApi() && a:buffer isnot bufnr(''))
return return
endif endif
call remove(g:ale_fix_buffer_data, a:buffer) call remove(g:ale_fix_buffer_data, a:buffer)
if l:data.changes_made if l:data.changes_made
" If the file is in DOS mode, we have to remove carriage returns from let l:new_lines = ale#util#SetBufferContents(a:buffer, l:data.output)
" the ends of lines before calling setline(), or we will see them
" twice.
let l:new_lines = getbufvar(a:buffer, '&fileformat') is# 'dos'
\ ? map(copy(l:data.output), 'substitute(v:val, ''\r\+$'', '''', '''')')
\ : l:data.output
let l:first_line_to_remove = len(l:new_lines) + 1
" Use a Vim API for setting lines in other buffers, if available.
if l:has_bufline_api
call setbufline(a:buffer, 1, l:new_lines)
call deletebufline(a:buffer, l:first_line_to_remove, '$')
" Fall back on setting lines the old way, for the current buffer.
else
let l:old_line_length = len(l:data.lines_before)
if l:old_line_length >= l:first_line_to_remove
let l:save = winsaveview()
silent execute
\ l:first_line_to_remove . ',' . l:old_line_length . 'd_'
call winrestview(l:save)
endif
call setline(1, l:new_lines)
endif
if l:data.should_save if l:data.should_save
if a:buffer is bufnr('') if a:buffer is bufnr('')

View file

@ -54,6 +54,11 @@ let s:default_registry = {
\ 'description': 'Apply elm-format to a file.', \ 'description': 'Apply elm-format to a file.',
\ 'aliases': ['format'], \ 'aliases': ['format'],
\ }, \ },
\ 'nimpretty': {
\ 'function': 'ale#fixers#nimpretty#Fix',
\ 'suggested_filetypes': ['nim'],
\ 'description': 'Apply nimpretty to a file.',
\ },
\ 'eslint': { \ 'eslint': {
\ 'function': 'ale#fixers#eslint#Fix', \ 'function': 'ale#fixers#eslint#Fix',
\ 'suggested_filetypes': ['javascript', 'typescript'], \ 'suggested_filetypes': ['javascript', 'typescript'],

View file

@ -0,0 +1,15 @@
" Author: Nhan <hi@imnhan.com>
" Description: Integration of nimpretty with ALE.
call ale#Set('nim_nimpretty_executable', 'nimpretty')
call ale#Set('nim_nimpretty_options', '--maxLineLen:80')
function! ale#fixers#nimpretty#Fix(buffer) abort
let l:executable = ale#Var(a:buffer, 'nim_nimpretty_executable')
let l:options = ale#Var(a:buffer, 'nim_nimpretty_options')
return {
\ 'command': ale#Escape(l:executable) . ' %t' . ale#Pad(l:options),
\ 'read_temporary_file': 1,
\}
endfunction

View file

@ -7,6 +7,7 @@ call ale#Set('javascript_standard_options', '')
function! ale#fixers#standard#GetExecutable(buffer) abort function! ale#fixers#standard#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'javascript_standard', [ return ale#node#FindExecutable(a:buffer, 'javascript_standard', [
\ 'node_modules/standardx/bin/cmd.js',
\ 'node_modules/standard/bin/cmd.js', \ 'node_modules/standard/bin/cmd.js',
\ 'node_modules/.bin/standard', \ 'node_modules/.bin/standard',
\]) \])
@ -14,7 +15,14 @@ endfunction
function! ale#fixers#standard#Fix(buffer) abort function! ale#fixers#standard#Fix(buffer) abort
let l:executable = ale#fixers#standard#GetExecutable(a:buffer) let l:executable = ale#fixers#standard#GetExecutable(a:buffer)
let l:options = ale#Var(a:buffer, 'javascript_standard_options') let l:filetype = getbufvar(a:buffer, '&filetype')
let l:options_type = 'javascript_standard_options'
if l:filetype =~# 'typescript'
let l:options_type = 'typescript_standard_options'
endif
let l:options = ale#Var(a:buffer, l:options_type)
return { return {
\ 'command': ale#node#Executable(a:buffer, l:executable) \ 'command': ale#node#Executable(a:buffer, l:executable)

View file

@ -42,7 +42,18 @@ function! ale#handlers#eslint#GetCommand(buffer) abort
let l:options = ale#Var(a:buffer, 'javascript_eslint_options') let l:options = ale#Var(a:buffer, 'javascript_eslint_options')
return ale#node#Executable(a:buffer, l:executable) " ESLint 6 loads plugins/configs/parsers from the project root
" By default, the project root is simply the CWD of the running process.
" https://github.com/eslint/rfcs/blob/master/designs/2018-simplified-package-loading/README.md
" https://github.com/dense-analysis/ale/issues/2787
" Identify project root from presence of node_modules dir.
" Note: If node_modules not present yet, can't load local deps anyway.
let l:modules_dir = ale#path#FindNearestDirectory(a:buffer, 'node_modules')
let l:project_dir = !empty(l:modules_dir) ? fnamemodify(l:modules_dir, ':h:h') : ''
let l:cd_command = !empty(l:project_dir) ? ale#path#CdString(l:project_dir) : ''
return l:cd_command
\ . ale#node#Executable(a:buffer, l:executable)
\ . (!empty(l:options) ? ' ' . l:options : '') \ . (!empty(l:options) ? ' ' . l:options : '')
\ . ' -f json --stdin --stdin-filename %s' \ . ' -f json --stdin --stdin-filename %s'
endfunction endfunction
@ -84,11 +95,14 @@ function! s:CheckForBadConfig(buffer, lines) abort
endfunction endfunction
function! s:parseJSON(buffer, lines) abort function! s:parseJSON(buffer, lines) abort
let l:parsed = []
for l:line in a:lines
try try
let l:parsed = json_decode(a:lines[-1]) let l:parsed = extend(l:parsed, json_decode(l:line))
catch catch
return []
endtry endtry
endfor
if type(l:parsed) != v:t_list || empty(l:parsed) if type(l:parsed) != v:t_list || empty(l:parsed)
return [] return []

View file

@ -0,0 +1,107 @@
" Author: w0rp <devw0rp@gmail.com>
" Description: This file adds support for using the shellcheck linter
function! ale#handlers#shellcheck#GetDialectArgument(buffer) abort
let l:shell_type = ale#handlers#sh#GetShellType(a:buffer)
if !empty(l:shell_type)
" Use the dash dialect for /bin/ash, etc.
if l:shell_type is# 'ash'
return 'dash'
endif
return l:shell_type
endif
" If there's no hashbang, try using Vim's buffer variables.
if getbufvar(a:buffer, 'is_bash', 0)
return 'bash'
elseif getbufvar(a:buffer, 'is_sh', 0)
return 'sh'
elseif getbufvar(a:buffer, 'is_kornshell', 0)
return 'ksh'
endif
return ''
endfunction
function! ale#handlers#shellcheck#GetCommand(buffer, version) abort
let l:options = ale#Var(a:buffer, 'sh_shellcheck_options')
let l:exclude_option = ale#Var(a:buffer, 'sh_shellcheck_exclusions')
let l:dialect = ale#Var(a:buffer, 'sh_shellcheck_dialect')
let l:external_option = ale#semver#GTE(a:version, [0, 4, 0]) ? ' -x' : ''
let l:cd_string = ale#Var(a:buffer, 'sh_shellcheck_change_directory')
\ ? ale#path#BufferCdString(a:buffer)
\ : ''
if l:dialect is# 'auto'
let l:dialect = ale#handlers#shellcheck#GetDialectArgument(a:buffer)
endif
return l:cd_string
\ . '%e'
\ . (!empty(l:dialect) ? ' -s ' . l:dialect : '')
\ . (!empty(l:options) ? ' ' . l:options : '')
\ . (!empty(l:exclude_option) ? ' -e ' . l:exclude_option : '')
\ . l:external_option
\ . ' -f gcc -'
endfunction
function! ale#handlers#shellcheck#Handle(buffer, lines) abort
let l:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+):(\d+)?:? ([^:]+): (.+) \[([^\]]+)\]$'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
if l:match[4] is# 'error'
let l:type = 'E'
elseif l:match[4] is# 'note'
let l:type = 'I'
else
let l:type = 'W'
endif
let l:item = {
\ 'lnum': str2nr(l:match[2]),
\ 'type': l:type,
\ 'text': l:match[5],
\ 'code': l:match[6],
\}
if !empty(l:match[3])
let l:item.col = str2nr(l:match[3])
endif
" If the filename is something like <stdin>, <nofile> or -, then
" this is an error for the file we checked.
if l:match[1] isnot# '-' && l:match[1][0] isnot# '<'
let l:item['filename'] = l:match[1]
endif
call add(l:output, l:item)
endfor
return l:output
endfunction
function! ale#handlers#shellcheck#DefineLinter(filetype) abort
" This global variable can be set with a string of comma-separated error
" codes to exclude from shellcheck. For example:
" let g:ale_sh_shellcheck_exclusions = 'SC2002,SC2004'
call ale#Set('sh_shellcheck_exclusions', get(g:, 'ale_linters_sh_shellcheck_exclusions', ''))
call ale#Set('sh_shellcheck_executable', 'shellcheck')
call ale#Set('sh_shellcheck_dialect', 'auto')
call ale#Set('sh_shellcheck_options', '')
call ale#Set('sh_shellcheck_change_directory', 1)
call ale#linter#Define(a:filetype, {
\ 'name': 'shellcheck',
\ 'executable': {buffer -> ale#Var(buffer, 'sh_shellcheck_executable')},
\ 'command': {buffer -> ale#semver#RunWithVersionCheck(
\ buffer,
\ ale#Var(buffer, 'sh_shellcheck_executable'),
\ '%e --version',
\ function('ale#handlers#shellcheck#GetCommand'),
\ )},
\ 'callback': 'ale#handlers#shellcheck#Handle',
\})
endfunction

View file

@ -210,6 +210,12 @@ function! ale#highlight#SetHighlights(buffer, loclist) abort
" Set the list in the buffer variable. " Set the list in the buffer variable.
call setbufvar(str2nr(a:buffer), 'ale_highlight_items', l:new_list) call setbufvar(str2nr(a:buffer), 'ale_highlight_items', l:new_list)
let l:exclude_list = ale#Var(a:buffer, 'exclude_highlights')
if !empty(l:exclude_list)
call filter(l:new_list, 'empty(ale#util#GetMatches(v:val.text, l:exclude_list))')
endif
" Update highlights for the current buffer, which may or may not " Update highlights for the current buffer, which may or may not
" be the buffer we just set highlights for. " be the buffer we just set highlights for.
call ale#highlight#UpdateHighlights() call ale#highlight#UpdateHighlights()

View file

@ -42,6 +42,11 @@ function! ale#hover#HandleTSServerResponse(conn_id, response) abort
\&& exists('*balloon_show') \&& exists('*balloon_show')
\&& ale#Var(l:options.buffer, 'set_balloons') \&& ale#Var(l:options.buffer, 'set_balloons')
call balloon_show(a:response.body.displayString) call balloon_show(a:response.body.displayString)
elseif g:ale_hover_to_preview
call ale#preview#Show(split(a:response.body.displayString, "\n"), {
\ 'filetype': 'ale-preview.message',
\ 'stay_here': 1,
\})
else else
call ale#util#ShowMessage(a:response.body.displayString) call ale#util#ShowMessage(a:response.body.displayString)
endif endif
@ -98,6 +103,11 @@ function! ale#hover#HandleLSPResponse(conn_id, response) abort
\&& exists('*balloon_show') \&& exists('*balloon_show')
\&& ale#Var(l:options.buffer, 'set_balloons') \&& ale#Var(l:options.buffer, 'set_balloons')
call balloon_show(l:str) call balloon_show(l:str)
elseif g:ale_hover_to_preview
call ale#preview#Show(split(l:str, "\n"), {
\ 'filetype': 'ale-preview.message',
\ 'stay_here': 1,
\})
else else
call ale#util#ShowMessage(l:str) call ale#util#ShowMessage(l:str)
endif endif

View file

@ -15,7 +15,7 @@ function! ale#organize_imports#HandleTSServerResponse(conn_id, response) abort
call ale#code_action#HandleCodeAction({ call ale#code_action#HandleCodeAction({
\ 'description': 'Organize Imports', \ 'description': 'Organize Imports',
\ 'changes': l:file_code_edits, \ 'changes': l:file_code_edits,
\}) \}, v:false)
endfunction endfunction
function! s:OnReady(linter, lsp_details) abort function! s:OnReady(linter, lsp_details) abort

View file

@ -1,6 +1,14 @@
" Author: w0rp <devw0rp@gmail.com> " Author: w0rp <devw0rp@gmail.com>
" Description: Preview windows for showing whatever information in. " Description: Preview windows for showing whatever information in.
if !has_key(s:, 'last_selection_list')
let s:last_selection_list = []
endif
if !has_key(s:, 'last_selection_open_in')
let s:last_selection_open_in = 'current-buffer'
endif
" Open a preview window and show some lines in it. " Open a preview window and show some lines in it.
" A second argument can be passed as a Dictionary with options. They are... " A second argument can be passed as a Dictionary with options. They are...
" "
@ -67,9 +75,24 @@ function! ale#preview#ShowSelection(item_list, ...) abort
call ale#preview#Show(l:lines, {'filetype': 'ale-preview-selection'}) call ale#preview#Show(l:lines, {'filetype': 'ale-preview-selection'})
let b:ale_preview_item_list = a:item_list let b:ale_preview_item_list = a:item_list
let b:ale_preview_item_open_in = get(l:options, 'open_in', 'current-buffer')
" Remove the last preview
let s:last_selection_list = b:ale_preview_item_list
let s:last_selection_open_in = b:ale_preview_item_open_in
endfunction endfunction
function! s:Open(open_in_tab) abort function! ale#preview#RepeatSelection() abort
if empty(s:last_selection_list)
return
endif
call ale#preview#ShowSelection(s:last_selection_list, {
\ 'open_in': s:last_selection_open_in,
\})
endfunction
function! s:Open(open_in) abort
let l:item_list = get(b:, 'ale_preview_item_list', []) let l:item_list = get(b:, 'ale_preview_item_list', [])
let l:item = get(l:item_list, getpos('.')[1] - 1, {}) let l:item = get(l:item_list, getpos('.')[1] - 1, {})
@ -77,22 +100,20 @@ function! s:Open(open_in_tab) abort
return return
endif endif
if !a:open_in_tab
:q! :q!
endif
call ale#util#Open( call ale#util#Open(
\ l:item.filename, \ l:item.filename,
\ l:item.line, \ l:item.line,
\ l:item.column, \ l:item.column,
\ {'open_in_tab': a:open_in_tab}, \ {'open_in': a:open_in},
\) \)
endfunction endfunction
function! ale#preview#OpenSelectionInBuffer() abort function! ale#preview#OpenSelection() abort
call s:Open(0) call s:Open(b:ale_preview_item_open_in)
endfunction endfunction
function! ale#preview#OpenSelectionInTab() abort function! ale#preview#OpenSelectionInTab() abort
call s:Open(1) call s:Open('tab')
endfunction endfunction

View file

@ -1,3 +1,5 @@
let g:ale_default_navigation = get(g:, 'ale_default_navigation', 'buffer')
let s:references_map = {} let s:references_map = {}
" Used to get the references map in tests. " Used to get the references map in tests.
@ -99,7 +101,8 @@ function! s:OnReady(line, column, options, linter, lsp_details) abort
let l:request_id = ale#lsp#Send(l:id, l:message) let l:request_id = ale#lsp#Send(l:id, l:message)
let s:references_map[l:request_id] = { let s:references_map[l:request_id] = {
\ 'use_relative_paths': has_key(a:options, 'use_relative_paths') ? a:options.use_relative_paths : 0 \ 'use_relative_paths': has_key(a:options, 'use_relative_paths') ? a:options.use_relative_paths : 0,
\ 'open_in': get(a:options, 'open_in', 'current-buffer'),
\} \}
endfunction endfunction
@ -110,10 +113,24 @@ function! ale#references#Find(...) abort
for l:option in a:000 for l:option in a:000
if l:option is? '-relative' if l:option is? '-relative'
let l:options.use_relative_paths = 1 let l:options.use_relative_paths = 1
elseif l:option is? '-tab'
let l:options.open_in = 'tab'
elseif l:option is? '-split'
let l:options.open_in = 'split'
elseif l:option is? '-vsplit'
let l:options.open_in = 'vsplit'
endif endif
endfor endfor
endif endif
if !has_key(l:options, 'open_in')
let l:default_navigation = ale#Var(bufnr(''), 'default_navigation')
if index(['tab', 'split', 'vsplit'], l:default_navigation) >= 0
let l:options.open_in = l:default_navigation
endif
endif
let l:buffer = bufnr('') let l:buffer = bufnr('')
let [l:line, l:column] = getpos('.')[1:2] let [l:line, l:column] = getpos('.')[1:2]
let l:column = min([l:column, len(getline(l:line))]) let l:column = min([l:column, len(getline(l:line))])

View file

@ -80,7 +80,7 @@ function! ale#rename#HandleTSServerResponse(conn_id, response) abort
call ale#code_action#HandleCodeAction({ call ale#code_action#HandleCodeAction({
\ 'description': 'rename', \ 'description': 'rename',
\ 'changes': l:changes, \ 'changes': l:changes,
\}) \}, v:true)
endfunction endfunction
function! ale#rename#HandleLSPResponse(conn_id, response) abort function! ale#rename#HandleLSPResponse(conn_id, response) abort
@ -134,7 +134,7 @@ function! ale#rename#HandleLSPResponse(conn_id, response) abort
call ale#code_action#HandleCodeAction({ call ale#code_action#HandleCodeAction({
\ 'description': 'rename', \ 'description': 'rename',
\ 'changes': l:changes, \ 'changes': l:changes,
\}) \}, v:true)
endif endif
endfunction endfunction

View file

@ -23,7 +23,7 @@ let g:ale_sign_offset = get(g:, 'ale_sign_offset', 1000000)
let g:ale_sign_column_always = get(g:, 'ale_sign_column_always', 0) let g:ale_sign_column_always = get(g:, 'ale_sign_column_always', 0)
let g:ale_sign_highlight_linenrs = get(g:, 'ale_sign_highlight_linenrs', 0) let g:ale_sign_highlight_linenrs = get(g:, 'ale_sign_highlight_linenrs', 0)
let s:supports_sign_groups = has('nvim-0.4.2') || (v:version >= 801 && has('patch614')) let s:supports_sign_groups = has('nvim-0.4.2') || has('patch-8.1.614')
if !hlexists('ALEErrorSign') if !hlexists('ALEErrorSign')
highlight link ALEErrorSign error highlight link ALEErrorSign error

View file

@ -91,17 +91,17 @@ endfunction
" options['open_in'] can be: " options['open_in'] can be:
" current-buffer (default) " current-buffer (default)
" tab " tab
" vertical-split " split
" horizontal-split " vsplit
function! ale#util#Open(filename, line, column, options) abort function! ale#util#Open(filename, line, column, options) abort
let l:open_in = get(a:options, 'open_in', 'current-buffer') let l:open_in = get(a:options, 'open_in', 'current-buffer')
let l:args_to_open = '+' . a:line . ' ' . fnameescape(a:filename) let l:args_to_open = '+' . a:line . ' ' . fnameescape(a:filename)
if l:open_in is# 'tab' if l:open_in is# 'tab'
call ale#util#Execute('tabedit ' . l:args_to_open) call ale#util#Execute('tabedit ' . l:args_to_open)
elseif l:open_in is# 'horizontal-split' elseif l:open_in is# 'split'
call ale#util#Execute('split ' . l:args_to_open) call ale#util#Execute('split ' . l:args_to_open)
elseif l:open_in is# 'vertical-split' elseif l:open_in is# 'vsplit'
call ale#util#Execute('vsplit ' . l:args_to_open) call ale#util#Execute('vsplit ' . l:args_to_open)
elseif bufnr(a:filename) isnot bufnr('') elseif bufnr(a:filename) isnot bufnr('')
" Open another file only if we need to. " Open another file only if we need to.
@ -336,15 +336,11 @@ function! ale#util#GetMatches(lines, patterns) abort
endfunction endfunction
function! s:LoadArgCount(function) abort function! s:LoadArgCount(function) abort
let l:Function = a:function try
let l:output = execute('function a:function')
redir => l:output catch /E123/
silent! function Function
redir END
if !exists('l:output')
return 0 return 0
endif endtry
let l:match = matchstr(split(l:output, "\n")[0], '\v\([^)]+\)')[1:-2] let l:match = matchstr(split(l:output, "\n")[0], '\v\([^)]+\)')[1:-2]
let l:arg_list = filter(split(l:match, ', '), 'v:val isnot# ''...''') let l:arg_list = filter(split(l:match, ', '), 'v:val isnot# ''...''')
@ -480,3 +476,44 @@ endfunction
function! ale#util#Input(message, value) abort function! ale#util#Input(message, value) abort
return input(a:message, a:value) return input(a:message, a:value)
endfunction endfunction
function! ale#util#HasBuflineApi() abort
return exists('*deletebufline') && exists('*setbufline')
endfunction
" Sets buffer contents to lines
function! ale#util#SetBufferContents(buffer, lines) abort
let l:has_bufline_api = ale#util#HasBuflineApi()
if !l:has_bufline_api && a:buffer isnot bufnr('')
return
endif
" If the file is in DOS mode, we have to remove carriage returns from
" the ends of lines before calling setline(), or we will see them
" twice.
let l:new_lines = getbufvar(a:buffer, '&fileformat') is# 'dos'
\ ? map(copy(a:lines), 'substitute(v:val, ''\r\+$'', '''', '''')')
\ : a:lines
let l:first_line_to_remove = len(l:new_lines) + 1
" Use a Vim API for setting lines in other buffers, if available.
if l:has_bufline_api
call setbufline(a:buffer, 1, l:new_lines)
call deletebufline(a:buffer, l:first_line_to_remove, '$')
" Fall back on setting lines the old way, for the current buffer.
else
let l:old_line_length = line('$')
if l:old_line_length >= l:first_line_to_remove
let l:save = winsaveview()
silent execute
\ l:first_line_to_remove . ',' . l:old_line_length . 'd_'
call winrestview(l:save)
endif
call setline(1, l:new_lines)
endif
return l:new_lines
endfunction

13
doc/ale-bats.txt Normal file
View file

@ -0,0 +1,13 @@
===============================================================================
ALE Bats Integration *ale-bats-options*
===============================================================================
shellcheck *ale-bats-shellcheck*
The `shellcheck` linter for Bats uses the sh options for `shellcheck`; see:
|ale-sh-shellcheck|.
===============================================================================
vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl:

View file

@ -219,6 +219,25 @@ g:ale_go_govet_options *g:ale_go_govet_options*
This variable can be set to pass additional options to the go vet linter. This variable can be set to pass additional options to the go vet linter.
===============================================================================
revive *ale-go-revive*
g:ale_go_revive_executable *g:ale_go_revive_executable*
*b:ale_go_revive_executable*
Type: |String|
Default: `'revive'`
This variable can be set to change the revive executable path.
g:ale_go_revive_options *g:ale_go_revive_options*
*b:ale_go_revive_options*
Type: |String|
Default: `''`
This variable can be set to pass additional options to the revive
=============================================================================== ===============================================================================
staticcheck *ale-go-staticcheck* staticcheck *ale-go-staticcheck*

View file

@ -46,7 +46,7 @@ javac *ale-java-javac*
g:ale_java_javac_classpath *g:ale_java_javac_classpath* g:ale_java_javac_classpath *g:ale_java_javac_classpath*
*b:ale_java_javac_classpath* *b:ale_java_javac_classpath*
Type: |String| Type: |String| or |List|
Default: `''` Default: `''`
This variable can be set to change the global classpath for Java. This variable can be set to change the global classpath for Java.
@ -67,6 +67,30 @@ g:ale_java_javac_options *g:ale_java_javac_options*
This variable can be set to pass additional options to javac. This variable can be set to pass additional options to javac.
g:ale_java_javac_sourcepath *g:ale_java_javac_sourcepath*
*b:ale_java_javac_sourcepath*
Type: |String| or |List|
Default: `''`
This variable can set multiple source code paths, the source code path is a
relative path (relative to the project root directory).
Example:
String type:
Note that the unix system separator is a colon(`:`) window system
is a semicolon(`;`).
>
let g:ale_java_javac_sourcepath = 'build/gen/source/xx/main:build/gen/source'
<
List type:
>
let g:ale_java_javac_sourcepath = [
\ 'build/generated/source/querydsl/main',
\ 'target/generated-sources/source/querydsl/main'
\ ]
<
=============================================================================== ===============================================================================
google-java-format *ale-java-google-java-format* google-java-format *ale-java-google-java-format*
@ -222,6 +246,17 @@ g:ale_java_eclipselsp_workspace_path *g:ale_java_eclipselsp_workspace_path*
absolute path of the Eclipse workspace. If not set this value will be set to absolute path of the Eclipse workspace. If not set this value will be set to
the parent folder of the project root. the parent folder of the project root.
g:ale_java_eclipselsp_javaagent *g:ale_java_eclipselsp_javaagent*
*b:ale_java_eclipselsp_javaagent*
Type: |String|
Default: `''`
A variable to add java agent for annotation processing such as Lombok.
If you have multiple java agent files, use space to separate them. For example:
>
let g:ale_java_eclipselsp_javaagent='/eclipse/lombok.jar /eclipse/jacoco.jar'
<
=============================================================================== ===============================================================================
uncrustify *ale-java-uncrustify* uncrustify *ale-java-uncrustify*

View file

@ -21,5 +21,25 @@ g:nim_nimlsp_nim_sources *g:nim_nimlsp_nim_sources*
command. command.
===============================================================================
nimpretty *ale-nim-nimpretty*
g:ale_nim_nimpretty_executable *g:ale_nim_nimpretty_executable*
*b:ale_nim_nimpretty_executable*
Type: |String|
Default: `'nimpretty'`
This variable can be changed to use a different executable for nimpretty.
g:ale_nim_nimpretty_options *g:ale_nim_nimpretty_options*
*b:ale_nim_nimpretty_options*
Type: |String|
Default: `'--maxLineLen:80'`
This variable can be changed to modify flags given to nimpretty.
=============================================================================== ===============================================================================
vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl: vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl:

View file

@ -263,6 +263,15 @@ to check for errors while you type.
`mypy` will be run from a detected project root, per |ale-python-root|. `mypy` will be run from a detected project root, per |ale-python-root|.
g:ale_python_mypy_auto_pipenv *g:ale_python_mypy_auto_pipenv*
*b:ale_python_mypy_auto_pipenv*
Type: |Number|
Default: `0`
Detect whether the file is inside a pipenv, and set the executable to `pipenv`
if true. This is overridden by a manually-set executable.
g:ale_python_mypy_executable *g:ale_python_mypy_executable* g:ale_python_mypy_executable *g:ale_python_mypy_executable*
*b:ale_python_mypy_executable* *b:ale_python_mypy_executable*
Type: |String| Type: |String|
@ -272,6 +281,7 @@ g:ale_python_mypy_executable *g:ale_python_mypy_executable*
Set this to `'pipenv'` to invoke `'pipenv` `run` `mypy'`. Set this to `'pipenv'` to invoke `'pipenv` `run` `mypy'`.
g:ale_python_mypy_ignore_invalid_syntax g:ale_python_mypy_ignore_invalid_syntax
*g:ale_python_mypy_ignore_invalid_syntax* *g:ale_python_mypy_ignore_invalid_syntax*
*b:ale_python_mypy_ignore_invalid_syntax* *b:ale_python_mypy_ignore_invalid_syntax*
@ -292,6 +302,14 @@ g:ale_python_mypy_options *g:ale_python_mypy_options*
invocation. invocation.
g:ale_python_mypy_show_notes *g:ale_python_mypy_show_notes*
*b:ale_python_mypy_show_notes*
Type: |Number|
Default: `1`
If enabled, notes on lines will be displayed as 'I' (info) messages.
g:ale_python_mypy_use_global *g:ale_python_mypy_use_global* g:ale_python_mypy_use_global *g:ale_python_mypy_use_global*
*b:ale_python_mypy_use_global* *b:ale_python_mypy_use_global*
Type: |Number| Type: |Number|
@ -300,14 +318,6 @@ g:ale_python_mypy_use_global *g:ale_python_mypy_use_global*
See |ale-integrations-local-executables| See |ale-integrations-local-executables|
g:ale_python_mypy_auto_pipenv *g:ale_python_mypy_auto_pipenv*
*b:ale_python_mypy_auto_pipenv*
Type: |Number|
Default: `0`
Detect whether the file is inside a pipenv, and set the executable to `pipenv`
if true. This is overridden by a manually-set executable.
=============================================================================== ===============================================================================
prospector *ale-python-prospector* prospector *ale-python-prospector*

View file

@ -9,7 +9,7 @@ Integration Information
files for Rust distributed in Vim >=8.0.0501 or upstream: files for Rust distributed in Vim >=8.0.0501 or upstream:
https://github.com/rust-lang/rust.vim https://github.com/rust-lang/rust.vim
Note that there are three possible linters for Rust files: Note that there are several possible linters and fixers for Rust files:
1. rustc -- The Rust compiler is used to check the currently edited file. 1. rustc -- The Rust compiler is used to check the currently edited file.
So, if your project consists of multiple files, you will get some errors So, if your project consists of multiple files, you will get some errors
@ -23,7 +23,12 @@ Integration Information
over cargo. rls implements the Language Server Protocol for incremental over cargo. rls implements the Language Server Protocol for incremental
compilation of Rust code, and can check Rust files while you type. `rls` compilation of Rust code, and can check Rust files while you type. `rls`
requires Rust files to contained in Cargo projects. requires Rust files to contained in Cargo projects.
4. rustfmt -- If you have `rustfmt` installed, you can use it as a fixer to 4. analyzer -- If you have rust-analyzer installed, you might prefer using
this linter over cargo and rls. rust-analyzer also implements the
Language Server Protocol for incremental compilation of Rust code, and is
the next iteration of rls. rust-analyzer, like rls, requires Rust files
to contained in Cargo projects.
5. rustfmt -- If you have `rustfmt` installed, you can use it as a fixer to
consistently reformat your Rust code. consistently reformat your Rust code.
Only cargo is enabled by default. To switch to using rustc instead of cargo, Only cargo is enabled by default. To switch to using rustc instead of cargo,
@ -36,6 +41,25 @@ Integration Information
Also note that rustc 1.12. or later is needed. Also note that rustc 1.12. or later is needed.
===============================================================================
analyzer *ale-rust-analyzer*
g:ale_rust_analyzer_executable *g:ale_rust_analyzer_executable*
*b:ale_rust_analyzer_executable*
Type: |String|
Default: `'rust-analyzer'`
This variable can be modified to change the executable path for
`rust-analyzer`.
g:ale_rust_analyzer_config *g:ale_rust_analyzer_config*
*b:ale_rust_analyzer_config*
Type: |Dictionary|
Default: `{}`
Dictionary with configuration settings for rust-analyzer.
=============================================================================== ===============================================================================
cargo *ale-rust-cargo* cargo *ale-rust-cargo*

View file

@ -36,6 +36,8 @@ Notes:
* `shell` (-n flag) * `shell` (-n flag)
* `shellcheck` * `shellcheck`
* `shfmt` * `shfmt`
* Bats
* `shellcheck`
* BibTeX * BibTeX
* `bibclean` * `bibclean`
* Bourne Shell * Bourne Shell
@ -163,6 +165,7 @@ Notes:
* `gosimple`!! * `gosimple`!!
* `gotype`!! * `gotype`!!
* `go vet`!! * `go vet`!!
* `revive`!!
* `staticcheck`!! * `staticcheck`!!
* GraphQL * GraphQL
* `eslint` * `eslint`
@ -285,6 +288,7 @@ Notes:
* Nim * Nim
* `nim check`!! * `nim check`!!
* `nimlsp` * `nimlsp`
* `nimpretty`
* nix * nix
* `nix-instantiate` * `nix-instantiate`
* `nixpkgs-fmt` * `nixpkgs-fmt`
@ -408,6 +412,7 @@ Notes:
* Rust * Rust
* `cargo`!! * `cargo`!!
* `rls` * `rls`
* `rust-analyzer`
* `rustc` (see |ale-integration-rust|) * `rustc` (see |ale-integration-rust|)
* `rustfmt` * `rustfmt`
* Sass * Sass
@ -469,6 +474,7 @@ Notes:
* `eslint` * `eslint`
* `fecs` * `fecs`
* `prettier` * `prettier`
* `standard`
* `tslint` * `tslint`
* `tsserver` * `tsserver`
* `typecheck` * `typecheck`
@ -484,6 +490,7 @@ Notes:
* `vcom` * `vcom`
* `xvhdl` * `xvhdl`
* Vim * Vim
* `vimls`
* `vint` * `vint`
* Vim help^ * Vim help^
* `alex`!! * `alex`!!

View file

@ -32,6 +32,25 @@ g:ale_terraform_terraform_executable *g:ale_terraform_terraform_executable*
This variable can be changed to use a different executable for terraform. This variable can be changed to use a different executable for terraform.
===============================================================================
terraform-lsp *ale-terraform-terraform-lsp*
g:ale_terraform_langserver_executable *g:ale_terraform_langserver_executable*
*b:ale_terraform_langserver_executable*
Type: |String|
Default: `'terraform-lsp'`
This variable can be changed to use a different executable for terraform-lsp.
g:ale_terraform_langserver_options *g:ale_terraform_langserver_options*
*b:ale_terraform_langserver_options*
Type: |String|
Default: `''`
This variable can be changed to pass custom CLI flags to terraform-lsp.
=============================================================================== ===============================================================================
tflint *ale-terraform-tflint* tflint *ale-terraform-tflint*

View file

@ -16,6 +16,33 @@ prettier *ale-typescript-prettier*
See |ale-javascript-prettier| for information about the available options. See |ale-javascript-prettier| for information about the available options.
===============================================================================
standard *ale-typescript-standard*
g:ale_typescript_standard_executable *g:ale_typescript_standard_executable*
*b:ale_typescript_standard_executable*
Type: |String|
Default: `'standard'`
See |ale-integrations-local-executables|
g:ale_typescript_standard_options *g:ale_typescript_standard_options*
*b:ale_typescript_standard_options*
Type: |String|
Default: `''`
This variable can be set to pass additional options to standard.
g:ale_typescript_standard_use_global *g:ale_typescript_standard_use_global*
*b:ale_typescript_standard_use_global*
Type: |Number|
Default: `get(g:, 'ale_use_global_executables', 0)`
See |ale-integrations-local-executables|
=============================================================================== ===============================================================================
tslint *ale-typescript-tslint* tslint *ale-typescript-tslint*

View file

@ -2,6 +2,61 @@
ALE Vim Integration *ale-vim-options* ALE Vim Integration *ale-vim-options*
===============================================================================
vimls *ale-vim-vimls*
The `vim-language-server` is the engine that powers VimL editor support
using the Language Server Protocol. See the installation instructions:
https://github.com/iamcco/vim-language-server#install
g:ale_vim_vimls_executable *g:ale_vim_vimls_executable*
*b:ale_vim_vimls_executable*
Type: |String|
Default: `'vim-language-server'`
This option can be set to change the executable path for vimls.
g:ale_vim_vimls_config *g:ale_vim_vimls_config*
*b:ale_vim_vimls_config*
Type: |Dictionary|
Default: `{}`
Dictionary containing configuration settings that will be passed to the
language server. For example: >
{
\ 'vim': {
\ 'iskeyword': '@,48-57,_,192-255,-#',
\ 'vimruntime': '',
\ 'runtimepath': '',
\ 'diagnostic': {
\ 'enable': v:true
\ },
\ 'indexes': {
\ 'runtimepath': v:true,
\ 'gap': 100,
\ 'count': 3,
\ 'projectRootPatterns' : ['.git', 'autoload', 'plugin']
\ },
\ 'suggest': {
\ 'fromVimruntime': v:true,
\ 'fromRuntimepath': v:false
\ },
\ }
\}
<
Consult the vim-language-server documentation for more information about
settings.
g:ale_vim_vimls_use_global *g:ale_vim_vimls_use_global*
*b:ale_vim_vimls_use_global*
Type: |Number|
Default: `get(g:, 'ale_use_global_executables', 0)`
See |ale-integrations-local-executables|
=============================================================================== ===============================================================================
vint *ale-vim-vint* vint *ale-vim-vint*

View file

@ -433,17 +433,54 @@ vimrc, and your issues should go away. >
set completeopt=menu,menuone,preview,noselect,noinsert set completeopt=menu,menuone,preview,noselect,noinsert
< <
Or alternatively, if you want to show documentation in popups: >
set completeopt=menu,menuone,popup,noselect,noinsert
<
*ale-symbols*
ALE provides a set of basic completion symbols. If you want to replace those
symbols with others, you can set the variable |g:ale_completion_symbols| with
a mapping of the type of completion to the symbol or other string that you
would like to use. An example here shows the available options for symbols >
let g:ale_completion_symbols = {
\ 'text': '',
\ 'method': '',
\ 'function': '',
\ 'constructor': '',
\ 'field': '',
\ 'variable': '',
\ 'class': '',
\ 'interface': '',
\ 'module': '',
\ 'property': '',
\ 'unit': 'unit',
\ 'value': 'val',
\ 'enum': '',
\ 'keyword': 'keyword',
\ 'snippet': '',
\ 'color': 'color',
\ 'file': '',
\ 'reference': 'ref',
\ 'folder': '',
\ 'enum member': '',
\ 'constant': '',
\ 'struct': '',
\ 'event': 'event',
\ 'operator': '',
\ 'type_parameter': 'type param',
\ '<default>': 'v'
\ }
<
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
5.2 Go To Definition *ale-go-to-definition* 5.2 Go To Definition *ale-go-to-definition*
ALE supports jumping to the files and locations where symbols are defined ALE supports jumping to the files and locations where symbols are defined
through any enabled LSP linters. The locations ALE will jump to depend on the through any enabled LSP linters. The locations ALE will jump to depend on the
information returned by LSP servers. The following commands are supported: information returned by LSP servers. The |ALEGoToDefinition| command will jump
to the definition of symbols under the cursor. See the documentation for the
|ALEGoToDefinition| - Open the definition of the symbol under the cursor. command for configuring how the location will be displayed.
|ALEGoToDefinitionInTab| - The same, but for opening the file in a new tab.
|ALEGoToDefinitionInSplit| - The same, but in a new split.
|ALEGoToDefinitionInVSplit| - The same, but in a new vertical split.
ALE will update Vim's |tagstack| automatically unless |g:ale_update_tagstack| is ALE will update Vim's |tagstack| automatically unless |g:ale_update_tagstack| is
set to `0`. set to `0`.
@ -453,15 +490,10 @@ set to `0`.
ALE supports jumping to the files and locations where symbols' types are ALE supports jumping to the files and locations where symbols' types are
defined through any enabled LSP linters. The locations ALE will jump to depend defined through any enabled LSP linters. The locations ALE will jump to depend
on the information returned by LSP servers. The following commands are on the information returned by LSP servers. The |ALEGoToTypeDefinition|
supported: command will jump to the definition of symbols under the cursor. See the
documentation for the command for configuring how the location will be
|ALEGoToTypeDefinition| - Open the definition of the symbol's type under displayed.
the cursor.
|ALEGoToTypeDefinitionInTab| - The same, but for opening the file in a new tab.
|ALEGoToTypeDefinitionInSplit| - The same, but in a new split.
|ALEGoToTypeDefinitionInVSplit| - The same, but in a new vertical split.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
5.4 Find References *ale-find-references* 5.4 Find References *ale-find-references*
@ -490,6 +522,9 @@ the mouse over a symbol in a buffer. Diagnostic information will take priority
over hover information for balloons. If a line contains a problem, that over hover information for balloons. If a line contains a problem, that
problem will be displayed in a balloon instead of hover information. problem will be displayed in a balloon instead of hover information.
Hover information can be displayed in the preview window instead by setting
|g:ale_hover_to_preview| to `1`.
For Vim 8.1+ terminals, mouse hovering is disabled by default. Enabling For Vim 8.1+ terminals, mouse hovering is disabled by default. Enabling
|balloonexpr| commands in terminals can cause scrolling issues in terminals, |balloonexpr| commands in terminals can cause scrolling issues in terminals,
so ALE will not attempt to show balloons unless |g:ale_set_balloons| is set to so ALE will not attempt to show balloons unless |g:ale_set_balloons| is set to
@ -623,7 +658,7 @@ g:ale_completion_delay *g:ale_completion_delay*
g:ale_completion_enabled *g:ale_completion_enabled* g:ale_completion_enabled *g:ale_completion_enabled*
b:ale_completion_enabled *b:ale_completion_enabled* *b:ale_completion_enabled*
Type: |Number| Type: |Number|
Default: `0` Default: `0`
@ -671,6 +706,47 @@ g:ale_completion_excluded_words *g:ale_completion_excluded_words*
let b:ale_completion_excluded_words = ['it', 'describe'] let b:ale_completion_excluded_words = ['it', 'describe']
< <
g:ale_completion_symbols *g:ale_completion_symbols*
Type: |Dictionary|
A mapping from completion types to symbols for completions. See
|ale-symbols| for more information.
By default, this mapping only uses built in Vim completion kinds, but it can
be updated to use any unicode character for the completion kind. For
example: >
let g:ale_completion_symbols = {
\ 'text': '',
\ 'method': '',
\ 'function': '',
\ 'constructor': '',
\ 'field': '',
\ 'variable': '',
\ 'class': '',
\ 'interface': '',
\ 'module': '',
\ 'property': '',
\ 'unit': 'v',
\ 'value': 'v',
\ 'enum': 't',
\ 'keyword': 'v',
\ 'snippet': 'v',
\ 'color': 'v',
\ 'file': 'v',
\ 'reference': 'v',
\ 'folder': 'v',
\ 'enum_member': 'm',
\ 'constant': 'm',
\ 'struct': 't',
\ 'event': 'v',
\ 'operator': 'f',
\ 'type_parameter': 'p',
\ '<default>': 'v'
\ })
<
g:ale_completion_max_suggestions *g:ale_completion_max_suggestions* g:ale_completion_max_suggestions *g:ale_completion_max_suggestions*
Type: |Number| Type: |Number|
@ -709,6 +785,16 @@ g:ale_cursor_detail *g:ale_cursor_detail*
loaded for messages to be displayed. See |ale-lint-settings-on-startup|. loaded for messages to be displayed. See |ale-lint-settings-on-startup|.
g:ale_default_navigation *g:ale_default_navigation*
*b:ale_default_navigation*
Type: |String|
Default: `'buffer'`
The default method for navigating away from the current buffer to another
buffer, such as for |ALEFindReferences:|, or |ALEGoToDefinition|.
g:ale_disable_lsp *g:ale_disable_lsp* g:ale_disable_lsp *g:ale_disable_lsp*
*b:ale_disable_lsp* *b:ale_disable_lsp*
@ -761,7 +847,7 @@ g:ale_echo_msg_error_str *g:ale_echo_msg_error_str*
g:ale_echo_msg_format *g:ale_echo_msg_format* g:ale_echo_msg_format *g:ale_echo_msg_format*
b:ale_echo_msg_format *b:ale_echo_msg_format* *b:ale_echo_msg_format*
Type: |String| Type: |String|
Default: `'%code: %%s'` Default: `'%code: %%s'`
@ -839,6 +925,21 @@ g:ale_enabled *g:ale_enabled*
See |g:ale_pattern_options| for more information on that option. See |g:ale_pattern_options| for more information on that option.
g:ale_exclude_highlights *g:ale_exclude_highlights*
*b:ale_exclude_highlights*
Type: |List|
Default: `[]`
A list of regular expressions for matching against highlight messages to
remove. For example: >
" Do not highlight messages matching strings like these.
let b:ale_exclude_highlights = ['line too long', 'foo.*bar']
<
See also: |g:ale_set_highlights|
g:ale_fixers *g:ale_fixers* g:ale_fixers *g:ale_fixers*
*b:ale_fixers* *b:ale_fixers*
@ -862,7 +963,7 @@ g:ale_fixers *g:ale_fixers*
< <
g:ale_fix_on_save *g:ale_fix_on_save* g:ale_fix_on_save *g:ale_fix_on_save*
b:ale_fix_on_save *b:ale_fix_on_save* *b:ale_fix_on_save*
Type: |Number| Type: |Number|
Default: `0` Default: `0`
@ -884,7 +985,7 @@ b:ale_fix_on_save *b:ale_fix_on_save*
g:ale_fix_on_save_ignore *g:ale_fix_on_save_ignore* g:ale_fix_on_save_ignore *g:ale_fix_on_save_ignore*
b:ale_fix_on_save_ignore *b:ale_fix_on_save_ignore* *b:ale_fix_on_save_ignore*
Type: |Dictionary| or |List| Type: |Dictionary| or |List|
Default: `{}` Default: `{}`
@ -947,6 +1048,16 @@ g:ale_history_log_output *g:ale_history_log_output*
if you want to save on some memory usage. if you want to save on some memory usage.
g:ale_hover_to_preview *g:ale_hover_to_preview*
*b:ale_hover_to_preview*
Type: |Number|
Default: `0`
If set to `1`, hover messages will be displayed in the preview window,
instead of in balloons or the message line.
g:ale_keep_list_window_open *g:ale_keep_list_window_open* g:ale_keep_list_window_open *g:ale_keep_list_window_open*
*b:ale_keep_list_window_open* *b:ale_keep_list_window_open*
Type: |Number| Type: |Number|
@ -1250,7 +1361,7 @@ g:ale_list_vertical *g:ale_list_vertical*
g:ale_loclist_msg_format *g:ale_loclist_msg_format* g:ale_loclist_msg_format *g:ale_loclist_msg_format*
b:ale_loclist_msg_format *b:ale_loclist_msg_format* *b:ale_loclist_msg_format*
Type: |String| Type: |String|
Default: `g:ale_echo_msg_format` Default: `g:ale_echo_msg_format`
@ -1302,7 +1413,7 @@ g:ale_lsp_show_message_severity *g:ale_lsp_show_message_
g:ale_lsp_root *g:ale_lsp_root* g:ale_lsp_root *g:ale_lsp_root*
b:ale_lsp_root *b:ale_lsp_root* *b:ale_lsp_root*
Type: |Dictionary| or |String| Type: |Dictionary| or |String|
Default: {} Default: {}
@ -1515,6 +1626,8 @@ g:ale_set_highlights *g:ale_set_highlights*
match highlights, whereas the line highlights when signs are enabled will match highlights, whereas the line highlights when signs are enabled will
run to the edge of the screen. run to the edge of the screen.
Highlights can be excluded with the |g:ale_exclude_highlights| option.
g:ale_set_loclist *g:ale_set_loclist* g:ale_set_loclist *g:ale_set_loclist*
@ -1781,7 +1894,8 @@ g:ale_virtualtext_cursor *g:ale_virtualtext_cursor*
g:ale_virtualtext_delay *g:ale_virtualtext_delay* g:ale_virtualtext_delay *g:ale_virtualtext_delay*
b:ale_virtualtext_delay *b:ale_virtualtext_delay* *b:ale_virtualtext_delay*
Type: |Number| Type: |Number|
Default: `10` Default: `10`
@ -1800,7 +1914,7 @@ g:ale_virtualtext_prefix *g:ale_virtualtext_prefix*
Prefix to be used with |g:ale_virtualtext_cursor|. Prefix to be used with |g:ale_virtualtext_cursor|.
g:ale_virtualenv_dir_names *g:ale_virtualenv_dir_names* g:ale_virtualenv_dir_names *g:ale_virtualenv_dir_names*
b:ale_virtualenv_dir_names *b:ale_virtualenv_dir_names* *b:ale_virtualenv_dir_names*
Type: |List| Type: |List|
Default: `['.env', '.venv', 'env', 've-py3', 've', 'virtualenv', 'venv']` Default: `['.env', '.venv', 'env', 've-py3', 've', 'virtualenv', 'venv']`
@ -1814,7 +1928,7 @@ b:ale_virtualenv_dir_names *b:ale_virtualenv_dir_names*
g:ale_warn_about_trailing_blank_lines *g:ale_warn_about_trailing_blank_lines* g:ale_warn_about_trailing_blank_lines *g:ale_warn_about_trailing_blank_lines*
b:ale_warn_about_trailing_blank_lines *b:ale_warn_about_trailing_blank_lines* *b:ale_warn_about_trailing_blank_lines*
Type: |Number| Type: |Number|
Default: `1` Default: `1`
@ -1826,7 +1940,7 @@ b:ale_warn_about_trailing_blank_lines *b:ale_warn_about_trailing_blank_lines*
g:ale_warn_about_trailing_whitespace *g:ale_warn_about_trailing_whitespace* g:ale_warn_about_trailing_whitespace *g:ale_warn_about_trailing_whitespace*
b:ale_warn_about_trailing_whitespace *b:ale_warn_about_trailing_whitespace* *b:ale_warn_about_trailing_whitespace*
Type: |Number| Type: |Number|
Default: `1` Default: `1`
@ -2166,6 +2280,8 @@ documented in additional help files.
gcc...................................|ale-asm-gcc| gcc...................................|ale-asm-gcc|
awk.....................................|ale-awk-options| awk.....................................|ale-awk-options|
gawk..................................|ale-awk-gawk| gawk..................................|ale-awk-gawk|
bats....................................|ale-bats-options|
shellcheck............................|ale-bats-shellcheck|
bib.....................................|ale-bib-options| bib.....................................|ale-bib-options|
bibclean..............................|ale-bib-bibclean| bibclean..............................|ale-bib-bibclean|
c.......................................|ale-c-options| c.......................................|ale-c-options|
@ -2264,6 +2380,7 @@ documented in additional help files.
gometalinter..........................|ale-go-gometalinter| gometalinter..........................|ale-go-gometalinter|
gopls.................................|ale-go-gopls| gopls.................................|ale-go-gopls|
govet.................................|ale-go-govet| govet.................................|ale-go-govet|
revive................................|ale-go-revive|
staticcheck...........................|ale-go-staticcheck| staticcheck...........................|ale-go-staticcheck|
graphql.................................|ale-graphql-options| graphql.................................|ale-graphql-options|
eslint................................|ale-graphql-eslint| eslint................................|ale-graphql-eslint|
@ -2362,6 +2479,7 @@ documented in additional help files.
nim.....................................|ale-nim-options| nim.....................................|ale-nim-options|
nimcheck..............................|ale-nim-nimcheck| nimcheck..............................|ale-nim-nimcheck|
nimlsp................................|ale-nim-nimlsp| nimlsp................................|ale-nim-nimlsp|
nimpretty.............................|ale-nim-nimpretty|
nix.....................................|ale-nix-options| nix.....................................|ale-nix-options|
nixpkgs-fmt...........................|ale-nix-nixpkgs-fmt| nixpkgs-fmt...........................|ale-nix-nixpkgs-fmt|
nroff...................................|ale-nroff-options| nroff...................................|ale-nroff-options|
@ -2465,6 +2583,7 @@ documented in additional help files.
sorbet................................|ale-ruby-sorbet| sorbet................................|ale-ruby-sorbet|
standardrb............................|ale-ruby-standardrb| standardrb............................|ale-ruby-standardrb|
rust....................................|ale-rust-options| rust....................................|ale-rust-options|
analyzer..............................|ale-rust-analyzer|
cargo.................................|ale-rust-cargo| cargo.................................|ale-rust-cargo|
rls...................................|ale-rust-rls| rls...................................|ale-rust-rls|
rustc.................................|ale-rust-rustc| rustc.................................|ale-rust-rustc|
@ -2509,6 +2628,7 @@ documented in additional help files.
terraform...............................|ale-terraform-options| terraform...............................|ale-terraform-options|
terraform-fmt-fixer...................|ale-terraform-fmt-fixer| terraform-fmt-fixer...................|ale-terraform-fmt-fixer|
terraform.............................|ale-terraform-terraform| terraform.............................|ale-terraform-terraform|
terraform-lsp.........................|ale-terraform-terraform-lsp|
tflint................................|ale-terraform-tflint| tflint................................|ale-terraform-tflint|
tex.....................................|ale-tex-options| tex.....................................|ale-tex-options|
chktex................................|ale-tex-chktex| chktex................................|ale-tex-chktex|
@ -2525,6 +2645,7 @@ documented in additional help files.
typescript..............................|ale-typescript-options| typescript..............................|ale-typescript-options|
eslint................................|ale-typescript-eslint| eslint................................|ale-typescript-eslint|
prettier..............................|ale-typescript-prettier| prettier..............................|ale-typescript-prettier|
standard..............................|ale-typescript-standard|
tslint................................|ale-typescript-tslint| tslint................................|ale-typescript-tslint|
tsserver..............................|ale-typescript-tsserver| tsserver..............................|ale-typescript-tsserver|
vala....................................|ale-vala-options| vala....................................|ale-vala-options|
@ -2539,6 +2660,7 @@ documented in additional help files.
vcom..................................|ale-vhdl-vcom| vcom..................................|ale-vhdl-vcom|
xvhdl.................................|ale-vhdl-xvhdl| xvhdl.................................|ale-vhdl-xvhdl|
vim.....................................|ale-vim-options| vim.....................................|ale-vim-options|
vimls.................................|ale-vim-vimls|
vint..................................|ale-vim-vint| vint..................................|ale-vim-vint|
vim help................................|ale-vim-help-options| vim help................................|ale-vim-help-options|
write-good............................|ale-vim-help-write-good| write-good............................|ale-vim-help-write-good|
@ -2592,11 +2714,23 @@ ALEFindReferences *ALEFindReferences*
Enter key (`<CR>`) can be used to jump to a referencing location, or the `t` Enter key (`<CR>`) can be used to jump to a referencing location, or the `t`
key can be used to jump to the location in a new tab. key can be used to jump to the location in a new tab.
The locations opened in different ways using the following variations.
`:ALEFindReferences -tab` - Open the location in a new tab.
`:ALEFindReferences -split` - Open the location in a horizontal split.
`:ALEFindReferences -vsplit` - Open the location in a vertical split.
The default method used for navigating to a new location can be changed
by modifying |g:ale_default_navigation|.
The selection can be opened again with the |ALERepeatSelection| command.
You can jump back to the position you were at before going to a reference of You can jump back to the position you were at before going to a reference of
something with jump motions like CTRL-O. See |jump-motions|. something with jump motions like CTRL-O. See |jump-motions|.
A plug mapping `<Plug>(ale_find_references)` is defined for this command. A plug mapping `<Plug>(ale_find_references)` is defined for this command.
ALEFix *ALEFix* ALEFix *ALEFix*
Fix problems with the current buffer. See |ale-fix| for more information. Fix problems with the current buffer. See |ale-fix| for more information.
@ -2611,42 +2745,31 @@ ALEFixSuggest *ALEFixSuggest*
See |ale-fix| for more information. See |ale-fix| for more information.
ALEGoToDefinition *ALEGoToDefinition* ALEGoToDefinition `<options>` *ALEGoToDefinition*
Jump to the definition of a symbol under the cursor using the enabled LSP Jump to the definition of a symbol under the cursor using the enabled LSP
linters for the buffer. ALE will jump to a definition if an LSP server linters for the buffer. ALE will jump to a definition if an LSP server
provides a location to jump to. Otherwise, ALE will do nothing. provides a location to jump to. Otherwise, ALE will do nothing.
The locations opened in different ways using the following variations.
`:ALEGoToDefinition -tab` - Open the location in a new tab.
`:ALEGoToDefinition -split` - Open the location in a horizontal split.
`:ALEGoToDefinition -vsplit` - Open the location in a vertical split.
The default method used for navigating to a new location can be changed
by modifying |g:ale_default_navigation|.
You can jump back to the position you were at before going to the definition You can jump back to the position you were at before going to the definition
of something with jump motions like CTRL-O. See |jump-motions|. of something with jump motions like CTRL-O. See |jump-motions|.
You should consider using the 'hidden' option in combination with this
command. Otherwise, Vim will refuse to leave the buffer you're jumping from
unless you have saved your edits.
A plug mapping `<Plug>(ale_go_to_definition)` is defined for this command. A plug mapping `<Plug>(ale_go_to_definition)` is defined for this command.
ALEGoToDefinitionInTab *ALEGoToDefinitionInTab*
The same as |ALEGoToDefinition|, but opens results in a new tab.
A plug mapping `<Plug>(ale_go_to_definition_in_tab)` is defined for this
command.
ALEGoToDefinitionInSplit *ALEGoToDefinitionInSplit*
The same as |ALEGoToDefinition|, but opens results in a new split.
A plug mapping `<Plug>(ale_go_to_definition_in_split)` is defined for this
command.
ALEGoToDefinitionInVSplit *ALEGoToDefinitionInVSplit*
The same as |ALEGoToDefinition|, but opens results in a new vertical split.
A plug mapping `<Plug>(ale_go_to_definition_in_vsplit)` is defined for this
command.
ALEGoToTypeDefinition *ALEGoToTypeDefinition* ALEGoToTypeDefinition *ALEGoToTypeDefinition*
This works similar to |ALEGoToDefinition| but instead jumps to the This works similar to |ALEGoToDefinition| but instead jumps to the
@ -2654,6 +2777,15 @@ ALEGoToTypeDefinition *ALEGoToTypeDefinition*
definition if an LSP server provides a location to jump to. Otherwise, ALE definition if an LSP server provides a location to jump to. Otherwise, ALE
will do nothing. will do nothing.
The locations opened in different ways using the following variations.
`:ALEGoToTypeDefinition -tab` - Open the location in a new tab.
`:ALEGoToTypeDefinition -split` - Open the location in a horizontal split.
`:ALEGoToTypeDefinition -vsplit` - Open the location in a vertical split.
The default method used for navigating to a new location can be changed
by modifying |g:ale_default_navigation|.
You can jump back to the position you were at before going to the definition You can jump back to the position you were at before going to the definition
of something with jump motions like CTRL-O. See |jump-motions|. of something with jump motions like CTRL-O. See |jump-motions|.
@ -2661,31 +2793,6 @@ ALEGoToTypeDefinition *ALEGoToTypeDefinition*
command. command.
ALEGoToTypeDefinitionInTab *ALEGoToTypeDefinitionInTab*
The same as |ALEGoToTypeDefinition|, but opens results in a new tab.
A plug mapping `<Plug>(ale_go_to_type_definition_in_tab)` is defined for
this command.
ALEGoToTypeDefinitionInSplit *ALEGoToTypeDefinitionInSplit*
The same as |ALEGoToTypeDefinition|, but opens results in a new split.
A plug mapping `<Plug>(ale_go_to_type_definition_in_split)` is defined for
this command.
ALEGoToTypeDefinitionInVSplit *ALEGoToTypeDefinitionInVSplit*
The same as |ALEGoToTypeDefinition|, but opens results in a new vertical
split.
A plug mapping `<Plug>(ale_go_to_type_definition_in_vsplit)` is defined for
this command.
ALEHover *ALEHover* ALEHover *ALEHover*
Print brief information about the symbol under the cursor, taken from any Print brief information about the symbol under the cursor, taken from any
@ -2711,6 +2818,11 @@ ALERename *ALERename*
The user will be prompted for a new name. The user will be prompted for a new name.
ALERepeatSelection *ALERepeatSelection*
Repeat the last selection displayed in the preview window.
ALESymbolSearch `<query>` *ALESymbolSearch* ALESymbolSearch `<query>` *ALESymbolSearch*
Search for symbols in the workspace, taken from any available LSP linters. Search for symbols in the workspace, taken from any available LSP linters.
@ -3019,7 +3131,6 @@ ale#command#Run(buffer, command, callback, [options]) *ale#command#Run()*
'command': {b -> ale#command#Run(b, 'foo', function('s:GetCommand'))} 'command': {b -> ale#command#Run(b, 'foo', function('s:GetCommand'))}
< <
The following `options` can be provided. The following `options` can be provided.
`output_stream` - Either `'stdout'`, `'stderr'`, `'both'`, or `'none`' for `output_stream` - Either `'stdout'`, `'stderr'`, `'both'`, or `'none`' for

View file

@ -12,5 +12,5 @@ noremap <buffer> A <NOP>
noremap <buffer> o <NOP> noremap <buffer> o <NOP>
noremap <buffer> O <NOP> noremap <buffer> O <NOP>
" Keybinds for opening selection items. " Keybinds for opening selection items.
noremap <buffer> <CR> :call ale#preview#OpenSelectionInBuffer()<CR> noremap <buffer> <CR> :call ale#preview#OpenSelection()<CR>
noremap <buffer> t :call ale#preview#OpenSelectionInTab()<CR> noremap <buffer> t :call ale#preview#OpenSelectionInTab()<CR>

View file

@ -109,6 +109,9 @@ let g:ale_set_signs = get(g:, 'ale_set_signs', has('signs'))
" This flag can be set to 0 to disable setting error highlights. " This flag can be set to 0 to disable setting error highlights.
let g:ale_set_highlights = get(g:, 'ale_set_highlights', has('syntax')) let g:ale_set_highlights = get(g:, 'ale_set_highlights', has('syntax'))
" This List can be configured to exclude particular highlights.
let g:ale_exclude_highlights = get(g:, 'ale_exclude_highlights', [])
" This flag can be set to 0 to disable echoing when the cursor moves. " This flag can be set to 0 to disable echoing when the cursor moves.
let g:ale_echo_cursor = get(g:, 'ale_echo_cursor', 1) let g:ale_echo_cursor = get(g:, 'ale_echo_cursor', 1)
@ -125,6 +128,9 @@ let g:ale_close_preview_on_insert = get(g:, 'ale_close_preview_on_insert', 0)
" This flag can be set to 0 to disable balloon support. " This flag can be set to 0 to disable balloon support.
let g:ale_set_balloons = get(g:, 'ale_set_balloons', has('balloon_eval') && has('gui_running')) let g:ale_set_balloons = get(g:, 'ale_set_balloons', has('balloon_eval') && has('gui_running'))
" Use preview window for hover messages.
let g:ale_hover_to_preview = get(g:, 'ale_hover_to_preview', 0)
" This flag can be set to 0 to disable warnings for trailing whitespace " This flag can be set to 0 to disable warnings for trailing whitespace
let g:ale_warn_about_trailing_whitespace = get(g:, 'ale_warn_about_trailing_whitespace', 1) let g:ale_warn_about_trailing_whitespace = get(g:, 'ale_warn_about_trailing_whitespace', 1)
" This flag can be set to 0 to disable warnings for trailing blank lines " This flag can be set to 0 to disable warnings for trailing blank lines
@ -196,16 +202,23 @@ command! -bar -nargs=* -complete=customlist,ale#fix#registry#CompleteFixers ALEF
command! -bar ALEFixSuggest :call ale#fix#registry#Suggest(&filetype) command! -bar ALEFixSuggest :call ale#fix#registry#Suggest(&filetype)
" Go to definition for tsserver and LSP " Go to definition for tsserver and LSP
command! -bar ALEGoToDefinition :call ale#definition#GoTo({}) command! -bar -nargs=* ALEGoToDefinition :call ale#definition#GoToCommandHandler('', <f-args>)
command! -bar ALEGoToDefinitionInTab :call ale#definition#GoTo({'open_in': 'tab'})
command! -bar ALEGoToDefinitionInSplit :call ale#definition#GoTo({'open_in': 'horizontal-split'}) " Deprecated commands we have to keep for now.
command! -bar ALEGoToDefinitionInVSplit :call ale#definition#GoTo({'open_in': 'vertical-split'}) command! -bar ALEGoToDefinitionInTab :call ale#definition#GoTo({'open_in': 'tab', 'deprecated_command': 'ALEGoToDefinitionInTab'})
command! -bar ALEGoToDefinitionInSplit :call ale#definition#GoTo({'open_in': 'split', 'deprecated_command': 'ALEGoToDefinitionInSplit'})
command! -bar ALEGoToDefinitionInVSplit :call ale#definition#GoTo({'open_in': 'vsplit', 'deprecated_command': 'ALEGoToDefinitionInVSplit'})
" Go to type definition for tsserver and LSP " Go to type definition for tsserver and LSP
command! -bar ALEGoToTypeDefinition :call ale#definition#GoToType({}) command! -bar -nargs=* ALEGoToTypeDefinition :call ale#definition#GoToCommandHandler('type', <f-args>)
command! -bar ALEGoToTypeDefinitionInTab :call ale#definition#GoToType({'open_in': 'tab'})
command! -bar ALEGoToTypeDefinitionInSplit :call ale#definition#GoToType({'open_in': 'horizontal-split'}) " Deprecated commands we have to keep for now.
command! -bar ALEGoToTypeDefinitionInVSplit :call ale#definition#GoToType({'open_in': 'vertical-split'}) command! -bar ALEGoToTypeDefinitionInTab :call ale#definition#GoToType({'open_in': 'tab', 'deprecated_command': 'ALEGoToTypeDefinitionInTab'})
command! -bar ALEGoToTypeDefinitionInSplit :call ale#definition#GoToType({'open_in': 'split', 'deprecated_command': 'ALEGoToTypeDefinitionInSplit'})
command! -bar ALEGoToTypeDefinitionInVSplit :call ale#definition#GoToType({'open_in': 'vsplit', 'deprecated_command': 'ALEGoToTypeDefinitionInVSplit'})
" Repeat a previous selection in the preview window
command! -bar ALERepeatSelection :call ale#preview#RepeatSelection()
" Find references for tsserver and LSP " Find references for tsserver and LSP
command! -bar -nargs=* ALEFindReferences :call ale#references#Find(<f-args>) command! -bar -nargs=* ALEFindReferences :call ale#references#Find(<f-args>)
@ -254,18 +267,21 @@ nnoremap <silent> <Plug>(ale_lint) :ALELint<Return>
nnoremap <silent> <Plug>(ale_detail) :ALEDetail<Return> nnoremap <silent> <Plug>(ale_detail) :ALEDetail<Return>
nnoremap <silent> <Plug>(ale_fix) :ALEFix<Return> nnoremap <silent> <Plug>(ale_fix) :ALEFix<Return>
nnoremap <silent> <Plug>(ale_go_to_definition) :ALEGoToDefinition<Return> nnoremap <silent> <Plug>(ale_go_to_definition) :ALEGoToDefinition<Return>
nnoremap <silent> <Plug>(ale_go_to_definition_in_tab) :ALEGoToDefinitionInTab<Return>
nnoremap <silent> <Plug>(ale_go_to_definition_in_split) :ALEGoToDefinitionInSplit<Return>
nnoremap <silent> <Plug>(ale_go_to_definition_in_vsplit) :ALEGoToDefinitionInVSplit<Return>
nnoremap <silent> <Plug>(ale_go_to_type_definition) :ALEGoToTypeDefinition<Return> nnoremap <silent> <Plug>(ale_go_to_type_definition) :ALEGoToTypeDefinition<Return>
nnoremap <silent> <Plug>(ale_go_to_type_definition_in_tab) :ALEGoToTypeDefinitionInTab<Return>
nnoremap <silent> <Plug>(ale_go_to_type_definition_in_split) :ALEGoToTypeDefinitionInSplit<Return>
nnoremap <silent> <Plug>(ale_go_to_type_definition_in_vsplit) :ALEGoToTypeDefinitionInVSplit<Return>
nnoremap <silent> <Plug>(ale_find_references) :ALEFindReferences<Return> nnoremap <silent> <Plug>(ale_find_references) :ALEFindReferences<Return>
nnoremap <silent> <Plug>(ale_hover) :ALEHover<Return> nnoremap <silent> <Plug>(ale_hover) :ALEHover<Return>
nnoremap <silent> <Plug>(ale_documentation) :ALEDocumentation<Return> nnoremap <silent> <Plug>(ale_documentation) :ALEDocumentation<Return>
inoremap <silent> <Plug>(ale_complete) <C-\><C-O>:ALEComplete<Return> inoremap <silent> <Plug>(ale_complete) <C-\><C-O>:ALEComplete<Return>
nnoremap <silent> <Plug>(ale_rename) :ALERename<Return> nnoremap <silent> <Plug>(ale_rename) :ALERename<Return>
nnoremap <silent> <Plug>(ale_repeat_selection) :ALERepeatSelection<Return>
" Deprecated <Plug> mappings
nnoremap <silent> <Plug>(ale_go_to_definition_in_tab) :ALEGoToDefinitionInTab<Return>
nnoremap <silent> <Plug>(ale_go_to_definition_in_split) :ALEGoToDefinitionInSplit<Return>
nnoremap <silent> <Plug>(ale_go_to_definition_in_vsplit) :ALEGoToDefinitionInVSplit<Return>
nnoremap <silent> <Plug>(ale_go_to_type_definition_in_tab) :ALEGoToTypeDefinitionInTab<Return>
nnoremap <silent> <Plug>(ale_go_to_type_definition_in_split) :ALEGoToTypeDefinitionInSplit<Return>
nnoremap <silent> <Plug>(ale_go_to_type_definition_in_vsplit) :ALEGoToTypeDefinitionInVSplit<Return>
" Set up autocmd groups now. " Set up autocmd groups now.
call ale#events#Init() call ale#events#Init()

View file

@ -24,6 +24,7 @@ class Source(Base):
self.rank = 1000 self.rank = 1000
self.is_bytepos = True self.is_bytepos = True
self.min_pattern_length = 1 self.min_pattern_length = 1
self.is_volatile = True
# Do not forget to update s:trigger_character_map in completion.vim in # Do not forget to update s:trigger_character_map in completion.vim in
# updating entries in this map. # updating entries in this map.
self.input_patterns = { self.input_patterns = {
@ -44,21 +45,16 @@ class Source(Base):
if not self.vim.call('ale#completion#CanProvideCompletions'): if not self.vim.call('ale#completion#CanProvideCompletions'):
return None return None
if context.get('is_refresh'): event = context.get('event')
context['is_async'] = False
if context['is_async']: if event == 'Async':
# Result is the same as for omnifunc, or None.
result = self.vim.call('ale#completion#GetCompletionResult') result = self.vim.call('ale#completion#GetCompletionResult')
return result or []
if result is not None: if context.get('is_refresh'):
context['is_async'] = False self.vim.command(
"call ale#completion#GetCompletions('ale-callback', " + \
return result "{'callback': {completions -> deoplete#auto_complete() }})"
else: )
context['is_async'] = True
# Request some completion results.
self.vim.call('ale#completion#GetCompletions', 'deoplete')
return [] return []

View file

@ -45,6 +45,8 @@ formatting.
* shell [-n flag](https://www.gnu.org/software/bash/manual/bash.html#index-set) * shell [-n flag](https://www.gnu.org/software/bash/manual/bash.html#index-set)
* [shellcheck](https://www.shellcheck.net/) * [shellcheck](https://www.shellcheck.net/)
* [shfmt](https://github.com/mvdan/sh) * [shfmt](https://github.com/mvdan/sh)
* Bats
* [shellcheck](https://www.shellcheck.net/)
* BibTeX * BibTeX
* [bibclean](http://ftp.math.utah.edu/pub/bibclean/) * [bibclean](http://ftp.math.utah.edu/pub/bibclean/)
* Bourne Shell * Bourne Shell
@ -172,6 +174,7 @@ formatting.
* [gosimple](https://github.com/dominikh/go-tools/tree/master/cmd/gosimple) :warning: :floppy_disk: * [gosimple](https://github.com/dominikh/go-tools/tree/master/cmd/gosimple) :warning: :floppy_disk:
* [gotype](https://godoc.org/golang.org/x/tools/cmd/gotype) :warning: :floppy_disk: * [gotype](https://godoc.org/golang.org/x/tools/cmd/gotype) :warning: :floppy_disk:
* [go vet](https://golang.org/cmd/vet/) :floppy_disk: * [go vet](https://golang.org/cmd/vet/) :floppy_disk:
* [revive](https://github.com/mgechev/revive) :warning: :floppy_disk:
* [staticcheck](https://github.com/dominikh/go-tools/tree/master/cmd/staticcheck) :warning: :floppy_disk: * [staticcheck](https://github.com/dominikh/go-tools/tree/master/cmd/staticcheck) :warning: :floppy_disk:
* GraphQL * GraphQL
* [eslint](http://eslint.org/) * [eslint](http://eslint.org/)
@ -294,6 +297,7 @@ formatting.
* Nim * Nim
* [nim check](https://nim-lang.org/docs/nimc.html) :floppy_disk: * [nim check](https://nim-lang.org/docs/nimc.html) :floppy_disk:
* [nimlsp](https://github.com/PMunch/nimlsp) * [nimlsp](https://github.com/PMunch/nimlsp)
* nimpretty
* nix * nix
* [nix-instantiate](http://nixos.org/nix/manual/#sec-nix-instantiate) * [nix-instantiate](http://nixos.org/nix/manual/#sec-nix-instantiate)
* [nixpkgs-fmt](https://github.com/nix-community/nixpkgs-fmt) * [nixpkgs-fmt](https://github.com/nix-community/nixpkgs-fmt)
@ -417,6 +421,7 @@ formatting.
* Rust * Rust
* [cargo](https://github.com/rust-lang/cargo) :floppy_disk: (see `:help ale-integration-rust` for configuration instructions) * [cargo](https://github.com/rust-lang/cargo) :floppy_disk: (see `:help ale-integration-rust` for configuration instructions)
* [rls](https://github.com/rust-lang-nursery/rls) :warning: * [rls](https://github.com/rust-lang-nursery/rls) :warning:
* [rust-analyzer](https://github.com/rust-analyzer/rust-analyzer) :warning:
* [rustc](https://www.rust-lang.org/) :warning: * [rustc](https://www.rust-lang.org/) :warning:
* [rustfmt](https://github.com/rust-lang-nursery/rustfmt) * [rustfmt](https://github.com/rust-lang-nursery/rustfmt)
* Sass * Sass
@ -478,6 +483,7 @@ formatting.
* [eslint](http://eslint.org/) * [eslint](http://eslint.org/)
* [fecs](http://fecs.baidu.com/) * [fecs](http://fecs.baidu.com/)
* [prettier](https://github.com/prettier/prettier) * [prettier](https://github.com/prettier/prettier)
* [standard](http://standardjs.com/)
* [tslint](https://github.com/palantir/tslint) * [tslint](https://github.com/palantir/tslint)
* [tsserver](https://github.com/Microsoft/TypeScript/wiki/Standalone-Server-%28tsserver%29) * [tsserver](https://github.com/Microsoft/TypeScript/wiki/Standalone-Server-%28tsserver%29)
* typecheck * typecheck
@ -493,6 +499,7 @@ formatting.
* [vcom](https://www.mentor.com/products/fv/questa/) * [vcom](https://www.mentor.com/products/fv/questa/)
* [xvhdl](https://www.xilinx.com/products/design-tools/vivado.html) * [xvhdl](https://www.xilinx.com/products/design-tools/vivado.html)
* Vim * Vim
* [vimls](https://github.com/iamcco/vim-language-server)
* [vint](https://github.com/Kuniwak/vint) * [vint](https://github.com/Kuniwak/vint)
* Vim help * Vim help
* [alex](https://github.com/wooorm/alex) :warning: :floppy_disk: * [alex](https://github.com/wooorm/alex) :warning: :floppy_disk:

View file

@ -54,6 +54,7 @@ Execute(VersionCheck should return correct version):
Execute(The eclipselsp callback should return the correct default value): Execute(The eclipselsp callback should return the correct default value):
let cmd = [ ale#Escape('java'), let cmd = [ ale#Escape('java'),
\ '',
\ '-Declipse.application=org.eclipse.jdt.ls.core.id1', \ '-Declipse.application=org.eclipse.jdt.ls.core.id1',
\ '-Dosgi.bundles.defaultStartLevel=4', \ '-Dosgi.bundles.defaultStartLevel=4',
\ '-Declipse.product=org.eclipse.jdt.ls.core.product', \ '-Declipse.product=org.eclipse.jdt.ls.core.product',
@ -72,6 +73,7 @@ Execute(The eclipselsp callback should return the correct default value):
Execute(The eclipselsp callback should allow custom executable): Execute(The eclipselsp callback should allow custom executable):
let b:ale_java_eclipselsp_executable='/bin/foobar' let b:ale_java_eclipselsp_executable='/bin/foobar'
let cmd = [ ale#Escape('/bin/foobar'), let cmd = [ ale#Escape('/bin/foobar'),
\ '',
\ '-Declipse.application=org.eclipse.jdt.ls.core.id1', \ '-Declipse.application=org.eclipse.jdt.ls.core.id1',
\ '-Dosgi.bundles.defaultStartLevel=4', \ '-Dosgi.bundles.defaultStartLevel=4',
\ '-Declipse.product=org.eclipse.jdt.ls.core.product', \ '-Declipse.product=org.eclipse.jdt.ls.core.product',
@ -87,9 +89,12 @@ Execute(The eclipselsp callback should allow custom executable):
\] \]
AssertLinter '/bin/foobar', join(cmd, ' ') AssertLinter '/bin/foobar', join(cmd, ' ')
Execute(The eclipselsp callback should allow custom configuration path): Execute(The eclipselsp callback should allow custom configuration path and javaagent):
let b:ale_java_eclipselsp_config_path = '/home/config' let b:ale_java_eclipselsp_config_path = '/home/config'
let b:ale_java_eclipselsp_javaagent = '/home/lombok.jar /home/lombok2.jar'
let cmd = [ ale#Escape('java'), let cmd = [ ale#Escape('java'),
\ ale#Escape('-javaagent:/home/lombok.jar'),
\ ale#Escape('-javaagent:/home/lombok2.jar'),
\ '-Declipse.application=org.eclipse.jdt.ls.core.id1', \ '-Declipse.application=org.eclipse.jdt.ls.core.id1',
\ '-Dosgi.bundles.defaultStartLevel=4', \ '-Dosgi.bundles.defaultStartLevel=4',
\ '-Declipse.product=org.eclipse.jdt.ls.core.product', \ '-Declipse.product=org.eclipse.jdt.ls.core.product',

View file

@ -31,7 +31,7 @@ After:
Execute(The javac callback should return the correct default value): Execute(The javac callback should return the correct default value):
AssertLinter 'javac', g:prefix . ' -d ' . ale#Escape('TEMP_DIR') . ' %t' AssertLinter 'javac', g:prefix . ' -d ' . ale#Escape('TEMP_DIR') . ' %t'
Execute(The javac callback should use g:ale_java_javac_classpath correctly): Execute(The javac callback should use string type g:ale_java_javac_classpath correctly):
let g:ale_java_javac_classpath = 'foo.jar' let g:ale_java_javac_classpath = 'foo.jar'
AssertLinter 'javac', AssertLinter 'javac',
@ -39,6 +39,14 @@ Execute(The javac callback should use g:ale_java_javac_classpath correctly):
\ . ' -cp ' . ale#Escape('foo.jar') \ . ' -cp ' . ale#Escape('foo.jar')
\ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t' \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t'
Execute(The javac callback should use list type g:ale_java_javac_classpath correctly):
let g:ale_java_javac_classpath = ['foo.jar']
AssertLinter 'javac',
\ g:prefix
\ . ' -cp ' . ale#Escape('foo.jar')
\ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t'
Execute(The executable should be configurable): Execute(The executable should be configurable):
let g:ale_java_javac_executable = 'foobar' let g:ale_java_javac_executable = 'foobar'
@ -108,6 +116,137 @@ Execute(The javac callback should combine discovered classpaths and manual ones)
\ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t', \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t',
\ substitute(b:command, '%e', '\=ale#Escape(''javac'')', 'g') \ substitute(b:command, '%e', '\=ale#Escape(''javac'')', 'g')
let g:ale_java_javac_classpath = ['configured.jar']
let b:command = ale_linters#java#javac#GetCommand(bufnr(''), [
\ '[DEBUG] Ignore this.',
\ '[INFO] Something we should ignore.',
\ '/foo/bar.jar',
\ '/xyz/abc.jar',
\], {})
AssertEqual
\ g:prefix
\ . ' -cp '
\ . ale#Escape(join(
\ [
\ '/foo/bar.jar',
\ '/xyz/abc.jar',
\ 'configured.jar',
\ ],
\ g:cp_sep
\ ))
\ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t',
\ substitute(b:command, '%e', '\=ale#Escape(''javac'')', 'g')
let g:ale_java_javac_classpath = ['configured.jar', 'configured2.jar']
let b:command = ale_linters#java#javac#GetCommand(bufnr(''), [
\ '[DEBUG] Ignore this.',
\ '[INFO] Something we should ignore.',
\ '/foo/bar.jar',
\ '/xyz/abc.jar',
\], {})
AssertEqual
\ g:prefix
\ . ' -cp '
\ . ale#Escape(join(
\ [
\ '/foo/bar.jar',
\ '/xyz/abc.jar',
\ 'configured.jar',
\ 'configured2.jar',
\ ],
\ g:cp_sep
\ ))
\ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t',
\ substitute(b:command, '%e', '\=ale#Escape(''javac'')', 'g')
Execute(The javac callback should use string type g:ale_java_javac_sourcepath correctly):
let g:ale_java_javac_sourcepath = 'java_paths/build/gen/main'
AssertLinter 'javac',
\ g:prefix
\ . ' -sourcepath ' . ale#Escape(
\ ale#path#Simplify(g:dir . '/java_paths/build/gen/main/')
\ )
\ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t'
Execute(The javac callback should use list type g:ale_java_javac_sourcepath correctly):
let g:ale_java_javac_sourcepath = ['java_paths/build/gen/main']
AssertLinter 'javac',
\ g:prefix
\ . ' -sourcepath ' . ale#Escape(
\ ale#path#Simplify(g:dir . '/java_paths/build/gen/main/')
\ )
\ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t'
Execute(The javac callback shouldn't add -sourcepath when g:ale_java_javac_sourcepath variable path doesn't exist):
let g:ale_java_javac_sourcepath = 'java_paths/build/gen3/main'
AssertLinter 'javac',
\ g:prefix
\ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t'
Execute(The javac callback should combine discovered sourcepath and manual ones):
call ale#engine#Cleanup(bufnr(''))
call ale#test#SetFilename('java_paths/src/main/java/com/something/dummy.java')
call ale#engine#InitBufferInfo(bufnr(''))
let g:ale_java_javac_sourcepath = 'java_paths/build/gen/main'
let b:command = ale_linters#java#javac#GetCommand(bufnr(''), [], {})
AssertEqual
\ ale#path#CdString(expand('%:p:h')) . ale#Escape('javac') . ' -Xlint'
\ . ' -sourcepath ' . ale#Escape(join([
\ ale#path#Simplify(g:dir . '/java_paths/src/main/java/'),
\ ale#path#Simplify(g:dir . '/java_paths/build/gen/main/'),
\ ], g:cp_sep))
\ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t',
\ substitute(b:command, '%e', '\=ale#Escape(''javac'')', 'g')
let g:ale_java_javac_sourcepath = 'java_paths/build/gen/main'
\ . g:cp_sep . 'java_paths/build/gen2/main'
let b:command = ale_linters#java#javac#GetCommand(bufnr(''), [], {})
AssertEqual
\ ale#path#CdString(expand('%:p:h')) . ale#Escape('javac') . ' -Xlint'
\ . ' -sourcepath ' . ale#Escape(join([
\ ale#path#Simplify(g:dir . '/java_paths/src/main/java/'),
\ ale#path#Simplify(g:dir . '/java_paths/build/gen/main/'),
\ ale#path#Simplify(g:dir . '/java_paths/build/gen2/main/')
\ ], g:cp_sep))
\ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t',
\ substitute(b:command, '%e', '\=ale#Escape(''javac'')', 'g')
let g:ale_java_javac_sourcepath = ['java_paths/build/gen/main']
let b:command = ale_linters#java#javac#GetCommand(bufnr(''), [], {})
AssertEqual
\ ale#path#CdString(expand('%:p:h')) . ale#Escape('javac') . ' -Xlint'
\ . ' -sourcepath ' . ale#Escape(join([
\ ale#path#Simplify(g:dir . '/java_paths/src/main/java/'),
\ ale#path#Simplify(g:dir . '/java_paths/build/gen/main/')
\ ], g:cp_sep))
\ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t',
\ substitute(b:command, '%e', '\=ale#Escape(''javac'')', 'g')
let g:ale_java_javac_sourcepath = [
\ 'java_paths/build/gen/main',
\ 'java_paths/build/gen2/main'
\ ]
let b:command = ale_linters#java#javac#GetCommand(bufnr(''), [], {})
AssertEqual
\ ale#path#CdString(expand('%:p:h')) . ale#Escape('javac') . ' -Xlint'
\ . ' -sourcepath ' . ale#Escape(join([
\ ale#path#Simplify(g:dir . '/java_paths/src/main/java/'),
\ ale#path#Simplify(g:dir . '/java_paths/build/gen/main/'),
\ ale#path#Simplify(g:dir . '/java_paths/build/gen2/main/')
\ ], g:cp_sep))
\ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t',
\ substitute(b:command, '%e', '\=ale#Escape(''javac'')', 'g')
Execute(The javac callback should detect source directories): Execute(The javac callback should detect source directories):
call ale#engine#Cleanup(bufnr('')) call ale#engine#Cleanup(bufnr(''))
noautocmd e! java_paths/src/main/java/com/something/dummy noautocmd e! java_paths/src/main/java/com/something/dummy

View file

@ -52,6 +52,15 @@ Execute(The mypy callbacks should detect virtualenv directories and switch to th
\ . ' --show-column-numbers ' \ . ' --show-column-numbers '
\ . '--shadow-file %s %t %s' \ . '--shadow-file %s %t %s'
Execute(The mypy callbacks should cd to directory containing mypy.ini if found):
silent execute 'file ' . fnameescape(g:dir . '/python_paths/with_mypy_ini_and_pytest_ini/tests/testsubfolder/my_tests.py')
AssertLinter 'mypy',
\ ale#path#CdString(ale#path#Simplify(g:dir . '/python_paths/with_mypy_ini_and_pytest_ini'))
\ . ale#Escape('mypy')
\ . ' --show-column-numbers '
\ . '--shadow-file %s %t %s'
Execute(You should able able to use the global mypy instead): Execute(You should able able to use the global mypy instead):
silent execute 'file ' . fnameescape(g:dir . '/python_paths/with_virtualenv/subdir/foo/bar.py') silent execute 'file ' . fnameescape(g:dir . '/python_paths/with_virtualenv/subdir/foo/bar.py')
let g:ale_python_mypy_use_global = 1 let g:ale_python_mypy_use_global = 1

View file

@ -0,0 +1,30 @@
Before:
Save g:ale_go_go111module
call ale#assert#SetUpLinterTest('go', 'revive')
After:
Restore
unlet! b:ale_go_go111module
call ale#assert#TearDownLinterTest()
Execute(The default revive command should be correct):
AssertLinter 'revive', ale#Escape('revive') . ' %t'
Execute(The revive executable should be configurable):
let b:ale_go_revive_executable = 'foobar'
AssertLinter 'foobar', ale#Escape('foobar') . ' %t'
Execute(The revive options should be configurable):
let b:ale_go_revive_options = '--foo'
AssertLinter 'revive', ale#Escape('revive') . ' --foo %t'
Execute(The revive command should support Go environment variables):
let b:ale_go_go111module = 'on'
AssertLinter 'revive',
\ ale#Env('GO111MODULE', 'on') . ale#Escape('revive') . ' %t'

View file

@ -0,0 +1,20 @@
Before:
call ale#assert#SetUpLinterTest('rust', 'analyzer')
After:
call ale#assert#TearDownLinterTest()
Execute(The default executable path should be correct):
AssertLinter 'rust-analyzer', ale#Escape('rust-analyzer')
Execute(The project root should be detected correctly):
AssertLSPProject ''
call ale#test#SetFilename('rust-rls-project/test.rs')
AssertLSPProject ale#path#Simplify(g:dir . '/rust-rls-project')
Execute(Should accept configuration settings):
AssertLSPConfig {}
let b:ale_rust_analyzer_config = {'rust': {'clippy_preference': 'on'}}
AssertLSPConfig {'rust': {'clippy_preference': 'on'}}

View file

@ -0,0 +1,43 @@
Before:
call ale#assert#SetUpLinterTest('typescript', 'standard')
call ale#test#SetFilename('testfile.js')
unlet! b:executable
After:
call ale#assert#TearDownLinterTest()
Execute(bin/cmd.js paths should be preferred):
call ale#test#SetFilename('standard-test-files/with-cmd/testfile.js')
let b:executable = ale#path#Simplify(
\ g:dir
\ . '/standard-test-files/with-cmd/node_modules/standard/bin/cmd.js'
\)
AssertLinter b:executable,
\ (has('win32') ? 'node.exe ' : '')
\ . ale#Escape(b:executable)
\ . ' --stdin %s'
Execute(.bin directories should be used too):
call ale#test#SetFilename('standard-test-files/with-bin/testfile.js')
let b:executable = ale#path#Simplify(
\ g:dir
\ . '/standard-test-files/with-bin/node_modules/.bin/standard'
\)
AssertLinter b:executable, ale#Escape(b:executable) . ' --stdin %s'
Execute(The global executable should be used otherwise):
AssertLinter 'standard', ale#Escape('standard') . ' --stdin %s'
Execute(The global executable should be configurable):
let b:ale_typescript_standard_executable = 'foobar'
AssertLinter 'foobar', ale#Escape('foobar') . ' --stdin %s'
Execute(The options should be configurable):
let b:ale_typescript_standard_options = '--wat'
AssertLinter 'standard', ale#Escape('standard') . ' --wat --stdin %s'

View file

@ -0,0 +1,48 @@
Before:
call ale#assert#SetUpLinterTest('terraform', 'terraform_lsp')
After:
if isdirectory(g:dir . '/.terraform')
call delete(g:dir . '/.terraform', 'd')
endif
unlet! b:ale_terraform_langserver_executable
unlet! b:ale_terraform_langserver_options
call ale#assert#TearDownLinterTest()
Execute(Should send correct LSP language):
AssertLSPLanguage 'terraform'
Execute(Should load default executable):
AssertLinter 'terraform-lsp', ale#Escape('terraform-lsp')
Execute(Should configure custom executable):
let b:ale_terraform_langserver_executable = 'foo'
AssertLinter 'foo', ale#Escape('foo')
Execute(Should set custom options):
let b:ale_terraform_langserver_options = '--bar'
AssertLinter 'terraform-lsp',
\ ale#Escape('terraform-lsp') . ' --bar'
Execute(Should return current directory if it contains .terraform directory):
call mkdir(g:dir . '/.terraform')
AssertLSPProject g:dir
Execute(Should return nearest directory with .terraform if found in parent directory):
call ale#test#SetFilename('../terraform_files/main.tf')
let b:parent_dir = ale#path#Simplify(g:dir . '/..')
let b:tf_dir = b:parent_dir . '/.terraform'
if !isdirectory(b:tf_dir)
call mkdir(b:tf_dir)
endif
AssertLSPProject b:parent_dir
call delete(b:tf_dir, 'd')
unlet!b:parent_dir
unlet!b:tf_dir

View file

@ -0,0 +1,76 @@
" Author: Jeffrey Lau https://github.com/zoonfafer
" Description: Tests for the Vim vimls linter
Before:
call ale#assert#SetUpLinterTest('vim', 'vimls')
After:
if isdirectory(g:dir . '/.git')
call delete(g:dir . '/.git', 'd')
endif
call ale#assert#TearDownLinterTest()
Execute(should set correct defaults):
AssertLinter 'vim-language-server', ale#Escape('vim-language-server') . ' --stdio'
Execute(should set correct LSP values):
call ale#test#SetFilename('vim_fixtures/path_with_autoload/test.vim')
AssertLSPLanguage 'vim'
AssertLSPOptions {}
AssertLSPConfig {}
AssertLSPProject ale#path#Simplify(g:dir . '/vim_fixtures/path_with_autoload')
Execute(should set correct project for .git/):
let b:parent_dir = ale#path#Simplify(g:dir . '/..')
let b:git_dir = b:parent_dir . '/.git'
call ale#test#SetFilename('vim_fixtures/test.vim')
if !isdirectory(b:git_dir)
call mkdir(b:git_dir)
endif
AssertLSPProject ale#path#Simplify(b:parent_dir)
call delete(b:git_dir, 'd')
unlet! b:git_dir
Execute(should set correct project for plugin/):
call ale#test#SetFilename('vim_fixtures/path_with_plugin/test.vim')
AssertLSPProject ale#path#Simplify(g:dir . '/vim_fixtures/path_with_plugin')
Execute(should accept configuration settings):
AssertLSPConfig {}
let b:ale_vim_vimls_config = {'vim': {'foobar': v:true}}
AssertLSPConfig {'vim': {'foobar': v:true}}
Execute(should set correct project for .vimrc):
call ale#test#SetFilename('vim_fixtures/path_with_vimrc/.vimrc')
AssertLSPProject ale#path#Simplify(g:dir . '/vim_fixtures/path_with_vimrc')
Execute(should set correct project for init.vim):
call ale#test#SetFilename('vim_fixtures/path_with_initvim/init.vim')
AssertLSPProject ale#path#Simplify(g:dir . '/vim_fixtures/path_with_initvim')
Execute(should use the local executable when available):
call ale#test#SetFilename('vim_fixtures/file.vim')
AssertLinter ale#path#Simplify(g:dir . '/vim_fixtures/node_modules/.bin/vim-language-server'),
\ ale#Escape(ale#path#Simplify(g:dir . '/vim_fixtures/node_modules/.bin/vim-language-server')) . ' --stdio'
Execute(should let the global executable to be used):
let g:ale_vim_vimls_use_global = 1
call ale#test#SetFilename('vim_fixtures/file.vim')
AssertLinter 'vim-language-server',
\ ale#Escape('vim-language-server') . ' --stdio'
Execute(should let the executable to be configured):
let g:ale_vim_vimls_executable = 'foobar'
AssertLinter 'foobar', ale#Escape('foobar') . ' --stdio'

View file

@ -50,7 +50,8 @@ Before:
let g:handle_code_action_called = 0 let g:handle_code_action_called = 0
function! MockHandleCodeAction() abort function! MockHandleCodeAction() abort
" delfunction! ale#code_action#HandleCodeAction " delfunction! ale#code_action#HandleCodeAction
function! ale#code_action#HandleCodeAction(action) abort function! ale#code_action#HandleCodeAction(action, should_save) abort
AssertEqual v:false, a:should_save
let g:handle_code_action_called += 1 let g:handle_code_action_called += 1
endfunction endfunction
endfunction endfunction
@ -233,7 +234,7 @@ Execute(ale#completion#Show() should make the correct feedkeys() call for manual
AssertEqual [["\<Plug>(ale_show_completion_menu)"]], g:feedkeys_calls AssertEqual [["\<Plug>(ale_show_completion_menu)"]], g:feedkeys_calls
Execute(ale#completion#Show() should not call feedkeys() for other sources): Execute(ale#completion#Show() should not call feedkeys() for other sources):
let b:ale_completion_info = {'source': 'deoplete'} let b:ale_completion_info = {'source': 'other-source'}
call ale#completion#Show([{'word': 'x', 'kind': 'v', 'icase': 1}]) call ale#completion#Show([{'word': 'x', 'kind': 'v', 'icase': 1}])
sleep 1ms sleep 1ms
@ -334,7 +335,7 @@ Execute(b:ale_completion_info should be set up correctly when requesting complet
Execute(b:ale_completion_info should be set up correctly for other sources): Execute(b:ale_completion_info should be set up correctly for other sources):
let b:ale_completion_result = [] let b:ale_completion_result = []
call setpos('.', [bufnr(''), 3, 14, 0]) call setpos('.', [bufnr(''), 3, 14, 0])
call ale#completion#GetCompletions('deoplete') call ale#completion#GetCompletions('ale-callback')
AssertEqual AssertEqual
\ { \ {
@ -344,7 +345,7 @@ Execute(b:ale_completion_info should be set up correctly for other sources):
\ 'line_length': 14, \ 'line_length': 14,
\ 'line': 3, \ 'line': 3,
\ 'prefix': 'ab', \ 'prefix': 'ab',
\ 'source': 'deoplete', \ 'source': 'ale-callback',
\ }, \ },
\ b:ale_completion_info \ b:ale_completion_info
Assert !exists('b:ale_completion_result') Assert !exists('b:ale_completion_result')

View file

@ -17,17 +17,17 @@ Execute(Should handle Rust completion results correctly):
\ {'word': 'from_iter', 'menu': 'fn from_iter<I: IntoIterator<Item = &''a str>>(iter: I) -> String', 'info': '', 'kind': 'f', 'icase': 1}, \ {'word': 'from_iter', 'menu': 'fn from_iter<I: IntoIterator<Item = &''a str>>(iter: I) -> String', 'info': '', 'kind': 'f', 'icase': 1},
\ {'word': 'from_iter', 'menu': 'fn from_iter<I: IntoIterator<Item = String>>(iter: I) -> String', 'info': '', 'kind': 'f', 'icase': 1}, \ {'word': 'from_iter', 'menu': 'fn from_iter<I: IntoIterator<Item = String>>(iter: I) -> String', 'info': '', 'kind': 'f', 'icase': 1},
\ {'word': 'from_iter', 'menu': 'fn from_iter<I: IntoIterator<Item = Cow<''a, str>>>(iter: I) -> String', 'info': '', 'kind': 'f', 'icase': 1}, \ {'word': 'from_iter', 'menu': 'fn from_iter<I: IntoIterator<Item = Cow<''a, str>>>(iter: I) -> String', 'info': '', 'kind': 'f', 'icase': 1},
\ {'word': 'Searcher', 'menu': 'type Searcher = <&''b str as Pattern<''a>>::Searcher;', 'info': '', 'kind': 'f', 'icase': 1}, \ {'word': 'Searcher', 'menu': 'type Searcher = <&''b str as Pattern<''a>>::Searcher;', 'info': '', 'kind': 't', 'icase': 1},
\ {'word': 'default', 'menu': 'fn default() -> String', 'info': '', 'kind': 'f', 'icase': 1}, \ {'word': 'default', 'menu': 'fn default() -> String', 'info': '', 'kind': 'f', 'icase': 1},
\ {'word': 'Output', 'menu': 'type Output = String;', 'info': '', 'kind': 'f', 'icase': 1}, \ {'word': 'Output', 'menu': 'type Output = String;', 'info': '', 'kind': 't', 'icase': 1},
\ {'word': 'Output', 'menu': 'type Output = str;', 'info': '', 'kind': 'f', 'icase': 1}, \ {'word': 'Output', 'menu': 'type Output = str;', 'info': '', 'kind': 't', 'icase': 1},
\ {'word': 'Output', 'menu': 'type Output = str;', 'info': '', 'kind': 'f', 'icase': 1}, \ {'word': 'Output', 'menu': 'type Output = str;', 'info': '', 'kind': 't', 'icase': 1},
\ {'word': 'Output', 'menu': 'type Output = str;', 'info': '', 'kind': 'f', 'icase': 1}, \ {'word': 'Output', 'menu': 'type Output = str;', 'info': '', 'kind': 't', 'icase': 1},
\ {'word': 'Output', 'menu': 'type Output = str;', 'info': '', 'kind': 'f', 'icase': 1}, \ {'word': 'Output', 'menu': 'type Output = str;', 'info': '', 'kind': 't', 'icase': 1},
\ {'word': 'Output', 'menu': 'type Output = str;', 'info': '', 'kind': 'f', 'icase': 1}, \ {'word': 'Output', 'menu': 'type Output = str;', 'info': '', 'kind': 't', 'icase': 1},
\ {'word': 'Output', 'menu': 'type Output = str;', 'info': '', 'kind': 'f', 'icase': 1}, \ {'word': 'Output', 'menu': 'type Output = str;', 'info': '', 'kind': 't', 'icase': 1},
\ {'word': 'Target', 'menu': 'type Target = str;', 'info': '', 'kind': 'f', 'icase': 1}, \ {'word': 'Target', 'menu': 'type Target = str;', 'info': '', 'kind': 't', 'icase': 1},
\ {'word': 'Err', 'menu': 'type Err = ParseError;', 'info': '', 'kind': 'f', 'icase': 1}, \ {'word': 'Err', 'menu': 'type Err = ParseError;', 'info': '', 'kind': 't', 'icase': 1},
\ {'word': 'from_str', 'menu': 'fn from_str(s: &str) -> Result<String, ParseError>', 'info': '', 'kind': 'f', 'icase': 1}, \ {'word': 'from_str', 'menu': 'fn from_str(s: &str) -> Result<String, ParseError>', 'info': '', 'kind': 'f', 'icase': 1},
\ {'word': 'from', 'menu': 'fn from(s: &''a str) -> String', 'info': '', 'kind': 'f', 'icase': 1}, \ {'word': 'from', 'menu': 'fn from(s: &''a str) -> String', 'info': '', 'kind': 'f', 'icase': 1},
\ {'word': 'from', 'menu': 'fn from(s: Box<str>) -> String', 'info': '', 'kind': 'f', 'icase': 1}, \ {'word': 'from', 'menu': 'fn from(s: Box<str>) -> String', 'info': '', 'kind': 'f', 'icase': 1},

View file

@ -36,7 +36,7 @@ Execute(TypeScript completion details responses should be parsed correctly):
\ 'word': 'abc', \ 'word': 'abc',
\ 'menu': '(property) Foo.abc: number', \ 'menu': '(property) Foo.abc: number',
\ 'info': '', \ 'info': '',
\ 'kind': 'f', \ 'kind': 'v',
\ 'icase': 1, \ 'icase': 1,
\ 'dup': g:ale_completion_tsserver_autoimport, \ 'dup': g:ale_completion_tsserver_autoimport,
\ }, \ },
@ -44,7 +44,7 @@ Execute(TypeScript completion details responses should be parsed correctly):
\ 'word': 'def', \ 'word': 'def',
\ 'menu': '(property) Foo.def: number', \ 'menu': '(property) Foo.def: number',
\ 'info': 'foo bar baz', \ 'info': 'foo bar baz',
\ 'kind': 'f', \ 'kind': 'v',
\ 'icase': 1, \ 'icase': 1,
\ 'dup': g:ale_completion_tsserver_autoimport, \ 'dup': g:ale_completion_tsserver_autoimport,
\ }, \ },
@ -52,7 +52,7 @@ Execute(TypeScript completion details responses should be parsed correctly):
\ 'word': 'ghi', \ 'word': 'ghi',
\ 'menu': '(class) Foo', \ 'menu': '(class) Foo',
\ 'info': '', \ 'info': '',
\ 'kind': 'f', \ 'kind': 'v',
\ 'icase': 1, \ 'icase': 1,
\ 'dup': g:ale_completion_tsserver_autoimport, \ 'dup': g:ale_completion_tsserver_autoimport,
\ }, \ },
@ -124,7 +124,7 @@ Execute(Entries without details should be included in the responses):
\ 'word': 'abc', \ 'word': 'abc',
\ 'menu': 'import { def } from "./Foo"; (property) Foo.abc: number', \ 'menu': 'import { def } from "./Foo"; (property) Foo.abc: number',
\ 'info': '', \ 'info': '',
\ 'kind': 'f', \ 'kind': 'v',
\ 'icase': 1, \ 'icase': 1,
\ 'user_data': json_encode({ \ 'user_data': json_encode({
\ 'codeActions': [{ \ 'codeActions': [{
@ -138,7 +138,7 @@ Execute(Entries without details should be included in the responses):
\ 'word': 'def', \ 'word': 'def',
\ 'menu': '(property) Foo.def: number', \ 'menu': '(property) Foo.def: number',
\ 'info': 'foo bar baz', \ 'info': 'foo bar baz',
\ 'kind': 'f', \ 'kind': 'v',
\ 'icase': 1, \ 'icase': 1,
\ 'dup': g:ale_completion_tsserver_autoimport, \ 'dup': g:ale_completion_tsserver_autoimport,
\ }, \ },

View file

@ -0,0 +1,23 @@
Before:
call ale#assert#SetUpFixerTest('nim', 'nimpretty')
After:
call ale#assert#TearDownFixerTest()
Execute(The nimpretty callback should return the correct default values):
AssertEqual
\ {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape('nimpretty') . ' %t --maxLineLen:80'
\ },
\ ale#fixers#nimpretty#Fix(bufnr(''))
Execute(The nimpretty callback should include any additional options):
let g:ale_nim_nimpretty_options = '--some-option'
AssertEqual
\ {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape('nimpretty') . ' %t --some-option'
\ },
\ ale#fixers#nimpretty#Fix(bufnr(''))

View file

@ -21,6 +21,7 @@ After:
unlet! g:config_error_lines unlet! g:config_error_lines
Execute(The eslint handler should parse json correctly): Execute(The eslint handler should parse json correctly):
call ale#test#SetFilename('foo.js')
AssertEqual AssertEqual
\ [ \ [
\ { \ {
@ -53,6 +54,21 @@ Execute(The eslint handler should parse json correctly):
\ '[{"filePath":"foo.js","messages":[{"ruleId":"no-unused-vars","severity":1,"message":"''variable'' is assigned a value but never used.","line":1,"column":7,"nodeType":"Identifier","endLine":1,"endColumn":15},{"ruleId":"semi","severity":1,"message":"Missing semicolon.","line":5,"column":15,"nodeType":"ExpressionStatement","fix":{"range":[46,46],"text":";"}},{"ruleId":"no-redeclare","severity":2,"message":"''variable'' is already defined.","line":7,"column":7,"nodeType":"Identifier","endLine":7,"endColumn":15}],"errorCount":1,"warningCount":3,"fixableErrorCount":0,"fixableWarningCount":1,"source":"const variable = {\n a: 3\n};\n\nconsole.log(1)\n\nclass variable {\n}\n"}]' \ '[{"filePath":"foo.js","messages":[{"ruleId":"no-unused-vars","severity":1,"message":"''variable'' is assigned a value but never used.","line":1,"column":7,"nodeType":"Identifier","endLine":1,"endColumn":15},{"ruleId":"semi","severity":1,"message":"Missing semicolon.","line":5,"column":15,"nodeType":"ExpressionStatement","fix":{"range":[46,46],"text":";"}},{"ruleId":"no-redeclare","severity":2,"message":"''variable'' is already defined.","line":7,"column":7,"nodeType":"Identifier","endLine":7,"endColumn":15}],"errorCount":1,"warningCount":3,"fixableErrorCount":0,"fixableWarningCount":1,"source":"const variable = {\n a: 3\n};\n\nconsole.log(1)\n\nclass variable {\n}\n"}]'
\ ]) \ ])
Execute(The eslint handler should suppress deprecation warnings):
call ale#test#SetFilename('foo.js')
AssertEqual
\ [
\ {
\ 'lnum': 1,
\ 'col': 9,
\ 'text': 'Parsing error: Unexpected token Controller',
\ 'type': 'E',
\ }
\ ],
\ ale#handlers#eslint#HandleJSON(bufnr(''), [
\ '[{"filePath":"foo.js","messages":[{"ruleId":null,"fatal":true,"severity":2 ,"message":"Parsing error: Unexpected token Controller","line":1,"column":9}],"errorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount": 0,"source":"i:mport Controller from \"@ember/controller\";\nimport listViewControllerMixin from \"elearning/mixins/list-view-controller\";\nimport { inject as service } from \"@ember/service\";\n\nexport default Controller.extend(listViewControllerMixin(), {\n modelName: \"notification\",\n intl: service(),\n\n flatpickrLocale: computed(\"intl.locale\", function() {\n return this.intl.locale.firstObject.split(\"-\")[0];\n })\n});\n"}]', '(node:616989) [ESLINT_LEGACY_OBJECT_REST_SPREAD] DeprecationWarning: The ''parserOptions.ecmaFeatures.experimentalObjectRestSpread'' option is deprecated. Use ''parser Options.ecmaVersion'' instead. (found in "node_modules/eslint-plugin-ember/lib/config/base.js")]'
\ ])
Execute(The eslint handler should print a message about a missing configuration file): Execute(The eslint handler should print a message about a missing configuration file):
let g:config_error_lines = [ let g:config_error_lines = [
\ '', \ '',
@ -262,7 +278,7 @@ Execute(Suppressing missing configs shouldn't suppress module import errors):
\ ale#handlers#eslint#HandleJSON(bufnr(''), g:config_error_lines[:]) \ ale#handlers#eslint#HandleJSON(bufnr(''), g:config_error_lines[:])
Execute(The eslint handler should hint about using typescript-eslint-parser): Execute(The eslint handler should hint about using typescript-eslint-parser):
silent! noautocmd file foo.ts call ale#test#SetFilename('foo.ts')
AssertEqual AssertEqual
\ [ \ [
@ -326,7 +342,7 @@ Execute(Failing to connect to eslint_d should be handled correctly):
\ ]) \ ])
Execute(Disabling warnings about trailing spaces should work): Execute(Disabling warnings about trailing spaces should work):
silent! noautocmd file foo.ts call ale#test#SetFilename('foo.js')
AssertEqual AssertEqual
\ [ \ [

View file

@ -1,6 +1,8 @@
Before: Before:
Save g:ale_python_mypy_ignore_invalid_syntax Save g:ale_python_mypy_ignore_invalid_syntax
Save g:ale_python_mypy_show_notes
unlet! g:ale_python_mypy_show_notes
unlet! g:ale_python_mypy_ignore_invalid_syntax unlet! g:ale_python_mypy_ignore_invalid_syntax
runtime ale_linters/python/mypy.vim runtime ale_linters/python/mypy.vim
@ -16,6 +18,8 @@ After:
Execute(The mypy handler should parse lines correctly): Execute(The mypy handler should parse lines correctly):
call ale#test#SetFilename('__init__.py') call ale#test#SetFilename('__init__.py')
let g:ale_python_mypy_show_notes = 0
AssertEqual AssertEqual
\ [ \ [
\ { \ {
@ -69,6 +73,31 @@ Execute(The mypy handler should parse lines correctly):
\ '__init__.py:72:1: warning: Some warning', \ '__init__.py:72:1: warning: Some warning',
\ ]) \ ])
Execute(The mypy handler should show notes if enabled):
call ale#test#SetFilename('__init__.py')
AssertEqual
\ [
\ {
\ 'lnum': 72,
\ 'col': 1,
\ 'filename': ale#path#Simplify(g:dir . '/__init__.py'),
\ 'type': 'I',
\ 'text': 'A note',
\ },
\ ],
\ ale_linters#python#mypy#Handle(bufnr(''), [
\ '__init__.py:72:1: note: A note',
\ ])
let g:ale_python_mypy_show_notes = 0
AssertEqual
\ [],
\ ale_linters#python#mypy#Handle(bufnr(''), [
\ '__init__.py:72:1: note: A note',
\ ])
Execute(The mypy handler should handle Windows names with spaces): Execute(The mypy handler should handle Windows names with spaces):
" This test works on Unix, where this is seen as a single filename " This test works on Unix, where this is seen as a single filename
silent file C:\\something\\with\ spaces.py silent file C:\\something\\with\ spaces.py

View file

@ -22,7 +22,7 @@ Execute(The shellcheck handler should handle basic errors or warnings):
\ 'code': 'SC1068', \ 'code': 'SC1068',
\ }, \ },
\ ], \ ],
\ ale_linters#sh#shellcheck#Handle(bufnr(''), [ \ ale#handlers#shellcheck#Handle(bufnr(''), [
\ '-:2:1: warning: In POSIX sh, ''let'' is not supported. [SC2039]', \ '-:2:1: warning: In POSIX sh, ''let'' is not supported. [SC2039]',
\ '-:2:3: error: Don''t put spaces around the = in assignments. [SC1068]', \ '-:2:3: error: Don''t put spaces around the = in assignments. [SC1068]',
\ ]) \ ])
@ -38,6 +38,6 @@ Execute(The shellcheck handler should handle notes):
\ 'code': 'SC2086', \ 'code': 'SC2086',
\ }, \ },
\ ], \ ],
\ ale_linters#sh#shellcheck#Handle(bufnr(''), [ \ ale#handlers#shellcheck#Handle(bufnr(''), [
\ '-:3:3: note: Double quote to prevent globbing and word splitting. [SC2086]', \ '-:3:3: note: Double quote to prevent globbing and word splitting. [SC2086]',
\ ]) \ ])

View file

@ -0,0 +1,48 @@
Before:
runtime ale_linters/verilog/verilator.vim
After:
call ale#linter#Reset()
Execute (The verilator handler should parse legacy messages with only line numbers):
AssertEqual
\ [
\ {
\ 'lnum': 3,
\ 'type': 'E',
\ 'text': 'syntax error, unexpected IDENTIFIER'
\ },
\ {
\ 'lnum': 10,
\ 'type': 'W',
\ 'text': 'Blocking assignments (=) in sequential (flop or latch) block; suggest delayed assignments (<=).'
\ },
\ ],
\ ale_linters#verilog#verilator#Handle(bufnr(''), [
\ '%Error: foo_verilator_linted.v:3: syntax error, unexpected IDENTIFIER',
\ '%Warning-BLKSEQ: bar_verilator_linted.v:10: Blocking assignments (=) in sequential (flop or latch) block; suggest delayed assignments (<=).',
\ ])
Execute (The verilator handler should parse new format messages with line and column numbers):
AssertEqual
\ [
\ {
\ 'lnum': 3,
\ 'col' : 1,
\ 'type': 'E',
\ 'text': 'syntax error, unexpected endmodule, expecting ;'
\ },
\ {
\ 'lnum': 4,
\ 'col' : 6,
\ 'type': 'W',
\ 'text': 'Signal is not used: r'
\ },
\ ],
\ ale_linters#verilog#verilator#Handle(bufnr(''), [
\ '%Error: bar_verilator_linted.v:3:1: syntax error, unexpected endmodule, expecting ;',
\ '%Warning-UNUSED: foo_verilator_linted.v:4:6: Signal is not used: r',
\ ])

View file

@ -8,15 +8,20 @@ ale_module = imp.load_source(
class VimMock(object): class VimMock(object):
def __init__(self, call_list, call_results): def __init__(self, call_list, call_results, commands):
self.__call_list = call_list self.__call_list = call_list
self.__call_results = call_results self.__call_results = call_results
self.__commands = commands
def call(self, function, *args): def call(self, function, *args):
self.__call_list.append((function, args)) self.__call_list.append((function, args))
return self.__call_results.get(function, 0) return self.__call_results.get(function, 0)
def command(self, command):
self.__commands.append(command)
class DeopleteSourceTest(unittest.TestCase): class DeopleteSourceTest(unittest.TestCase):
def setUp(self): def setUp(self):
@ -24,8 +29,10 @@ class DeopleteSourceTest(unittest.TestCase):
self.call_list = [] self.call_list = []
self.call_results = {'ale#completion#CanProvideCompletions': 1} self.call_results = {'ale#completion#CanProvideCompletions': 1}
self.commands = []
self.source = ale_module.Source('vim') self.source = ale_module.Source('vim')
self.source.vim = VimMock(self.call_list, self.call_results) self.source.vim = VimMock(
self.call_list, self.call_results, self.commands)
def test_attributes(self): def test_attributes(self):
""" """
@ -48,6 +55,7 @@ class DeopleteSourceTest(unittest.TestCase):
'cpp': r'(\.|::|->)\w*$', 'cpp': r'(\.|::|->)\w*$',
}, },
'is_bytepos': True, 'is_bytepos': True,
'is_volatile': True,
'mark': '[L]', 'mark': '[L]',
'min_pattern_length': 1, 'min_pattern_length': 1,
'name': 'ale', 'name': 'ale',
@ -64,70 +72,28 @@ class DeopleteSourceTest(unittest.TestCase):
]) ])
def test_request_completion_results(self): def test_request_completion_results(self):
context = {'is_async': False} context = {'event': 'TextChangedI', 'is_refresh': True}
self.assertEqual(self.source.gather_candidates(context), []) self.assertEqual(self.source.gather_candidates(context), [])
self.assertEqual(context, {'is_async': True})
self.assertEqual(self.call_list, [ self.assertEqual(self.call_list, [
('ale#completion#CanProvideCompletions', ()), ('ale#completion#CanProvideCompletions', ()),
('ale#completion#GetCompletions', ('deoplete',)), ])
self.assertEqual(self.commands, [
"call ale#completion#GetCompletions('ale-callback', " + \
"{'callback': {completions -> deoplete#auto_complete() }})"
]) ])
def test_request_completion_results_from_buffer_without_providers(self): def test_request_completion_results_from_buffer_without_providers(self):
self.call_results['ale#completion#CanProvideCompletions'] = 0 self.call_results['ale#completion#CanProvideCompletions'] = 0
context = {'is_async': False} context = {'event': 'TextChangedI', 'is_refresh': True}
self.assertIsNone(self.source.gather_candidates(context), []) self.assertIsNone(self.source.gather_candidates(context), [])
self.assertEqual(context, {'is_async': False})
self.assertEqual(self.call_list, [ self.assertEqual(self.call_list, [
('ale#completion#CanProvideCompletions', ()), ('ale#completion#CanProvideCompletions', ()),
]) ])
def test_refresh_completion_results(self): def test_async_event(self):
context = {'is_async': False} context = {'event': 'Async', 'is_refresh': True}
self.assertEqual(self.source.gather_candidates(context), [])
self.assertEqual(context, {'is_async': True})
self.assertEqual(self.call_list, [
('ale#completion#CanProvideCompletions', ()),
('ale#completion#GetCompletions', ('deoplete',)),
])
context = {'is_async': True, 'is_refresh': True}
self.assertEqual(self.source.gather_candidates(context), [])
self.assertEqual(context, {'is_async': True, 'is_refresh': True})
self.assertEqual(self.call_list, [
('ale#completion#CanProvideCompletions', ()),
('ale#completion#GetCompletions', ('deoplete',)),
('ale#completion#CanProvideCompletions', ()),
('ale#completion#GetCompletions', ('deoplete',)),
])
def test_poll_no_result(self):
context = {'is_async': True}
self.call_results['ale#completion#GetCompletionResult'] = None
self.assertEqual(self.source.gather_candidates(context), [])
self.assertEqual(context, {'is_async': True})
self.assertEqual(self.call_list, [
('ale#completion#CanProvideCompletions', ()),
('ale#completion#GetCompletionResult', ()),
])
def test_poll_empty_result_ready(self):
context = {'is_async': True}
self.call_results['ale#completion#GetCompletionResult'] = []
self.assertEqual(self.source.gather_candidates(context), [])
self.assertEqual(context, {'is_async': False})
self.assertEqual(self.call_list, [
('ale#completion#CanProvideCompletions', ()),
('ale#completion#GetCompletionResult', ()),
])
def test_poll_non_empty_result_ready(self):
context = {'is_async': True}
self.call_results['ale#completion#GetCompletionResult'] = [ self.call_results['ale#completion#GetCompletionResult'] = [
{ {
'word': 'foobar', 'word': 'foobar',
@ -147,7 +113,7 @@ class DeopleteSourceTest(unittest.TestCase):
'info': '', 'info': '',
}, },
]) ])
self.assertEqual(context, {'is_async': False})
self.assertEqual(self.call_list, [ self.assertEqual(self.call_list, [
('ale#completion#CanProvideCompletions', ()), ('ale#completion#CanProvideCompletions', ()),
('ale#completion#GetCompletionResult', ()), ('ale#completion#GetCompletionResult', ()),

View file

@ -32,7 +32,7 @@ Before:
function! CollectSigns() function! CollectSigns()
redir => l:output redir => l:output
if has('nvim-0.4.2') || (v:version >= 801 && has('patch614')) if has('nvim-0.4.2') || has('patch-8.1.614')
silent exec 'sign place group=ale' silent exec 'sign place group=ale'
else else
silent exec 'sign place' silent exec 'sign place'

View file

@ -1,5 +1,5 @@
Execute (Parsing English signs should work): Execute (Parsing English signs should work):
if has('nvim-0.4.2') || (v:version >= 801 && has('patch614')) if has('nvim-0.4.2') || has('patch-8.1.614')
AssertEqual AssertEqual
\ [0, [[9, 1000001, 'ALEWarningSign']]], \ [0, [[9, 1000001, 'ALEWarningSign']]],
\ ale#sign#ParseSigns([ \ ale#sign#ParseSigns([
@ -16,7 +16,7 @@ Execute (Parsing English signs should work):
endif endif
Execute (Parsing Russian signs should work): Execute (Parsing Russian signs should work):
if has('nvim-0.4.2') || (v:version >= 801 && has('patch614')) if has('nvim-0.4.2') || has('patch-8.1.614')
AssertEqual AssertEqual
\ [0, [[1, 1000001, 'ALEErrorSign']]], \ [0, [[1, 1000001, 'ALEErrorSign']]],
\ ale#sign#ParseSigns([' строка=1 id=1000001 группа=ale имя=ALEErrorSign']) \ ale#sign#ParseSigns([' строка=1 id=1000001 группа=ale имя=ALEErrorSign'])
@ -27,7 +27,7 @@ Execute (Parsing Russian signs should work):
endif endif
Execute (Parsing Japanese signs should work): Execute (Parsing Japanese signs should work):
if has('nvim-0.4.2') || (v:version >= 801 && has('patch614')) if has('nvim-0.4.2') || has('patch-8.1.614')
AssertEqual AssertEqual
\ [0, [[1, 1000001, 'ALEWarningSign']]], \ [0, [[1, 1000001, 'ALEWarningSign']]],
\ ale#sign#ParseSigns([' 行=1 識別子=1000001 グループ=ale 名前=ALEWarningSign']) \ ale#sign#ParseSigns([' 行=1 識別子=1000001 グループ=ale 名前=ALEWarningSign'])
@ -38,7 +38,7 @@ Execute (Parsing Japanese signs should work):
endif endif
Execute (Parsing Spanish signs should work): Execute (Parsing Spanish signs should work):
if has('nvim-0.4.2') || (v:version >= 801 && has('patch614')) if has('nvim-0.4.2') || has('patch-8.1.614')
AssertEqual AssertEqual
\ [0, [[12, 1000001, 'ALEWarningSign']]], \ [0, [[12, 1000001, 'ALEWarningSign']]],
\ ale#sign#ParseSigns([' línea=12 id=1000001 grupo=ale nombre=ALEWarningSign']) \ ale#sign#ParseSigns([' línea=12 id=1000001 grupo=ale nombre=ALEWarningSign'])
@ -49,7 +49,7 @@ Execute (Parsing Spanish signs should work):
endif endif
Execute (Parsing Italian signs should work): Execute (Parsing Italian signs should work):
if has('nvim-0.4.2') || (v:version >= 801 && has('patch614')) if has('nvim-0.4.2') || has('patch-8.1.614')
AssertEqual AssertEqual
\ [0, [[1, 1000001, 'ALEWarningSign']]], \ [0, [[1, 1000001, 'ALEWarningSign']]],
\ ale#sign#ParseSigns([' riga=1 id=1000001, gruppo=ale nome=ALEWarningSign']) \ ale#sign#ParseSigns([' riga=1 id=1000001, gruppo=ale nome=ALEWarningSign'])
@ -60,7 +60,7 @@ Execute (Parsing Italian signs should work):
endif endif
Execute (Parsing German signs should work): Execute (Parsing German signs should work):
if has('nvim-0.4.2') || (v:version >= 801 && has('patch614')) if has('nvim-0.4.2') || has('patch-8.1.614')
AssertEqual AssertEqual
\ [0, [[235, 1000001, 'ALEErrorSign']]], \ [0, [[235, 1000001, 'ALEErrorSign']]],
\ ale#sign#ParseSigns([' Zeile=235 id=1000001 Gruppe=ale Name=ALEErrorSign']) \ ale#sign#ParseSigns([' Zeile=235 id=1000001 Gruppe=ale Name=ALEErrorSign'])
@ -71,7 +71,7 @@ Execute (Parsing German signs should work):
endif endif
Execute (The sign parser should indicate if the dummy sign is set): Execute (The sign parser should indicate if the dummy sign is set):
if has('nvim-0.4.2') || (v:version >= 801 && has('patch614')) if has('nvim-0.4.2') || has('patch-8.1.614')
AssertEqual AssertEqual
\ [1, [[1, 1000001, 'ALEErrorSign']]], \ [1, [[1, 1000001, 'ALEErrorSign']]],
\ ale#sign#ParseSigns([ \ ale#sign#ParseSigns([

View file

@ -68,7 +68,7 @@ Before:
function! ParseSigns() function! ParseSigns()
redir => l:output redir => l:output
if has('nvim-0.4.2') || (v:version >= 801 && has('patch614')) if has('nvim-0.4.2') || has('patch-8.1.614')
silent sign place group=ale silent sign place group=ale
else else
silent sign place silent sign place
@ -152,7 +152,7 @@ Execute(The current signs should be set for running a job):
\ ParseSigns() \ ParseSigns()
Execute(Loclist items with sign_id values should be kept): Execute(Loclist items with sign_id values should be kept):
if has('nvim-0.4.2') || (v:version >= 801 && has('patch614')) if has('nvim-0.4.2') || has('patch-8.1.614')
exec 'sign place 1000347 group=ale line=3 name=ALEErrorSign buffer=' . bufnr('') exec 'sign place 1000347 group=ale line=3 name=ALEErrorSign buffer=' . bufnr('')
exec 'sign place 1000348 group=ale line=15 name=ALEErrorSign buffer=' . bufnr('') exec 'sign place 1000348 group=ale line=15 name=ALEErrorSign buffer=' . bufnr('')
exec 'sign place 1000349 group=ale line=16 name=ALEWarningSign buffer=' . bufnr('') exec 'sign place 1000349 group=ale line=16 name=ALEWarningSign buffer=' . bufnr('')
@ -297,7 +297,7 @@ Execute(No exceptions should be thrown when setting signs for invalid buffers):
Execute(Signs should be removed when lines have multiple sign IDs on them): Execute(Signs should be removed when lines have multiple sign IDs on them):
" We can fail to remove signs if there are multiple signs on one line, " We can fail to remove signs if there are multiple signs on one line,
" say after deleting lines in Vim, etc. " say after deleting lines in Vim, etc.
if has('nvim-0.4.2') || (v:version >= 801 && has('patch614')) if has('nvim-0.4.2') || has('patch-8.1.614')
exec 'sign place 1000347 group=ale line=3 name=ALEErrorSign buffer=' . bufnr('') exec 'sign place 1000347 group=ale line=3 name=ALEErrorSign buffer=' . bufnr('')
exec 'sign place 1000348 group=ale line=3 name=ALEWarningSign buffer=' . bufnr('') exec 'sign place 1000348 group=ale line=3 name=ALEWarningSign buffer=' . bufnr('')
exec 'sign place 1000349 group=ale line=10 name=ALEErrorSign buffer=' . bufnr('') exec 'sign place 1000349 group=ale line=10 name=ALEErrorSign buffer=' . bufnr('')

View file

View file

@ -37,10 +37,10 @@ Before:
After: After:
" Close the extra buffers if we opened it. " Close the extra buffers if we opened it.
if bufnr(g:file1) != -1 if bufnr(g:file1) != -1
execute ':bp | :bd ' . bufnr(g:file1) execute ':bp! | :bd! ' . bufnr(g:file1)
endif endif
if bufnr(g:file2) != -1 if bufnr(g:file2) != -1
execute ':bp | :bd ' . bufnr(g:file2) execute ':bp! | :bd! ' . bufnr(g:file2)
endif endif
if filereadable(g:file1) if filereadable(g:file1)
@ -116,7 +116,7 @@ Execute(It should modify and save multiple files):
\ 'newText': "import {A, B} from 'module'\n\n", \ 'newText': "import {A, B} from 'module'\n\n",
\ }] \ }]
\ }], \ }],
\}) \}, v:true)
AssertEqual [ AssertEqual [
\ 'class Value {', \ 'class Value {',
@ -161,7 +161,7 @@ Execute(Beginning of file can be modified):
\ 'newText': "type A: string\ntype B: number\n", \ 'newText': "type A: string\ntype B: number\n",
\ }], \ }],
\ }] \ }]
\}) \}, v:true)
AssertEqual [ AssertEqual [
\ 'type A: string', \ 'type A: string',
@ -192,7 +192,7 @@ Execute(End of file can be modified):
\ 'newText': "type A: string\ntype B: number\n", \ 'newText': "type A: string\ntype B: number\n",
\ }], \ }],
\ }] \ }]
\}) \}, v:true)
AssertEqual g:test.text + [ AssertEqual g:test.text + [
\ 'type A: string', \ 'type A: string',
@ -227,7 +227,7 @@ Execute(Current buffer contents will be reloaded):
\ 'newText': "type A: string\ntype B: number\n", \ 'newText': "type A: string\ntype B: number\n",
\ }], \ }],
\ }] \ }]
\}) \}, v:true)
AssertEqual [ AssertEqual [
\ 'type A: string', \ 'type A: string',
@ -249,11 +249,11 @@ Execute(Cursor will not move when it is before text change):
let g:test.changes = g:test.create_change(2, 3, 2, 8, 'value2') let g:test.changes = g:test.create_change(2, 3, 2, 8, 'value2')
call setpos('.', [0, 1, 1, 0]) call setpos('.', [0, 1, 1, 0])
call ale#code_action#HandleCodeAction(g:test.changes) call ale#code_action#HandleCodeAction(g:test.changes, v:true)
AssertEqual [1, 1], getpos('.')[1:2] AssertEqual [1, 1], getpos('.')[1:2]
call setpos('.', [0, 2, 2, 0]) call setpos('.', [0, 2, 2, 0])
call ale#code_action#HandleCodeAction(g:test.changes) call ale#code_action#HandleCodeAction(g:test.changes, v:true)
AssertEqual [2, 2], getpos('.')[1:2] AssertEqual [2, 2], getpos('.')[1:2]
# ====C==== # ====C====
@ -264,7 +264,7 @@ Execute(Cursor column will move to the change end when cursor between start/end)
call WriteFileAndEdit() call WriteFileAndEdit()
call setpos('.', [0, 2, r, 0]) call setpos('.', [0, 2, r, 0])
AssertEqual ' value: string', getline('.') AssertEqual ' value: string', getline('.')
call ale#code_action#HandleCodeAction(g:test.changes) call ale#code_action#HandleCodeAction(g:test.changes, v:true)
AssertEqual ' value2: string', getline('.') AssertEqual ' value2: string', getline('.')
AssertEqual [2, 9], getpos('.')[1:2] AssertEqual [2, 9], getpos('.')[1:2]
endfor endfor
@ -275,7 +275,8 @@ Execute(Cursor column will move back when new text is shorter):
call WriteFileAndEdit() call WriteFileAndEdit()
call setpos('.', [0, 2, 8, 0]) call setpos('.', [0, 2, 8, 0])
AssertEqual ' value: string', getline('.') AssertEqual ' value: string', getline('.')
call ale#code_action#HandleCodeAction(g:test.create_change(2, 3, 2, 8, 'val')) call ale#code_action#HandleCodeAction(
\ g:test.create_change(2, 3, 2, 8, 'val'), v:true)
AssertEqual ' val: string', getline('.') AssertEqual ' val: string', getline('.')
AssertEqual [2, 6], getpos('.')[1:2] AssertEqual [2, 6], getpos('.')[1:2]
@ -286,7 +287,8 @@ Execute(Cursor column will move forward when new text is longer):
call setpos('.', [0, 2, 8, 0]) call setpos('.', [0, 2, 8, 0])
AssertEqual ' value: string', getline('.') AssertEqual ' value: string', getline('.')
call ale#code_action#HandleCodeAction(g:test.create_change(2, 3, 2, 8, 'longValue')) call ale#code_action#HandleCodeAction(
\ g:test.create_change(2, 3, 2, 8, 'longValue'), v:true)
AssertEqual ' longValue: string', getline('.') AssertEqual ' longValue: string', getline('.')
AssertEqual [2, 12], getpos('.')[1:2] AssertEqual [2, 12], getpos('.')[1:2]
@ -297,7 +299,8 @@ Execute(Cursor line will move when updates are happening on lines above):
call WriteFileAndEdit() call WriteFileAndEdit()
call setpos('.', [0, 3, 1, 0]) call setpos('.', [0, 3, 1, 0])
AssertEqual '}', getline('.') AssertEqual '}', getline('.')
call ale#code_action#HandleCodeAction(g:test.create_change(1, 1, 2, 1, "test\ntest\n")) call ale#code_action#HandleCodeAction(
\ g:test.create_change(1, 1, 2, 1, "test\ntest\n"), v:true)
AssertEqual '}', getline('.') AssertEqual '}', getline('.')
AssertEqual [4, 1], getpos('.')[1:2] AssertEqual [4, 1], getpos('.')[1:2]
@ -308,7 +311,8 @@ Execute(Cursor line and column will move when change on lines above and just bef
call WriteFileAndEdit() call WriteFileAndEdit()
call setpos('.', [0, 2, 2, 0]) call setpos('.', [0, 2, 2, 0])
AssertEqual ' value: string', getline('.') AssertEqual ' value: string', getline('.')
call ale#code_action#HandleCodeAction(g:test.create_change(1, 1, 2, 1, "test\ntest\n123")) call ale#code_action#HandleCodeAction(
\ g:test.create_change(1, 1, 2, 1, "test\ntest\n123"), v:true)
AssertEqual '123 value: string', getline('.') AssertEqual '123 value: string', getline('.')
AssertEqual [3, 5], getpos('.')[1:2] AssertEqual [3, 5], getpos('.')[1:2]
@ -319,7 +323,8 @@ Execute(Cursor line and column will move at the end of changes):
call WriteFileAndEdit() call WriteFileAndEdit()
call setpos('.', [0, 2, 10, 0]) call setpos('.', [0, 2, 10, 0])
AssertEqual ' value: string', getline('.') AssertEqual ' value: string', getline('.')
call ale#code_action#HandleCodeAction(g:test.create_change(1, 1, 3, 1, "test\n")) call ale#code_action#HandleCodeAction(
\ g:test.create_change(1, 1, 3, 1, "test\n"), v:true)
AssertEqual '}', getline('.') AssertEqual '}', getline('.')
AssertEqual [2, 1], getpos('.')[1:2] AssertEqual [2, 1], getpos('.')[1:2]
@ -329,6 +334,19 @@ Execute(Cursor will not move when changes happening on lines >= cursor, but afte
call WriteFileAndEdit() call WriteFileAndEdit()
call setpos('.', [0, 2, 3, 0]) call setpos('.', [0, 2, 3, 0])
AssertEqual ' value: string', getline('.') AssertEqual ' value: string', getline('.')
call ale#code_action#HandleCodeAction(g:test.create_change(2, 10, 3, 1, "number\n")) call ale#code_action#HandleCodeAction(
\ g:test.create_change(2, 10, 3, 1, "number\n"), v:true)
AssertEqual ' value: number', getline('.') AssertEqual ' value: number', getline('.')
AssertEqual [2, 3], getpos('.')[1:2] AssertEqual [2, 3], getpos('.')[1:2]
Execute(It should just modify file when should_save is set to v:false):
call WriteFileAndEdit()
let g:test.change = g:test.create_change(1, 1, 1, 1, "import { writeFile } from 'fs';\n")
call ale#code_action#HandleCodeAction(g:test.change, v:false)
AssertEqual 1, getbufvar(bufnr(''), '&modified')
AssertEqual [
\ 'import { writeFile } from ''fs'';',
\ 'class Name {',
\ ' value: string',
\ '}',
\], getline(1, '$')

View file

@ -15,7 +15,7 @@ Before:
\ 'col': 10, \ 'col': 10,
\ 'bufnr': bufnr('%'), \ 'bufnr': bufnr('%'),
\ 'vcol': 0, \ 'vcol': 0,
\ 'linter_name': 'eslint', \ 'linter_name': 'bettercode',
\ 'nr': -1, \ 'nr': -1,
\ 'type': 'W', \ 'type': 'W',
\ 'code': 'semi', \ 'code': 'semi',
@ -26,7 +26,7 @@ Before:
\ 'col': 10, \ 'col': 10,
\ 'bufnr': bufnr('%'), \ 'bufnr': bufnr('%'),
\ 'vcol': 0, \ 'vcol': 0,
\ 'linter_name': 'eslint', \ 'linter_name': 'bettercode',
\ 'nr': -1, \ 'nr': -1,
\ 'type': 'E', \ 'type': 'E',
\ 'code': 'semi', \ 'code': 'semi',
@ -38,7 +38,7 @@ Before:
\ 'col': 14, \ 'col': 14,
\ 'bufnr': bufnr('%'), \ 'bufnr': bufnr('%'),
\ 'vcol': 0, \ 'vcol': 0,
\ 'linter_name': 'eslint', \ 'linter_name': 'bettercode',
\ 'nr': -1, \ 'nr': -1,
\ 'type': 'I', \ 'type': 'I',
\ 'text': 'Some information', \ 'text': 'Some information',
@ -48,7 +48,7 @@ Before:
\ 'col': 10, \ 'col': 10,
\ 'bufnr': bufnr('%'), \ 'bufnr': bufnr('%'),
\ 'vcol': 0, \ 'vcol': 0,
\ 'linter_name': 'eslint', \ 'linter_name': 'bettercode',
\ 'nr': -1, \ 'nr': -1,
\ 'type': 'W', \ 'type': 'W',
\ 'code': 'space-infix-ops', \ 'code': 'space-infix-ops',
@ -59,7 +59,7 @@ Before:
\ 'col': 15, \ 'col': 15,
\ 'bufnr': bufnr('%'), \ 'bufnr': bufnr('%'),
\ 'vcol': 0, \ 'vcol': 0,
\ 'linter_name': 'eslint', \ 'linter_name': 'bettercode',
\ 'nr': -1, \ 'nr': -1,
\ 'type': 'E', \ 'type': 'E',
\ 'code': 'radix', \ 'code': 'radix',
@ -70,7 +70,7 @@ Before:
\ 'col': 1, \ 'col': 1,
\ 'bufnr': bufnr('%'), \ 'bufnr': bufnr('%'),
\ 'vcol': 0, \ 'vcol': 0,
\ 'linter_name': 'eslint', \ 'linter_name': 'bettercode',
\ 'nr': -1, \ 'nr': -1,
\ 'type': 'E', \ 'type': 'E',
\ 'text': 'lowercase error', \ 'text': 'lowercase error',
@ -196,7 +196,7 @@ Execute(The linter name should be formatted into the message correctly):
call ale#cursor#EchoCursorWarning() call ale#cursor#EchoCursorWarning()
AssertEqual AssertEqual
\ 'eslint: Infix operators must be spaced.', \ 'bettercode: Infix operators must be spaced.',
\ GetLastMessage() \ GetLastMessage()
Execute(The severity should be formatted into the message correctly): Execute(The severity should be formatted into the message correctly):

View file

@ -57,13 +57,25 @@ Execute(eslint.js executables should be run with node on Windows):
" We have to execute the file with node. " We have to execute the file with node.
if has('win32') if has('win32')
AssertEqual AssertEqual
\ ale#Escape('node.exe') . ' ' \ ale#path#CdString(ale#path#Simplify(g:dir . '/eslint-test-files/react-app'))
\ . ale#Escape('node.exe') . ' '
\ . ale#Escape(ale#path#Simplify(g:dir . '/eslint-test-files/react-app/node_modules/eslint/bin/eslint.js')) \ . ale#Escape(ale#path#Simplify(g:dir . '/eslint-test-files/react-app/node_modules/eslint/bin/eslint.js'))
\ . ' -f json --stdin --stdin-filename %s', \ . ' -f json --stdin --stdin-filename %s',
\ ale#handlers#eslint#GetCommand(bufnr('')) \ ale#handlers#eslint#GetCommand(bufnr(''))
else else
AssertEqual AssertEqual
\ ale#Escape(ale#path#Simplify(g:dir . '/eslint-test-files/react-app/node_modules/eslint/bin/eslint.js')) \ ale#path#CdString(ale#path#Simplify(g:dir . '/eslint-test-files/react-app'))
\ . ale#Escape(ale#path#Simplify(g:dir . '/eslint-test-files/react-app/node_modules/eslint/bin/eslint.js'))
\ . ' -f json --stdin --stdin-filename %s', \ . ' -f json --stdin --stdin-filename %s',
\ ale#handlers#eslint#GetCommand(bufnr('')) \ ale#handlers#eslint#GetCommand(bufnr(''))
endif endif
Execute(eslint.js executables can be run outside project dir):
" Set filename above eslint-test-files (which contains node_modules)
call ale#test#SetFilename('testfile.js')
" cd "..." not present, since project root not found (from node_modules)
AssertEqual
\ ale#Escape(ale#handlers#eslint#GetExecutable(bufnr('')))
\ . ' -f json --stdin --stdin-filename %s',
\ ale#handlers#eslint#GetCommand(bufnr(''))

View file

@ -2,6 +2,8 @@ Before:
call ale#test#SetDirectory('/testplugin/test') call ale#test#SetDirectory('/testplugin/test')
call ale#test#SetFilename('dummy.txt') call ale#test#SetFilename('dummy.txt')
Save g:ale_default_navigation
let g:old_filename = expand('%:p') let g:old_filename = expand('%:p')
let g:Callback = '' let g:Callback = ''
let g:expr_list = [] let g:expr_list = []
@ -12,6 +14,7 @@ Before:
let g:capability_checked = '' let g:capability_checked = ''
let g:conn_id = v:null let g:conn_id = v:null
let g:InitCallback = v:null let g:InitCallback = v:null
let g:ale_default_navigation = 'buffer'
runtime autoload/ale/lsp_linter.vim runtime autoload/ale/lsp_linter.vim
runtime autoload/ale/lsp.vim runtime autoload/ale/lsp.vim
@ -63,6 +66,8 @@ Before:
endfunction endfunction
After: After:
Restore
if g:conn_id isnot v:null if g:conn_id isnot v:null
call ale#lsp#RemoveConnectionWithID(g:conn_id) call ale#lsp#RemoveConnectionWithID(g:conn_id)
endif endif
@ -152,6 +157,20 @@ Execute(Results should be shown for tsserver responses):
\ g:item_list \ g:item_list
AssertEqual {}, ale#references#GetMap() AssertEqual {}, ale#references#GetMap()
" We should be able to repeat selections with ALERepeatSelection
let g:ale_item_list = []
ALERepeatSelection
AssertEqual
\ [
\ {'filename': '/foo/bar/app.ts', 'column': 9, 'line': 9, 'match': 'import {doSomething} from ''./whatever'''},
\ {'filename': '/foo/bar/app.ts', 'column': 3, 'line': 804, 'match': 'doSomething()'},
\ {'filename': '/foo/bar/other/app.ts', 'column': 3, 'line': 51, 'match': 'doSomething()'},
\ ],
\ g:item_list
AssertEqual {}, ale#references#GetMap()
Execute(The preview window should not be opened for empty tsserver responses): Execute(The preview window should not be opened for empty tsserver responses):
call ale#references#SetMap({3: {}}) call ale#references#SetMap({3: {}})
call ale#references#HandleTSServerResponse(1, { call ale#references#HandleTSServerResponse(1, {
@ -195,7 +214,7 @@ Execute(tsserver reference requests should be sent):
\ [0, 'ts@references', {'file': expand('%:p'), 'line': 2, 'offset': 5}] \ [0, 'ts@references', {'file': expand('%:p'), 'line': 2, 'offset': 5}]
\ ], \ ],
\ g:message_list \ g:message_list
AssertEqual {'42': {'use_relative_paths': 0}}, ale#references#GetMap() AssertEqual {'42': {'open_in': 'current-buffer', 'use_relative_paths': 0}}, ale#references#GetMap()
Execute('-relative' argument should enable 'use_relative_paths' in HandleTSServerResponse): Execute('-relative' argument should enable 'use_relative_paths' in HandleTSServerResponse):
runtime ale_linters/typescript/tsserver.vim runtime ale_linters/typescript/tsserver.vim
@ -205,7 +224,48 @@ Execute('-relative' argument should enable 'use_relative_paths' in HandleTSServe
call g:InitCallback() call g:InitCallback()
AssertEqual {'42': {'use_relative_paths': 1}}, ale#references#GetMap() AssertEqual {'42': {'open_in': 'current-buffer', 'use_relative_paths': 1}}, ale#references#GetMap()
Execute(`-tab` should display results in tabs):
runtime ale_linters/typescript/tsserver.vim
call setpos('.', [bufnr(''), 2, 5, 0])
ALEFindReferences -tab
call g:InitCallback()
AssertEqual {'42': {'open_in': 'tab', 'use_relative_paths': 0}}, ale#references#GetMap()
Execute(The default navigation type should be used):
runtime ale_linters/typescript/tsserver.vim
call setpos('.', [bufnr(''), 2, 5, 0])
let g:ale_default_navigation = 'tab'
ALEFindReferences
call g:InitCallback()
AssertEqual {'42': {'open_in': 'tab', 'use_relative_paths': 0}}, ale#references#GetMap()
Execute(`-split` should display results in splits):
runtime ale_linters/typescript/tsserver.vim
call setpos('.', [bufnr(''), 2, 5, 0])
ALEFindReferences -split
call g:InitCallback()
AssertEqual {'42': {'open_in': 'split', 'use_relative_paths': 0}}, ale#references#GetMap()
Execute(`-vsplit` should display results in vsplits):
runtime ale_linters/typescript/tsserver.vim
call setpos('.', [bufnr(''), 2, 5, 0])
ALEFindReferences -vsplit
call g:InitCallback()
AssertEqual {'42': {'open_in': 'vsplit', 'use_relative_paths': 0}}, ale#references#GetMap()
Given python(Some Python file): Given python(Some Python file):
foo foo
@ -302,7 +362,7 @@ Execute(LSP reference requests should be sent):
\ ], \ ],
\ g:message_list \ g:message_list
AssertEqual {'42': {'use_relative_paths': 0}}, ale#references#GetMap() AssertEqual {'42': {'open_in': 'current-buffer', 'use_relative_paths': 0}}, ale#references#GetMap()
Execute('-relative' argument should enable 'use_relative_paths' in HandleLSPResponse): Execute('-relative' argument should enable 'use_relative_paths' in HandleLSPResponse):
runtime ale_linters/python/pyls.vim runtime ale_linters/python/pyls.vim
@ -313,4 +373,4 @@ Execute('-relative' argument should enable 'use_relative_paths' in HandleLSPResp
call g:InitCallback() call g:InitCallback()
AssertEqual {'42': {'use_relative_paths': 1}}, ale#references#GetMap() AssertEqual {'42': {'open_in': 'current-buffer', 'use_relative_paths': 1}}, ale#references#GetMap()

View file

@ -2,6 +2,8 @@ Before:
call ale#test#SetDirectory('/testplugin/test') call ale#test#SetDirectory('/testplugin/test')
call ale#test#SetFilename('dummy.txt') call ale#test#SetFilename('dummy.txt')
Save g:ale_default_navigation
let g:old_filename = expand('%:p') let g:old_filename = expand('%:p')
let g:Callback = '' let g:Callback = ''
let g:message_list = [] let g:message_list = []
@ -9,6 +11,7 @@ Before:
let g:capability_checked = '' let g:capability_checked = ''
let g:conn_id = v:null let g:conn_id = v:null
let g:InitCallback = v:null let g:InitCallback = v:null
let g:ale_default_navigation = 'buffer'
runtime autoload/ale/linter.vim runtime autoload/ale/linter.vim
runtime autoload/ale/lsp_linter.vim runtime autoload/ale/lsp_linter.vim
@ -54,6 +57,8 @@ Before:
endfunction endfunction
After: After:
Restore
if g:conn_id isnot v:null if g:conn_id isnot v:null
call ale#lsp#RemoveConnectionWithID(g:conn_id) call ale#lsp#RemoveConnectionWithID(g:conn_id)
endif endif
@ -164,7 +169,7 @@ Execute(Other files should be jumped to for definition responses in tabs too):
AssertEqual {}, ale#definition#GetMap() AssertEqual {}, ale#definition#GetMap()
Execute(Other files should be jumped to for definition responses in splits too): Execute(Other files should be jumped to for definition responses in splits too):
call ale#definition#SetMap({3: {'open_in': 'horizontal-split'}}) call ale#definition#SetMap({3: {'open_in': 'split'}})
call ale#definition#HandleTSServerResponse( call ale#definition#HandleTSServerResponse(
\ 1, \ 1,
\ { \ {
@ -189,7 +194,7 @@ Execute(Other files should be jumped to for definition responses in splits too):
AssertEqual {}, ale#definition#GetMap() AssertEqual {}, ale#definition#GetMap()
Execute(Other files should be jumped to for definition responses in vsplits too): Execute(Other files should be jumped to for definition responses in vsplits too):
call ale#definition#SetMap({3: {'open_in': 'vertical-split'}}) call ale#definition#SetMap({3: {'open_in': 'vsplit'}})
call ale#definition#HandleTSServerResponse( call ale#definition#HandleTSServerResponse(
\ 1, \ 1,
\ { \ {
@ -241,7 +246,32 @@ Execute(tsserver tab definition requests should be sent):
runtime ale_linters/typescript/tsserver.vim runtime ale_linters/typescript/tsserver.vim
call setpos('.', [bufnr(''), 2, 5, 0]) call setpos('.', [bufnr(''), 2, 5, 0])
ALEGoToDefinitionInTab ALEGoToDefinition -tab
" We shouldn't register the callback yet.
AssertEqual '''''', string(g:Callback)
AssertEqual type(function('type')), type(g:InitCallback)
call g:InitCallback()
AssertEqual 'definition', g:capability_checked
AssertEqual
\ 'function(''ale#definition#HandleTSServerResponse'')',
\ string(g:Callback)
AssertEqual
\ [
\ ale#lsp#tsserver_message#Change(bufnr('')),
\ [0, 'ts@definition', {'file': expand('%:p'), 'line': 2, 'offset': 5}]
\ ],
\ g:message_list
AssertEqual {'42': {'open_in': 'tab'}}, ale#definition#GetMap()
Execute(The default navigation type should be used):
runtime ale_linters/typescript/tsserver.vim
call setpos('.', [bufnr(''), 2, 5, 0])
let g:ale_default_navigation = 'tab'
ALEGoToDefinition
" We shouldn't register the callback yet. " We shouldn't register the callback yet.
AssertEqual '''''', string(g:Callback) AssertEqual '''''', string(g:Callback)
@ -448,7 +478,7 @@ Execute(LSP tab definition requests should be sent):
let b:ale_linters = ['pyls'] let b:ale_linters = ['pyls']
call setpos('.', [bufnr(''), 1, 5, 0]) call setpos('.', [bufnr(''), 1, 5, 0])
ALEGoToDefinitionInTab ALEGoToDefinition -tab
" We shouldn't register the callback yet. " We shouldn't register the callback yet.
AssertEqual '''''', string(g:Callback) AssertEqual '''''', string(g:Callback)

View file

@ -7,6 +7,8 @@ Before:
Save g:ale_set_loclist Save g:ale_set_loclist
Save g:ale_set_quickfix Save g:ale_set_quickfix
Save g:ale_set_signs Save g:ale_set_signs
Save g:ale_exclude_highlights
Save b:ale_exclude_highlights
runtime autoload/ale/highlight.vim runtime autoload/ale/highlight.vim
@ -20,6 +22,8 @@ Before:
let g:ale_set_quickfix = 0 let g:ale_set_quickfix = 0
let g:ale_set_loclist = 0 let g:ale_set_loclist = 0
let g:ale_echo_cursor = 0 let g:ale_echo_cursor = 0
let g:ale_exclude_highlights = []
let b:ale_exclude_highlights = []
function! GenerateResults(buffer, output) function! GenerateResults(buffer, output)
return [ return [
@ -363,6 +367,23 @@ Execute(Highlights should always be cleared when the buffer highlight list is em
\ GetMatchesWithoutIDs() \ GetMatchesWithoutIDs()
endif endif
Execute(Highlights should be hidden when excluded):
let b:ale_exclude_highlights = ['ig.*ore', 'nope']
call ale#highlight#SetHighlights(bufnr('%'), [
\ {'bufnr': bufnr('%'), 'type': 'E', 'lnum': 1, 'col': 1, 'text': 'hello'},
\ {'bufnr': bufnr('%'), 'type': 'E', 'lnum': 2, 'col': 1, 'text': 'ignore'},
\ {'bufnr': bufnr('%'), 'type': 'E', 'lnum': 3, 'col': 1, 'text': 'nope'},
\ {'bufnr': bufnr('%'), 'type': 'E', 'lnum': 4, 'col': 1, 'text': 'world'},
\])
AssertEqual
\ [
\ {'group': 'ALEError', 'priority': 10, 'pos1': [1, 1, 1]},
\ {'group': 'ALEError', 'priority': 10, 'pos1': [4, 1, 1]},
\ ],
\ GetMatchesWithoutIDs()
Execute(Highlights should be cleared when ALE is disabled): Execute(Highlights should be cleared when ALE is disabled):
let g:ale_enabled = 1 let g:ale_enabled = 1
call ale#highlight#SetHighlights(bufnr(''), [ call ale#highlight#SetHighlights(bufnr(''), [

View file

@ -57,8 +57,9 @@ Before:
call add(g:expr_list, a:expr) call add(g:expr_list, a:expr)
endfunction endfunction
function! ale#code_action#HandleCodeAction(code_action) abort function! ale#code_action#HandleCodeAction(code_action, should_save) abort
let g:handle_code_action_called = 1 let g:handle_code_action_called = 1
AssertEqual v:false, a:should_save
call add(g:code_actions, a:code_action) call add(g:code_actions, a:code_action)
endfunction endfunction

View file

@ -57,8 +57,9 @@ Before:
call add(g:expr_list, a:expr) call add(g:expr_list, a:expr)
endfunction endfunction
function! ale#code_action#HandleCodeAction(code_action) abort function! ale#code_action#HandleCodeAction(code_action, should_save) abort
let g:handle_code_action_called = 1 let g:handle_code_action_called = 1
AssertEqual v:true, a:should_save
call add(g:code_actions, a:code_action) call add(g:code_actions, a:code_action)
endfunction endfunction

View file

@ -15,7 +15,7 @@ Given(A file with a Bash hashbang):
Execute(/bin/bash should be detected appropriately): Execute(/bin/bash should be detected appropriately):
AssertEqual 'bash', ale#handlers#sh#GetShellType(bufnr('')) AssertEqual 'bash', ale#handlers#sh#GetShellType(bufnr(''))
AssertEqual 'bash', ale_linters#sh#shell#GetExecutable(bufnr('')) AssertEqual 'bash', ale_linters#sh#shell#GetExecutable(bufnr(''))
AssertEqual 'bash', ale_linters#sh#shellcheck#GetDialectArgument(bufnr('')) AssertEqual 'bash', ale#handlers#shellcheck#GetDialectArgument(bufnr(''))
Given(A file with /bin/sh): Given(A file with /bin/sh):
#!/usr/bin/env sh -eu --foobar #!/usr/bin/env sh -eu --foobar
@ -23,7 +23,7 @@ Given(A file with /bin/sh):
Execute(/bin/sh should be detected appropriately): Execute(/bin/sh should be detected appropriately):
AssertEqual 'sh', ale#handlers#sh#GetShellType(bufnr('')) AssertEqual 'sh', ale#handlers#sh#GetShellType(bufnr(''))
AssertEqual 'sh', ale_linters#sh#shell#GetExecutable(bufnr('')) AssertEqual 'sh', ale_linters#sh#shell#GetExecutable(bufnr(''))
AssertEqual 'sh', ale_linters#sh#shellcheck#GetDialectArgument(bufnr('')) AssertEqual 'sh', ale#handlers#shellcheck#GetDialectArgument(bufnr(''))
Given(A file with bash as an argument to env): Given(A file with bash as an argument to env):
#!/usr/bin/env bash #!/usr/bin/env bash
@ -31,7 +31,7 @@ Given(A file with bash as an argument to env):
Execute(/usr/bin/env bash should be detected appropriately): Execute(/usr/bin/env bash should be detected appropriately):
AssertEqual 'bash', ale#handlers#sh#GetShellType(bufnr('')) AssertEqual 'bash', ale#handlers#sh#GetShellType(bufnr(''))
AssertEqual 'bash', ale_linters#sh#shell#GetExecutable(bufnr('')) AssertEqual 'bash', ale_linters#sh#shell#GetExecutable(bufnr(''))
AssertEqual 'bash', ale_linters#sh#shellcheck#GetDialectArgument(bufnr('')) AssertEqual 'bash', ale#handlers#shellcheck#GetDialectArgument(bufnr(''))
Given(A file with a tcsh hash bang and arguments): Given(A file with a tcsh hash bang and arguments):
#!/usr/bin/env tcsh -eu --foobar #!/usr/bin/env tcsh -eu --foobar
@ -39,7 +39,7 @@ Given(A file with a tcsh hash bang and arguments):
Execute(tcsh should be detected appropriately): Execute(tcsh should be detected appropriately):
AssertEqual 'tcsh', ale#handlers#sh#GetShellType(bufnr('')) AssertEqual 'tcsh', ale#handlers#sh#GetShellType(bufnr(''))
AssertEqual 'tcsh', ale_linters#sh#shell#GetExecutable(bufnr('')) AssertEqual 'tcsh', ale_linters#sh#shell#GetExecutable(bufnr(''))
AssertEqual 'tcsh', ale_linters#sh#shellcheck#GetDialectArgument(bufnr('')) AssertEqual 'tcsh', ale#handlers#shellcheck#GetDialectArgument(bufnr(''))
Given(A file with a zsh hash bang and arguments): Given(A file with a zsh hash bang and arguments):
#!/usr/bin/env zsh -eu --foobar #!/usr/bin/env zsh -eu --foobar
@ -47,7 +47,7 @@ Given(A file with a zsh hash bang and arguments):
Execute(zsh should be detected appropriately): Execute(zsh should be detected appropriately):
AssertEqual 'zsh', ale#handlers#sh#GetShellType(bufnr('')) AssertEqual 'zsh', ale#handlers#sh#GetShellType(bufnr(''))
AssertEqual 'zsh', ale_linters#sh#shell#GetExecutable(bufnr('')) AssertEqual 'zsh', ale_linters#sh#shell#GetExecutable(bufnr(''))
AssertEqual 'zsh', ale_linters#sh#shellcheck#GetDialectArgument(bufnr('')) AssertEqual 'zsh', ale#handlers#shellcheck#GetDialectArgument(bufnr(''))
Given(A file with a csh hash bang and arguments): Given(A file with a csh hash bang and arguments):
#!/usr/bin/env csh -eu --foobar #!/usr/bin/env csh -eu --foobar
@ -55,7 +55,7 @@ Given(A file with a csh hash bang and arguments):
Execute(csh should be detected appropriately): Execute(csh should be detected appropriately):
AssertEqual 'csh', ale#handlers#sh#GetShellType(bufnr('')) AssertEqual 'csh', ale#handlers#sh#GetShellType(bufnr(''))
AssertEqual 'csh', ale_linters#sh#shell#GetExecutable(bufnr('')) AssertEqual 'csh', ale_linters#sh#shell#GetExecutable(bufnr(''))
AssertEqual 'csh', ale_linters#sh#shellcheck#GetDialectArgument(bufnr('')) AssertEqual 'csh', ale#handlers#shellcheck#GetDialectArgument(bufnr(''))
Given(A file with a ksh hashbang): Given(A file with a ksh hashbang):
#!/bin/ksh #!/bin/ksh
@ -63,7 +63,7 @@ Given(A file with a ksh hashbang):
Execute(/bin/ksh should be detected appropriately): Execute(/bin/ksh should be detected appropriately):
AssertEqual 'ksh', ale#handlers#sh#GetShellType(bufnr('')) AssertEqual 'ksh', ale#handlers#sh#GetShellType(bufnr(''))
AssertEqual 'ksh', ale_linters#sh#shell#GetExecutable(bufnr('')) AssertEqual 'ksh', ale_linters#sh#shell#GetExecutable(bufnr(''))
AssertEqual 'ksh', ale_linters#sh#shellcheck#GetDialectArgument(bufnr('')) AssertEqual 'ksh', ale#handlers#shellcheck#GetDialectArgument(bufnr(''))
Given(A file with a ksh as an argument to env): Given(A file with a ksh as an argument to env):
#!/usr/bin/env ksh #!/usr/bin/env ksh
@ -71,7 +71,7 @@ Given(A file with a ksh as an argument to env):
Execute(ksh should be detected appropriately): Execute(ksh should be detected appropriately):
AssertEqual 'ksh', ale#handlers#sh#GetShellType(bufnr('')) AssertEqual 'ksh', ale#handlers#sh#GetShellType(bufnr(''))
AssertEqual 'ksh', ale_linters#sh#shell#GetExecutable(bufnr('')) AssertEqual 'ksh', ale_linters#sh#shell#GetExecutable(bufnr(''))
AssertEqual 'ksh', ale_linters#sh#shellcheck#GetDialectArgument(bufnr('')) AssertEqual 'ksh', ale#handlers#shellcheck#GetDialectArgument(bufnr(''))
Given(A file with a sh hash bang and arguments): Given(A file with a sh hash bang and arguments):
#!/usr/bin/env sh -eu --foobar #!/usr/bin/env sh -eu --foobar
@ -79,24 +79,24 @@ Given(A file with a sh hash bang and arguments):
Execute(sh should be detected appropriately): Execute(sh should be detected appropriately):
AssertEqual 'sh', ale#handlers#sh#GetShellType(bufnr('')) AssertEqual 'sh', ale#handlers#sh#GetShellType(bufnr(''))
AssertEqual 'sh', ale_linters#sh#shell#GetExecutable(bufnr('')) AssertEqual 'sh', ale_linters#sh#shell#GetExecutable(bufnr(''))
AssertEqual 'sh', ale_linters#sh#shellcheck#GetDialectArgument(bufnr('')) AssertEqual 'sh', ale#handlers#shellcheck#GetDialectArgument(bufnr(''))
Given(A file without a hashbang): Given(A file without a hashbang):
Execute(The bash dialect should be used for shellcheck if b:is_bash is 1): Execute(The bash dialect should be used for shellcheck if b:is_bash is 1):
let b:is_bash = 1 let b:is_bash = 1
AssertEqual 'bash', ale_linters#sh#shellcheck#GetDialectArgument(bufnr('')) AssertEqual 'bash', ale#handlers#shellcheck#GetDialectArgument(bufnr(''))
Execute(The sh dialect should be used for shellcheck if b:is_sh is 1): Execute(The sh dialect should be used for shellcheck if b:is_sh is 1):
let b:is_sh = 1 let b:is_sh = 1
AssertEqual 'sh', ale_linters#sh#shellcheck#GetDialectArgument(bufnr('')) AssertEqual 'sh', ale#handlers#shellcheck#GetDialectArgument(bufnr(''))
Execute(The ksh dialect should be used for shellcheck if b:is_kornshell is 1): Execute(The ksh dialect should be used for shellcheck if b:is_kornshell is 1):
let b:is_kornshell = 1 let b:is_kornshell = 1
AssertEqual 'ksh', ale_linters#sh#shellcheck#GetDialectArgument(bufnr('')) AssertEqual 'ksh', ale#handlers#shellcheck#GetDialectArgument(bufnr(''))
Given(A file with /bin/ash): Given(A file with /bin/ash):
#!/bin/ash #!/bin/ash
@ -106,7 +106,7 @@ Execute(The ash dialect should be used for the shell and the base function):
AssertEqual 'ash', ale_linters#sh#shell#GetExecutable(bufnr('')) AssertEqual 'ash', ale_linters#sh#shell#GetExecutable(bufnr(''))
Execute(dash should be used for shellcheck, which has no ash dialect): Execute(dash should be used for shellcheck, which has no ash dialect):
AssertEqual 'dash', ale_linters#sh#shellcheck#GetDialectArgument(bufnr('')) AssertEqual 'dash', ale#handlers#shellcheck#GetDialectArgument(bufnr(''))
Given(A file with /bin/dash): Given(A file with /bin/dash):
#!/bin/dash #!/bin/dash
@ -116,4 +116,4 @@ Execute(The dash dialect should be used for the shell and the base function):
AssertEqual 'dash', ale_linters#sh#shell#GetExecutable(bufnr('')) AssertEqual 'dash', ale_linters#sh#shell#GetExecutable(bufnr(''))
Execute(dash should be used for shellcheck): Execute(dash should be used for shellcheck):
AssertEqual 'dash', ale_linters#sh#shellcheck#GetDialectArgument(bufnr('')) AssertEqual 'dash', ale#handlers#shellcheck#GetDialectArgument(bufnr(''))