Compare commits

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

17 commits

Author SHA1 Message Date
w0rp
5556fcbd1c Stop the completion tests from failing randomly 2017-11-21 14:57:28 +00:00
w0rp
cf599f4470 #1149 Fix conversion from URIs to filenames on Windows 2017-11-21 14:56:37 +00:00
w0rp
e71d831119 Fix #1124 - Handle stack-build errors with leading spaces 2017-11-13 22:48:30 +00:00
w0rp
d8abe0d6a2 Fix #1101 - Ignore no-implicit-dependencies errors until TSLint supports checking via stdin properly 2017-11-09 10:33:56 +00:00
w0rp
55757e3d78 #1006 Fix raw message handling for LSP support in NeoVim 2017-11-06 22:53:27 +00:00
w0rp
8e7ede3be8 Fix #1085 - Add a final newline character to tsserver and LSP messages 2017-11-05 21:52:11 +00:00
w0rp
6f8db3e5c4 Fix #1061 - Handle the filenames returned by javac 2017-11-05 15:34:46 +00:00
w0rp
2398fd7456 Fix #1058 - Ignore all errors with bad calls to jobstop() in NeoVim 2017-11-04 10:54:06 +00:00
w0rp
c1366f8a62 #1081 Remove the ale#python#IsExecutable function 2017-11-04 10:47:47 +00:00
w0rp
5089b09b7e #1081 Use executable() for Python executables on Windows, and rename the test files to .exe so they will pass the executable() check 2017-11-04 10:47:35 +00:00
Antoine Reilles
220ebb3a79 windows compatible warning match pattern for erlc (#1071)
* windows compatible warning match pattern for erlc
2017-11-03 18:57:21 +00:00
w0rp
25b5fad15c Merge pull request #1072 from drrcknlsn/master
Prevent logging of errors in the php linter.
2017-11-01 20:56:43 +00:00
w0rp
39f15811c3 Fix #936 - Check the actual files for gosimple and staticcheck 2017-10-31 13:01:52 +00:00
w0rp
34171774eb Fix #1041 - Do not request completions shortly after CompleteDone 2017-10-26 23:19:49 +01:00
w0rp
80328fa156 Fix #1051 - Support ash and dash for shellcheck and the sh linter 2017-10-26 21:17:47 +01:00
w0rp
1fcf6444dc Fix #1048 - Do not lint files named "." 2017-10-26 20:30:40 +01:00
w0rp
e57978ddd6 Fix #1045 - Handle both output streams for Cargo 2017-10-26 10:04:52 +01:00
38 changed files with 251 additions and 90 deletions

View file

@ -95,7 +95,7 @@ formatting.
| Fortran | [gcc](https://gcc.gnu.org/) | | Fortran | [gcc](https://gcc.gnu.org/) |
| FusionScript | [fusion-lint](https://github.com/RyanSquared/fusionscript) | | FusionScript | [fusion-lint](https://github.com/RyanSquared/fusionscript) |
| GLSL | [glslang](https://github.com/KhronosGroup/glslang) | | 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) | | GraphQL | [gqlint](https://github.com/happylinks/gqlint) |
| Haml | [haml-lint](https://github.com/brigade/haml-lint) | | Haml | [haml-lint](https://github.com/brigade/haml-lint) |
| Handlebars | [ember-template-lint](https://github.com/rwjblue/ember-template-lint) | | Handlebars | [ember-template-lint](https://github.com/rwjblue/ember-template-lint) |

View file

@ -17,7 +17,7 @@ function! ale_linters#erlang#erlc#Handle(buffer, lines) abort
" error.erl:4: variable 'B' is unbound " error.erl:4: variable 'B' is unbound
" error.erl:3: Warning: function main/0 is unused " error.erl:3: Warning: function main/0 is unused
" error.erl:4: Warning: variable 'A' 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: " parse_transforms are a special case. The error message does not indicate a location:
" error.erl: undefined parse transform 'some_parse_transform' " error.erl: undefined parse transform 'some_parse_transform'

View file

@ -4,7 +4,8 @@
call ale#linter#Define('go', { call ale#linter#Define('go', {
\ 'name': 'gosimple', \ 'name': 'gosimple',
\ 'executable': 'gosimple', \ 'executable': 'gosimple',
\ 'command': 'gosimple %t', \ 'command': 'gosimple %s',
\ 'callback': 'ale#handlers#unix#HandleAsWarning', \ 'callback': 'ale#handlers#unix#HandleAsWarning',
\ 'output_stream': 'both' \ 'output_stream': 'both',
\ 'lint_file': 1,
\}) \})

View file

@ -4,7 +4,8 @@
call ale#linter#Define('go', { call ale#linter#Define('go', {
\ 'name': 'staticcheck', \ 'name': 'staticcheck',
\ 'executable': 'staticcheck', \ 'executable': 'staticcheck',
\ 'command': 'staticcheck %t', \ 'command': 'staticcheck %s',
\ 'callback': 'ale#handlers#unix#HandleAsWarning', \ 'callback': 'ale#handlers#unix#HandleAsWarning',
\ 'output_stream': 'both' \ 'output_stream': 'both',
\ 'lint_file': 1,
\}) \})

