summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md1
-rw-r--r--ale_linters/bib/bibclean.vim49
-rw-r--r--ale_linters/c/flawfinder.vim12
-rw-r--r--ale_linters/clojure/joker.vim2
-rw-r--r--ale_linters/cpp/flawfinder.vim12
-rw-r--r--ale_linters/crystal/ameba.vim4
-rw-r--r--ale_linters/cypher/cypher_lint.vim26
-rw-r--r--ale_linters/elm/make.vim8
-rw-r--r--ale_linters/go/langserver.vim4
-rw-r--r--ale_linters/hack/hhast.vim2
-rw-r--r--ale_linters/haskell/hie.vim26
-rw-r--r--ale_linters/idris/idris.vim8
-rw-r--r--ale_linters/java/javalsp.vim4
-rwxr-xr-xale_linters/javascript/flow.vim3
-rw-r--r--ale_linters/kotlin/kotlinc.vim2
-rw-r--r--ale_linters/markdown/markdownlint.vim14
-rw-r--r--ale_linters/perl6/perl6.vim14
-rw-r--r--ale_linters/python/pylint.vim2
-rw-r--r--ale_linters/slim/slimlint.vim10
-rw-r--r--ale_linters/swift/swiftlint.vim18
-rw-r--r--ale_linters/verilog/vlog.vim10
-rw-r--r--ale_linters/verilog/xvlog.vim10
-rw-r--r--ale_linters/vhdl/ghdl.vim2
-rw-r--r--ale_linters/vhdl/vcom.vim10
-rw-r--r--ale_linters/vhdl/xvhdl.vim10
-rw-r--r--ale_linters/xml/xmllint.vim24
-rw-r--r--autoload/ale/args.vim43
-rw-r--r--autoload/ale/c.vim12
-rw-r--r--autoload/ale/command.vim203
-rw-r--r--autoload/ale/completion.vim6
-rw-r--r--autoload/ale/engine.vim275
-rw-r--r--autoload/ale/filetypes.vim2
-rw-r--r--autoload/ale/fix.vim163
-rw-r--r--autoload/ale/fixers/jq.vim20
-rw-r--r--autoload/ale/fixers/prettier.vim4
-rw-r--r--autoload/ale/fixers/qmlfmt.vim6
-rw-r--r--autoload/ale/fixers/stylelint.vim9
-rw-r--r--autoload/ale/go.vim12
-rw-r--r--autoload/ale/handlers/flawfinder.vim3
-rw-r--r--autoload/ale/handlers/haskell.vim8
-rw-r--r--autoload/ale/handlers/markdownlint.vim8
-rw-r--r--autoload/ale/handlers/sml.vim31
-rw-r--r--autoload/ale/hover.vim4
-rw-r--r--autoload/ale/job.vim6
-rw-r--r--autoload/ale/lsp/response.vim16
-rw-r--r--autoload/ale/lsp_linter.vim13
-rw-r--r--autoload/ale/preview.vim3
-rw-r--r--autoload/ale/python.vim2
-rw-r--r--autoload/ale/ruby.vim2
-rw-r--r--autoload/ale/sign.vim2
-rw-r--r--autoload/ale/statusline.vim6
-rw-r--r--autoload/ale/symbol.vim22
-rw-r--r--autoload/ale/test.vim106
-rw-r--r--doc/ale-java.txt25
-rw-r--r--doc/ale.txt13
-rw-r--r--plugin/ale.vim2
-rw-r--r--test/command_callback/test_cypher_cypher_lint_command_callback.vader8
-rw-r--r--test/command_callback/test_javalsp_command_callback.vader4
-rw-r--r--test/completion/test_lsp_completion_messages.vader4
-rw-r--r--test/fix/test_ale_fix.vader59
-rw-r--r--test/handler/test_cypher_lint_handler.vader21
-rw-r--r--test/handler/test_flow_handler.vader3
-rw-r--r--test/lsp/test_reset_lsp.vader12
-rwxr-xr-xtest/script/block-padding-checker25
-rw-r--r--test/sign/test_linting_sets_signs.vader1
-rw-r--r--test/sign/test_sign_placement.vader1
-rw-r--r--test/smoke_test.vader8
-rw-r--r--test/test_ale_lint_command.vader4
-rw-r--r--test/test_ale_toggle.vader19
-rw-r--r--test/test_command_chain.vader3
-rw-r--r--test/test_errors_removed_after_filetype_changed.vader7
-rw-r--r--test/test_format_temporary_file_creation.vader3
-rw-r--r--test/test_highlight_placement.vader3
-rw-r--r--test/test_history_saving.vader68
-rw-r--r--test/test_lint_file_linters.vader20
-rw-r--r--test/test_lint_on_enter_when_file_changed.vader2
-rw-r--r--test/test_linting_blacklist.vader2
-rw-r--r--test/test_linting_updates_loclist.vader1
-rw-r--r--test/test_no_linting_on_write_quit.vader8
-rw-r--r--test/test_parse_command_args.vader52
-rw-r--r--test/test_symbol_search.vader18
-rw-r--r--test/test_temporary_file_management.vader10
82 files changed, 1012 insertions, 668 deletions
diff --git a/README.md b/README.md
index 03173c91..fa067545 100644
--- a/README.md
+++ b/README.md
@@ -118,6 +118,7 @@ formatting.
| Crystal | [ameba](https://github.com/veelenga/ameba) !!, [crystal](https://crystal-lang.org/) !! |
| CSS | [csslint](http://csslint.net/), [prettier](https://github.com/prettier/prettier), [stylelint](https://github.com/stylelint/stylelint) |
| Cucumber | [cucumber](https://cucumber.io/) |
+| Cypher | [cypher-lint](https://github.com/cleishm/libcypher-parser) |
| Cython (pyrex filetype) | [cython](http://cython.org/) |
| D | [dls](https://github.com/d-language-server/dls), [dmd](https://dlang.org/dmd-linux.html), [uncrustify](https://github.com/uncrustify/uncrustify) |
| Dafny | [dafny](https://rise4fun.com/Dafny) !! |
diff --git a/ale_linters/bib/bibclean.vim b/ale_linters/bib/bibclean.vim
index 6750f22f..1c6b55d0 100644
--- a/ale_linters/bib/bibclean.vim
+++ b/ale_linters/bib/bibclean.vim
@@ -11,9 +11,9 @@ endfunction
function! ale_linters#bib#bibclean#get_type(str) abort
if a:str is# '??'
- return 'E'
+ return 'E'
else
- return 'W'
+ return 'W'
endif
endfunction
@@ -36,30 +36,31 @@ function! ale_linters#bib#bibclean#Handle(buffer, lines) abort
let l:msg = ''
for l:line in a:lines
- if empty(l:msg)
- let l:mlist = ale_linters#bib#bibclean#match_msg(l:line)
+ if empty(l:msg)
+ let l:mlist = ale_linters#bib#bibclean#match_msg(l:line)
- if !empty(l:mlist)
- let l:msg = l:mlist[3]
- let l:type = ale_linters#bib#bibclean#get_type(l:mlist[1])
- endif
- else
- if l:type is# 'E'
- let l:mlist = ale_linters#bib#bibclean#match_entry(l:line)
- else
- let l:mlist = ale_linters#bib#bibclean#match_value(l:line)
- endif
+ if !empty(l:mlist)
+ let l:msg = l:mlist[3]
+ let l:type = ale_linters#bib#bibclean#get_type(l:mlist[1])
+ endif
+ else
+ if l:type is# 'E'
+ let l:mlist = ale_linters#bib#bibclean#match_entry(l:line)
+ else
+ let l:mlist = ale_linters#bib#bibclean#match_value(l:line)
+ endif
- if !empty(l:mlist)
- call add(l:output, {
- \ 'lnum': l:mlist[1],
- \ 'col': l:mlist[2],
- \ 'text': l:msg,
- \ 'type': l:type
- \})
- let l:msg = ''
- endif
- endif
+ if !empty(l:mlist)
+ call add(l:output, {
+ \ 'lnum': l:mlist[1],
+ \ 'col': l:mlist[2],
+ \ 'text': l:msg,
+ \ 'type': l:type
+ \})
+
+ let l:msg = ''
+ endif
+ endif
endfor
return l:output
diff --git a/ale_linters/c/flawfinder.vim b/ale_linters/c/flawfinder.vim
index 7e1f6769..94104141 100644
--- a/ale_linters/c/flawfinder.vim
+++ b/ale_linters/c/flawfinder.vim
@@ -7,13 +7,13 @@ call ale#Set('c_flawfinder_minlevel', 1)
call ale#Set('c_flawfinder_error_severity', 6)
function! ale_linters#c#flawfinder#GetCommand(buffer) abort
- " Set the minimum vulnerability level for flawfinder to bother with
- let l:minlevel = ' --minlevel=' . ale#Var(a:buffer, 'c_flawfinder_minlevel')
+ " Set the minimum vulnerability level for flawfinder to bother with
+ let l:minlevel = ' --minlevel=' . ale#Var(a:buffer, 'c_flawfinder_minlevel')
- return '%e -CDQS'
- \ . ale#Pad(ale#Var(a:buffer, 'c_flawfinder_options'))
- \ . l:minlevel
- \ . ' %t'
+ return '%e -CDQS'
+ \ . ale#Pad(ale#Var(a:buffer, 'c_flawfinder_options'))
+ \ . l:minlevel
+ \ . ' %t'
endfunction
call ale#linter#Define('c', {
diff --git a/ale_linters/clojure/joker.vim b/ale_linters/clojure/joker.vim
index 2f61148b..1f17cd31 100644
--- a/ale_linters/clojure/joker.vim
+++ b/ale_linters/clojure/joker.vim
@@ -11,7 +11,7 @@ function! ale_linters#clojure#joker#HandleJokerFormat(buffer, lines) abort
let l:type = 'E'
if l:match[4] is? 'Parse warning'
- let l:type = 'W'
+ let l:type = 'W'
endif
call add(l:output, {
diff --git a/ale_linters/cpp/flawfinder.vim b/ale_linters/cpp/flawfinder.vim
index 4f669bff..0a966604 100644
--- a/ale_linters/cpp/flawfinder.vim
+++ b/ale_linters/cpp/flawfinder.vim
@@ -7,13 +7,13 @@ call ale#Set('cpp_flawfinder_minlevel', 1)
call ale#Set('c_flawfinder_error_severity', 6)
function! ale_linters#cpp#flawfinder#GetCommand(buffer) abort
- " Set the minimum vulnerability level for flawfinder to bother with
- let l:minlevel = ' --minlevel=' . ale#Var(a:buffer, 'cpp_flawfinder_minlevel')
+ " Set the minimum vulnerability level for flawfinder to bother with
+ let l:minlevel = ' --minlevel=' . ale#Var(a:buffer, 'cpp_flawfinder_minlevel')
- return '%e -CDQS'
- \ . ale#Var(a:buffer, 'cpp_flawfinder_options')
- \ . l:minlevel
- \ . ' %t'
+ return '%e -CDQS'
+ \ . ale#Var(a:buffer, 'cpp_flawfinder_options')
+ \ . l:minlevel
+ \ . ' %t'
endfunction
call ale#linter#Define('cpp', {
diff --git a/ale_linters/crystal/ameba.vim b/ale_linters/crystal/ameba.vim
index 165cabd0..a1bf9c1d 100644
--- a/ale_linters/crystal/ameba.vim
+++ b/ale_linters/crystal/ameba.vim
@@ -14,7 +14,7 @@ endfunction
" Handle output from ameba
function! ale_linters#crystal#ameba#HandleAmebaOutput(buffer, lines) abort
if len(a:lines) == 0
- return []
+ return []
endif
let l:errors = ale#util#FuzzyJSONDecode(a:lines[0], {})
@@ -32,7 +32,7 @@ function! ale_linters#crystal#ameba#HandleAmebaOutput(buffer, lines) abort
let l:end_col = str2nr(l:error['end_location']['column'])
if !l:end_col
- let l:end_col = l:start_col + 1
+ let l:end_col = l:start_col + 1
endif
call add(l:output, {
diff --git a/ale_linters/cypher/cypher_lint.vim b/ale_linters/cypher/cypher_lint.vim
new file mode 100644
index 00000000..408ddd6e
--- /dev/null
+++ b/ale_linters/cypher/cypher_lint.vim
@@ -0,0 +1,26 @@
+" Author: Francisco Lopes <francisco@oblita.com>
+" Description: Linting for Neo4j's Cypher
+
+function! ale_linters#cypher#cypher_lint#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)
+ call add(l:output, {
+ \ 'lnum': l:match[2] + 0,
+ \ 'col': l:match[3] + 0,
+ \ 'text': l:match[4],
+ \ 'type': 'E',
+ \})
+ endfor
+
+ return l:output
+endfunction
+
+call ale#linter#Define('cypher', {
+\ 'name': 'cypher_lint',
+\ 'executable': 'cypher-lint',
+\ 'command': 'cypher-lint',
+\ 'output_stream': 'stderr',
+\ 'callback': 'ale_linters#cypher#cypher_lint#Handle',
+\})
diff --git a/ale_linters/elm/make.vim b/ale_linters/elm/make.vim
index 325689fe..190f7541 100644
--- a/ale_linters/elm/make.vim
+++ b/ale_linters/elm/make.vim
@@ -222,10 +222,10 @@ function! ale_linters#elm#make#GetExecutable(buffer) abort
if l:is_test && l:is_v19
return ale#node#FindExecutable(
-\ a:buffer,
-\ 'elm_make',
-\ ['node_modules/.bin/elm-test', 'node_modules/.bin/elm']
-\ )
+ \ a:buffer,
+ \ 'elm_make',
+ \ ['node_modules/.bin/elm-test', 'node_modules/.bin/elm']
+ \)
else
return ale#node#FindExecutable(a:buffer, 'elm_make', ['node_modules/.bin/elm'])
endif
diff --git a/ale_linters/go/langserver.vim b/ale_linters/go/langserver.vim
index df956483..e049be7b 100644
--- a/ale_linters/go/langserver.vim
+++ b/ale_linters/go/langserver.vim
@@ -10,8 +10,8 @@ function! ale_linters#go#langserver#GetCommand(buffer) abort
let l:options = substitute(l:options, '-gocodecompletion', '', 'g')
let l:options = filter(split(l:options, ' '), 'empty(v:val) != 1')
- if(ale#Var(a:buffer, 'completion_enabled') == 1)
- call add(l:options, '-gocodecompletion')
+ if ale#Var(a:buffer, 'completion_enabled')
+ call add(l:options, '-gocodecompletion')
endif
let l:options = uniq(sort(l:options))
diff --git a/ale_linters/hack/hhast.vim b/ale_linters/hack/hhast.vim
index 710b7b25..f6870b59 100644
--- a/ale_linters/hack/hhast.vim
+++ b/ale_linters/hack/hhast.vim
@@ -9,7 +9,7 @@ function! ale_linters#hack#hhast#GetProjectRoot(buffer) abort
let l:hhconfig = ale#path#FindNearestFile(a:buffer, '.hhconfig')
if empty(l:hhconfig)
- return ''
+ return ''
endif
let l:root = fnamemodify(l:hhconfig, ':h')
diff --git a/ale_linters/haskell/hie.vim b/ale_linters/haskell/hie.vim
index 3ff1180a..cc85fbed 100644
--- a/ale_linters/haskell/hie.vim
+++ b/ale_linters/haskell/hie.vim
@@ -9,33 +9,27 @@ function! ale_linters#haskell#hie#GetProjectRoot(buffer) abort
" If it's empty, search for the cabal file
if empty(l:project_file)
- let l:cabal_file = fnamemodify(bufname(a:buffer), ':p:h')
- let l:paths = ''
-
- while empty(matchstr(l:cabal_file, '^\(\/\|\(\w:\\\)\)$'))
- let l:cabal_file = fnamemodify(l:cabal_file, ':h')
- let l:paths = l:paths . l:cabal_file . ','
- endwhile
-
+ " Search all of the paths except for the root filesystem path.
+ let l:paths = join(
+ \ ale#path#Upwards(expand('#' . a:buffer . ':p:h'))[:-2],
+ \ ','
+ \)
let l:project_file = globpath(l:paths, '*.cabal')
endif
- " Either extract the project directory or take the current working
- " directory
- if !empty(l:project_file)
- let l:project_file = fnamemodify(l:project_file, ':h')
- else
- let l:project_file = expand('#' . a:buffer . ':p:h')
+ " If we still can't find one, use the current file.
+ if empty(l:project_file)
+ let l:project_file = expand('#' . a:buffer . ':p')
endif
- return l:project_file
+ return fnamemodify(l:project_file, ':h')
endfunction
function! ale_linters#haskell#hie#GetCommand(buffer) abort
let l:executable = ale#Var(a:buffer, 'haskell_hie_executable')
return ale#handlers#haskell_stack#EscapeExecutable(l:executable, 'hie')
-\ . ' --lsp'
+ \ . ' --lsp'
endfunction
call ale#linter#Define('haskell', {
diff --git a/ale_linters/idris/idris.vim b/ale_linters/idris/idris.vim
index feac0f10..42b88158 100644
--- a/ale_linters/idris/idris.vim
+++ b/ale_linters/idris/idris.vim
@@ -49,11 +49,11 @@ function! ale_linters#idris#idris#Handle(buffer, lines) abort
let l:errors = matchlist(l:match[5], '\v([wW]arning|[eE]rror) - ?(.*)')
if len(l:errors) > 0
- let l:ghc_type = l:errors[1]
- let l:text = l:errors[2]
+ let l:ghc_type = l:errors[1]
+ let l:text = l:errors[2]
else
- let l:ghc_type = ''
- let l:text = l:match[5][:0] is# ' ' ? l:match[5][1:] : l:match[5]
+ let l:ghc_type = ''
+ let l:text = l:match[5][:0] is# ' ' ? l:match[5][1:] : l:match[5]
endif
if l:ghc_type is? 'Warning'
diff --git a/ale_linters/java/javalsp.vim b/ale_linters/java/javalsp.vim
index 1436a52c..6329ab3c 100644
--- a/ale_linters/java/javalsp.vim
+++ b/ale_linters/java/javalsp.vim
@@ -1,7 +1,6 @@
" Author: Horacio Sanson <https://github.com/hsanson>
" Description: Support for the Java language server https://github.com/georgewfraser/vscode-javac
-call ale#Set('java_javalsp_jar', 'javacs.jar')
call ale#Set('java_javalsp_executable', 'java')
function! ale_linters#java#javalsp#Executable(buffer) abort
@@ -9,10 +8,9 @@ function! ale_linters#java#javalsp#Executable(buffer) abort
endfunction
function! ale_linters#java#javalsp#Command(buffer) abort
- let l:jar = ale#Var(a:buffer, 'java_javalsp_jar')
let l:executable = ale_linters#java#javalsp#Executable(a:buffer)
- return ale#Escape(l:executable) . ' -cp ' . l:jar . ' -Xverify:none org.javacs.Main'
+ return ale#Escape(l:executable) . ' -Xverify:none -m javacs/org.javacs.Main'
endfunction
call ale#linter#Define('java', {
diff --git a/ale_linters/javascript/flow.vim b/ale_linters/javascript/flow.vim
index a4664fda..0561ab74 100755
--- a/ale_linters/javascript/flow.vim
+++ b/ale_linters/javascript/flow.vim
@@ -156,7 +156,8 @@ function! ale_linters#javascript#flow#Handle(buffer, lines) abort
\}
if has_key(l:error, 'extra')
- let l:errorToAdd.detail = s:GetDetails(l:error)
+ let l:errorToAdd.detail = l:errorToAdd.text
+ \ . "\n" . s:GetDetails(l:error)
endif
call add(l:output, l:errorToAdd)
diff --git a/ale_linters/kotlin/kotlinc.vim b/ale_linters/kotlin/kotlinc.vim
index 4a993986..32dcc6d1 100644
--- a/ale_linters/kotlin/kotlinc.vim
+++ b/ale_linters/kotlin/kotlinc.vim
@@ -20,7 +20,7 @@ function! ale_linters#kotlin#kotlinc#GetImportPaths(buffer) abort
if !empty(l:pom_path) && executable('mvn')
return ale#path#CdString(fnamemodify(l:pom_path, ':h'))
- \ . 'mvn dependency:build-classpath'
+ \ . 'mvn dependency:build-classpath'
endif
let l:classpath_command = ale#gradle#BuildClasspathCommand(a:buffer)
diff --git a/ale_linters/markdown/markdownlint.vim b/ale_linters/markdown/markdownlint.vim
index 5c8af650..e935cbfe 100644
--- a/ale_linters/markdown/markdownlint.vim
+++ b/ale_linters/markdown/markdownlint.vim
@@ -2,10 +2,10 @@
" Description: Adds support for markdownlint
call ale#linter#Define('markdown', {
- \ 'name': 'markdownlint',
- \ 'executable': 'markdownlint',
- \ 'lint_file': 1,
- \ 'output_stream': 'both',
- \ 'command': 'markdownlint %s',
- \ 'callback': 'ale#handlers#markdownlint#Handle'
-\ })
+\ 'name': 'markdownlint',
+\ 'executable': 'markdownlint',
+\ 'lint_file': 1,
+\ 'output_stream': 'both',
+\ 'command': 'markdownlint %s',
+\ 'callback': 'ale#handlers#markdownlint#Handle'
+\})
diff --git a/ale_linters/perl6/perl6.vim b/ale_linters/perl6/perl6.vim
index b33a0c51..59042e57 100644
--- a/ale_linters/perl6/perl6.vim
+++ b/ale_linters/perl6/perl6.vim
@@ -36,8 +36,8 @@ function! ale_linters#perl6#perl6#ExtractError(dict, item, type, buffer) abort
endif
if has_key(a:dict[a:item], 'line') && !empty(a:dict[a:item]['line'])
- let l:line = a:dict[a:item]['line']
- let l:counter -= 1
+ let l:line = a:dict[a:item]['line']
+ let l:counter -= 1
endif
if has_key(a:dict[a:item], 'column') && !empty(a:dict[a:item]['column'])
@@ -61,7 +61,7 @@ function! ale_linters#perl6#perl6#ExtractError(dict, item, type, buffer) abort
" Currently, filenames and line numbers are not always given in the error output
if l:counter < 2
- \&& ( ale#path#IsBufferPath(a:buffer, l:file) || l:file is# '' )
+ \&& ( ale#path#IsBufferPath(a:buffer, l:file) || l:file is# '' )
return {
\ 'lnum': '' . l:line,
\ 'text': l:text,
@@ -83,7 +83,7 @@ function! ale_linters#perl6#perl6#Handle(buffer, lines) abort
endif
if a:lines[0] is# 'Syntax OK'
- return l:output
+ return l:output
endif
try
@@ -115,7 +115,7 @@ function! ale_linters#perl6#perl6#Handle(buffer, lines) abort
\ )
if l:result isnot# ''
- call add(l:output, l:result)
+ call add(l:output, l:result)
endif
endfor
endfor
@@ -133,7 +133,7 @@ function! ale_linters#perl6#perl6#Handle(buffer, lines) abort
\ )
if l:result isnot# ''
- call add(l:output, l:result)
+ call add(l:output, l:result)
endif
endfor
endfor
@@ -147,7 +147,7 @@ function! ale_linters#perl6#perl6#Handle(buffer, lines) abort
\ )
if l:result isnot# ''
- call add(l:output, l:result)
+ call add(l:output, l:result)
endif
endif
endfor
diff --git a/ale_linters/python/pylint.vim b/ale_linters/python/pylint.vim
index 01c3cb37..da845b7a 100644
--- a/ale_linters/python/pylint.vim
+++ b/ale_linters/python/pylint.vim
@@ -53,7 +53,7 @@ function! ale_linters#python#pylint#Handle(buffer, lines) abort
if l:code is# 'I0011'
" Skip 'Locally disabling' message
- continue
+ continue
endif
call add(l:output, {
diff --git a/ale_linters/slim/slimlint.vim b/ale_linters/slim/slimlint.vim
index 00c6b26c..a27736f8 100644
--- a/ale_linters/slim/slimlint.vim
+++ b/ale_linters/slim/slimlint.vim
@@ -11,11 +11,11 @@ function! ale_linters#slim#slimlint#GetCommand(buffer) abort
"
" See https://github.com/sds/slim-lint/blob/master/lib/slim_lint/linter/README.md#rubocop
if !empty(l:rubocop_config)
- if ale#Has('win32')
- let l:command = 'set SLIM_LINT_RUBOCOP_CONF=' . ale#Escape(l:rubocop_config) . ' && ' . l:command
- else
- let l:command = 'SLIM_LINT_RUBOCOP_CONF=' . ale#Escape(l:rubocop_config) . ' ' . l:command
- endif
+ if ale#Has('win32')
+ let l:command = 'set SLIM_LINT_RUBOCOP_CONF=' . ale#Escape(l:rubocop_config) . ' && ' . l:command
+ else
+ let l:command = 'SLIM_LINT_RUBOCOP_CONF=' . ale#Escape(l:rubocop_config) . ' ' . l:command
+ endif
endif
return l:command
diff --git a/ale_linters/swift/swiftlint.vim b/ale_linters/swift/swiftlint.vim
index a1150658..0f2ea8de 100644
--- a/ale_linters/swift/swiftlint.vim
+++ b/ale_linters/swift/swiftlint.vim
@@ -6,10 +6,10 @@ call ale#Set('swift_swiftlint_use_global', get(g:, 'ale_use_global_executables',
function! ale_linters#swift#swiftlint#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'swift_swiftlint', [
- \ 'Pods/SwiftLint/swiftlint',
- \ 'ios/Pods/SwiftLint/swiftlint',
- \ 'swiftlint',
- \])
+ \ 'Pods/SwiftLint/swiftlint',
+ \ 'ios/Pods/SwiftLint/swiftlint',
+ \ 'swiftlint',
+ \])
endfunction
function! ale_linters#swift#swiftlint#GetCommand(buffer) abort
@@ -17,7 +17,7 @@ function! ale_linters#swift#swiftlint#GetCommand(buffer) abort
let l:args = 'lint --use-stdin'
return ale#Escape(l:executable)
- \ . ' ' .l:args
+ \ . ' ' .l:args
endfunction
function! ale_linters#swift#swiftlint#Handle(buffer, lines) abort
@@ -26,10 +26,10 @@ function! ale_linters#swift#swiftlint#Handle(buffer, lines) abort
for l:match in ale#util#GetMatches(a:lines, l:pattern)
let l:item = {
- \ 'lnum': str2nr(l:match[2]),
- \ 'type': l:match[4] is# 'error' ? 'E' : 'W',
- \ 'text': l:match[5],
- \}
+ \ 'lnum': str2nr(l:match[2]),
+ \ 'type': l:match[4] is# 'error' ? 'E' : 'W',
+ \ 'text': l:match[5],
+ \}
if l:match[4] is# 'error'
let l:item.type = 'E'
diff --git a/ale_linters/verilog/vlog.vim b/ale_linters/verilog/vlog.vim
index 1a1fcb6a..c7686291 100644
--- a/ale_linters/verilog/vlog.vim
+++ b/ale_linters/verilog/vlog.vim
@@ -17,11 +17,11 @@ function! ale_linters#verilog#vlog#Handle(buffer, lines) abort
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
- call add(l:output, {
- \ 'lnum': l:match[2] + 0,
- \ 'type': l:match[1] is? 'Error' ? 'E' : 'W',
- \ 'text': l:match[3],
- \})
+ call add(l:output, {
+ \ 'lnum': l:match[2] + 0,
+ \ 'type': l:match[1] is? 'Error' ? 'E' : 'W',
+ \ 'text': l:match[3],
+ \})
endfor
return l:output
diff --git a/ale_linters/verilog/xvlog.vim b/ale_linters/verilog/xvlog.vim
index db2227cd..52498f8f 100644
--- a/ale_linters/verilog/xvlog.vim
+++ b/ale_linters/verilog/xvlog.vim
@@ -16,11 +16,11 @@ function! ale_linters#verilog#xvlog#Handle(buffer, lines) abort
" NOTE: `xvlog` only prints 'INFO' and 'ERROR' messages
for l:match in ale#util#GetMatches(a:lines, l:pattern)
- call add(l:output, {
- \ 'lnum': l:match[2] + 0,
- \ 'type': 'E',
- \ 'text': l:match[1],
- \})
+ call add(l:output, {
+ \ 'lnum': l:match[2] + 0,
+ \ 'type': 'E',
+ \ 'text': l:match[1],
+ \})
endfor
return l:output
diff --git a/ale_linters/vhdl/ghdl.vim b/ale_linters/vhdl/ghdl.vim
index 2aef6cd5..c21be242 100644
--- a/ale_linters/vhdl/ghdl.vim
+++ b/ale_linters/vhdl/ghdl.vim
@@ -6,7 +6,7 @@ call ale#Set('vhdl_ghdl_executable', 'ghdl')
call ale#Set('vhdl_ghdl_options', '--std=08')
function! ale_linters#vhdl#ghdl#GetCommand(buffer) abort
- return '%e -s ' . ale#Pad(ale#Var(a:buffer, 'vhdl_ghdl_options')) . ' %t'
+ return '%e -s ' . ale#Pad(ale#Var(a:buffer, 'vhdl_ghdl_options')) . ' %t'
endfunction
function! ale_linters#vhdl#ghdl#Handle(buffer, lines) abort
diff --git a/ale_linters/vhdl/vcom.vim b/ale_linters/vhdl/vcom.vim
index 3df5633e..e4631b68 100644
--- a/ale_linters/vhdl/vcom.vim
+++ b/ale_linters/vhdl/vcom.vim
@@ -19,11 +19,11 @@ function! ale_linters#vhdl#vcom#Handle(buffer, lines) abort
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
- call add(l:output, {
- \ 'lnum': l:match[2] + 0,
- \ 'type': l:match[1] is? 'Error' ? 'E' : 'W',
- \ 'text': l:match[3],
- \})
+ call add(l:output, {
+ \ 'lnum': l:match[2] + 0,
+ \ 'type': l:match[1] is? 'Error' ? 'E' : 'W',
+ \ 'text': l:match[3],
+ \})
endfor
return l:output
diff --git a/ale_linters/vhdl/xvhdl.vim b/ale_linters/vhdl/xvhdl.vim
index c8336eac..6e0d411d 100644
--- a/ale_linters/vhdl/xvhdl.vim
+++ b/ale_linters/vhdl/xvhdl.vim
@@ -18,11 +18,11 @@ function! ale_linters#vhdl#xvhdl#Handle(buffer, lines) abort
" NOTE: `xvhdl` only prints 'INFO' and 'ERROR' messages
for l:match in ale#util#GetMatches(a:lines, l:pattern)
- call add(l:output, {
- \ 'lnum': l:match[2] + 0,
- \ 'type': 'E',
- \ 'text': l:match[1],
- \})
+ call add(l:output, {
+ \ 'lnum': l:match[2] + 0,
+ \ 'type': 'E',
+ \ 'text': l:match[1],
+ \})
endfor
return l:output
diff --git a/ale_linters/xml/xmllint.vim b/ale_linters/xml/xmllint.vim
index 59f43d16..b003b096 100644
--- a/ale_linters/xml/xmllint.vim
+++ b/ale_linters/xml/xmllint.vim
@@ -29,27 +29,27 @@ function! ale_linters#xml#xmllint#Handle(buffer, lines) abort
let l:match_message = matchlist(l:line, l:pattern_message)
if !empty(l:match_message)
- let l:line = l:match_message[2] + 0
- let l:type = l:match_message[4] =~? 'warning' ? 'W' : 'E'
- let l:text = l:match_message[3]
+ let l:line = l:match_message[2] + 0
+ let l:type = l:match_message[4] =~? 'warning' ? 'W' : 'E'
+ let l:text = l:match_message[3]
- call add(l:output, {
- \ 'lnum': l:line,
- \ 'text': l:text,
- \ 'type': l:type,
- \})
+ call add(l:output, {
+ \ 'lnum': l:line,
+ \ 'text': l:text,
+ \ 'type': l:type,
+ \})
- continue
+ continue
endif
" Parse column position
let l:match_column_token = matchlist(l:line, l:pattern_column_token)
if !empty(l:output) && !empty(l:match_column_token)
- let l:previous = l:output[len(l:output) - 1]
- let l:previous['col'] = len(l:match_column_token[0])
+ let l:previous = l:output[len(l:output) - 1]
+ let l:previous['col'] = len(l:match_column_token[0])
- continue
+ continue
endif
endfor
diff --git a/autoload/ale/args.vim b/autoload/ale/args.vim
new file mode 100644
index 00000000..70afb2e5
--- /dev/null
+++ b/autoload/ale/args.vim
@@ -0,0 +1,43 @@
+" Author: w0rp <devw0rp@gmail.com>
+" Description: This module implements a function for parsing arguments for
+" commands.
+
+" Given a list of valid arguments like ['foo', 'bar'] and a string to parse,
+" parse the arguments from the string and return [parsed_args, remainder].
+"
+" Arguments must be prefixed in the string with a single minus (-), and a
+" double minus (--) denotes the end of arguments.
+function! ale#args#Parse(arg_list, string) abort
+ let l:parsed = {}
+ let l:end_of_args = 0
+ let l:word_list = split(a:string, ' ')
+ let l:index = 0
+
+ while l:index < len(l:word_list)
+ let l:word = l:word_list[l:index]
+
+ if l:word[:0] is# '-'
+ let l:index += 1
+
+ if l:word is# '--'
+ break
+ endif
+
+ let l:arg = l:word[1:]
+
+ if index(a:arg_list, l:arg) >= 0
+ let l:parsed[l:arg] = ''
+ else
+ throw 'Invalid argument: ' . l:word
+ endif
+ elseif l:word is# ''
+ let l:index += 1
+ else
+ break
+ endif
+ endwhile
+
+ let l:new_string = join(l:word_list[l:index :], ' ')
+
+ return [l:parsed, l:new_string]
+endfunction
diff --git a/autoload/ale/c.vim b/autoload/ale/c.vim
index 6ac2d398..d759b25a 100644
--- a/autoload/ale/c.vim
+++ b/autoload/ale/c.vim
@@ -86,8 +86,8 @@ function! ale#c#ParseCFlags(path_prefix, cflag_line) abort
let l:next_option_index = l:option_index + 1
" Join space-separated option
- while l:next_option_index < len(l:split_lines) &&
- \ stridx(l:split_lines[l:next_option_index], '-') != 0
+ while l:next_option_index < len(l:split_lines)
+ \&& stridx(l:split_lines[l:next_option_index], '-') != 0
let l:next_option_index += 1
endwhile
@@ -96,9 +96,9 @@ function! ale#c#ParseCFlags(path_prefix, cflag_line) abort
call insert(l:split_lines, l:option, l:option_index)
" Ignore invalid or conflicting options
- if stridx(l:option, '-') != 0 ||
- \ stridx(l:option, '-o') == 0 ||
- \ stridx(l:option, '-c') == 0
+ if stridx(l:option, '-') != 0
+ \|| stridx(l:option, '-o') == 0
+ \|| stridx(l:option, '-c') == 0
call remove(l:split_lines, l:option_index)
let l:option_index = l:option_index - 1
" Fix relative path
@@ -202,7 +202,7 @@ function! s:GetLookupFromCompileCommandsFile(compile_commands_file) abort
let l:file_lookup[l:basename] = get(l:file_lookup, l:basename, []) + [l:entry]
let l:dirbasename = tolower(fnamemodify(l:entry.directory, ':p:h:t'))
- let l:dir_lookup[l:dirbasename] = get(l:dir_lookup, l:basename, []) + [l:entry]
+ let l:dir_lookup[l:dirbasename] = get(l:dir_lookup, l:dirbasename, []) + [l:entry]
endfor
if !empty(l:file_lookup) && !empty(l:dir_lookup)
diff --git a/autoload/ale/command.vim b/autoload/ale/command.vim
index 6944f170..ceb642f0 100644
--- a/autoload/ale/command.vim
+++ b/autoload/ale/command.vim
@@ -3,33 +3,37 @@
" managing files during linting and fixing cycles.
" This dictionary holds lists of files and directories to remove later.
-if !exists('s:managed_data')
- let s:managed_data = {}
+if !exists('s:buffer_data')
+ let s:buffer_data = {}
endif
" Used to get the data in tests.
function! ale#command#GetData() abort
- return deepcopy(s:managed_data)
+ return deepcopy(s:buffer_data)
endfunction
function! ale#command#ClearData() abort
- let s:managed_data = {}
+ let s:buffer_data = {}
endfunction
-function! ale#command#ManageFile(buffer, file) abort
- if !has_key(s:managed_data, a:buffer)
- let s:managed_data[a:buffer] = {'file_list': [], 'directory_list': []}
+function! ale#command#InitData(buffer) abort
+ if !has_key(s:buffer_data, a:buffer)
+ let s:buffer_data[a:buffer] = {
+ \ 'jobs': {},
+ \ 'file_list': [],
+ \ 'directory_list': [],
+ \}
endif
+endfunction
- call add(s:managed_data[a:buffer].file_list, a:file)
+function! ale#command#ManageFile(buffer, file) abort
+ call ale#command#InitData(a:buffer)
+ call add(s:buffer_data[a:buffer].file_list, a:file)
endfunction
function! ale#command#ManageDirectory(buffer, directory) abort
- if !has_key(s:managed_data, a:buffer)
- let s:managed_data[a:buffer] = {'file_list': [], 'directory_list': []}
- endif
-
- call add(s:managed_data[a:buffer].directory_list, a:directory)
+ call ale#command#InitData(a:buffer)
+ call add(s:buffer_data[a:buffer].directory_list, a:directory)
endfunction
function! ale#command#CreateFile(buffer) abort
@@ -61,17 +65,9 @@ function! ale#command#CreateDirectory(buffer) abort
endfunction
function! ale#command#RemoveManagedFiles(buffer) abort
- let l:info = get(s:managed_data, a:buffer, {})
+ let l:info = get(s:buffer_data, a:buffer, {})
- if !empty(l:info)
- \&& (
- \ !exists('*ale#engine#IsCheckingBuffer')
- \ || !ale#engine#IsCheckingBuffer(a:buffer)
- \)
- \&& (
- \ !has_key(g:ale_fix_buffer_data, a:buffer)
- \ || g:ale_fix_buffer_data[a:buffer].done
- \)
+ if !empty(l:info) && empty(l:info.jobs)
" We can't delete anything in a sandbox, so wait until we escape from
" it to delete temporary files and directories.
if ale#util#InSandbox()
@@ -91,7 +87,7 @@ function! ale#command#RemoveManagedFiles(buffer) abort
call delete(l:directory, 'rf')
endfor
- call remove(s:managed_data, a:buffer)
+ call remove(s:buffer_data, a:buffer)
endif
endfunction
@@ -187,3 +183,162 @@ function! ale#command#FormatCommand(buffer, executable, command, pipe_file_if_ne
return [l:temporary_file, l:command, l:file_created]
endfunction
+
+function! ale#command#StopJobs(buffer, job_type) abort
+ let l:info = get(s:buffer_data, a:buffer, {})
+
+ if !empty(l:info)
+ let l:new_map = {}
+
+ for [l:job_id, l:job_type] in items(l:info.jobs)
+ let l:job_id = str2nr(l:job_id)
+
+ if a:job_type is# 'all' || a:job_type is# l:job_type
+ call ale#job#Stop(l:job_id)
+ else
+ let l:new_map[l:job_id] = l:job_type
+ endif
+ endfor
+
+ let l:info.jobs = l:new_map
+ endif
+endfunction
+
+function! s:GatherOutput(line_list, job_id, line) abort
+ call add(a:line_list, a:line)
+endfunction
+
+function! s:ExitCallback(buffer, line_list, Callback, data) abort
+ if !has_key(s:buffer_data, a:buffer)
+ return
+ endif
+
+ let l:jobs = s:buffer_data[a:buffer].jobs
+
+ if !has_key(l:jobs, a:data.job_id)
+ return
+ endif
+
+ let l:job_type = remove(l:jobs, a:data.job_id)
+
+ if g:ale_history_enabled
+ call ale#history#SetExitCode(a:buffer, a:data.job_id, a:data.exit_code)
+
+ " Log the output of the command for ALEInfo if we should.
+ if g:ale_history_log_output && a:data.log_output is 1
+ call ale#history#RememberOutput(
+ \ a:buffer,
+ \ a:data.job_id,
+ \ a:line_list[:]
+ \)
+ endif
+ endif
+
+ " If the callback starts any new jobs, use the same job type for them.
+ call setbufvar(a:buffer, 'ale_job_type', l:job_type)
+ let l:result = a:Callback(a:buffer, a:line_list, {
+ \ 'exit_code': a:data.exit_code,
+ \ 'temporary_file': a:data.temporary_file,
+ \})
+
+ if get(a:data, 'result_callback', v:null) isnot v:null
+ call call(a:data.result_callback, [l:result])
+ endif
+endfunction
+
+function! ale#command#Run(buffer, command, Callback, options) abort
+ let l:output_stream = get(a:options, 'output_stream', 'stdout')
+ let l:line_list = []
+
+ let [l:temporary_file, l:command, l:file_created] = ale#command#FormatCommand(
+ \ a:buffer,
+ \ get(a:options, 'executable', ''),
+ \ a:command,
+ \ get(a:options, 'read_buffer', 0),
+ \ get(a:options, 'input', v:null),
+ \)
+ let l:command = ale#job#PrepareCommand(a:buffer, l:command)
+ let l:job_options = {
+ \ 'exit_cb': {job_id, exit_code -> s:ExitCallback(
+ \ a:buffer,
+ \ l:line_list,
+ \ a:Callback,
+ \ {
+ \ 'job_id': job_id,
+ \ 'exit_code': exit_code,
+ \ 'temporary_file': l:temporary_file,
+ \ 'log_output': get(a:options, 'log_output', 1),
+ \ 'result_callback': get(l:result, 'result_callback', v:null),
+ \ }
+ \ )},
+ \ 'mode': 'nl',
+ \}
+
+ if l:output_stream is# 'stdout'
+ let l:job_options.out_cb = function('s:GatherOutput', [l:line_list])
+ elseif l:output_stream is# 'stderr'
+ let l:job_options.err_cb = function('s:GatherOutput', [l:line_list])
+ elseif l:output_stream is# 'both'
+ let l:job_options.out_cb = function('s:GatherOutput', [l:line_list])
+ let l:job_options.err_cb = function('s:GatherOutput', [l:line_list])
+ endif
+
+ let l:status = 'failed'
+
+ if get(g:, 'ale_run_synchronously') == 1
+ if get(g:, 'ale_emulate_job_failure') == 1
+ let l:job_id = 0
+ else
+ " Generate a fake job ID for tests.
+ let s:fake_job_id = get(s:, 'fake_job_id', 0) + 1
+ let l:job_id = s:fake_job_id
+ endif
+ else
+ let l:job_id = ale#job#Start(l:command, l:job_options)
+ endif
+
+ if l:job_id
+ let l:status = 'started'
+ let l:job_type = getbufvar(a:buffer, 'ale_job_type', 'all')
+
+ call ale#command#InitData(a:buffer)
+ let s:buffer_data[a:buffer].jobs[l:job_id] = l:job_type
+ endif
+
+ if g:ale_history_enabled
+ call ale#history#Add(a:buffer, l:status, l:job_id, l:command)
+ endif
+
+ " We'll return this Dictionary. A `result_callback` can be assigned to it
+ " later for capturing the result of a:Callback.
+ "
+ " The `_deferred_job_id` is used for both checking the type of object, and
+ " for checking the job ID and status.
+ let l:result = {'_deferred_job_id': l:job_id}
+
+ if get(g:, 'ale_run_synchronously') == 1 && l:job_id
+ " Run a command synchronously if this test option is set.
+ call extend(l:line_list, systemlist(
+ \ type(l:command) is v:t_list
+ \ ? join(l:command[0:1]) . ' ' . ale#Escape(l:command[2])
+ \ : l:command
+ \))
+
+ " Don't capture output when the callbacks aren't set.
+ if !has_key(l:job_options, 'out_cb')
+ \&& !has_key(l:job_options, 'err_cb')
+ let l:line_list = []
+ endif
+
+ if !exists('g:ale_run_synchronously_callbacks')
+ let g:ale_run_synchronously_callbacks = []
+ endif
+
+ call add(
+ \ g:ale_run_synchronously_callbacks,
+ \ {-> l:job_options.exit_cb(l:job_id, v:shell_error)}
+ \)
+ endif
+
+ return l:result
+endfunction
diff --git a/autoload/ale/completion.vim b/autoload/ale/completion.vim
index 9baf29fd..8a96032e 100644
--- a/autoload/ale/completion.vim
+++ b/autoload/ale/completion.vim
@@ -316,7 +316,7 @@ function! ale#completion#ParseTSServerCompletionEntryDetails(response) abort
endfunction
function! ale#completion#NullFilter(buffer, item) abort
- return 1
+ return 1
endfunction
function! ale#completion#ParseLSPCompletions(response) abort
@@ -480,8 +480,8 @@ function! s:OnReady(linter, lsp_details, ...) abort
\ b:ale_completion_info.line,
\ min([
\ b:ale_completion_info.line_length,
- \ b:ale_completion_info.column + 1,
- \ ]),
+ \ b:ale_completion_info.column,
+ \ ]) + 1,
\ ale#completion#GetTriggerCharacter(&filetype, b:ale_completion_info.prefix),
\)
endif
diff --git a/autoload/ale/engine.vim b/autoload/ale/engine.vim
index c3313512..16653dba 100644
--- a/autoload/ale/engine.vim
+++ b/autoload/ale/engine.vim
@@ -5,20 +5,10 @@
" Remapping of linter problems.
let g:ale_type_map = get(g:, 'ale_type_map', {})
-" Stores information for each job including:
-"
-" linter: The linter dictionary for the job.
-" buffer: The buffer number for the job.
-" output: The array of lines for the output of the job.
-if !has_key(s:, 'job_info_map')
- let s:job_info_map = {}
-endif
-
if !has_key(s:, 'executable_cache_map')
let s:executable_cache_map = {}
endif
-
function! ale#engine#CleanupEveryBuffer() abort
for l:key in keys(g:ale_buffer_info)
" The key could be a filename or a buffer number, so try and
@@ -71,11 +61,9 @@ endfunction
function! ale#engine#InitBufferInfo(buffer) abort
if !has_key(g:ale_buffer_info, a:buffer)
- " job_list will hold the list of job IDs
" active_linter_list will hold the list of active linter names
" loclist holds the loclist items after all jobs have completed.
let g:ale_buffer_info[a:buffer] = {
- \ 'job_list': [],
\ 'active_linter_list': [],
\ 'active_other_sources_list': [],
\ 'loclist': [],
@@ -121,12 +109,6 @@ function! ale#engine#CreateDirectory(buffer) abort
return ale#command#CreateDirectory(a:buffer)
endfunction
-function! s:GatherOutput(job_id, line) abort
- if has_key(s:job_info_map, a:job_id)
- call add(s:job_info_map[a:job_id].output, a:line)
- endif
-endfunction
-
function! ale#engine#HandleLoclist(linter_name, buffer, loclist, from_other_source) abort
let l:info = get(g:ale_buffer_info, a:buffer, {})
@@ -137,7 +119,7 @@ function! ale#engine#HandleLoclist(linter_name, buffer, loclist, from_other_sour
if !a:from_other_source
" Remove this linter from the list of active linters.
" This may have already been done when the job exits.
- call filter(l:info.active_linter_list, 'v:val isnot# a:linter_name')
+ call filter(l:info.active_linter_list, 'v:val.name isnot# a:linter_name')
endif
" Make some adjustments to the loclists to fix common problems, and also
@@ -170,27 +152,19 @@ function! ale#engine#HandleLoclist(linter_name, buffer, loclist, from_other_sour
call ale#engine#SetResults(a:buffer, l:info.loclist)
endfunction
-function! s:HandleExit(job_id, exit_code) abort
- if !has_key(s:job_info_map, a:job_id)
+function! s:HandleExit(job_info, buffer, output, data) abort
+ let l:buffer_info = get(g:ale_buffer_info, a:buffer)
+
+ if empty(l:buffer_info)
return
endif
- let l:job_info = s:job_info_map[a:job_id]
- let l:linter = l:job_info.linter
- let l:output = l:job_info.output
- let l:buffer = l:job_info.buffer
- let l:executable = l:job_info.executable
- let l:next_chain_index = l:job_info.next_chain_index
-
- if g:ale_history_enabled
- call ale#history#SetExitCode(l:buffer, a:job_id, a:exit_code)
- endif
+ let l:linter = a:job_info.linter
+ let l:executable = a:job_info.executable
+ let l:next_chain_index = a:job_info.next_chain_index
" Remove this job from the list.
- call ale#job#Stop(a:job_id)
- call remove(s:job_info_map, a:job_id)
- call filter(g:ale_buffer_info[l:buffer].job_list, 'v:val isnot# a:job_id')
- call filter(g:ale_buffer_info[l:buffer].active_linter_list, 'v:val isnot# l:linter.name')
+ call filter(l:buffer_info.active_linter_list, 'v:val.name isnot# l:linter.name')
" Stop here if we land in the handle for a job completing if we're in
" a sandbox.
@@ -198,29 +172,24 @@ function! s:HandleExit(job_id, exit_code) abort
return
endif
- if has('nvim') && !empty(l:output) && empty(l:output[-1])
- call remove(l:output, -1)
+ if has('nvim') && !empty(a:output) && empty(a:output[-1])
+ call remove(a:output, -1)
endif
if l:next_chain_index < len(get(l:linter, 'command_chain', []))
- call s:InvokeChain(l:buffer, l:executable, l:linter, l:next_chain_index, l:output)
+ call s:InvokeChain(a:buffer, l:executable, l:linter, l:next_chain_index, a:output)
return
endif
- " Log the output of the command for ALEInfo if we should.
- if g:ale_history_enabled && g:ale_history_log_output
- call ale#history#RememberOutput(l:buffer, a:job_id, l:output[:])
- endif
-
try
- let l:loclist = ale#util#GetFunction(l:linter.callback)(l:buffer, l:output)
+ let l:loclist = ale#util#GetFunction(l:linter.callback)(a:buffer, a:output)
" Handle the function being unknown, or being deleted.
catch /E700/
let l:loclist = []
endtry
- call ale#engine#HandleLoclist(l:linter.name, l:buffer, l:loclist, 0)
+ call ale#engine#HandleLoclist(l:linter.name, a:buffer, l:loclist, 0)
endfunction
function! ale#engine#SetResults(buffer, loclist) abort
@@ -431,7 +400,7 @@ function! s:RunJob(options) abort
let l:command = a:options.command
if empty(l:command)
- return 0
+ return v:false
endif
let l:executable = a:options.executable
@@ -442,87 +411,39 @@ function! s:RunJob(options) abort
let l:read_buffer = a:options.read_buffer
let l:info = g:ale_buffer_info[l:buffer]
- let [l:temporary_file, l:command, l:file_created] = ale#command#FormatCommand(
- \ l:buffer,
- \ l:executable,
- \ l:command,
- \ l:read_buffer,
- \ v:null,
- \)
-
- if l:file_created
- " If a temporary filename has been formatted in to the command, then
- " we do not need to send the Vim buffer to the command.
- let l:read_buffer = 0
- endif
-
- let l:command = ale#job#PrepareCommand(l:buffer, l:command)
- let l:job_options = {
- \ 'mode': 'nl',
- \ 'exit_cb': function('s:HandleExit'),
- \}
-
- if l:output_stream is# 'stderr'
- let l:job_options.err_cb = function('s:GatherOutput')
- elseif l:output_stream is# 'both'
- let l:job_options.out_cb = function('s:GatherOutput')
- let l:job_options.err_cb = function('s:GatherOutput')
- else
- let l:job_options.out_cb = function('s:GatherOutput')
- endif
-
- if get(g:, 'ale_run_synchronously') == 1
- " Find a unique Job value to use, which will be the same as the ID for
- " running commands synchronously. This is only for test code.
- let l:job_id = len(s:job_info_map) + 1
+ let l:Callback = function('s:HandleExit', [{
+ \ 'linter': l:linter,
+ \ 'executable': l:executable,
+ \ 'next_chain_index': l:next_chain_index,
+ \}])
+ let l:result = ale#command#Run(l:buffer, l:command, l:Callback, {
+ \ 'output_stream': l:output_stream,
+ \ 'executable': l:executable,
+ \ 'read_buffer': l:read_buffer,
+ \ 'log_output': l:next_chain_index >= len(get(l:linter, 'command_chain', [])),
+ \})
- while has_key(s:job_info_map, l:job_id)
- let l:job_id += 1
- endwhile
- else
- let l:job_id = ale#job#Start(l:command, l:job_options)
+ if !l:result._deferred_job_id
+ return 0
endif
- let l:status = 'failed'
-
" Only proceed if the job is being run.
- if l:job_id
- " Add the job to the list of jobs, so we can track them.
- call add(l:info.job_list, l:job_id)
+ let l:found = 0
- if index(l:info.active_linter_list, l:linter.name) < 0
- call add(l:info.active_linter_list, l:linter.name)
+ for l:other_linter in l:info.active_linter_list
+ if l:other_linter.name is# l:linter.name
+ let l:found = 1
+ break
endif
+ endfor
- let l:status = 'started'
- " Store the ID for the job in the map to read back again.
- let s:job_info_map[l:job_id] = {
- \ 'linter': l:linter,
- \ 'buffer': l:buffer,
- \ 'executable': l:executable,
- \ 'output': [],
- \ 'next_chain_index': l:next_chain_index,
- \}
-
- silent doautocmd <nomodeline> User ALEJobStarted
- endif
-
- if g:ale_history_enabled
- call ale#history#Add(l:buffer, l:status, l:job_id, l:command)
+ if !l:found
+ call add(l:info.active_linter_list, l:linter)
endif
- if get(g:, 'ale_run_synchronously') == 1
- " Run a command synchronously if this test option is set.
- let s:job_info_map[l:job_id].output = systemlist(
- \ type(l:command) is v:t_list
- \ ? join(l:command[0:1]) . ' ' . ale#Escape(l:command[2])
- \ : l:command
- \)
-
- call l:job_options.exit_cb(l:job_id, v:shell_error)
- endif
+ silent doautocmd <nomodeline> User ALEJobStarted
- return l:job_id != 0
+ return 1
endfunction
" Determine which commands to run for a link in a command chain, or
@@ -599,35 +520,26 @@ function! s:InvokeChain(buffer, executable, linter, chain_index, input) abort
endfunction
function! s:StopCurrentJobs(buffer, include_lint_file_jobs) abort
+ call ale#command#StopJobs(a:buffer, 'linter')
+
+ if a:include_lint_file_jobs
+ call ale#command#StopJobs(a:buffer, 'file_linter')
+ endif
+
let l:info = get(g:ale_buffer_info, a:buffer, {})
- let l:new_job_list = []
let l:new_active_linter_list = []
- for l:job_id in get(l:info, 'job_list', [])
- let l:job_info = get(s:job_info_map, l:job_id, {})
-
- if !empty(l:job_info)
- if a:include_lint_file_jobs || !l:job_info.linter.lint_file
- call ale#job#Stop(l:job_id)
- call remove(s:job_info_map, l:job_id)
- else
- call add(l:new_job_list, l:job_id)
- " Linters with jobs still running are still active.
- call add(l:new_active_linter_list, l:job_info.linter.name)
- endif
+ for l:linter in get(l:info, 'active_linter_list', [])
+ " Keep jobs for linting files when we're only linting buffers.
+ if !a:include_lint_file_jobs && get(l:linter, 'lint_file')
+ call add(l:new_active_linter_list, l:linter)
endif
endfor
- " Remove duplicates from the active linter list.
- call uniq(sort(l:new_active_linter_list))
-
- " Update the List, so it includes only the jobs we still need.
- let l:info.job_list = l:new_job_list
" Update the active linter list, clearing out anything not running.
let l:info.active_linter_list = l:new_active_linter_list
endfunction
-
function! s:RemoveProblemsForDisabledLinters(buffer, linters) abort
" Figure out which linters are still enabled, and remove
" problems for linters which are no longer enabled.
@@ -687,6 +599,10 @@ function! s:RunLinter(buffer, linter) abort
else
let l:executable = ale#linter#GetExecutable(a:buffer, a:linter)
+ " Use different job types for file or linter jobs.
+ let l:job_type = a:linter.lint_file ? 'file_linter' : 'linter'
+ call setbufvar(a:buffer, 'ale_job_type', l:job_type)
+
if ale#engine#IsExecutable(a:buffer, l:executable)
return s:InvokeChain(a:buffer, l:executable, a:linter, 0, [])
endif
@@ -757,90 +673,3 @@ function! ale#engine#GetLoclist(buffer) abort
return g:ale_buffer_info[a:buffer].loclist
endfunction
-
-" This function can be called with a timeout to wait for all jobs to finish.
-" If the jobs to not finish in the given number of milliseconds,
-" an exception will be thrown.
-"
-" The time taken will be a very rough approximation, and more time may be
-" permitted than is specified.
-function! ale#engine#WaitForJobs(deadline) abort
- let l:start_time = ale#events#ClockMilliseconds()
-
- if l:start_time == 0
- throw 'Failed to read milliseconds from the clock!'
- endif
-
- let l:job_list = []
-
- " Gather all of the jobs from every buffer.
- for l:info in values(g:ale_buffer_info)
- call extend(l:job_list, get(l:info, 'job_list', []))
- endfor
-
- " NeoVim has a built-in API for this, so use that.
- if has('nvim')
- let l:nvim_code_list = jobwait(l:job_list, a:deadline)
-
- if index(l:nvim_code_list, -1) >= 0
- throw 'Jobs did not complete on time!'
- endif
-
- return
- endif
-
- let l:should_wait_more = 1
-
- while l:should_wait_more
- let l:should_wait_more = 0
-
- for l:job_id in l:job_list
- if ale#job#IsRunning(l:job_id)
- let l:now = ale#events#ClockMilliseconds()
-
- if l:now - l:start_time > a:deadline
- " Stop waiting after a timeout, so we don't wait forever.
- throw 'Jobs did not complete on time!'
- endif
-
- " Wait another 10 milliseconds
- let l:should_wait_more = 1
- sleep 10ms
- break
- endif
- endfor
- endwhile
-
- " Sleep for a small amount of time after all jobs finish.
- " This seems to be enough to let handlers after jobs end run, and
- " prevents the occasional failure where this function exits after jobs
- " end, but before handlers are run.
- sleep 10ms
-
- " We must check the buffer data again to see if new jobs started
- " for command_chain linters.
- let l:has_new_jobs = 0
-
- " Check again to see if any jobs are running.
- for l:info in values(g:ale_buffer_info)
- for l:job_id in get(l:info, 'job_list', [])
- if ale#job#IsRunning(l:job_id)
- let l:has_new_jobs = 1
- break
- endif
- endfor
- endfor
-
- if l:has_new_jobs
- " We have to wait more. Offset the timeout by the time taken so far.
- let l:now = ale#events#ClockMilliseconds()
- let l:new_deadline = a:deadline - (l:now - l:start_time)
-
- if l:new_deadline <= 0
- " Enough time passed already, so stop immediately.
- throw 'Jobs did not complete on time!'
- endif
-
- call ale#engine#WaitForJobs(l:new_deadline)
- endif
-endfunction
diff --git a/autoload/ale/filetypes.vim b/autoload/ale/filetypes.vim
index 6174aa0e..6cdc9ece 100644
--- a/autoload/ale/filetypes.vim
+++ b/autoload/ale/filetypes.vim
@@ -5,7 +5,7 @@ function! ale#filetypes#LoadExtensionMap() abort
" Output includes:
" '*.erl setf erlang'
redir => l:output
- silent exec 'autocmd'
+ silent exec 'autocmd'
redir end
let l:map = {}
diff --git a/autoload/ale/fix.vim b/autoload/ale/fix.vim
index b13878eb..7c428f52 100644
--- a/autoload/ale/fix.vim
+++ b/autoload/ale/fix.vim
@@ -1,13 +1,3 @@
-if !has_key(s:, 'job_info_map')
- let s:job_info_map = {}
-endif
-
-function! s:GatherOutput(job_id, line) abort
- if has_key(s:job_info_map, a:job_id)
- call add(s:job_info_map[a:job_id].output, a:line)
- endif
-endfunction
-
" Apply fixes queued up for buffers which may be hidden.
" Vim doesn't let you modify hidden buffers.
function! ale#fix#ApplyQueuedFixes() abort
@@ -94,52 +84,48 @@ function! ale#fix#ApplyFixes(buffer, output) abort
call ale#fix#ApplyQueuedFixes()
endfunction
-function! s:HandleExit(job_id, exit_code) abort
- if !has_key(s:job_info_map, a:job_id)
- return
- endif
-
- let l:job_info = remove(s:job_info_map, a:job_id)
- let l:buffer = l:job_info.buffer
+function! s:HandleExit(job_info, buffer, job_output, data) abort
+ let l:buffer_info = get(g:ale_fix_buffer_data, a:buffer, {})
- if g:ale_history_enabled
- call ale#history#SetExitCode(l:buffer, a:job_id, a:exit_code)
+ if empty(l:buffer_info)
+ return
endif
- if has_key(l:job_info, 'file_to_read')
- let l:job_info.output = readfile(l:job_info.file_to_read)
+ if a:job_info.read_temporary_file
+ let l:output = !empty(a:data.temporary_file)
+ \ ? readfile(a:data.temporary_file)
+ \ : []
+ else
+ let l:output = a:job_output
endif
- let l:ChainCallback = get(l:job_info, 'chain_with', v:null)
- let l:ProcessWith = get(l:job_info, 'process_with', v:null)
+ let l:ChainCallback = get(a:job_info, 'chain_with', v:null)
+ let l:ProcessWith = get(a:job_info, 'process_with', v:null)
" Post-process the output with a function if we have one.
if l:ProcessWith isnot v:null
- let l:job_info.output = call(
- \ ale#util#GetFunction(l:ProcessWith),
- \ [l:buffer, l:job_info.output]
- \)
+ let l:output = call(l:ProcessWith, [a:buffer, l:output])
endif
" Use the output of the job for changing the file if it isn't empty,
" otherwise skip this job and use the input from before.
"
" We'll use the input from before for chained commands.
- if l:ChainCallback is v:null && !empty(split(join(l:job_info.output)))
- let l:input = l:job_info.output
+ if l:ChainCallback is v:null && !empty(split(join(l:output)))
+ let l:input = l:output
else
- let l:input = l:job_info.input
+ let l:input = a:job_info.input
endif
let l:next_index = l:ChainCallback is v:null
- \ ? l:job_info.callback_index + 1
- \ : l:job_info.callback_index
+ \ ? a:job_info.callback_index + 1
+ \ : a:job_info.callback_index
call s:RunFixer({
- \ 'buffer': l:buffer,
+ \ 'buffer': a:buffer,
\ 'input': l:input,
- \ 'output': l:job_info.output,
- \ 'callback_list': l:job_info.callback_list,
+ \ 'output': l:output,
+ \ 'callback_list': a:job_info.callback_list,
\ 'callback_index': l:next_index,
\ 'chain_callback': l:ChainCallback,
\})
@@ -149,15 +135,13 @@ function! s:RunJob(options) abort
let l:buffer = a:options.buffer
let l:command = a:options.command
let l:input = a:options.input
- let l:output_stream = a:options.output_stream
- let l:read_temporary_file = a:options.read_temporary_file
let l:ChainWith = a:options.chain_with
let l:read_buffer = a:options.read_buffer
if empty(l:command)
" If there's nothing further to chain the command with, stop here.
if l:ChainWith is v:null
- return 0
+ return v:false
endif
" If there's another chained callback to run, then run that.
@@ -170,87 +154,32 @@ function! s:RunJob(options) abort
\ 'output': [],
\})
- return 1
+ return v:true
endif
- let [l:temporary_file, l:command, l:file_created] = ale#command#FormatCommand(
- \ l:buffer,
- \ '',
- \ l:command,
- \ l:read_buffer,
- \ l:input,
- \)
-
- let l:command = ale#job#PrepareCommand(l:buffer, l:command)
- let l:job_options = {
- \ 'mode': 'nl',
- \ 'exit_cb': function('s:HandleExit'),
- \}
+ let l:output_stream = a:options.output_stream
+
+ if a:options.read_temporary_file
+ let l:output_stream = 'none'
+ endif
- let l:job_info = {
- \ 'buffer': l:buffer,
+ let l:Callback = function('s:HandleExit', [{
\ 'input': l:input,
- \ 'output': [],
\ 'chain_with': l:ChainWith,
\ 'callback_index': a:options.callback_index,
\ 'callback_list': a:options.callback_list,
\ 'process_with': a:options.process_with,
- \}
-
- if l:read_temporary_file
- " TODO: Check that a temporary file is set here.
- let l:job_info.file_to_read = l:temporary_file
- elseif l:output_stream is# 'stderr'
- let l:job_options.err_cb = function('s:GatherOutput')
- elseif l:output_stream is# 'both'
- let l:job_options.out_cb = function('s:GatherOutput')
- let l:job_options.err_cb = function('s:GatherOutput')
- else
- let l:job_options.out_cb = function('s:GatherOutput')
- endif
-
- if get(g:, 'ale_emulate_job_failure') == 1
- let l:job_id = 0
- elseif get(g:, 'ale_run_synchronously') == 1
- " Find a unique Job value to use, which will be the same as the ID for
- " running commands synchronously. This is only for test code.
- let l:job_id = len(s:job_info_map) + 1
-
- while has_key(s:job_info_map, l:job_id)
- let l:job_id += 1
- endwhile
- else
- let l:job_id = ale#job#Start(l:command, l:job_options)
- endif
-
- let l:status = l:job_id ? 'started' : 'failed'
-
- if g:ale_history_enabled
- call ale#history#Add(l:buffer, l:status, l:job_id, l:command)
- endif
-
- if l:job_id == 0
- return 0
- endif
-
- let s:job_info_map[l:job_id] = l:job_info
-
- if get(g:, 'ale_run_synchronously') == 1
- " Run a command synchronously if this test option is set.
- let l:output = systemlist(
- \ type(l:command) is v:t_list
- \ ? join(l:command[0:1]) . ' ' . ale#Escape(l:command[2])
- \ : l:command
- \)
-
- if !l:read_temporary_file
- let s:job_info_map[l:job_id].output = l:output
- endif
-
- call l:job_options.exit_cb(l:job_id, v:shell_error)
- endif
+ \ 'read_temporary_file': a:options.read_temporary_file,
+ \}])
+ let l:result = ale#command#Run(l:buffer, l:command, l:Callback, {
+ \ 'output_stream': l:output_stream,
+ \ 'executable': '',
+ \ 'read_buffer': l:read_buffer,
+ \ 'input': l:input,
+ \ 'log_output': 0,
+ \})
- return 1
+ return l:result._deferred_job_id != 0
endfunction
function! s:RunFixer(options) abort
@@ -259,6 +188,9 @@ function! s:RunFixer(options) abort
let l:index = a:options.callback_index
let l:ChainCallback = get(a:options, 'chain_callback', v:null)
+ " Record new jobs started as fixer jobs.
+ call setbufvar(l:buffer, 'ale_job_type', 'fixer')
+
while len(a:options.callback_list) > l:index
let l:Function = l:ChainCallback isnot v:null
\ ? ale#util#GetFunction(l:ChainCallback)
@@ -419,16 +351,7 @@ function! ale#fix#Fix(buffer, fixing_flag, ...) abort
return 0
endif
- for l:job_id in keys(s:job_info_map)
- call remove(s:job_info_map, l:job_id)
- call ale#job#Stop(l:job_id)
- endfor
-
- " Mark the buffer as `done` so files can be removed.
- if has_key(g:ale_fix_buffer_data, a:buffer)
- let g:ale_fix_buffer_data[a:buffer].done = 1
- endif
-
+ call ale#command#StopJobs(a:buffer, 'fixer')
" Clean up any files we might have left behind from a previous run.
call ale#command#RemoveManagedFiles(a:buffer)
call ale#fix#InitBufferData(a:buffer, a:fixing_flag)
diff --git a/autoload/ale/fixers/jq.vim b/autoload/ale/fixers/jq.vim
index 1b743e49..cd9b9138 100644
--- a/autoload/ale/fixers/jq.vim
+++ b/autoload/ale/fixers/jq.vim
@@ -7,16 +7,16 @@ function! ale#fixers#jq#GetExecutable(buffer) abort
endfunction
function! ale#fixers#jq#Fix(buffer) abort
- let l:options = ale#Var(a:buffer, 'json_jq_options')
- let l:filters = ale#Var(a:buffer, 'json_jq_filters')
+ let l:options = ale#Var(a:buffer, 'json_jq_options')
+ let l:filters = ale#Var(a:buffer, 'json_jq_filters')
- if empty(l:filters)
- return 0
- endif
+ if empty(l:filters)
+ return 0
+ endif
- return {
- \ 'command': ale#Escape(ale#fixers#jq#GetExecutable(a:buffer))
- \ . ' ' . l:filters . ' '
- \ . l:options,
- \}
+ return {
+ \ 'command': ale#Escape(ale#fixers#jq#GetExecutable(a:buffer))
+ \ . ' ' . l:filters . ' '
+ \ . l:options,
+ \}
endfunction
diff --git a/autoload/ale/fixers/prettier.vim b/autoload/ale/fixers/prettier.vim
index 95932474..0f99ae97 100644
--- a/autoload/ale/fixers/prettier.vim
+++ b/autoload/ale/fixers/prettier.vim
@@ -51,9 +51,9 @@ function! ale#fixers#prettier#ApplyFixForVersion(buffer, version_output) abort
" filetype (scratch buffer), Prettier needs `parser` set to know how
" to process the buffer.
if ale#semver#GTE(l:version, [1, 16, 0])
- let l:parser = 'babel'
+ let l:parser = 'babel'
else
- let l:parser = 'babylon'
+ let l:parser = 'babylon'
endif
let l:prettier_parsers = {
diff --git a/autoload/ale/fixers/qmlfmt.vim b/autoload/ale/fixers/qmlfmt.vim
index d750d1c4..90b25679 100644
--- a/autoload/ale/fixers/qmlfmt.vim
+++ b/autoload/ale/fixers/qmlfmt.vim
@@ -5,7 +5,7 @@ function! ale#fixers#qmlfmt#GetExecutable(buffer) abort
endfunction
function! ale#fixers#qmlfmt#Fix(buffer) abort
- return {
- \ 'command': ale#Escape(ale#fixers#qmlfmt#GetExecutable(a:buffer)),
- \}
+ return {
+ \ 'command': ale#Escape(ale#fixers#qmlfmt#GetExecutable(a:buffer)),
+ \}
endfunction
diff --git a/autoload/ale/fixers/stylelint.vim b/autoload/ale/fixers/stylelint.vim
index 30309c7e..6bfb2fde 100644
--- a/autoload/ale/fixers/stylelint.vim
+++ b/autoload/ale/fixers/stylelint.vim
@@ -5,13 +5,12 @@ call ale#Set('stylelint_executable', 'stylelint')
call ale#Set('stylelint_use_global', get(g:, 'ale_use_global_executables', 0))
function! ale#fixers#stylelint#GetExecutable(buffer) abort
- return ale#node#FindExecutable(a:buffer, 'stylelint', [
- \ 'node_modules/stylelint/bin/stylelint.js',
- \ 'node_modules/.bin/stylelint',
- \])
+ return ale#node#FindExecutable(a:buffer, 'stylelint', [
+ \ 'node_modules/stylelint/bin/stylelint.js',
+ \ 'node_modules/.bin/stylelint',
+ \])
endfunction
-
function! ale#fixers#stylelint#Fix(buffer) abort
let l:executable = ale#fixers#stylelint#GetExecutable(a:buffer)
diff --git a/autoload/ale/go.vim b/autoload/ale/go.vim
index a166480a..cd7d9503 100644
--- a/autoload/ale/go.vim
+++ b/autoload/ale/go.vim
@@ -9,18 +9,18 @@ function! ale#go#FindProjectRoot(buffer) abort
let l:filename = ale#path#Simplify(expand('#' . a:buffer . ':p'))
for l:name in split($GOPATH, l:sep)
- let l:path_dir = ale#path#Simplify(l:name)
+ let l:path_dir = ale#path#Simplify(l:name)
- " Use the directory from GOPATH if the current filename starts with it.
- if l:filename[: len(l:path_dir) - 1] is? l:path_dir
- return l:path_dir
- endif
+ " Use the directory from GOPATH if the current filename starts with it.
+ if l:filename[: len(l:path_dir) - 1] is? l:path_dir
+ return l:path_dir
+ endif
endfor
let l:default_go_path = ale#path#Simplify(expand('~/go'))
if isdirectory(l:default_go_path)
- return l:default_go_path
+ return l:default_go_path
endif
return ''
diff --git a/autoload/ale/handlers/flawfinder.vim b/autoload/ale/handlers/flawfinder.vim
index a650d6dd..b7d2bec3 100644
--- a/autoload/ale/handlers/flawfinder.vim
+++ b/autoload/ale/handlers/flawfinder.vim
@@ -1,3 +1,4 @@
+scriptencoding utf-8
" Author: Christian Gibbons <cgibbons@gmu.edu>
" Description: This file defines a handler function that should work for the
" flawfinder format with the -CDQS flags.
@@ -30,7 +31,7 @@ function! ale#handlers#flawfinder#HandleFlawfinderFormat(buffer, lines) abort
\ 'lnum': str2nr(l:match[2]),
\ 'col': str2nr(l:match[3]),
\ 'type': (l:severity < ale#Var(a:buffer, 'c_flawfinder_error_severity'))
- \ ? 'W' : 'E',
+ \ ? 'W' : 'E',
\ 'text': s:RemoveUnicodeQuotes(join(split(l:match[4])[1:]) . ': ' . l:match[5]),
\}
diff --git a/autoload/ale/handlers/haskell.vim b/autoload/ale/handlers/haskell.vim
index 9e495b36..3613b1bb 100644
--- a/autoload/ale/handlers/haskell.vim
+++ b/autoload/ale/handlers/haskell.vim
@@ -66,11 +66,11 @@ function! ale#handlers#haskell#HandleGHCFormat(buffer, lines) abort
let l:errors = matchlist(l:match[4], '\v([wW]arning|[eE]rror): ?(.*)')
if len(l:errors) > 0
- let l:ghc_type = l:errors[1]
- let l:text = l:errors[2]
+ let l:ghc_type = l:errors[1]
+ let l:text = l:errors[2]
else
- let l:ghc_type = ''
- let l:text = l:match[4][:0] is# ' ' ? l:match[4][1:] : l:match[4]
+ let l:ghc_type = ''
+ let l:text = l:match[4][:0] is# ' ' ? l:match[4][1:] : l:match[4]
endif
if l:ghc_type is? 'Warning'
diff --git a/autoload/ale/handlers/markdownlint.vim b/autoload/ale/handlers/markdownlint.vim
index 12fc501c..daaa1d66 100644
--- a/autoload/ale/handlers/markdownlint.vim
+++ b/autoload/ale/handlers/markdownlint.vim
@@ -7,10 +7,10 @@ function! ale#handlers#markdownlint#Handle(buffer, lines) abort
for l:match in ale#util#GetMatches(a:lines, l:pattern)
call add(l:output, {
- \ 'lnum': l:match[1] + 0,
- \ 'text': '(' . l:match[2] . l:match[3] . l:match[4] . ')' . l:match[5],
- \ 'type': 'W',
- \ })
+ \ 'lnum': l:match[1] + 0,
+ \ 'text': '(' . l:match[2] . l:match[3] . l:match[4] . ')' . l:match[5],
+ \ 'type': 'W',
+ \})
endfor
return l:output
diff --git a/autoload/ale/handlers/sml.vim b/autoload/ale/handlers/sml.vim
index 92c5f83b..e5e528a5 100644
--- a/autoload/ale/handlers/sml.vim
+++ b/autoload/ale/handlers/sml.vim
@@ -64,26 +64,27 @@ function! ale#handlers#sml#Handle(buffer, lines) abort
let l:match2 = matchlist(l:line, l:pattern2)
if len(l:match2) != 0
- call add(l:out, {
- \ 'bufnr': a:buffer,
- \ 'lnum': l:match2[1] + 0,
- \ 'col' : l:match2[2] - 1,
- \ 'text': l:match2[3],
- \ 'type': l:match2[3] =~# '^Warning' ? 'W' : 'E',
- \})
- continue
+ call add(l:out, {
+ \ 'bufnr': a:buffer,
+ \ 'lnum': l:match2[1] + 0,
+ \ 'col' : l:match2[2] - 1,
+ \ 'text': l:match2[3],
+ \ 'type': l:match2[3] =~# '^Warning' ? 'W' : 'E',
+ \})
+
+ continue
endif
let l:match = matchlist(l:line, l:pattern)
if len(l:match) != 0
- call add(l:out, {
- \ 'bufnr': a:buffer,
- \ 'lnum': l:match[1] + 0,
- \ 'text': l:match[2] . ': ' . l:match[3],
- \ 'type': l:match[2] is# 'error' ? 'E' : 'W',
- \})
- continue
+ call add(l:out, {
+ \ 'bufnr': a:buffer,
+ \ 'lnum': l:match[1] + 0,
+ \ 'text': l:match[2] . ': ' . l:match[3],
+ \ 'type': l:match[2] is# 'error' ? 'E' : 'W',
+ \})
+ continue
endif
endfor
diff --git a/autoload/ale/hover.vim b/autoload/ale/hover.vim
index 490cc406..873c9558 100644
--- a/autoload/ale/hover.vim
+++ b/autoload/ale/hover.vim
@@ -78,8 +78,8 @@ function! ale#hover#HandleLSPResponse(conn_id, response) abort
let l:result = l:result.contents
if type(l:result) is v:t_string
- " The result can be just a string.
- let l:result = [l:result]
+ " The result can be just a string.
+ let l:result = [l:result]
endif
if type(l:result) is v:t_dict
diff --git a/autoload/ale/job.vim b/autoload/ale/job.vim
index f9a917e1..d4cda489 100644
--- a/autoload/ale/job.vim
+++ b/autoload/ale/job.vim
@@ -99,7 +99,8 @@ function! s:VimCloseCallback(channel) abort
if job_status(l:job) is# 'dead'
try
if !empty(l:info) && has_key(l:info, 'exit_cb')
- call ale#util#GetFunction(l:info.exit_cb)(l:job_id, get(l:info, 'exit_code', 1))
+ " We have to remove the callback, so we don't call it twice.
+ call ale#util#GetFunction(remove(l:info, 'exit_cb'))(l:job_id, get(l:info, 'exit_code', 1))
endif
finally
" Automatically forget about the job after it's done.
@@ -124,7 +125,8 @@ function! s:VimExitCallback(job, exit_code) abort
if ch_status(job_getchannel(a:job)) is# 'closed'
try
if !empty(l:info) && has_key(l:info, 'exit_cb')
- call ale#util#GetFunction(l:info.exit_cb)(l:job_id, a:exit_code)
+ " We have to remove the callback, so we don't call it twice.
+ call ale#util#GetFunction(remove(l:info, 'exit_cb'))(l:job_id, a:exit_code)
endif
finally
" Automatically forget about the job after it's done.
diff --git a/autoload/ale/lsp/response.vim b/autoload/ale/lsp/response.vim
index 5e62a29a..b91d875b 100644
--- a/autoload/ale/lsp/response.vim
+++ b/autoload/ale/lsp/response.vim
@@ -58,16 +58,20 @@ function! ale#lsp#response#ReadDiagnostics(response) abort
if has_key(l:diagnostic, 'relatedInformation')
let l:related = deepcopy(l:diagnostic.relatedInformation)
call map(l:related, {key, val ->
- \ ale#path#FromURI(val.location.uri) .
- \ ':' . (val.location.range.start.line + 1) .
- \ ':' . (val.location.range.start.character + 1) .
- \ ":\n\t" . val.message
- \ })
+ \ ale#path#FromURI(val.location.uri) .
+ \ ':' . (val.location.range.start.line + 1) .
+ \ ':' . (val.location.range.start.character + 1) .
+ \ ":\n\t" . val.message
+ \})
let l:loclist_item.detail = l:diagnostic.message . "\n" . join(l:related, "\n")
endif
if has_key(l:diagnostic, 'source')
- let l:loclist_item.detail = printf('[%s] %s', l:diagnostic.source, l:diagnostic.message)
+ let l:loclist_item.detail = printf(
+ \ '[%s] %s',
+ \ l:diagnostic.source,
+ \ l:diagnostic.message
+ \)
endif
call add(l:loclist, l:loclist_item)
diff --git a/autoload/ale/lsp_linter.vim b/autoload/ale/lsp_linter.vim
index b029d833..70299655 100644
--- a/autoload/ale/lsp_linter.vim
+++ b/autoload/ale/lsp_linter.vim
@@ -292,8 +292,17 @@ function! ale#lsp_linter#CheckWithLSP(buffer, linter) abort
endif
if l:notified
- if index(l:info.active_linter_list, a:linter.name) < 0
- call add(l:info.active_linter_list, a:linter.name)
+ let l:found = 0
+
+ for l:other_linter in l:info.active_linter_list
+ if l:other_linter.name is# a:linter.name
+ let l:found = 1
+ break
+ endif
+ endfor
+
+ if !l:found
+ call add(l:info.active_linter_list, a:linter)
endif
endif
diff --git a/autoload/ale/preview.vim b/autoload/ale/preview.vim
index 5b8fdcdb..a94da594 100644
--- a/autoload/ale/preview.vim
+++ b/autoload/ale/preview.vim
@@ -52,7 +52,8 @@ function! ale#preview#ShowSelection(item_list, ...) abort
let l:filename = l:item.filename
if get(l:options, 'use_relative_paths')
- let l:filename = substitute(l:item.filename, '^' . getcwd() . l:sep, '', '') " no-custom-checks
+ let l:cwd = getcwd() " no-custom-checks
+ let l:filename = substitute(l:filename, '^' . l:cwd . l:sep, '', '')
endif
call add(
diff --git a/autoload/ale/python.vim b/autoload/ale/python.vim
index 8d6bf1f0..5c569561 100644
--- a/autoload/ale/python.vim
+++ b/autoload/ale/python.vim
@@ -48,7 +48,7 @@ function! ale#python#FindProjectRoot(buffer) abort
let l:ini_root = ale#python#FindProjectRootIni(a:buffer)
if !empty(l:ini_root)
- return l:ini_root
+ return l:ini_root
endif
for l:path in ale#path#Upwards(expand('#' . a:buffer . ':p:h'))
diff --git a/autoload/ale/ruby.vim b/autoload/ale/ruby.vim
index 3d9c5a51..69d7a0c0 100644
--- a/autoload/ale/ruby.vim
+++ b/autoload/ale/ruby.vim
@@ -26,7 +26,7 @@ function! ale#ruby#FindProjectRoot(buffer) abort
let l:dir = ale#ruby#FindRailsRoot(a:buffer)
if isdirectory(l:dir)
- return l:dir
+ return l:dir
endif
for l:name in ['.solargraph.yml', 'Rakefile', 'Gemfile']
diff --git a/autoload/ale/sign.vim b/autoload/ale/sign.vim
index af863682..fc1ea5b6 100644
--- a/autoload/ale/sign.vim
+++ b/autoload/ale/sign.vim
@@ -116,7 +116,7 @@ endfunction
" Read sign data for a buffer to a list of lines.
function! ale#sign#ReadSigns(buffer) abort
redir => l:output
- silent execute 'sign place buffer=' . a:buffer
+ silent execute 'sign place buffer=' . a:buffer
redir end
return split(l:output, "\n")
diff --git a/autoload/ale/statusline.vim b/autoload/ale/statusline.vim
index 3040985f..6b93ba51 100644
--- a/autoload/ale/statusline.vim
+++ b/autoload/ale/statusline.vim
@@ -78,8 +78,10 @@ endfunction
function! s:UpdateCacheIfNecessary(buffer) abort
" Cache is cold, so manually ask for an update.
if !has_key(g:ale_buffer_info[a:buffer], 'count')
- call ale#statusline#Update(a:buffer,
- \ g:ale_buffer_info[a:buffer].loclist)
+ call ale#statusline#Update(
+ \ a:buffer,
+ \ g:ale_buffer_info[a:buffer].loclist
+ \)
endif
endfunction
diff --git a/autoload/ale/symbol.vim b/autoload/ale/symbol.vim
index 5180cb86..dba78afa 100644
--- a/autoload/ale/symbol.vim
+++ b/autoload/ale/symbol.vim
@@ -52,12 +52,12 @@ function! ale#symbol#HandleLSPResponse(conn_id, response) abort
if empty(l:item_list)
call ale#util#Execute('echom ''No symbols found.''')
else
- call ale#preview#ShowSelection(l:item_list)
+ call ale#preview#ShowSelection(l:item_list, l:options)
endif
endif
endfunction
-function! s:OnReady(linter, lsp_details, query, ...) abort
+function! s:OnReady(linter, lsp_details, query, options, ...) abort
let l:buffer = a:lsp_details.buffer
" If we already made a request, stop here.
@@ -76,34 +76,42 @@ function! s:OnReady(linter, lsp_details, query, ...) abort
call setbufvar(l:buffer, 'ale_symbol_request_made', 1)
let s:symbol_map[l:request_id] = {
\ 'buffer': l:buffer,
+ \ 'use_relative_paths': has_key(a:options, 'use_relative_paths') ? a:options.use_relative_paths : 0
\}
endfunction
-function! s:Search(linter, buffer, query) abort
+function! s:Search(linter, buffer, query, options) abort
let l:lsp_details = ale#lsp_linter#StartLSP(a:buffer, a:linter)
if !empty(l:lsp_details)
call ale#lsp#WaitForCapability(
\ l:lsp_details.connection_id,
\ 'symbol_search',
- \ function('s:OnReady', [a:linter, l:lsp_details, a:query]),
+ \ function('s:OnReady', [a:linter, l:lsp_details, a:query, a:options]),
\)
endif
endfunction
-function! ale#symbol#Search(query) abort
- if type(a:query) isnot v:t_string || empty(a:query)
+function! ale#symbol#Search(args) abort
+ let [l:opts, l:query] = ale#args#Parse(['relative'], a:args)
+
+ if empty(l:query)
throw 'A non-empty string must be provided!'
endif
let l:buffer = bufnr('')
+ let l:options = {}
+
+ if has_key(l:opts, 'relative')
+ let l:options.use_relative_paths = 1
+ endif
" Set a flag so we only make one request.
call setbufvar(l:buffer, 'ale_symbol_request_made', 0)
for l:linter in ale#linter#Get(getbufvar(l:buffer, '&filetype'))
if !empty(l:linter.lsp) && l:linter.lsp isnot# 'tsserver'
- call s:Search(l:linter, l:buffer, a:query)
+ call s:Search(l:linter, l:buffer, l:query, l:options)
endif
endfor
endfunction
diff --git a/autoload/ale/test.vim b/autoload/ale/test.vim
index e6ec70dc..082d91ff 100644
--- a/autoload/ale/test.vim
+++ b/autoload/ale/test.vim
@@ -55,9 +55,9 @@ endfunction
function! s:RemoveModule(results) abort
for l:item in a:results
- if has_key(l:item, 'module')
- call remove(l:item, 'module')
- endif
+ if has_key(l:item, 'module')
+ call remove(l:item, 'module')
+ endif
endfor
endfunction
@@ -85,3 +85,103 @@ function! ale#test#GetPreviewWindowText() abort
endif
endfor
endfunction
+
+" This function can be called with a timeout to wait for all jobs to finish.
+" If the jobs to not finish in the given number of milliseconds,
+" an exception will be thrown.
+"
+" The time taken will be a very rough approximation, and more time may be
+" permitted than is specified.
+function! ale#test#WaitForJobs(deadline) abort
+ let l:start_time = ale#events#ClockMilliseconds()
+
+ if l:start_time == 0
+ throw 'Failed to read milliseconds from the clock!'
+ endif
+
+ let l:job_list = []
+
+ " Gather all of the jobs from every buffer.
+ for [l:buffer, l:data] in items(ale#command#GetData())
+ call extend(l:job_list, map(keys(l:data.jobs), 'str2nr(v:val)'))
+ endfor
+
+ " NeoVim has a built-in API for this, so use that.
+ if has('nvim')
+ let l:nvim_code_list = jobwait(l:job_list, a:deadline)
+
+ if index(l:nvim_code_list, -1) >= 0
+ throw 'Jobs did not complete on time!'
+ endif
+
+ return
+ endif
+
+ let l:should_wait_more = 1
+
+ while l:should_wait_more
+ let l:should_wait_more = 0
+
+ for l:job_id in l:job_list
+ if ale#job#IsRunning(l:job_id)
+ let l:now = ale#events#ClockMilliseconds()
+
+ if l:now - l:start_time > a:deadline
+ " Stop waiting after a timeout, so we don't wait forever.
+ throw 'Jobs did not complete on time!'
+ endif
+
+ " Wait another 10 milliseconds
+ let l:should_wait_more = 1
+ sleep 10ms
+ break
+ endif
+ endfor
+ endwhile
+
+ " Sleep for a small amount of time after all jobs finish.
+ " This seems to be enough to let handlers after jobs end run, and
+ " prevents the occasional failure where this function exits after jobs
+ " end, but before handlers are run.
+ sleep 10ms
+
+ " We must check the buffer data again to see if new jobs started
+ " for command_chain linters.
+ let l:has_new_jobs = 0
+
+ " Check again to see if any jobs are running.
+ for l:info in values(g:ale_buffer_info)
+ for [l:job_id, l:linter] in get(l:info, 'job_list', [])
+ if ale#job#IsRunning(l:job_id)
+ let l:has_new_jobs = 1
+ break
+ endif
+ endfor
+ endfor
+
+ if l:has_new_jobs
+ " We have to wait more. Offset the timeout by the time taken so far.
+ let l:now = ale#events#ClockMilliseconds()
+ let l:new_deadline = a:deadline - (l:now - l:start_time)
+
+ if l:new_deadline <= 0
+ " Enough time passed already, so stop immediately.
+ throw 'Jobs did not complete on time!'
+ endif
+
+ call ale#test#WaitForJobs(l:new_deadline)
+ endif
+endfunction
+
+function! ale#test#FlushJobs() abort
+ " The variable is checked for in a loop, as calling one series of
+ " callbacks can trigger a further series of callbacks.
+ while exists('g:ale_run_synchronously_callbacks')
+ let l:callbacks = g:ale_run_synchronously_callbacks
+ unlet g:ale_run_synchronously_callbacks
+
+ for l:Callback in l:callbacks
+ call l:Callback()
+ endfor
+ endwhile
+endfunction
diff --git a/doc/ale-java.txt b/doc/ale-java.txt
index 8e40aea0..aa226305 100644
--- a/doc/ale-java.txt
+++ b/doc/ale-java.txt
@@ -79,14 +79,19 @@ g:ale_java_pmd_options *g:ale_java_pmd_options*
javalsp *ale-java-javalsp*
To enable Java LSP linter you need to download and build the vscode-javac
-language server from https://github.com/georgewfraser/vscode-javac. Simply
-download the source code and then build the plugin using maven:
+language server from https://github.com/georgewfraser/java-language-server.
+Simply download the source code and then build a distribution:
- mvn package
+ scripts/link_mac.sh
-This generates a out/fat-jar.jar file that contains the language server. To
-let ALE use this language server you need to set the g:ale_java_javalsp_jar
-variable to the absolute path of this jar file.
+or
+
+ scripts/link_windows.sh
+
+This generates a dist/mac or dist/windows directory that contains the
+language server. To let ALE use this language server you need to set the
+g:ale_java_javalsp_executable variable to the absolute path of the java
+executable in this directory.
g:ale_java_javalsp_executable *g:ale_java_javalsp_executable*
*b:ale_java_javalsp_executable*
@@ -95,14 +100,6 @@ g:ale_java_javalsp_executable *g:ale_java_javalsp_executable*
This variable can be changed to use a different executable for java.
-g:ale_java_javalsp_jar *g:ale_java_javalsp_jar*
- *b:ale_java_javalsp_jar*
-
- Type: |String|
- Default: `'fat-jar.jar'`
-
- Path to the location of the vscode-javac language server plugin.
-
===============================================================================
uncrustify *ale-java-uncrustify*
diff --git a/doc/ale.txt b/doc/ale.txt
index 006928ef..6e80117e 100644
--- a/doc/ale.txt
+++ b/doc/ale.txt
@@ -439,6 +439,7 @@ Notes:
* Crystal: `ameba`!!, `crystal`!!
* CSS: `csslint`, `prettier`, `stylelint`
* Cucumber: `cucumber`
+* Cypher: `cypher-lint`
* Cython (pyrex filetype): `cython`
* D: `dls`, `dmd`, `uncrustify`
* Dafny: `dafny`!!
@@ -890,6 +891,8 @@ supported:
|ALEFindReferences| - Find references for the word under the cursor.
+Options:
+ `-relative` Show file paths in the results relative to the working dir
-------------------------------------------------------------------------------
5.5 Hovering *ale-hover*
@@ -930,6 +933,8 @@ commands are supported:
|ALESymbolSearch| - Search for symbols in the workspace.
+Options:
+ `-relative` Show file paths in the results relative to the working dir
===============================================================================
6. Global Options *ale-options*
@@ -2669,9 +2674,9 @@ ale#command#ManageDirectory(buffer, directory) *ale#command#ManageDirectory()*
ale#command#ManageFile(buffer, filename) *ale#command#ManageFile()*
- Given a buffer number for a buffer currently running some linting tasks
- and a filename, register a filename with ALE for automatic deletion after
- linting is complete, or when Vim exits.
+ Given a buffer number for a buffer currently running some linting or fixing
+ tasks and a filename, register a filename with ALE for automatic deletion
+ after linting or fixing is complete, or when Vim exits.
If Vim exits suddenly, ALE will try its best to remove temporary files, but
ALE cannot guarantee with absolute certainty that the files will be removed.
@@ -2682,7 +2687,7 @@ ale#command#ManageFile(buffer, filename) *ale#command#ManageFile()*
files and symlinks given to this function. This is to prevent entire
directories from being accidentally deleted, say in cases of writing
`dir . '/' . filename` where `filename` is actually `''`, etc. ALE instead
- manages directories separetly with the |ale#command#ManageDirectory| function.
+ manages directories separately with the |ale#command#ManageDirectory| function.
ale#engine#GetLoclist(buffer) *ale#engine#GetLoclist()*
diff --git a/plugin/ale.vim b/plugin/ale.vim
index 1181fb21..b2e6bf8c 100644
--- a/plugin/ale.vim
+++ b/plugin/ale.vim
@@ -258,6 +258,6 @@ augroup ALECleanupGroup
autocmd QuitPre * call ale#events#QuitEvent(str2nr(expand('<abuf>')))
if exists('##VimSuspend')
- autocmd VimSuspend * if exists('*ale#engine#CleanupEveryBuffer') | call ale#engine#CleanupEveryBuffer() | endif
+ autocmd VimSuspend * if exists('*ale#engine#CleanupEveryBuffer') | call ale#engine#CleanupEveryBuffer() | endif
endif
augroup END
diff --git a/test/command_callback/test_cypher_cypher_lint_command_callback.vader b/test/command_callback/test_cypher_cypher_lint_command_callback.vader
new file mode 100644
index 00000000..6b64dc1f
--- /dev/null
+++ b/test/command_callback/test_cypher_cypher_lint_command_callback.vader
@@ -0,0 +1,8 @@
+Before:
+ call ale#assert#SetUpLinterTest('cypher', 'cypher_lint')
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(The default command and executable should be correct):
+ AssertLinter 'cypher-lint', 'cypher-lint'
diff --git a/test/command_callback/test_javalsp_command_callback.vader b/test/command_callback/test_javalsp_command_callback.vader
index aedb4a4b..8bfaa8ee 100644
--- a/test/command_callback/test_javalsp_command_callback.vader
+++ b/test/command_callback/test_javalsp_command_callback.vader
@@ -6,9 +6,9 @@ After:
call ale#assert#TearDownLinterTest()
Execute(The javalsp callback should return the correct default value):
- AssertLinter 'java', ale#Escape('java') . ' -cp javacs.jar -Xverify:none org.javacs.Main'
+ AssertLinter 'java', ale#Escape('java') . ' -Xverify:none -m javacs/org.javacs.Main'
Execute(The javalsp java executable should be configurable):
let b:ale_java_javalsp_executable = '/bin/foobar'
- AssertLinter '/bin/foobar', ale#Escape('/bin/foobar') . ' -cp javacs.jar -Xverify:none org.javacs.Main'
+ AssertLinter '/bin/foobar', ale#Escape('/bin/foobar') . ' -Xverify:none -m javacs/org.javacs.Main'
diff --git a/test/completion/test_lsp_completion_messages.vader b/test/completion/test_lsp_completion_messages.vader
index f670e186..130f31b9 100644
--- a/test/completion/test_lsp_completion_messages.vader
+++ b/test/completion/test_lsp_completion_messages.vader
@@ -215,7 +215,7 @@ Execute(The right message should be sent for the initial LSP request):
\ }],
\ [0, 'textDocument/completion', {
\ 'textDocument': {'uri': ale#path#ToURI(expand('%:p'))},
- \ 'position': {'line': 0, 'character': 2},
+ \ 'position': {'line': 0, 'character': 3},
\ }],
\ ],
\ g:message_list
@@ -274,7 +274,7 @@ Execute(Two completion requests shouldn't be sent in a row):
\ }],
\ [0, 'textDocument/completion', {
\ 'textDocument': {'uri': ale#path#ToURI(expand('%:p'))},
- \ 'position': {'line': 0, 'character': 2},
+ \ 'position': {'line': 0, 'character': 3},
\ }],
\ ],
\ g:message_list
diff --git a/test/fix/test_ale_fix.vader b/test/fix/test_ale_fix.vader
index 1b1891ce..500eb71c 100644
--- a/test/fix/test_ale_fix.vader
+++ b/test/fix/test_ale_fix.vader
@@ -11,6 +11,7 @@ Before:
let g:ale_enabled = 0
let g:ale_echo_cursor = 0
let g:ale_run_synchronously = 1
+ unlet! g:ale_run_synchronously_callbacks
let g:ale_set_lists_synchronously = 1
let g:ale_fix_buffer_data = {}
let g:ale_fixers = {
@@ -59,6 +60,10 @@ Before:
return {'command': 'echo x > %t', 'read_temporary_file': 1}
endfunction
+ function CatWithTempFile(buffer, done, lines) abort
+ return {'command': 'cat %t <(echo d)'}
+ endfunction
+
function RemoveLastLine(buffer, done, lines) abort
return ['a', 'b']
endfunction
@@ -177,6 +182,7 @@ After:
Restore
unlet! g:ale_run_synchronously
unlet! g:ale_set_lists_synchronously
+ unlet! g:ale_run_synchronously_callbacks
unlet! g:ale_emulate_job_failure
unlet! b:ale_fixers
unlet! b:ale_fix_on_save
@@ -187,6 +193,7 @@ After:
delfunction CatLine
delfunction CatLineOneArg
delfunction ReplaceWithTempFile
+ delfunction CatWithTempFile
delfunction RemoveLastLine
delfunction RemoveLastLineOneArg
delfunction TestCallback
@@ -235,11 +242,13 @@ Given testft (A file with three lines):
Execute(ALEFix should complain when there are no functions to call):
ALEFix
+ call ale#test#FlushJobs()
AssertEqual 'No fixers have been defined. Try :ALEFixSuggest', GetLastMessage()
Execute(ALEFix should apply simple functions):
let g:ale_fixers.testft = ['AddCarets']
ALEFix
+ call ale#test#FlushJobs()
Expect(The first function should be used):
^a
@@ -249,6 +258,7 @@ Expect(The first function should be used):
Execute(ALEFix should apply simple functions in a chain):
let g:ale_fixers.testft = ['AddCarets', 'AddDollars']
ALEFix
+ call ale#test#FlushJobs()
Expect(Both functions should be used):
$^a
@@ -258,6 +268,7 @@ Expect(Both functions should be used):
Execute(ALEFix should allow 0 to be returned to skip functions):
let g:ale_fixers.testft = ['DoNothing', 'AddDollars']
ALEFix
+ call ale#test#FlushJobs()
Expect(Only the second function should be applied):
$a
@@ -268,6 +279,7 @@ Execute(The * fixers shouldn't be used if an empty list is set for fixers):
let g:ale_fixers.testft = []
let g:ale_fixers['*'] = ['AddDollars']
ALEFix
+ call ale#test#FlushJobs()
Expect(Nothing should be changed):
a
@@ -277,6 +289,7 @@ Expect(Nothing should be changed):
Execute(* fixers should be used if no filetype is matched):
let g:ale_fixers = {'*': ['AddDollars']}
ALEFix
+ call ale#test#FlushJobs()
Expect(The file should be changed):
$a
@@ -290,6 +303,7 @@ Execute(ALEFix should allow commands to be run):
else
let g:ale_fixers.testft = ['CatLine']
ALEFix
+ call ale#test#FlushJobs()
endif
Expect(An extra line should be added):
@@ -301,6 +315,7 @@ Expect(An extra line should be added):
Execute(ALEFix should use fixers passed in commandline when provided):
let g:ale_fixers.testft = ['RemoveLastLine']
ALEFix AddCarets AddDollars
+ call ale#test#FlushJobs()
Expect(Only fixers passed via command line should be run):
$^a
@@ -315,11 +330,28 @@ Execute(ALEFix should allow temporary files to be read):
else
let g:ale_fixers.testft = ['ReplaceWithTempFile']
ALEFix
+ call ale#test#FlushJobs()
endif
Expect(The line we wrote to the temporary file should be used here):
x
+Execute(ALEFix should not read the temporary file when the option is not set):
+ if has('win32')
+ " Just skip this test on Windows, we can't run it.
+ call setline(1, ['a', 'b', 'c', 'd'])
+ else
+ let g:ale_fixers.testft = ['CatWithTempFile']
+ ALEFix
+ call ale#test#FlushJobs()
+ endif
+
+Expect(An extra line should be added):
+ a
+ b
+ c
+ d
+
Execute(ALEFix should allow jobs and simple functions to be combined):
if has('win32')
" Just skip this test on Windows, we can't run it.
@@ -328,6 +360,7 @@ Execute(ALEFix should allow jobs and simple functions to be combined):
else
let g:ale_fixers.testft = ['ReplaceWithTempFile', 'AddDollars']
ALEFix
+ call ale#test#FlushJobs()
endif
Expect(The lines from the temporary file should be modified):
@@ -340,6 +373,7 @@ Execute(ALEFix should send lines modified by functions to jobs):
else
let g:ale_fixers.testft = ['AddDollars', 'CatLine']
ALEFix
+ call ale#test#FlushJobs()
endif
Expect(The lines should first be modified by the function, then the job):
@@ -352,6 +386,7 @@ Execute(ALEFix should skip commands when jobs fail to run):
let g:ale_emulate_job_failure = 1
let g:ale_fixers.testft = ['CatLine', 'AddDollars']
ALEFix
+ call ale#test#FlushJobs()
Expect(Only the second function should be applied):
$a
@@ -361,6 +396,7 @@ Expect(Only the second function should be applied):
Execute(ALEFix should handle strings for selecting a single function):
let g:ale_fixers.testft = 'AddCarets'
ALEFix
+ call ale#test#FlushJobs()
Expect(The first function should be used):
^a
@@ -371,6 +407,7 @@ Execute(ALEFix should use functions from the registry):
call ale#fix#registry#Add('add_carets', 'AddCarets', [], 'Add some carets')
let g:ale_fixers.testft = ['add_carets']
ALEFix
+ call ale#test#FlushJobs()
Expect(The registry function should be used):
^a
@@ -380,6 +417,7 @@ Expect(The registry function should be used):
Execute(ALEFix should be able to remove the last line for files):
let g:ale_fixers.testft = ['RemoveLastLine']
ALEFix
+ call ale#test#FlushJobs()
Expect(There should be only two lines):
a
@@ -388,6 +426,7 @@ Expect(There should be only two lines):
Execute(ALEFix should accept funcrefs):
let g:ale_fixers.testft = [function('RemoveLastLine')]
ALEFix
+ call ale#test#FlushJobs()
Expect(There should be only two lines):
a
@@ -401,6 +440,7 @@ Execute(ALEFix should accept lambdas):
else
let g:ale_fixers.testft = [{buffer, done, lines -> lines + ['d']}]
ALEFix
+ call ale#test#FlushJobs()
endif
Expect(There should be an extra line):
@@ -413,6 +453,7 @@ Execute(ALEFix should user buffer-local fixer settings):
let g:ale_fixers.testft = ['AddCarets', 'AddDollars']
let b:ale_fixers = {'testft': ['RemoveLastLine']}
ALEFix
+ call ale#test#FlushJobs()
Expect(There should be only two lines):
a
@@ -422,6 +463,7 @@ Execute(ALEFix should allow Lists to be used for buffer-local fixer settings):
let g:ale_fixers.testft = ['AddCarets', 'AddDollars']
let b:ale_fixers = ['RemoveLastLine']
ALEFix
+ call ale#test#FlushJobs()
Expect(There should be only two lines):
a
@@ -447,6 +489,7 @@ Execute(ALEFix should fix files on the save event):
call SetUpLinters()
call ale#events#SaveEvent(bufnr(''))
+ call ale#test#FlushJobs()
" We should save the file.
AssertEqual ['$a', '$b', '$c'], readfile('fix_test_file')
@@ -518,6 +561,7 @@ Execute(ALEFix should still lint with no linters to be applied):
call SetUpLinters()
call ale#events#SaveEvent(bufnr(''))
+ call ale#test#FlushJobs()
Assert !filereadable('fix_test_file'), 'The file should not have been saved'
@@ -552,6 +596,7 @@ Execute(ALEFix should still lint when nothing was fixed on save):
call SetUpLinters()
call ale#events#SaveEvent(bufnr(''))
+ call ale#test#FlushJobs()
Assert !filereadable('fix_test_file'), 'The file should not have been saved'
@@ -597,6 +642,7 @@ Execute(ale#fix#InitBufferData() should set up the correct data):
Execute(ALEFix simple functions should be able to accept one argument, the buffer):
let g:ale_fixers.testft = ['RemoveLastLineOneArg']
ALEFix
+ call ale#test#FlushJobs()
Expect(There should be only two lines):
a
@@ -632,6 +678,7 @@ Execute(ALEFix functions returning jobs should be able to accept one argument):
else
let g:ale_fixers.testft = ['CatLine']
ALEFix
+ call ale#test#FlushJobs()
endif
Expect(An extra line should be added):
@@ -643,22 +690,26 @@ Expect(An extra line should be added):
Execute(ALE should print a message telling you something isn't a valid fixer when you type some nonsense):
let g:ale_fixers.testft = ['CatLine', 'invalidname']
ALEFix
+ call ale#test#FlushJobs()
AssertEqual 'There is no fixer named `invalidname`. Check :ALEFixSuggest', GetLastMessage()
Execute(ALE should complain about invalid fixers with minuses in the name):
let g:ale_fixers.testft = ['foo-bar']
ALEFix
+ call ale#test#FlushJobs()
AssertEqual 'There is no fixer named `foo-bar`. Check :ALEFixSuggest', GetLastMessage()
Execute(ALE should tolerate valid fixers with minuses in the name):
let g:ale_fixers.testft = ['prettier-standard']
ALEFix
+ call ale#test#FlushJobs()
Execute(Test fixing with chained callbacks):
let g:ale_fixers.testft = ['FirstChainCallback']
ALEFix
+ call ale#test#FlushJobs()
" The buffer shouldn't be piped in for earlier commands in the chain.
AssertEqual
@@ -677,6 +728,7 @@ Expect(The echoed line should be added):
Execute(Test fixing with chained callback where the first command is skipped):
let g:ale_fixers.testft = ['FirstChainCallbackSkipped']
ALEFix
+ call ale#test#FlushJobs()
Expect(The default line should be added):
a
@@ -687,6 +739,7 @@ Expect(The default line should be added):
Execute(Test fixing with chained callback where the second command is skipped):
let g:ale_fixers.testft = ['FirstChainCallbackSecondSkipped']
ALEFix
+ call ale#test#FlushJobs()
Expect(The default line should be added):
a
@@ -697,6 +750,7 @@ Expect(The default line should be added):
Execute(Test fixing with chained callback where the final callback is skipped):
let g:ale_fixers.testft = ['ChainWhereLastIsSkipped']
ALEFix
+ call ale#test#FlushJobs()
Expect(The lines should be the same):
a
@@ -706,6 +760,7 @@ Expect(The lines should be the same):
Execute(Empty output should be ignored):
let g:ale_fixers.testft = ['IgnoredEmptyOutput']
ALEFix
+ call ale#test#FlushJobs()
Expect(The lines should be the same):
a
@@ -715,6 +770,7 @@ Expect(The lines should be the same):
Execute(A temporary file shouldn't be piped into the command when disabled):
let g:ale_fixers.testft = ['EchoLineNoPipe']
ALEFix
+ call ale#test#FlushJobs()
AssertEqual
\ string(ale#job#PrepareCommand(bufnr(''), 'echo new line')),
@@ -731,6 +787,7 @@ Expect(The new line should be used):
Execute(Post-processing should work):
let g:ale_fixers.testft = ['FixWithJSONPostProcessing']
ALEFix
+ call ale#test#FlushJobs()
Expect(The lines in the JSON should be used):
x
@@ -740,5 +797,7 @@ Expect(The lines in the JSON should be used):
Execute(ALEFix should apply autocmds):
let g:ale_fixers.testft = ['AddCarets']
ALEFix
+ call ale#test#FlushJobs()
+
AssertEqual g:pre_success, 1
AssertEqual g:post_success, 1
diff --git a/test/handler/test_cypher_lint_handler.vader b/test/handler/test_cypher_lint_handler.vader
new file mode 100644
index 00000000..066adae4
--- /dev/null
+++ b/test/handler/test_cypher_lint_handler.vader
@@ -0,0 +1,21 @@
+Before:
+ runtime ale_linters/cypher/cypher_lint.vim
+
+After:
+ call ale#linter#Reset()
+
+Execute(The cypher-lint handler should handle errors for the current file correctly):
+ AssertEqual
+ \ [
+ \ {
+ \ 'lnum': 1,
+ \ 'col': 75,
+ \ 'type': 'E',
+ \ 'text': "Invalid input ',': expected an identifier, shortestPath, allShortestPaths or '('",
+ \ },
+ \ ],
+ \ ale_linters#cypher#cypher_lint#Handle(bufnr(''), [
+ \ "shakespeare.cql:1:75: Invalid input ',': expected an identifier, shortestPath, allShortestPaths or '('",
+ \ "CREATE (shakespeare:Author {firstname:'William', lastname:'Shakespeare'}),,",
+ \ " ^",
+ \ ])
diff --git a/test/handler/test_flow_handler.vader b/test/handler/test_flow_handler.vader
index 3a575a01..055ba026 100644
--- a/test/handler/test_flow_handler.vader
+++ b/test/handler/test_flow_handler.vader
@@ -499,7 +499,8 @@ Execute(The flow handler should handle extra errors):
\ 'col': 35,
\ 'type': 'E',
\ 'text': 'props of React element `New`: This type is incompatible with object type',
- \ 'detail': 'Property `setVector` is incompatible: number This type is incompatible with function type ',
+ \ 'detail': 'props of React element `New`: This type is incompatible with object type'
+ \ . "\nProperty `setVector` is incompatible: number This type is incompatible with function type ",
\ }
\]
diff --git a/test/lsp/test_reset_lsp.vader b/test/lsp/test_reset_lsp.vader
index 2bec13dc..4a1a155e 100644
--- a/test/lsp/test_reset_lsp.vader
+++ b/test/lsp/test_reset_lsp.vader
@@ -18,6 +18,9 @@ Before:
endfunction
call ale#engine#InitBufferInfo(bufnr(''))
+ " Call this function first, so we can be sure the module is loaded before we
+ " check if it exists.
+ call ale#lsp_linter#ClearLSPData()
call ale#linter#Define('testft', {
\ 'name': 'lsplinter',
@@ -68,7 +71,10 @@ Execute(ALEStopAllLSPs should clear the loclist):
\ 'linter_name': 'otherlinter',
\ },
\]
- let g:ale_buffer_info[bufnr('')].active_linter_list = ['lsplinter', 'otherlinter']
+ let g:ale_buffer_info[bufnr('')].active_linter_list = [
+ \ {'name': 'lsplinter'},
+ \ {'name': 'otherlinter'},
+ \]
ALEStopAllLSPs
@@ -87,4 +93,6 @@ Execute(ALEStopAllLSPs should clear the loclist):
\]
" The LSP linter should be removed from the active linter list.
- AssertEqual g:ale_buffer_info[bufnr('')].active_linter_list, ['otherlinter']
+ AssertEqual
+ \ ['otherlinter'],
+ \ map(copy(g:ale_buffer_info[bufnr('')].active_linter_list), 'v:val.name')
diff --git a/test/script/block-padding-checker b/test/script/block-padding-checker
index b13c9b92..97ae7646 100755
--- a/test/script/block-padding-checker
+++ b/test/script/block-padding-checker
@@ -10,7 +10,7 @@ import re
INDENTATION_RE = re.compile(r'^ *')
COMMENT_LINE_RE = re.compile(r'^ *"')
-COMMAND_RE = re.compile(r'^ *([a-zA-Z]+)')
+COMMAND_RE = re.compile(r'^ *([a-zA-Z\\]+)')
START_BLOCKS = set(['if', 'for', 'while', 'try', 'function'])
END_BLOCKS = set(['endif', 'endfor', 'endwhile', 'endtry', 'endfunction'])
@@ -21,6 +21,7 @@ WHITESPACE_BEFORE_SET = START_BLOCKS | TERMINATORS
WHITESPACE_FORBIDDEN_BEFORE_SET = END_BLOCKS | MIDDLE_BLOCKS
WHITESPACE_AFTER_SET = END_BLOCKS
WHITESPACE_FORBIDDEN_AFTER_SET = START_BLOCKS | MIDDLE_BLOCKS
+SAME_INDENTATION_SET = set(['\\'])
def remove_comment_lines(line_iter):
@@ -44,7 +45,7 @@ def check_lines(line_iter):
):
yield (
line_number,
- 'Blank line forbidden after `%s`' % (command,)
+ 'Blank line forbidden after `%s`' % (previous_command,)
)
previous_line_blank = True
@@ -56,6 +57,26 @@ def check_lines(line_iter):
if command_match:
command = command_match.group(1)
+ if (
+ command in SAME_INDENTATION_SET
+ and previous_indentation_level is not None
+ and indentation_level != previous_indentation_level
+ ):
+ yield (
+ line_number,
+ 'Line continuation should match previous indentation'
+ )
+
+ if (
+ previous_indentation_level is not None
+ and indentation_level != previous_indentation_level
+ and abs(indentation_level - previous_indentation_level) != 4
+ ):
+ yield (
+ line_number,
+ 'Indentation should be 4 spaces'
+ )
+
# Check for commands requiring blank lines before them, if they
# aren't at the start of a block.
if (
diff --git a/test/sign/test_linting_sets_signs.vader b/test/sign/test_linting_sets_signs.vader
index 3ccecf45..c72b0882 100644
--- a/test/sign/test_linting_sets_signs.vader
+++ b/test/sign/test_linting_sets_signs.vader
@@ -63,5 +63,6 @@ After:
Execute(The signs should be updated after linting is done):
ALELint
+ call ale#test#FlushJobs()
AssertEqual [['1', 'ALEWarningSign'], ['2', 'ALEErrorSign']], CollectSigns()
diff --git a/test/sign/test_sign_placement.vader b/test/sign/test_sign_placement.vader
index e2d95ff0..41bed715 100644
--- a/test/sign/test_sign_placement.vader
+++ b/test/sign/test_sign_placement.vader
@@ -134,6 +134,7 @@ Given testft(A file with warnings/errors):
Execute(The current signs should be set for running a job):
ALELint
+ call ale#test#FlushJobs()
AssertEqual
\ [
diff --git a/test/smoke_test.vader b/test/smoke_test.vader
index c87f95b2..53e08a8d 100644
--- a/test/smoke_test.vader
+++ b/test/smoke_test.vader
@@ -66,7 +66,7 @@ Execute(Linters should run with the default options):
" where tests fail randomly.
for g:i in range(has('nvim-0.3') || has('win32') ? 5 : 1)
call ale#Queue(0, '')
- call ale#engine#WaitForJobs(2000)
+ call ale#test#WaitForJobs(2000)
let g:results = ale#test#GetLoclistWithoutModule()
@@ -110,7 +110,7 @@ Execute(Linters should run in PowerShell too):
\})
call ale#Queue(0, '')
- call ale#engine#WaitForJobs(4000)
+ call ale#test#WaitForJobs(4000)
AssertEqual [
\ {
@@ -140,7 +140,7 @@ Execute(Linters should run in PowerShell too):
Execute(Previous errors should be removed when linters change):
call ale#Queue(0, '')
- call ale#engine#WaitForJobs(2000)
+ call ale#test#WaitForJobs(2000)
call ale#linter#Reset()
@@ -167,7 +167,7 @@ Execute(Previous errors should be removed when linters change):
" where tests fail randomly.
for g:i in range(has('nvim-0.3') || has('win32') ? 5 : 1)
call ale#Queue(0, '')
- call ale#engine#WaitForJobs(2000)
+ call ale#test#WaitForJobs(2000)
let g:results = ale#test#GetLoclistWithoutModule()
diff --git a/test/test_ale_lint_command.vader b/test/test_ale_lint_command.vader
index bc2ebabe..ba7308dd 100644
--- a/test/test_ale_lint_command.vader
+++ b/test/test_ale_lint_command.vader
@@ -1,7 +1,9 @@
Before:
Save g:ale_buffer_info
+ Save g:ale_enabled
let g:ale_buffer_info = {}
+ let g:ale_enabled = 1
let g:expected_loclist = [{
\ 'bufnr': bufnr('%'),
@@ -58,7 +60,7 @@ Execute(ALELint should run the linters):
" Try to run the linter a few times, as it fails randomly in NeoVim.
for b:i in range(5)
ALELint
- call ale#engine#WaitForJobs(2000)
+ call ale#test#WaitForJobs(2000)
if !has('nvim')
" Sleep so the delayed list function can run.
diff --git a/test/test_ale_toggle.vader b/test/test_ale_toggle.vader
index db891009..d0bca329 100644
--- a/test/test_ale_toggle.vader
+++ b/test/test_ale_toggle.vader
@@ -10,6 +10,7 @@ Before:
let g:ale_set_signs = 1
let g:ale_set_lists_synchronously = 1
let g:ale_run_synchronously = 1
+ unlet! g:ale_run_synchronously_callbacks
let g:ale_pattern_options = {}
let g:ale_pattern_options_enabled = 1
let g:ale_set_balloons =
@@ -85,6 +86,7 @@ Before:
After:
Restore
+ unlet! g:ale_run_synchronously_callbacks
unlet! g:expected_loclist
unlet! g:expected_groups
unlet! b:ale_enabled
@@ -113,6 +115,7 @@ Execute(ALEToggle should reset everything and then run again):
AssertEqual 'foobar', &filetype
ALELint
+ call ale#test#FlushJobs()
" First check that everything is there...
AssertEqual g:expected_loclist, ale#test#GetLoclistWithoutModule()
@@ -135,6 +138,7 @@ Execute(ALEToggle should reset everything and then run again):
" Toggle ALE on, everything should be set up and run again.
ALEToggle
+ call ale#test#FlushJobs()
AssertEqual g:expected_loclist, ale#test#GetLoclistWithoutModule()
AssertEqual [0, [[2, 1000001, 'ALEErrorSign']]], ale#sign#FindCurrentSigns(bufnr('%'))
@@ -157,6 +161,7 @@ Execute(ALEToggle should skip filename keys and preserve them):
\}
ALELint
+ call ale#test#FlushJobs()
" Now Toggle ALE off.
ALEToggle
@@ -174,6 +179,7 @@ Execute(ALEToggle should skip filename keys and preserve them):
" Toggle ALE on again.
ALEToggle
+ call ale#test#FlushJobs()
AssertEqual
\ {
@@ -188,15 +194,18 @@ Execute(ALEToggle should skip filename keys and preserve them):
Execute(ALEDisable should reset everything and stay disabled):
ALELint
+ call ale#test#FlushJobs()
AssertEqual g:expected_loclist, ale#test#GetLoclistWithoutModule()
ALEDisable
+ call ale#test#FlushJobs()
AssertEqual [], ale#test#GetLoclistWithoutModule()
AssertEqual 0, g:ale_enabled
ALEDisable
+ call ale#test#FlushJobs()
AssertEqual [], ale#test#GetLoclistWithoutModule()
AssertEqual 0, g:ale_enabled
@@ -205,6 +214,7 @@ Execute(ALEEnable should enable ALE and lint again):
let g:ale_enabled = 0
ALEEnable
+ call ale#test#FlushJobs()
AssertEqual g:expected_loclist, ale#test#GetLoclistWithoutModule()
AssertEqual 1, g:ale_enabled
@@ -213,6 +223,7 @@ Execute(ALEReset should reset everything for a buffer):
AssertEqual 'foobar', &filetype
ALELint
+ call ale#test#FlushJobs()
" First check that everything is there...
AssertEqual g:expected_loclist, ale#test#GetLoclistWithoutModule()
@@ -224,6 +235,7 @@ Execute(ALEReset should reset everything for a buffer):
" Now Toggle ALE off.
ALEReset
+ call ale#test#FlushJobs()
" Everything should be cleared.
Assert !has_key(g:ale_buffer_info, bufnr('')), 'The g:ale_buffer_info Dictionary was not removed'
@@ -237,6 +249,7 @@ Execute(ALEToggleBuffer should reset everything and then run again):
AssertEqual 'foobar', &filetype
ALELint
+ call ale#test#FlushJobs()
" First check that everything is there...
AssertEqual g:expected_loclist, ale#test#GetLoclistWithoutModule()
@@ -257,6 +270,7 @@ Execute(ALEToggleBuffer should reset everything and then run again):
" Toggle ALE on, everything should be set up and run again.
ALEToggleBuffer
+ call ale#test#FlushJobs()
AssertEqual g:expected_loclist, ale#test#GetLoclistWithoutModule()
AssertEqual [0, [[2, 1000001, 'ALEErrorSign']]], ale#sign#FindCurrentSigns(bufnr('%'))
@@ -268,10 +282,12 @@ Execute(ALEToggleBuffer should reset everything and then run again):
Execute(ALEDisableBuffer should reset everything and stay disabled):
ALELint
+ call ale#test#FlushJobs()
AssertEqual g:expected_loclist, ale#test#GetLoclistWithoutModule()
ALEDisableBuffer
+ call ale#test#FlushJobs()
AssertEqual [], ale#test#GetLoclistWithoutModule()
AssertEqual 0, b:ale_enabled
@@ -280,6 +296,7 @@ Execute(ALEEnableBuffer should enable ALE and lint again):
let b:ale_enabled = 0
ALEEnableBuffer
+ call ale#test#FlushJobs()
AssertEqual g:expected_loclist, ale#test#GetLoclistWithoutModule()
AssertEqual 1, b:ale_enabled
@@ -303,6 +320,7 @@ Execute(ALEResetBuffer should reset everything for a buffer):
AssertEqual 'foobar', &filetype
ALELint
+ call ale#test#FlushJobs()
" First check that everything is there...
AssertEqual g:expected_loclist, ale#test#GetLoclistWithoutModule()
@@ -314,6 +332,7 @@ Execute(ALEResetBuffer should reset everything for a buffer):
" Now Toggle ALE off.
ALEResetBuffer
+ call ale#test#FlushJobs()
" Everything should be cleared.
Assert !has_key(g:ale_buffer_info, bufnr('')), 'The g:ale_buffer_info Dictionary was not removed'
diff --git a/test/test_command_chain.vader b/test/test_command_chain.vader
index 591f6f40..329ebc97 100644
--- a/test/test_command_chain.vader
+++ b/test/test_command_chain.vader
@@ -1,6 +1,7 @@
Before:
Save &shell, g:ale_run_synchronously
let g:ale_run_synchronously = 1
+ unlet! g:ale_run_synchronously_callbacks
if !has('win32')
set shell=/bin/sh
@@ -47,6 +48,7 @@ Before:
After:
Restore
+ unlet! g:ale_run_synchronously_callbacks
unlet! g:first_echo_called
unlet! g:second_echo_called
unlet! g:final_callback_called
@@ -63,6 +65,7 @@ Given foobar (Some imaginary filetype):
Execute(Check the results of running the chain):
AssertEqual 'foobar', &filetype
call ale#Queue(0)
+ call ale#test#FlushJobs()
Assert g:first_echo_called, 'The first chain item was not called'
Assert g:second_echo_called, 'The second chain item was not called'
diff --git a/test/test_errors_removed_after_filetype_changed.vader b/test/test_errors_removed_after_filetype_changed.vader
index 651a74f2..a47dbcd1 100644
--- a/test/test_errors_removed_after_filetype_changed.vader
+++ b/test/test_errors_removed_after_filetype_changed.vader
@@ -3,7 +3,6 @@ Before:
Save g:ale_buffer_info
Save g:ale_echo_cursor
Save g:ale_run_synchronously
- Save g:ale_run_synchronously
Save g:ale_set_highlights
Save g:ale_set_loclist
Save g:ale_set_quickfix
@@ -17,6 +16,7 @@ Before:
let g:ale_echo_cursor = 0
let g:ale_run_synchronously = 1
+ unlet! g:ale_run_synchronously_callbacks
call setloclist(0, [])
noautocmd let &filetype = 'foobar'
@@ -44,6 +44,8 @@ Before:
After:
Restore
+
+ unlet! g:ale_run_synchronously_callbacks
delfunction TestCallback
call ale#linter#Reset()
@@ -51,6 +53,7 @@ After:
Execute(Error should be removed when the filetype changes to something else we cannot check):
call ale#Queue(0)
+ call ale#test#FlushJobs()
sleep 1ms
AssertEqual 1, len(ale#test#GetLoclistWithoutModule())
@@ -58,6 +61,7 @@ Execute(Error should be removed when the filetype changes to something else we c
noautocmd let &filetype = 'foobar2'
call ale#Queue(0)
+ call ale#test#FlushJobs()
sleep 1ms
" We should get some items from the second filetype.
@@ -66,6 +70,7 @@ Execute(Error should be removed when the filetype changes to something else we c
noautocmd let &filetype = 'xxx'
call ale#Queue(0)
+ call ale#test#FlushJobs()
sleep 1ms
AssertEqual 0, len(ale#test#GetLoclistWithoutModule())
diff --git a/test/test_format_temporary_file_creation.vader b/test/test_format_temporary_file_creation.vader
index 385af908..10409400 100644
--- a/test/test_format_temporary_file_creation.vader
+++ b/test/test_format_temporary_file_creation.vader
@@ -13,6 +13,7 @@ Before:
let g:ale_echo_cursor = 0
let g:ale_enabled = 1
let g:ale_run_synchronously = 1
+ unlet! g:ale_run_synchronously_callbacks
let g:ale_set_highlights = 0
let g:ale_set_loclist = 0
let g:ale_set_quickfix = 0
@@ -41,6 +42,7 @@ Before:
After:
Restore
+ unlet! g:ale_run_synchronously_callbacks
unlet! g:output
delfunction TestCallback
@@ -56,5 +58,6 @@ Execute(ALE should be able to read the %t file):
AssertEqual 'foobar', &filetype
ALELint
+ call ale#test#FlushJobs()
AssertEqual ['foo', 'bar', 'baz'], g:output
diff --git a/test/test_highlight_placement.vader b/test/test_highlight_placement.vader
index 53dcea06..619a964e 100644
--- a/test/test_highlight_placement.vader
+++ b/test/test_highlight_placement.vader
@@ -9,6 +9,7 @@ Before:
Save g:ale_set_signs
let g:ale_run_synchronously = 1
+ unlet! g:ale_run_synchronously_callbacks
let g:ale_set_highlights = 1
let g:ale_set_signs = 1
let g:ale_buffer_info = {}
@@ -64,6 +65,7 @@ Before:
After:
Restore
+ unlet! g:ale_run_synchronously_callbacks
unlet! g:items
unlet! b:ale_enabled
@@ -81,6 +83,7 @@ Given testft(A Javscript file with warnings/errors):
Execute(Highlights should be set when a linter runs):
ALELint
+ call ale#test#FlushJobs()
AssertEqual
\ [
diff --git a/test/test_history_saving.vader b/test/test_history_saving.vader
index d7a307b5..18b64db5 100644
--- a/test/test_history_saving.vader
+++ b/test/test_history_saving.vader
@@ -2,6 +2,10 @@ Before:
Save g:ale_max_buffer_history_size
Save g:ale_history_log_output
Save g:ale_run_synchronously
+ Save g:ale_enabled
+
+ let g:ale_enabled = 1
+ let g:ale_run_synchronously = 1
unlet! b:ale_fixers
unlet! b:ale_enabled
@@ -68,27 +72,19 @@ Given foobar (Some imaginary filetype):
Execute(History should be set when commands are run):
AssertEqual 'foobar', &filetype
- let g:expected_results = ['command', 'exit_code', 'job_id', 'status']
-
- " Retry this test until it works. This one can randomly fail.
- for g:i in range(has('nvim-0.3') || has('win32') ? 5 : 1)
- let b:ale_history = []
- call ale#Queue(0)
- call ale#engine#WaitForJobs(2000)
+ let b:ale_history = []
+ ALELint
+ call ale#test#FlushJobs()
- let g:history = filter(
- \ copy(ale#history#Get(bufnr(''))),
- \ 'v:val.job_id isnot# ''executable''',
- \)
+ let g:history = filter(
+ \ copy(ale#history#Get(bufnr(''))),
+ \ 'v:val.job_id isnot# ''executable''',
+ \)
- AssertEqual 1, len(g:history)
-
- if sort(keys(g:history[0])) == g:expected_results
- break
- endif
- endfor
-
- AssertEqual g:expected_results, sort(keys(g:history[0]))
+ AssertEqual 1, len(g:history)
+ AssertEqual
+ \ ['command', 'exit_code', 'job_id', 'status'],
+ \ sort(keys(g:history[0]))
if has('win32')
AssertEqual 'cmd /s/c "echo command history test"', g:history[0].command
@@ -106,8 +102,8 @@ Execute(History should be not set when disabled):
let g:ale_history_enabled = 0
- call ale#Queue(0)
- call ale#engine#WaitForJobs(2000)
+ ALELint
+ call ale#test#FlushJobs()
AssertEqual [], ale#history#Get(bufnr(''))
@@ -115,24 +111,21 @@ Execute(History should include command output if logging is enabled):
AssertEqual 'foobar', &filetype
let g:ale_history_log_output = 1
- let g:expected_results = ['command history test']
" Retry this test until it works. This one can randomly fail.
- for g:i in range(has('nvim-0.3') || has('win32') ? 5 : 1)
- let b:ale_history = []
- call ale#Queue(0)
- call ale#engine#WaitForJobs(2000)
+ let b:ale_history = []
+ ALELint
+ call ale#test#FlushJobs()
- let g:history = ale#history#Get(bufnr(''))
+ let g:history = ale#history#Get(bufnr(''))
- AssertEqual 1, len(g:history)
-
- if get(g:history[0], 'output', []) == g:expected_results
- break
- endif
- endfor
-
- AssertEqual g:expected_results, get(g:history[0], 'output', [])
+ AssertEqual 1, len(g:history)
+ AssertEqual
+ \ ['command history test'],
+ \ map(
+ \ copy(get(g:history[0], 'output', [])),
+ \ 'substitute(v:val, ''[\r ]*$'', '''', ''g'')'
+ \ )
Execute(History items should be popped after going over the max):
let b:ale_history = map(range(20), '{''status'': ''started'', ''job_id'': v:val, ''command'': ''foobar''}')
@@ -169,10 +162,13 @@ Execute(The history should be updated when fixers are run):
let b:ale_fixers = {'foobar': ['TestFixer']}
let b:ale_enabled = 0
- let g:ale_run_synchronously = 1
ALEFix
+ AssertEqual ['started'], map(copy(b:ale_history), 'v:val.status')
+
+ call ale#test#FlushJobs()
+
AssertEqual ['finished'], map(copy(b:ale_history), 'v:val.status')
if has('win32')
diff --git a/test/test_lint_file_linters.vader b/test/test_lint_file_linters.vader
index f67fad44..d16f4aa1 100644
--- a/test/test_lint_file_linters.vader
+++ b/test/test_lint_file_linters.vader
@@ -8,6 +8,7 @@ Before:
let g:ale_buffer_info = {}
let g:ale_run_synchronously = 1
+ unlet! g:ale_run_synchronously_callbacks
let g:ale_set_lists_synchronously = 1
let b:ale_save_event_fired = 0
@@ -89,6 +90,7 @@ After:
Restore
+ unlet! g:ale_run_synchronously_callbacks
unlet! b:ale_save_event_fired
unlet! b:ale_enabled
unlet g:buffer_result
@@ -111,6 +113,7 @@ Given foobar (Some imaginary filetype):
Execute(Running linters without 'lint_file' should run only buffer linters):
call ale#Queue(0)
+ call ale#test#FlushJobs()
AssertEqual [
\ {
@@ -131,6 +134,7 @@ Execute(Running linters with 'lint_file' should run all linters):
Assert filereadable(expand('%:p')), 'The file was not readable'
call ale#Queue(0, 'lint_file')
+ call ale#test#FlushJobs()
AssertEqual [
\ {
@@ -163,6 +167,7 @@ Execute(Linter errors from files should be kept):
Assert filereadable(expand('%:p')), 'The file was not readable'
call ale#Queue(0, 'lint_file')
+ call ale#test#FlushJobs()
" Change the results for the buffer callback.
let g:buffer_result = [
@@ -175,6 +180,7 @@ Execute(Linter errors from files should be kept):
\]
call ale#Queue(0)
+ call ale#test#FlushJobs()
AssertEqual [
\ {
@@ -202,6 +208,7 @@ Execute(Linter errors from files should be kept when no other linters are run):
Assert filereadable(expand('%:p')), 'The file was not readable'
call ale#Queue(0, 'lint_file')
+ call ale#test#FlushJobs()
AssertEqual [
\ {
@@ -240,11 +247,13 @@ Execute(The Save event should respect the buffer number):
Assert filereadable(expand('%:p')), 'The file was not readable'
call ale#events#SaveEvent(bufnr('') + 1)
+ call ale#test#FlushJobs()
" We shouldn't get any prblems yet.
AssertEqual [], GetSimplerLoclist()
call ale#events#SaveEvent(bufnr(''))
+ call ale#test#FlushJobs()
" We should get them now we used the right buffer number.
AssertEqual [
@@ -268,6 +277,7 @@ Execute(The Save event should set b:ale_save_event_fired to 1):
call ale#linter#Reset()
call ale#events#SaveEvent(bufnr(''))
+ call ale#test#FlushJobs()
" This flag needs to be set so windows can be opened, etc.
AssertEqual 1, b:ale_save_event_fired
@@ -276,6 +286,7 @@ Execute(b:ale_save_event_fired should be set to 0 when results are set):
let b:ale_save_event_fired = 1
call ale#engine#SetResults(bufnr(''), [])
+ call ale#test#FlushJobs()
AssertEqual 0, b:ale_save_event_fired
@@ -289,15 +300,18 @@ Execute(lint_file linters should stay running after checking without them):
" The lint_file linter should still be running.
AssertEqual
\ ['lint_file_linter', 'buffer_linter'],
- \ g:ale_buffer_info[bufnr('')].active_linter_list
+ \ map(copy(g:ale_buffer_info[bufnr('')].active_linter_list), 'v:val.name')
" We should have 1 job for each linter.
- AssertEqual 2, len(g:ale_buffer_info[bufnr('')].job_list)
+ AssertEqual
+ \ 2,
+ \ len(keys(get(get(ale#command#GetData(), bufnr(''), {}), 'jobs', {})))
- call ale#engine#WaitForJobs(2000)
+ call ale#test#WaitForJobs(2000)
Execute(The save event should not lint the buffer when ALE is disabled):
let g:ale_enabled = 0
call ale#events#SaveEvent(bufnr(''))
+ call ale#test#FlushJobs()
AssertEqual [], GetSimplerLoclist()
AssertEqual 0, b:ale_save_event_fired
diff --git a/test/test_lint_on_enter_when_file_changed.vader b/test/test_lint_on_enter_when_file_changed.vader
index 67f43c17..88493005 100644
--- a/test/test_lint_on_enter_when_file_changed.vader
+++ b/test/test_lint_on_enter_when_file_changed.vader
@@ -50,6 +50,7 @@ Execute(The file changed event function should set b:ale_file_changed):
Execute(The file changed event function should lint the current buffer when it has changed):
set filetype=foobar
call ale#events#FileChangedEvent(bufnr(''))
+ call ale#test#FlushJobs()
AssertEqual [{
\ 'bufnr': bufnr(''),
@@ -68,6 +69,7 @@ Execute(The buffer should be checked after entering it after the file has change
set filetype=foobar
call ale#events#ReadOrEnterEvent(bufnr(''))
+ call ale#test#FlushJobs()
AssertEqual [{
\ 'bufnr': bufnr(''),
diff --git a/test/test_linting_blacklist.vader b/test/test_linting_blacklist.vader
index 73190b7f..2bcc9576 100644
--- a/test/test_linting_blacklist.vader
+++ b/test/test_linting_blacklist.vader
@@ -11,6 +11,6 @@ Given unite (A Unite.vim file):
Execute(Running ALE on a blacklisted file shouldn't change anything):
call ale#Queue(0)
- call ale#engine#WaitForJobs(2000)
+ call ale#test#WaitForJobs(2000)
AssertEqual {}, g:ale_buffer_info
diff --git a/test/test_linting_updates_loclist.vader b/test/test_linting_updates_loclist.vader
index 921cdb08..8a162703 100644
--- a/test/test_linting_updates_loclist.vader
+++ b/test/test_linting_updates_loclist.vader
@@ -64,6 +64,7 @@ Given foobar (Some JavaScript with problems):
Execute(The loclist should be updated after linting is done):
ALELint
+ call ale#test#FlushJobs()
AssertEqual
\ [
diff --git a/test/test_no_linting_on_write_quit.vader b/test/test_no_linting_on_write_quit.vader
index 75de06a4..7ad08d08 100644
--- a/test/test_no_linting_on_write_quit.vader
+++ b/test/test_no_linting_on_write_quit.vader
@@ -58,6 +58,7 @@ Execute(No linting should be done on :wq or :x):
" First try just the SaveEvent, to be sure that we set errors in the test.
call ale#events#SaveEvent(bufnr(''))
+ call ale#test#FlushJobs()
AssertEqual 1, len(ale#test#GetLoclistWithoutModule())
@@ -65,6 +66,7 @@ Execute(No linting should be done on :wq or :x):
call setloclist(0, [])
call ale#events#QuitEvent(bufnr(''))
call ale#events#SaveEvent(bufnr(''))
+ call ale#test#FlushJobs()
AssertEqual [], ale#test#GetLoclistWithoutModule()
@@ -73,11 +75,13 @@ Execute(No linting should be for :w after :q fails):
let g:ale_fix_on_save = 0
call ale#events#QuitEvent(bufnr(''))
+ call ale#test#FlushJobs()
" Simulate 2 seconds passing.
let b:ale_quitting -= 1000
call ale#events#SaveEvent(bufnr(''))
+ call ale#test#FlushJobs()
AssertEqual 1, len(ale#test#GetLoclistWithoutModule())
@@ -86,6 +90,7 @@ Execute(No linting should be done on :wq or :x after fixing files):
let g:ale_fix_on_save = 1
call ale#events#SaveEvent(bufnr(''))
+ call ale#test#FlushJobs()
AssertEqual 1, len(ale#test#GetLoclistWithoutModule())
@@ -93,6 +98,7 @@ Execute(No linting should be done on :wq or :x after fixing files):
call setloclist(0, [])
call ale#events#QuitEvent(bufnr(''))
call ale#events#SaveEvent(bufnr(''))
+ call ale#test#FlushJobs()
AssertEqual [], ale#test#GetLoclistWithoutModule()
@@ -101,10 +107,12 @@ Execute(Linting should be done after :q fails and fixing files):
let g:ale_fix_on_save = 1
call ale#events#QuitEvent(bufnr(''))
+ call ale#test#FlushJobs()
" Simulate 2 seconds passing.
let b:ale_quitting -= 1000
call ale#events#SaveEvent(bufnr(''))
+ call ale#test#FlushJobs()
AssertEqual 1, len(ale#test#GetLoclistWithoutModule())
diff --git a/test/test_parse_command_args.vader b/test/test_parse_command_args.vader
new file mode 100644
index 00000000..0103b967
--- /dev/null
+++ b/test/test_parse_command_args.vader
@@ -0,0 +1,52 @@
+After:
+ unlet! b:parse_result
+
+ if exists(':ParseTest')
+ delcommand ParseTest
+ endif
+
+Execute(ale#args#Parse should handle empty input):
+ AssertEqual
+ \ [{}, ''],
+ \ ale#args#Parse([], '')
+ AssertEqual
+ \ [{}, ''],
+ \ ale#args#Parse(['foo', 'bar'], '')
+
+Execute(ale#args#Parse should parse commands correctly):
+ AssertEqual
+ \ [{'foo': '', 'bar': ''}, 'leave these alone'],
+ \ ale#args#Parse(['foo', 'bar'], '-foo -bar leave these alone')
+ AssertEqual
+ \ [{'foo': ''}, 'leave these alone'],
+ \ ale#args#Parse(['foo', 'bar'], '-foo leave these alone')
+
+Execute(ale#args#Parse should raise errors for unknown arguments):
+ AssertThrows call ale#args#Parse(['foo', 'bar'], '-nope leave these alone')
+ AssertEqual 'Invalid argument: -nope', g:vader_exception
+
+Execute(ale#args#Parse should stop parsing arguments after --):
+ AssertEqual
+ \ [{'foo': ''}, ' --nope leave these alone'],
+ \ ale#args#Parse(['foo', 'bar'], '-foo -- --nope leave these alone')
+ AssertEqual
+ \ [{}, '--'],
+ \ ale#args#Parse(['foo', 'bar'], '-- --')
+ AssertEqual
+ \ [{}, ''],
+ \ ale#args#Parse(['foo', 'bar'], '--')
+
+Execute(ale#args#Parse should work for an example command):
+ command! -nargs=* ParseTest let b:parse_result = ale#args#Parse(['foo', 'bar'], <q-args>)
+
+ ParseTest
+ AssertEqual [{}, ''], b:parse_result
+
+ ParseTest -foo
+ AssertEqual [{'foo': ''}, ''], b:parse_result
+
+ ParseTest -foo -bar
+ AssertEqual [{'foo': '', 'bar': ''}, ''], b:parse_result
+
+ ParseTest -foo -bar leave these alone
+ AssertEqual [{'foo': '', 'bar': ''}, 'leave these alone'], b:parse_result
diff --git a/test/test_symbol_search.vader b/test/test_symbol_search.vader
index d8b7a4a6..9d50e267 100644
--- a/test/test_symbol_search.vader
+++ b/test/test_symbol_search.vader
@@ -7,6 +7,7 @@ Before:
let g:message_list = []
let g:preview_called = 0
let g:item_list = []
+ let g:options = {}
let g:capability_checked = ''
let g:conn_id = v:null
let g:WaitCallback = v:null
@@ -47,9 +48,10 @@ Before:
call add(g:expr_list, a:expr)
endfunction
- function! ale#preview#ShowSelection(item_list) abort
+ function! ale#preview#ShowSelection(item_list, options) abort
let g:preview_called = 1
let g:item_list = a:item_list
+ let g:options = a:options
endfunction
After:
@@ -63,6 +65,7 @@ After:
unlet! g:message_list
unlet! g:expr_list
unlet! b:ale_linters
+ unlet! g:options
unlet! g:item_list
unlet! g:preview_called
@@ -170,4 +173,15 @@ Execute(LSP symbol requests should be sent):
\ ],
\ g:message_list
- AssertEqual {'42': {'buffer': bufnr('')}}, ale#symbol#GetMap()
+ AssertEqual {'42': {'buffer': bufnr(''), 'use_relative_paths': 0}}, ale#symbol#GetMap()
+
+Execute('-relative' argument should enable 'use_relative_paths' in HandleLSPResponse):
+ runtime ale_linters/python/pyls.vim
+ let b:ale_linters = ['pyls']
+ call setpos('.', [bufnr(''), 1, 5, 0])
+
+ ALESymbolSearch -relative foo bar
+
+ call call(g:WaitCallback, [g:conn_id, '/foo/bar'])
+
+ AssertEqual {'42': {'buffer': bufnr(''), 'use_relative_paths': 1}}, ale#symbol#GetMap()
diff --git a/test/test_temporary_file_management.vader b/test/test_temporary_file_management.vader
index b25da7ac..9fff1ace 100644
--- a/test/test_temporary_file_management.vader
+++ b/test/test_temporary_file_management.vader
@@ -70,7 +70,7 @@ Execute(ALE should delete managed files/directories appropriately after linting)
AssertEqual 'foobar', &filetype
call ale#Queue(0)
- call ale#engine#WaitForJobs(2000)
+ call ale#test#FlushJobs()
Assert !filereadable(g:filename), 'The temporary file was not deleted'
Assert !isdirectory(g:directory), 'The temporary directory was not deleted'
@@ -82,7 +82,7 @@ Execute(ALE should delete managed files even if no command is run):
let g:command = ''
call ale#Queue(0)
- call ale#engine#WaitForJobs(2000)
+ call ale#test#WaitForJobs(2000)
Assert !filereadable(g:filename), 'The temporary file was not deleted'
Assert !isdirectory(g:directory), 'The temporary directory was not deleted'
@@ -119,24 +119,26 @@ Execute(ALE should create and delete directories for ale#command#CreateDirectory
Assert !isdirectory(b:dir), 'The directory was not deleted'
Assert !isdirectory(b:dir2), 'The second directory was not deleted'
-Execute(ale#command#ManageFile should add the file even if the buffer info hasn't be set yet):
+Execute(ale#command#ManageFile should add the file even if the buffer info hasn't been set yet):
call ale#command#ManageFile(bufnr(''), '/foo/bar')
AssertEqual
\ {
\ bufnr(''): {
+ \ 'jobs': {},
\ 'file_list': ['/foo/bar'],
\ 'directory_list': [],
\ },
\ },
\ ale#command#GetData()
-Execute(ale#command#ManageDirectory should add the directory even if the buffer info hasn't be set yet):
+Execute(ale#command#ManageDirectory should add the directory even if the buffer info hasn't been set yet):
call ale#command#ManageDirectory(bufnr(''), '/foo/bar')
AssertEqual
\ {
\ bufnr(''): {
+ \ 'jobs': {},
\ 'file_list': [],
\ 'directory_list': ['/foo/bar'],
\ },