fix cppcheck for 1.89+, and add column support (#3030)

* fix cppcheck for 1.89+, and add column support

In cppcheck 1.89 the output changed to be more like GCC. This commit
forces any version of cppcheck to output in that same format. This also
allows for ALE to pick up the linter's column information

* Add parameters to tests. Vader passes.

* Fix c cppcheck for v1.89
This commit is contained in:
tsjordan-eng 2020-08-06 13:50:44 -06:00 committed by GitHub
parent 4044196047
commit f17b74679f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 44 additions and 17 deletions

View file

@ -10,9 +10,11 @@ function! ale_linters#c#cppcheck#GetCommand(buffer) abort
let l:buffer_path_include = empty(l:compile_commands_option) let l:buffer_path_include = empty(l:compile_commands_option)
\ ? ale#handlers#cppcheck#GetBufferPathIncludeOptions(a:buffer) \ ? ale#handlers#cppcheck#GetBufferPathIncludeOptions(a:buffer)
\ : '' \ : ''
let l:template = ' --template=''{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\\n{code}'''
return l:cd_command return l:cd_command
\ . '%e -q --language=c' \ . '%e -q --language=c'
\ . l:template
\ . ale#Pad(l:compile_commands_option) \ . ale#Pad(l:compile_commands_option)
\ . ale#Pad(ale#Var(a:buffer, 'c_cppcheck_options')) \ . ale#Pad(ale#Var(a:buffer, 'c_cppcheck_options'))
\ . l:buffer_path_include \ . l:buffer_path_include

View file

@ -10,9 +10,11 @@ function! ale_linters#cpp#cppcheck#GetCommand(buffer) abort
let l:buffer_path_include = empty(l:compile_commands_option) let l:buffer_path_include = empty(l:compile_commands_option)
\ ? ale#handlers#cppcheck#GetBufferPathIncludeOptions(a:buffer) \ ? ale#handlers#cppcheck#GetBufferPathIncludeOptions(a:buffer)
\ : '' \ : ''
let l:template = ' --template=''{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\\n{code}'''
return l:cd_command return l:cd_command
\ . '%e -q --language=c++' \ . '%e -q --language=c++'
\ . l:template
\ . ale#Pad(l:compile_commands_option) \ . ale#Pad(l:compile_commands_option)
\ . ale#Pad(ale#Var(a:buffer, 'cpp_cppcheck_options')) \ . ale#Pad(ale#Var(a:buffer, 'cpp_cppcheck_options'))
\ . l:buffer_path_include \ . l:buffer_path_include

View file

@ -44,16 +44,21 @@ endfunction
function! ale#handlers#cppcheck#HandleCppCheckFormat(buffer, lines) abort function! ale#handlers#cppcheck#HandleCppCheckFormat(buffer, lines) abort
" Look for lines like the following. " Look for lines like the following.
" "
" [test.cpp:5]: (error) Array 'a[10]' accessed at index 10, which is out of bounds "test.cpp:974:6: error: Array 'n[3]' accessed at index 3, which is out of bounds. [arrayIndexOutOfBounds]\
let l:pattern = '\v^\[(.+):(\d+)\]: \(([a-z]+)\) (.+)$' " n[3]=3;
" ^
let l:pattern = '\v^(\f+):(\d+):(\d+): (\w+): (.*) \[(\w+)\]\'
let l:output = [] let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:match in ale#util#GetMatches(a:lines, l:pattern)
if ale#path#IsBufferPath(a:buffer, l:match[1]) if ale#path#IsBufferPath(a:buffer, l:match[1])
call add(l:output, { call add(l:output, {
\ 'lnum': str2nr(l:match[2]), \ 'lnum': str2nr(l:match[2]),
\ 'type': l:match[3] is# 'error' ? 'E' : 'W', \ 'col': str2nr(l:match[3]),
\ 'text': l:match[4], \ 'type': l:match[4] is# 'error' ? 'E' : 'W',
\ 'sub_type': l:match[4] is# 'style' ? 'style' : '',
\ 'text': l:match[5],
\ 'code': l:match[6]
\}) \})
endif endif
endfor endfor

View file

@ -1,7 +1,6 @@
Before: Before:
call ale#assert#SetUpLinterTest('c', 'cppcheck') call ale#assert#SetUpLinterTest('c', 'cppcheck')
let b:command_tail = ' -q --language=c --template=''{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\\n{code}'' --enable=style -I' . ale#Escape(ale#path#Simplify(g:dir)) .' %t'
let b:command_tail = ' -q --language=c --enable=style -I' . ale#Escape(ale#path#Simplify(g:dir)) .' %t'
After: After:
" Remove a test file we might open for some tests. " Remove a test file we might open for some tests.
@ -10,9 +9,8 @@ After:
set buftype=nofile set buftype=nofile
endif endif
call ale#assert#TearDownLinterTest()
unlet! b:command_tail unlet! b:command_tail
call ale#assert#TearDownLinterTest()
Execute(The executable should be configurable): Execute(The executable should be configurable):
AssertLinter 'cppcheck', ale#Escape('cppcheck') . b:command_tail AssertLinter 'cppcheck', ale#Escape('cppcheck') . b:command_tail
@ -28,6 +26,7 @@ Execute(cppcheck for C should detect compile_commands.json files):
\ ale#path#CdString(ale#path#Simplify(g:dir . '/cppcheck_paths/one')) \ ale#path#CdString(ale#path#Simplify(g:dir . '/cppcheck_paths/one'))
\ . ale#Escape('cppcheck') \ . ale#Escape('cppcheck')
\ . ' -q --language=c' \ . ' -q --language=c'
\ . ' --template=''{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\\n{code}'''
\ . ' --project=' . ale#Escape('compile_commands.json') \ . ' --project=' . ale#Escape('compile_commands.json')
\ . ' --enable=style %t' \ . ' --enable=style %t'
@ -38,6 +37,7 @@ Execute(cppcheck for C should detect compile_commands.json files in build direct
\ ale#path#CdString(ale#path#Simplify(g:dir . '/cppcheck_paths/with_build_dir')) \ ale#path#CdString(ale#path#Simplify(g:dir . '/cppcheck_paths/with_build_dir'))
\ . ale#Escape('cppcheck') \ . ale#Escape('cppcheck')
\ . ' -q --language=c' \ . ' -q --language=c'
\ . ' --template=''{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\\n{code}'''
\ . ' --project=' . ale#Escape(ale#path#Simplify('build/compile_commands.json')) \ . ' --project=' . ale#Escape(ale#path#Simplify('build/compile_commands.json'))
\ . ' --enable=style %t' \ . ' --enable=style %t'
@ -47,6 +47,7 @@ Execute(cppcheck for C should include file dir if compile_commands.json file is
AssertLinter 'cppcheck', AssertLinter 'cppcheck',
\ ale#Escape('cppcheck') \ ale#Escape('cppcheck')
\ . ' -q --language=c' \ . ' -q --language=c'
\ . ' --template=''{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\\n{code}'''
\ . ' --enable=style' \ . ' --enable=style'
\ . ' -I' . ale#Escape(ale#path#Simplify(g:dir . '/cppcheck_paths')) \ . ' -I' . ale#Escape(ale#path#Simplify(g:dir . '/cppcheck_paths'))
\ . ' %t' \ . ' %t'
@ -61,6 +62,7 @@ Execute(cppcheck for C should ignore compile_commands.json file if buffer is mod
\ ale#path#CdString(ale#path#Simplify(g:dir . '/cppcheck_paths/one')) \ ale#path#CdString(ale#path#Simplify(g:dir . '/cppcheck_paths/one'))
\ . ale#Escape('cppcheck') \ . ale#Escape('cppcheck')
\ . ' -q --language=c' \ . ' -q --language=c'
\ . ' --template=''{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\\n{code}'''
\ . ' --enable=style' \ . ' --enable=style'
\ . ' -I' . ale#Escape(ale#path#Simplify(g:dir . '/cppcheck_paths/one')) \ . ' -I' . ale#Escape(ale#path#Simplify(g:dir . '/cppcheck_paths/one'))
\ . ' %t' \ . ' %t'

View file

@ -1,6 +1,6 @@
Before: Before:
call ale#assert#SetUpLinterTest('cpp', 'cppcheck') call ale#assert#SetUpLinterTest('cpp', 'cppcheck')
let b:command_tail = ' -q --language=c++ --enable=style -I' . ale#Escape(ale#path#Simplify(g:dir)) .' %t' let b:command_tail = ' -q --language=c++ --template=''{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\\n{code}'' --enable=style -I' . ale#Escape(ale#path#Simplify(g:dir)) .' %t'
After: After:
" Remove a test file we might open for some tests. " Remove a test file we might open for some tests.
@ -26,6 +26,7 @@ Execute(cppcheck for C++ should detect compile_commands.json files):
\ ale#path#CdString(ale#path#Simplify(g:dir . '/cppcheck_paths/one')) \ ale#path#CdString(ale#path#Simplify(g:dir . '/cppcheck_paths/one'))
\ . ale#Escape('cppcheck') \ . ale#Escape('cppcheck')
\ . ' -q --language=c++' \ . ' -q --language=c++'
\ . ' --template=''{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\\n{code}'''
\ . ' --project=' . ale#Escape('compile_commands.json') \ . ' --project=' . ale#Escape('compile_commands.json')
\ . ' --enable=style %t' \ . ' --enable=style %t'
@ -36,6 +37,7 @@ Execute(cppcheck for C++ should detect compile_commands.json files in build dire
\ ale#path#CdString(ale#path#Simplify(g:dir . '/cppcheck_paths/with_build_dir')) \ ale#path#CdString(ale#path#Simplify(g:dir . '/cppcheck_paths/with_build_dir'))
\ . ale#Escape('cppcheck') \ . ale#Escape('cppcheck')
\ . ' -q --language=c++' \ . ' -q --language=c++'
\ . ' --template=''{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\\n{code}'''
\ . ' --project=' . ale#Escape(ale#path#Simplify('build/compile_commands.json')) \ . ' --project=' . ale#Escape(ale#path#Simplify('build/compile_commands.json'))
\ . ' --enable=style %t' \ . ' --enable=style %t'
@ -45,6 +47,7 @@ Execute(cppcheck for C++ should include file dir if compile_commands.json file i
AssertLinter 'cppcheck', AssertLinter 'cppcheck',
\ ale#Escape('cppcheck') \ ale#Escape('cppcheck')
\ . ' -q --language=c++' \ . ' -q --language=c++'
\ . ' --template=''{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\\n{code}'''
\ . ' --enable=style' \ . ' --enable=style'
\ . ' -I' . ale#Escape(ale#path#Simplify(g:dir . '/cppcheck_paths')) \ . ' -I' . ale#Escape(ale#path#Simplify(g:dir . '/cppcheck_paths'))
\ . ' %t' \ . ' %t'
@ -59,6 +62,7 @@ Execute(cppcheck for C++ should ignore compile_commands.json file if buffer is m
\ ale#path#CdString(ale#path#Simplify(g:dir . '/cppcheck_paths/one')) \ ale#path#CdString(ale#path#Simplify(g:dir . '/cppcheck_paths/one'))
\ . ale#Escape('cppcheck') \ . ale#Escape('cppcheck')
\ . ' -q --language=c++' \ . ' -q --language=c++'
\ . ' --template=''{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\\n{code}'''
\ . ' --enable=style' \ . ' --enable=style'
\ . ' -I' . ale#Escape(ale#path#Simplify(g:dir . '/cppcheck_paths/one')) \ . ' -I' . ale#Escape(ale#path#Simplify(g:dir . '/cppcheck_paths/one'))
\ . ' %t' \ . ' %t'

View file

@ -10,19 +10,29 @@ Execute(Basic errors should be handled by cppcheck):
AssertEqual AssertEqual
\ [ \ [
\ { \ {
\ 'lnum': 5, \ 'lnum': 974,
\ 'col' : 6,
\ 'type': 'E', \ 'type': 'E',
\ 'text': 'Array ''a[10]'' accessed at index 10, which is out of bounds', \ 'sub_type': '',
\ 'text': 'Array ''n[3]'' accessed at index 3, which is out of bounds.',
\ 'code': 'arrayIndexOutOfBounds'
\ }, \ },
\ { \ {
\ 'lnum': 7, \ 'lnum': 1185,
\ 'col' : 10,
\ 'type': 'W', \ 'type': 'W',
\ 'text': 'Some other problem', \ 'sub_type': 'style',
\ 'text': 'The scope of the variable ''indxStr'' can be reduced.',
\ 'code': 'variableScope'
\ }, \ },
\ ], \ ],
\ ale#handlers#cppcheck#HandleCppCheckFormat(bufnr(''), [ \ ale#handlers#cppcheck#HandleCppCheckFormat(bufnr(''), [
\ '[test.cpp:5]: (error) Array ''a[10]'' accessed at index 10, which is out of bounds', \ 'test.cpp:974:6: error: Array ''n[3]'' accessed at index 3, which is out of bounds. [arrayIndexOutOfBounds]\',
\ '[test.cpp:7]: (warning) Some other problem', \ ' n[3]=3;',
\ ' ^',
\ 'test.cpp:1185:10: style: The scope of the variable ''indxStr'' can be reduced. [variableScope]\',
\ ' char indxStr[16];',
\ ' ^',
\ ]) \ ])
Execute(Problems from other files should be ignored by cppcheck): Execute(Problems from other files should be ignored by cppcheck):
@ -32,5 +42,7 @@ Execute(Problems from other files should be ignored by cppcheck):
\ [ \ [
\ ], \ ],
\ ale#handlers#cppcheck#HandleCppCheckFormat(bufnr(''), [ \ ale#handlers#cppcheck#HandleCppCheckFormat(bufnr(''), [
\ '[bar.cpp:5]: (error) Array ''a[10]'' accessed at index 10, which is out of bounds', \ 'bar.cpp:974:6: error: Array ''n[3]'' accessed at index 3, which is out of bounds. [arrayIndexOutOfBounds]\',
\ ' n[3]=3;',
\ ' ^',
\ ]) \ ])