Add support for dot-seperate linters, improve linter tests

This PR first and formost implements support for dot-seperate filetypes,
a very trivial change.

This closes #132

But more importantly, this PR vastly improves the test quality for
`ale#linter#Get`. It enables us to reset the state of ale's internal
linter cache, to facilitate better testing, as well as making use of
mocked linters instead of depending on linters on disk (which may
change). In addition, a dummy linter is defined to test the autoloading
behavior.

Header guards were removed from all linters as:

* A: ale won't try and load linters if they already exist in memory
* B: we can't reset state for testing if they can't be loaded again
This commit is contained in:
Bjorn Neergaard 2016-10-21 21:02:20 -05:00
parent 216eadbcbe
commit f49f615ef6
No known key found for this signature in database
GPG key ID: D8F4DB0CE841305D
45 changed files with 96 additions and 298 deletions

View file

@ -1,12 +1,6 @@
" Author: Bjorn Neergaard <bjorn@neersighted.com>
" Description: ansible-lint for ansible-yaml files
if exists('g:loaded_ale_linters_ansible_ansiblelint')
finish
endif
let g:loaded_ale_linters_ansible_ansiblelint = 1
call ale#linter#Define('ansible', {
\ 'name': 'ansible',
\ 'executable': 'ansible',

View file

@ -1,12 +1,6 @@
" Author: Bart Libert <bart.libert@gmail.com>
" Description: cppcheck linter for c files
if exists('g:loaded_ale_linters_c_cppcheck')
finish
endif
let g:loaded_ale_linters_c_cppcheck = 1
" Set this option to change the cppcheck options
if !exists('g:ale_c_cppcheck_options')
let g:ale_c_cppcheck_options = '--enable=style'

View file

@ -1,12 +1,6 @@
" Author: w0rp <devw0rp@gmail.com>
" Description: gcc linter for c files
if exists('g:loaded_ale_linters_c_gcc')
finish
endif
let g:loaded_ale_linters_c_gcc = 1
" Set this option to change the GCC options for warnings for C.
if !exists('g:ale_c_gcc_options')
" let g:ale_c_gcc_options = '-Wall'

View file

@ -1,12 +1,6 @@
" Author: KabbAmine - https://github.com/KabbAmine
" Description: Coffee for checking coffee files
if exists('g:loaded_ale_linters_coffee_coffee')
finish
endif
let g:loaded_ale_linters_coffee_coffee = 1
call ale#linter#Define('coffee', {
\ 'name': 'coffee',
\ 'executable': 'coffee',
@ -14,4 +8,3 @@ call ale#linter#Define('coffee', {
\ 'output_stream': 'stderr',
\ 'callback': 'ale#handlers#HandleGCCFormat',
\})

View file

@ -1,12 +1,6 @@
" Author: Prashanth Chandra https://github.com/prashcr
" Description: coffeelint linter for coffeescript files
if exists('g:loaded_ale_linters_coffee_coffeelint')
finish
endif
let g:loaded_ale_linters_coffee_coffeelint = 1
function! ale_linters#coffee#coffeelint#Handle(buffer, lines)
" Matches patterns like the following:
"

View file

@ -1,12 +1,6 @@
" Author: Bart Libert <bart.libert@gmail.com>
" Description: cppcheck linter for cpp files
if exists('g:loaded_ale_linters_cpp_cppcheck')
finish
endif
let g:loaded_ale_linters_cpp_cppcheck = 1
" Set this option to change the cppcheck options
if !exists('g:ale_cpp_cppcheck_options')
let g:ale_cpp_cppcheck_options = '--enable=style'

View file

@ -1,12 +1,6 @@
" Author: geam <mdelage@student.42.fr>
" Description: gcc linter for cpp files
if exists('g:loaded_ale_linters_cpp_gcc')
finish
endif
let g:loaded_ale_linters_cpp_gcc = 1
" Set this option to change the GCC options for warnings for C.
if !exists('g:ale_cpp_gcc_options')
" added c++14 standard support

View file

@ -1,12 +1,6 @@
" Author: w0rp <devw0rp@gmail.com>
" Description: This file adds support for checking CSS code with csslint.
if exists('g:loaded_ale_linters_css_csslint')
finish
endif
let g:loaded_ale_linters_css_csslint = 1
call ale#linter#Define('css', {
\ 'name': 'csslint',
\ 'executable': 'csslint',