View file

@ -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. " Create .class files in a temporary directory, which we will delete later.
let l:class_file_directory = ale#engine#CreateDirectory(a:buffer) 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:cp_option
\ . ' ' . l:sp_option \ . ' ' . l:sp_option
\ . ' -d ' . ale#Escape(l:class_file_directory) \ . ' -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:13: warning: [deprecation] donaught() in Testclass has been deprecated
" Main.java:16: error: ';' expected " 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:col_pattern = '\v^(\s*\^)$'
let l:symbol_pattern = '\v^ +symbol: *(class|method) +([^ ]+)' let l:symbol_pattern = '\v^ +symbol: *(class|method) +([^ ]+)'
let l:output = [] let l:output = []
for l:match in ale#util#GetMatches(a:lines, [l:pattern, l:col_pattern, l:symbol_pattern]) 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]) 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]) elseif empty(l:match[3])
" Add symbols to 'cannot find symbol' errors. " Add symbols to 'cannot find symbol' errors.
if l:output[-1].text is# 'error: cannot find symbol' if l:output[-1].text is# 'error: cannot find symbol'
@ -78,9 +82,10 @@ function! ale_linters#java#javac#Handle(buffer, lines) abort
endif endif
else else
call add(l:output, { call add(l:output, {
\ 'lnum': l:match[1] + 0, \ 'filename': ale#path#GetAbsPath(l:directory, l:match[1]),
\ 'text': l:match[2] . ':' . l:match[3], \ 'lnum': l:match[2] + 0,
\ 'type': l:match[2] is# 'error' ? 'E' : 'W', \ 'text': l:match[3] . ':' . l:match[4],
\ 'type': l:match[3] is# 'error' ? 'E' : 'W',
\}) \})
endif endif
endfor endfor

View file

@ -30,6 +30,6 @@ call ale#linter#Define('php', {
\ 'name': 'php', \ 'name': 'php',
\ 'executable': 'php', \ 'executable': 'php',
\ 'output_stream': 'stdout', \ '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', \ 'callback': 'ale_linters#php#php#Handle',
\}) \})

View file

@ -26,6 +26,6 @@ call ale#linter#Define('rust', {
\ 'executable_callback': 'ale_linters#rust#cargo#GetCargoExecutable', \ 'executable_callback': 'ale_linters#rust#cargo#GetCargoExecutable',
\ 'command_callback': 'ale_linters#rust#cargo#GetCommand', \ 'command_callback': 'ale_linters#rust#cargo#GetCommand',
\ 'callback': 'ale#handlers#rust#HandleRustErrors', \ 'callback': 'ale#handlers#rust#HandleRustErrors',
\ 'output_stream': 'stdout', \ 'output_stream': 'both',
\ 'lint_file': 1, \ 'lint_file': 1,
\}) \})

View file

@ -23,15 +23,20 @@ function! ale_linters#sh#shellcheck#GetDialectArgument(buffer) abort
let l:shell_type = ale#handlers#sh#GetShellType(a:buffer) let l:shell_type = ale#handlers#sh#GetShellType(a:buffer)
if !empty(l:shell_type) 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 return l:shell_type
endif endif
" If there's no hashbang, try using Vim's buffer variables. " 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' return 'bash'
elseif get(b:, 'is_sh') elseif getbufvar(a:buffer, 'is_sh', 0)
return 'sh' return 'sh'
elseif get(b:, 'is_kornshell') elseif getbufvar(a:buffer, 'is_kornshell', 0)
return 'ksh' return 'ksh'
endif endif

