Compare commits

...
This repository has been archived on 2024-07-19. You can view files and clone it, but cannot push or open issues or pull requests.

8 commits

Author SHA1 Message Date
w0rp
76b5c9283d #574 Do not restore items with no columns for highlights from hidden buffers 2017-06-02 19:21:45 +01:00
w0rp
9b6d6344b2 Merge pull request #589 from bardzusny/ember-template-lint-handler-parsing-error
Ember-template-lint handler: properly handle template parsing errors.
2017-05-30 09:47:26 +01:00
w0rp
e94aea9144 Merge pull request #578 from nOkuda/master
Translate pylint output column to 1-based index
2017-05-25 13:38:05 +01:00
w0rp
64b56f84ef Fix #555 - Handle csslint errors without groups 2017-05-15 21:21:25 +01:00
w0rp
72f5aae74e Update the Makefile so tests will run correctly 2017-05-15 20:49:22 +01:00
w0rp
548c1a1007 Fix #553 - Filter out errors from other files for gometalinter 2017-05-15 20:44:09 +01:00
Adriaan Zonnenberg
2503eda68b Merge pull request #533 from pbogut/add_php7_compatibility
Add PHP 7 compatibility
2017-05-09 22:39:00 +01:00
w0rp
8e4bac54a6 #540 Fix shell escaping pretty much everywhere 2017-05-08 23:02:26 +01:00
48 changed files with 289 additions and 117 deletions

View file