View file

@ -1,12 +1,6 @@
" Author: w0rp <devw0rp@gmail.com>
" Description: "dmd for D files"
if exists('g:loaded_ale_linters_d_dmd')
finish
endif
let g:loaded_ale_linters_d_dmd = 1
" A function for finding the dmd-wrapper script in the Vim runtime paths
function! s:FindWrapperScript()
for l:parent in split(&runtimepath, ',')

View file

@ -1,11 +1,5 @@
" Author: hauleth - https://github.com/haulethe
if exists('g:loaded_ale_linters_elixir_credo')
finish
endif
let g:loaded_ale_linters_elixir_credo = 1
function! ale_linters#elixir#credo#Handle(buffer, lines)
" Matches patterns line the following:
"

View file

@ -1,12 +1,6 @@
" Author: w0rp <devw0rp@gmail.com>
" Description: gcc for Fortran files
if exists('g:loaded_ale_linters_fortran_gcc')
finish
endif
let g:loaded_ale_linters_fortran_gcc = 1
" Set this option to change the GCC options for warnings for Fortran.
if !exists('g:ale_fortran_gcc_options')
let g:ale_fortran_gcc_options = '-Wall'

View file

@ -1,12 +1,6 @@
" Author: neersighted <bjorn@neersighted.com>
" Description: gofmt for Go files
if exists('g:loaded_ale_linters_go_gofmt')
finish
endif
let g:loaded_ale_linters_go_gofmt = 1
call ale#linter#Define('go', {
\ 'name': 'gofmt',
\ 'output_stream': 'stderr',
@ -14,4 +8,3 @@ call ale#linter#Define('go', {
\ 'command': g:ale#util#stdin_wrapper . ' .go gofmt -e',
\ 'callback': 'ale#handlers#HandleUnixFormatAsError',
\})

View file

@ -1,12 +1,6 @@
" Author: neersighted <bjorn@neersighted.com>
" Description: golint for Go files
if exists('g:loaded_ale_linters_go_golint')
finish
endif
let g:loaded_ale_linters_go_golint = 1
call ale#linter#Define('go', {
\ 'name': 'golint',
\ 'executable': 'golint',

View file

@ -1,12 +1,6 @@
" Author: neersighted <bjorn@neersighted.com>
" Description: go vet for Go files
if exists('g:loaded_ale_linters_go_govet')
finish
endif
let g:loaded_ale_linters_go_govet = 1
call ale#linter#Define('go', {
\ 'name': 'go vet',
\ 'output_stream': 'stderr',
@ -14,4 +8,3 @@ call ale#linter#Define('go', {
\ 'command': g:ale#util#stdin_wrapper . ' .go go vet',
\ 'callback': 'ale#handlers#HandleUnixFormatAsError',
\})

View file

@ -1,12 +1,6 @@
" Author: w0rp <devw0rp@gmail.com>
" Description: ghc for Haskell files
if exists('g:loaded_ale_linters_haskell_ghc')
finish
endif
let g:loaded_ale_linters_haskell_ghc = 1
call ale#linter#Define('haskell', {
\ 'name': 'ghc',
\ 'output_stream': 'stderr',

View file

@ -1,12 +1,6 @@
" Author: jparoz <jesse.paroz@gmail.com>
" Description: hlint for Haskell files
if exists('g:loaded_ale_linters_haskell_hlint')
finish
endif
let g:loaded_ale_linters_haskell_hlint = 1
function! ale_linters#haskell#hlint#Handle(buffer, lines)
let l:errors = json_decode(join(a:lines, ''))

View file

@ -1,12 +1,6 @@
" Author: KabbAmine <amine.kabb@gmail.com>
" Description: HTMLHint for checking html files
if exists('g:loaded_ale_linters_html_htmlhint')
finish
endif
let g:loaded_ale_linters_html_htmlhint = 1
call ale#linter#Define('html', {
\ 'name': 'htmlhint',
\ 'executable': 'htmlhint',

View file

