summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ale_linters/handlebars/embertemplatelint.vim28
-rw-r--r--ale_linters/php/psalm.vim10
-rw-r--r--ale_linters/python/flake8.vim28
-rw-r--r--ale_linters/vim/vint.vim2
-rw-r--r--autoload/ale.vim2
-rw-r--r--autoload/ale/c.vim7
-rw-r--r--autoload/ale/code_action.vim39
-rw-r--r--autoload/ale/completion.vim13
-rw-r--r--autoload/ale/fix.vim32
-rw-r--r--autoload/ale/handlers/gcc.vim19
-rw-r--r--autoload/ale/util.vim11
-rw-r--r--doc/ale-c.txt16
-rw-r--r--doc/ale-cpp.txt1
-rw-r--r--doc/ale-php.txt45
-rw-r--r--doc/ale-python.txt13
-rw-r--r--doc/ale.txt47
-rw-r--r--test/command_callback/test_flake8_command_callback.vader43
-rw-r--r--test/command_callback/test_psalm_command_callbacks.vader32
-rw-r--r--test/command_callback/test_vint_command_callback.vader2
-rw-r--r--test/completion/test_completion_events.vader2
-rw-r--r--test/ember-template-lint-test-files/app/template.hbs0
-rw-r--r--test/ember-template-lint-test-files/package.json0
-rw-r--r--test/fix/test_ale_fix.vader13
-rw-r--r--test/handler/test_gcc_handler.vader35
-rw-r--r--test/test_c_flag_parsing.vader20
-rw-r--r--test/test_code_action.vader46
-rw-r--r--test/test_cursor_warnings.vader2
-rw-r--r--test/test_embertemplatelint_executable_detection.vader22
-rw-r--r--test/test_list_formatting.vader4
29 files changed, 451 insertions, 83 deletions
diff --git a/ale_linters/handlebars/embertemplatelint.vim b/ale_linters/handlebars/embertemplatelint.vim
index 74bd6a99..31d65b70 100644
--- a/ale_linters/handlebars/embertemplatelint.vim
+++ b/ale_linters/handlebars/embertemplatelint.vim
@@ -4,6 +4,28 @@
call ale#Set('handlebars_embertemplatelint_executable', 'ember-template-lint')
call ale#Set('handlebars_embertemplatelint_use_global', get(g:, 'ale_use_global_executables', 0))
+function! ale_linters#handlebars#embertemplatelint#GetExecutable(buffer) abort
+ return ale#node#FindExecutable(a:buffer, 'handlebars_embertemplatelint', [
+ \ 'node_modules/.bin/ember-template-lint',
+ \])
+endfunction
+
+function! ale_linters#handlebars#embertemplatelint#GetCommand(buffer, version) abort
+ " Reading from stdin was introduced in ember-template-lint@1.6.0
+ return ale#semver#GTE(a:version, [1, 6, 0])
+ \ ? '%e --json --filename %s'
+ \ : '%e --json %t'
+endfunction
+
+function! ale_linters#handlebars#embertemplatelint#GetCommandWithVersionCheck(buffer) abort
+ return ale#semver#RunWithVersionCheck(
+ \ a:buffer,
+ \ ale_linters#handlebars#embertemplatelint#GetExecutable(a:buffer),
+ \ '%e --version',
+ \ function('ale_linters#handlebars#embertemplatelint#GetCommand'),
+ \ )
+endfunction
+
function! ale_linters#handlebars#embertemplatelint#Handle(buffer, lines) abort
let l:output = []
let l:json = ale#util#FuzzyJSONDecode(a:lines, {})
@@ -31,9 +53,7 @@ endfunction
call ale#linter#Define('handlebars', {
\ 'name': 'ember-template-lint',
-\ 'executable': {b -> ale#node#FindExecutable(b, 'handlebars_embertemplatelint', [
-\ 'node_modules/.bin/ember-template-lint',
-\ ])},
-\ 'command': '%e --json %t',
+\ 'executable': function('ale_linters#handlebars#embertemplatelint#GetExecutable'),
+\ 'command': function('ale_linters#handlebars#embertemplatelint#GetCommandWithVersionCheck'),
\ 'callback': 'ale_linters#handlebars#embertemplatelint#Handle',
\})
diff --git a/ale_linters/php/psalm.vim b/ale_linters/php/psalm.vim
index ab4dbbc9..286c8a96 100644
--- a/ale_linters/php/psalm.vim
+++ b/ale_linters/php/psalm.vim
@@ -1,9 +1,9 @@
" Author: Matt Brown <https://github.com/muglug>
" Description: plugin for Psalm, static analyzer for PHP
-call ale#Set('psalm_langserver_executable', 'psalm')
-call ale#Set('psalm_langserver_options', '')
-call ale#Set('psalm_langserver_use_global', get(g:, 'ale_use_global_executables', 0))
+call ale#Set('php_psalm_executable', 'psalm')
+call ale#Set('php_psalm_options', '')
+call ale#Set('php_psalm_use_global', get(g:, 'ale_use_global_executables', 0))
function! ale_linters#php#psalm#GetProjectRoot(buffer) abort
let l:git_path = ale#path#FindNearestDirectory(a:buffer, '.git')
@@ -12,13 +12,13 @@ function! ale_linters#php#psalm#GetProjectRoot(buffer) abort
endfunction
function! ale_linters#php#psalm#GetCommand(buffer) abort
- return '%e --language-server' . ale#Pad(ale#Var(a:buffer, 'psalm_langserver_options'))
+ return '%e --language-server' . ale#Pad(ale#Var(a:buffer, 'php_psalm_options'))
endfunction
call ale#linter#Define('php', {
\ 'name': 'psalm',
\ 'lsp': 'stdio',
-\ 'executable': {b -> ale#node#FindExecutable(b, 'psalm_langserver', [
+\ 'executable': {b -> ale#node#FindExecutable(b, 'php_psalm', [
\ 'vendor/bin/psalm',
\ ])},
\ 'command': function('ale_linters#php#psalm#GetCommand'),
diff --git a/ale_linters/python/flake8.vim b/ale_linters/python/flake8.vim
index e2e7b743..fc4ab692 100644
--- a/ale_linters/python/flake8.vim
+++ b/ale_linters/python/flake8.vim
@@ -4,7 +4,7 @@
call ale#Set('python_flake8_executable', 'flake8')
call ale#Set('python_flake8_options', '')
call ale#Set('python_flake8_use_global', get(g:, 'ale_use_global_executables', 0))
-call ale#Set('python_flake8_change_directory', 1)
+call ale#Set('python_flake8_change_directory', 'project')
call ale#Set('python_flake8_auto_pipenv', 0)
function! s:UsingModule(buffer) abort
@@ -38,10 +38,30 @@ function! ale_linters#python#flake8#RunWithVersionCheck(buffer) abort
\)
endfunction
+function! ale_linters#python#flake8#GetCdString(buffer) abort
+ let l:change_directory = ale#Var(a:buffer, 'python_flake8_change_directory')
+ let l:cd_string = ''
+
+ if l:change_directory is# 'project'
+ let l:project_root = ale#python#FindProjectRootIni(a:buffer)
+
+ if !empty(l:project_root)
+ let l:cd_string = ale#path#CdString(l:project_root)
+ endif
+ endif
+
+ if (l:change_directory is# 'project' && empty(l:cd_string))
+ \|| l:change_directory is# 1
+ \|| l:change_directory is# 'file'
+ let l:cd_string = ale#path#BufferCdString(a:buffer)
+ endif
+
+ return l:cd_string
+endfunction
+
function! ale_linters#python#flake8#GetCommand(buffer, version) abort
- let l:cd_string = ale#Var(a:buffer, 'python_flake8_change_directory')
- \ ? ale#path#BufferCdString(a:buffer)
- \ : ''
+ let l:cd_string = ale_linters#python#flake8#GetCdString(a:buffer)
+
let l:executable = ale_linters#python#flake8#GetExecutable(a:buffer)
let l:exec_args = l:executable =~? 'pipenv$'
diff --git a/ale_linters/vim/vint.vim b/ale_linters/vim/vint.vim
index 65e19126..c7461bc8 100644
--- a/ale_linters/vim/vint.vim
+++ b/ale_linters/vim/vint.vim
@@ -5,7 +5,7 @@
call ale#Set('vim_vint_show_style_issues', 1)
call ale#Set('vim_vint_executable', 'vint')
let s:enable_neovim = has('nvim') ? ' --enable-neovim' : ''
-let s:format = '-f "{file_path}:{line_number}:{column_number}: {severity}: {description} (see {reference})"'
+let s:format = '-f "{file_path}:{line_number}:{column_number}: {severity}: {policy_name} - {description} (see {reference})"'
function! ale_linters#vim#vint#GetCommand(buffer, version) abort
let l:can_use_no_color_flag = empty(a:version)
diff --git a/autoload/ale.vim b/autoload/ale.vim
index b75c9fc9..5ec22f57 100644
--- a/autoload/ale.vim
+++ b/autoload/ale.vim
@@ -263,6 +263,8 @@ function! ale#GetLocItemMessage(item, format_string) abort
let l:msg = substitute(l:msg, '\V%linter%', '\=l:linter_name', 'g')
" Replace %s with the text.
let l:msg = substitute(l:msg, '\V%s', '\=a:item.text', 'g')
+ " Windows may insert carriage return line endings (^M), strip these characters.
+ let l:msg = substitute(l:msg, '\r', '', 'g')
return l:msg
endfunction
diff --git a/autoload/ale/c.vim b/autoload/ale/c.vim
index d0a4fa06..cff53125 100644
--- a/autoload/ale/c.vim
+++ b/autoload/ale/c.vim
@@ -2,7 +2,9 @@
" Description: Functions for integrating with C-family linters.
call ale#Set('c_parse_makefile', 0)
+call ale#Set('c_always_make', has('unix') && !has('macunix'))
call ale#Set('c_parse_compile_commands', 1)
+
let s:sep = has('win32') ? '\' : '/'
" Set just so tests can override it.
@@ -504,7 +506,10 @@ function! ale#c#GetMakeCommand(buffer) abort
let l:path = ale#path#FindNearestFile(a:buffer, 'Makefile')
if !empty(l:path)
- return ale#path#CdString(fnamemodify(l:path, ':h')) . 'make -n'
+ let l:always_make = ale#Var(a:buffer, 'c_always_make')
+
+ return ale#path#CdString(fnamemodify(l:path, ':h'))
+ \ . 'make -n' . (l:always_make ? ' --always-make' : '')
endif
endif
diff --git a/autoload/ale/code_action.vim b/autoload/ale/code_action.vim
index 60c3bbef..8c7263f3 100644
--- a/autoload/ale/code_action.vim
+++ b/autoload/ale/code_action.vim
@@ -24,6 +24,42 @@ function! ale#code_action#HandleCodeAction(code_action, should_save) abort
endfor
endfunction
+function! s:ChangeCmp(left, right) abort
+ if a:left.start.line < a:right.start.line
+ return -1
+ endif
+
+ if a:left.start.line > a:right.start.line
+ return 1
+ endif
+
+ if a:left.start.offset < a:right.start.offset
+ return -1
+ endif
+
+ if a:left.start.offset > a:right.start.offset
+ return 1
+ endif
+
+ if a:left.end.line < a:right.end.line
+ return -1
+ endif
+
+ if a:left.end.line > a:right.end.line
+ return 1
+ endif
+
+ if a:left.end.offset < a:right.end.offset
+ return -1
+ endif
+
+ if a:left.end.offset > a:right.end.offset
+ return 1
+ endif
+
+ return 0
+endfunction
+
function! ale#code_action#ApplyChanges(filename, changes, should_save) abort
let l:current_buffer = bufnr('')
" The buffer is used to determine the fileformat, if available.
@@ -48,7 +84,8 @@ function! ale#code_action#ApplyChanges(filename, changes, should_save) abort
let l:column_offset = 0
let l:last_end_line = 0
- for l:code_edit in a:changes
+ " Changes have to be sorted so we apply them from top-to-bottom.
+ for l:code_edit in sort(copy(a:changes), function('s:ChangeCmp'))
if l:code_edit.start.line isnot l:last_end_line
let l:column_offset = 0
endif
diff --git a/autoload/ale/completion.vim b/autoload/ale/completion.vim
index f6a0c350..c2cfd74a 100644
--- a/autoload/ale/completion.vim
+++ b/autoload/ale/completion.vim
@@ -5,7 +5,7 @@ scriptencoding utf-8
" The omnicompletion menu is shown through a special Plug mapping which is
" only valid in Insert mode. This way, feedkeys() won't send these keys if you
" quit Insert mode quickly enough.
-inoremap <silent> <Plug>(ale_show_completion_menu) <C-x><C-o>
+inoremap <silent> <Plug>(ale_show_completion_menu) <C-x><C-o><C-p>
" If we hit the key sequence in normal mode, then we won't show the menu, so
" we should restore the old settings right away.
nnoremap <silent> <Plug>(ale_show_completion_menu) :call ale#completion#RestoreCompletionOptions()<CR>
@@ -324,6 +324,12 @@ function! ale#completion#AutomaticOmniFunc(findstart, base) abort
endif
endfunction
+function! s:OpenCompletionMenu(...) abort
+ if !&l:paste
+ call ale#util#FeedKeys("\<Plug>(ale_show_completion_menu)")
+ endif
+endfunction
+
function! ale#completion#Show(result) abort
if ale#util#Mode() isnot# 'i'
return
@@ -344,10 +350,7 @@ function! ale#completion#Show(result) abort
let l:source = get(get(b:, 'ale_completion_info', {}), 'source', '')
if l:source is# 'ale-automatic' || l:source is# 'ale-manual'
- call timer_start(
- \ 0,
- \ {-> ale#util#FeedKeys("\<Plug>(ale_show_completion_menu)")}
- \)
+ call timer_start(0, function('s:OpenCompletionMenu'))
endif
if l:source is# 'ale-callback'
diff --git a/autoload/ale/fix.vim b/autoload/ale/fix.vim
index 3ad0a433..8b841b13 100644
--- a/autoload/ale/fix.vim
+++ b/autoload/ale/fix.vim
@@ -15,22 +15,29 @@ function! ale#fix#ApplyQueuedFixes(buffer) abort
call remove(g:ale_fix_buffer_data, a:buffer)
- if l:data.changes_made
- let l:new_lines = ale#util#SetBufferContents(a:buffer, l:data.output)
-
- if l:data.should_save
- if a:buffer is bufnr('')
- if empty(&buftype)
- noautocmd :w!
+ try
+ if l:data.changes_made
+ let l:new_lines = ale#util#SetBufferContents(a:buffer, l:data.output)
+
+ if l:data.should_save
+ if a:buffer is bufnr('')
+ if empty(&buftype)
+ noautocmd :w!
+ else
+ set nomodified
+ endif
else
- set nomodified
+ call writefile(l:new_lines, expand('#' . a:buffer . ':p')) " no-custom-checks
+ call setbufvar(a:buffer, '&modified', 0)
endif
- else
- call writefile(l:new_lines, expand('#' . a:buffer . ':p')) " no-custom-checks
- call setbufvar(a:buffer, '&modified', 0)
endif
endif
- endif
+ catch /E21/
+ " If we cannot modify the buffer now, try again later.
+ let g:ale_fix_buffer_data[a:buffer] = l:data
+
+ return
+ endtry
if l:data.should_save
let l:should_lint = ale#Var(a:buffer, 'fix_on_save')
@@ -376,3 +383,4 @@ endfunction
augroup ALEBufferFixGroup
autocmd!
autocmd BufEnter * call ale#fix#ApplyQueuedFixes(str2nr(expand('<abuf>')))
+augroup END
diff --git a/autoload/ale/handlers/gcc.vim b/autoload/ale/handlers/gcc.vim
index ec16b977..0b37c98a 100644
--- a/autoload/ale/handlers/gcc.vim
+++ b/autoload/ale/handlers/gcc.vim
@@ -10,7 +10,7 @@ let s:pragma_error = '#pragma once in main file'
" <stdin>:8:5: warning: conversion lacks type at end of format [-Wformat=]
" <stdin>:10:27: error: invalid operands to binary - (have ‘int’ and ‘char *’)
" -:189:7: note: $/${} is unnecessary on arithmetic variables. [SC2004]
-let s:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+):(\d+)?:? ([^:]+): (.+)$'
+let s:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+)?:?(\d+)?:? ([^:]+): (.+)$'
let s:inline_pattern = '\v inlined from .* at \<stdin\>:(\d+):(\d+):$'
function! s:IsHeaderFile(filename) abort
@@ -117,6 +117,23 @@ function! ale#handlers#gcc#HandleGCCFormat(buffer, lines) abort
if !empty(l:output)
if !has_key(l:output[-1], 'detail')
let l:output[-1].detail = l:output[-1].text
+
+ " handle macro expansion errors/notes
+ if l:match[5] =~? '^in expansion of macro ‘\w*\w’$'
+ " if the macro expansion is in the file we're in, add
+ " the lnum and col keys to the previous error
+ if l:match[1] is# '<stdin>'
+ \ && !has_key(l:output[-1], 'col')
+ let l:output[-1].lnum = str2nr(l:match[2])
+ let l:output[-1].col = str2nr(l:match[3])
+ else
+ " the error is not in the current file, and since
+ " macro expansion errors don't show the full path to
+ " the error from the current file, we have to just
+ " give out a generic error message
+ let l:output[-1].text = 'Error found in macro expansion. See :ALEDetail'
+ endif
+ endif
endif
let l:output[-1].detail = l:output[-1].detail . "\n"
diff --git a/autoload/ale/util.vim b/autoload/ale/util.vim
index 05f11993..1f396377 100644
--- a/autoload/ale/util.vim
+++ b/autoload/ale/util.vim
@@ -505,13 +505,6 @@ function! ale#util#SetBufferContents(buffer, lines) abort
\ : a:lines
let l:first_line_to_remove = len(l:new_lines) + 1
- " We'll temporarily make a buffer modifiable, to force edits.
- let l:modifiable = getbufvar(a:buffer, '&modifiable')
-
- if !l:modifiable
- call setbufvar(a:buffer, '&modifiable', 1)
- endif
-
" Use a Vim API for setting lines in other buffers, if available.
if l:has_bufline_api
call setbufline(a:buffer, 1, l:new_lines)
@@ -530,9 +523,5 @@ function! ale#util#SetBufferContents(buffer, lines) abort
call setline(1, l:new_lines)
endif
- if !l:modifiable
- call setbufvar(a:buffer, '&modifiable', 0)
- endif
-
return l:new_lines
endfunction
diff --git a/doc/ale-c.txt b/doc/ale-c.txt
index fe28cf4a..b0d94b8e 100644
--- a/doc/ale-c.txt
+++ b/doc/ale-c.txt
@@ -8,6 +8,17 @@ runs either `clang`, or `gcc`. See |ale-c-cc|.
===============================================================================
Global Options
+g:ale_c_always_make *g:ale_c_always_make*
+ *b:ale_c_always_make*
+ Type: |Number|
+ Default: `has('unix') && !has('macunix')`
+
+ If set to `1`, use `--always-make` for `make`, which means that output will
+ always be parsed from `make` dry runs with GNU make. BSD `make` does not
+ support this option, so you probably want to turn this option off when using
+ a BSD variant.
+
+
g:ale_c_build_dir_names *g:ale_c_build_dir_names*
*b:ale_c_build_dir_names*
@@ -58,6 +69,11 @@ g:ale_c_parse_makefile *g:ale_c_parse_makefile*
set for C or C++ compilers. This can make it easier to determine the correct
build flags to use for different files.
+ NOTE: When using this option on BSD, you may need to set
+ |g:ale_c_always_make| to `0`, and `make -n` will not provide consistent
+ results if binaries have already been built, so use `make clean` when
+ editing your files.
+
WARNING: Running `make -n` automatically can execute arbitrary code, even
though it's supposed to be a dry run, so enable this option with care. You
might prefer to use the buffer-local version of the option instead with
diff --git a/doc/ale-cpp.txt b/doc/ale-cpp.txt
index 651b4160..17894e6e 100644
--- a/doc/ale-cpp.txt
+++ b/doc/ale-cpp.txt
@@ -10,6 +10,7 @@ Global Options
The following C options also apply to some C++ linters too.
+* |g:ale_c_always_make|
* |g:ale_c_build_dir_names|
* |g:ale_c_build_dir|
* |g:ale_c_parse_makefile|
diff --git a/doc/ale-php.txt b/doc/ale-php.txt
index 645decd7..9fe868f8 100644
--- a/doc/ale-php.txt
+++ b/doc/ale-php.txt
@@ -189,42 +189,55 @@ g:ale_php_psalm_executable *g:ale_php_psalm_executable*
This variable sets the executable used for psalm.
-g:ale_psalm_langserver_options *g:ale_psalm_langserver_options*
- *b:ale_psalm_langserver_options*
+
+g:ale_php_psalm_options *g:ale_php_psalm_options*
+ *b:ale_php_psalm_options*
Type: |String|
Default: `''`
This variable can be set to pass additional options to psalm.
+
+g:ale_php_psalm_use_global *g:ale_php_psalm_use_global*
+ *b:ale_php_psalm_use_global*
+ Type: |Boolean|
+ Default: `get(g:, 'ale_use_global_executables', 0)`
+
+ See |ale-integrations-local-executables|
+
+
===============================================================================
-php-cs-fixer *ale-php-php-cs-fixer*
+php-cs-fixer *ale-php-php-cs-fixer*
-g:ale_php_cs_fixer_executable *g:ale_php_cs_fixer_executable*
- *b:ale_php_cs_fixer_executable*
+g:ale_php_cs_fixer_executable *g:ale_php_cs_fixer_executable*
+ *b:ale_php_cs_fixer_executable*
Type: |String|
Default: `'php-cs-fixer'`
This variable sets executable used for php-cs-fixer.
-g:ale_php_cs_fixer_use_global *g:ale_php_cs_fixer_use_global*
- *b:ale_php_cs_fixer_use_global*
- Type: |Boolean|
- Default: `get(g:, 'ale_use_global_executables', 0)`
-
- This variable force globally installed fixer.
-g:ale_php_cs_fixer_options *g:ale_php_cs_fixer_options*
- *b:ale_php_cs_fixer_options*
+g:ale_php_cs_fixer_options *g:ale_php_cs_fixer_options*
+ *b:ale_php_cs_fixer_options*
Type: |String|
Default: `''`
This variable can be set to pass additional options to php-cs-fixer.
+
+g:ale_php_cs_fixer_use_global *g:ale_php_cs_fixer_use_global*
+ *b:ale_php_cs_fixer_use_global*
+ Type: |Boolean|
+ Default: `get(g:, 'ale_use_global_executables', 0)`
+
+ See |ale-integrations-local-executables|
+
+
===============================================================================
-php *ale-php-php*
+php *ale-php-php*
-g:ale_php_php_executable *g:ale_php_php_executable*
- *b:ale_php_php_executable*
+g:ale_php_php_executable *g:ale_php_php_executable*
+ *b:ale_php_php_executable*
Type: |String|
Default: `'php'`
diff --git a/doc/ale-python.txt b/doc/ale-python.txt
index 60b0771d..6b1a6d33 100644
--- a/doc/ale-python.txt
+++ b/doc/ale-python.txt
@@ -169,13 +169,14 @@ 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`
+ Type: |String|
+ Default: `project`
- 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.
+ If set to `project`, ALE will switch to the project root before checking file.
+ If set to `file`, ALE will switch to directory the Python file being
+ checked with `flake8` is in before checking it.
+ You can turn it off with `off` option if you want to control the directory
+ Python is executed from yourself.
g:ale_python_flake8_executable *g:ale_python_flake8_executable*
diff --git a/doc/ale.txt b/doc/ale.txt
index f3b83df3..472c4852 100644
--- a/doc/ale.txt
+++ b/doc/ale.txt
@@ -463,12 +463,56 @@ is loaded. The delay for completion can be configured with
|g:ale_completion_delay|. This setting should not be enabled if you wish to
use ALE as a completion source for other plugins.
+ALE automatic completion will not work when 'paste' is active. Only set
+'paste' when you are copy and pasting text into your buffers.
+
+ALE automatic completion will interfere with default insert completion with
+`CTRL-N` and so on (|compl-vim|). You can write your own keybinds and a
+function in your |vimrc| file to force insert completion instead, like so: >
+
+ function! SmartInsertCompletion() abort
+ " Use the default CTRL-N in completion menus
+ if pumvisible()
+ return "\<C-n>"
+ endif
+
+ " Exit and re-enter insert mode, and use insert completion
+ return "\<C-c>a\<C-n>"
+ endfunction
+
+ inoremap <silent> <C-n> <C-R>=SmartInsertCompletion()<CR>
+<
ALE provides an 'omnifunc' function |ale#completion#OmniFunc| for triggering
completion manually with CTRL-X CTRL-O. |i_CTRL-X_CTRL-O| >
" Use ALE's function for omnicompletion.
set omnifunc=ale#completion#OmniFunc
<
+ *ale-completion-fallback*
+
+You can write your own completion function and fallback on other methods of
+completion by checking if there are no results that ALE can determine. For
+example, for Python code, you could fall back on the `python3complete`
+function. >
+
+ function! TestCompletionFunc(findstart, base) abort
+ let l:result = ale#completion#OmniFunc(a:findstart, a:base)
+
+ " Check if ALE couldn't find anything.
+ if (a:findstart && l:result is -3)
+ \|| (!a:findstart && empty(l:result))
+ " Defer to another omnifunc if ALE couldn't find anything.
+ return python3complete#Complete(a:findstart, a:base)
+ endif
+
+ return l:result
+ endfunction
+
+ set omnifunc=TestCompletionFunc
+<
+See |complete-functions| for documentation on how to write completion
+functions.
+
ALE will only suggest so many possible matches for completion. The maximum
number of items can be controlled with |g:ale_completion_max_suggestions|.
@@ -729,6 +773,9 @@ g:ale_completion_enabled *g:ale_completion_enabled*
This setting should not be enabled if you wish to use ALE as a completion
source for other completion plugins.
+ ALE automatic completion will not work when 'paste' is active. Only set
+ 'paste' when you are copy and pasting text into your buffers.
+
A buffer-local version of this setting `b:ale_completion_enabled` can be set
to `0` to disable ALE's automatic completion support for a single buffer.
ALE's completion support must be enabled globally to be enabled locally.
diff --git a/test/command_callback/test_flake8_command_callback.vader b/test/command_callback/test_flake8_command_callback.vader
index f082a63a..09f64ee3 100644
--- a/test/command_callback/test_flake8_command_callback.vader
+++ b/test/command_callback/test_flake8_command_callback.vader
@@ -34,13 +34,52 @@ Execute(The flake8 callbacks should return the correct default values):
\]
Execute(The option for disabling changing directories should work):
- let g:ale_python_flake8_change_directory = 0
+ let g:ale_python_flake8_change_directory = 'off'
AssertLinter 'flake8', [
\ ale#Escape('flake8') . ' --version',
\ ale#Escape('flake8') . ' --format=default --stdin-display-name %s -',
\]
+ let g:ale_python_flake8_change_directory = 0
+
+ AssertLinter 'flake8', [
+ \ ale#Escape('flake8') . ' --format=default --stdin-display-name %s -',
+ \]
+
+ " Invalid options should be considered the same as turning the setting off.
+ let g:ale_python_flake8_change_directory = 'xxx'
+
+ AssertLinter 'flake8', [
+ \ ale#Escape('flake8') . ' --format=default --stdin-display-name %s -',
+ \]
+
+Execute(The option for changing directory to project root should work):
+ silent execute 'file ' . fnameescape(g:dir . '/python_paths/namespace_package_tox/namespace/foo/bar.py')
+
+ AssertLinter 'flake8', [
+ \ ale#Escape('flake8') . ' --version',
+ \ ale#path#CdString(ale#python#FindProjectRootIni(bufnr('')))
+ \ . ale#Escape('flake8') . ' --format=default --stdin-display-name %s -',
+ \]
+
+Execute(The option for changing directory to file dir should work):
+ let g:ale_python_flake8_change_directory = 'file'
+ silent execute 'file ' . fnameescape(g:dir . '/python_paths/namespace_package_tox/namespace/foo/bar.py')
+
+ AssertLinter 'flake8', [
+ \ ale#Escape('flake8') . ' --version',
+ \ ale#path#BufferCdString(bufnr(''))
+ \ . ale#Escape('flake8') . ' --format=default --stdin-display-name %s -',
+ \]
+
+ let g:ale_python_flake8_change_directory = 1
+
+ AssertLinter 'flake8', [
+ \ ale#path#BufferCdString(bufnr(''))
+ \ . ale#Escape('flake8') . ' --format=default --stdin-display-name %s -',
+ \]
+
Execute(The flake8 command callback should let you set options):
let g:ale_python_flake8_options = '--some-option'
@@ -163,5 +202,5 @@ Execute(Pipenv is detected when python_flake8_auto_pipenv is set):
call ale#test#SetFilename('../python_fixtures/pipenv/whatever.py')
AssertLinter 'pipenv',
- \ ale#path#BufferCdString(bufnr(''))
+ \ ale#path#CdString(ale#python#FindProjectRootIni(bufnr('')))
\ . ale#Escape('pipenv') . ' run flake8 --format=default --stdin-display-name %s -'
diff --git a/test/command_callback/test_psalm_command_callbacks.vader b/test/command_callback/test_psalm_command_callbacks.vader
index 70b5af95..d32780e6 100644
--- a/test/command_callback/test_psalm_command_callbacks.vader
+++ b/test/command_callback/test_psalm_command_callbacks.vader
@@ -2,6 +2,9 @@ Before:
call ale#assert#SetUpLinterTest('php', 'psalm')
After:
+ unlet! g:i
+ unlet! g:matched
+
if isdirectory(g:dir . '/.git')
call delete(g:dir . '/.git', 'd')
endif
@@ -22,19 +25,36 @@ Execute(Vendor executables should be detected):
\ . '/psalm-project/vendor/bin/psalm'
\ )) . ' --language-server'
+ let g:ale_php_psalm_use_global = 1
+
+ AssertLinter 'psalm',
+ \ ale#Escape('psalm') . ' --language-server'
+
Execute(User provided options should be used):
- let g:ale_psalm_langserver_options = '--my-user-provided-option my-value'
+ let g:ale_php_psalm_options = '--my-user-provided-option my-value'
AssertLinter 'psalm',
\ ale#Escape('psalm')
\ . ' --language-server --my-user-provided-option my-value'
-
Execute(The project path should be correct for .git directories):
call ale#test#SetFilename('psalm-project/test.php')
+ let g:matched = 0
- if !isdirectory(g:dir . '/.git')
- call mkdir(g:dir . '/.git')
- endif
+ for g:i in range(4)
+ if !isdirectory(g:dir . '/.git')
+ call mkdir(g:dir . '/.git')
+ endif
+
+ try
+ AssertLSPProject g:dir
+ catch /.+/
+ endtry
- AssertLSPProject g:dir
+ let g:matched = 1
+ break
+ endfor
+
+ if !g:matched
+ AssertLSPProject g:dir
+ endif
diff --git a/test/command_callback/test_vint_command_callback.vader b/test/command_callback/test_vint_command_callback.vader
index e0051f26..4ce277e8 100644
--- a/test/command_callback/test_vint_command_callback.vader
+++ b/test/command_callback/test_vint_command_callback.vader
@@ -1,7 +1,7 @@
Before:
call ale#assert#SetUpLinterTest('vim', 'vint')
let b:command_tail = (has('nvim') ? ' --enable-neovim' : '')
- \ . ' -f "{file_path}:{line_number}:{column_number}: {severity}: {description} (see {reference})" %t'
+ \ . ' -f "{file_path}:{line_number}:{column_number}: {severity}: {policy_name} - {description} (see {reference})" %t'
After:
unlet! b:bin_dir
diff --git a/test/completion/test_completion_events.vader b/test/completion/test_completion_events.vader
index 3a7a31d0..87bd10ad 100644
--- a/test/completion/test_completion_events.vader
+++ b/test/completion/test_completion_events.vader
@@ -35,7 +35,7 @@ Before:
let g:ale_completion_delay = 0
" Run this check a few times, as it can fail randomly.
- for g:i in range(has('nvim-0.3') || has('win32') ? 5 : 1)
+ for l:i in range(has('nvim-0.3') || has('win32') ? 5 : 1)
call ale#completion#Queue()
sleep 1m
diff --git a/test/ember-template-lint-test-files/app/template.hbs b/test/ember-template-lint-test-files/app/template.hbs
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/test/ember-template-lint-test-files/app/template.hbs
diff --git a/test/ember-template-lint-test-files/package.json b/test/ember-template-lint-test-files/package.json
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/test/ember-template-lint-test-files/package.json
diff --git a/test/fix/test_ale_fix.vader b/test/fix/test_ale_fix.vader
index e8a9dd7a..a51a5a53 100644
--- a/test/fix/test_ale_fix.vader
+++ b/test/fix/test_ale_fix.vader
@@ -727,6 +727,19 @@ Expect(There should be only two lines):
a
b
+Execute(ALEFix should modify a buffer that is not modifiable, if it becomes modifiable later):
+ let g:ale_fixers.testft = ['RemoveLastLineOneArg']
+
+ set nomodifiable
+ ALEFix
+ call ale#test#FlushJobs()
+ set modifiable
+ call ale#fix#ApplyQueuedFixes(bufnr(''))
+
+Expect(There should be only two lines):
+ a
+ b
+
Execute(b:ale_fix_on_save = 1 should override g:ale_fix_on_save = 0):
let g:ale_fix_on_save = 0
let b:ale_fix_on_save = 1
diff --git a/test/handler/test_gcc_handler.vader b/test/handler/test_gcc_handler.vader
index b67483a6..a4231cab 100644
--- a/test/handler/test_gcc_handler.vader
+++ b/test/handler/test_gcc_handler.vader
@@ -279,3 +279,38 @@ Execute(The GCC handler should handle errors for inlined header functions):
\ ' __open_too_many_args ();',
\ ' ^~~~~~~~~~~~~~~~~~~~~~~',
\ ])
+
+Execute(The GCC handler should handle macro expansion errors in current file):
+ AssertEqual
+ \ [
+ \ {
+ \ 'lnum': 1,
+ \ 'col': 19,
+ \ 'type': 'E',
+ \ 'text': 'error message',
+ \ 'detail': "error message\n<stdin>:1:19: note: in expansion of macro 'TEST'",
+ \ },
+ \ ],
+ \ ale#handlers#gcc#HandleGCCFormatWithIncludes(347, [
+ \ '<command-line>: error: error message',
+ \ '<stdin>:1:19: note: in expansion of macro ‘TEST’',
+ \ ' 1 | std::string str = TEST;',
+ \ ' | ^~~~',
+ \ ])
+
+Execute(The GCC handler should handle macro expansion errors in other files):
+ AssertEqual
+ \ [
+ \ {
+ \ 'lnum': 0,
+ \ 'type': 'E',
+ \ 'text': 'Error found in macro expansion. See :ALEDetail',
+ \ 'detail': "error message\ninc.h:1:19: note: in expansion of macro 'TEST'",
+ \ },
+ \ ],
+ \ ale#handlers#gcc#HandleGCCFormatWithIncludes(347, [
+ \ '<command-line>: error: error message',
+ \ 'inc.h:1:19: note: in expansion of macro ‘TEST’',
+ \ ' 1 | std::string str = TEST;',
+ \ ' | ^~~~',
+ \ ])
diff --git a/test/test_c_flag_parsing.vader b/test/test_c_flag_parsing.vader
index 076be6a1..99722b17 100644
--- a/test/test_c_flag_parsing.vader
+++ b/test/test_c_flag_parsing.vader
@@ -1,9 +1,13 @@
Before:
Save g:ale_c_parse_makefile
+ Save g:ale_c_always_make
+ Save b:ale_c_always_make
call ale#test#SetDirectory('/testplugin/test')
let g:ale_c_parse_makefile = 1
+ let g:ale_c_always_make = 1
+ let b:ale_c_always_make = 1
function SplitAndParse(path_prefix, command) abort
let l:args = ale#c#ShellSplit(a:command)
@@ -18,6 +22,22 @@ After:
call ale#test#RestoreDirectory()
+Execute(The make command should be correct):
+ call ale#test#SetFilename('test_c_projects/makefile_project/subdir/file.c')
+
+ AssertEqual
+ \ ale#path#CdString(ale#path#Simplify(g:dir. '/test_c_projects/makefile_project'))
+ \ . 'make -n --always-make',
+ \ ale#c#GetMakeCommand(bufnr(''))
+
+ " You should be able to disable --always-make for a buffer.
+ let b:ale_c_always_make = 0
+
+ AssertEqual
+ \ ale#path#CdString(ale#path#Simplify(g:dir. '/test_c_projects/makefile_project'))
+ \ . 'make -n',
+ \ ale#c#GetMakeCommand(bufnr(''))
+
Execute(The CFlags parser should be able to parse include directives):
call ale#test#SetFilename('test_c_projects/makefile_project/subdir/file.c')
diff --git a/test/test_code_action.vader b/test/test_code_action.vader
index b47f24ff..19de7268 100644
--- a/test/test_code_action.vader
+++ b/test/test_code_action.vader
@@ -1,4 +1,8 @@
Before:
+ Save g:ale_enabled
+
+ let g:ale_enabled = 0
+
runtime autoload/ale/code_action.vim
runtime autoload/ale/util.vim
@@ -35,6 +39,8 @@ Before:
endfunction!
After:
+ Restore
+
" Close the extra buffers if we opened it.
if bufnr(g:file1) != -1
execute ':bp! | :bd! ' . bufnr(g:file1)
@@ -50,9 +56,10 @@ After:
call delete(g:file2)
endif
- unlet g:file1
- unlet g:file2
- unlet g:test
+ unlet! g:file1
+ unlet! g:file2
+ unlet! g:test
+ unlet! g:changes
delfunction WriteFileAndEdit
runtime autoload/ale/code_action.vim
@@ -350,3 +357,36 @@ Execute(It should just modify file when should_save is set to v:false):
\ ' value: string',
\ '}',
\], getline(1, '$')
+
+Given typescript(An example TypeScript file):
+ type Foo = {}
+
+ export interface ISomething {
+ fooLongName: Foo | null
+ }
+
+ export class SomethingElse implements ISomething {
+ // Bindings
+ fooLongName!: ISomething['fooLongName']
+ }
+
+Execute():
+ let g:changes = [
+ \ {'end': {'offset': 14, 'line': 4}, 'newText': 'foo', 'start': {'offset': 3, 'line': 4}},
+ \ {'end': {'offset': 40, 'line': 9}, 'newText': 'foo', 'start': {'offset': 29, 'line': 9}},
+ \ {'end': {'offset': 14, 'line': 9}, 'newText': 'foo', 'start': {'offset': 3, 'line': 9}},
+ \]
+
+ call ale#code_action#ApplyChanges(expand('%:p'), g:changes, 0)
+
+Expect(The changes should be applied correctly):
+ type Foo = {}
+
+ export interface ISomething {
+ foo: Foo | null
+ }
+
+ export class SomethingElse implements ISomething {
+ // Bindings
+ foo!: ISomething['foo']
+ }
diff --git a/test/test_cursor_warnings.vader b/test/test_cursor_warnings.vader
index 339cd71e..ef385061 100644
--- a/test/test_cursor_warnings.vader
+++ b/test/test_cursor_warnings.vader
@@ -30,7 +30,7 @@ Before:
\ 'nr': -1,
\ 'type': 'E',
\ 'code': 'semi',
- \ 'text': 'Missing semicolon.',
+ \ 'text': "Missing semicolon.\r",
\ 'detail': "Every statement should end with a semicolon\nsecond line",
\ },
\ {
diff --git a/test/test_embertemplatelint_executable_detection.vader b/test/test_embertemplatelint_executable_detection.vader
new file mode 100644
index 00000000..bd0f5dd9
--- /dev/null
+++ b/test/test_embertemplatelint_executable_detection.vader
@@ -0,0 +1,22 @@
+Before:
+ call ale#test#SetDirectory('/testplugin/test')
+
+ runtime ale_linters/handlebars/embertemplatelint.vim
+
+After:
+ call ale#test#RestoreDirectory()
+ call ale#linter#Reset()
+
+Execute(ember-template-lint executables runs the right command):
+ call ale#test#SetFilename('ember-template-lint-test-files/app/template.hbs')
+
+ AssertEqual
+ \ ale_linters#handlebars#embertemplatelint#GetCommand(bufnr(''), [2, 0, 0]),
+ \ '%e --json --filename %s'
+
+Execute(old ember-template-lint executables runs the right command):
+ call ale#test#SetFilename('ember-template-lint-test-files/app/template.hbs')
+
+ AssertEqual
+ \ ale_linters#handlebars#embertemplatelint#GetCommand(bufnr(''), [1, 5, 0]),
+ \ '%e --json %t'
diff --git a/test/test_list_formatting.vader b/test/test_list_formatting.vader
index dcefac53..d79a664b 100644
--- a/test/test_list_formatting.vader
+++ b/test/test_list_formatting.vader
@@ -36,7 +36,7 @@ After:
call setqflist([])
Execute(Formatting with codes should work for the loclist):
- call AddItem({'text': 'nocode'})
+ call AddItem({'text': "nocode\r"})
call ale#list#SetLists(bufnr(''), g:loclist)
AssertEqual
@@ -79,7 +79,7 @@ Execute(Formatting with codes should work for the quickfix list):
let g:ale_set_loclist = 0
let g:ale_set_quickfix = 1
- call AddItem({'text': 'nocode'})
+ call AddItem({'text': "nocode\r"})
call ale#list#SetLists(bufnr(''), g:loclist)
AssertEqual