@ -1,12 +1,12 @@
SHELL := /usr/bin/env bash SHELL := /usr/bin/env bash
IMAGE ?= w0rp/ale IMAGE ?= w0rp/ale:30a9967dbdb1
CURRENT_IMAGE_ID = 30a9967dbdb1 CURRENT_IMAGE_ID = 30a9967dbdb1
DOCKER_FLAGS = --rm -v $(PWD):/testplugin -v $(PWD)/test:/home "$(IMAGE)" DOCKER_FLAGS = --rm -v $(PWD):/testplugin -v $(PWD)/test:/home "$(IMAGE)"
tests = test/*.vader test/*/*.vader test/*/*/*.vader test/*/*/*/*.vader tests = test/*.vader test/*/*.vader test/*/*/*.vader test/*/*/*/*.vader
test-setup: test-setup:
docker images -q w0rp/ale | grep ^$(CURRENT_IMAGE_ID) > /dev/null || \ docker images -q w0rp/ale | grep ^$(CURRENT_IMAGE_ID) > /dev/null || \
docker pull $(IMAGE) docker pull w0rp/ale
vader: test-setup vader: test-setup
@:; \ @:; \

View file

@ -5,7 +5,7 @@ let g:ale_asm_gcc_options = get(g:, 'ale_asm_gcc_options', '-Wall')
function! ale_linters#asm#gcc#GetCommand(buffer) abort function! ale_linters#asm#gcc#GetCommand(buffer) abort
return 'gcc -x assembler -fsyntax-only ' return 'gcc -x assembler -fsyntax-only '
\ . '-iquote ' . fnameescape(fnamemodify(bufname(a:buffer), ':p:h')) \ . '-iquote ' . shellescape(fnamemodify(bufname(a:buffer), ':p:h'))
\ . ' ' . ale#Var(a:buffer, 'asm_gcc_options') . ' -' \ . ' ' . ale#Var(a:buffer, 'asm_gcc_options') . ' -'
endfunction endfunction

View file

@ -13,7 +13,7 @@ function! ale_linters#c#clang#GetCommand(buffer) abort
" -iquote with the directory the file is in makes #include work for " -iquote with the directory the file is in makes #include work for
" headers in the same directory. " headers in the same directory.
return 'clang -S -x c -fsyntax-only ' return 'clang -S -x c -fsyntax-only '
\ . '-iquote ' . fnameescape(fnamemodify(bufname(a:buffer), ':p:h')) \ . '-iquote ' . shellescape(fnamemodify(bufname(a:buffer), ':p:h'))
\ . ' ' . ale#Var(a:buffer, 'c_clang_options') . ' -' \ . ' ' . ale#Var(a:buffer, 'c_clang_options') . ' -'
endfunction endfunction

View file

@ -13,7 +13,7 @@ function! ale_linters#c#gcc#GetCommand(buffer) abort
" -iquote with the directory the file is in makes #include work for " -iquote with the directory the file is in makes #include work for
" headers in the same directory. " headers in the same directory.
return 'gcc -S -x c -fsyntax-only ' return 'gcc -S -x c -fsyntax-only '
\ . '-iquote ' . fnameescape(fnamemodify(bufname(a:buffer), ':p:h')) \ . '-iquote ' . shellescape(fnamemodify(bufname(a:buffer), ':p:h'))
\ . ' ' . ale#Var(a:buffer, 'c_gcc_options') . ' -' \ . ' ' . ale#Var(a:buffer, 'c_gcc_options') . ' -'
endfunction endfunction

View file

@ -10,7 +10,7 @@ function! ale_linters#cpp#clang#GetCommand(buffer) abort
" -iquote with the directory the file is in makes #include work for " -iquote with the directory the file is in makes #include work for
" headers in the same directory. " headers in the same directory.
return 'clang++ -S -x c++ -fsyntax-only ' return 'clang++ -S -x c++ -fsyntax-only '
\ . '-iquote ' . fnameescape(fnamemodify(bufname(a:buffer), ':p:h')) \ . '-iquote ' . shellescape(fnamemodify(bufname(a:buffer), ':p:h'))
\ . ' ' . ale#Var(a:buffer, 'cpp_clang_options') . ' -' \ . ' ' . ale#Var(a:buffer, 'cpp_clang_options') . ' -'
endfunction endfunction

View file

@ -20,7 +20,7 @@ function! ale_linters#cpp#gcc#GetCommand(buffer) abort
" -iquote with the directory the file is in makes #include work for " -iquote with the directory the file is in makes #include work for
" headers in the same directory. " headers in the same directory.
return 'gcc -S -x c++ -fsyntax-only ' return 'gcc -S -x c++ -fsyntax-only '
\ . '-iquote ' . fnameescape(fnamemodify(bufname(a:buffer), ':p:h')) \ . '-iquote ' . shellescape(fnamemodify(bufname(a:buffer), ':p:h'))
\ . ' ' . ale#Var(a:buffer, 'cpp_gcc_options') . ' -' \ . ' ' . ale#Var(a:buffer, 'cpp_gcc_options') . ' -'
endfunction endfunction

View file

@ -4,7 +4,7 @@
function! ale_linters#css#csslint#GetCommand(buffer) abort function! ale_linters#css#csslint#GetCommand(buffer) abort
let l:csslintrc = ale#path#FindNearestFile(a:buffer, '.csslintrc') let l:csslintrc = ale#path#FindNearestFile(a:buffer, '.csslintrc')
let l:config_option = !empty(l:csslintrc) let l:config_option = !empty(l:csslintrc)
\ ? '--config=' . fnameescape(l:csslintrc) \ ? '--config=' . shellescape(l:csslintrc)
\ : '' \ : ''
return 'csslint --format=compact ' . l:config_option . ' %t' return 'csslint --format=compact ' . l:config_option . ' %t'

View file

@ -31,7 +31,7 @@ function! ale_linters#d#dmd#DUBCommand(buffer) abort
" To support older dub versions, we just change the directory to " To support older dub versions, we just change the directory to
" the directory where we found the dub config, and then run `dub describe` " the directory where we found the dub config, and then run `dub describe`
" from that directory. " from that directory.
return 'cd ' . fnameescape(fnamemodify(l:dub_file, ':h')) return 'cd ' . shellescape(fnamemodify(l:dub_file, ':h'))
\ . ' && dub describe --import-paths' \ . ' && dub describe --import-paths'
endfunction endfunction
@ -42,7 +42,7 @@ function! ale_linters#d#dmd#DMDCommand(buffer, dub_output) abort
for l:line in a:dub_output for l:line in a:dub_output
if !empty(l:line) if !empty(l:line)
" The arguments must be '-Ifilename', not '-I filename' " The arguments must be '-Ifilename', not '-I filename'
call add(l:import_list, '-I' . fnameescape(l:line)) call add(l:import_list, '-I' . shellescape(l:line))
endif endif
endfor endfor

View file

@ -43,7 +43,7 @@ function! ale_linters#elm#make#GetCommand(buffer) abort
let l:dir_set_cmd = '' let l:dir_set_cmd = ''
else else
let l:root_dir = fnamemodify(l:elm_package, ':p:h') let l:root_dir = fnamemodify(l:elm_package, ':p:h')
let l:dir_set_cmd = 'cd ' . fnameescape(l:root_dir) . ' && ' let l:dir_set_cmd = 'cd ' . shellescape(l:root_dir) . ' && '
endif endif
" The elm-make compiler, at the time of this writing, uses '/dev/null' as " The elm-make compiler, at the time of this writing, uses '/dev/null' as

View file

@ -6,7 +6,7 @@ function! ale_linters#erlang#erlc#GetCommand(buffer) abort
let l:output_file = tempname() let l:output_file = tempname()
call ale#engine#ManageFile(a:buffer, l:output_file) call ale#engine#ManageFile(a:buffer, l:output_file)
return 'erlc -o ' . fnameescape(l:output_file) return 'erlc -o ' . shellescape(l:output_file)
\ . ' ' . ale#Var(a:buffer, 'erlang_erlc_options') \ . ' ' . ale#Var(a:buffer, 'erlang_erlc_options')
\ . ' %t' \ . ' %t'
endfunction endfunction

View file

@ -8,7 +8,7 @@ endif
function! ale_linters#go#gometalinter#GetCommand(buffer) abort function! ale_linters#go#gometalinter#GetCommand(buffer) abort
return 'gometalinter ' return 'gometalinter '
\ . ale#Var(a:buffer, 'go_gometalinter_options') \ . ale#Var(a:buffer, 'go_gometalinter_options')
\ . ' ' . fnameescape(fnamemodify(bufname(a:buffer), ':p:h')) \ . ' ' . shellescape(fnamemodify(bufname(a:buffer), ':p:h'))
endfunction endfunction
function! ale_linters#go#gometalinter#GetMatches(lines) abort function! ale_linters#go#gometalinter#GetMatches(lines) abort
@ -22,7 +22,7 @@ function! ale_linters#go#gometalinter#Handler(buffer, lines) abort
for l:match in ale_linters#go#gometalinter#GetMatches(a:lines) for l:match in ale_linters#go#gometalinter#GetMatches(a:lines)
" Omit errors from files other than the one currently open " Omit errors from files other than the one currently open
if ale#path#IsBufferPath(a:buffer, l:match[0]) if !ale#path#IsBufferPath(a:buffer, l:match[1])
continue continue
endif endif

View file

@ -35,13 +35,23 @@ function! ale_linters#handlebars#embertemplatelint#Handle(buffer, lines) abort
let l:file_errors = values(l:input_json)[0] let l:file_errors = values(l:input_json)[0]
for l:error in l:file_errors for l:error in l:file_errors
call add(l:output, { if has_key(l:error, 'fatal')
\ 'bufnr': a:buffer, call add(l:output, {
\ 'lnum': l:error.line, \ 'bufnr': a:buffer,
\ 'col': l:error.column, \ 'lnum': 1,
\ 'text': l:error.rule . ': ' . l:error.message, \ 'col': 1,
\ 'type': l:error.severity == 1 ? 'W' : 'E', \ 'text': l:error.message,
\}) \ 'type': l:error.severity == 1 ? 'W' : 'E',
\})
else
call add(l:output, {
\ 'bufnr': a:buffer,
\ 'lnum': l:error.line,
\ 'col': l:error.column,
\ 'text': l:error.rule . ': ' . l:error.message,
\ 'type': l:error.severity == 1 ? 'W' : 'E',
\})
endif
endfor endfor
return l:output return l:output

View file

@ -41,14 +41,13 @@ 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 map(l:class_paths, 'fnameescape(v:val)')
call extend( call extend(
\ l:class_paths, \ l:class_paths,
\ split(ale#Var(a:buffer, 'java_javac_classpath'), s:classpath_sep), \ split(ale#Var(a:buffer, 'java_javac_classpath'), s:classpath_sep),
\) \)
return !empty(l:class_paths) return !empty(l:class_paths)
\ ? '-cp ' . join(l:class_paths, s:classpath_sep) \ ? '-cp ' . shellescape(join(l:class_paths, s:classpath_sep))
\ : '' \ : ''
endfunction endfunction
@ -65,7 +64,7 @@ function! ale_linters#java#javac#GetCommand(buffer, import_paths) abort
let l:src_dir = ale#path#FindNearestDirectory(a:buffer, 'src/main/java') let l:src_dir = ale#path#FindNearestDirectory(a:buffer, 'src/main/java')
if !empty(l:src_dir) if !empty(l:src_dir)
let l:sp_option = '-sourcepath ' . fnameescape(l:src_dir) let l:sp_option = '-sourcepath ' . shellescape(l:src_dir)
endif endif
" Create .class files in a temporary directory, which we will delete later. " Create .class files in a temporary directory, which we will delete later.
@ -74,7 +73,7 @@ function! ale_linters#java#javac#GetCommand(buffer, import_paths) abort
return 'javac -Xlint' return 'javac -Xlint'
\ . ' ' . l:cp_option \ . ' ' . l:cp_option
\ . ' ' . l:sp_option \ . ' ' . l:sp_option
\ . ' -d ' . fnameescape(l:class_file_directory) \ . ' -d ' . shellescape(l:class_file_directory)
\ . ' ' . ale#Var(a:buffer, 'java_javac_options') \ . ' ' . ale#Var(a:buffer, 'java_javac_options')
\ . ' %t' \ . ' %t'
endfunction endfunction

View file

@ -34,7 +34,7 @@ function! ale_linters#javascript#eslint#GetExecutable(buffer) abort
endfunction endfunction
function! ale_linters#javascript#eslint#GetCommand(buffer) abort function! ale_linters#javascript#eslint#GetCommand(buffer) abort
return fnameescape(ale_linters#javascript#eslint#GetExecutable(a:buffer)) return shellescape(ale_linters#javascript#eslint#GetExecutable(a:buffer))
\ . ' ' . ale#Var(a:buffer, 'javascript_eslint_options') \ . ' ' . ale#Var(a:buffer, 'javascript_eslint_options')
\ . ' -f unix --stdin --stdin-filename %s' \ . ' -f unix --stdin --stdin-filename %s'
endfunction endfunction

View file

@ -27,7 +27,7 @@ function! ale_linters#javascript#flow#GetCommand(buffer) abort
return '' return ''
endif endif
return fnameescape(ale_linters#javascript#flow#GetExecutable(a:buffer)) return shellescape(ale_linters#javascript#flow#GetExecutable(a:buffer))
\ . ' check-contents --respect-pragma --json --from ale %s' \ . ' check-contents --respect-pragma --json --from ale %s'
endfunction endfunction

View file

@ -27,11 +27,11 @@ function! ale_linters#javascript#jshint#GetCommand(buffer) abort
\ get(g:, 'ale_jshint_config_loc', '') \ get(g:, 'ale_jshint_config_loc', '')
\) \)
let l:command = fnameescape(ale_linters#javascript#jshint#GetExecutable(a:buffer)) let l:command = shellescape(ale_linters#javascript#jshint#GetExecutable(a:buffer))
let l:command .= ' --reporter unix --extract auto' let l:command .= ' --reporter unix --extract auto'
if !empty(l:jshint_config) if !empty(l:jshint_config)
let l:command .= ' --config ' . fnameescape(l:jshint_config) let l:command .= ' --config ' . shellescape(l:jshint_config)
endif endif
let l:command .= ' -' let l:command .= ' -'

View file

@ -23,7 +23,7 @@ function! ale_linters#javascript#standard#GetExecutable(buffer) abort
endfunction endfunction
function! ale_linters#javascript#standard#GetCommand(buffer) abort function! ale_linters#javascript#standard#GetCommand(buffer) abort
return fnameescape(ale_linters#javascript#standard#GetExecutable(a:buffer)) return shellescape(ale_linters#javascript#standard#GetExecutable(a:buffer))
\ . ' ' . ale#Var(a:buffer, 'javascript_standard_options') \ . ' ' . ale#Var(a:buffer, 'javascript_standard_options')
\ . ' --stdin %s' \ . ' --stdin %s'
endfunction endfunction

View file

@ -23,7 +23,7 @@ function! ale_linters#javascript#xo#GetExecutable(buffer) abort
endfunction endfunction
function! ale_linters#javascript#xo#GetCommand(buffer) abort function! ale_linters#javascript#xo#GetCommand(buffer) abort
return fnameescape(ale_linters#javascript#xo#GetExecutable(a:buffer)) return shellescape(ale_linters#javascript#xo#GetExecutable(a:buffer))
\ . ' ' . ale#Var(a:buffer, 'javascript_xo_options') \ . ' ' . ale#Var(a:buffer, 'javascript_xo_options')
\ . ' --reporter unix --stdin --stdin-filename %s' \ . ' --reporter unix --stdin --stdin-filename %s'
endfunction endfunction

View file

@ -16,13 +16,13 @@ function! ale_linters#kotlin#kotlinc#GetCommand(buffer) abort
" If the config file is enabled and readable, source it " If the config file is enabled and readable, source it
if ale#Var(a:buffer, 'kotlin_kotlinc_enable_config') if ale#Var(a:buffer, 'kotlin_kotlinc_enable_config')
if filereadable(expand(ale#Var(a:buffer, 'kotlin_kotlinc_config_file'), 1)) if filereadable(expand(ale#Var(a:buffer, 'kotlin_kotlinc_config_file'), 1))
execute 'source ' . fnameescape(expand(ale#Var(a:buffer, 'kotlin_kotlinc_config_file'), 1)) execute 'source ' . shellescape(expand(ale#Var(a:buffer, 'kotlin_kotlinc_config_file'), 1))
endif endif
endif endif
" If use module and module file is readable use that and return " If use module and module file is readable use that and return
if ale#Var(a:buffer, 'kotlin_kotlinc_use_module_file') if ale#Var(a:buffer, 'kotlin_kotlinc_use_module_file')
let l:module_filename = fnameescape(expand(ale#Var(a:buffer, 'kotlin_kotlinc_module_filename'), 1)) let l:module_filename = shellescape(expand(ale#Var(a:buffer, 'kotlin_kotlinc_module_filename'), 1))
if filereadable(l:module_filename) if filereadable(l:module_filename)
let l:kotlinc_opts .= ' -module ' . l:module_filename let l:kotlinc_opts .= ' -module ' . l:module_filename

View file

@ -12,7 +12,7 @@ function! ale_linters#lua#luacheck#GetExecutable(buffer) abort
endfunction endfunction
function! ale_linters#lua#luacheck#GetCommand(buffer) abort function! ale_linters#lua#luacheck#GetCommand(buffer) abort
return ale_linters#lua#luacheck#GetExecutable(a:buffer) return shellescape(ale_linters#lua#luacheck#GetExecutable(a:buffer))
\ . ' ' . ale#Var(a:buffer, 'lua_luacheck_options') \ . ' ' . ale#Var(a:buffer, 'lua_luacheck_options')
\ . ' --formatter plain --codes --filename %s -' \ . ' --formatter plain --codes --filename %s -'
endfunction endfunction

View file

@ -44,7 +44,7 @@ endfunction
function! ale_linters#nim#nimcheck#GetCommand(buffer) abort function! ale_linters#nim#nimcheck#GetCommand(buffer) abort
let l:directory = fnameescape(fnamemodify(bufname(a:buffer), ':p:h')) let l:directory = shellescape(fnamemodify(bufname(a:buffer), ':p:h'))
return 'nim check --path:' . l:directory return 'nim check --path:' . l:directory
\ . ' --threads:on --verbosity:0 --colors:off --listFullPaths %t' \ . ' --threads:on --verbosity:0 --colors:off --listFullPaths %t'

View file

@ -5,7 +5,7 @@ function! ale_linters#php#php#Handle(buffer, lines) abort
" Matches patterns like the following: " Matches patterns like the following:
" "
" PHP Parse error: syntax error, unexpected ';', expecting ']' in - on line 15 " PHP Parse error: syntax error, unexpected ';', expecting ']' in - on line 15
let l:pattern = '\vPHP %(Fatal|Parse) error:\s+(.+unexpected ''(.+)%(expecting.+)@<!''.*|.+) in - on line (\d+)' let l:pattern = '\v^%(Fatal|Parse) error:\s+(.+unexpected ''(.+)%(expecting.+)@<!''.*|.+) in - on line (\d+)'
let l:output = [] let l:output = []
@ -23,7 +23,7 @@ endfunction
call ale#linter#Define('php', { call ale#linter#Define('php', {
\ 'name': 'php', \ 'name': 'php',
\ 'executable': 'php', \ 'executable': 'php',
\ 'output_stream': 'both', \ 'output_stream': 'stdout',
\ 'command': 'php -l -d display_errors=1 --', \ 'command': 'php -l -d error_reporting=E_ALL -d display_errors=1 --',
\ 'callback': 'ale_linters#php#php#Handle', \ 'callback': 'ale_linters#php#php#Handle',
\}) \})

View file

@ -48,7 +48,7 @@ function! ale_linters#python#flake8#VersionCheck(buffer) abort
return '' return ''
endif endif
let l:executable = fnameescape(ale_linters#python#flake8#GetExecutable(a:buffer)) let l:executable = shellescape(ale_linters#python#flake8#GetExecutable(a:buffer))
let l:module_string = s:UsingModule(a:buffer) ? ' -m flake8' : '' let l:module_string = s:UsingModule(a:buffer) ? ' -m flake8' : ''
return l:executable . l:module_string . ' --version' return l:executable . l:module_string . ' --version'
@ -89,7 +89,7 @@ function! ale_linters#python#flake8#GetCommand(buffer, version_output) abort
let l:options = ale#Var(a:buffer, 'python_flake8_options') let l:options = ale#Var(a:buffer, 'python_flake8_options')
return fnameescape(ale_linters#python#flake8#GetExecutable(a:buffer)) return shellescape(ale_linters#python#flake8#GetExecutable(a:buffer))
\ . (!empty(l:options) ? ' ' . l:options : '') \ . (!empty(l:options) ? ' ' . l:options : '')
\ . l:display_name_args . ' -' \ . l:display_name_args . ' -'
endfunction endfunction

View file

@ -30,7 +30,7 @@ function! ale_linters#python#mypy#GetCommand(buffer) abort
let l:executable = ale_linters#python#mypy#GetExecutable(a:buffer) let l:executable = ale_linters#python#mypy#GetExecutable(a:buffer)
return l:cd_command return l:cd_command
\ . fnameescape(l:executable) \ . shellescape(l:executable)
\ . ' --show-column-numbers ' \ . ' --show-column-numbers '
\ . ale#Var(a:buffer, 'python_mypy_options') \ . ale#Var(a:buffer, 'python_mypy_options')
\ . ' %s' \ . ' %s'

View file

@ -26,16 +26,49 @@ function! ale_linters#python#pylint#GetExecutable(buffer) abort
endfunction endfunction
function! ale_linters#python#pylint#GetCommand(buffer) abort function! ale_linters#python#pylint#GetCommand(buffer) abort
return fnameescape(ale_linters#python#pylint#GetExecutable(a:buffer)) return shellescape(ale_linters#python#pylint#GetExecutable(a:buffer))
\ . ' ' . ale#Var(a:buffer, 'python_pylint_options') \ . ' ' . ale#Var(a:buffer, 'python_pylint_options')
\ . ' --output-format text --msg-template="{path}:{line}:{column}: {msg_id} ({symbol}) {msg}" --reports n' \ . ' --output-format text --msg-template="{path}:{line}:{column}: {msg_id} ({symbol}) {msg}" --reports n'
\ . ' %s' \ . ' %s'
endfunction endfunction
function! ale_linters#python#pylint#Handle(buffer, lines) abort
" Matches patterns like the following:
"
" test.py:4:4: W0101 (unreachable) Unreachable code
let l:pattern = '\v^[^:]+:(\d+):(\d+): ([[:alnum:]]+) \((.*)\) (.*)$'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
"let l:failed = append(0, l:match)
let l:code = l:match[3]
if (l:code ==# 'C0303')
\ && !ale#Var(a:buffer, 'warn_about_trailing_whitespace')
" Skip warnings for trailing whitespace if the option is off.
continue
endif
if l:code ==# 'I0011'
" Skip 'Locally disabling' message
continue
endif
call add(l:output, {
\ 'lnum': l:match[1] + 0,
\ 'col': l:match[2] + 1,
\ 'text': l:code . ': ' . l:match[5],
\ 'type': l:code[:0] ==# 'E' ? 'E' : 'W',
\})
endfor
return l:output
endfunction
call ale#linter#Define('python', { call ale#linter#Define('python', {
\ 'name': 'pylint', \ 'name': 'pylint',
\ 'executable_callback': 'ale_linters#python#pylint#GetExecutable', \ 'executable_callback': 'ale_linters#python#pylint#GetExecutable',
\ 'command_callback': 'ale_linters#python#pylint#GetCommand', \ 'command_callback': 'ale_linters#python#pylint#GetCommand',
\ 'callback': 'ale#handlers#python#HandlePEP8Format', \ 'callback': 'ale_linters#python#pylint#Handle',
\ 'lint_file': 1, \ 'lint_file': 1,
\}) \})

View file

@ -18,7 +18,7 @@ function! ale_linters#tex#chktex#GetCommand(buffer) abort
let l:command .= ' -v0 -p stdin -q' let l:command .= ' -v0 -p stdin -q'
if !empty(l:chktex_config) if !empty(l:chktex_config)
let l:command .= ' -l ' . fnameescape(l:chktex_config) let l:command .= ' -l ' . shellescape(l:chktex_config)
endif endif
let l:command .= ' ' . ale#Var(a:buffer, 'tex_chktex_options') let l:command .= ' ' . ale#Var(a:buffer, 'tex_chktex_options')

View file

@ -55,7 +55,7 @@ function! ale_linters#typescript#tslint#BuildLintCommand(buffer) abort
\) \)
let l:tslint_config_option = !empty(l:tslint_config_path) let l:tslint_config_option = !empty(l:tslint_config_path)
\ ? '-c ' . fnameescape(l:tslint_config_path) \ ? '-c ' . shellescape(l:tslint_config_path)
\ : '' \ : ''
return ale_linters#typescript#tslint#GetExecutable(a:buffer) return ale_linters#typescript#tslint#GetExecutable(a:buffer)

View file

@ -8,7 +8,7 @@ function! ale_linters#verilog#verilator#GetCommand(buffer) abort
call ale#engine#ManageFile(a:buffer, l:filename) call ale#engine#ManageFile(a:buffer, l:filename)
call writefile(getbufline(a:buffer, 1, '$'), l:filename) call writefile(getbufline(a:buffer, 1, '$'), l:filename)
return 'verilator --lint-only -Wall -Wno-DECLFILENAME ' . fnameescape(l:filename) return 'verilator --lint-only -Wall -Wno-DECLFILENAME ' . shellescape(l:filename)
endfunction endfunction
function! ale_linters#verilog#verilator#Handle(buffer, lines) abort function! ale_linters#verilog#verilator#Handle(buffer, lines) abort

View file

@ -480,14 +480,14 @@ function! ale#engine#FormatCommand(buffer, command) abort
" file. " file.
if l:command =~# '%s' if l:command =~# '%s'
let l:filename = fnamemodify(bufname(a:buffer), ':p') let l:filename = fnamemodify(bufname(a:buffer), ':p')
let l:command = substitute(l:command, '%s', '\=fnameescape(l:filename)', 'g') let l:command = substitute(l:command, '%s', '\=shellescape(l:filename)', 'g')
endif endif
if l:command =~# '%t' if l:command =~# '%t'
" Create a temporary filename, <temp_dir>/<original_basename> " Create a temporary filename, <temp_dir>/<original_basename>
" The file itself will not be created by this function. " The file itself will not be created by this function.
let l:temporary_file = s:TemporaryFilename(a:buffer) let l:temporary_file = s:TemporaryFilename(a:buffer)
let l:command = substitute(l:command, '%t', '\=fnameescape(l:temporary_file)', 'g') let l:command = substitute(l:command, '%t', '\=shellescape(l:temporary_file)', 'g')
endif endif
" Finish formatting so %% becomes %. " Finish formatting so %% becomes %.
@ -529,7 +529,7 @@ function! s:RunJob(options) abort
" in the shell. We'll write out the file to a temporary file, " in the shell. We'll write out the file to a temporary file,
" and then read it back in, in the shell. " and then read it back in, in the shell.
let l:temporary_file = s:TemporaryFilename(l:buffer) let l:temporary_file = s:TemporaryFilename(l:buffer)
let l:command = l:command . ' < ' . fnameescape(l:temporary_file) let l:command = l:command . ' < ' . shellescape(l:temporary_file)
endif endif
if s:CreateTemporaryFileForJob(l:buffer, l:temporary_file) if s:CreateTemporaryFileForJob(l:buffer, l:temporary_file)

View file

@ -10,17 +10,20 @@ function! ale#handlers#css#HandleCSSLintFormat(buffer, lines) abort
" "
" These errors can be very massive, so the type will be moved to the front " These errors can be very massive, so the type will be moved to the front
" so you can actually read the error type. " so you can actually read the error type.
let l:pattern = '^.*: line \(\d\+\), col \(\d\+\), \(Error\|Warning\) - \(.\+\) (\([^)]\+\))$' let l:pattern = '\v^.*: line (\d+), col (\d+), (Error|Warning) - (.+)$'
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:text = l:match[4] let l:text = l:match[4]
let l:type = l:match[3] let l:type = l:match[3]
let l:errorGroup = l:match[5]
let l:group_match = matchlist(l:text, '\v^(.+) \((.+)\)$')
" Put the error group at the front, so we can see what kind of error " Put the error group at the front, so we can see what kind of error
" it is on small echo lines. " it is on small echo lines.
let l:text = '(' . l:errorGroup . ') ' . l:text if !empty(l:group_match)
let l:text = '(' . l:group_match[2] . ') ' . l:group_match[1]
endif
call add(l:output, { call add(l:output, {
\ 'lnum': l:match[1] + 0, \ 'lnum': l:match[1] + 0,

View file

@ -109,7 +109,11 @@ function! ale#highlight#BufferHidden(buffer) abort
endif endif
endfor endfor
let s:buffer_restore_map[a:buffer] = l:loclist let s:buffer_restore_map[a:buffer] = filter(
\ copy(l:loclist),
\ 'v:val.bufnr == a:buffer && v:val.col > 0'
\)
call clearmatches() call clearmatches()
endif endif
endfunction endfunction

View file

@ -47,7 +47,7 @@ endfunction
" Output 'cd <directory> && ' " Output 'cd <directory> && '
" This function can be used changing the directory for a linter command. " This function can be used changing the directory for a linter command.
function! ale#path#CdString(directory) abort function! ale#path#CdString(directory) abort
return 'cd ' . fnameescape(a:directory) . ' && ' return 'cd ' . shellescape(a:directory) . ' && '
endfunction endfunction
" Output 'cd <buffer_filename_directory> && ' " Output 'cd <buffer_filename_directory> && '

View file

@ -19,7 +19,7 @@ Execute(cppcheck for C should detect compile_commands.json files):
cd cppcheck_paths/one cd cppcheck_paths/one
AssertEqual AssertEqual
\ 'cd ' . fnameescape(b:dir . '/cppcheck_paths/one') . ' && ' \ 'cd ' . shellescape(b:dir . '/cppcheck_paths/one') . ' && '
\ . 'cppcheck -q --language=c --project=compile_commands.json --enable=style %t', \ . 'cppcheck -q --language=c --project=compile_commands.json --enable=style %t',
\ ale_linters#c#cppcheck#GetCommand(bufnr('')) \ ale_linters#c#cppcheck#GetCommand(bufnr(''))
@ -35,6 +35,6 @@ Execute(cppcheck for C++ should detect compile_commands.json files):
cd cppcheck_paths/one cd cppcheck_paths/one
AssertEqual AssertEqual
\ 'cd ' . fnameescape(b:dir . '/cppcheck_paths/one') . ' && ' \ 'cd ' . shellescape(b:dir . '/cppcheck_paths/one') . ' && '
\ . 'cppcheck -q --language=c++ --project=compile_commands.json --enable=style %t', \ . 'cppcheck -q --language=c++ --project=compile_commands.json --enable=style %t',
\ ale_linters#cpp#cppcheck#GetCommand(bufnr('')) \ ale_linters#cpp#cppcheck#GetCommand(bufnr(''))

View file

@ -22,26 +22,26 @@ Execute(The flake8 callbacks should return the correct default values):
\ 'flake8', \ 'flake8',
\ ale_linters#python#flake8#GetExecutable(bufnr('')) \ ale_linters#python#flake8#GetExecutable(bufnr(''))
AssertEqual AssertEqual
\ 'flake8 --version', \ '''flake8'' --version',
\ ale_linters#python#flake8#VersionCheck(bufnr('')) \ ale_linters#python#flake8#VersionCheck(bufnr(''))
AssertEqual AssertEqual
\ 'flake8 --stdin-display-name %s -', \ '''flake8'' --stdin-display-name %s -',
\ ale_linters#python#flake8#GetCommand(bufnr(''), ['3.0.0']) \ ale_linters#python#flake8#GetCommand(bufnr(''), ['3.0.0'])
" Try with older versions. " Try with older versions.
call ale_linters#python#flake8#ClearVersionCache() call ale_linters#python#flake8#ClearVersionCache()
AssertEqual AssertEqual
\ 'flake8 -', \ '''flake8'' -',
\ ale_linters#python#flake8#GetCommand(bufnr(''), ['2.9.9']) \ ale_linters#python#flake8#GetCommand(bufnr(''), ['2.9.9'])
Execute(The flake8 command callback should let you set options): Execute(The flake8 command callback should let you set options):
let g:ale_python_flake8_options = '--some-option' let g:ale_python_flake8_options = '--some-option'
AssertEqual AssertEqual
\ 'flake8 --some-option --stdin-display-name %s -', \ '''flake8'' --some-option --stdin-display-name %s -',
\ ale_linters#python#flake8#GetCommand(bufnr(''), ['3.0.4']) \ ale_linters#python#flake8#GetCommand(bufnr(''), ['3.0.4'])
call ale_linters#python#flake8#ClearVersionCache() call ale_linters#python#flake8#ClearVersionCache()
AssertEqual AssertEqual
\ 'flake8 --some-option -', \ '''flake8'' --some-option -',
\ ale_linters#python#flake8#GetCommand(bufnr(''), ['2.9.9']) \ ale_linters#python#flake8#GetCommand(bufnr(''), ['2.9.9'])
Execute(You should be able to set a custom executable and it should be escaped): Execute(You should be able to set a custom executable and it should be escaped):
@ -51,10 +51,10 @@ Execute(You should be able to set a custom executable and it should be escaped):
\ 'executable with spaces', \ 'executable with spaces',
\ ale_linters#python#flake8#GetExecutable(bufnr('')) \ ale_linters#python#flake8#GetExecutable(bufnr(''))
AssertEqual AssertEqual
\ 'executable\ with\ spaces --version', \ '''executable with spaces'' --version',
\ ale_linters#python#flake8#VersionCheck(bufnr('')) \ ale_linters#python#flake8#VersionCheck(bufnr(''))
AssertEqual AssertEqual
\ 'executable\ with\ spaces --stdin-display-name %s -', \ '''executable with spaces'' --stdin-display-name %s -',
\ ale_linters#python#flake8#GetCommand(bufnr(''), ['3.0.0']) \ ale_linters#python#flake8#GetCommand(bufnr(''), ['3.0.0'])
Execute(The flake8 callbacks should detect virtualenv directories): Execute(The flake8 callbacks should detect virtualenv directories):
@ -64,10 +64,10 @@ Execute(The flake8 callbacks should detect virtualenv directories):
\ g:dir . '/python_paths/with_virtualenv/env/bin/flake8', \ g:dir . '/python_paths/with_virtualenv/env/bin/flake8',
\ ale_linters#python#flake8#GetExecutable(bufnr('')) \ ale_linters#python#flake8#GetExecutable(bufnr(''))
AssertEqual AssertEqual
\ g:dir . '/python_paths/with_virtualenv/env/bin/flake8 --version', \ '''' . g:dir . '/python_paths/with_virtualenv/env/bin/flake8'' --version',
\ ale_linters#python#flake8#VersionCheck(bufnr('')) \ ale_linters#python#flake8#VersionCheck(bufnr(''))
AssertEqual AssertEqual
\ g:dir . '/python_paths/with_virtualenv/env/bin/flake8' \ '''' . g:dir . '/python_paths/with_virtualenv/env/bin/flake8'''
\ . ' --stdin-display-name %s -', \ . ' --stdin-display-name %s -',
\ ale_linters#python#flake8#GetCommand(bufnr(''), ['3.0.0']) \ ale_linters#python#flake8#GetCommand(bufnr(''), ['3.0.0'])
@ -82,10 +82,10 @@ Execute(Using `python -m flake8` should be supported for running flake8):
\ 'python', \ 'python',
\ ale_linters#python#flake8#GetExecutable(bufnr('')) \ ale_linters#python#flake8#GetExecutable(bufnr(''))
AssertEqual AssertEqual
\ 'python -m flake8 --version', \ '''python'' -m flake8 --version',
\ ale_linters#python#flake8#VersionCheck(bufnr('')) \ ale_linters#python#flake8#VersionCheck(bufnr(''))
AssertEqual AssertEqual
\ 'python -m flake8 --some-option -', \ '''python'' -m flake8 --some-option -',
\ ale_linters#python#flake8#GetCommand(bufnr(''), ['2.9.9']) \ ale_linters#python#flake8#GetCommand(bufnr(''), ['2.9.9'])
call ale_linters#python#flake8#ClearVersionCache() call ale_linters#python#flake8#ClearVersionCache()
@ -97,8 +97,8 @@ Execute(Using `python -m flake8` should be supported for running flake8):
\ 'python', \ 'python',
\ ale_linters#python#flake8#GetExecutable(bufnr('')) \ ale_linters#python#flake8#GetExecutable(bufnr(''))
AssertEqual AssertEqual
\ 'python -m flake8 --version', \ '''python'' -m flake8 --version',
\ ale_linters#python#flake8#VersionCheck(bufnr('')) \ ale_linters#python#flake8#VersionCheck(bufnr(''))
AssertEqual AssertEqual
\ 'python -m flake8 --some-option -', \ '''python'' -m flake8 --some-option -',
\ ale_linters#python#flake8#GetCommand(bufnr(''), ['2.9.9']) \ ale_linters#python#flake8#GetCommand(bufnr(''), ['2.9.9'])

View file

@ -15,7 +15,7 @@ After:
Execute(The javac callback should return the correct default value): Execute(The javac callback should return the correct default value):
let b:command = ale_linters#java#javac#GetCommand(bufnr(''), []) let b:command = ale_linters#java#javac#GetCommand(bufnr(''), [])
Assert match(b:command, '\v^javac +-Xlint +-d +/tmp/[0-9a-zA-Z/]+ +\%t$') >= 0, Assert match(b:command, '\v^javac +-Xlint +-d +''/tmp/[0-9a-zA-Z/]+'' +\%t$') >= 0,
\ 'Invalid command string: ' . b:command \ 'Invalid command string: ' . b:command
Execute(The javac callback should use g:ale_java_javac_classpath correctly): Execute(The javac callback should use g:ale_java_javac_classpath correctly):
@ -23,7 +23,7 @@ Execute(The javac callback should use g:ale_java_javac_classpath correctly):
let b:command = ale_linters#java#javac#GetCommand(bufnr(''), []) let b:command = ale_linters#java#javac#GetCommand(bufnr(''), [])
Assert match(b:command, '\v^javac +-Xlint +-cp +foo\.jar +-d +/tmp/[0-9a-zA-Z/]+ +\%t$') >= 0, Assert match(b:command, '\v^javac +-Xlint +-cp ''+foo\.jar'' +-d ''+/tmp/[0-9a-zA-Z/]+'' +\%t$') >= 0,
\ 'Invalid command string: ' . b:command \ 'Invalid command string: ' . b:command
Execute(The javac callback should include discovered classpaths): Execute(The javac callback should include discovered classpaths):
@ -34,7 +34,7 @@ Execute(The javac callback should include discovered classpaths):
\ '/xyz/abc.jar', \ '/xyz/abc.jar',
\]) \])
Assert match(b:command, '\v^javac +-Xlint +-cp +/foo/bar\.jar:/xyz/abc\.jar +-d +/tmp/[0-9a-zA-Z/]+ +\%t$') >= 0, Assert match(b:command, '\v^javac +-Xlint +-cp ''+/foo/bar\.jar:/xyz/abc\.jar'' +-d +''/tmp/[0-9a-zA-Z/]+'' +\%t$') >= 0,
\ 'Invalid command string: ' . b:command \ 'Invalid command string: ' . b:command
Execute(The javac callback should combine discovered classpaths and manual ones): Execute(The javac callback should combine discovered classpaths and manual ones):
@ -47,7 +47,7 @@ Execute(The javac callback should combine discovered classpaths and manual ones)
\ '/xyz/abc.jar', \ '/xyz/abc.jar',
\]) \])
Assert match(b:command, '\v^javac +-Xlint +-cp +/foo/bar\.jar:/xyz/abc\.jar:configured\.jar +-d +/tmp/[0-9a-zA-Z/]+ +\%t$') >= 0, Assert match(b:command, '\v^javac +-Xlint +-cp +''/foo/bar\.jar:/xyz/abc\.jar:configured\.jar'' +-d ''+/tmp/[0-9a-zA-Z/]+'' +\%t$') >= 0,
\ 'Invalid command string: ' . b:command \ 'Invalid command string: ' . b:command
let g:ale_java_javac_classpath = 'configured.jar:configured2.jar' let g:ale_java_javac_classpath = 'configured.jar:configured2.jar'
@ -59,7 +59,7 @@ Execute(The javac callback should combine discovered classpaths and manual ones)
\ '/xyz/abc.jar', \ '/xyz/abc.jar',
\]) \])
Assert match(b:command, '\v^javac +-Xlint +-cp +/foo/bar\.jar:/xyz/abc\.jar:configured\.jar:configured2\.jar +-d +/tmp/[0-9a-zA-Z/]+ +\%t$') >= 0, Assert match(b:command, '\v^javac +-Xlint +-cp +''/foo/bar\.jar:/xyz/abc\.jar:configured\.jar:configured2\.jar'' +-d +''/tmp/[0-9a-zA-Z/]+'' +\%t$') >= 0,
\ 'Invalid command string: ' . b:command \ 'Invalid command string: ' . b:command
Execute(The javac callback should detect source directories): Execute(The javac callback should detect source directories):
@ -69,7 +69,7 @@ Execute(The javac callback should detect source directories):
let b:command = ale_linters#java#javac#GetCommand(bufnr(''), []) let b:command = ale_linters#java#javac#GetCommand(bufnr(''), [])
Assert match(b:command, '\v^javac +-Xlint +-sourcepath /.*java_paths/src/main/java/ +-d +/tmp/[0-9a-zA-Z/]+ +\%t$') >= 0, Assert match(b:command, '\v^javac +-Xlint +-sourcepath ''/.*java_paths/src/main/java/'' +-d +''/tmp/[0-9a-zA-Z/]+'' +\%t$') >= 0,
\ 'Invalid command string: ' . b:command \ 'Invalid command string: ' . b:command
Execute(The javac callback should combine detected source directories and classpaths): Execute(The javac callback should combine detected source directories and classpaths):
@ -84,7 +84,7 @@ Execute(The javac callback should combine detected source directories and classp
\ '/xyz/abc.jar', \ '/xyz/abc.jar',
\]) \])
Assert match(b:command, '\v^javac +-Xlint +-cp +/foo/bar\.jar:/xyz/abc\.jar +-sourcepath /.*java_paths/src/main/java/ +-d +/tmp/[0-9a-zA-Z/]+ +\%t$') >= 0, Assert match(b:command, '\v^javac +-Xlint +-cp +''/foo/bar\.jar:/xyz/abc\.jar'' +-sourcepath ''/.*java_paths/src/main/java/'' +-d +''/tmp/[0-9a-zA-Z/]+'' +\%t$') >= 0,
\ 'Invalid command string: ' . b:command \ 'Invalid command string: ' . b:command
Execute(The javac callback should use g:ale_java_javac_options correctly): Execute(The javac callback should use g:ale_java_javac_options correctly):
@ -93,5 +93,5 @@ Execute(The javac callback should use g:ale_java_javac_options correctly):
let b:command = ale_linters#java#javac#GetCommand(bufnr(''), []) let b:command = ale_linters#java#javac#GetCommand(bufnr(''), [])
Assert match(b:command, '\v^javac +-Xlint +-d +/tmp/[0-9a-zA-Z/]+ --anything --else +\%t$') >= 0, Assert match(b:command, '\v^javac +-Xlint +-d +''/tmp/[0-9a-zA-Z/]+'' --anything --else +\%t$') >= 0,
\ 'Invalid command string: ' . b:command \ 'Invalid command string: ' . b:command

View file

@ -7,18 +7,18 @@ After:
let g:ale_lua_luacheck_executable = 'luacheck' let g:ale_lua_luacheck_executable = 'luacheck'
Execute(The lua luacheck command callback should return the correct default string): Execute(The lua luacheck command callback should return the correct default string):
AssertEqual 'luacheck --formatter plain --codes --filename %s -', AssertEqual '''luacheck'' --formatter plain --codes --filename %s -',
\ join(split(ale_linters#lua#luacheck#GetCommand(1))) \ join(split(ale_linters#lua#luacheck#GetCommand(1)))
Execute(The lua luacheck command callback should let you set options): Execute(The lua luacheck command callback should let you set options):
let g:ale_lua_luacheck_options = '--config filename' let g:ale_lua_luacheck_options = '--config filename'
AssertEqual 'luacheck --config filename --formatter plain --codes --filename %s -', AssertEqual '''luacheck'' --config filename --formatter plain --codes --filename %s -',
\ join(split(ale_linters#lua#luacheck#GetCommand(1))) \ join(split(ale_linters#lua#luacheck#GetCommand(1)))
Execute(The luacheck executable should be configurable): Execute(The luacheck executable should be configurable):
let g:ale_lua_luacheck_executable = 'luacheck.sh' let g:ale_lua_luacheck_executable = 'luacheck.sh'
AssertEqual 'luacheck.sh', ale_linters#lua#luacheck#GetExecutable(1) AssertEqual 'luacheck.sh', ale_linters#lua#luacheck#GetExecutable(1)
AssertEqual 'luacheck.sh --formatter plain --codes --filename %s -', AssertEqual '''luacheck.sh'' --formatter plain --codes --filename %s -',
\ join(split(ale_linters#lua#luacheck#GetCommand(1))) \ join(split(ale_linters#lua#luacheck#GetCommand(1)))

View file

@ -20,7 +20,7 @@ Execute(The mypy callbacks should return the correct default values):
\ 'mypy', \ 'mypy',
\ ale_linters#python#mypy#GetExecutable(bufnr('')) \ ale_linters#python#mypy#GetExecutable(bufnr(''))
AssertEqual AssertEqual
\ 'cd ' . g:dir . ' && mypy --show-column-numbers %s', \ 'cd ''' . g:dir . ''' && ''mypy'' --show-column-numbers %s',
\ ale_linters#python#mypy#GetCommand(bufnr('')) \ ale_linters#python#mypy#GetCommand(bufnr(''))
Execute(The mypy executable should be configurable, and escaped properly): Execute(The mypy executable should be configurable, and escaped properly):
@ -30,14 +30,14 @@ Execute(The mypy executable should be configurable, and escaped properly):
\ 'executable with spaces', \ 'executable with spaces',
\ ale_linters#python#mypy#GetExecutable(bufnr('')) \ ale_linters#python#mypy#GetExecutable(bufnr(''))
AssertEqual AssertEqual
\ 'cd ' . g:dir . ' && executable\ with\ spaces --show-column-numbers %s', \ 'cd ''' . g:dir . ''' && ''executable with spaces'' --show-column-numbers %s',
\ ale_linters#python#mypy#GetCommand(bufnr('')) \ ale_linters#python#mypy#GetCommand(bufnr(''))
Execute(The mypy command callback should let you set options): Execute(The mypy command callback should let you set options):
let g:ale_python_mypy_options = '--some-option' let g:ale_python_mypy_options = '--some-option'
AssertEqual AssertEqual
\ 'cd ' . g:dir . ' && mypy --show-column-numbers --some-option %s', \ 'cd ''' . g:dir . ''' && ''mypy'' --show-column-numbers --some-option %s',
\ ale_linters#python#mypy#GetCommand(bufnr('')) \ ale_linters#python#mypy#GetCommand(bufnr(''))
Execute(The mypy command should switch directories to the detected project root): Execute(The mypy command should switch directories to the detected project root):
@ -47,7 +47,7 @@ Execute(The mypy command should switch directories to the detected project root)
\ 'mypy', \ 'mypy',
\ ale_linters#python#mypy#GetExecutable(bufnr('')) \ ale_linters#python#mypy#GetExecutable(bufnr(''))
AssertEqual AssertEqual
\ 'cd ' . g:dir . '/python_paths/no_virtualenv/subdir && mypy --show-column-numbers %s', \ 'cd ''' . g:dir . '/python_paths/no_virtualenv/subdir'' && ''mypy'' --show-column-numbers %s',
\ ale_linters#python#mypy#GetCommand(bufnr('')) \ ale_linters#python#mypy#GetCommand(bufnr(''))
Execute(The mypy callbacks should detect virtualenv directories and switch to the project root): Execute(The mypy callbacks should detect virtualenv directories and switch to the project root):
@ -57,8 +57,8 @@ Execute(The mypy callbacks should detect virtualenv directories and switch to th
\ g:dir . '/python_paths/with_virtualenv/env/bin/mypy', \ g:dir . '/python_paths/with_virtualenv/env/bin/mypy',
\ ale_linters#python#mypy#GetExecutable(bufnr('')) \ ale_linters#python#mypy#GetExecutable(bufnr(''))
AssertEqual AssertEqual
\ 'cd ' . g:dir . '/python_paths/with_virtualenv/subdir && ' \ 'cd ''' . g:dir . '/python_paths/with_virtualenv/subdir'' && '''
\ . g:dir . '/python_paths/with_virtualenv/env/bin/mypy --show-column-numbers %s', \ . g:dir . '/python_paths/with_virtualenv/env/bin/mypy'' --show-column-numbers %s',
\ ale_linters#python#mypy#GetCommand(bufnr('')) \ ale_linters#python#mypy#GetCommand(bufnr(''))
Execute(You should able able to use the global mypy instead): Execute(You should able able to use the global mypy instead):
@ -69,5 +69,5 @@ Execute(You should able able to use the global mypy instead):
\ 'mypy', \ 'mypy',
\ ale_linters#python#mypy#GetExecutable(bufnr('')) \ ale_linters#python#mypy#GetExecutable(bufnr(''))
AssertEqual AssertEqual
\ 'cd ' . g:dir . '/python_paths/with_virtualenv/subdir && mypy --show-column-numbers %s', \ 'cd ''' . g:dir . '/python_paths/with_virtualenv/subdir'' && ''mypy'' --show-column-numbers %s',
\ ale_linters#python#mypy#GetCommand(bufnr('')) \ ale_linters#python#mypy#GetCommand(bufnr(''))

View file

@ -21,7 +21,7 @@ Execute(The pylint callbacks should return the correct default values):
\ 'pylint', \ 'pylint',
\ ale_linters#python#pylint#GetExecutable(bufnr('')) \ ale_linters#python#pylint#GetExecutable(bufnr(''))
AssertEqual AssertEqual
\ 'pylint ' . b:command_tail, \ '''pylint'' ' . b:command_tail,
\ ale_linters#python#pylint#GetCommand(bufnr('')) \ ale_linters#python#pylint#GetCommand(bufnr(''))
Execute(The pylint executable should be configurable, and escaped properly): Execute(The pylint executable should be configurable, and escaped properly):
@ -31,14 +31,14 @@ Execute(The pylint executable should be configurable, and escaped properly):
\ 'executable with spaces', \ 'executable with spaces',
\ ale_linters#python#pylint#GetExecutable(bufnr('')) \ ale_linters#python#pylint#GetExecutable(bufnr(''))
AssertEqual AssertEqual
\ 'executable\ with\ spaces ' . b:command_tail, \ '''executable with spaces'' ' . b:command_tail,
\ ale_linters#python#pylint#GetCommand(bufnr('')) \ ale_linters#python#pylint#GetCommand(bufnr(''))
Execute(The pylint command callback should let you set options): Execute(The pylint command callback should let you set options):
let g:ale_python_pylint_options = '--some-option' let g:ale_python_pylint_options = '--some-option'
AssertEqual AssertEqual
\ 'pylint --some-option' . b:command_tail, \ '''pylint'' --some-option' . b:command_tail,
\ ale_linters#python#pylint#GetCommand(bufnr('')) \ ale_linters#python#pylint#GetCommand(bufnr(''))
Execute(The pylint callbacks shouldn't detect virtualenv directories where they don't exist): Execute(The pylint callbacks shouldn't detect virtualenv directories where they don't exist):
@ -48,7 +48,7 @@ Execute(The pylint callbacks shouldn't detect virtualenv directories where they
\ 'pylint', \ 'pylint',
\ ale_linters#python#pylint#GetExecutable(bufnr('')) \ ale_linters#python#pylint#GetExecutable(bufnr(''))
AssertEqual AssertEqual
\ 'pylint ' . b:command_tail, \ '''pylint'' ' . b:command_tail,
\ ale_linters#python#pylint#GetCommand(bufnr('')) \ ale_linters#python#pylint#GetCommand(bufnr(''))
Execute(The pylint callbacks should detect virtualenv directories): Execute(The pylint callbacks should detect virtualenv directories):
@ -58,7 +58,7 @@ Execute(The pylint callbacks should detect virtualenv directories):
\ g:dir . '/python_paths/with_virtualenv/env/bin/pylint', \ g:dir . '/python_paths/with_virtualenv/env/bin/pylint',
\ ale_linters#python#pylint#GetExecutable(bufnr('')) \ ale_linters#python#pylint#GetExecutable(bufnr(''))
AssertEqual AssertEqual
\ g:dir . '/python_paths/with_virtualenv/env/bin/pylint ' . b:command_tail, \ ''''. g:dir . '/python_paths/with_virtualenv/env/bin/pylint'' ' . b:command_tail,
\ ale_linters#python#pylint#GetCommand(bufnr('')) \ ale_linters#python#pylint#GetCommand(bufnr(''))
Execute(You should able able to use the global pylint instead): Execute(You should able able to use the global pylint instead):
@ -69,5 +69,5 @@ Execute(You should able able to use the global pylint instead):
\ 'pylint', \ 'pylint',
\ ale_linters#python#pylint#GetExecutable(bufnr('')) \ ale_linters#python#pylint#GetExecutable(bufnr(''))
AssertEqual AssertEqual
\ 'pylint ' . b:command_tail, \ '''pylint'' ' . b:command_tail,
\ ale_linters#python#pylint#GetCommand(bufnr('')) \ ale_linters#python#pylint#GetCommand(bufnr(''))

View file

@ -11,12 +11,33 @@ Execute(HandleCSSLintFormat should handle CSS errors):
\ 'lnum': 2, \ 'lnum': 2,
\ 'col': 5, \ 'col': 5,
\ 'type': 'W', \ 'type': 'W',
\ 'text': "(known-properties) Expected ... but found 'wat'.", \ 'text': '(known-properties) Expected ... but found ''wat''.',
\ }, \ },
\ ], \ ],
\ ale#handlers#css#HandleCSSLintFormat(42, [ \ ale#handlers#css#HandleCSSLintFormat(42, [
\ 'something.css: line 2, col 1, Error - Expected RBRACE at line 2, col 1. (errors)', \ 'something.css: line 2, col 1, Error - Expected RBRACE at line 2, col 1. (errors)',
\ "something.css: line 2, col 5, Warning - Expected ... but found 'wat'. (known-properties)", \ 'something.css: line 2, col 5, Warning - Expected ... but found ''wat''. (known-properties)',
\ ])
Execute(HandleCSSLintFormat should handle CSS errors without groups):
AssertEqual
\ [
\ {
\ 'lnum': 7,
\ 'col': 3,
\ 'type': 'W',
\ 'text': 'Unknown property ''fill''.',
\ },
\ {
\ 'lnum': 8,
\ 'col': 3,
\ 'type': 'W',
\ 'text': 'Unknown property ''fill-opacity''.',
\ },
\ ],
\ ale#handlers#css#HandleCSSLintFormat(42, [
\ 'something.css: line 7, col 3, Warning - Unknown property ''fill''.',
\ 'something.css: line 8, col 3, Warning - Unknown property ''fill-opacity''.',
\ ]) \ ])
Execute (HandlePEP8Format should handle the correct lines of output): Execute (HandlePEP8Format should handle the correct lines of output):

View file

@ -46,6 +46,33 @@ Execute(The ember-template-lint handler should parse lines correctly):
\ ], \ ],
\ ale_linters#handlebars#embertemplatelint#Handle(347, input_lines) \ ale_linters#handlebars#embertemplatelint#Handle(347, input_lines)
Execute(The ember-template-lint handler should handle template parsing error correctly):
let input_lines = split('{
\ "/ember-project/app/templates/application.hbs": [
\ {
\ "fatal": true,
\ "moduleId": "app/templates/application",
\ "message": "Parse error on line 5 ...",
\ "line": 1,
\ "column": 1,
\ "source": "Error: Parse error on line 5 ...",
\ "severity": 2
\ }
\ ]
\ }', '\n')
AssertEqual
\ [
\ {
\ 'bufnr': 347,
\ 'lnum': 1,
\ 'col': 1,
\ 'text': 'Parse error on line 5 ...',
\ 'type': 'E',
\ },
\ ],
\ ale_linters#handlebars#embertemplatelint#Handle(347, input_lines)
Execute(The ember-template-lint handler should handle no lint errors/warnings): Execute(The ember-template-lint handler should handle no lint errors/warnings):
AssertEqual AssertEqual
\ [ \ [

View file

@ -30,7 +30,7 @@ Execute (The gometalinter handler should handle names with spaces):
\ ]), 'v:val[1:5]') \ ]), 'v:val[1:5]')
Execute (The gometalinter handler should handle relative paths correctly): Execute (The gometalinter handler should handle relative paths correctly):
:file! /foo/bar/baz.go silent file /foo/bar/baz.go
AssertEqual AssertEqual
\ [ \ [
@ -47,7 +47,28 @@ Execute (The gometalinter handler should handle relative paths correctly):
\ 'type': 'E', \ 'type': 'E',
\ }, \ },
\ ], \ ],
\ ale_linters#go#gometalinter#Handler(42, [ \ ale_linters#go#gometalinter#Handler(bufnr(''), [
\ 'baz.go:12:3:warning: expected ''package'', found ''IDENT'' gibberish (staticcheck)', \ 'baz.go:12:3:warning: expected ''package'', found ''IDENT'' gibberish (staticcheck)',
\ 'baz.go:37:5:error: expected ''package'', found ''IDENT'' gibberish (golint)', \ 'baz.go:37:5:error: expected ''package'', found ''IDENT'' gibberish (golint)',
\ ]) \ ])
Execute (The gometalinter handler should filter out errors from other files):
silent file! /some/path/sql.go
AssertEqual
\ [],
\ ale_linters#go#gometalinter#Handler(bufnr(''), [
\ '/some/path/interface_implementation_test.go:417::warning: cyclomatic complexity 24 of function testGetUserHeaders() is high (> 10) (gocyclo)',
\ '/some/path/sql_helpers.go:38::warning: cyclomatic complexity 11 of function CreateTestUserMetadataDB() is high (> 10) (gocyclo)',
\ '/some/path/sql_alpha.go:560:7:warning: ineffectual assignment to err (ineffassign)',
\ '/some/path/sql_alpha.go:589:7:warning: ineffectual assignment to err (ineffassign)',
\ '/some/path/sql_test.go:124:9:warning: should not use basic type untyped string as key in context.WithValue (golint)',
\ '/some/path/interface_implementation_test.go:640::warning: declaration of "cfg" shadows declaration at sql_test.go:21 (vetshadow)',
\ '/some/path/sql_helpers.go:55::warning: declaration of "err" shadows declaration at sql_helpers.go:48 (vetshadow)',
\ '/some/path/sql_helpers.go:91::warning: declaration of "err" shadows declaration at sql_helpers.go:48 (vetshadow)',
\ '/some/path/sql_helpers.go:108::warning: declaration of "err" shadows declaration at sql_helpers.go:48 (vetshadow)',
\ '/some/path/user_metadata_db.go:149::warning: declaration of "err" shadows declaration at user_metadata_db.go:140 (vetshadow)',
\ '/some/path/user_metadata_db.go:188::warning: declaration of "err" shadows declaration at user_metadata_db.go:179 (vetshadow)',
\ '/some/path/queries_alpha.go:62::warning: Potential hardcoded credentials,HIGH,LOW (gas)',
\ ])

View file

@ -48,14 +48,14 @@ Execute(The php handler should parse lines correctly):
\ ], \ ],
\ ale_linters#php#php#Handle(347, [ \ ale_linters#php#php#Handle(347, [
\ 'This line should be ignored completely', \ 'This line should be ignored completely',
\ "Parse error: syntax error, This line should be ignored completely in - on line 1", \ "PHP Parse error: syntax error, This line should be ignored completely in - on line 1",
\ "PHP Parse error: syntax error, unexpected ';', expecting ']' in - on line 1", \ "Parse error: syntax error, unexpected ';', expecting ']' in - on line 1",
\ "PHP Parse error: syntax error, unexpected '/', expecting function (T_FUNCTION) or const (T_CONST) in - on line 2", \ "Parse error: syntax error, unexpected '/', expecting function (T_FUNCTION) or const (T_CONST) in - on line 2",
\ "PHP Parse error: syntax error, unexpected ')' in - on line 3", \ "Parse error: syntax error, unexpected ')' in - on line 3",
\ "PHP Parse error: syntax error, unexpected ''bar'' (T_CONSTANT_ENCAPSED_STRING), expecting ']' in - on line 4", \ "Parse error: syntax error, unexpected ''bar'' (T_CONSTANT_ENCAPSED_STRING), expecting ']' in - on line 4",
\ "PHP Fatal error: Cannot redeclare count() in - on line 5", \ "Fatal error: Cannot redeclare count() in - on line 5",
\ 'PHP Parse error: syntax error, unexpected end of file in - on line 21', \ 'Parse error: syntax error, unexpected end of file in - on line 21',
\ 'PHP Parse error: Invalid numeric literal in - on line 47', \ 'Parse error: Invalid numeric literal in - on line 47',
\ ]) \ ])
After: After:

View file

@ -0,0 +1,53 @@
Before:
runtime ale_linters/python/pylint.vim
After:
call ale#linter#Reset()
silent file something_else.py
Execute(pylint handler parsing, translating columns to 1-based index):
AssertEqual
\ [
\ {
\ 'lnum': 4,
\ 'col': 1,
\ 'text': 'C0303: Trailing whitespace',
\ 'type': 'W',
\ },
\ {
\ 'lnum': 1,
\ 'col': 1,
\ 'text': 'C0111: Missing module docstring',
\ 'type': 'W',
\ },
\ {
\ 'lnum': 2,
\ 'col': 1,
\ 'text': 'C0111: Missing function docstring',
\ 'type': 'W',
\ },
\ {
\ 'lnum': 3,
\ 'col': 5,
\ 'text': 'E0103: ''break'' not properly in loop',
\ 'type': 'E',
\ },
\ {
\ 'lnum': 4,
\ 'col': 5,
\ 'text': 'W0101: Unreachable code',
\ 'type': 'W',
\ },
\ ],
\ ale_linters#python#pylint#Handle(bufnr(''), [
\ 'No config file found, using default configuration',
\ '************* Module test',
\ 'test.py:4:0: C0303 (trailing-whitespace) Trailing whitespace',
\ 'test.py:1:0: C0111 (missing-docstring) Missing module docstring',
\ 'test.py:2:0: C0111 (missing-docstring) Missing function docstring',
\ 'test.py:3:4: E0103 (not-in-loop) ''break'' not properly in loop',
\ 'test.py:4:4: W0101 (unreachable) Unreachable code',
\ '',
\ '------------------------------------------------------------------',
\ 'Your code has been rated at 0.00/10 (previous run: 2.50/10, -2.50)',
\ ])

View file

@ -16,7 +16,7 @@ Execute(--config should be set when the .csslintrc file is found):
AssertEqual AssertEqual
\ ( \ (
\ 'csslint --format=compact ' \ 'csslint --format=compact '
\ . '--config=' . fnameescape(g:dir . '/csslint-test-files/some-app/.csslintrc') \ . '--config=' . shellescape(g:dir . '/csslint-test-files/some-app/.csslintrc')
\ . ' %t' \ . ' %t'
\ ), \ ),
\ ale_linters#css#csslint#GetCommand(bufnr('')) \ ale_linters#css#csslint#GetCommand(bufnr(''))

View file

@ -8,7 +8,7 @@ Execute(flow should return a command to run if a .flowconfig file exists):
silent! cd /testplugin/test silent! cd /testplugin/test
:e! flow/a/sub/dummy :e! flow/a/sub/dummy
AssertEqual 'flow check-contents --respect-pragma --json --from ale %s', ale_linters#javascript#flow#GetCommand(bufnr('%')) AssertEqual '''flow'' check-contents --respect-pragma --json --from ale %s', ale_linters#javascript#flow#GetCommand(bufnr('%'))
Execute(flow should not return a command to run if no .flowconfig file exists): Execute(flow should not return a command to run if no .flowconfig file exists):
silent! cd /testplugin/test silent! cd /testplugin/test

View file

@ -1,6 +1,6 @@
Before: Before:
silent! cd /testplugin/test silent! cd /testplugin/test
:e! top/middle/bottom/dummy.txt silent file top/middle/bottom/dummy.txt
After: After:
unlet! g:result unlet! g:result
@ -13,29 +13,29 @@ Execute(FormatCommand should handle %%, and ignore other percents):
AssertEqual ['', '% %%d %%f %x %'], ale#engine#FormatCommand(bufnr('%'), '%% %%%d %%%f %x %') AssertEqual ['', '% %%d %%f %x %'], ale#engine#FormatCommand(bufnr('%'), '%% %%%d %%%f %x %')
Execute(FormatCommand should convert %s to the current filename): Execute(FormatCommand should convert %s to the current filename):
AssertEqual ['', 'foo ' . fnameescape(expand('%:p')) . ' bar ' . fnameescape(expand('%:p'))], ale#engine#FormatCommand(bufnr('%'), 'foo %s bar %s') AssertEqual ['', 'foo ' . shellescape(expand('%:p')) . ' bar ' . shellescape(expand('%:p'))], ale#engine#FormatCommand(bufnr('%'), 'foo %s bar %s')
Execute(FormatCommand should convert %t to a new temporary filename): Execute(FormatCommand should convert %t to a new temporary filename):
let g:result = ale#engine#FormatCommand(bufnr('%'), 'foo %t bar %t') let g:result = ale#engine#FormatCommand(bufnr('%'), 'foo %t bar %t')
let g:match = matchlist(g:result[1], '\v^foo (/tmp/.*/dummy.txt) bar (/tmp/.*/dummy.txt)$') let g:match = matchlist(g:result[1], '\v^foo (''/tmp/[^'']*/dummy.txt'') bar (''/tmp/[^'']*/dummy.txt'')$')
Assert !empty(g:match), 'No match found! Result was: ' . g:result[1] Assert !empty(g:match), 'No match found! Result was: ' . g:result[1]
" The first item of the result should be a temporary filename, and it should " The first item of the result should be a temporary filename, and it should
" be the same as the escaped name in the command string. " be the same as the escaped name in the command string.
AssertEqual g:result[0], fnameescape(g:match[1]) AssertEqual shellescape(g:result[0]), g:match[1]
" The two temporary filenames formatted in should be the same. " The two temporary filenames formatted in should be the same.
AssertEqual g:match[1], g:match[2] AssertEqual g:match[1], g:match[2]
Execute(FormatCommand should let you combine %s and %t): Execute(FormatCommand should let you combine %s and %t):
let g:result = ale#engine#FormatCommand(bufnr('%'), 'foo %t bar %s') let g:result = ale#engine#FormatCommand(bufnr('%'), 'foo %t bar %s')
let g:match = matchlist(g:result[1], '\v^foo (/tmp/.*/dummy.txt) bar (.*/dummy.txt)$') let g:match = matchlist(g:result[1], '\v^foo (''/tmp/.*/dummy.txt'') bar (''.*/dummy.txt'')$')
Assert !empty(g:match), 'No match found! Result was: ' . g:result[1] Assert !empty(g:match), 'No match found! Result was: ' . g:result[1]
" The first item of the result should be a temporary filename, and it should " The first item of the result should be a temporary filename, and it should
" be the same as the escaped name in the command string. " be the same as the escaped name in the command string.
AssertEqual g:result[0], fnameescape(g:match[1]) AssertEqual shellescape(g:result[0]), g:match[1]
" The second item should be equal to the original filename. " The second item should be equal to the original filename.
AssertEqual fnameescape(expand('%:p')), g:match[2] AssertEqual shellescape(expand('%:p')), g:match[2]
Execute(EscapeCommandPart should escape all percent signs): Execute(EscapeCommandPart should escape all percent signs):
AssertEqual '%%s %%t %%%% %%s %%t %%%%', ale#engine#EscapeCommandPart('%s %t %% %s %t %%') AssertEqual '%%s %%t %%%% %%s %%t %%%%', ale#engine#EscapeCommandPart('%s %t %% %s %t %%')