@ -1,12 +1,6 @@
" Author: KabbAmine <amine.kabb@gmail.com>
" Description: This file adds support for checking HTML code with tidy.
if exists('g:loaded_ale_linters_html_tidy')
finish
endif
let g:loaded_ale_linters_html_tidy = 1
" CLI options
let g:ale_html_tidy_executable = get(g:, 'ale_html_tidy_executable', 'tidy')
let g:ale_html_tidy_args = get(g:, 'ale_html_tidy_args', '-q -e -language en')

View file

@ -1,12 +1,6 @@
" Author: w0rp <devw0rp@gmail.com>
" Description: eslint for JavaScript files
if exists('g:loaded_ale_linters_javascript_eslint')
finish
endif
let g:loaded_ale_linters_javascript_eslint = 1
let g:ale_javascript_eslint_executable =
\ get(g:, 'ale_javascript_eslint_executable', 'eslint')

View file

@ -1,12 +1,6 @@
" Author: Chris Kyrouac - https://github.com/fijshion
" Description: jscs for JavaScript files
if exists('g:loaded_ale_linters_javascript_jscs')
finish
endif
let g:loaded_ale_linters_javascript_jscs = 1
call ale#linter#Define('javascript', {
\ 'name': 'jscs',
\ 'executable': 'jscs',

View file

@ -1,12 +1,6 @@
" Author: Chris Kyrouac - https://github.com/fijshion
" Description: JSHint for Javascript files
if exists('g:loaded_ale_linters_javascript_jshint')
finish
endif
let g:loaded_ale_linters_javascript_jshint = 1
let g:ale_javascript_jshint_executable =
\ get(g:, 'ale_javascript_jshint_executable', 'jshint')

View file

@ -1,11 +1,5 @@
" Author: KabbAmine <amine.kabb@gmail.com>
if exists('g:loaded_ale_linters_json_jsonlint')
finish
endif
let g:loaded_ale_linters_json_jsonlint = 1
function! ale_linters#json#jsonlint#Handle(buffer, lines)
" Matches patterns like the following:
" line 2, col 15, found: 'STRING' - expected: 'EOF', '}', ',', ']'.

View file

@ -1,12 +1,6 @@
" Author: Sol Bekic https://github.com/s-ol
" Description: luacheck linter for lua files
if exists('g:loaded_ale_linters_lua_luacheck')
finish
endif
let g:loaded_ale_linters_lua_luacheck = 1
let g:ale_lua_luacheck_executable =
\ get(g:, 'ale_lua_luacheck_executable', 'luacheck')

View file

@ -1,11 +1,6 @@
" Author: Vincent Lequertier <https://github.com/SkySymbol>
" Description: This file adds support for checking perl syntax
if exists('g:loaded_ale_linters_perl_perlcritic')
finish
endif
let g:loaded_ale_linters_perl_perl = 1
function! ale_linters#perl#perl#Handle(buffer, lines)
let l:pattern = '\(.\+\) at \(.\+\) line \(\d\+\)'
let l:output = []

View file

@ -1,11 +1,6 @@
" Author: Vincent Lequertier <https://github.com/SkySymbol>
" Description: This file adds support for checking perl with perl critic
if exists('g:loaded_ale_linters_perl_perlcritic')
finish
endif
let g:loaded_ale_linters_perl_perlcritic = 1
function! ale_linters#perl#perlcritic#Handle(buffer, lines)
let l:pattern = '\(.\+\) at \(.\+\) line \(\d\+\)'
let l:output = []

View file

@ -1,12 +1,6 @@
" Author: Spencer Wood <https://github.com/scwood>
" Description: This file adds support for checking PHP with php-cli
if exists('g:loaded_ale_linters_php_php')
finish
endif
let g:loaded_ale_linters_php_php = 1
function! ale_linters#php#php#Handle(buffer, lines)
" Matches patterns like the following:
"

View file

@ -1,12 +1,6 @@
" Author: jwilliams108 <https://github.com/jwilliams108>
" Description: phpcs for PHP files
if exists('g:loaded_ale_linters_php_phpcs')
finish
endif
let g:loaded_ale_linters_php_phpcs = 1
function! ale_linters#php#phpcs#GetCommand(buffer)
let l:command = 'phpcs -s --report=emacs --stdin-path=%s'

View file

