Split up the flake8 and ansible-lint handlers

This commit is contained in:
w0rp 2017-06-14 16:20:30 +01:00
parent 3442e58c8b
commit f6b0a28cba
12 changed files with 240 additions and 178 deletions

View File

@ -1,9 +0,0 @@
" Author: Bjorn Neergaard <bjorn@neersighted.com>
" Description: ansible-lint for ansible-yaml files
call ale#linter#Define('ansible', {
\ 'name': 'ansible',
\ 'executable': 'ansible',
\ 'command': 'ansible-lint -p %t',
\ 'callback': 'ale#handlers#python#HandlePEP8Format',
\})

View File

@ -0,0 +1,48 @@
" Author: Bjorn Neergaard <bjorn@neersighted.com>
" Description: ansible-lint for ansible-yaml files
function! ale_linters#ansible#ansible_lint#Handle(buffer, lines) abort
for l:line in a:lines[:10]
if match(l:line, '^Traceback') >= 0
return [{
\ 'lnum': 1,
\ 'text': 'An exception was thrown. See :ALEDetail',
\ 'detail': join(a:lines, "\n"),
\}]
endif
endfor
" Matches patterns line the following:
"
" test.yml:35: [EANSIBLE0002] Trailing whitespace
let l:pattern = '\v^[a-zA-Z]?:?[^:]+:(\d+):?(\d+)?: \[?([[:alnum:]]+)\]? (.*)$'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
let l:code = l:match[3]
if (l:code ==# 'EANSIBLE002')
\ && !ale#Var(a:buffer, 'warn_about_trailing_whitespace')
" Skip warnings for trailing whitespace if the option is off.
continue
endif
let l:item = {
\ 'lnum': l:match[1] + 0,
\ 'col': l:match[2] + 0,
\ 'text': l:code . ': ' . l:match[4],
\ 'type': l:code[:0] ==# 'E' ? 'E' : 'W',
\}
call add(l:output, l:item)
endfor
return l:output
endfunction
call ale#linter#Define('ansible', {
\ 'name': 'ansible',
\ 'executable': 'ansible',
\ 'command': 'ansible-lint -p %t',
\ 'callback': 'ale_linters#ansible#ansible_lint#Handle',
\})

View File

@ -94,6 +94,65 @@ function! ale_linters#python#flake8#GetCommand(buffer, version_output) abort
\ . l:display_name_args . ' -'
endfunction
let s:end_col_pattern_map = {
\ 'F405': '\(.\+\) may be undefined',
\ 'F821': 'undefined name ''\([^'']\+\)''',
\ 'F999': '^''\([^'']\+\)''',
\ 'F841': 'local variable ''\([^'']\+\)''',
\}
function! ale_linters#python#flake8#Handle(buffer, lines) abort
for l:line in a:lines[:10]
if match(l:line, '^Traceback') >= 0
return [{
\ 'lnum': 1,
\ 'text': 'An exception was thrown. See :ALEDetail',
\ 'detail': join(a:lines, "\n"),
\}]
endif
endfor
" Matches patterns line the following:
"
" Matches patterns line the following:
"
" stdin:6:6: E111 indentation is not a multiple of four
" test.yml:35: [EANSIBLE0002] Trailing whitespace
let l:pattern = '\v^[a-zA-Z]?:?[^:]+:(\d+):?(\d+)?: ([[:alnum:]]+) (.*)$'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
let l:code = l:match[3]
if (l:code ==# 'W291' || l:code ==# 'W293')
\ && !ale#Var(a:buffer, 'warn_about_trailing_whitespace')
" Skip warnings for trailing whitespace if the option is off.
continue
endif
let l:item = {
\ 'lnum': l:match[1] + 0,
\ 'col': l:match[2] + 0,
\ 'text': l:code . ': ' . l:match[4],
\ 'type': l:code[:0] ==# 'E' ? 'E' : 'W',
\}
let l:end_col_pattern = get(s:end_col_pattern_map, l:code, '')
if !empty(l:end_col_pattern)
let l:end_col_match = matchlist(l:match[4], l:end_col_pattern)
if !empty(l:end_col_match)
let l:item.end_col = l:item.col + len(l:end_col_match[1]) - 1
endif
endif
call add(l:output, l:item)
endfor
return l:output
endfunction
call ale#linter#Define('python', {
\ 'name': 'flake8',
\ 'executable_callback': 'ale_linters#python#flake8#GetExecutable',
@ -101,5 +160,5 @@ call ale#linter#Define('python', {
\ {'callback': 'ale_linters#python#flake8#VersionCheck'},
\ {'callback': 'ale_linters#python#flake8#GetCommand', 'output_stream': 'both'},
\ ],
\ 'callback': 'ale#handlers#python#HandlePEP8Format',
\ 'callback': 'ale_linters#python#flake8#Handle',
\})