View file

@ -24,6 +24,10 @@ function! ale_linters#typescript#tslint#Handle(buffer, lines) abort
let l:output = [] let l:output = []
for l:error in ale#util#FuzzyJSONDecode(a:lines, []) for l:error in ale#util#FuzzyJSONDecode(a:lines, [])
if get(l:error, 'ruleName', '') is# 'no-implicit-dependencies'
continue
endif
call add(l:output, { call add(l:output, {
\ 'filename': ale#path#GetAbsPath(l:dir, l:error.name), \ 'filename': ale#path#GetAbsPath(l:dir, l:error.name),
\ 'type': (get(l:error, 'ruleSeverity', '') is# 'WARNING' ? 'W' : 'E'), \ 'type': (get(l:error, 'ruleSeverity', '') is# 'WARNING' ? 'W' : 'E'),

View file

@ -61,6 +61,12 @@ function! ale#ShouldDoNothing(buffer) abort
return 1 return 1
endif endif
let l:filename = fnamemodify(bufname(a:buffer), ':t')
if l:filename is# '.'
return 1
endif
" Do nothing if running in the sandbox " Do nothing if running in the sandbox
if ale#util#InSandbox() if ale#util#InSandbox()
return 1 return 1

View file

@ -282,7 +282,23 @@ function! s:TimerHandler(...) abort
endif endif
endfunction 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 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] let s:timer_pos = getcurpos()[1:2]
" If we changed the text again while we're still waiting for a response, " 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 let b:ale_completion_info.request_id = 0
endif endif
if s:timer_id != -1 call ale#completion#StopTimer()
call timer_stop(s:timer_id)
endif
let s:timer_id = timer_start(g:ale_completion_delay, function('s:TimerHandler')) let s:timer_id = timer_start(g:ale_completion_delay, function('s:TimerHandler'))
endfunction endfunction
@ -311,6 +325,9 @@ function! ale#completion#Done() abort
let &l:completeopt = b:ale_old_completopt let &l:completeopt = b:ale_old_completopt
unlet b:ale_old_completopt unlet b:ale_old_completopt
endif endif
" Set a timestamp, so we can avoid requesting completions again.
let b:ale_complete_done_time = ale#util#ClockMilliseconds()
endfunction endfunction
function! s:Setup(enabled) abort function! s:Setup(enabled) abort

View file

@ -12,7 +12,7 @@ function! ale#fixers#autopep8#Fix(buffer) abort
\ ['autopep8'], \ ['autopep8'],
\) \)
if !ale#python#IsExecutable(l:executable) if !executable(l:executable)
return 0 return 0
endif endif

View file

@ -11,7 +11,7 @@ function! ale#fixers#isort#Fix(buffer) abort
\ ['isort'], \ ['isort'],
\) \)
if !ale#python#IsExecutable(l:executable) if !executable(l:executable)
return 0 return 0
endif endif

View file

@ -11,7 +11,7 @@ function! ale#fixers#yapf#Fix(buffer) abort
\ ['yapf'], \ ['yapf'],
\) \)
if !ale#python#IsExecutable(l:executable) if !executable(l:executable)
return 0 return 0
endif endif

View file

@ -19,7 +19,7 @@ function! ale#handlers#haskell#HandleGHCFormat(buffer, lines) abort
" in Haskell error messages with the basename for this file. " in Haskell error messages with the basename for this file.
let l:temp_filename_regex = s:temp_regex_prefix . l:basename 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:output = []
let l:corrected_lines = [] let l:corrected_lines = []

View file

@ -9,7 +9,7 @@ function! ale#handlers#sh#GetShellType(buffer) abort
" Remove options like -e, etc. " Remove options like -e, etc.
let l:command = substitute(l:bang_line, ' --\?[a-zA-Z0-9]\+', '', 'g') 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*$' if l:command =~# l:possible_shell . '\s*$'
return l:possible_shell return l:possible_shell
endif endif

View file