@ -1,12 +1,6 @@
" Author: w0rp - <devw0rp@gmail.com>
" Description: pug-lint for checking Pug/Jade files.
if exists('g:loaded_ale_linters_pug_puglint')
finish
endif
let g:loaded_ale_linters_pug_puglint = 1
call ale#linter#Define('pug', {
\ 'name': 'puglint',
\ 'executable': 'pug-lint',

View file

@ -1,12 +1,6 @@
" Author: w0rp <devw0rp@gmail.com>
" Description: flake8 for python files
if exists('g:loaded_ale_linters_python_flake8')
finish
endif
let g:loaded_ale_linters_python_flake8 = 1
call ale#linter#Define('python', {
\ 'name': 'flake8',
\ 'executable': 'flake8',

View file

@ -1,12 +1,6 @@
" Author: ynonp - https://github.com/ynonp
" Description: rubocop for Ruby files
if exists('g:loaded_ale_linters_ruby_rubocop')
finish
endif
let g:loaded_ale_linters_ruby_rubocop = 1
function! ale_linters#ruby#rubocop#Handle(buffer, lines)
" Matches patterns line the following:
"

View file

@ -1,11 +1,5 @@
" Author: KabbAmine - https://github.com/KabbAmine
if exists('g:loaded_ale_linters_sass_sasslint')
finish
endif
let g:loaded_ale_linters_sass_sasslint = 1
call ale#linter#Define('sass', {
\ 'name': 'sasslint',
\ 'executable': 'sass-lint',

View file

@ -2,12 +2,6 @@
" Author: Zoltan Kalmar - https://github.com/kalmiz
" Description: Basic scala support using scalac
if exists('g:loaded_ale_linters_scala_scalac')
finish
endif
let g:loaded_ale_linters_scala_scalac = 1
function! ale_linters#scala#scalac#Handle(buffer, lines)
" Matches patterns line the following:
"

View file

@ -1,11 +1,5 @@
" Author: KabbAmine - https://github.com/KabbAmine
if exists('g:loaded_ale_linters_scss_sasslint')
finish
endif
let g:loaded_ale_linters_scss_sasslint = 1
call ale#linter#Define('scss', {
\ 'name': 'sasslint',
\ 'executable': 'sass-lint',

View file

@ -1,12 +1,6 @@
" Author: w0rp <devw0rp@gmail.com>
" Description: This file add scsslint support for SCSS support
if exists('g:loaded_ale_linters_scss_scsslint')
finish
endif
let g:loaded_ale_linters_scss_scsslint = 1
function! ale_linters#scss#scsslint#Handle(buffer, lines)
" Matches patterns like the following:
"

View file

@ -1,12 +1,6 @@
" Author: w0rp <devw0rp@gmail.com>
" Description: Lints sh files using bash -n
if exists('g:loaded_ale_linters_sh_shell')
finish
endif
let g:loaded_ale_linters_sh_shell = 1
" This option can be changed to change the default shell when the shell
" cannot be taken from the hashbang line.
if !exists('g:ale_linters_sh_shell_default_shell')

View file

@ -2,12 +2,6 @@
" Description: This file adds support for using the shellcheck linter with
" shell scripts.
if exists('g:loaded_ale_linters_sh_shellcheck')
finish
endif
let g:loaded_ale_linters_sh_shellcheck = 1
" This global variable can be set with a string of comma-seperated error
" codes to exclude from shellcheck. For example:
"

View file

@ -0,0 +1,10 @@
" Author: neersighted <bjorn@neersighted.com>
" Description: dummy linter to use in tests
call ale#linter#Define('testft', {
\ 'name': 'testlinter',
\ 'output_stream': 'stdout',
\ 'executable': 'testlinter',
\ 'command': 'testlinter',
\ 'callback': 'testCB',
\})

View file

@ -1,12 +1,6 @@
" Author: Prashanth Chandra https://github.com/prashcr
" Description: tslint for TypeScript files
if exists('g:loaded_ale_linters_typescript_tslint')
finish
endif
let g:loaded_ale_linters_typescript_tslint = 1
function! ale_linters#typescript#tslint#Handle(buffer, lines)
" Matches patterns like the following:
"

View file

@ -1,12 +1,6 @@
" Author: Masahiro H https://github.com/mshr-h
" Description: iverilog for verilog files
if exists('g:loaded_ale_linters_verilog_iverilog')
finish
endif
let g:loaded_ale_linters_verilog_iverilog = 1
function! ale_linters#verilog#iverilog#Handle(buffer, lines)
" Look for lines like the following.
"

