diff --git a/README.md b/README.md index 89fd380..265e174 100644 --- a/README.md +++ b/README.md @@ -95,7 +95,7 @@ formatting. | Fortran | [gcc](https://gcc.gnu.org/) | | FusionScript | [fusion-lint](https://github.com/RyanSquared/fusionscript) | | GLSL | [glslang](https://github.com/KhronosGroup/glslang) | -| Go | [gofmt](https://golang.org/cmd/gofmt/), [go vet](https://golang.org/cmd/vet/), [golint](https://godoc.org/github.com/golang/lint), [gometalinter](https://github.com/alecthomas/gometalinter) !!, [go build](https://golang.org/cmd/go/) !!, [gosimple](https://github.com/dominikh/go-tools/tree/master/cmd/gosimple), [staticcheck](https://github.com/dominikh/go-tools/tree/master/cmd/staticcheck) | +| Go | [gofmt](https://golang.org/cmd/gofmt/), [go vet](https://golang.org/cmd/vet/), [golint](https://godoc.org/github.com/golang/lint), [gometalinter](https://github.com/alecthomas/gometalinter) !!, [go build](https://golang.org/cmd/go/) !!, [gosimple](https://github.com/dominikh/go-tools/tree/master/cmd/gosimple) !!, [staticcheck](https://github.com/dominikh/go-tools/tree/master/cmd/staticcheck) !! | | GraphQL | [gqlint](https://github.com/happylinks/gqlint) | | Haml | [haml-lint](https://github.com/brigade/haml-lint) | | Handlebars | [ember-template-lint](https://github.com/rwjblue/ember-template-lint) | diff --git a/ale_linters/erlang/erlc.vim b/ale_linters/erlang/erlc.vim index 559dc67..bddb175 100644 --- a/ale_linters/erlang/erlc.vim +++ b/ale_linters/erlang/erlc.vim @@ -17,7 +17,7 @@ function! ale_linters#erlang#erlc#Handle(buffer, lines) abort " error.erl:4: variable 'B' is unbound " error.erl:3: Warning: function main/0 is unused " error.erl:4: Warning: variable 'A' is unused - let l:pattern = '\v^([^:]+):(\d+): (Warning: )?(.+)$' + let l:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+): (Warning: )?(.+)$' " parse_transforms are a special case. The error message does not indicate a location: " error.erl: undefined parse transform 'some_parse_transform' diff --git a/ale_linters/go/gosimple.vim b/ale_linters/go/gosimple.vim index 9188e0d..8a4c01e 100644 --- a/ale_linters/go/gosimple.vim +++ b/ale_linters/go/gosimple.vim @@ -4,7 +4,8 @@ call ale#linter#Define('go', { \ 'name': 'gosimple', \ 'executable': 'gosimple', -\ 'command': 'gosimple %t', +\ 'command': 'gosimple %s', \ 'callback': 'ale#handlers#unix#HandleAsWarning', -\ 'output_stream': 'both' +\ 'output_stream': 'both', +\ 'lint_file': 1, \}) diff --git a/ale_linters/go/staticcheck.vim b/ale_linters/go/staticcheck.vim index cb4a5c7..255fd17 100644 --- a/ale_linters/go/staticcheck.vim +++ b/ale_linters/go/staticcheck.vim @@ -4,7 +4,8 @@ call ale#linter#Define('go', { \ 'name': 'staticcheck', \ 'executable': 'staticcheck', -\ 'command': 'staticcheck %t', +\ 'command': 'staticcheck %s', \ 'callback': 'ale#handlers#unix#HandleAsWarning', -\ 'output_stream': 'both' +\ 'output_stream': 'both', +\ 'lint_file': 1, \}) diff --git a/ale_linters/java/javac.vim b/ale_linters/java/javac.vim index d83da18..f7da560 100644 --- a/ale_linters/java/javac.vim +++ b/ale_linters/java/javac.vim @@ -49,7 +49,10 @@ function! ale_linters#java#javac#GetCommand(buffer, import_paths) abort " Create .class files in a temporary directory, which we will delete later. let l:class_file_directory = ale#engine#CreateDirectory(a:buffer) - return 'javac -Xlint' + " Always run javac from the directory the file is in, so we can resolve + " relative paths correctly. + return ale#path#BufferCdString(a:buffer) + \ . 'javac -Xlint' \ . ' ' . l:cp_option \ . ' ' . l:sp_option \ . ' -d ' . ale#Escape(l:class_file_directory) @@ -63,14 +66,15 @@ function! ale_linters#java#javac#Handle(buffer, lines) abort " Main.java:13: warning: [deprecation] donaught() in Testclass has been deprecated " Main.java:16: error: ';' expected - let l:pattern = '\v^.*:(\d+): (.+):(.+)$' + let l:directory = expand('#' . a:buffer . ':p:h') + let l:pattern = '\v^(.*):(\d+): (.+):(.+)$' let l:col_pattern = '\v^(\s*\^)$' let l:symbol_pattern = '\v^ +symbol: *(class|method) +([^ ]+)' let l:output = [] for l:match in ale#util#GetMatches(a:lines, [l:pattern, l:col_pattern, l:symbol_pattern]) if empty(l:match[2]) && empty(l:match[3]) - let l:output[-1].col = len(l:match[1]) + let l:output[-1].col = len(l:match[1]) elseif empty(l:match[3]) " Add symbols to 'cannot find symbol' errors. if l:output[-1].text is# 'error: cannot find symbol' @@ -78,9 +82,10 @@ function! ale_linters#java#javac#Handle(buffer, lines) abort endif else call add(l:output, { - \ 'lnum': l:match[1] + 0, - \ 'text': l:match[2] . ':' . l:match[3], - \ 'type': l:match[2] is# 'error' ? 'E' : 'W', + \ 'filename': ale#path#GetAbsPath(l:directory, l:match[1]), + \ 'lnum': l:match[2] + 0, + \ 'text': l:match[3] . ':' . l:match[4], + \ 'type': l:match[3] is# 'error' ? 'E' : 'W', \}) endif endfor diff --git a/ale_linters/php/php.vim b/ale_linters/php/php.vim index 7158c95..b263c5f 100644 --- a/ale_linters/php/php.vim +++ b/ale_linters/php/php.vim @@ -30,6 +30,6 @@ call ale#linter#Define('php', { \ 'name': 'php', \ 'executable': 'php', \ 'output_stream': 'stdout', -\ 'command': 'php -l -d error_reporting=E_ALL -d display_errors=1 --', +\ 'command': 'php -l -d error_reporting=E_ALL -d display_errors=1 -d log_errors=0 --', \ 'callback': 'ale_linters#php#php#Handle', \}) diff --git a/ale_linters/rust/cargo.vim b/ale_linters/rust/cargo.vim index f19061a..c887ea7 100644 --- a/ale_linters/rust/cargo.vim +++ b/ale_linters/rust/cargo.vim @@ -26,6 +26,6 @@ call ale#linter#Define('rust', { \ 'executable_callback': 'ale_linters#rust#cargo#GetCargoExecutable', \ 'command_callback': 'ale_linters#rust#cargo#GetCommand', \ 'callback': 'ale#handlers#rust#HandleRustErrors', -\ 'output_stream': 'stdout', +\ 'output_stream': 'both', \ 'lint_file': 1, \}) diff --git a/ale_linters/sh/shellcheck.vim b/ale_linters/sh/shellcheck.vim index b47ba19..21f9fde 100644 --- a/ale_linters/sh/shellcheck.vim +++ b/ale_linters/sh/shellcheck.vim @@ -23,15 +23,20 @@ function! ale_linters#sh#shellcheck#GetDialectArgument(buffer) abort let l:shell_type = ale#handlers#sh#GetShellType(a:buffer) if !empty(l:shell_type) + " Use the dash dialect for /bin/ash, etc. + if l:shell_type is# 'ash' + return 'dash' + endif + return l:shell_type endif " If there's no hashbang, try using Vim's buffer variables. - if get(b:, 'is_bash') + if getbufvar(a:buffer, 'is_bash', 0) return 'bash' - elseif get(b:, 'is_sh') + elseif getbufvar(a:buffer, 'is_sh', 0) return 'sh' - elseif get(b:, 'is_kornshell') + elseif getbufvar(a:buffer, 'is_kornshell', 0) return 'ksh' endif diff --git a/ale_linters/typescript/tslint.vim b/ale_linters/typescript/tslint.vim index c3852b8..e366af8 100644 --- a/ale_linters/typescript/tslint.vim +++ b/ale_linters/typescript/tslint.vim @@ -24,6 +24,10 @@ function! ale_linters#typescript#tslint#Handle(buffer, lines) abort let l:output = [] for l:error in ale#util#FuzzyJSONDecode(a:lines, []) + if get(l:error, 'ruleName', '') is# 'no-implicit-dependencies' + continue + endif + call add(l:output, { \ 'filename': ale#path#GetAbsPath(l:dir, l:error.name), \ 'type': (get(l:error, 'ruleSeverity', '') is# 'WARNING' ? 'W' : 'E'), diff --git a/autoload/ale.vim b/autoload/ale.vim index 6500b30..15fb53d 100644 --- a/autoload/ale.vim +++ b/autoload/ale.vim @@ -61,6 +61,12 @@ function! ale#ShouldDoNothing(buffer) abort return 1 endif + let l:filename = fnamemodify(bufname(a:buffer), ':t') + + if l:filename is# '.' + return 1 + endif + " Do nothing if running in the sandbox if ale#util#InSandbox() return 1 diff --git a/autoload/ale/completion.vim b/autoload/ale/completion.vim index 9f4e3c2..e471a3b 100644 --- a/autoload/ale/completion.vim +++ b/autoload/ale/completion.vim @@ -282,7 +282,23 @@ function! s:TimerHandler(...) abort endif endfunction +" Stop any completion timer that is queued. This is useful for tests. +function! ale#completion#StopTimer() abort + if s:timer_id != -1 + call timer_stop(s:timer_id) + endif + + let s:timer_id = -1 +endfunction + function! ale#completion#Queue() abort + let l:time = get(b:, 'ale_complete_done_time', 0) + + if l:time && ale#util#ClockMilliseconds() - l:time < 100 + " Do not ask for completions shortly after we just closed the menu. + return + endif + let s:timer_pos = getcurpos()[1:2] " If we changed the text again while we're still waiting for a response, @@ -291,9 +307,7 @@ function! ale#completion#Queue() abort let b:ale_completion_info.request_id = 0 endif - if s:timer_id != -1 - call timer_stop(s:timer_id) - endif + call ale#completion#StopTimer() let s:timer_id = timer_start(g:ale_completion_delay, function('s:TimerHandler')) endfunction @@ -311,6 +325,9 @@ function! ale#completion#Done() abort let &l:completeopt = b:ale_old_completopt unlet b:ale_old_completopt endif + + " Set a timestamp, so we can avoid requesting completions again. + let b:ale_complete_done_time = ale#util#ClockMilliseconds() endfunction function! s:Setup(enabled) abort diff --git a/autoload/ale/fixers/autopep8.vim b/autoload/ale/fixers/autopep8.vim index e0e6205..e2dd7bf 100644 --- a/autoload/ale/fixers/autopep8.vim +++ b/autoload/ale/fixers/autopep8.vim @@ -12,7 +12,7 @@ function! ale#fixers#autopep8#Fix(buffer) abort \ ['autopep8'], \) - if !ale#python#IsExecutable(l:executable) + if !executable(l:executable) return 0 endif diff --git a/autoload/ale/fixers/isort.vim b/autoload/ale/fixers/isort.vim index ddd9561..00d968f 100644 --- a/autoload/ale/fixers/isort.vim +++ b/autoload/ale/fixers/isort.vim @@ -11,7 +11,7 @@ function! ale#fixers#isort#Fix(buffer) abort \ ['isort'], \) - if !ale#python#IsExecutable(l:executable) + if !executable(l:executable) return 0 endif diff --git a/autoload/ale/fixers/yapf.vim b/autoload/ale/fixers/yapf.vim index b15e481..ba7453b 100644 --- a/autoload/ale/fixers/yapf.vim +++ b/autoload/ale/fixers/yapf.vim @@ -11,7 +11,7 @@ function! ale#fixers#yapf#Fix(buffer) abort \ ['yapf'], \) - if !ale#python#IsExecutable(l:executable) + if !executable(l:executable) return 0 endif diff --git a/autoload/ale/handlers/haskell.vim b/autoload/ale/handlers/haskell.vim index 9c8d058..0960669 100644 --- a/autoload/ale/handlers/haskell.vim +++ b/autoload/ale/handlers/haskell.vim @@ -19,7 +19,7 @@ function! ale#handlers#haskell#HandleGHCFormat(buffer, lines) abort " in Haskell error messages with the basename for this file. let l:temp_filename_regex = s:temp_regex_prefix . l:basename - let l:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+):(\d+):(.*)?$' + let l:pattern = '\v^\s*([a-zA-Z]?:?[^:]+):(\d+):(\d+):(.*)?$' let l:output = [] let l:corrected_lines = [] diff --git a/autoload/ale/handlers/sh.vim b/autoload/ale/handlers/sh.vim index 894879e..e96dd3c 100644 --- a/autoload/ale/handlers/sh.vim +++ b/autoload/ale/handlers/sh.vim @@ -9,7 +9,7 @@ function! ale#handlers#sh#GetShellType(buffer) abort " Remove options like -e, etc. let l:command = substitute(l:bang_line, ' --\?[a-zA-Z0-9]\+', '', 'g') - for l:possible_shell in ['bash', 'tcsh', 'csh', 'zsh', 'sh'] + for l:possible_shell in ['bash', 'dash', 'ash', 'tcsh', 'csh', 'zsh', 'sh'] if l:command =~# l:possible_shell . '\s*$' return l:possible_shell endif diff --git a/autoload/ale/job.vim b/autoload/ale/job.vim index 254f4ee..e6a75c8 100644 --- a/autoload/ale/job.vim +++ b/autoload/ale/job.vim @@ -25,6 +25,11 @@ endfunction " Note that jobs and IDs are the same thing on NeoVim. function! ale#job#JoinNeovimOutput(job, last_line, data, mode, callback) abort + if a:mode is# 'raw' + call a:callback(a:job, join(a:data, "\n")) + return '' + endif + let l:lines = a:data[:-2] if len(a:data) > 1 @@ -34,15 +39,9 @@ function! ale#job#JoinNeovimOutput(job, last_line, data, mode, callback) abort let l:new_last_line = a:last_line . a:data[0] endif - if a:mode is# 'raw' - if !empty(l:lines) - call a:callback(a:job, join(l:lines, "\n") . "\n") - endif - else - for l:line in l:lines - call a:callback(a:job, l:line) - endfor - endif + for l:line in l:lines + call a:callback(a:job, l:line) + endfor return l:new_last_line endfunction @@ -290,7 +289,7 @@ function! ale#job#Stop(job_id) abort " FIXME: NeoVim kills jobs on a timer, but will not kill any processes " which are child processes on Unix. Some work needs to be done to " kill child processes to stop long-running processes like pylint. - call jobstop(a:job_id) + silent! call jobstop(a:job_id) else let l:job = s:job_map[a:job_id].job diff --git a/autoload/ale/lsp/message.vim b/autoload/ale/lsp/message.vim index 7910247..31a9b21 100644 --- a/autoload/ale/lsp/message.vim +++ b/autoload/ale/lsp/message.vim @@ -53,7 +53,7 @@ function! ale#lsp#message#DidOpen(buffer, language_id) abort \ 'uri': ale#path#ToURI(expand('#' . a:buffer . ':p')), \ 'languageId': a:language_id, \ 'version': ale#lsp#message#GetNextVersionID(), - \ 'text': join(l:lines, "\n"), + \ 'text': join(l:lines, "\n") . "\n", \ }, \}] endfunction @@ -67,7 +67,7 @@ function! ale#lsp#message#DidChange(buffer) abort \ 'uri': ale#path#ToURI(expand('#' . a:buffer . ':p')), \ 'version': ale#lsp#message#GetNextVersionID(), \ }, - \ 'contentChanges': [{'text': join(l:lines, "\n")}] + \ 'contentChanges': [{'text': join(l:lines, "\n") . "\n"}] \}] endfunction diff --git a/autoload/ale/lsp/tsserver_message.vim b/autoload/ale/lsp/tsserver_message.vim index ab18d74..e2706ed 100644 --- a/autoload/ale/lsp/tsserver_message.vim +++ b/autoload/ale/lsp/tsserver_message.vim @@ -28,7 +28,7 @@ function! ale#lsp#tsserver_message#Change(buffer) abort \ 'offset': 1, \ 'endLine': 1073741824, \ 'endOffset': 1, - \ 'insertString': join(l:lines, "\n"), + \ 'insertString': join(l:lines, "\n") . "\n", \}] endfunction diff --git a/autoload/ale/path.vim b/autoload/ale/path.vim index 83f6e85..bca0fe8 100644 --- a/autoload/ale/path.vim +++ b/autoload/ale/path.vim @@ -185,5 +185,12 @@ function! ale#path#FromURI(uri) abort let l:i = len('file://') let l:encoded_path = a:uri[: l:i - 1] is# 'file://' ? a:uri[l:i :] : a:uri - return ale#uri#Decode(l:encoded_path) + let l:path = ale#uri#Decode(l:encoded_path) + + " If the path is like /C:/foo/bar, it should be C:\foo\bar instead. + if l:path =~# '^/[a-zA-Z]:' + let l:path = substitute(l:path[1:], '/', '\\', 'g') + endif + + return l:path endfunction diff --git a/autoload/ale/python.vim b/autoload/ale/python.vim index d788b77..2a15f45 100644 --- a/autoload/ale/python.vim +++ b/autoload/ale/python.vim @@ -74,12 +74,6 @@ function! ale#python#FindVirtualenv(buffer) abort return $VIRTUAL_ENV endfunction -" Run an executable check for Python scripts. -" On Windows, 1 will be returned if the file is merely readable. -function! ale#python#IsExecutable(path) abort - return has('win32') ? filereadable(a:path) : executable(a:path) -endfunction - " Given a buffer number and a command name, find the path to the executable. " First search on a virtualenv for Python, if nothing is found, try the global " command. Returns an empty string if cannot find the executable @@ -96,7 +90,7 @@ function! ale#python#FindExecutable(buffer, base_var_name, path_list) abort \ join([l:virtualenv, s:bin_dir, l:path], s:sep) \) - if ale#python#IsExecutable(l:ve_executable) + if executable(l:ve_executable) return l:ve_executable endif endfor diff --git a/doc/ale.txt b/doc/ale.txt index fb0b5a7..57928a1 100644 --- a/doc/ale.txt +++ b/doc/ale.txt @@ -247,7 +247,7 @@ Notes: * Fortran: `gcc` * FusionScript: `fusion-lint` * GLSL: glslang -* Go: `gofmt`, `go vet`, `golint`, `gometalinter`!!, `go build`!!, `gosimple`, `staticcheck` +* Go: `gofmt`, `go vet`, `golint`, `gometalinter`!!, `go build`!!, `gosimple`!!, `staticcheck`!! * GraphQL: `gqlint` * Haml: `haml-lint` * Handlebars: `ember-template-lint` diff --git a/test/command_callback/python_paths/with_virtualenv/env/Scripts/autopep8 b/test/command_callback/python_paths/with_virtualenv/env/Scripts/autopep8.exe similarity index 100% rename from test/command_callback/python_paths/with_virtualenv/env/Scripts/autopep8 rename to test/command_callback/python_paths/with_virtualenv/env/Scripts/autopep8.exe diff --git a/test/command_callback/python_paths/with_virtualenv/env/Scripts/flake8 b/test/command_callback/python_paths/with_virtualenv/env/Scripts/flake8.exe similarity index 100% rename from test/command_callback/python_paths/with_virtualenv/env/Scripts/flake8 rename to test/command_callback/python_paths/with_virtualenv/env/Scripts/flake8.exe diff --git a/test/command_callback/python_paths/with_virtualenv/env/Scripts/isort b/test/command_callback/python_paths/with_virtualenv/env/Scripts/isort.exe similarity index 100% rename from test/command_callback/python_paths/with_virtualenv/env/Scripts/isort rename to test/command_callback/python_paths/with_virtualenv/env/Scripts/isort.exe diff --git a/test/command_callback/python_paths/with_virtualenv/env/Scripts/mypy b/test/command_callback/python_paths/with_virtualenv/env/Scripts/mypy.exe similarity index 100% rename from test/command_callback/python_paths/with_virtualenv/env/Scripts/mypy rename to test/command_callback/python_paths/with_virtualenv/env/Scripts/mypy.exe diff --git a/test/command_callback/python_paths/with_virtualenv/env/Scripts/pylint b/test/command_callback/python_paths/with_virtualenv/env/Scripts/pylint.exe similarity index 100% rename from test/command_callback/python_paths/with_virtualenv/env/Scripts/pylint rename to test/command_callback/python_paths/with_virtualenv/env/Scripts/pylint.exe diff --git a/test/command_callback/python_paths/with_virtualenv/env/Scripts/yapf b/test/command_callback/python_paths/with_virtualenv/env/Scripts/yapf.exe similarity index 100% rename from test/command_callback/python_paths/with_virtualenv/env/Scripts/yapf rename to test/command_callback/python_paths/with_virtualenv/env/Scripts/yapf.exe diff --git a/test/command_callback/test_javac_command_callback.vader b/test/command_callback/test_javac_command_callback.vader index 8033e4f..77be1d5 100644 --- a/test/command_callback/test_javac_command_callback.vader +++ b/test/command_callback/test_javac_command_callback.vader @@ -28,12 +28,15 @@ Before: call ale#test#SetFilename('dummy.java') + let g:prefix = 'cd ' . ale#Escape(expand('%:p:h')) . ' && javac -Xlint' + After: call ale#test#RestoreDirectory() Restore unlet! g:cp_sep + unlet! g:prefix delfunction GetCommand @@ -43,20 +46,21 @@ After: call ale#engine#Cleanup(bufnr('')) Execute(The javac callback should return the correct default value): - AssertEqual 'javac -Xlint -d TEMP %t', GetCommand([]) + AssertEqual g:prefix . ' -d TEMP %t', GetCommand([]) Execute(The javac callback should use g:ale_java_javac_classpath correctly): let g:ale_java_javac_classpath = 'foo.jar' AssertEqual - \ 'javac -Xlint' + \ g:prefix \ . ' -cp ' . ale#Escape('foo.jar') \ . ' -d TEMP %t', \ GetCommand([]) Execute(The javac callback should include discovered classpaths): AssertEqual - \ 'javac -Xlint -cp ' + \ g:prefix + \ . ' -cp ' \ . ale#Escape(join(['/foo/bar.jar', '/xyz/abc.jar'], g:cp_sep)) \ . ' -d TEMP %t', \ GetCommand([ @@ -70,7 +74,8 @@ Execute(The javac callback should combine discovered classpaths and manual ones) let g:ale_java_javac_classpath = 'configured.jar' AssertEqual - \ 'javac -Xlint -cp ' + \ g:prefix + \ . ' -cp ' \ . ale#Escape(join( \ [ \ '/foo/bar.jar', @@ -90,7 +95,8 @@ Execute(The javac callback should combine discovered classpaths and manual ones) let g:ale_java_javac_classpath = 'configured.jar' . g:cp_sep . 'configured2.jar' AssertEqual - \ 'javac -Xlint -cp ' + \ g:prefix + \ . ' -cp ' \ . ale#Escape(join( \ [ \ '/foo/bar.jar', @@ -114,7 +120,7 @@ Execute(The javac callback should detect source directories): call ale#engine#InitBufferInfo(bufnr('')) AssertEqual - \ 'javac -Xlint' + \ 'cd ' . ale#Escape(expand('%:p:h')) . ' && javac -Xlint' \ . ' -sourcepath ' . ale#Escape( \ ale#path#Winify(g:dir . '/java_paths/src/main/java/') \ ) @@ -127,7 +133,7 @@ Execute(The javac callback should combine detected source directories and classp call ale#engine#InitBufferInfo(bufnr('')) AssertEqual - \ 'javac -Xlint' + \ 'cd ' . ale#Escape(expand('%:p:h')) . ' && javac -Xlint' \ . ' -cp ' . ale#Escape(join(['/foo/bar.jar', '/xyz/abc.jar'], g:cp_sep)) \ . ' -sourcepath ' . ale#Escape( \ ale#path#Winify(g:dir . '/java_paths/src/main/java/') @@ -146,6 +152,6 @@ Execute(The javac callback should use g:ale_java_javac_options correctly): let b:command = ale_linters#java#javac#GetCommand(bufnr(''), []) AssertEqual - \ 'javac -Xlint' + \ g:prefix \ . ' -d TEMP --anything --else %t', \ GetCommand([]) diff --git a/test/handler/test_ghc_handler.vader b/test/handler/test_ghc_handler.vader index b76046c..b47cdf6 100644 --- a/test/handler/test_ghc_handler.vader +++ b/test/handler/test_ghc_handler.vader @@ -76,3 +76,25 @@ Execute(The ghc handler should handle ghc 7 output): \ ale#path#Winify('src/Main.hs') . ':94:5:Error:', \ ' Some other error', \ ]) + +Execute(The ghc handler should handle stack 1.5.1 output): + call ale#test#SetFilename('src/Main.hs') + + AssertEqual + \ [ + \ { + \ 'lnum': 160, + \ 'col': 14, + \ 'type': 'E', + \ 'text': '• Expecting one fewer arguments to ‘Exp’ Expected kind ‘k0 -> *’, but ‘Exp’ has kind ‘*’ • In the type ‘Exp a’ | 160 | pattern F :: Exp a | ^^^^^', + \ }, + \ ], + \ ale#handlers#haskell#HandleGHCFormat(bufnr(''), [ + \ ' ' . ale#path#Winify('src/Main.hs') . ':160:14: error:', + \ ' • Expecting one fewer arguments to ‘Exp’', + \ ' Expected kind ‘k0 -> *’, but ‘Exp’ has kind ‘*’', + \ ' • In the type ‘Exp a’', + \ ' |', + \ ' 160 | pattern F :: Exp a', + \ ' | ^^^^^', + \ ]) diff --git a/test/handler/test_javac_handler.vader b/test/handler/test_javac_handler.vader index 2cf3207..3997b42 100644 --- a/test/handler/test_javac_handler.vader +++ b/test/handler/test_javac_handler.vader @@ -1,42 +1,51 @@ Before: runtime ale_linters/java/javac.vim + call ale#test#SetDirectory('/testplugin/test') + call ale#test#SetFilename('dummy.java') + After: + call ale#test#RestoreDirectory() call ale#linter#Reset() Execute(The javac handler should handle cannot find symbol errors): AssertEqual \ [ \ { + \ 'filename': '/tmp/vLPr4Q5/33/foo.java', \ 'lnum': 1, \ 'text': 'error: some error', \ 'type': 'E', \ }, \ { + \ 'filename': '/tmp/vLPr4Q5/33/foo.java', \ 'lnum': 2, \ 'col': 5, \ 'text': 'error: cannot find symbol: BadName', \ 'type': 'E', \ }, \ { + \ 'filename': '/tmp/vLPr4Q5/33/foo.java', \ 'lnum': 34, \ 'col': 5, \ 'text': 'error: cannot find symbol: BadName2', \ 'type': 'E', \ }, \ { + \ 'filename': '/tmp/vLPr4Q5/33/foo.java', \ 'lnum': 37, \ 'text': 'warning: some warning', \ 'type': 'W', \ }, \ { + \ 'filename': '/tmp/vLPr4Q5/33/foo.java', \ 'lnum': 42, \ 'col': 11, \ 'text': 'error: cannot find symbol: bar()', \ 'type': 'E', \ }, \ ], - \ ale_linters#java#javac#Handle(347, [ + \ ale_linters#java#javac#Handle(bufnr(''), [ \ '/tmp/vLPr4Q5/33/foo.java:1: error: some error', \ '/tmp/vLPr4Q5/33/foo.java:2: error: cannot find symbol', \ ' BadName foo() {', @@ -49,9 +58,30 @@ Execute(The javac handler should handle cannot find symbol errors): \ ' symbol: class BadName2', \ ' location: class Bar', \ '/tmp/vLPr4Q5/33/foo.java:37: warning: some warning', - \ '/tmp/vLPr4Q5/264/foo.java:42: error: cannot find symbol', + \ '/tmp/vLPr4Q5/33/foo.java:42: error: cannot find symbol', \ ' this.bar();', \ ' ^', \ ' symbol: method bar()', \ '5 errors', \ ]) + +Execute(The javac handler should resolve files from different directories): + AssertEqual + \ [ + \ { + \ 'filename': ale#path#Winify(g:dir . '/Foo.java'), + \ 'lnum': 1, + \ 'text': 'error: some error', + \ 'type': 'E', + \ }, + \ { + \ 'filename': ale#path#Winify(g:dir . '/Bar.java'), + \ 'lnum': 1, + \ 'text': 'error: some error', + \ 'type': 'E', + \ }, + \ ], + \ ale_linters#java#javac#Handle(bufnr(''), [ + \ './Foo.java:1: error: some error', + \ './Bar.java:1: error: some error', + \ ]) diff --git a/test/handler/test_tslint_handler.vader b/test/handler/test_tslint_handler.vader index 2ed3357..db6294c 100644 --- a/test/handler/test_tslint_handler.vader +++ b/test/handler/test_tslint_handler.vader @@ -252,3 +252,26 @@ Execute(The tslint handler should report errors when the ignore option is on, bu \ 'position': 1 \ } \ }])]) + +Execute(The tslint handler should not report no-implicit-dependencies errors): + call ale#test#SetFilename('app/test.ts') + + AssertEqual + \ [ + \ ], + \ ale_linters#typescript#tslint#Handle(bufnr(''), [json_encode([{ + \ 'endPosition': { + \ 'character': 0, + \ 'line': 1, + \ 'position': 1 + \ }, + \ 'failure': 'this is ignored', + \ 'name': 'test.ts', + \ 'ruleName': 'no-implicit-dependencies', + \ 'ruleSeverity': 'ERROR', + \ 'startPosition': { + \ 'character': 0, + \ 'line': 1, + \ 'position': 1 + \ } + \ }])]) diff --git a/test/lsp/test_lsp_client_messages.vader b/test/lsp/test_lsp_client_messages.vader index 7ec905c..a7660ce 100644 --- a/test/lsp/test_lsp_client_messages.vader +++ b/test/lsp/test_lsp_client_messages.vader @@ -45,7 +45,7 @@ Execute(ale#lsp#message#DidOpen() should return correct messages): \ 'uri': ale#path#ToURI(g:dir . '/foo/bar.ts'), \ 'languageId': 'typescript', \ 'version': 12, - \ 'text': "foo()\nbar()\nbaz()", + \ 'text': "foo()\nbar()\nbaz()\n", \ }, \ } \ ], @@ -63,7 +63,7 @@ Execute(ale#lsp#message#DidChange() should return correct messages): \ 'uri': ale#path#ToURI(g:dir . '/foo/bar.ts'), \ 'version': 34, \ }, - \ 'contentChanges': [{'text': "foo()\nbar()\nbaz()"}], + \ 'contentChanges': [{'text': "foo()\nbar()\nbaz()\n"}], \ } \ ], \ ale#lsp#message#DidChange(bufnr('')) @@ -134,7 +134,7 @@ Execute(ale#lsp#tsserver_message#Change() should return correct messages): \ 'offset': 1, \ 'endLine': 1073741824, \ 'endOffset': 1, - \ 'insertString': "foo()\nbar()\nbaz()", + \ 'insertString': "foo()\nbar()\nbaz()\n", \ } \ ], \ ale#lsp#tsserver_message#Change(bufnr('')) diff --git a/test/test_completion.vader b/test/test_completion.vader index 811a264..3dfc205 100644 --- a/test/test_completion.vader +++ b/test/test_completion.vader @@ -13,6 +13,21 @@ Before: call add(g:test_vars.feedkeys_calls, [a:string, a:mode]) endfunction + function! CheckCompletionCalled(expect_success) abort + let g:test_vars.get_completions_called = 0 + + " We just want to check if the function is called. + function! ale#completion#GetCompletions() + let g:test_vars.get_completions_called = 1 + endfunction + + let g:ale_completion_delay = 0 + call ale#completion#Queue() + sleep 1m + + AssertEqual a:expect_success, g:test_vars.get_completions_called + endfunction + After: Restore @@ -22,6 +37,13 @@ After: unlet! b:ale_completion_info unlet! b:ale_completion_response unlet! b:ale_completion_parser + unlet! b:ale_complete_done_time + + delfunction CheckCompletionCalled + + " Stop any timers we left behind. + " This stops the tests from failing randomly. + call ale#completion#StopTimer() runtime autoload/ale/completion.vim runtime autoload/ale/lsp.vim @@ -294,18 +316,7 @@ Execute(b:ale_completion_info should be set up correctly when requesting complet \ b:ale_completion_info Execute(ale#completion#GetCompletions should be called when the cursor position stays the same): - let g:test_vars.get_completions_called = 0 - - " We just want to check if the function is called. - function! ale#completion#GetCompletions() - let g:test_vars.get_completions_called = 1 - endfunction - - let g:ale_completion_delay = 0 - call ale#completion#Queue() - sleep 1m - - Assert g:test_vars.get_completions_called + call CheckCompletionCalled(1) Execute(ale#completion#GetCompletions should not be called when the cursor position changes): call setpos('.', [bufnr(''), 1, 2, 0]) @@ -326,3 +337,8 @@ Execute(ale#completion#GetCompletions should not be called when the cursor posit sleep 1m Assert !g:test_vars.get_completions_called + +Execute(Completion should not be done shortly after the CompleteDone function): + call CheckCompletionCalled(1) + call ale#completion#Done() + call CheckCompletionCalled(0) diff --git a/test/test_line_join.vader b/test/test_line_join.vader index 0426429..c93b192 100644 --- a/test/test_line_join.vader +++ b/test/test_line_join.vader @@ -62,8 +62,8 @@ Execute (ALE should pass on full lines for NeoVim for raw data): Execute (ALE should pass on a single long line): let g:last_line = ale#job#JoinNeovimOutput(1, '', ['x'], 'raw', function('RawCallback')) - AssertEqual '', g:data - AssertEqual 'x', g:last_line + AssertEqual 'x', g:data + AssertEqual '', g:last_line Execute (ALE should handle just a single line of output): let g:last_line = ale#job#JoinNeovimOutput(1, '', ['x', ''], 'raw', function('RawCallback')) @@ -71,20 +71,8 @@ Execute (ALE should handle just a single line of output): AssertEqual "x\n", g:data AssertEqual '', g:last_line -Execute (ALE should join two incomplete pieces of large lines together): - let g:last_line = ale#job#JoinNeovimOutput(1, 'x', ['y'], 'raw', function('RawCallback')) +Execute (ALE should pass on two lines and one incomplete one): + let g:last_line = ale#job#JoinNeovimOutput(1, '', ['y', 'z', 'a'], 'raw', function('RawCallback')) - AssertEqual '', g:data - AssertEqual 'xy', g:last_line - -Execute (ALE join incomplete lines, and set new ones): - let g:last_line = ale#job#JoinNeovimOutput(1, 'x', ['y', 'z', 'a'], 'raw', function('RawCallback')) - - AssertEqual "xy\nz\n", g:data - AssertEqual 'a', g:last_line - -Execute (ALE join incomplete lines, and set new ones, with two elements): - let g:last_line = ale#job#JoinNeovimOutput(1, 'x', ['y', 'z'], 'raw', function('RawCallback')) - - AssertEqual "xy\n", g:data - AssertEqual 'z', g:last_line + AssertEqual "y\nz\na", g:data + AssertEqual '', g:last_line diff --git a/test/test_path_uri.vader b/test/test_path_uri.vader index dbceac3..a3e68d9 100644 --- a/test/test_path_uri.vader +++ b/test/test_path_uri.vader @@ -2,6 +2,9 @@ Execute(ale#path#ToURI should work for Windows paths): AssertEqual 'file:///C:/foo/bar/baz.tst', ale#path#ToURI('C:\foo\bar\baz.tst') AssertEqual 'foo/bar/baz.tst', ale#path#ToURI('foo\bar\baz.tst') +Execute(ale#path#FromURI should work for Windows paths): + AssertEqual 'C:\foo\bar\baz.tst', ale#path#FromURI('file:///C:/foo/bar/baz.tst') + Execute(ale#path#ToURI should work for Unix paths): AssertEqual 'file:///foo/bar/baz.tst', ale#path#ToURI('/foo/bar/baz.tst') AssertEqual 'foo/bar/baz.tst', ale#path#ToURI('foo/bar/baz.tst') diff --git a/test/test_shell_detection.vader b/test/test_shell_detection.vader index 37cf43c..adb8d70 100644 --- a/test/test_shell_detection.vader +++ b/test/test_shell_detection.vader @@ -81,3 +81,23 @@ Execute(The ksh dialect should be used for shellcheck if b:is_kornshell is 1): let b:is_kornshell = 1 AssertEqual 'ksh', ale_linters#sh#shellcheck#GetDialectArgument(bufnr('')) + +Given(A file with /bin/ash): + #!/bin/ash + +Execute(The ash dialect should be used for the shell and the base function): + AssertEqual 'ash', ale#handlers#sh#GetShellType(bufnr('')) + AssertEqual 'ash', ale_linters#sh#shell#GetExecutable(bufnr('')) + +Execute(dash should be used for shellcheck, which has no ash dialect): + AssertEqual 'dash', ale_linters#sh#shellcheck#GetDialectArgument(bufnr('')) + +Given(A file with /bin/dash): + #!/bin/dash + +Execute(The dash dialect should be used for the shell and the base function): + AssertEqual 'dash', ale#handlers#sh#GetShellType(bufnr('')) + AssertEqual 'dash', ale_linters#sh#shell#GetExecutable(bufnr('')) + +Execute(dash should be used for shellcheck): + AssertEqual 'dash', ale_linters#sh#shellcheck#GetDialectArgument(bufnr('')) diff --git a/test/test_should_do_nothing_conditions.vader b/test/test_should_do_nothing_conditions.vader index 3afa11a..23ebd92 100644 --- a/test/test_should_do_nothing_conditions.vader +++ b/test/test_should_do_nothing_conditions.vader @@ -1,6 +1,8 @@ Before: Save &l:statusline + call ale#test#SetDirectory('/testplugin/test') + let b:funky_command_created = 0 " We will test for the existence of this command, so create one if needed. @@ -10,6 +12,8 @@ Before: endif After: + call ale#test#RestoreDirectory() + if b:funky_command_created delcommand CtrlPFunky let b:funky_command_created = 0 @@ -25,3 +29,13 @@ Execute(ALE shouldn't do much of anything for ctrlp-funky buffers): let &l:statusline = '%#CtrlPMode2# prt %*%#CtrlPMode1# line %* ={%#CtrlPMode1# funky %*}= <-> %=%<%#CtrlPMode2# %{getcwd()} %*' Assert ale#ShouldDoNothing(bufnr('')) + +Execute(ALE shouldn't try to check buffers with '.' as the filename): + AssertEqual + \ 0, + \ ale#ShouldDoNothing(bufnr('')), + \ 'ShouldDoNothing() was 1 for some other reason' + + silent! noautocmd file . + + Assert ale#ShouldDoNothing(bufnr(''))