@ -25,6 +25,11 @@ endfunction
" Note that jobs and IDs are the same thing on NeoVim. " Note that jobs and IDs are the same thing on NeoVim.
function! ale#job#JoinNeovimOutput(job, last_line, data, mode, callback) abort 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] let l:lines = a:data[:-2]
if len(a:data) > 1 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] let l:new_last_line = a:last_line . a:data[0]
endif endif
if a:mode is# 'raw' for l:line in l:lines
if !empty(l:lines) call a:callback(a:job, l:line)
call a:callback(a:job, join(l:lines, "\n") . "\n") endfor
endif
else
for l:line in l:lines
call a:callback(a:job, l:line)
endfor
endif
return l:new_last_line return l:new_last_line
endfunction 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 " 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 " which are child processes on Unix. Some work needs to be done to
" kill child processes to stop long-running processes like pylint. " kill child processes to stop long-running processes like pylint.
call jobstop(a:job_id) silent! call jobstop(a:job_id)
else else
let l:job = s:job_map[a:job_id].job let l:job = s:job_map[a:job_id].job

View file

@ -53,7 +53,7 @@ function! ale#lsp#message#DidOpen(buffer, language_id) abort
\ 'uri': ale#path#ToURI(expand('#' . a:buffer . ':p')), \ 'uri': ale#path#ToURI(expand('#' . a:buffer . ':p')),
\ 'languageId': a:language_id, \ 'languageId': a:language_id,
\ 'version': ale#lsp#message#GetNextVersionID(), \ 'version': ale#lsp#message#GetNextVersionID(),
\ 'text': join(l:lines, "\n"), \ 'text': join(l:lines, "\n") . "\n",
\ }, \ },
\}] \}]
endfunction endfunction
@ -67,7 +67,7 @@ function! ale#lsp#message#DidChange(buffer) abort
\ 'uri': ale#path#ToURI(expand('#' . a:buffer . ':p')), \ 'uri': ale#path#ToURI(expand('#' . a:buffer . ':p')),
\ 'version': ale#lsp#message#GetNextVersionID(), \ 'version': ale#lsp#message#GetNextVersionID(),
\ }, \ },
\ 'contentChanges': [{'text': join(l:lines, "\n")}] \ 'contentChanges': [{'text': join(l:lines, "\n") . "\n"}]
\}] \}]
endfunction endfunction

View file

@ -28,7 +28,7 @@ function! ale#lsp#tsserver_message#Change(buffer) abort
\ 'offset': 1, \ 'offset': 1,
\ 'endLine': 1073741824, \ 'endLine': 1073741824,
\ 'endOffset': 1, \ 'endOffset': 1,
\ 'insertString': join(l:lines, "\n"), \ 'insertString': join(l:lines, "\n") . "\n",
\}] \}]
endfunction endfunction

View file

@ -185,5 +185,12 @@ function! ale#path#FromURI(uri) abort
let l:i = len('file://') let l:i = len('file://')
let l:encoded_path = a:uri[: l:i - 1] is# 'file://' ? a:uri[l:i :] : a:uri 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 endfunction

View file

@ -74,12 +74,6 @@ function! ale#python#FindVirtualenv(buffer) abort
return $VIRTUAL_ENV return $VIRTUAL_ENV
endfunction 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. " 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 " First search on a virtualenv for Python, if nothing is found, try the global
" command. Returns an empty string if cannot find the executable " 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) \ 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 return l:ve_executable
endif endif
endfor endfor

View file

@ -247,7 +247,7 @@ Notes:
* Fortran: `gcc` * Fortran: `gcc`
* FusionScript: `fusion-lint` * FusionScript: `fusion-lint`
* GLSL: glslang * GLSL: glslang
* Go: `gofmt`, `go vet`, `golint`, `gometalinter`!!, `go build`!!, `gosimple`, `staticcheck` * Go: `gofmt`, `go vet`, `golint`, `gometalinter`!!, `go build`!!, `gosimple`!!, `staticcheck`!!
* GraphQL: `gqlint` * GraphQL: `gqlint`
* Haml: `haml-lint` * Haml: `haml-lint`
* Handlebars: `ember-template-lint` * Handlebars: `ember-template-lint`

View file

