diff --git a/README.md b/README.md index 379e69e..b9f32a1 100644 --- a/README.md +++ b/README.md @@ -30,8 +30,8 @@ name. That seems to be the fairest way to arrange this table. | -------- | ----- | | Bash | [-n flag](https://www.gnu.org/software/bash/manual/bash.html#index-set), [shellcheck](https://www.shellcheck.net/) | | Bourne Shell | [-n flag](http://linux.die.net/man/1/sh), [shellcheck](https://www.shellcheck.net/) | -| C | [gcc](https://gcc.gnu.org/) | -| C++ (filetype cpp)| [gcc](https://gcc.gnu.org/) | +| C | [cppcheck](http://cppcheck.sourceforge.net), [gcc](https://gcc.gnu.org/)| +| C++ (filetype cpp)| [cppcheck] (http://cppcheck.sourceforge.net), [gcc](https://gcc.gnu.org/)| | CoffeeScript | [coffee](http://coffeescript.org/), [coffeelint](https://www.npmjs.com/package/coffeelint) | | CSS | [csslint](http://csslint.net/) | | Cython (pyrex filetype) | [cython](http://cython.org/) | diff --git a/ale_linters/c/cppcheck.vim b/ale_linters/c/cppcheck.vim new file mode 100644 index 0000000..891b4ff --- /dev/null +++ b/ale_linters/c/cppcheck.vim @@ -0,0 +1,22 @@ +" Author: Bart Libert +" 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' +endif + +call ale#linter#Define('c', { +\ 'name': 'cppcheck', +\ 'output_stream': 'both', +\ 'executable': 'cppcheck', +\ 'command': g:ale#util#stdin_wrapper . ' .c cppcheck -q --language=c ' +\ . g:ale_c_cppcheck_options, +\ 'callback': 'ale#handlers#HandleCppCheckFormat', +\}) diff --git a/ale_linters/cpp/cppcheck.vim b/ale_linters/cpp/cppcheck.vim new file mode 100644 index 0000000..d805790 --- /dev/null +++ b/ale_linters/cpp/cppcheck.vim @@ -0,0 +1,22 @@ +" Author: Bart Libert +" 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' +endif + +call ale#linter#Define('cpp', { +\ 'name': 'cppcheck', +\ 'output_stream': 'both', +\ 'executable': 'cppcheck', +\ 'command': g:ale#util#stdin_wrapper . ' .cpp cppcheck -q --language=c++ ' +\ . g:ale_cpp_cppcheck_options, +\ 'callback': 'ale#handlers#HandleCppCheckFormat', +\}) diff --git a/autoload/ale/handlers.vim b/autoload/ale/handlers.vim index cca35d4..5322bfb 100644 --- a/autoload/ale/handlers.vim +++ b/autoload/ale/handlers.vim @@ -45,7 +45,6 @@ function! ale#handlers#HandleUnixFormatAsWarning(buffer, lines) abort return s:HandleUnixFormat(a:buffer, a:lines, 'W') endfunction - function! ale#handlers#HandleGCCFormat(buffer, lines) abort " Look for lines like the following. " @@ -76,6 +75,35 @@ function! ale#handlers#HandleGCCFormat(buffer, lines) abort return l:output endfunction +function! ale#handlers#HandleCppCheckFormat(buffer, lines) abort + " Look for lines like the following. + " + " [test.cpp:5]: (error) Array 'a[10]' accessed at index 10, which is out of bounds + let l:pattern = '^\[.\{-}:\(\d\+\)\]: (\(.\{-}\)) \(.\+\)' + let l:output = [] + + for l:line in a:lines + let l:match = matchlist(l:line, l:pattern) + + if len(l:match) == 0 + continue + endif + + call add(l:output, { + \ 'bufnr': a:buffer, + \ 'lnum': l:match[1] + 0, + \ 'vcol': 0, + \ 'col': 0, + \ 'text': l:match[3] . ' (' . l:match[2] . ')', + \ 'type': l:match[2] ==# 'error' ? 'E' : 'W', + \ 'nr': -1, + \}) + endfor + return l:output + +endfunction + + function! ale#handlers#HandleCSSLintFormat(buffer, lines) abort " Matches patterns line the following: " diff --git a/doc/ale.txt b/doc/ale.txt index 3400ed3..ab6f609 100644 --- a/doc/ale.txt +++ b/doc/ale.txt @@ -21,6 +21,8 @@ CONTENTS *ale-contents* 4.9. shellcheck............................|ale-linter-options-shellcheck| 4.10. vint..................................|ale-linter-options-vint| 4.11. luacheck..............................|ale-linter-options-luacheck| + 4.12. c-cppcheck............................|ale-linter-options-c-cppcheck| + 4.13. cpp-cppcheck..........................|ale-linter-options-cpp-cppcheck| 5. API........................................|ale-api| 6. Special Thanks.............................|ale-special-thanks| 7. Contact....................................|ale-contact| @@ -50,8 +52,8 @@ The following languages and tools are supported. * Bash: 'shell' (-n flag), 'shellcheck' * Bourne Shell: 'shell' (-n flag), 'shellcheck' -* C: 'gcc' -* C++ (filetype cpp): 'gcc' +* C: 'cppcheck', 'gcc' +* C++ (filetype cpp): 'cppcheck', 'gcc' * CoffeeScript: 'coffee', 'coffelint' * CSS: 'csslint' * Cython (pyrex filetype): 'cython' @@ -505,6 +507,28 @@ g:ale_lua_luacheck_executable *g:ale_lua_luacheck_executable* This variable can be changed to change the path to luacheck. +------------------------------------------------------------------------------- +4.12. c-cppcheck *ale-linter-options-c-cppcheck* + +g:ale_c_cppcheck_options *g:ale_c_cppcheck_options* + + Type: |String| + Default: `'--enable=style'` + + This variable can be changed to modify flags given to cppcheck. + + +------------------------------------------------------------------------------- +4.13. cpp-cppcheck *ale-linter-options-cpp-cppcheck* + +g:ale_cpp_cppcheck_options *g:ale_cpp_cppcheck_options* + + Type: |String| + Default: `'--enable=style'` + + This variable can be changed to modify flags given to cppcheck. + + =============================================================================== 5. API *ale-api* diff --git a/test/test_common_handlers.vader b/test/test_common_handlers.vader index 678b933..6fee00b 100644 --- a/test/test_common_handlers.vader +++ b/test/test_common_handlers.vader @@ -138,5 +138,33 @@ Then (The loclist should be correct): \ }, \], g:loclist +Execute (Run HandleCppCheckFormat): + let g:loclist = ale#handlers#HandleCppCheckFormat(42, [ + \ '[/tmp/test.c:5]: (style) Variable a is assigned a value that is never used.', + \ '[/tmp/test.c:12]: (error) Array a[10] accessed at index 10, which is out of bounds.' + \]) + +Then (The loclist should be correct): + AssertEqual [ + \ { + \ 'bufnr': 42, + \ 'vcol': 0, + \ 'nr': -1, + \ 'lnum': 5, + \ 'col': 0, + \ 'type': 'W', + \ 'text': 'Variable a is assigned a value that is never used. (style)', + \ }, + \ { + \ 'bufnr': 42, + \ 'vcol': 0, + \ 'nr': -1, + \ 'lnum': 12, + \ 'col': 0, + \ 'type': 'E', + \ 'text': 'Array a[10] accessed at index 10, which is out of bounds. (error)', + \ }, + \], g:loclist + After: unlet g:loclist