View file

@ -1,12 +1,6 @@
" Author: Masahiro H https://github.com/mshr-h
" Description: verilator for verilog files
if exists('g:loaded_ale_linters_verilog_verilator')
finish
endif
let g:loaded_ale_linters_verilog_verilator = 1
function! ale_linters#verilog#verilator#Handle(buffer, lines)
" Look for lines like the following.
"

View file

@ -1,12 +1,6 @@
" Author: w0rp <devw0rp@gmail.com>, KabbAmine <amine.kabb@gmail.com>
" Description: This file adds support for checking Vim code with Vint.
if exists('g:loaded_ale_linters_vim_vint')
finish
endif
let g:loaded_ale_linters_vim_vint = 1
" This flag can be used to change enable/disable style issues.
let g:ale_vim_vint_show_style_issues =
\ get(g:, 'ale_vim_vint_show_style_issues', 1)

View file

@ -1,11 +1,5 @@
" Author: KabbAmine <amine.kabb@gmail.com>
if exists('g:loaded_ale_linters_yaml_yamllint')
finish
endif
let g:loaded_ale_linters_yaml_yamllint = 1
function! ale_linters#yaml#yamllint#Handle(buffer, lines)
" Matches patterns line the following:
" something.yaml:1:1: [warning] missing document start "---" (document-start)

View file

@ -7,7 +7,6 @@ let s:linters = {}
" Default filetype aliaes.
" The user defined aliases will be merged with this Dictionary.
let s:default_ale_linter_aliases = {
\ 'javascript.jsx': 'javascript',
\ 'zsh': 'sh',
\ 'csh': 'sh',
\}
@ -19,6 +18,11 @@ let s:default_ale_linters = {
\ 'csh': ['shell'],
\}
" Testing/debugging helper to unload all linters.
function! ale#linter#Reset() abort
let s:linters = {}
endfunction
function! ale#linter#Define(filetype, linter) abort
if !has_key(s:linters, a:filetype)
let s:linters[a:filetype] = []
@ -74,16 +78,20 @@ function! s:LoadLinters(filetype) abort
return s:linters[a:filetype]
endfunction
function! ale#linter#Get(original_filetype) abort
function! ale#linter#Get(original_filetypes) abort
let l:combined_linters = []
" Handle dot-seperated filetypes.
for l:original_filetype in split(a:original_filetypes, '\.')
" Try and get an aliased file type either from the user's Dictionary, or
" our default Dictionary, otherwise use the filetype as-is.
let l:filetype = get(
\ g:ale_linter_aliases,
\ a:original_filetype,
\ l:original_filetype,
\ get(
\ s:default_ale_linter_aliases,
\ a:original_filetype,
\ a:original_filetype
\ l:original_filetype,
\ l:original_filetype
\ )
\)
@ -92,27 +100,30 @@ function! ale#linter#Get(original_filetype) abort
" and users may define their own list of linters to run.
let l:linter_names = get(
\ g:ale_linters,
\ a:original_filetype,
\ l:original_filetype,
\ get(
\ s:default_ale_linters,
\ a:original_filetype,
\ l:original_filetype,
\ 'all'
\ )
\)
let l:all_linters = s:LoadLinters(l:filetype)
let l:combined_linters = []
let l:filetype_linters = []
if type(l:linter_names) == type('') && l:linter_names ==# 'all'
let l:combined_linters = l:all_linters
let l:filetype_linters = l:all_linters
elseif type(l:linter_names) == type([])
" Select only the linters we or the user has specified.
for l:linter in l:all_linters
if index(l:linter_names, l:linter.name) >= 0
call add(l:combined_linters, l:linter)
call add(l:filetype_linters, l:linter)
endif
endfor
endif
call extend(l:combined_linters, l:filetype_linters)
endfor
return l:combined_linters
endfunction

View file