@ -28,12 +28,15 @@ Before:
call ale#test#SetFilename('dummy.java') call ale#test#SetFilename('dummy.java')
let g:prefix = 'cd ' . ale#Escape(expand('%:p:h')) . ' && javac -Xlint'
After: After:
call ale#test#RestoreDirectory() call ale#test#RestoreDirectory()
Restore Restore
unlet! g:cp_sep unlet! g:cp_sep
unlet! g:prefix
delfunction GetCommand delfunction GetCommand
@ -43,20 +46,21 @@ After:
call ale#engine#Cleanup(bufnr('')) call ale#engine#Cleanup(bufnr(''))
Execute(The javac callback should return the correct default value): 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): Execute(The javac callback should use g:ale_java_javac_classpath correctly):
let g:ale_java_javac_classpath = 'foo.jar' let g:ale_java_javac_classpath = 'foo.jar'
AssertEqual AssertEqual
\ 'javac -Xlint' \ g:prefix
\ . ' -cp ' . ale#Escape('foo.jar') \ . ' -cp ' . ale#Escape('foo.jar')
\ . ' -d TEMP %t', \ . ' -d TEMP %t',
\ GetCommand([]) \ GetCommand([])
Execute(The javac callback should include discovered classpaths): Execute(The javac callback should include discovered classpaths):
AssertEqual AssertEqual
\ 'javac -Xlint -cp ' \ g:prefix
\ . ' -cp '
\ . ale#Escape(join(['/foo/bar.jar', '/xyz/abc.jar'], g:cp_sep)) \ . ale#Escape(join(['/foo/bar.jar', '/xyz/abc.jar'], g:cp_sep))
\ . ' -d TEMP %t', \ . ' -d TEMP %t',
\ GetCommand([ \ GetCommand([
@ -70,7 +74,8 @@ Execute(The javac callback should combine discovered classpaths and manual ones)
let g:ale_java_javac_classpath = 'configured.jar' let g:ale_java_javac_classpath = 'configured.jar'
AssertEqual AssertEqual
\ 'javac -Xlint -cp ' \ g:prefix
\ . ' -cp '
\ . ale#Escape(join( \ . ale#Escape(join(
\ [ \ [
\ '/foo/bar.jar', \ '/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' let g:ale_java_javac_classpath = 'configured.jar' . g:cp_sep . 'configured2.jar'
AssertEqual AssertEqual
\ 'javac -Xlint -cp ' \ g:prefix
\ . ' -cp '
\ . ale#Escape(join( \ . ale#Escape(join(
\ [ \ [
\ '/foo/bar.jar', \ '/foo/bar.jar',
@ -114,7 +120,7 @@ Execute(The javac callback should detect source directories):
call ale#engine#InitBufferInfo(bufnr('')) call ale#engine#InitBufferInfo(bufnr(''))
AssertEqual AssertEqual
\ 'javac -Xlint' \ 'cd ' . ale#Escape(expand('%:p:h')) . ' && javac -Xlint'
\ . ' -sourcepath ' . ale#Escape( \ . ' -sourcepath ' . ale#Escape(
\ ale#path#Winify(g:dir . '/java_paths/src/main/java/') \ 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('')) call ale#engine#InitBufferInfo(bufnr(''))
AssertEqual AssertEqual
\ 'javac -Xlint' \ 'cd ' . ale#Escape(expand('%:p:h')) . ' && javac -Xlint'
\ . ' -cp ' . ale#Escape(join(['/foo/bar.jar', '/xyz/abc.jar'], g:cp_sep)) \ . ' -cp ' . ale#Escape(join(['/foo/bar.jar', '/xyz/abc.jar'], g:cp_sep))
\ . ' -sourcepath ' . ale#Escape( \ . ' -sourcepath ' . ale#Escape(
\ ale#path#Winify(g:dir . '/java_paths/src/main/java/') \ 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(''), []) let b:command = ale_linters#java#javac#GetCommand(bufnr(''), [])
AssertEqual AssertEqual
\ 'javac -Xlint' \ g:prefix
\ . ' -d TEMP --anything --else %t', \ . ' -d TEMP --anything --else %t',
\ GetCommand([]) \ GetCommand([])

View file

@ -76,3 +76,25 @@ Execute(The ghc handler should handle ghc 7 output):
\ ale#path#Winify('src/Main.hs') . ':94:5:Error:', \ ale#path#Winify('src/Main.hs') . ':94:5:Error:',
\ ' Some other 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',
\ ' | ^^^^^',
\ ])

View file

@ -1,42 +1,51 @@
Before: Before:
runtime ale_linters/java/javac.vim runtime ale_linters/java/javac.vim
call ale#test#SetDirectory('/testplugin/test')
call ale#test#SetFilename('dummy.java')
After: After:
call ale#test#RestoreDirectory()
call ale#linter#Reset() call ale#linter#Reset()
Execute(The javac handler should handle cannot find symbol errors): Execute(The javac handler should handle cannot find symbol errors):
AssertEqual AssertEqual
\ [ \ [
\ { \ {
\ 'filename': '/tmp/vLPr4Q5/33/foo.java',
\ 'lnum': 1, \ 'lnum': 1,
\ 'text': 'error: some error', \ 'text': 'error: some error',
\ 'type': 'E', \ 'type': 'E',
\ }, \ },
\ { \ {
\ 'filename': '/tmp/vLPr4Q5/33/foo.java',
\ 'lnum': 2, \ 'lnum': 2,
\ 'col': 5, \ 'col': 5,
\ 'text': 'error: cannot find symbol: BadName', \ 'text': 'error: cannot find symbol: BadName',
\ 'type': 'E', \ 'type': 'E',
\ }, \ },
\ { \ {
\ 'filename': '/tmp/vLPr4Q5/33/foo.java',
\ 'lnum': 34, \ 'lnum': 34,
\ 'col': 5, \ 'col': 5,
\ 'text': 'error: cannot find symbol: BadName2', \ 'text': 'error: cannot find symbol: BadName2',
\ 'type': 'E', \ 'type': 'E',
\ }, \ },
\ { \ {
\ 'filename': '/tmp/vLPr4Q5/33/foo.java',
\ 'lnum': 37, \ 'lnum': 37,
\ 'text': 'warning: some warning', \ 'text': 'warning: some warning',
\ 'type': 'W', \ 'type': 'W',
\ }, \ },
\ { \ {
\ 'filename': '/tmp/vLPr4Q5/33/foo.java',
\ 'lnum': 42, \ 'lnum': 42,
\ 'col': 11, \ 'col': 11,
\ 'text': 'error: cannot find symbol: bar()', \ 'text': 'error: cannot find symbol: bar()',
\ 'type': 'E', \ '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:1: error: some error',
\ '/tmp/vLPr4Q5/33/foo.java:2: error: cannot find symbol', \ '/tmp/vLPr4Q5/33/foo.java:2: error: cannot find symbol',
\ ' BadName foo() {', \ ' BadName foo() {',
@ -49,9 +58,30 @@ Execute(The javac handler should handle cannot find symbol errors):
\ ' symbol: class BadName2', \ ' symbol: class BadName2',
\ ' location: class Bar', \ ' location: class Bar',
\ '/tmp/vLPr4Q5/33/foo.java:37: warning: some warning', \ '/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();', \ ' this.bar();',
\ ' ^', \ ' ^',
\ ' symbol: method bar()', \ ' symbol: method bar()',
\ '5 errors', \ '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',
\ ])

View file

@ -252,3 +252,26 @@ Execute(The tslint handler should report errors when the ignore option is on, bu
\ 'position': 1 \ '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
\ }
\ }])])

View file

@ -45,7 +45,7 @@ Execute(ale#lsp#message#DidOpen() should return correct messages):
\ 'uri': ale#path#ToURI(g:dir . '/foo/bar.ts'), \ 'uri': ale#path#ToURI(g:dir . '/foo/bar.ts'),
\ 'languageId': 'typescript', \ 'languageId': 'typescript',
\ 'version': 12, \ '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'), \ 'uri': ale#path#ToURI(g:dir . '/foo/bar.ts'),
\ 'version': 34, \ 'version': 34,
\ }, \ },
\ 'contentChanges': [{'text': "foo()\nbar()\nbaz()"}], \ 'contentChanges': [{'text': "foo()\nbar()\nbaz()\n"}],
\ } \ }
\ ], \ ],
\ ale#lsp#message#DidChange(bufnr('')) \ ale#lsp#message#DidChange(bufnr(''))
@ -134,7 +134,7 @@ Execute(ale#lsp#tsserver_message#Change() should return correct messages):
\ 'offset': 1, \ 'offset': 1,
\ 'endLine': 1073741824, \ 'endLine': 1073741824,
\ 'endOffset': 1, \ 'endOffset': 1,
\ 'insertString': "foo()\nbar()\nbaz()", \ 'insertString': "foo()\nbar()\nbaz()\n",
\ } \ }
\ ], \ ],
\ ale#lsp#tsserver_message#Change(bufnr('')) \ ale#lsp#tsserver_message#Change(bufnr(''))