View File

@ -2,7 +2,7 @@
" Description: Fixing files with autopep8.
function! ale#fixers#autopep8#Fix(buffer) abort
let l:executable = ale#handlers#python#GetExecutable(a:buffer, 'autopep8')
let l:executable = ale#python#GetExecutable(a:buffer, 'autopep8')
if empty(l:executable)
return 0
endif

View File

@ -2,7 +2,7 @@
" Description: Fixing Python imports with isort.
function! ale#fixers#isort#Fix(buffer) abort
let l:executable = ale#handlers#python#GetExecutable(a:buffer, 'isort')
let l:executable = ale#python#GetExecutable(a:buffer, 'isort')
if empty(l:executable)
return 0
endif

View File

@ -2,7 +2,7 @@
" Description: Fixing Python files with yapf.
function! ale#fixers#yapf#Fix(buffer) abort
let l:executable = ale#handlers#python#GetExecutable(a:buffer, 'yapf')
let l:executable = ale#python#GetExecutable(a:buffer, 'yapf')
if empty(l:executable)
return 0
endif

View File

@ -1,87 +0,0 @@
" Author: w0rp <devw0rp@gmail.com>
" Description: Error handling for flake8, etc.
let s:end_col_pattern_map = {
\ 'F405': '\(.\+\) may be undefined',
\ 'F821': 'undefined name ''\([^'']\+\)''',
\ 'F999': '^''\([^'']\+\)''',
\ 'F841': 'local variable ''\([^'']\+\)''',
\}
function! ale#handlers#python#HandlePEP8Format(buffer, lines) abort
for l:line in a:lines[:10]
if match(l:line, '^Traceback') >= 0
return [{
\ 'lnum': 1,
\ 'text': 'An exception was thrown. See :ALEDetail',
\ 'detail': join(a:lines, "\n"),
\}]
endif
endfor
" Matches patterns line the following:
"
" Matches patterns line the following:
"
" stdin:6:6: E111 indentation is not a multiple of four
" test.yml:35: [EANSIBLE0002] Trailing whitespace
let l:pattern = '\v^[a-zA-Z]?:?[^:]+:(\d+):?(\d+)?: \[?([[:alnum:]]+)\]? (.*)$'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
let l:code = l:match[3]
if (l:code ==# 'W291' || l:code ==# 'W293' || l:code ==# 'EANSIBLE002')
\ && !ale#Var(a:buffer, 'warn_about_trailing_whitespace')
" Skip warnings for trailing whitespace if the option is off.
continue
endif
if l:code ==# 'I0011'
" Skip 'Locally disabling' message
continue
endif
let l:item = {
\ 'lnum': l:match[1] + 0,
\ 'col': l:match[2] + 0,
\ 'text': l:code . ': ' . l:match[4],
\ 'type': l:code[:0] ==# 'E' ? 'E' : 'W',
\}
let l:end_col_pattern = get(s:end_col_pattern_map, l:code, '')
if !empty(l:end_col_pattern)
let l:end_col_match = matchlist(l:match[4], l:end_col_pattern)
if !empty(l:end_col_match)
let l:item.end_col = l:item.col + len(l:end_col_match[1]) - 1
endif
endif
call add(l:output, l:item)
endfor
return l:output
endfunction
" Given a buffer number and a command name, find the path to the executable.
" First search on a virtualenv for Python, if nothing is found, try the global
" command. Returns an empty string if cannot find the executable
function! ale#handlers#python#GetExecutable(buffer, cmd_name) abort
let l:virtualenv = ale#python#FindVirtualenv(a:buffer)
if !empty(l:virtualenv)
let l:ve_executable = l:virtualenv . '/bin/' . a:cmd_name
if executable(l:ve_executable)
return l:ve_executable
endif
endif
if executable(a:cmd_name)
return a:cmd_name
endif
return ''
endfunction

View File

@ -9,6 +9,26 @@ let g:ale_virtualenv_dir_names = get(g:, 'ale_virtualenv_dir_names', [
\ 'virtualenv',
\])
" Given a buffer number and a command name, find the path to the executable.
" First search on a virtualenv for Python, if nothing is found, try the global
" command. Returns an empty string if cannot find the executable
function! ale#python#GetExecutable(buffer, cmd_name) abort
let l:virtualenv = ale#python#FindVirtualenv(a:buffer)
if !empty(l:virtualenv)
let l:ve_executable = l:virtualenv . '/bin/' . a:cmd_name
if executable(l:ve_executable)
return l:ve_executable
endif
endif
if executable(a:cmd_name)
return a:cmd_name
endif
return ''
endfunction
" Given a buffer number, find the project root directory for Python.
" The root directory is defined as the first directory found while searching

View File

@ -11,18 +11,18 @@ After:
Execute(The python GetExecutable callbacks should return the correct path):
AssertEqual
\ '',
\ ale#handlers#python#GetExecutable(bufnr(''), 'isort')
\ ale#python#GetExecutable(bufnr(''), 'isort')
silent execute 'file ' . fnameescape(g:dir . '/python_paths/with_virtualenv/subdir/foo/bar.py')
AssertEqual
\ g:dir . '/python_paths/with_virtualenv/env/bin/isort',
\ ale#handlers#python#GetExecutable(bufnr(''), 'isort')
\ ale#python#GetExecutable(bufnr(''), 'isort')
AssertEqual
\ g:dir . '/python_paths/with_virtualenv/env/bin/autopep8',
\ ale#handlers#python#GetExecutable(bufnr(''), 'autopep8')
\ ale#python#GetExecutable(bufnr(''), 'autopep8')
AssertEqual
\ g:dir . '/python_paths/with_virtualenv/env/bin/yapf',
\ ale#handlers#python#GetExecutable(bufnr(''), 'yapf')
\ ale#python#GetExecutable(bufnr(''), 'yapf')
Execute(The autopep8 callbacks should return the correct default values):

View File

@ -0,0 +1,33 @@
Before:
runtime ale_linters/ansible/ansible_lint.vim
After:
call ale#linter#Reset()
Execute(The ansible-lint handler should handle basic errors):
AssertEqual
\ [
\ {
\ 'lnum': 35,
\ 'col': 0,
\ 'type': 'E',
\ 'text': "EANSIBLE0002: Trailing whitespace",
\ },
\ ],
\ ale_linters#ansible#ansible_lint#Handle(42, [
\ "test.yml:35: [EANSIBLE0002] Trailing whitespace",
\ ])
Execute (The ansible-lint handler should handle names with spaces):
AssertEqual
\ [
\ {
\ 'lnum': 6,
\ 'col': 6,
\ 'type': 'E',
\ 'text': 'E111: indentation is not a multiple of four',
\ },
\ ],
\ ale_linters#python#flake8#Handle(42, [
\ 'C:\something\with spaces.yml:6:6: E111 indentation is not a multiple of four',
\ ])

