summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md84
-rw-r--r--after/plugin/ale.vim37
-rw-r--r--ale_linters/d/dmd.vim2
-rw-r--r--ale_linters/elm/make.vim170
-rw-r--r--ale_linters/html/tidy.vim8
-rw-r--r--ale_linters/perl/perlcritic.vim19
-rw-r--r--ale_linters/php/phan.vim63
-rw-r--r--ale_linters/python/flake8.vim23
-rw-r--r--ale_linters/sass/sasslint.vim5
-rw-r--r--ale_linters/scss/sasslint.vim14
-rw-r--r--autoload/ale.vim31
-rw-r--r--autoload/ale/completion.vim36
-rw-r--r--autoload/ale/cursor.vim5
-rw-r--r--autoload/ale/debugging.vim25
-rw-r--r--autoload/ale/definition.vim2
-rw-r--r--autoload/ale/engine.vim45
-rw-r--r--autoload/ale/fix/registry.vim2
-rw-r--r--autoload/ale/handlers/sasslint.vim8
-rw-r--r--autoload/ale/history.vim3
-rw-r--r--autoload/ale/job.vim3
-rw-r--r--autoload/ale/linter.vim3
-rw-r--r--autoload/ale/list.vim13
-rw-r--r--autoload/ale/lsp.vim5
-rw-r--r--autoload/ale/lsp/response.vim42
-rw-r--r--autoload/ale/pattern_options.vim8
-rw-r--r--autoload/ale/python.vim1
-rw-r--r--autoload/ale/sign.vim19
-rw-r--r--autoload/ale/statusline.vim10
-rw-r--r--autoload/ale/toggle.vim7
-rw-r--r--doc/ale-elm.txt2
-rw-r--r--doc/ale-gitcommit.txt10
-rw-r--r--doc/ale-php.txt18
-rw-r--r--doc/ale-python.txt41
-rw-r--r--doc/ale.txt71
-rw-r--r--plugin/ale.vim108
-rw-r--r--test/command_callback/test_flake8_command_callback.vader32
-rw-r--r--test/command_callback/test_perlcritic_command_callback.vader16
-rw-r--r--test/command_callback/test_sasslint_command_callback.vader12
-rw-r--r--test/completion/test_completion_prefixes.vader9
-rw-r--r--test/completion/test_lsp_completion_messages.vader7
-rw-r--r--test/completion/test_lsp_completion_parsing.vader39
-rw-r--r--test/completion/test_tsserver_completion_parsing.vader74
-rw-r--r--test/elm-test-files/app/node_modules/.bin/elm (renamed from test/elm-test-files/app/node_modules/.bin/elm-make)0
-rw-r--r--test/fix/test_ale_fix_completion_filter.vader14
-rw-r--r--test/handler/test_elmmake_handler.vader246
-rw-r--r--test/lsp/test_lsp_error_parsing.vader65
-rw-r--r--test/sign/test_sign_placement.vader2
-rw-r--r--test/test_ale_info.vader61
-rw-r--r--test/test_alelint_autocmd.vader1
-rw-r--r--test/test_conflicting_plugin_warnings.vader74
-rw-r--r--test/test_elm_executable_detection.vader8
-rw-r--r--test/test_engine_lsp_response_handling.vader23
-rw-r--r--test/test_go_to_definition.vader13
-rw-r--r--test/test_lint_error_delay.vader3
-rw-r--r--test/test_pattern_options.vader11
-rw-r--r--test/test_should_do_nothing_conditions.vader11
-rw-r--r--test/test_temporary_file_management.vader19
-rw-r--r--test/test_verilog_verilator_options.vader1
58 files changed, 1284 insertions, 400 deletions
diff --git a/README.md b/README.md
index 0c3aba77..54fdc2b2 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@
![ALE Logo by Mark Grealish - https://www.bhalash.com/](img/logo.jpg?raw=true)
ALE (Asynchronous Lint Engine) is a plugin for providing linting in NeoVim
-and Vim 8 while you edit your text files.
+0.2.0+ and Vim 8 while you edit your text files.
![linting example](img/example.gif?raw=true)
@@ -210,24 +210,42 @@ ale-linter-options` for options specified to particular linters.
### 2.ii Fixing
ALE can fix files with the `ALEFix` command. Functions need to be configured
-for different filetypes with the `g:ale_fixers` variable. For example, the
-following code can be used to fix JavaScript code with ESLint:
+either in each buffer with a `b:ale_fixers`, or globally with `g:ale_fixers`.
+
+The recommended way to configure fixers is to define a List in an ftplugin file.
```vim
-" Put this in vimrc or a plugin file of your own.
-" After this is configured, :ALEFix will try and fix your JS code with ESLint.
+" In ~/.vim/ftplugin/javascript.vim, or somewhere similar.
+
+" Fix files with prettier, and then ESLint.
+let b:ale_fixers = ['prettier', 'eslint']
+" Equivalent to the above.
+let b:ale_fixers = {'javascript': ['prettier', 'eslint']}
+```
+
+You can also configure your fixers from vimrc using `g:ale_fixers`, before
+or after ALE has been loaded.
+
+```vim
+" In ~/.vim/vimrc, or somewhere similar.
let g:ale_fixers = {
\ 'javascript': ['eslint'],
\}
+```
-" Set this setting in vimrc if you want to fix files automatically on save.
-" This is off by default.
+If you want to automatically fix files when you save them, you need to turn
+a setting on in vimrc.
+
+```vim
+" Set this variable to 1 to fix files when you save them.
let g:ale_fix_on_save = 1
```
-The `:ALEFixSuggest` command will suggest some supported tools for fixing code,
-but fixers can be also implemented with functions, including lambda functions
-too. See `:help ale-fix` for detailed information.
+The `:ALEFixSuggest` command will suggest some supported tools for fixing code.
+Both `g:ale_fixers` and `b:ale_fixers` can also accept functions, including
+lambda functions, as fixers, for fixing files with custom tools.
+
+See `:help ale-fix` for complete information on how to fix files with ALE.
<a name="usage-completion"></a>
@@ -272,6 +290,9 @@ ALE supports "hover" information for printing brief information about symbols at
the cursor taken from Language Server Protocol linters and `tsserver` with the
`ALEHover` command.
+On vim/gvim with `balloon` support you can see the information in a tooltip
+that appears under the mouse when you mouseover a symbol.
+
See `:help ale-hover` for more information.
<a name="installation"></a>
@@ -382,12 +403,28 @@ on Freenode. Web chat is available [here](https://webchat.freenode.net/?channels
### 5.i. How do I disable particular linters?
-By default, all available tools for all supported languages will be run.
-If you want to only select a subset of the tools, simply create a
-`g:ale_linters` dictionary in your vimrc file mapping filetypes
-to lists of linters to run.
+By default, all available tools for all supported languages will be run. If you
+want to only select a subset of the tools, you can define `b:ale_linters` for a
+single buffer, or `g:ale_linters` globally.
+
+The recommended way to configure linters is to define a List in an ftplugin
+file.
+
+```vim
+" In ~/.vim/ftplugin/javascript.vim, or somewhere similar.
+
+" Enable ESLint only for JavaScript.
+let b:ale_linters = ['eslint']
+
+" Equivalent to the above.
+let b:ale_linters = {'javascript': ['eslint']}
+```
+
+You can also declare which linters you want to run in your vimrc file, before or
+after ALE has been loaded.
```vim
+" In ~/.vim/vimrc, or somewhere similar.
let g:ale_linters = {
\ 'javascript': ['eslint'],
\}
@@ -398,6 +435,14 @@ be run for those languages, just as when the dictionary is not defined.
Running many linters should not typically obstruct editing in Vim,
as they will all be executed in separate processes simultaneously.
+If you don't want ALE to run anything other than what you've explicitly asked
+for, you can set `g:ale_linters_explicit` to `1`.
+
+```vim
+" Only run linters named in ale_linters settings.
+let g:ale_linters_explicit = 1
+```
+
This plugin will look for linters in the [`ale_linters`](ale_linters) directory.
Each directory within corresponds to a particular filetype in Vim, and each file
in each directory corresponds to the name of a particular linter.
@@ -647,9 +692,18 @@ augroup END
```
Supposing the filetype has been set correctly, you can set the following
-options in your vimrc file:
+options in a jsx.vim ftplugin file.
+
+```vim
+" In ~/.vim/ftplugin/jsx.vim, or somewhere similar.
+let b:ale_linters = ['stylelint', 'eslint']
+let b:ale_linter_aliases = ['css']
+```
+
+Or if you want, you can configure the linters from your vimrc file.
```vim
+" In ~/.vim/vimrc, or somewhere similar.
let g:ale_linters = {'jsx': ['stylelint', 'eslint']}
let g:ale_linter_aliases = {'jsx': 'css'}
```
diff --git a/after/plugin/ale.vim b/after/plugin/ale.vim
deleted file mode 100644
index d738dbdd..00000000
--- a/after/plugin/ale.vim
+++ /dev/null
@@ -1,37 +0,0 @@
-" Author: w0rp <devw0rp@gmail.com>
-" Description: Follow-up checks for the plugin: warn about conflicting plugins.
-
-" A flag for ensuring that this is not run more than one time.
-if exists('g:loaded_ale_after')
- finish
-endif
-
-" Set the flag so this file is not run more than one time.
-let g:loaded_ale_after = 1
-
-" Check if the flag is available and set to 0 to disable checking for and
-" emitting conflicting plugin warnings.
-if exists('g:ale_emit_conflict_warnings') && !g:ale_emit_conflict_warnings
- finish
-endif
-
-" Conflicting Plugins Checks
-
-function! s:GetConflictingPluginWarning(plugin_name) abort
- return 'ALE conflicts with ' . a:plugin_name
- \ . '. Uninstall it, or disable this warning with '
- \ . '`let g:ale_emit_conflict_warnings = 0` in your vimrc file, '
- \ . '*before* plugins are loaded.'
-endfunction
-
-if exists('g:loaded_syntastic_plugin')
- throw s:GetConflictingPluginWarning('Syntastic')
-endif
-
-if exists('g:loaded_neomake')
- throw s:GetConflictingPluginWarning('Neomake')
-endif
-
-if exists('g:loaded_validator_plugin')
- throw s:GetConflictingPluginWarning('Validator')
-endif
diff --git a/ale_linters/d/dmd.vim b/ale_linters/d/dmd.vim
index b91238ae..d64b6c3d 100644
--- a/ale_linters/d/dmd.vim
+++ b/ale_linters/d/dmd.vim
@@ -46,7 +46,7 @@ function! ale_linters#d#dmd#DMDCommand(buffer, dub_output) abort
endif
endfor
- return 'dmd '. join(l:import_list) . ' -o- -vcolumns -c %t'
+ return 'dmd '. join(l:import_list) . ' -o- -wi -vcolumns -c %t'
endfunction
function! ale_linters#d#dmd#Handle(buffer, lines) abort
diff --git a/ale_linters/elm/make.vim b/ale_linters/elm/make.vim
index a665cef4..cc14fe4e 100644
--- a/ale_linters/elm/make.vim
+++ b/ale_linters/elm/make.vim
@@ -1,45 +1,26 @@
-" Author: buffalocoder - https://github.com/buffalocoder, soywod - https://github.com/soywod
+" Author: buffalocoder - https://github.com/buffalocoder, soywod - https://github.com/soywod, hecrj - https://github.com/hecrj
" Description: Elm linting in Ale. Closely follows the Syntastic checker in https://github.com/ElmCast/elm-vim.
-call ale#Set('elm_make_executable', 'elm-make')
+call ale#Set('elm_make_executable', 'elm')
call ale#Set('elm_make_use_global', get(g:, 'ale_use_global_executables', 0))
function! ale_linters#elm#make#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'elm_make', [
- \ 'node_modules/.bin/elm-make',
+ \ 'node_modules/.bin/elm',
\])
endfunction
function! ale_linters#elm#make#Handle(buffer, lines) abort
let l:output = []
- let l:is_windows = has('win32')
- let l:temp_dir = l:is_windows ? $TMP : $TMPDIR
let l:unparsed_lines = []
- for l:line in a:lines
- if l:line[0] is# '['
- let l:errors = json_decode(l:line)
-
- for l:error in l:errors
- " Check if file is from the temp directory.
- " Filters out any errors not related to the buffer.
- if l:is_windows
- let l:file_is_buffer = l:error.file[0:len(l:temp_dir) - 1] is? l:temp_dir
- else
- let l:file_is_buffer = l:error.file[0:len(l:temp_dir) - 1] is# l:temp_dir
- endif
- if l:file_is_buffer
- call add(l:output, {
- \ 'lnum': l:error.region.start.line,
- \ 'col': l:error.region.start.column,
- \ 'end_lnum': l:error.region.end.line,
- \ 'end_col': l:error.region.end.column,
- \ 'type': (l:error.type is? 'error') ? 'E' : 'W',
- \ 'text': l:error.overview,
- \ 'detail': l:error.overview . "\n\n" . l:error.details
- \})
- endif
- endfor
+ for l:line in a:lines
+ if l:line[0] is# '{'
+ " Elm 0.19
+ call ale_linters#elm#make#HandleElm019Line(l:line, l:output)
+ elseif l:line[0] is# '['
+ " Elm 0.18
+ call ale_linters#elm#make#HandleElm018Line(l:line, l:output)
elseif l:line isnot# 'Successfully generated /dev/null'
call add(l:unparsed_lines, l:line)
endif
@@ -57,23 +38,142 @@ function! ale_linters#elm#make#Handle(buffer, lines) abort
return l:output
endfunction
+function! ale_linters#elm#make#HandleElm019Line(line, output) abort
+ let l:report = json_decode(a:line)
+
+ if l:report.type is? 'error'
+ " General problem
+ let l:details = ale_linters#elm#make#ParseMessage(l:report.message)
+
+ if empty(l:report.path)
+ let l:report.path = 'Elm'
+ endif
+
+ if ale_linters#elm#make#FileIsBuffer(l:report.path)
+ call add(a:output, {
+ \ 'lnum': 1,
+ \ 'type': 'E',
+ \ 'text': l:details,
+ \})
+ else
+ call add(a:output, {
+ \ 'lnum': 1,
+ \ 'type': 'E',
+ \ 'text': l:report.path .' - '. l:details,
+ \ 'detail': l:report.path ." ----------\n\n". l:details,
+ \})
+ endif
+ else
+ " Compilation errors
+ for l:error in l:report.errors
+ let l:file_is_buffer = ale_linters#elm#make#FileIsBuffer(l:error.path)
+
+ for l:problem in l:error.problems
+ let l:details = ale_linters#elm#make#ParseMessage(l:problem.message)
+
+ if l:file_is_buffer
+ " Buffer module has problems
+ call add(a:output, {
+ \ 'lnum': l:problem.region.start.line,
+ \ 'col': l:problem.region.start.column,
+ \ 'end_lnum': l:problem.region.end.line,
+ \ 'end_col': l:problem.region.end.column,
+ \ 'type': 'E',
+ \ 'text': l:details,
+ \})
+ else
+ " Imported module has problems
+ let l:location = l:error.path .':'. l:problem.region.start.line
+ call add(a:output, {
+ \ 'lnum': 1,
+ \ 'type': 'E',
+ \ 'text': l:location .' - '. l:details,
+ \ 'detail': l:location ." ----------\n\n". l:details,
+ \})
+ endif
+ endfor
+ endfor
+ endif
+endfunction
+
+function! ale_linters#elm#make#HandleElm018Line(line, output) abort
+ let l:errors = json_decode(a:line)
+
+ for l:error in l:errors
+ let l:file_is_buffer = ale_linters#elm#make#FileIsBuffer(l:error.file)
+
+ if l:file_is_buffer
+ " Current buffer has problems
+ call add(a:output, {
+ \ 'lnum': l:error.region.start.line,
+ \ 'col': l:error.region.start.column,
+ \ 'end_lnum': l:error.region.end.line,
+ \ 'end_col': l:error.region.end.column,
+ \ 'type': (l:error.type is? 'error') ? 'E' : 'W',
+ \ 'text': l:error.overview,
+ \ 'detail': l:error.overview . "\n\n" . l:error.details
+ \})
+ elseif l:error.type is? 'error'
+ " Imported module has errors
+ let l:location = l:error.file .':'. l:error.region.start.line
+
+ call add(a:output, {
+ \ 'lnum': 1,
+ \ 'type': 'E',
+ \ 'text': l:location .' - '. l:error.overview,
+ \ 'detail': l:location ." ----------\n\n". l:error.overview . "\n\n" . l:error.details
+ \})
+ endif
+ endfor
+endfunction
+
+function! ale_linters#elm#make#FileIsBuffer(path) abort
+ let l:is_windows = has('win32')
+ let l:temp_dir = l:is_windows ? $TMP : $TMPDIR
+
+ if has('win32')
+ return a:path[0:len(l:temp_dir) - 1] is? l:temp_dir
+ else
+ return a:path[0:len(l:temp_dir) - 1] is# l:temp_dir
+ endif
+endfunction
+
+function! ale_linters#elm#make#ParseMessage(message) abort
+ return join(map(copy(a:message), 'ale_linters#elm#make#ParseMessageItem(v:val)'), '')
+endfunction
+
+function! ale_linters#elm#make#ParseMessageItem(item) abort
+ if type(a:item) == type('')
+ return a:item
+ else
+ return a:item.string
+ endif
+endfunction
+
" Return the command to execute the linter in the projects directory.
" If it doesn't, then this will fail when imports are needed.
function! ale_linters#elm#make#GetCommand(buffer) abort
- let l:elm_package = ale#path#FindNearestFile(a:buffer, 'elm-package.json')
+ let l:elm_json = ale#path#FindNearestFile(a:buffer, 'elm.json')
let l:elm_exe = ale_linters#elm#make#GetExecutable(a:buffer)
- if empty(l:elm_package)
+
+ if empty(l:elm_json)
+ " Fallback to Elm 0.18
+ let l:elm_json = ale#path#FindNearestFile(a:buffer, 'elm-package.json')
+ endif
+
+ if empty(l:elm_json)
let l:dir_set_cmd = ''
else
- let l:root_dir = fnamemodify(l:elm_package, ':p:h')
+ let l:root_dir = fnamemodify(l:elm_json, ':p:h')
let l:dir_set_cmd = 'cd ' . ale#Escape(l:root_dir) . ' && '
endif
- " The elm-make compiler, at the time of this writing, uses '/dev/null' as
+ " The elm compiler, at the time of this writing, uses '/dev/null' as
" a sort of flag to tell the compiler not to generate an output file,
- " which is why this is hard coded here. It does not use NUL on Windows.
- " Source: https://github.com/elm-lang/elm-make/blob/master/src/Flags.hs
+ " which is why this is hard coded here.
+ " Source: https://github.com/elm-lang/elm-compiler/blob/19d5a769b30ec0b2fc4475985abb4cd94cd1d6c3/builder/src/Generate/Output.hs#L253
let l:elm_cmd = ale#Escape(l:elm_exe)
+ \ . ' make'
\ . ' --report=json'
\ . ' --output=/dev/null'
diff --git a/ale_linters/html/tidy.vim b/ale_linters/html/tidy.vim
index 34152c6b..3af64d74 100644
--- a/ale_linters/html/tidy.vim
+++ b/ale_linters/html/tidy.vim
@@ -3,11 +3,19 @@
" CLI options
let g:ale_html_tidy_executable = get(g:, 'ale_html_tidy_executable', 'tidy')
+" remove in 2.0
" Look for the old _args variable first.
+let s:deprecation_warning_echoed = 0
let s:default_options = get(g:, 'ale_html_tidy_args', '-q -e -language en')
let g:ale_html_tidy_options = get(g:, 'ale_html_tidy_options', s:default_options)
function! ale_linters#html#tidy#GetCommand(buffer) abort
+ " remove in 2.0
+ if exists('g:ale_html_tidy_args') && !s:deprecation_warning_echoed
+ execute 'echom ''Rename your g:ale_html_tidy_args setting to g:ale_html_tidy_options instead. Support for this will removed in ALE 2.0.'''
+ let s:deprecation_warning_echoed = 1
+ endif
+
" Specify file encoding in options
" (Idea taken from https://github.com/scrooloose/syntastic/blob/master/syntax_checkers/html/tidy.vim)
let l:file_encoding = get({
diff --git a/ale_linters/perl/perlcritic.vim b/ale_linters/perl/perlcritic.vim
index 24f7eb86..e91c8a03 100644
--- a/ale_linters/perl/perlcritic.vim
+++ b/ale_linters/perl/perlcritic.vim
@@ -18,9 +18,9 @@ function! ale_linters#perl#perlcritic#GetExecutable(buffer) abort
endfunction
function! ale_linters#perl#perlcritic#GetProfile(buffer) abort
-
" first see if we've been overridden
let l:profile = ale#Var(a:buffer, 'perl_perlcritic_profile')
+
if l:profile is? ''
return ''
endif
@@ -31,6 +31,7 @@ endfunction
function! ale_linters#perl#perlcritic#GetCommand(buffer) abort
let l:critic_verbosity = '%l:%c %m\n'
+
if ale#Var(a:buffer, 'perl_perlcritic_showrules')
let l:critic_verbosity = '%l:%c %m [%p]\n'
endif
@@ -38,17 +39,11 @@ function! ale_linters#perl#perlcritic#GetCommand(buffer) abort
let l:profile = ale_linters#perl#perlcritic#GetProfile(a:buffer)
let l:options = ale#Var(a:buffer, 'perl_perlcritic_options')
- let l:command = ale#Escape(ale_linters#perl#perlcritic#GetExecutable(a:buffer))
- \ . " --verbose '". l:critic_verbosity . "' --nocolor"
-
- if l:profile isnot? ''
- let l:command .= ' --profile ' . ale#Escape(l:profile)
- endif
- if l:options isnot? ''
- let l:command .= ' ' . l:options
- endif
-
- return l:command
+ return ale#Escape(ale_linters#perl#perlcritic#GetExecutable(a:buffer))
+ \ . ' --verbose ' . ale#Escape(l:critic_verbosity)
+ \ . ' --nocolor'
+ \ . (!empty(l:profile) ? ' --profile ' . ale#Escape(l:profile) : '')
+ \ . (!empty(l:options) ? ' ' . l:options : '')
endfunction
diff --git a/ale_linters/php/phan.vim b/ale_linters/php/phan.vim
index f3b3d48f..c6f16356 100644
--- a/ale_linters/php/phan.vim
+++ b/ale_linters/php/phan.vim
@@ -1,28 +1,65 @@
-" Author: diegoholiveira <https://github.com/diegoholiveira>
+" Author: diegoholiveira <https://github.com/diegoholiveira>, haginaga <https://github.com/haginaga>
" Description: static analyzer for PHP
" Define the minimum severity
let g:ale_php_phan_minimum_severity = get(g:, 'ale_php_phan_minimum_severity', 0)
+let g:ale_php_phan_executable = get(g:, 'ale_php_phan_executable', 'phan')
+let g:ale_php_phan_use_client = get(g:, 'ale_php_phan_use_client', 0)
+
+function! ale_linters#php#phan#GetExecutable(buffer) abort
+ let l:executable = ale#Var(a:buffer, 'php_phan_executable')
+
+ if ale#Var(a:buffer, 'php_phan_use_client') == 1 && l:executable is# 'phan'
+ let l:executable = 'phan_client'
+ endif
+
+ return l:executable
+endfunction
+
function! ale_linters#php#phan#GetCommand(buffer) abort
- return 'phan -y '
- \ . ale#Var(a:buffer, 'php_phan_minimum_severity')
- \ . ' %s'
+ if ale#Var(a:buffer, 'php_phan_use_client') == 1
+ let l:args = '-l '
+ \ . ' %s'
+ else
+ let l:args = '-y '
+ \ . ale#Var(a:buffer, 'php_phan_minimum_severity')
+ \ . ' %s'
+ endif
+
+ let l:executable = ale_linters#php#phan#GetExecutable(a:buffer)
+
+ return ale#Escape(l:executable) . ' ' . l:args
endfunction
function! ale_linters#php#phan#Handle(buffer, lines) abort
" Matches against lines like the following:
- "
- " /path/to/some-filename.php:18 ERRORTYPE message
- let l:pattern = '^.*:\(\d\+\)\s\(\w\+\)\s\(.\+\)$'
+ if ale#Var(a:buffer, 'php_phan_use_client') == 1
+ " Phan error: ERRORTYPE: message in /path/to/some-filename.php on line nnn
+ let l:pattern = '^Phan error: \(\w\+\): \(.\+\) in \(.\+\) on line \(\d\+\)$'
+ else
+ " /path/to/some-filename.php:18 ERRORTYPE message
+ let l:pattern = '^.*:\(\d\+\)\s\(\w\+\)\s\(.\+\)$'
+ endif
+
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
- call add(l:output, {
- \ 'lnum': l:match[1] + 0,
- \ 'text': l:match[3],
- \ 'type': 'W',
- \})
+ if ale#Var(a:buffer, 'php_phan_use_client') == 1
+ let l:dict = {
+ \ 'lnum': l:match[4] + 0,
+ \ 'text': l:match[2],
+ \ 'type': 'W',
+ \}
+ else
+ let l:dict = {
+ \ 'lnum': l:match[1] + 0,
+ \ 'text': l:match[3],
+ \ 'type': 'W',
+ \}
+ endif
+
+ call add(l:output, l:dict)
endfor
return l:output
@@ -30,7 +67,7 @@ endfunction
call ale#linter#Define('php', {
\ 'name': 'phan',
-\ 'executable': 'phan',
+\ 'executable_callback': 'ale_linters#php#phan#GetExecutable',
\ 'command_callback': 'ale_linters#php#phan#GetCommand',
\ 'callback': 'ale_linters#php#phan#Handle',
\})
diff --git a/ale_linters/python/flake8.vim b/ale_linters/python/flake8.vim
index 4ed41935..7398b1dc 100644
--- a/ale_linters/python/flake8.vim
+++ b/ale_linters/python/flake8.vim
@@ -1,14 +1,15 @@
" Author: w0rp <devw0rp@gmail.com>
" Description: flake8 for python files
-let g:ale_python_flake8_executable =
-\ get(g:, 'ale_python_flake8_executable', 'flake8')
-
+" remove in 2.0
" Support an old setting as a fallback.
+let s:deprecation_warning_echoed = 0
let s:default_options = get(g:, 'ale_python_flake8_args', '')
-let g:ale_python_flake8_options =
-\ get(g:, 'ale_python_flake8_options', s:default_options)
-let g:ale_python_flake8_use_global = get(g:, 'ale_python_flake8_use_global', get(g:, 'ale_use_global_executables', 0))
+
+call ale#Set('python_flake8_executable', 'flake8')
+call ale#Set('python_flake8_options', s:default_options)
+call ale#Set('python_flake8_use_global', get(g:, 'ale_use_global_executables', 0))
+call ale#Set('python_flake8_change_directory', 1)
function! s:UsingModule(buffer) abort
return ale#Var(a:buffer, 'python_flake8_options') =~# ' *-m flake8'
@@ -39,7 +40,15 @@ function! ale_linters#python#flake8#VersionCheck(buffer) abort
endfunction
function! ale_linters#python#flake8#GetCommand(buffer, version_output) abort
- let l:cd_string = ale#path#BufferCdString(a:buffer)
+ " remove in 2.0
+ if exists('g:ale_python_flake8_args') && !s:deprecation_warning_echoed
+ execute 'echom ''Rename your g:ale_python_flake8_args setting to g:ale_python_flake8_options instead. Support for this will removed in ALE 2.0.'''
+ let s:deprecation_warning_echoed = 1
+ endif
+
+ let l:cd_string = ale#Var(a:buffer, 'python_flake8_change_directory')
+ \ ? ale#path#BufferCdString(a:buffer)
+ \ : ''
let l:executable = ale_linters#python#flake8#GetExecutable(a:buffer)
let l:version = ale#semver#GetVersion(l:executable, a:version_output)
diff --git a/ale_linters/sass/sasslint.vim b/ale_linters/sass/sasslint.vim
index bbe71255..4df56dfd 100644
--- a/ale_linters/sass/sasslint.vim
+++ b/ale_linters/sass/sasslint.vim
@@ -1,8 +1,9 @@
-" Author: KabbAmine - https://github.com/KabbAmine
+" Author: KabbAmine - https://github.com/KabbAmine,
+" Ben Falconer <ben@falconers.me.uk>
call ale#linter#Define('sass', {
\ 'name': 'sasslint',
\ 'executable': 'sass-lint',
-\ 'command': 'sass-lint -v -q -f compact %t',
+\ 'command_callback': 'ale#handlers#sasslint#GetCommand',
\ 'callback': 'ale#handlers#css#HandleCSSLintFormat',
\})
diff --git a/ale_linters/scss/sasslint.vim b/ale_linters/scss/sasslint.vim
index bd016465..f6075001 100644
--- a/ale_linters/scss/sasslint.vim
+++ b/ale_linters/scss/sasslint.vim
@@ -1,8 +1,18 @@
-" Author: KabbAmine - https://github.com/KabbAmine
+" Author: KabbAmine - https://github.com/KabbAmine, Ben Falconer
+" <ben@falconers.me.uk>
+
+function! ale_linters#scss#sasslint#GetCommand(buffer) abort
+ return ale#path#BufferCdString(a:buffer)
+ \ . ale#Escape('sass-lint')
+ \ . ' -v'
+ \ . ' -q'
+ \ . ' -f compact'
+ \ . ' %t'
+endfunction
call ale#linter#Define('scss', {
\ 'name': 'sasslint',
\ 'executable': 'sass-lint',
-\ 'command': 'sass-lint -v -q -f compact %t',
+\ 'command_callback': 'ale_linters#scss#sasslint#GetCommand',
\ 'callback': 'ale#handlers#css#HandleCSSLintFormat',
\})
diff --git a/autoload/ale.vim b/autoload/ale.vim
index 5c4a0f55..f31446cb 100644
--- a/autoload/ale.vim
+++ b/autoload/ale.vim
@@ -2,6 +2,11 @@
" Description: Primary code path for the plugin
" Manages execution of linters when requested by autocommands
+" Strings used for severity in the echoed message
+let g:ale_echo_msg_error_str = get(g:, 'ale_echo_msg_error_str', 'Error')
+let g:ale_echo_msg_info_str = get(g:, 'ale_echo_msg_info_str', 'Info')
+let g:ale_echo_msg_warning_str = get(g:, 'ale_echo_msg_warning_str', 'Warning')
+
let s:lint_timer = -1
let s:queued_buffer_number = -1
let s:should_lint_file_for_buffer = {}
@@ -32,12 +37,8 @@ function! ale#CallWithCooldown(timestamp_key, func, arglist) abort
endfunction
" Return 1 if a file is too large for ALE to handle.
-function! ale#FileTooLarge() abort
- if !exists('g:ale_maximum_file_size')
- return 0
- endif
-
- let l:max = ale#Var(bufnr(''), 'maximum_file_size')
+function! ale#FileTooLarge(buffer) abort
+ let l:max = getbufvar(a:buffer, 'ale_maximum_file_size', get(g:, 'ale_maximum_file_size', 0))
return l:max > 0 ? (line2byte(line('$') + 1) > l:max) : 0
endfunction
@@ -60,29 +61,37 @@ function! ale#ShouldDoNothing(buffer) abort
return 1
endif
- " Do nothing for blacklisted files
- if index(get(g:, 'ale_filetype_blacklist', []), getbufvar(a:buffer, '&filetype')) >= 0
+ let l:filetype = getbufvar(a:buffer, '&filetype')
+
+ " Do nothing when there's no filetype.
+ if l:filetype is# ''
+ return 1
+ endif
+
+ " Do nothing for blacklisted files.
+ if index(get(g:, 'ale_filetype_blacklist', []), l:filetype) >= 0
return 1
endif
- " Do nothing if running from command mode
+ " Do nothing if running from command mode.
if s:getcmdwintype_exists && !empty(getcmdwintype())
return 1
endif
let l:filename = fnamemodify(bufname(a:buffer), ':t')
+ " Do nothing for directories.
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()
return 1
endif
" Do nothing if the file is too large.
- if ale#FileTooLarge()
+ if ale#FileTooLarge(a:buffer)
return 1
endif
diff --git a/autoload/ale/completion.vim b/autoload/ale/completion.vim
index c15a4867..6fa2619b 100644
--- a/autoload/ale/completion.vim
+++ b/autoload/ale/completion.vim
@@ -1,7 +1,9 @@
" Author: w0rp <devw0rp@gmail.com>
" Description: Completion support for LSP linters
-call ale#Set('completion_excluded_words', [])
+let g:ale_completion_delay = get(g:, 'ale_completion_delay', 100)
+let g:ale_completion_excluded_words = get(g:, 'ale_completion_excluded_words', [])
+let g:ale_completion_max_suggestions = get(g:, 'ale_completion_max_suggestions', 50)
let s:timer_id = -1
let s:last_done_pos = []
@@ -30,6 +32,7 @@ let s:LSP_COMPLETION_REFERENCE_KIND = 18
" the insert cursor is. If one of these matches, we'll check for completions.
let s:should_complete_map = {
\ '<default>': '\v[a-zA-Z$_][a-zA-Z$_0-9]*$|\.$',
+\ 'typescript': '\v[a-zA-Z$_][a-zA-Z$_0-9]*$|\.$|''$|"$',
\ 'rust': '\v[a-zA-Z$_][a-zA-Z$_0-9]*$|\.$|::$',
\}
@@ -41,6 +44,7 @@ let s:omni_start_map = {
" A map of exact characters for triggering LSP completions.
let s:trigger_character_map = {
\ '<default>': ['.'],
+\ 'typescript': ['.', '''', '"'],
\ 'rust': ['.', '::'],
\}
@@ -198,7 +202,9 @@ function! ale#completion#ParseTSServerCompletions(response) abort
endfunction
function! ale#completion#ParseTSServerCompletionEntryDetails(response) abort
+ let l:buffer = bufnr('')
let l:results = []
+ let l:names_with_details = []
for l:suggestion in a:response.body
let l:displayParts = []
@@ -232,6 +238,26 @@ function! ale#completion#ParseTSServerCompletionEntryDetails(response) abort
\})
endfor
+ let l:names = getbufvar(l:buffer, 'ale_tsserver_completion_names', [])
+
+ if !empty(l:names) && len(l:names) != len(l:results)
+ let l:names_with_details = map(copy(l:results), 'v:val.word')
+ let l:missing_names = filter(
+ \ copy(l:names),
+ \ 'index(l:names_with_details, v:val) < 0',
+ \)
+
+ for l:name in l:missing_names
+ call add(l:results, {
+ \ 'word': l:name,
+ \ 'kind': 'v',
+ \ 'icase': 1,
+ \ 'menu': '',
+ \ 'info': '',
+ \})
+ endfor
+ endif
+
return l:results
endfunction
@@ -296,6 +322,10 @@ function! ale#completion#ParseLSPCompletions(response) abort
\})
endfor
+ if has_key(l:info, 'prefix')
+ return ale#completion#Filter(l:buffer, l:results, l:info.prefix)
+ endif
+
return l:results
endfunction
@@ -318,6 +348,10 @@ function! ale#completion#HandleTSServerResponse(conn_id, response) abort
\ b:ale_completion_info.prefix,
\)[: g:ale_completion_max_suggestions - 1]
+ " We need to remember some names for tsserver, as it doesn't send
+ " details back for everything we send.
+ call setbufvar(l:buffer, 'ale_tsserver_completion_names', l:names)
+
if !empty(l:names)
let b:ale_completion_info.request_id = ale#lsp#Send(
\ b:ale_completion_info.conn_id,
diff --git a/autoload/ale/cursor.vim b/autoload/ale/cursor.vim
index 50b1fb50..e3dd4208 100644
--- a/autoload/ale/cursor.vim
+++ b/autoload/ale/cursor.vim
@@ -1,6 +1,11 @@
" Author: w0rp <devw0rp@gmail.com>
" Description: Echoes lint message for the current line, if any
+" Controls the milliseconds delay before echoing a message.
+let g:ale_echo_delay = get(g:, 'ale_echo_delay', 10)
+" A string format for the echoed message.
+let g:ale_echo_msg_format = get(g:, 'ale_echo_msg_format', '%code: %%s')
+
let s:cursor_timer = -1
let s:last_pos = [0, 0, 0]
diff --git a/autoload/ale/debugging.vim b/autoload/ale/debugging.vim
index bec79a85..f32e4308 100644
--- a/autoload/ale/debugging.vim
+++ b/autoload/ale/debugging.vim
@@ -168,6 +168,30 @@ function! s:EchoLinterAliases(all_linters) abort
endfor
endfunction
+function! s:EchoLSPErrorMessages(all_linter_names) abort
+ let l:lsp_error_messages = get(g:, 'ale_lsp_error_messages', {})
+ let l:header_echoed = 0
+
+ for l:linter_name in a:all_linter_names
+ let l:error_list = get(l:lsp_error_messages, l:linter_name, [])
+
+ if !empty(l:error_list)
+ if !l:header_echoed
+ call s:Echo(' LSP Error Messages:')
+ call s:Echo('')
+ endif
+
+ call s:Echo('(Errors for ' . l:linter_name . ')')
+
+ for l:message in l:error_list
+ for l:line in split(l:message, "\n")
+ call s:Echo(l:line)
+ endfor
+ endfor
+ endif
+ endfor
+endfunction
+
function! ale#debugging#Info() abort
let l:filetype = &filetype
@@ -200,6 +224,7 @@ function! ale#debugging#Info() abort
call s:Echo(' Global Variables:')
call s:Echo('')
call s:EchoGlobalVariables()
+ call s:EchoLSPErrorMessages(l:all_names)
call s:Echo(' Command History:')
call s:Echo('')
call s:EchoCommandHistory()
diff --git a/autoload/ale/definition.vim b/autoload/ale/definition.vim
index a3bfcd17..a17eb2e7 100644
--- a/autoload/ale/definition.vim
+++ b/autoload/ale/definition.vim
@@ -22,7 +22,7 @@ function! ale#definition#HandleTSServerResponse(conn_id, response) abort
\&& has_key(s:go_to_definition_map, a:response.request_seq)
let l:options = remove(s:go_to_definition_map, a:response.request_seq)
- if get(a:response, 'success', v:false) is v:true
+ if get(a:response, 'success', v:false) is v:true && !empty(a:response.body)
let l:filename = a:response.body[0].file
let l:line = a:response.body[0].start.line
let l:column = a:response.body[0].start.offset
diff --git a/autoload/ale/engine.vim b/autoload/ale/engine.vim
index e1c41552..10589869 100644
--- a/autoload/ale/engine.vim
+++ b/autoload/ale/engine.vim
@@ -2,6 +2,9 @@
" Description: Backend execution and job management
" Executes linters in the background, using NeoVim or Vim 8 jobs
+" 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.
@@ -44,7 +47,7 @@ function! ale#engine#IsExecutable(buffer, executable) abort
" Cache the executable check if we found it, or if the option to cache
" failing checks is on.
- if l:result || g:ale_cache_executable_check_failures
+ if l:result || get(g:, 'ale_cache_executable_check_failures', 0)
let s:executable_cache_map[a:executable] = l:result
endif
@@ -81,6 +84,11 @@ function! ale#engine#ClearLSPData() abort
let s:lsp_linter_map = {}
endfunction
+" Just for tests.
+function! ale#engine#SetLSPLinterMap(replacement_map) abort
+ let s:lsp_linter_map = a:replacement_map
+endfunction
+
" This function is documented and part of the public API.
"
" Return 1 if ALE is busy checking a given buffer
@@ -93,11 +101,13 @@ endfunction
" Register a temporary file to be managed with the ALE engine for
" a current job run.
function! ale#engine#ManageFile(buffer, filename) abort
+ call ale#engine#InitBufferInfo(a:buffer)
call add(g:ale_buffer_info[a:buffer].temporary_file_list, a:filename)
endfunction
" Same as the above, but manage an entire directory.
function! ale#engine#ManageDirectory(buffer, directory) abort
+ call ale#engine#InitBufferInfo(a:buffer)
call add(g:ale_buffer_info[a:buffer].temporary_directory_list, a:directory)
endfunction
@@ -270,20 +280,38 @@ function! s:HandleTSServerDiagnostics(response, error_type) abort
call ale#engine#HandleLoclist('tsserver', l:buffer, l:loclist)
endfunction
-function! s:HandleLSPErrorMessage(error_message) abort
- execute 'echoerr ''Error from LSP:'''
+function! s:HandleLSPErrorMessage(linter_name, response) abort
+ if !g:ale_history_enabled || !g:ale_history_log_output
+ return
+ endif
- for l:line in split(a:error_message, "\n")
- execute 'echoerr l:line'
- endfor
+ if empty(a:linter_name)
+ return
+ endif
+
+ let l:message = ale#lsp#response#GetErrorMessage(a:response)
+
+ if empty(l:message)
+ return
+ endif
+
+ " This global variable is set here so we don't load the debugging.vim file
+ " until someone uses :ALEInfo.
+ let g:ale_lsp_error_messages = get(g:, 'ale_lsp_error_messages', {})
+
+ if !has_key(g:ale_lsp_error_messages, a:linter_name)
+ let g:ale_lsp_error_messages[a:linter_name] = []
+ endif
+
+ call add(g:ale_lsp_error_messages[a:linter_name], l:message)
endfunction
function! ale#engine#HandleLSPResponse(conn_id, response) abort
let l:method = get(a:response, 'method', '')
+ let l:linter_name = get(s:lsp_linter_map, a:conn_id, '')
if get(a:response, 'jsonrpc', '') is# '2.0' && has_key(a:response, 'error')
- " Uncomment this line to print LSP error messages.
- " call s:HandleLSPErrorMessage(a:response.error.message)
+ call s:HandleLSPErrorMessage(l:linter_name, a:response)
elseif l:method is# 'textDocument/publishDiagnostics'
call s:HandleLSPDiagnostics(a:conn_id, a:response)
elseif get(a:response, 'type', '') is# 'event'
@@ -339,6 +367,7 @@ function! ale#engine#SetResults(buffer, loclist) abort
" Call user autocommands. This allows users to hook into ALE's lint cycle.
silent doautocmd <nomodeline> User ALELintPost
+ " remove in 2.0
" Old DEPRECATED name; call it for backwards compatibility.
silent doautocmd <nomodeline> User ALELint
endif
diff --git a/autoload/ale/fix/registry.vim b/autoload/ale/fix/registry.vim
index 7b5fdb8e..17532b3b 100644
--- a/autoload/ale/fix/registry.vim
+++ b/autoload/ale/fix/registry.vim
@@ -332,7 +332,7 @@ endfunction
" Function that returns autocomplete candidates for ALEFix command
function! ale#fix#registry#CompleteFixers(ArgLead, CmdLine, CursorPos) abort
- return ale#fix#registry#GetApplicableFixers(&filetype)
+ return filter(ale#fix#registry#GetApplicableFixers(&filetype), 'v:val =~? a:ArgLead')
endfunction
" Suggest functions to use from the registry.
diff --git a/autoload/ale/handlers/sasslint.vim b/autoload/ale/handlers/sasslint.vim
new file mode 100644
index 00000000..399bf47c
--- /dev/null
+++ b/autoload/ale/handlers/sasslint.vim
@@ -0,0 +1,8 @@
+" Author: KabbAmine - https://github.com/KabbAmine,
+" Ben Falconer <ben@falconers.me.uk>
+
+function! ale#handlers#sasslint#GetCommand(buffer) abort
+ return ale#path#BufferCdString(a:buffer)
+ \ . ale#Escape('sass-lint')
+ \ . ' -v -q -f compact %t'
+endfunction
diff --git a/autoload/ale/history.vim b/autoload/ale/history.vim
index a6282ea5..27ae74c2 100644
--- a/autoload/ale/history.vim
+++ b/autoload/ale/history.vim
@@ -1,6 +1,9 @@
" Author: w0rp <devw0rp@gmail.com>
" Description: Tools for managing command history
+" A flag for controlling the maximum size of the command history to store.
+let g:ale_max_buffer_history_size = get(g:, 'ale_max_buffer_history_size', 20)
+
" Return a shallow copy of the command history for a given buffer number.
function! ale#history#Get(buffer) abort
return copy(getbufvar(a:buffer, 'ale_history', []))
diff --git a/autoload/ale/job.vim b/autoload/ale/job.vim
index 33040bbf..6ffc2a06 100644
--- a/autoload/ale/job.vim
+++ b/autoload/ale/job.vim
@@ -8,6 +8,9 @@
" ale#job#IsRunning(job_id) -> 1 if running, 0 otherwise.
" ale#job#Stop(job_id)
+" A setting for wrapping commands.
+let g:ale_command_wrapper = get(g:, 'ale_command_wrapper', '')
+
if !has_key(s:, 'job_map')
let s:job_map = {}
endif
diff --git a/autoload/ale/linter.vim b/autoload/ale/linter.vim
index 1e0ec304..c791ba46 100644
--- a/autoload/ale/linter.vim
+++ b/autoload/ale/linter.vim
@@ -8,11 +8,14 @@ let s:linters = {}
" Default filetype aliases.
" The user defined aliases will be merged with this Dictionary.
+"
+" NOTE: Update the g:ale_linter_aliases documentation when modifying this.
let s:default_ale_linter_aliases = {
\ 'Dockerfile': 'dockerfile',
\ 'csh': 'sh',
\ 'plaintex': 'tex',
\ 'systemverilog': 'verilog',
+\ 'vimwiki': 'markdown',
\ 'zsh': 'sh',
\}
diff --git a/autoload/ale/list.vim b/autoload/ale/list.vim
index 30b8f5cf..35304a09 100644
--- a/autoload/ale/list.vim
+++ b/autoload/ale/list.vim
@@ -1,6 +1,19 @@
" Author: Bjorn Neergaard <bjorn@neersighted.com>, modified by Yann fery <yann@fery.me>
" Description: Manages the loclist and quickfix lists
+" This flag dictates if ale open the configured loclist
+let g:ale_open_list = get(g:, 'ale_open_list', 0)
+" This flag dictates if ale keeps open loclist even if there is no error in loclist
+let g:ale_keep_list_window_open = get(g:, 'ale_keep_list_window_open', 0)
+" This flag dictates that quickfix windows should be opened vertically
+let g:ale_list_vertical = get(g:, 'ale_list_vertical', 0)
+" The window size to set for the quickfix and loclist windows
+let g:ale_list_window_size = get(g:, 'ale_list_window_size', 10)
+" A string format for the loclist messages.
+let g:ale_loclist_msg_format = get(g:, 'ale_loclist_msg_format',
+\ get(g:, 'ale_echo_msg_format', '%code: %%s')
+\)
+
if !exists('s:timer_args')
let s:timer_args = {}
endif
diff --git a/autoload/ale/lsp.vim b/autoload/ale/lsp.vim
index 8db9348f..c1d04dbf 100644
--- a/autoload/ale/lsp.vim
+++ b/autoload/ale/lsp.vim
@@ -207,6 +207,11 @@ function! ale#lsp#HandleOtherInitializeResponses(conn, response) abort
endfunction
function! ale#lsp#HandleMessage(conn, message) abort
+ if type(a:message) != type('')
+ " Ignore messages that aren't strings.
+ return
+ endif
+
let a:conn.data .= a:message
" Parse the objects now if we can, and keep the remaining text.
diff --git a/autoload/ale/lsp/response.vim b/autoload/ale/lsp/response.vim
index 5a431287..94794e98 100644
--- a/autoload/ale/lsp/response.vim
+++ b/autoload/ale/lsp/response.vim
@@ -1,6 +1,20 @@
" Author: w0rp <devw0rp@gmail.com>
" Description: Parsing and transforming of LSP server responses.
+" Constants for error codes.
+" Defined by JSON RPC
+let s:PARSE_ERROR = -32700
+let s:INVALID_REQUEST = -32600
+let s:METHOD_NOT_FOUND = -32601
+let s:INVALID_PARAMS = -32602
+let s:INTERNAL_ERROR = -32603
+let s:SERVER_ERROR_START = -32099
+let s:SERVER_ERROR_END = -32000
+let s:SERVER_NOT_INITIALIZED = -32002
+let s:UNKNOWN_ERROR_CODE = -32001
+" Defined by the protocol.
+let s:REQUEST_CANCELLED = -32800
+
" Constants for message severity codes.
let s:SEVERITY_ERROR = 1
let s:SEVERITY_WARNING = 2
@@ -72,3 +86,31 @@ function! ale#lsp#response#ReadTSServerDiagnostics(response) abort
return l:loclist
endfunction
+
+function! ale#lsp#response#GetErrorMessage(response) abort
+ if type(get(a:response, 'error', 0)) isnot type({})
+ return ''
+ endif
+
+ let l:code = get(a:response.error, 'code')
+
+ " Only report things for these error codes.
+ if l:code isnot s:INVALID_PARAMS && l:code isnot s:INTERNAL_ERROR
+ return ''
+ endif
+
+ let l:message = get(a:response.error, 'message', '')
+
+ if empty(l:message)
+ return ''
+ endif
+
+ " Include the traceback as details, if it's there.
+ let l:traceback = get(get(a:response.error, 'data', {}), 'traceback', [])
+
+ if type(l:traceback) is type([]) && !empty(l:traceback)
+ let l:message .= "\n" . join(l:traceback, "\n")
+ endif
+
+ return l:message
+endfunction
diff --git a/autoload/ale/pattern_options.vim b/autoload/ale/pattern_options.vim
index e58b8cf2..d1f91785 100644
--- a/autoload/ale/pattern_options.vim
+++ b/autoload/ale/pattern_options.vim
@@ -1,6 +1,11 @@
" Author: w0rp <devw0rp@gmail.com>
" Description: Set options in files based on regex patterns.
+" A dictionary mapping regular expression patterns to arbitrary buffer
+" variables to be set. Useful for configuring ALE based on filename patterns.
+let g:ale_pattern_options = get(g:, 'ale_pattern_options', {})
+let g:ale_pattern_options_enabled = get(g:, 'ale_pattern_options_enabled', !empty(g:ale_pattern_options))
+
" These variables are used to cache the sorting of patterns below.
let s:last_pattern_options = {}
let s:sorted_items = []
@@ -18,7 +23,8 @@ function! s:CmpPatterns(left_item, right_item) abort
endfunction
function! ale#pattern_options#SetOptions(buffer) abort
- if !g:ale_pattern_options_enabled || empty(g:ale_pattern_options)
+ if !get(g:, 'ale_pattern_options_enabled', 0)
+ \|| empty(get(g:, 'ale_pattern_options', 0))
return
endif
diff --git a/autoload/ale/python.vim b/autoload/ale/python.vim
index 82dd9d7c..cdc71cdd 100644
--- a/autoload/ale/python.vim
+++ b/autoload/ale/python.vim
@@ -15,6 +15,7 @@ let g:ale_virtualenv_dir_names = get(g:, 'ale_virtualenv_dir_names', [
function! ale#python#FindProjectRootIni(buffer) abort
for l:path in ale#path#Upwards(expand('#' . a:buffer . ':p:h'))
+ " If you change this, update ale-python-root documentation.
if filereadable(l:path . '/MANIFEST.in')
\|| filereadable(l:path . '/setup.cfg')
\|| filereadable(l:path . '/pytest.ini')
diff --git a/autoload/ale/sign.vim b/autoload/ale/sign.vim
index d1139c03..31663721 100644
--- a/autoload/ale/sign.vim
+++ b/autoload/ale/sign.vim
@@ -2,6 +2,25 @@ scriptencoding utf8
" Author: w0rp <devw0rp@gmail.com>
" Description: Draws error and warning signs into signcolumn
+" This flag can be set to some integer to control the maximum number of signs
+" that ALE will set.
+let g:ale_max_signs = get(g:, 'ale_max_signs', -1)
+" This flag can be set to 1 to enable changing the sign column colors when
+" there are errors.
+let g:ale_change_sign_column_color = get(g:, 'ale_change_sign_column_color', 0)
+" These variables dictate what signs are used to indicate errors and warnings.
+let g:ale_sign_error = get(g:, 'ale_sign_error', '>>')
+let g:ale_sign_style_error = get(g:, 'ale_sign_style_error', g:ale_sign_error)
+let g:ale_sign_warning = get(g:, 'ale_sign_warning', '--')
+let g:ale_sign_style_warning = get(g:, 'ale_sign_style_warning', g:ale_sign_warning)
+let g:ale_sign_info = get(g:, 'ale_sign_info', g:ale_sign_warning)
+" This variable sets an offset which can be set for sign IDs.
+" This ID can be changed depending on what IDs are set for other plugins.
+" The dummy sign will use the ID exactly equal to the offset.
+let g:ale_sign_offset = get(g:, 'ale_sign_offset', 1000000)
+" This flag can be set to 1 to keep sign gutter always open
+let g:ale_sign_column_always = get(g:, 'ale_sign_column_always', 0)
+
if !hlexists('ALEErrorSign')
highlight link ALEErrorSign error
endif
diff --git a/autoload/ale/statusline.vim b/autoload/ale/statusline.vim
index 3f53368b..851618cc 100644
--- a/autoload/ale/statusline.vim
+++ b/autoload/ale/statusline.vim
@@ -1,6 +1,14 @@
" Author: KabbAmine <amine.kabb@gmail.com>
" Description: Statusline related function(s)
+" remove in 2.0
+"
+" A deprecated setting for ale#statusline#Status()
+" See :help ale#statusline#Count() for getting status reports.
+let g:ale_statusline_format = get(g:, 'ale_statusline_format',
+\ ['%d error(s)', '%d warning(s)', 'OK']
+\)
+
function! s:CreateCountDict() abort
" Keys 0 and 1 are for backwards compatibility.
" The count object used to be a List of [error_count, warning_count].
@@ -90,6 +98,8 @@ function! s:StatusForListFormat() abort
return l:res
endfunction
+" remove in 2.0
+"
" Returns a formatted string that can be integrated in the statusline.
"
" This function is deprecated, and should not be used. Use the airline plugin
diff --git a/autoload/ale/toggle.vim b/autoload/ale/toggle.vim
index 1f691544..d8472cd8 100644
--- a/autoload/ale/toggle.vim
+++ b/autoload/ale/toggle.vim
@@ -1,6 +1,6 @@
function! s:EnablePreamble() abort
" Set pattern options again, if enabled.
- if g:ale_pattern_options_enabled
+ if get(g:, 'ale_pattern_options_enabled', 0)
call ale#pattern_options#SetOptions(bufnr(''))
endif
@@ -53,11 +53,6 @@ endfunction
function! ale#toggle#Enable() abort
if !g:ale_enabled
- " Set pattern options again, if enabled.
- if g:ale_pattern_options_enabled
- call ale#pattern_options#SetOptions(bufnr(''))
- endif
-
call ale#toggle#Toggle()
endif
endfunction
diff --git a/doc/ale-elm.txt b/doc/ale-elm.txt
index 32beab7b..de7d8939 100644
--- a/doc/ale-elm.txt
+++ b/doc/ale-elm.txt
@@ -34,7 +34,7 @@ elm-make *ale-elm-elm-make*
g:ale_elm_make_executable *g:ale_elm_make_executable*
*b:ale_elm_make_executable*
Type: |String|
- Default: `'elm-make'`
+ Default: `'elm'`
See |ale-integrations-local-executables|
diff --git a/doc/ale-gitcommit.txt b/doc/ale-gitcommit.txt
index 19ba8e94..38f3fd90 100644
--- a/doc/ale-gitcommit.txt
+++ b/doc/ale-gitcommit.txt
@@ -19,12 +19,14 @@ g:ale_gitcommit_gitlint_options *g:ale_gitcommit_gitlint_options*
Default: `''`
This variable can be changed to add command-line arguments to the gitlint
- invocation.
+ invocation. For example, you can specify the path to a configuration file. >
- For example, to dinamically set the gitlint configuration file path, you
- may want to set >
+ let g:ale_gitcommit_gitlint_options = '-C /home/user/.config/gitlint.ini'
+<
+ You can also disable particular error codes using this option. For example,
+ you can ignore errors for git commits with a missing body. >
- let g:ale_gitcommit_gitlint_options = '-C /home/user/.config/gitlint.ini'
+ let g:ale_gitcommit_gitlint_options = '--ignore B6'
<
g:ale_gitcommit_gitlint_use_global *g:ale_gitcommit_gitlint_use_global*
diff --git a/doc/ale-php.txt b/doc/ale-php.txt
index 1ba34388..33796f7c 100644
--- a/doc/ale-php.txt
+++ b/doc/ale-php.txt
@@ -48,7 +48,7 @@ g:ale_php_langserver_use_global *g:ale_php_langserver_use_global*
===============================================================================
phan *ale-php-phan*
-WARNING: please do not use this linter if you have an configuration file
+WARNING: please use the phan_client linter if you have an configuration file
for your project because the phan will look into your entirely project and
ale will display in the current buffer warnings that may belong to other file.
@@ -57,8 +57,22 @@ g:ale_php_phan_minimum_severity *g:ale_php_phan_minimum_severity*
Type: |Number|
Default: `0`
- This variable defines the minimum severity level
+ This variable defines the minimum severity level.
+g:ale_php_phan_executable *g:ale_php_phan_executable*
+ *b:ale_php_phan_executable*
+ Type: |String|
+ Default: `'phan'`
+
+ This variable sets executable used for phan or phan_client.
+
+g:ale_php_phan_use_client *g:ale_php_phan_use_client*
+ *b:ale_php_phan_use_client*
+ Type: |Number|
+ Default: `get(g:, 'ale_php_phan_use_client', 0)`
+
+ This variable can be set to 1 to use the phan_client with phan daemon mode
+ instead of the phan standalone.
===============================================================================
phpcbf *ale-php-phpcbf*
diff --git a/doc/ale-python.txt b/doc/ale-python.txt
index e1614262..55641892 100644
--- a/doc/ale-python.txt
+++ b/doc/ale-python.txt
@@ -3,6 +3,31 @@ ALE Python Integration *ale-python-options*
===============================================================================
+ALE Python Project Root Behavior *ale-python-root*
+
+For some linters, ALE will search for a Python project root by looking at the
+files in directories on or above where a file being checked is. ALE applies
+the following methods, in order:
+
+1. Find the first directory containing a common Python configuration file.
+2. If no configuration file can be found, use the first directory which does
+ not contain a readable file named `__init__.py`.
+
+ALE will look for configuration files with the following filenames. >
+
+ MANIFEST.in
+ setup.cfg
+ pytest.ini
+ tox.ini
+ mypy.ini
+ pycodestyle.cfg
+ flake8.cfg
+<
+
+The first directory containing any of the files named above will be used.
+
+
+===============================================================================
autopep8 *ale-python-autopep8*
g:ale_python_autopep8_executable *g:ale_python_autopep8_executable*
@@ -59,6 +84,17 @@ g:ale_python_black_use_global *g:ale_python_black_use_global*
===============================================================================
flake8 *ale-python-flake8*
+g:ale_python_flake8_change_directory *g:ale_python_flake8_change_directory*
+ *b:ale_python_flake8_change_directory*
+ Type: |Number|
+ Default: `1`
+
+ If set to `1`, ALE will switch to the directory the Python file being
+ checked with `flake8` is in before checking it. This helps `flake8` find
+ configuration files more easily. This option can be turned off if you want
+ to control the directory Python is executed from yourself.
+
+
g:ale_python_flake8_executable *g:ale_python_flake8_executable*
*b:ale_python_flake8_executable*
Type: |String|
@@ -123,6 +159,8 @@ The minimum supported version of mypy that ALE supports is v0.4.4. This is
the first version containing the `--shadow-file` option ALE needs to be able
to check for errors while you type.
+`mypy` will be run from a detected project root, per |ale-python-root|.
+
g:ale_python_mypy_executable *g:ale_python_mypy_executable*
*b:ale_python_mypy_executable*
@@ -281,6 +319,9 @@ g:ale_python_pylint_use_global *g:ale_python_pylint_use_global*
===============================================================================
pyls *ale-python-pyls*
+`pyls` will be run from a detected project root, per |ale-python-root|.
+
+
g:ale_python_pyls_executable *g:ale_python_pyls_executable*
*b:ale_python_pyls_executable*
Type: |String|
diff --git a/doc/ale.txt b/doc/ale.txt
index 636ef12a..2b4452d9 100644
--- a/doc/ale.txt
+++ b/doc/ale.txt
@@ -475,6 +475,12 @@ the buffer-local options can be used with external plugins for reading Vim
project configuration files. Buffer-local settings can also be used in
ftplugin files for different filetypes.
+ALE offers several options for controlling which linters are run.
+
+* Selecting linters to run. - |g:ale_linters|
+* Aliasing filetypes for linters - |g:ale_linter_aliases|
+* Only running linters you asked for. - |g:ale_linters_explicit|
+
===============================================================================
4. Fixing Problems *ale-fix*
@@ -668,6 +674,12 @@ at the cursor taken from LSP linters. The following commands are supported:
|ALEHover| - Print information about the symbol at the cursor.
+If |b:ale_set_balloons| is set to `1` and your version of Vim supports the
+|balloon_show()| function, then "hover" information also show up when you move
+the mouse over a symbol in a buffer. Diagnostic information will take priority
+over hover information for balloons. If a line contains a problem, that
+problem will be displayed in a balloon instead of hover information.
+
===============================================================================
6. Global Options *ale-options*
@@ -686,7 +698,7 @@ g:airline#extensions#ale#enabled *g:airline#extensions#ale#enabled*
g:ale_cache_executable_check_failures *g:ale_cache_executable_check_failures*
Type: |Number|
- Default: `0`
+ Default: undefined
When set to `1`, ALE will cache failing executable checks for linters. By
default, only executable checks which succeed will be cached.
@@ -886,20 +898,6 @@ g:ale_echo_msg_warning_str *g:ale_echo_msg_warning_str*
The string used for `%severity%` for warnings. See |g:ale_echo_msg_format|
-g:ale_emit_conflict_warnings *g:ale_emit_conflict_warnings*
-
- Type: |Number|
- Default: `1`
-
- When set to `0`, ALE will not emit any warnings on startup about conflicting
- plugins. ALE will probably not work if other linting plugins are installed.
-
- When this option is set to `1`, ALE will add its `after` directory to
- |runtimepath| automatically, so the checks can be applied. Setting this
- option to `0` before ALE is loaded will prevent ALE from modifying
- |runtimepath|.
-
-
g:ale_enabled *g:ale_enabled*
*b:ale_enabled*
@@ -1109,8 +1107,12 @@ g:ale_linter_aliases *g:ale_linter_aliases*
following values: >
{
- \ 'zsh': 'sh',
+ \ 'Dockerfile': 'dockerfile',
\ 'csh': 'sh',
+ \ 'plaintex': 'tex',
+ \ 'systemverilog': 'verilog',
+ \ 'vimwiki': 'markdown',
+ \ 'zsh': 'sh',
\}
<
For example, if you wish to map a new filetype `'foobar'` to run the `'php'`
@@ -1269,7 +1271,7 @@ g:ale_max_signs *g:ale_max_signs*
g:ale_maximum_file_size *g:ale_maximum_file_size*
*b:ale_maximum_file_size*
Type: |Number|
- Default: `0`
+ Default: undefined
A maximum file size in bytes for ALE to check. If set to any positive
number, ALE will skip checking files larger than the given size.
@@ -1350,18 +1352,23 @@ g:ale_set_balloons *g:ale_set_balloons*
*b:ale_set_balloons*
Type: |Number|
- Default: `has('balloon_eval') && has('gui_running') ||`
- `has('balloon_eval_term') && !has('gui_running')`
+ Default: `(has('balloon_eval') && has('gui_running'))`
+ `|| (has('balloon_eval_term') && !has('gui_running'))`
When this option is set to `1`, balloon messages will be displayed for
- problems. Problems nearest to the cursor on the line the cursor is over will
- be displayed. Balloons will not be shown when either |g:ale_enabled| is `0`
- or |b:ale_enabled| is `0`.
+ problems or hover information if available.
+
+ Problems nearest to the line the mouse cursor is over will be displayed. If
+ there are no problems to show, and one of the linters is an LSP linter
+ supporting "Hover" information, per |ale-hover|, then brief information
+ about the symbol under the cursor will be displayed in a balloon.
`b:ale_set_balloons` can be set to `0` to disable balloons for a buffer.
Balloons cannot be enabled for a specific buffer when not initially enabled
globally.
+ Balloons will not be shown when |g:ale_enabled| or |b:ale_enabled| is `0`.
+
g:ale_set_balloons_legacy_echo *g:ale_set_balloons_legacy_echo*
*b:ale_set_balloons_legacy_echo*
@@ -2312,14 +2319,17 @@ ale#linter#Define(filetype, linter) *ale#linter#Define()*
process for a language server runnning, and
communicates with it directly via a |channel|.
- When this argument is not empty, `project_callback`
- must be defined, and only one of either `language` or
- `language_callback` must be defined.
+ When this argument is not empty, only one of either
+ `language` or `language_callback` must be defined,
+ and `project_root_callback` must be defined.
LSP linters handle diagnostics automatically, so
the `callback` argument must not be defined.
- `project_callback` A |String| or |Funcref| for a callback function
+ An optional `completion_filter` callback may be
+ defined for filtering completion results.
+
+ `project_root_callback` A |String| or |Funcref| for a callback function
accepting a buffer number. A |String| should be
returned representing the path to the project for the
file being checked with the language server. If an
@@ -2344,6 +2354,15 @@ ale#linter#Define(filetype, linter) *ale#linter#Define()*
This option can be used instead of `language` if a
linter can check multiple languages.
+ `completion_filter` A |String| or |Funcref| for a callback function
+ accepting a buffer number and a completion item.
+
+ The completion item will be a |Dictionary| following
+ the Language Server Protocol `CompletionItem`
+ interface as described in the specification,
+ available online here:
+ https://microsoft.github.io/language-server-protocol
+
`aliases` A |List| of aliases for the linter name.
This argument can be set with alternative names for
diff --git a/plugin/ale.vim b/plugin/ale.vim
index 48ff531c..bea5a49e 100644
--- a/plugin/ale.vim
+++ b/plugin/ale.vim
@@ -32,21 +32,12 @@ if !s:has_features
finish
endif
+" remove in 2.0
if has('nvim') && !has('nvim-0.2.0') && !get(g:, 'ale_use_deprecated_neovim')
execute 'echom ''ALE support for NeoVim versions below 0.2.0 is deprecated.'''
execute 'echom ''Use `let g:ale_use_deprecated_neovim = 1` to silence this warning for now.'''
endif
-" This flag can be set to 0 to disable emitting conflict warnings.
-let g:ale_emit_conflict_warnings = get(g:, 'ale_emit_conflict_warnings', 1)
-
-if g:ale_emit_conflict_warnings
-\&& match(&runtimepath, '[/\\]ale[/\\]after') < 0
- " Add the after directory to the runtimepath
- " This is only done if the after directory isn't already in runtimepath
- let &runtimepath .= ',' . expand('<sfile>:p:h:h') . '/after'
-endif
-
" Set this flag so that other plugins can use it, like airline.
let g:loaded_ale = 1
@@ -73,9 +64,9 @@ let g:ale_filetype_blacklist = [
\]
" This Dictionary configures which linters are enabled for which languages.
-call ale#Set('linters', {})
+let g:ale_linters = get(g:, 'ale_linters', {})
" This option can be changed to only enable explicitly selected linters.
-call ale#Set('linters_explicit', 0)
+let g:ale_linters_explicit = get(g:, 'ale_linters_explicit', 0)
" This Dictionary configures which functions will be used for fixing problems.
let g:ale_fixers = get(g:, 'ale_fixers', {})
@@ -106,7 +97,8 @@ let g:ale_lint_on_save = get(g:, 'ale_lint_on_save', 1)
" This flag can be set to 1 to enable linting when the filetype is changed.
let g:ale_lint_on_filetype_changed = get(g:, 'ale_lint_on_filetype_changed', 1)
-call ale#Set('fix_on_save', 0)
+" This flag can be set to 1 to enable automatically fixing files on save.
+let g:ale_fix_on_save = get(g:, 'ale_fix_on_save', 0)
" This flag may be set to 0 to disable ale. After ale is loaded, :ALEToggle
" should be used instead.
@@ -117,81 +109,26 @@ let g:ale_enabled = get(g:, 'ale_enabled', 1)
let g:ale_set_loclist = get(g:, 'ale_set_loclist', 1)
let g:ale_set_quickfix = get(g:, 'ale_set_quickfix', 0)
-" This flag dictates if ale open the configured loclist
-let g:ale_open_list = get(g:, 'ale_open_list', 0)
-
-" This flag dictates if ale keeps open loclist even if there is no error in loclist
-let g:ale_keep_list_window_open = get(g:, 'ale_keep_list_window_open', 0)
-
-" This flag dictates that quickfix windows should be opened vertically
-let g:ale_list_vertical = get(g:, 'ale_list_vertical', 0)
-
-" The window size to set for the quickfix and loclist windows
-call ale#Set('list_window_size', 10)
-
" This flag can be set to 0 to disable setting signs.
" This is enabled by default only if the 'signs' feature exists.
let g:ale_set_signs = get(g:, 'ale_set_signs', has('signs'))
-" This flag can be set to some integer to control the maximum number of signs
-" that ALE will set.
-let g:ale_max_signs = get(g:, 'ale_max_signs', -1)
-
-" This flag can be set to 1 to enable changing the sign column colors when
-" there are errors.
-call ale#Set('change_sign_column_color', 0)
" This flag can be set to 0 to disable setting error highlights.
let g:ale_set_highlights = get(g:, 'ale_set_highlights', has('syntax'))
-" These variables dictate what sign is used to indicate errors and warnings.
-call ale#Set('sign_error', '>>')
-call ale#Set('sign_style_error', g:ale_sign_error)
-call ale#Set('sign_warning', '--')
-call ale#Set('sign_style_warning', g:ale_sign_warning)
-call ale#Set('sign_info', g:ale_sign_warning)
-
-" This variable sets an offset which can be set for sign IDs.
-" This ID can be changed depending on what IDs are set for other plugins.
-" The dummy sign will use the ID exactly equal to the offset.
-let g:ale_sign_offset = get(g:, 'ale_sign_offset', 1000000)
-
-" This flag can be set to 1 to keep sign gutter always open
-let g:ale_sign_column_always = get(g:, 'ale_sign_column_always', 0)
-
-" A string format for the echoed message
-call ale#Set('echo_msg_format', '%code: %%s')
-" The same for the loclist.
-call ale#Set('loclist_msg_format', g:ale_echo_msg_format)
-
-" Strings used for severity in the echoed message
-let g:ale_echo_msg_error_str = get(g:, 'ale_echo_msg_error_str', 'Error')
-let g:ale_echo_msg_info_str = get(g:, 'ale_echo_msg_info_str', 'Info')
-let g:ale_echo_msg_warning_str = get(g:, 'ale_echo_msg_warning_str', 'Warning')
-
" This flag can be set to 0 to disable echoing when the cursor moves.
let g:ale_echo_cursor = get(g:, 'ale_echo_cursor', 1)
-" Controls the milliseconds delay before echoing a message.
-let g:ale_echo_delay = get(g:, 'ale_echo_delay', 10)
" This flag can be set to 0 to disable balloon support.
-call ale#Set('set_balloons',
-\ has('balloon_eval') && has('gui_running') ||
-\ has('balloon_eval_term') && !has('gui_running')
-\)
-
-" A deprecated setting for ale#statusline#Status()
-" See :help ale#statusline#Count() for getting status reports.
-let g:ale_statusline_format = get(g:, 'ale_statusline_format',
-\ ['%d error(s)', '%d warning(s)', 'OK']
+let g:ale_set_balloons = get(g:, 'ale_set_balloons',
+\ (has('balloon_eval') && has('gui_running'))
+\ || (has('balloon_eval_term') && !has('gui_running'))
\)
" This flag can be set to 0 to disable warnings for trailing whitespace
-call ale#Set('warn_about_trailing_whitespace', 1)
+let g:ale_warn_about_trailing_whitespace = get(g:, 'ale_warn_about_trailing_whitespace', 1)
" This flag can be set to 0 to disable warnings for trailing blank lines
-call ale#Set('warn_about_trailing_blank_lines', 1)
-
-" A flag for controlling the maximum size of the command history to store.
-let g:ale_max_buffer_history_size = get(g:, 'ale_max_buffer_history_size', 20)
+let g:ale_warn_about_trailing_blank_lines = get(g:, 'ale_warn_about_trailing_blank_lines', 1)
" A flag for enabling or disabling the command history.
let g:ale_history_enabled = get(g:, 'ale_history_enabled', 1)
@@ -199,29 +136,8 @@ let g:ale_history_enabled = get(g:, 'ale_history_enabled', 1)
" A flag for storing the full output of commands in the history.
let g:ale_history_log_output = get(g:, 'ale_history_log_output', 1)
-" A flag for caching failed executable checks.
-" This is off by default, because it will cause problems.
-call ale#Set('cache_executable_check_failures', 0)
-
-" A dictionary mapping regular expression patterns to arbitrary buffer
-" variables to be set. Useful for configuration ALE based on filename
-" patterns.
-call ale#Set('pattern_options', {})
-call ale#Set('pattern_options_enabled', !empty(g:ale_pattern_options))
-
-" A maximum file size for checking for errors.
-call ale#Set('maximum_file_size', 0)
-
-" Remapping of linter problems.
-call ale#Set('type_map', {})
-
" Enable automatic completion with LSP servers and tsserver
-call ale#Set('completion_enabled', 0)
-call ale#Set('completion_delay', 100)
-call ale#Set('completion_max_suggestions', 50)
-
-" A setting for wrapping commands.
-call ale#Set('command_wrapper', '')
+let g:ale_completion_enabled = get(g:, 'ale_completion_enabled', 0)
if g:ale_set_balloons
call ale#balloon#Enable()
@@ -318,6 +234,7 @@ augroup END
" Backwards Compatibility
+" remove in 2.0
function! ALELint(delay) abort
if !get(g:, 'ale_deprecation_ale_lint', 0)
execute 'echom ''ALELint() is deprecated, use ale#Queue() instead.'''
@@ -327,6 +244,7 @@ function! ALELint(delay) abort
call ale#Queue(a:delay)
endfunction
+" remove in 2.0
function! ALEGetStatusLine() abort
if !get(g:, 'ale_deprecation_ale_get_status_line', 0)
execute 'echom ''ALEGetStatusLine() is deprecated.'''
diff --git a/test/command_callback/test_flake8_command_callback.vader b/test/command_callback/test_flake8_command_callback.vader
index 6297bd3f..ecd06332 100644
--- a/test/command_callback/test_flake8_command_callback.vader
+++ b/test/command_callback/test_flake8_command_callback.vader
@@ -2,11 +2,13 @@ Before:
Save g:ale_python_flake8_executable
Save g:ale_python_flake8_options
Save g:ale_python_flake8_use_global
+ Save g:ale_python_flake8_change_directory
unlet! g:ale_python_flake8_executable
unlet! g:ale_python_flake8_args
unlet! g:ale_python_flake8_options
unlet! g:ale_python_flake8_use_global
+ unlet! g:ale_python_flake8_change_directory
let b:bin_dir = has('win32') ? 'Scripts' : 'bin'
@@ -44,6 +46,13 @@ Execute(The flake8 callbacks should return the correct default values):
\ . ale#Escape('flake8') . ' --format=default -',
\ ale_linters#python#flake8#GetCommand(bufnr(''), ['2.9.9'])
+Execute(The option for disabling changing directories should work):
+ let g:ale_python_flake8_change_directory = 0
+
+ AssertEqual
+ \ ale#Escape('flake8') . ' --format=default --stdin-display-name %s -',
+ \ ale_linters#python#flake8#GetCommand(bufnr(''), ['3.0.0'])
+
Execute(The flake8 command callback should let you set options):
let g:ale_python_flake8_options = '--some-option'
@@ -165,26 +174,3 @@ Execute(Using `python -m flake8` should be supported for running flake8):
\ ale#path#BufferCdString(bufnr(''))
\ . ale#Escape('python') . ' -m flake8 --some-option --format=default -',
\ ale_linters#python#flake8#GetCommand(bufnr(''), ['2.9.9'])
-
-Execute(Using `python2 -m flake8` should be supported with the old args option):
- let g:ale_python_flake8_executable = 'python2'
- let g:ale_python_flake8_args = '-m flake8'
- let g:ale_python_flake8_use_global = 0
-
- unlet! g:ale_python_flake8_options
-
- call ale#linter#Reset()
- runtime ale_linters/python/flake8.vim
-
- silent execute 'file ' . fnameescape(g:dir . '/python_paths/with_virtualenv/subdir/foo/bar.py')
-
- AssertEqual
- \ 'python2',
- \ ale_linters#python#flake8#GetExecutable(bufnr(''))
- AssertEqual
- \ ale#Escape('python2') . ' -m flake8 --version',
- \ ale_linters#python#flake8#VersionCheck(bufnr(''))
- AssertEqual
- \ ale#path#BufferCdString(bufnr(''))
- \ . ale#Escape('python2') . ' -m flake8 --format=default -',
- \ ale_linters#python#flake8#GetCommand(bufnr(''), ['2.9.9'])
diff --git a/test/command_callback/test_perlcritic_command_callback.vader b/test/command_callback/test_perlcritic_command_callback.vader
index 6507868b..e8d8cc18 100644
--- a/test/command_callback/test_perlcritic_command_callback.vader
+++ b/test/command_callback/test_perlcritic_command_callback.vader
@@ -30,14 +30,18 @@ Execute(The command should be correct with g:ale_perl_perlcritic_showrules off):
let b:ale_perl_perlcritic_showrules = 0
AssertEqual
- \ ale#Escape('perlcritic') . ' --verbose ''%l:%c %m\n'' --nocolor',
+ \ ale#Escape('perlcritic')
+ \ . ' --verbose ' . ale#Escape('%l:%c %m\n')
+ \ . ' --nocolor',
\ ale_linters#perl#perlcritic#GetCommand(bufnr(''))
Execute(The command should be correct with g:ale_perl_perlcritic_showrules on):
let b:ale_perl_perlcritic_showrules = 1
AssertEqual
- \ ale#Escape('perlcritic') . ' --verbose ''%l:%c %m [%p]\n'' --nocolor',
+ \ ale#Escape('perlcritic')
+ \ . ' --verbose ' . ale#Escape('%l:%c %m [%p]\n')
+ \ . ' --nocolor',
\ ale_linters#perl#perlcritic#GetCommand(bufnr(''))
Execute(The command search for the profile file when set):
@@ -46,7 +50,9 @@ Execute(The command search for the profile file when set):
let b:readme_path = ale#path#Simplify(expand('%:p:h:h:h') . '/README.md')
AssertEqual
- \ ale#Escape('perlcritic') . ' --verbose ''%l:%c %m\n'' --nocolor'
+ \ ale#Escape('perlcritic')
+ \ . ' --verbose ' . ale#Escape('%l:%c %m\n')
+ \ . ' --nocolor'
\ . ' --profile ' . ale#Escape(b:readme_path),
\ ale_linters#perl#perlcritic#GetCommand(bufnr(''))
@@ -54,6 +60,8 @@ Execute(Extra options should be set appropriately):
let b:ale_perl_perlcritic_options = 'beep boop'
AssertEqual
- \ ale#Escape('perlcritic') . ' --verbose ''%l:%c %m\n'' --nocolor'
+ \ ale#Escape('perlcritic')
+ \ . ' --verbose ' . ale#Escape('%l:%c %m\n')
+ \ . ' --nocolor'
\ . ' beep boop',
\ ale_linters#perl#perlcritic#GetCommand(bufnr(''))
diff --git a/test/command_callback/test_sasslint_command_callback.vader b/test/command_callback/test_sasslint_command_callback.vader
new file mode 100644
index 00000000..1db7e5fb
--- /dev/null
+++ b/test/command_callback/test_sasslint_command_callback.vader
@@ -0,0 +1,12 @@
+Before:
+ call ale#test#SetDirectory('/testplugin/test/command_callback')
+ call ale#test#SetFilename('test.sass')
+
+After:
+ call ale#test#RestoreDirectory()
+
+Execute(The default sasslint command should be correct):
+ AssertEqual
+ \ 'cd ' . ale#Escape(expand('%:p:h')) . ' && '
+ \ . ale#Escape('sass-lint') . ' -v -q -f compact %t',
+ \ ale#handlers#sasslint#GetCommand(bufnr(''))
diff --git a/test/completion/test_completion_prefixes.vader b/test/completion/test_completion_prefixes.vader
index a88e978d..0b2cfeaf 100644
--- a/test/completion/test_completion_prefixes.vader
+++ b/test/completion/test_completion_prefixes.vader
@@ -2,6 +2,8 @@ Given typescript():
let abc = y.
let foo = ab
let foo = (ab)
+ let string1 = '
+ let string2 = "
Execute(Completion should be done after dots in TypeScript):
AssertEqual '.', ale#completion#GetPrefix(&filetype, 1, 13)
@@ -15,6 +17,13 @@ Execute(Completion should be done after words in parens in TypeScript):
Execute(Completion should not be done after parens in TypeScript):
AssertEqual '', ale#completion#GetPrefix(&filetype, 3, 15)
+Execute(Completion should be done after strings in TypeScript):
+ AssertEqual '''', ale#completion#GetPrefix(&filetype, 4, 16)
+ AssertEqual '"', ale#completion#GetPrefix(&filetype, 5, 16)
+
+Execute(Completion prefixes should work for other filetypes):
+ AssertEqual 'ab', ale#completion#GetPrefix('xxxyyyzzz', 3, 14)
+
Execute(Completion prefixes should work for other filetypes):
AssertEqual 'ab', ale#completion#GetPrefix('xxxyyyzzz', 3, 14)
diff --git a/test/completion/test_lsp_completion_messages.vader b/test/completion/test_lsp_completion_messages.vader
index af3aa8c0..734b330c 100644
--- a/test/completion/test_lsp_completion_messages.vader
+++ b/test/completion/test_lsp_completion_messages.vader
@@ -41,6 +41,7 @@ After:
unlet! b:ale_completion_parser
unlet! b:ale_complete_done_time
unlet! b:ale_linters
+ unlet! b:ale_tsserver_completion_names
call ale#test#RestoreDirectory()
call ale#linter#Reset()
@@ -112,6 +113,12 @@ Execute(The right message sent to the tsserver LSP when the first completion mes
\ ],
\})
+ " We should save the names we got in the buffer, as TSServer doesn't return
+ " details for every name.
+ AssertEqual
+ \ ['Foo', 'FooBar', 'frazzle'],
+ \ get(b:, 'ale_tsserver_completion_names', [])
+
" The entry details messages should have been sent.
AssertEqual
\ [[
diff --git a/test/completion/test_lsp_completion_parsing.vader b/test/completion/test_lsp_completion_parsing.vader
index c9c51a66..23bbd14c 100644
--- a/test/completion/test_lsp_completion_parsing.vader
+++ b/test/completion/test_lsp_completion_parsing.vader
@@ -390,3 +390,42 @@ Execute(Should handle Python completion results correctly):
\ ]
\ }
\ })
+
+Execute(Should handle Python completion results correctly):
+ let b:ale_completion_info = {
+ \ 'completion_filter': 'ale#completion#python#CompletionItemFilter',
+ \ 'prefix': 'mig',
+ \}
+
+ AssertEqual
+ \ [
+ \ {'word': 'migrations', 'menu': 'xxx', 'info': 'migrations', 'kind': 'f', 'icase': 1},
+ \ {'word': 'MigEngine', 'menu': 'xxx', 'info': 'mig engine', 'kind': 'f', 'icase': 1},
+ \ ],
+ \ ale#completion#ParseLSPCompletions({
+ \ 'jsonrpc': '2.0',
+ \ 'id': 6,
+ \ 'result': {
+ \ 'isIncomplete': v:false,
+ \ 'items': [
+ \ {
+ \ 'label': 'migrations',
+ \ 'kind': 3,
+ \ 'detail': 'xxx',
+ \ 'documentation': 'migrations',
+ \ },
+ \ {
+ \ 'label': 'MigEngine',
+ \ 'kind': 3,
+ \ 'detail': 'xxx',
+ \ 'documentation': 'mig engine',
+ \ },
+ \ {
+ \ 'label': 'ignore me',
+ \ 'kind': 3,
+ \ 'detail': 'nope',
+ \ 'documentation': 'nope',
+ \ },
+ \ ]
+ \ }
+ \ })
diff --git a/test/completion/test_tsserver_completion_parsing.vader b/test/completion/test_tsserver_completion_parsing.vader
index b663ef40..c8e2c993 100644
--- a/test/completion/test_tsserver_completion_parsing.vader
+++ b/test/completion/test_tsserver_completion_parsing.vader
@@ -1,3 +1,6 @@
+After:
+ unlet! b:ale_tsserver_completion_names
+
Execute(TypeScript completions responses should be parsed correctly):
AssertEqual [],
\ ale#completion#ParseTSServerCompletions({
@@ -73,3 +76,74 @@ Execute(TypeScript completion details responses should be parsed correctly):
\ },
\ ],
\})
+
+Execute(Entries without details should be included in the responses):
+ let b:ale_tsserver_completion_names = ['xyz']
+
+ AssertEqual
+ \ [
+ \ {
+ \ 'word': 'abc',
+ \ 'menu': '(property) Foo.abc: number',
+ \ 'info': '',
+ \ 'kind': 'f',
+ \ 'icase': 1,
+ \ },
+ \ {
+ \ 'word': 'def',
+ \ 'menu': '(property) Foo.def: number',
+ \ 'info': 'foo bar baz',
+ \ 'kind': 'f',
+ \ 'icase': 1,
+ \ },
+ \ {
+ \ 'word': 'xyz',
+ \ 'menu': '',
+ \ 'info': '',
+ \ 'kind': 'v',
+ \ 'icase': 1,
+ \ },
+ \ ],
+ \ ale#completion#ParseTSServerCompletionEntryDetails({
+ \ 'body': [
+ \ {
+ \ 'name': 'abc',
+ \ 'kind': 'parameterName',
+ \ 'displayParts': [
+ \ {'text': '('},
+ \ {'text': 'property'},
+ \ {'text': ')'},
+ \ {'text': ' '},
+ \ {'text': 'Foo'},
+ \ {'text': '.'},
+ \ {'text': 'abc'},
+ \ {'text': ':'},
+ \ {'text': ' '},
+ \ {'text': 'number'},
+ \ ],
+ \ },
+ \ {
+ \ 'name': 'def',
+ \ 'kind': 'parameterName',
+ \ 'displayParts': [
+ \ {'text': '('},
+ \ {'text': 'property'},
+ \ {'text': ')'},
+ \ {'text': ' '},
+ \ {'text': 'Foo'},
+ \ {'text': '.'},
+ \ {'text': 'def'},
+ \ {'text': ':'},
+ \ {'text': ' '},
+ \ {'text': 'number'},
+ \ ],
+ \ 'documentation': [
+ \ {'text': 'foo'},
+ \ {'text': ' '},
+ \ {'text': 'bar'},
+ \ {'text': ' '},
+ \ {'text': 'baz'},
+ \ ],
+ \ },
+ \ ],
+ \})
diff --git a/test/elm-test-files/app/node_modules/.bin/elm-make b/test/elm-test-files/app/node_modules/.bin/elm
index e69de29b..e69de29b 100644
--- a/test/elm-test-files/app/node_modules/.bin/elm-make
+++ b/test/elm-test-files/app/node_modules/.bin/elm
diff --git a/test/fix/test_ale_fix_completion_filter.vader b/test/fix/test_ale_fix_completion_filter.vader
new file mode 100644
index 00000000..536b7138
--- /dev/null
+++ b/test/fix/test_ale_fix_completion_filter.vader
@@ -0,0 +1,14 @@
+Before:
+ call ale#fix#registry#Clear()
+ call ale#test#SetFilename('test.js')
+ call ale#fix#registry#Add('prettier', '', ['javascript'], 'prettier')
+ call ale#fix#registry#Add('eslint', '', ['javascript'], 'eslint')
+ setfiletype javascript
+
+Execute(completeFixers returns all of the applicable fixers without an arglead):
+ AssertEqual ['eslint', 'prettier'],
+ \ ale#fix#registry#CompleteFixers('', 'ALEFix ', 7)
+
+Execute(completeFixers returns all of the applicable fixers without an arglead):
+ AssertEqual ['prettier'],
+ \ ale#fix#registry#CompleteFixers('pre', 'ALEFix ', 10)
diff --git a/test/handler/test_elmmake_handler.vader b/test/handler/test_elmmake_handler.vader
index f3424b4b..41c9646f 100644
--- a/test/handler/test_elmmake_handler.vader
+++ b/test/handler/test_elmmake_handler.vader
@@ -9,7 +9,139 @@ After:
call ale#linter#Reset()
-Execute(The elm-make handler should parse lines correctly):
+
+" Elm 0.19
+
+Execute(The elm-make handler should parse Elm 0.19 general problems correctly):
+ AssertEqual
+ \ [
+ \ {
+ \ 'lnum': 1,
+ \ 'type': 'E',
+ \ 'text': "error details\n\nstyled details"
+ \ }
+ \ ],
+ \ ale_linters#elm#make#Handle(347, [
+ \ '{
+ \ "type": "error",
+ \ "path": "' . b:tmp . '/Module.elm",
+ \ "title": "UNKNOWN IMPORT",
+ \ "message": ["error details\n\n", { "string": "styled details" }]
+ \ }'
+ \ ])
+
+Execute(The elm-make handler should parse Elm 0.19 compilation errors correctly):
+ AssertEqual
+ \ [
+ \ {
+ \ 'lnum': 404,
+ \ 'col': 1,
+ \ 'end_lnum': 408,
+ \ 'end_col': 18,
+ \ 'type': 'E',
+ \ 'text': "error details 1\n\nstyled details"
+ \ },
+ \ {
+ \ 'lnum': 406,
+ \ 'col': 5,
+ \ 'end_lnum': 407,
+ \ 'end_col': 17,
+ \ 'type': 'E',
+ \ 'text': "error details 2",
+ \ },
+ \ {
+ \ 'lnum': 406,
+ \ 'col': 5,
+ \ 'end_lnum': 406,
+ \ 'end_col': 93,
+ \ 'type': 'E',
+ \ 'text': "error details 3",
+ \ },
+ \ ],
+ \ ale_linters#elm#make#Handle(347, [
+ \ '{
+ \ "type": "compile-errors",
+ \ "errors": [
+ \ {
+ \ "path": "' . b:tmp . '/Module.elm",
+ \ "problems": [
+ \ {
+ \ "title": "TYPE MISMATCH",
+ \ "message": ["error details 1\n\n", { "string": "styled details" }],
+ \ "region": { "start": { "line": 404, "column": 1 }, "end": { "line": 408, "column": 18 } }
+ \ },
+ \ {
+ \ "title": "TYPE MISMATCH",
+ \ "message": ["error details 2"],
+ \ "region": { "start": {"line": 406, "column": 5}, "end": {"line": 407, "column": 17 } }
+ \ },
+ \ {
+ \ "title": "TYPE MISMATCH",
+ \ "message": ["error details 3"],
+ \ "region": { "start": { "line": 406, "column": 5}, "end": {"line": 406, "column": 93 } }
+ \ }
+ \ ]
+ \ }
+ \ ]
+ \ }'
+ \ ])
+
+Execute(The elm-make handler should handle errors in Elm 0.19 imported modules):
+ AssertEqual
+ \ [
+ \ {
+ \ 'lnum': 1,
+ \ 'type': 'E',
+ \ 'text': "src/Module.elm - error details\n\nstyled details",
+ \ 'detail': "src/Module.elm ----------\n\nerror details\n\nstyled details"
+ \ },
+ \ {
+ \ 'lnum': 1,
+ \ 'type': 'E',
+ \ 'text': "Elm - error details\n\nstyled details",
+ \ 'detail': "Elm ----------\n\nerror details\n\nstyled details"
+ \ },
+ \ {
+ \ 'lnum': 1,
+ \ 'type': 'E',
+ \ 'text': "src/Module.elm:404 - error details\n\nstyled details",
+ \ 'detail': "src/Module.elm:404 ----------\n\nerror details\n\nstyled details"
+ \ },
+ \ ],
+ \ ale_linters#elm#make#Handle(347, [
+ \ '{
+ \ "type": "error",
+ \ "path": "src/Module.elm",
+ \ "title": "UNKNOWN IMPORT",
+ \ "message": ["error details\n\n", { "string": "styled details" }]
+ \ }',
+ \ '{
+ \ "type": "error",
+ \ "path": null,
+ \ "title": "UNKNOWN IMPORT",
+ \ "message": ["error details\n\n", { "string": "styled details" }]
+ \ }',
+ \ '{
+ \ "type": "compile-errors",
+ \ "errors": [
+ \ {
+ \ "path": "src/Module.elm",
+ \ "problems": [
+ \ {
+ \ "title": "TYPE MISMATCH",
+ \ "message": ["error details\n\n", { "string": "styled details" }],
+ \ "region": { "start": { "line": 404, "column": 1 }, "end": { "line": 408, "column": 18 } }
+ \ }
+ \ ]
+ \ }
+ \ ]
+ \ }'
+ \ ])
+
+
+" Elm 0.18
+
+Execute(The elm-make handler should parse Elm 0.18 compilation errors correctly):
AssertEqual
\ [
\ {
@@ -50,21 +182,90 @@ Execute(The elm-make handler should parse lines correctly):
\ },
\ ],
\ ale_linters#elm#make#Handle(347, [
- \ '[{"tag":"unused import","overview":"warning overview","details":"warning details","region":{"start":{"line":33,"column":1},"end":{"line":33,"column":19}},"type":"warning","file":"' . b:tmp . 'Module.elm"}]',
- \ '[{"tag":"TYPE MISMATCH","overview":"error overview 1","subregion":{"start":{"line":406,"column":5},"end":{"line":408,"column":18}},"details":"error details 1","region":{"start":{"line":404,"column":1},"end":{"line":408,"column":18}},"type":"error","file":"' . b:tmp . 'Module.elm"},{"tag":"TYPE MISMATCH","overview":"error overview 2","subregion":{"start":{"line":407,"column":12},"end":{"line":407,"column":17}},"details":"error details 2","region":{"start":{"line":406,"column":5},"end":{"line":407,"column":17}},"type":"error","file":"' . b:tmp . 'Module.elm"},{"tag":"TYPE MISMATCH","overview":"error overview 3","subregion":{"start":{"line":406,"column":88},"end":{"line":406,"column":93}},"details":"error details 3","region":{"start":{"line":406,"column":5},"end":{"line":406,"column":93}},"type":"error","file":"' . b:tmp . 'Module.elm"}]'
+ \ '[
+ \ {
+ \ "tag": "unused import",
+ \ "overview": "warning overview",
+ \ "details": "warning details",
+ \ "region": {"start": { "line": 33, "column": 1 }, "end": { "line": 33, "column": 19 } },
+ \ "type": "warning",
+ \ "file": "' . b:tmp . '/Module.elm"
+ \ }
+ \ ]',
+ \ '[
+ \ {
+ \ "tag": "TYPE MISMATCH",
+ \ "overview": "error overview 1",
+ \ "subregion": { "start": { "line": 406, "column": 5 }, "end": { "line": 408, "column": 18 } },
+ \ "details": "error details 1",
+ \ "region": { "start": { "line": 404, "column": 1 }, "end": { "line": 408, "column": 18 } },
+ \ "type": "error",
+ \ "file":"' . b:tmp . '/Module.elm"
+ \ },
+ \ {
+ \ "tag": "TYPE MISMATCH",
+ \ "overview": "error overview 2",
+ \ "subregion": { "start": { "line": 407, "column": 12 }, "end": { "line": 407, "column": 17 } },
+ \ "details": "error details 2",
+ \ "region": { "start": { "line": 406, "column": 5}, "end": { "line": 407, "column": 17 } },
+ \ "type":"error",
+ \ "file":"' . b:tmp . '/Module.elm"
+ \ },
+ \ {
+ \ "tag": "TYPE MISMATCH",
+ \ "overview": "error overview 3",
+ \ "subregion": { "start": { "line": 406, "column": 88 }, "end": { "line": 406, "column": 93 } },
+ \ "details": "error details 3",
+ \ "region": { "start": { "line": 406, "column": 5 }, "end": { "line": 406, "column": 93 } },
+ \ "type":"error",
+ \ "file":"' . b:tmp . '/Module.elm"
+ \ }
+ \ ]'
\ ])
+Execute(The elm-make handler should handle errors in Elm 0.18 imported modules):
+ AssertEqual
+ \ [
+ \ {
+ \ 'lnum': 1,
+ \ 'type': 'E',
+ \ 'text': "src/Module.elm:33 - error overview",
+ \ 'detail': "src/Module.elm:33 ----------\n\nerror overview\n\nerror details"
+ \ }
+ \ ],
+ \ ale_linters#elm#make#Handle(347, [
+ \ '[
+ \ {
+ \ "tag": "unused import",
+ \ "overview": "warning overview",
+ \ "details": "warning details",
+ \ "region": {"start": { "line": 33, "column": 1 }, "end": { "line": 33, "column": 19 } },
+ \ "type": "warning",
+ \ "file": "src/Module.elm"
+ \ },
+ \ {
+ \ "tag": "type error",
+ \ "overview": "error overview",
+ \ "details": "error details",
+ \ "region": {"start": { "line": 33, "column": 1 }, "end": { "line": 33, "column": 19 } },
+ \ "type": "error",
+ \ "file": "src/Module.elm"
+ \ }
+ \ ]',
+ \ ])
+
+" Generic
+
Execute(The elm-make handler should put an error on the first line if a line cannot be parsed):
AssertEqual
\ [
\ {
- \ 'lnum': 33,
+ \ 'lnum': 404,
\ 'col': 1,
- \ 'end_lnum': 33,
- \ 'end_col': 19,
- \ 'type': 'W',
- \ 'text': 'warning overview',
- \ 'detail': "warning overview\n\nwarning details",
+ \ 'end_lnum': 408,
+ \ 'end_col': 18,
+ \ 'type': 'E',
+ \ 'text': "error details 1\n\nstyled details"
\ },
\ {
\ 'lnum': 1,
@@ -74,7 +275,28 @@ Execute(The elm-make handler should put an error on the first line if a line can
\ },
\ ],
\ ale_linters#elm#make#Handle(347, [
- \ '[{"tag":"unused import","overview":"warning overview","details":"warning details","region":{"start":{"line":33,"column":1},"end":{"line":33,"column":19}},"type":"warning","file":"' . b:tmp . 'Module.elm"}]',
- \ "Not JSON",
- \ "Also not JSON",
+ \ '{
+ \ "type": "compile-errors",
+ \ "errors": [
+ \ {
+ \ "path": "' . b:tmp . '/Module.elm",
+ \ "problems": [
+ \ {
+ \ "title": "TYPE MISMATCH",
+ \ "message": ["error details 1\n\n", { "string": "styled details" }],
+ \ "region": { "start": { "line": 404, "column": 1 }, "end": { "line": 408, "column": 18 } }
+ \ }
+ \ ]
+ \ }
+ \ ]
+ \ }',
+ \ 'Not JSON',
+ \ 'Also not JSON',
+ \ ])
+
+Execute(The elm-make handler should ignore success lines):
+ AssertEqual
+ \ [],
+ \ ale_linters#elm#make#Handle(347, [
+ \ 'Successfully generated /dev/null',
\ ])
diff --git a/test/lsp/test_lsp_error_parsing.vader b/test/lsp/test_lsp_error_parsing.vader
new file mode 100644
index 00000000..7464b0e7
--- /dev/null
+++ b/test/lsp/test_lsp_error_parsing.vader
@@ -0,0 +1,65 @@
+Execute(Invalid responses should be handled):
+ AssertEqual '', ale#lsp#response#GetErrorMessage({})
+ AssertEqual '', ale#lsp#response#GetErrorMessage({'error': 0})
+ AssertEqual '', ale#lsp#response#GetErrorMessage({'error': {}})
+ AssertEqual '', ale#lsp#response#GetErrorMessage({
+ \ 'error': {
+ \ 'code': 0,
+ \ 'message': 'x',
+ \ },
+ \})
+ AssertEqual '', ale#lsp#response#GetErrorMessage({'error': {'code': -32602}})
+ AssertEqual '', ale#lsp#response#GetErrorMessage({'error': {'code': -32603}})
+
+Execute(Messages without tracebacks should be handled):
+ AssertEqual 'xyz', ale#lsp#response#GetErrorMessage({
+ \ 'error': {
+ \ 'code': -32602,
+ \ 'message': 'xyz',
+ \ },
+ \})
+ AssertEqual 'abc', ale#lsp#response#GetErrorMessage({
+ \ 'error': {
+ \ 'code': -32603,
+ \ 'message': 'abc',
+ \ },
+ \})
+
+Execute(Invalid traceback data should be tolerated):
+ AssertEqual 'xyz', ale#lsp#response#GetErrorMessage({
+ \ 'error': {
+ \ 'code': -32602,
+ \ 'message': 'xyz',
+ \ 'data': {
+ \ },
+ \ },
+ \})
+ AssertEqual 'xyz', ale#lsp#response#GetErrorMessage({
+ \ 'error': {
+ \ 'code': -32602,
+ \ 'message': 'xyz',
+ \ 'data': {
+ \ 'traceback': 0,
+ \ },
+ \ },
+ \})
+ AssertEqual 'xyz', ale#lsp#response#GetErrorMessage({
+ \ 'error': {
+ \ 'code': -32602,
+ \ 'message': 'xyz',
+ \ 'data': {
+ \ 'traceback': [],
+ \ },
+ \ },
+ \})
+
+Execute(Messages with tracebacks should be handled):
+ AssertEqual "xyz\n123\n456", ale#lsp#response#GetErrorMessage({
+ \ 'error': {
+ \ 'code': -32602,
+ \ 'message': 'xyz',
+ \ 'data': {
+ \ 'traceback': ['123', '456'],
+ \ },
+ \ },
+ \})
diff --git a/test/sign/test_sign_placement.vader b/test/sign/test_sign_placement.vader
index 36f34e16..19267fe7 100644
--- a/test/sign/test_sign_placement.vader
+++ b/test/sign/test_sign_placement.vader
@@ -1,7 +1,9 @@
Before:
Save g:ale_set_signs
+ Save g:ale_buffer_info
let g:ale_set_signs = 1
+ let g:ale_buffer_info = {}
call ale#linter#Reset()
sign unplace *
diff --git a/test/test_ale_info.vader b/test/test_ale_info.vader
index c1ae5a7d..75078607 100644
--- a/test/test_ale_info.vader
+++ b/test/test_ale_info.vader
@@ -1,30 +1,50 @@
Before:
Save g:ale_buffer_info
Save g:ale_cache_executable_check_failures
+ Save g:ale_completion_delay
Save g:ale_completion_enabled
+ Save g:ale_completion_max_suggestions
Save g:ale_fixers
Save g:ale_history_log_output
Save g:ale_lint_on_insert_leave
Save g:ale_lint_on_text_changed
Save g:ale_linters
+ Save g:ale_lsp_error_messages
Save g:ale_maximum_file_size
Save g:ale_pattern_options
Save g:ale_pattern_options_enabled
Save g:ale_set_balloons
+ Save g:ale_sign_error
+ Save g:ale_sign_info
+ Save g:ale_sign_style_error
+ Save g:ale_sign_style_warning
+ Save g:ale_sign_warning
+ Save g:ale_statusline_format
+ Save g:ale_type_map
Save g:ale_warn_about_trailing_whitespace
unlet! b:ale_history
let g:ale_buffer_info = {}
let g:ale_cache_executable_check_failures = 0
+ let g:ale_completion_delay = 100
let g:ale_completion_enabled = 0
+ let g:ale_completion_max_suggestions = 50
let g:ale_history_log_output = 1
let g:ale_lint_on_insert_leave = 0
let g:ale_lint_on_text_changed = 'always'
+ let g:ale_lsp_error_messages = {}
let g:ale_maximum_file_size = 0
let g:ale_pattern_options = {}
let g:ale_pattern_options_enabled = 0
let g:ale_set_balloons = 0
+ let g:ale_sign_error = '>>'
+ let g:ale_sign_info = '--'
+ let g:ale_sign_style_error = '>>'
+ let g:ale_sign_style_warning = '--'
+ let g:ale_sign_warning = '--'
+ let g:ale_statusline_format = ['%d error(s)', '%d warning(s)', 'OK']
+ let g:ale_type_map = {}
let g:ale_warn_about_trailing_whitespace = 1
let g:testlinter1 = {'name': 'testlinter1', 'executable': 'testlinter1', 'command': 'testlinter1', 'callback': 'testCB1', 'output_stream': 'stdout'}
@@ -469,3 +489,44 @@ Execute (The option for caching failing executable checks should work):
\ '(executable check - success) ' . (has('win32') ? 'cmd' : 'echo'),
\ '(executable check - failure) TheresNoWayThisIsExecutable',
\])
+
+Given testft (Empty buffer):
+Execute (LSP errors for a linter should be outputted):
+ let g:ale_lsp_error_messages = {'testlinter1': ['foo', 'bar']}
+ call ale#linter#Define('testft', g:testlinter1)
+
+ call CheckInfo(
+ \ [
+ \ ' Current Filetype: testft',
+ \ 'Available Linters: [''testlinter1'']',
+ \ ' Enabled Linters: [''testlinter1'']',
+ \ ' Linter Variables:',
+ \ '',
+ \ ]
+ \ + g:globals_lines
+ \ + [
+ \ ' LSP Error Messages:',
+ \ '',
+ \ '(Errors for testlinter1)',
+ \ 'foo',
+ \ 'bar',
+ \ ]
+ \ + g:command_header
+ \)
+
+Given testft (Empty buffer):
+Execute (LSP errors for other linters shouldn't appear):
+ let g:ale_lsp_error_messages = {'testlinter2': ['foo']}
+ call ale#linter#Define('testft', g:testlinter1)
+
+ call CheckInfo(
+ \ [
+ \ ' Current Filetype: testft',
+ \ 'Available Linters: [''testlinter1'']',
+ \ ' Enabled Linters: [''testlinter1'']',
+ \ ' Linter Variables:',
+ \ '',
+ \ ]
+ \ + g:globals_lines
+ \ + g:command_header
+ \)
diff --git a/test/test_alelint_autocmd.vader b/test/test_alelint_autocmd.vader
index d51694ff..5af1cd47 100644
--- a/test/test_alelint_autocmd.vader
+++ b/test/test_alelint_autocmd.vader
@@ -14,6 +14,7 @@ After:
catch
endtry
+Given foobar(An empty file):
Execute(Run a lint cycle, and check that a variable is set in the autocmd):
augroup VaderTest
autocmd!
diff --git a/test/test_conflicting_plugin_warnings.vader b/test/test_conflicting_plugin_warnings.vader
deleted file mode 100644
index 08a4c412..00000000
--- a/test/test_conflicting_plugin_warnings.vader
+++ /dev/null
@@ -1,74 +0,0 @@
-Execute(The after file should have been loaded for real):
- " FIXME: Fix these tests in NeoVim.
- if !has('nvim')
- Assert has_key(g:, 'loaded_ale_after'), 'g:loaded_ale_after was not set!'
- Assert g:loaded_ale_after
- endif
-
-Before:
- silent! cd /testplugin/test
- cd ..
- unlet! g:loaded_ale_after
-
-After:
- cd test
- let g:loaded_ale_after = 1
- let g:ale_emit_conflict_warnings = 1
- unlet! g:loaded_syntastic_plugin
- unlet! g:loaded_neomake
- unlet! g:loaded_validator_plugin
-
-Execute(ALE should not warn when nothing extra is installed):
- " Nothing should be thrown when loading the after file.
- source after/plugin/ale.vim
-
-Execute(ALE should warn users when Syntastic is installed):
- let g:loaded_syntastic_plugin = 1
-
- AssertThrows source after/plugin/ale.vim
- AssertEqual
- \ 'ALE conflicts with Syntastic'
- \ . '. Uninstall it, or disable this warning with '
- \ . '`let g:ale_emit_conflict_warnings = 0` in your vimrc file, '
- \ . '*before* plugins are loaded.',
- \ g:vader_exception
-
-Execute(ALE should not warn about Syntastic when the flag is set):
- let g:loaded_syntastic_plugin = 1
- let g:ale_emit_conflict_warnings = 0
-
- source after/plugin/ale.vim
-
-Execute(ALE should warn users when Neomake is installed):
- let g:loaded_neomake = 1
-
- AssertThrows source after/plugin/ale.vim
- AssertEqual
- \ 'ALE conflicts with Neomake'
- \ . '. Uninstall it, or disable this warning with '
- \ . '`let g:ale_emit_conflict_warnings = 0` in your vimrc file, '
- \ . '*before* plugins are loaded.',
- \ g:vader_exception
-
-Execute(ALE should not warn about Neomake when the flag is set):
- let g:loaded_neomake = 1
- let g:ale_emit_conflict_warnings = 0
-
- source after/plugin/ale.vim
-
-Execute(ALE should warn users when Validator is installed):
- let g:loaded_validator_plugin = 1
-
- AssertThrows source after/plugin/ale.vim
- AssertEqual
- \ 'ALE conflicts with Validator'
- \ . '. Uninstall it, or disable this warning with '
- \ . '`let g:ale_emit_conflict_warnings = 0` in your vimrc file, '
- \ . '*before* plugins are loaded.',
- \ g:vader_exception
-
-Execute(ALE should not warn about Validator when the flag is set):
- let g:loaded_validator_plugin = 1
- let g:ale_emit_conflict_warnings = 0
-
- source after/plugin/ale.vim
diff --git a/test/test_elm_executable_detection.vader b/test/test_elm_executable_detection.vader
index 4227cbfa..9146eea6 100644
--- a/test/test_elm_executable_detection.vader
+++ b/test/test_elm_executable_detection.vader
@@ -12,7 +12,7 @@ Execute(should get valid executable with default params):
call ale#test#SetFilename('elm-test-files/app/testfile.elm')
AssertEqual
- \ ale#path#Simplify(g:dir . '/elm-test-files/app/node_modules/.bin/elm-make'),
+ \ ale#path#Simplify(g:dir . '/elm-test-files/app/node_modules/.bin/elm'),
\ ale_linters#elm#make#GetExecutable(bufnr(''))
Execute(should get valid executable with 'use_global' params):
@@ -21,16 +21,16 @@ Execute(should get valid executable with 'use_global' params):
call ale#test#SetFilename('elm-test-files/app/testfile.elm')
AssertEqual
- \ 'elm-make',
+ \ 'elm',
\ ale_linters#elm#make#GetExecutable(bufnr(''))
Execute(should get valid executable with 'use_global' and 'executable' params):
- let g:ale_elm_make_executable = 'other-elm-make'
+ let g:ale_elm_make_executable = 'other-elm'
let g:ale_elm_make_use_global = 1
call ale#test#SetFilename('elm-test-files/app/testfile.elm')
AssertEqual
- \ 'other-elm-make',
+ \ 'other-elm',
\ ale_linters#elm#make#GetExecutable(bufnr(''))
diff --git a/test/test_engine_lsp_response_handling.vader b/test/test_engine_lsp_response_handling.vader
index b3a45b14..3d317e9c 100644
--- a/test/test_engine_lsp_response_handling.vader
+++ b/test/test_engine_lsp_response_handling.vader
@@ -1,5 +1,9 @@
Before:
Save g:ale_buffer_info
+ Save g:ale_lsp_error_messages
+
+ unlet! g:ale_lsp_error_messages
+
call ale#test#SetDirectory('/testplugin/test')
After:
@@ -7,7 +11,9 @@ After:
call ale#test#RestoreDirectory()
call ale#linter#Reset()
+ call ale#engine#ClearLSPData()
+Given foobar(An empty file):
Execute(tsserver syntax error responses should be handled correctly):
runtime ale_linters/typescript/tsserver.vim
call ale#test#SetFilename('filename.ts')
@@ -153,3 +159,20 @@ Execute(tsserver semantic error responses should be handled correctly):
\ [
\ ],
\ getloclist(0)
+
+Execute(LSP errors should be logged in the history):
+ call ale#engine#SetLSPLinterMap({'347': 'foobar'})
+ call ale#engine#HandleLSPResponse(347, {
+ \ 'jsonrpc': '2.0',
+ \ 'error': {
+ \ 'code': -32602,
+ \ 'message': 'xyz',
+ \ 'data': {
+ \ 'traceback': ['123', '456'],
+ \ },
+ \ },
+ \})
+
+ AssertEqual
+ \ {'foobar': ["xyz\n123\n456"]},
+ \ get(g:, 'ale_lsp_error_messages', {})
diff --git a/test/test_go_to_definition.vader b/test/test_go_to_definition.vader
index 5bd75675..6af97099 100644
--- a/test/test_go_to_definition.vader
+++ b/test/test_go_to_definition.vader
@@ -56,6 +56,19 @@ Execute(Failed definition responses should be handled correctly):
\)
AssertEqual {}, ale#definition#GetMap()
+Execute(Failed definition responses with no files should be handled correctly):
+ call ale#definition#SetMap({3: {'open_in_tab': 0}})
+ call ale#definition#HandleTSServerResponse(
+ \ 1,
+ \ {
+ \ 'command': 'definition',
+ \ 'request_seq': 3,
+ \ 'success': v:true,
+ \ 'body': [],
+ \ }
+ \)
+ AssertEqual {}, ale#definition#GetMap()
+
Given typescript(Some typescript file):
foo
somelongerline
diff --git a/test/test_lint_error_delay.vader b/test/test_lint_error_delay.vader
index 05664899..cf73b2c0 100644
--- a/test/test_lint_error_delay.vader
+++ b/test/test_lint_error_delay.vader
@@ -2,7 +2,7 @@ Before:
runtime autoload/ale.vim
" Replace one of the key ALE functions and make it throw.
- function! ale#FileTooLarge() abort
+ function! ale#FileTooLarge(buffer) abort
throw 'broken'
endfunction
@@ -11,6 +11,7 @@ After:
call ale#ResetErrorDelays()
+Given foobar(An empty file):
Execute(ALE should stop queuing for a while after exceptions are thrown):
AssertThrows call ale#Queue(100)
call ale#Queue(100)
diff --git a/test/test_pattern_options.vader b/test/test_pattern_options.vader
index 0e26eaaa..f439afbd 100644
--- a/test/test_pattern_options.vader
+++ b/test/test_pattern_options.vader
@@ -90,3 +90,14 @@ Execute(Patterns should be applied after the Dictionary changes):
call ale#pattern_options#SetOptions(bufnr(''))
AssertEqual 666, b:some_option
+
+Execute(SetOptions should tolerate settings being unset):
+ " This might happen if ALE is loaded in a weird way, so tolerate it.
+ unlet! g:ale_pattern_options
+ unlet! g:ale_pattern_options_enabled
+
+ call ale#pattern_options#SetOptions(bufnr(''))
+
+ let g:ale_pattern_options_enabled = 1
+
+ call ale#pattern_options#SetOptions(bufnr(''))
diff --git a/test/test_should_do_nothing_conditions.vader b/test/test_should_do_nothing_conditions.vader
index 85874e53..062ab875 100644
--- a/test/test_should_do_nothing_conditions.vader
+++ b/test/test_should_do_nothing_conditions.vader
@@ -26,6 +26,7 @@ After:
unlet! b:funky_command_created
+Given foobar(An empty file):
Execute(ALE shouldn't do much of anything for ctrlp-funky buffers):
Assert !ale#ShouldDoNothing(bufnr('')), 'The preliminary check failed'
@@ -43,6 +44,16 @@ Execute(ALE shouldn't try to check buffers with '.' as the filename):
Assert ale#ShouldDoNothing(bufnr(''))
+Execute(DoNothing should return 0 when the filetype is empty):
+ AssertEqual
+ \ 0,
+ \ ale#ShouldDoNothing(bufnr('')),
+ \ 'ShouldDoNothing() was 1 for some other reason'
+
+ set filetype=
+
+ AssertEqual 1, ale#ShouldDoNothing(bufnr(''))
+
Execute(The DoNothing check should work if the ALE globals aren't defined):
unlet! g:ale_filetype_blacklist
unlet! g:ale_maximum_file_size
diff --git a/test/test_temporary_file_management.vader b/test/test_temporary_file_management.vader
index ae2bf251..e248331c 100644
--- a/test/test_temporary_file_management.vader
+++ b/test/test_temporary_file_management.vader
@@ -1,4 +1,7 @@
Before:
+ Save g:ale_buffer_info
+
+ let g:ale_buffer_info = {}
let g:ale_run_synchronously = 1
let g:command = 'echo test'
@@ -41,6 +44,8 @@ Before:
\})
After:
+ Restore
+
if !empty(g:preserved_directory)
call delete(g:preserved_directory, 'rf')
endif
@@ -111,3 +116,17 @@ Execute(ALE should create and delete directories for ale#engine#CreateDirectory(
Assert !isdirectory(b:dir), 'The directory was not deleted'
Assert !isdirectory(b:dir2), 'The second directory was not deleted'
+
+Execute(ale#engine#ManageFile should add the file even if the buffer info hasn't be set yet):
+ let g:ale_buffer_info = {}
+ call ale#engine#ManageFile(bufnr(''), '/foo/bar')
+ AssertEqual
+ \ ['/foo/bar'],
+ \ g:ale_buffer_info[bufnr('')].temporary_file_list
+
+Execute(ale#engine#ManageDirectory should add the directory even if the buffer info hasn't be set yet):
+ let g:ale_buffer_info = {}
+ call ale#engine#ManageDirectory(bufnr(''), '/foo/bar')
+ AssertEqual
+ \ ['/foo/bar'],
+ \ g:ale_buffer_info[bufnr('')].temporary_directory_list
diff --git a/test/test_verilog_verilator_options.vader b/test/test_verilog_verilator_options.vader
index 561786ee..e53037b1 100644
--- a/test/test_verilog_verilator_options.vader
+++ b/test/test_verilog_verilator_options.vader
@@ -22,4 +22,3 @@ Execute(Set Verilog Verilator linter additional options to `-sv --default-langua
\ g:matched ,
\ -1 ,
\ 'Additionnal arguments not found in the run command'
-