View file

@ -96,8 +96,10 @@ Execute(Highlights set by ALE should be removed when buffer cleanup is done):
Execute(Highlights should be cleared when buffers are hidden): Execute(Highlights should be cleared when buffers are hidden):
call ale#engine#InitBufferInfo(bufnr('%')) call ale#engine#InitBufferInfo(bufnr('%'))
" The second item should be ignored, as it has no column infomration.
let g:ale_buffer_info[bufnr('%')].loclist = [ let g:ale_buffer_info[bufnr('%')].loclist = [
\ {'bufnr': bufnr('%'), 'type': 'E', 'lnum': 3, 'col': 2}, \ {'bufnr': bufnr('%'), 'type': 'E', 'lnum': 3, 'col': 2},
\ {'bufnr': bufnr('%'), 'type': 'E', 'lnum': 4, 'col': 0},
\] \]
call ale#highlight#SetHighlights( call ale#highlight#SetHighlights(
\ bufnr('%'), \ bufnr('%'),

View file

@ -2,8 +2,7 @@ Before:
silent! cd /testplugin/test/util silent! cd /testplugin/test/util
Execute(CdString should output the correct command string): Execute(CdString should output the correct command string):
AssertEqual 'cd /foo\ bar/baz && ', ale#path#CdString('/foo bar/baz') AssertEqual 'cd ''/foo bar/baz'' && ', ale#path#CdString('/foo bar/baz')
Execute(BufferCdString should output the correct command string): Execute(BufferCdString should output the correct command string):
Assert match(ale#path#BufferCdString(bufnr('')), '^cd .*test/util && $') >= 0, AssertEqual 'cd ' . shellescape(getcwd()) . ' && ', ale#path#BufferCdString(bufnr(''))
\ 'String didn''t match regex: ' . ale#path#BufferCdString(bufnr(''))