Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
c78be86103
29 changed files with 452 additions and 84 deletions
|
@ -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',
|
||||
\})
|
||||
|
|
|
@ -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'),
|
||||
|
|
|
@ -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$'
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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)
|
||||
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!
|
||||
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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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|
|
||||
|
|
|
@ -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.
|
||||
|
||||
===============================================================================
|
||||
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_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*
|
||||
|
||||
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.
|
||||
|
||||
===============================================================================
|
||||
php *ale-php-php*
|
||||
|
||||
g:ale_php_php_executable *g:ale_php_php_executable*
|
||||
*b:ale_php_php_executable*
|
||||
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*
|
||||
|
||||
g:ale_php_php_executable *g:ale_php_php_executable*
|
||||
*b:ale_php_php_executable*
|
||||
Type: |String|
|
||||
Default: `'php'`
|
||||
|
||||
|
|
|
@ -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*
|
||||
|
|
47
doc/ale.txt
47
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.
|
||||
|
|
|
@ -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 -'
|
||||
|
|
|
@ -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')
|
||||
for g:i in range(4)
|
||||
if !isdirectory(g:dir . '/.git')
|
||||
call mkdir(g:dir . '/.git')
|
||||
endif
|
||||
|
||||
try
|
||||
AssertLSPProject g:dir
|
||||
catch /.+/
|
||||
endtry
|
||||
|
||||
let g:matched = 1
|
||||
break
|
||||
endfor
|
||||
|
||||
if !g:matched
|
||||
AssertLSPProject g:dir
|
||||
endif
|
||||
|
||||
AssertLSPProject g:dir
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
0
test/ember-template-lint-test-files/app/template.hbs
Normal file
0
test/ember-template-lint-test-files/app/template.hbs
Normal file
0
test/ember-template-lint-test-files/package.json
Normal file
0
test/ember-template-lint-test-files/package.json
Normal file
|
@ -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
|
||||
|
|
|
@ -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;',
|
||||
\ ' | ^~~~',
|
||||
\ ])
|
||||
|
|
|
@ -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')
|
||||
|
||||
|
|
|
@ -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']
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
\ },
|
||||
\ {
|
||||
|
|
22
test/test_embertemplatelint_executable_detection.vader
Normal file
22
test/test_embertemplatelint_executable_detection.vader
Normal file
|
@ -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'
|
|
@ -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
|
||||
|
|
Reference in a new issue