View file

@ -13,6 +13,21 @@ Before:
call add(g:test_vars.feedkeys_calls, [a:string, a:mode]) call add(g:test_vars.feedkeys_calls, [a:string, a:mode])
endfunction 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: After:
Restore Restore
@ -22,6 +37,13 @@ After:
unlet! b:ale_completion_info unlet! b:ale_completion_info
unlet! b:ale_completion_response unlet! b:ale_completion_response
unlet! b:ale_completion_parser 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/completion.vim
runtime autoload/ale/lsp.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 \ b:ale_completion_info
Execute(ale#completion#GetCompletions should be called when the cursor position stays the same): Execute(ale#completion#GetCompletions should be called when the cursor position stays the same):
let g:test_vars.get_completions_called = 0 call CheckCompletionCalled(1)
" 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
Execute(ale#completion#GetCompletions should not be called when the cursor position changes): Execute(ale#completion#GetCompletions should not be called when the cursor position changes):
call setpos('.', [bufnr(''), 1, 2, 0]) call setpos('.', [bufnr(''), 1, 2, 0])
@ -326,3 +337,8 @@ Execute(ale#completion#GetCompletions should not be called when the cursor posit
sleep 1m sleep 1m
Assert !g:test_vars.get_completions_called 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)

View file

@ -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): Execute (ALE should pass on a single long line):
let g:last_line = ale#job#JoinNeovimOutput(1, '', ['x'], 'raw', function('RawCallback')) let g:last_line = ale#job#JoinNeovimOutput(1, '', ['x'], 'raw', function('RawCallback'))
AssertEqual '', g:data AssertEqual 'x', g:data
AssertEqual 'x', g:last_line AssertEqual '', g:last_line
Execute (ALE should handle just a single line of output): Execute (ALE should handle just a single line of output):
let g:last_line = ale#job#JoinNeovimOutput(1, '', ['x', ''], 'raw', function('RawCallback')) 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 "x\n", g:data
AssertEqual '', g:last_line AssertEqual '', g:last_line
Execute (ALE should join two incomplete pieces of large lines together): Execute (ALE should pass on two lines and one incomplete one):
let g:last_line = ale#job#JoinNeovimOutput(1, 'x', ['y'], 'raw', function('RawCallback')) let g:last_line = ale#job#JoinNeovimOutput(1, '', ['y', 'z', 'a'], 'raw', function('RawCallback'))
AssertEqual '', g:data AssertEqual "y\nz\na", g:data
AssertEqual 'xy', g:last_line AssertEqual '', 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

View file

@ -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 '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') 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): Execute(ale#path#ToURI should work for Unix paths):
AssertEqual 'file:///foo/bar/baz.tst', ale#path#ToURI('/foo/bar/baz.tst') 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') AssertEqual 'foo/bar/baz.tst', ale#path#ToURI('foo/bar/baz.tst')

View file

@ -81,3 +81,23 @@ Execute(The ksh dialect should be used for shellcheck if b:is_kornshell is 1):
let b:is_kornshell = 1 let b:is_kornshell = 1
AssertEqual 'ksh', ale_linters#sh#shellcheck#GetDialectArgument(bufnr('')) AssertEqual 'ksh', ale_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(''))

View file

@ -1,6 +1,8 @@
Before: Before:
Save &l:statusline Save &l:statusline
call ale#test#SetDirectory('/testplugin/test')
let b:funky_command_created = 0 let b:funky_command_created = 0
" We will test for the existence of this command, so create one if needed. " We will test for the existence of this command, so create one if needed.
@ -10,6 +12,8 @@ Before:
endif endif
After: After:
call ale#test#RestoreDirectory()
if b:funky_command_created if b:funky_command_created
delcommand CtrlPFunky delcommand CtrlPFunky
let b:funky_command_created = 0 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 %* <mru>={%#CtrlPMode1# funky %*}=<fil> <-> %=%<%#CtrlPMode2# %{getcwd()} %*' let &l:statusline = '%#CtrlPMode2# prt %*%#CtrlPMode1# line %* <mru>={%#CtrlPMode1# funky %*}=<fil> <-> %=%<%#CtrlPMode2# %{getcwd()} %*'
Assert ale#ShouldDoNothing(bufnr('')) 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(''))