@ -1,19 +1,43 @@
Before:
let g:testlinter1 = {'name': 'testlinter1', 'executable': 'testlinter1', 'command': 'testlinter1', 'callback': 'testCB1', 'output_stream': 'stdout'}
let g:testlinter2 = {'name': 'testlinter2', 'executable': 'testlinter2', 'command': 'testlinter2', 'callback': 'testCB2', 'output_stream': 'stdout'}
call ale#linter#Reset()
let g:ale_linters = {}
let g:ale_linter_aliases = {}
After:
let g:ale_linters = {}
let g:ale_linter_aliases = {}
Execute (Define a linter):
call ale#linter#Define('testft', g:testlinter1)
Then (Get the defined linter):
AssertEqual [g:testlinter1], ale#linter#Get('testft')
Execute (Defaults should be correct):
AssertEqual [{'output_stream': 'stdout', 'name': 'eslint', 'executable': 'eslint', 'command': 'eslint -f unix --stdin --stdin-filename %s', 'callback': 'ale_linters#javascript#eslint#Handle'}, {'output_stream': 'stdout', 'name': 'jscs', 'executable': 'jscs', 'command': 'jscs -r unix -n -', 'callback': 'ale#handlers#HandleUnixFormatAsError'}, {'output_stream': 'stdout', 'name': 'jshint', 'executable': 'jshint', 'command_callback': 'ale_linters#javascript#jshint#GetCommand', 'callback': 'ale#handlers#HandleUnixFormatAsError'}], ale#linter#Get('javascript')
Execute (Define a couple linters, filtering one.):
call ale#linter#Define('testft', g:testlinter1)
call ale#linter#Define('testft', g:testlinter2)
let g:ale_linters = {'testft': ['testlinter1']}
Then (Only the configured linter should be returned):
AssertEqual [g:testlinter1], ale#linter#Get('testft')
Execute (You should be able to select only a few linters):
let g:ale_linters = {'javascript': ['eslint']}
AssertEqual [{'output_stream': 'stdout', 'name': 'eslint', 'executable': 'eslint', 'command': 'eslint -f unix --stdin --stdin-filename %s', 'callback': 'ale_linters#javascript#eslint#Handle'}], ale#linter#Get('javascript')
Execute (Define a linter for a filetype, and create a filetype alias):
call ale#linter#Define('testft1', g:testlinter1)
let g:ale_linter_aliases = {'testft2': 'testft1'}
Then (Linters should be transparently aliased):
AssertEqual [g:testlinter1], ale#linter#Get('testft2')
Execute (You should be able to alias filetypes and select different linters):
let g:ale_linter_aliases = {'foobar': 'javascript'}
let g:ale_linters = {'javascript': ['eslint'], 'foobar': ['jshint']}
AssertEqual [{'output_stream': 'stdout', 'name': 'jshint', 'executable': 'jshint', 'command_callback': 'ale_linters#javascript#jshint#GetCommand', 'callback': 'ale#handlers#HandleUnixFormatAsError'}], ale#linter#Get('foobar')
Execute (Define multiple linters, with filters and aliases):
call ale#linter#Define('testft1', g:testlinter1)
call ale#linter#Define('testft1', g:testlinter2)
let g:ale_linters = {'testft1': ['testlinter1'], 'testft2': ['testlinter2']}
let g:ale_linter_aliases = {'testft2': 'testft1'}
Then (Linters should be transparently filtered and aliased):
AssertEqual [g:testlinter1], ale#linter#Get('testft1')
AssertEqual [g:testlinter2], ale#linter#Get('testft2')
Execute (Define multiple linters for different filetypes):
call ale#linter#Define('testft1', g:testlinter1)
call ale#linter#Define('testft2', g:testlinter2)
Then (Linters for dot-seperated filetypes should be properly handled):
AssertEqual [g:testlinter1, g:testlinter2], ale#linter#Get('testft1.testft2')
Execute (Try to load a linter from disk):
AssertEqual [{'name': 'testlinter', 'output_stream': 'stdout', 'executable': 'testlinter', 'command': 'testlinter', 'callback': 'testCB'}], ale#linter#Get('testft')

View file

@ -52,7 +52,7 @@ Execute (Given some warnings):
Then (Statusline is formatted to the users preference):
AssertEqual '3W', ale#statusline#Status()
Execute (Given some warnings, and errors.):
Execute (Given some warnings, and errors):
call ale#statusline#Update(bufnr('%'), [{'type': 'E'}, {'type': 'W'}, {'type': 'W'}])
Then (Statusline is formatted to the users preference):