View File

@ -40,78 +40,6 @@ Execute(HandleCSSLintFormat should handle CSS errors without groups):
\ 'something.css: line 8, col 3, Warning - Unknown property ''fill-opacity''.',
\ ])
Execute (HandlePEP8Format should handle the correct lines of output):
AssertEqual
\ [
\ {
\ 'lnum': 6,
\ 'col': 6,
\ 'type': 'E',
\ 'text': 'E111: indentation is not a multiple of four',
\ },
\ {
\ 'lnum': 35,
\ 'col': 0,
\ 'type': 'E',
\ 'text': "EANSIBLE0002: Trailing whitespace",
\ },
\ ],
\ ale#handlers#python#HandlePEP8Format(42, [
\ "stdin:6:6: E111 indentation is not a multiple of four",
\ "test.yml:35: [EANSIBLE0002] Trailing whitespace",
\ ])
Execute (HandlePEP8Format should handle names with spaces):
AssertEqual
\ [
\ {
\ 'lnum': 6,
\ 'col': 6,
\ 'type': 'E',
\ 'text': 'E111: indentation is not a multiple of four',
\ },
\ ],
\ ale#handlers#python#HandlePEP8Format(42, [
\ 'C:\something\with spaces.py:6:6: E111 indentation is not a multiple of four',
\ ])
Execute (HandlePEP8Format should stack traces):
AssertEqual
\ [
\ {
\ 'lnum': 1,
\ 'text': 'An exception was thrown. See :ALEDetail',
\ 'detail': join([
\ 'Traceback (most recent call last):',
\ ' File "/usr/local/bin/flake8", line 7, in <module>',
\ ' from flake8.main.cli import main',
\ ' File "/usr/local/lib/python2.7/dist-packages/flake8/main/cli.py", line 2, in <module>',
\ ' from flake8.main import application',
\ ' File "/usr/local/lib/python2.7/dist-packages/flake8/main/application.py", line 17, in <module>',
\ ' from flake8.plugins import manager as plugin_manager',
\ ' File "/usr/local/lib/python2.7/dist-packages/flake8/plugins/manager.py", line 5, in <module>',
\ ' import pkg_resources',
\ ' File "/usr/lib/python2.7/dist-packages/pkg_resources/__init__.py", line 35, in <module>',
\ ' import email.parser',
\ 'ImportError: No module named parser',
\ ], "\n"),
\ },
\ ],
\ ale#handlers#python#HandlePEP8Format(42, [
\ 'Traceback (most recent call last):',
\ ' File "/usr/local/bin/flake8", line 7, in <module>',
\ ' from flake8.main.cli import main',
\ ' File "/usr/local/lib/python2.7/dist-packages/flake8/main/cli.py", line 2, in <module>',
\ ' from flake8.main import application',
\ ' File "/usr/local/lib/python2.7/dist-packages/flake8/main/application.py", line 17, in <module>',
\ ' from flake8.plugins import manager as plugin_manager',
\ ' File "/usr/local/lib/python2.7/dist-packages/flake8/plugins/manager.py", line 5, in <module>',
\ ' import pkg_resources',
\ ' File "/usr/lib/python2.7/dist-packages/pkg_resources/__init__.py", line 35, in <module>',
\ ' import email.parser',
\ 'ImportError: No module named parser',
\ ])
Execute (HandleGCCFormat should handle the correct lines of output):
AssertEqual
\ [

View File

@ -1,5 +1,24 @@
Before:
runtime ale_linters/python/flake8.vim
Execute(End column indexes should be set for certain errors):
After:
call ale#linter#Reset()
Execute(The flake8 handler should handle basic errors):
AssertEqual
\ [
\ {
\ 'lnum': 6,
\ 'col': 6,
\ 'type': 'E',
\ 'text': 'E111: indentation is not a multiple of four',
\ },
\ ],
\ ale_linters#python#flake8#Handle(1, [
\ 'stdin:6:6: E111 indentation is not a multiple of four',
\ ])
Execute(The flake8 handler should set end column indexes should be set for certain errors):
AssertEqual
\ [
\ {
@ -38,10 +57,61 @@ Execute(End column indexes should be set for certain errors):
\ 'text': 'F841: local variable ''test'' is assigned to but never used',
\ },
\ ],
\ ale#handlers#python#HandlePEP8Format(1, [
\ ale_linters#python#flake8#Handle(1, [
\ 'foo.py:25:1: F821 undefined name ''foo''',
\ 'foo.py:28:5: F405 hello may be undefined, or defined from star imports: x',
\ 'foo.py:104:5: F999 ''continue'' not properly in loop',
\ 'foo.py:106:5: F999 ''break'' outside loop',
\ 'foo.py:109:5: F841 local variable ''test'' is assigned to but never used',
\ ])
Execute(The flake8 handler should handle stack traces):
AssertEqual
\ [
\ {
\ 'lnum': 1,
\ 'text': 'An exception was thrown. See :ALEDetail',
\ 'detail': join([
\ 'Traceback (most recent call last):',
\ ' File "/usr/local/bin/flake8", line 7, in <module>',
\ ' from flake8.main.cli import main',
\ ' File "/usr/local/lib/python2.7/dist-packages/flake8/main/cli.py", line 2, in <module>',
\ ' from flake8.main import application',
\ ' File "/usr/local/lib/python2.7/dist-packages/flake8/main/application.py", line 17, in <module>',
\ ' from flake8.plugins import manager as plugin_manager',
\ ' File "/usr/local/lib/python2.7/dist-packages/flake8/plugins/manager.py", line 5, in <module>',
\ ' import pkg_resources',
\ ' File "/usr/lib/python2.7/dist-packages/pkg_resources/__init__.py", line 35, in <module>',
\ ' import email.parser',
\ 'ImportError: No module named parser',
\ ], "\n"),
\ },
\ ],
\ ale_linters#python#flake8#Handle(42, [
\ 'Traceback (most recent call last):',
\ ' File "/usr/local/bin/flake8", line 7, in <module>',
\ ' from flake8.main.cli import main',
\ ' File "/usr/local/lib/python2.7/dist-packages/flake8/main/cli.py", line 2, in <module>',
\ ' from flake8.main import application',
\ ' File "/usr/local/lib/python2.7/dist-packages/flake8/main/application.py", line 17, in <module>',
\ ' from flake8.plugins import manager as plugin_manager',
\ ' File "/usr/local/lib/python2.7/dist-packages/flake8/plugins/manager.py", line 5, in <module>',
\ ' import pkg_resources',
\ ' File "/usr/lib/python2.7/dist-packages/pkg_resources/__init__.py", line 35, in <module>',
\ ' import email.parser',
\ 'ImportError: No module named parser',
\ ])
Execute (The flake8 handler should handle names with spaces):
AssertEqual
\ [
\ {
\ 'lnum': 6,
\ 'col': 6,
\ 'type': 'E',
\ 'text': 'E111: indentation is not a multiple of four',
\ },
\ ],
\ ale_linters#python#flake8#Handle(42, [
\ 'C:\something\with spaces.py:6:6: E111 indentation is not a multiple of four',
\ ])