Add clangtidy fixer (#2548)

* Add clangtidy fixer
* Add extra_options to clangtidy fixer
* Also, use cpp variables in cpp filetypes
This commit is contained in:
ObserverOfTime 2019-07-02 10:11:10 +03:00 committed by w0rp
parent 89f7292138
commit 8700586890
5 changed files with 126 additions and 0 deletions

View File

@ -145,6 +145,11 @@ let s:default_registry = {
\ 'suggested_filetypes': ['php'],
\ 'description': 'Fix PHP files with php-cs-fixer.',
\ },
\ 'clangtidy': {
\ 'function': 'ale#fixers#clangtidy#Fix',
\ 'suggested_filetypes': ['c', 'cpp', 'objc'],
\ 'description': 'Fix C/C++ and ObjectiveC files with clang-tidy.',
\ },
\ 'clang-format': {
\ 'function': 'ale#fixers#clangformat#Fix',
\ 'suggested_filetypes': ['c', 'cpp', 'cuda'],

View File

@ -0,0 +1,52 @@
scriptencoding utf-8
" Author: ObserverOfTime <chronobserver@disroot.org>
" Description: Fixing C/C++ files with clang-tidy.
function! s:set_variables() abort
let l:use_global = get(g:, 'ale_use_global_executables', 0)
for l:ft in ['c', 'cpp']
call ale#Set(l:ft . '_clangtidy_executable', 'clang-tidy')
call ale#Set(l:ft . '_clangtidy_use_global', l:use_global)
call ale#Set(l:ft . '_clangtidy_checks', [])
call ale#Set(l:ft . '_clangtidy_options', '')
call ale#Set(l:ft . '_clangtidy_extra_options', '')
call ale#Set(l:ft . '_clangtidy_fix_errors', 1)
endfor
call ale#Set('c_build_dir', '')
endfunction
call s:set_variables()
function! ale#fixers#clangtidy#Var(buffer, name) abort
let l:ft = getbufvar(str2nr(a:buffer), '&filetype')
let l:ft = l:ft =~# 'cpp' ? 'cpp' : 'c'
return ale#Var(a:buffer, l:ft . '_clangtidy_' . a:name)
endfunction
function! ale#fixers#clangtidy#GetCommand(buffer) abort
let l:checks = join(ale#fixers#clangtidy#Var(a:buffer, 'checks'), ',')
let l:extra_options = ale#fixers#clangtidy#Var(a:buffer, 'extra_options')
let l:build_dir = ale#c#GetBuildDirectory(a:buffer)
let l:options = empty(l:build_dir)
\ ? ale#fixers#clangtidy#Var(a:buffer, 'options') : ''
let l:fix_errors = ale#fixers#clangtidy#Var(a:buffer, 'fix_errors')
return ' -fix' . (l:fix_errors ? ' -fix-errors' : '')
\ . (empty(l:checks) ? '' : ' -checks=' . ale#Escape(l:checks))
\ . (empty(l:extra_options) ? '' : ' ' . l:extra_options)
\ . (empty(l:build_dir) ? '' : ' -p ' . ale#Escape(l:build_dir))
\ . ' %t' . (empty(l:options) ? '' : ' -- ' . l:options)
endfunction
function! ale#fixers#clangtidy#Fix(buffer) abort
let l:executable = ale#fixers#clangtidy#Var(a:buffer, 'executable')
let l:command = ale#fixers#clangtidy#GetCommand(a:buffer)
return {
\ 'command': ale#Escape(l:executable) . l:command,
\ 'read_temporary_file': 1,
\}
endfunction

View File

@ -177,6 +177,15 @@ g:ale_c_clangtidy_extra_options *g:ale_c_clangtidy_extra_options*
This variable can be changed to modify flags given to clang-tidy.
g:ale_c_clangtidy_fix_errors *g:ale_c_clangtidy_fix_errors*
*b:ale_c_clangtidy_fix_errors*
Type: |Number|
Default: `1`
This variable can be changed to disable the `-fix-errors` option for the
|clangtidy| fixer.
===============================================================================
cppcheck *ale-c-cppcheck*

View File

@ -146,6 +146,15 @@ g:ale_cpp_clangtidy_extra_options *g:ale_cpp_clangtidy_extra_options*
This variable can be changed to modify flags given to clang-tidy.
g:ale_cpp_clangtidy_fix_errors *g:ale_cpp_clangtidy_fix_errors*
*b:ale_cpp_clangtidy_fix_errors*
Type: |Number|
Default: `1`
This variable can be changed to disable the `-fix-errors` option for the
|clangtidy| fixer.
===============================================================================
clazy *ale-cpp-clazy*

View File

@ -0,0 +1,51 @@
Before:
Save g:ale_c_clangtidy_executable
" Use an invalid global executable, so we don't match it.
let g:ale_c_clangtidy_executable = 'xxxinvalid'
let g:ale_c_build_dir = ''
call ale#test#SetDirectory('/testplugin/test/fixers')
silent cd ../command_callback
let g:dir = getcwd()
After:
Restore
call ale#test#RestoreDirectory()
Execute(The clangtidy callback should return the correct default values):
call ale#test#SetFilename('c_paths/dummy.c')
AssertEqual
\ {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape(g:ale_c_clangtidy_executable)
\ . ' -fix -fix-errors %t'
\ },
\ ale#fixers#clangtidy#Fix(bufnr(''))
Execute(The clangtidy callback should include any additional options):
call ale#test#SetFilename('c_paths/dummy.c')
let g:ale_c_clangtidy_extra_options = '--some-option'
AssertEqual
\ {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape(g:ale_c_clangtidy_executable)
\ . ' -fix -fix-errors --some-option %t',
\ },
\ ale#fixers#clangtidy#Fix(bufnr(''))
Execute(The clangtidy callback should support cpp files):
call ale#test#SetFilename('c_paths/dummy.cpp')
let g:ale_cpp_clangtidy_executable = 'invalidpp'
set filetype=cpp " The test fails without this
AssertEqual
\ {
\ 'read_temporary_file': 1,
\ 'command': ale#Escape(g:ale_cpp_clangtidy_executable)
\ . ' -fix -fix-errors %t',
\ },
\ ale#fixers#clangtidy#Fix(bufnr(''))