From a767578d44dd96bfcb395a8cc605b1905f5393dd Mon Sep 17 00:00:00 2001 From: Andrej Radovic Date: Sat, 5 Aug 2017 15:21:02 +0200 Subject: [PATCH 1/4] Added clang-tidy for C, too. A limited number of clang-tidy checks can be used with C, too. I pretty much copied and refactored the C++ clang-tidy linter, and added some documentation about C-compatible checks. --- README.md | 2 +- ale_linters/c/clangtidy.vim | 107 ++++++++++++++++++++++++++++++ doc/ale-c.txt | 129 ++++++++++++++++++++++++++++++++++++ doc/ale.txt | 1 + 4 files changed, 238 insertions(+), 1 deletion(-) create mode 100644 ale_linters/c/clangtidy.vim diff --git a/README.md b/README.md index e90474e..cf1e992 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ name. That seems to be the fairest way to arrange this table. | Awk | [gawk](https://www.gnu.org/software/gawk/)| | 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 | [cppcheck](http://cppcheck.sourceforge.net), [gcc](https://gcc.gnu.org/), [clang](http://clang.llvm.org/)| +| C | [cppcheck](http://cppcheck.sourceforge.net), [gcc](https://gcc.gnu.org/), [clang](http://clang.llvm.org/), [clangtidy](http://clang.llvm.org/extra/clang-tidy/)| | C++ (filetype cpp) | [clang](http://clang.llvm.org/), [clangcheck](http://clang.llvm.org/docs/ClangCheck.html), [clangtidy](http://clang.llvm.org/extra/clang-tidy/), [cppcheck](http://cppcheck.sourceforge.net), [cpplint](https://github.com/google/styleguide/tree/gh-pages/cpplint), [gcc](https://gcc.gnu.org/)| | C# | [mcs](http://www.mono-project.com/docs/about-mono/languages/csharp/) | | Chef | [foodcritic](http://www.foodcritic.io/) | diff --git a/ale_linters/c/clangtidy.vim b/ale_linters/c/clangtidy.vim new file mode 100644 index 0000000..e92c0c0 --- /dev/null +++ b/ale_linters/c/clangtidy.vim @@ -0,0 +1,107 @@ +" Author: vdeurzen , w0rp , +" gagbo , Andrej Radovic +" Description: clang-tidy linter for c files + +call ale#Set('c_clangtidy_executable', 'clang-tidy') +" Set this option to check the checks clang-tidy will apply. +" The number of checks that can be applied to C files is limited in contrast to +" C++ +" +" Here is an incomplete list of C-compatible checks for clang-tidy version 6: +" bugprone-suspicious-memset-usage +" cert-env33-c +" cert-err34-c +" cert-flp30-c +" google-runtime-int +" llvm-header-guard +" llvm-include-order +" misc-argument-comment +" misc-assert-side-effect +" misc-bool-pointer-implicit-conversion +" misc-definitions-in-headers +" misc-incorrect-roundings +" misc-macro-parentheses +" misc-macro-repeated-side-effects +" misc-misplaced-const +" misc-misplaced-widening-cast +" misc-multiple-statement-macro +" misc-non-copyable-objects +" misc-redundant-expression +" misc-sizeof-expression +" misc-static-assert +" misc-string-literal-with-embedded-nul +" misc-suspicious-enum-usage +" misc-suspicious-missing-comma +" misc-suspicious-semicolon +" misc-suspicious-string-compare +" misc-swapped-arguments +" modernize-redundant-void-arg +" modernize-use-bool-literals +" performance-type-promotion-in-math-fn +" readability-braces-around-statements +" readability-else-after-return +" readability-function-size +" readability-identifier-naming +" readability-implicit-bool-cast +" readability-inconsistent-declaration-parameter-name +" readability-misleading-indentation +" readability-misplaced-array-index +" readability-named-parameter +" readability-non-const-parameter +" readability-redundant-control-flow +" readability-redundant-declaration +" readability-redundant-function-ptr-dereference +" readability-simplify-boolean-expr + +call ale#Set('c_clangtidy_checks', ['*']) +" Set this option to manually set some options for clang-tidy. +" This will disable compile_commands.json detection. +call ale#Set('c_clangtidy_options', '') +call ale#Set('c_build_dir', '') + +function! ale_linters#c#clangtidy#GetExecutable(buffer) abort + return ale#Var(a:buffer, 'c_clangtidy_executable') +endfunction + +function! s:GetBuildDirectory(buffer) abort + " Don't include build directory for header files, as compile_commands.json + " files don't consider headers to be translation units, and provide no + " commands for compiling header files. + if expand('#' . a:buffer) =~# '\v\.(h|hpp)$' + return '' + endif + + let l:build_dir = ale#Var(a:buffer, 'c_build_dir') + + " c_build_dir has the priority if defined + if !empty(l:build_dir) + return l:build_dir + endif + + return ale#c#FindCompileCommands(a:buffer) +endfunction + +function! ale_linters#c#clangtidy#GetCommand(buffer) abort + let l:checks = join(ale#Var(a:buffer, 'c_clangtidy_checks'), ',') + let l:build_dir = s:GetBuildDirectory(a:buffer) + + " Get the extra options if we couldn't find a build directory. + let l:options = empty(l:build_dir) + \ ? ale#Var(a:buffer, 'c_clangtidy_options') + \ : '' + + return ale#Escape(ale_linters#c#clangtidy#GetExecutable(a:buffer)) + \ . (!empty(l:checks) ? ' -checks=' . ale#Escape(l:checks) : '') + \ . ' %s' + \ . (!empty(l:build_dir) ? ' -p ' . ale#Escape(l:build_dir) : '') + \ . (!empty(l:options) ? ' -- ' . l:options : '') +endfunction + +call ale#linter#Define('c', { +\ 'name': 'clangtidy', +\ 'output_stream': 'stdout', +\ 'executable_callback': 'ale_linters#c#clangtidy#GetExecutable', +\ 'command_callback': 'ale_linters#c#clangtidy#GetCommand', +\ 'callback': 'ale#handlers#gcc#HandleGCCFormat', +\ 'lint_file': 1, +\}) diff --git a/doc/ale-c.txt b/doc/ale-c.txt index 2572d88..eb52bc1 100644 --- a/doc/ale-c.txt +++ b/doc/ale-c.txt @@ -2,6 +2,37 @@ ALE C Integration *ale-c-options* +=============================================================================== +Global Options + +g:ale_c_build_dir_names *g:ale_c_build_dir_names* + *b:ale_c_build_dir_names* + + Type: |List| + Default: `['build', 'bin']` + + A list of directory names to be used when searching upwards from cpp + files to discover compilation databases with. For directory named `'foo'`, + ALE will search for `'foo/compile_commands.json'` in all directories on and above + the directory containing the cpp file to find path to compilation database. + This feature is useful for the clang tools wrapped around LibTooling (namely + here, clang-tidy) + + +g:ale_c_build_dir *g:ale_c_build_dir* + *b:ale_c_build_dir* + + Type: |String| + Default: `''` + + A path to the directory containing the `compile_commands.json` file to use + with c-family linters. Usually setting this option to a non-empty string + will override the |g:ale_c_build_dir_names| option to impose a compilation + database (it can be useful if multiple builds are in multiple build + subdirectories in the project tree). + This feature is also most useful for the clang tools linters, wrapped + aroung LibTooling (namely clang-tidy here) + =============================================================================== clang *ale-c-clang* @@ -21,6 +52,104 @@ g:ale_c_clang_options *g:ale_c_clang_options* This variable can be changed to modify flags given to clang. +=============================================================================== +clangtidy *ale-c-clangtidy* + +`clang-tidy` will be run only when files are saved to disk, so that +`compile_commands.json` files can be used. It is recommended to use this +linter in combination with `compile_commands.json` files. +Therefore, `clang-tidy` linter reads the options |g:ale_c_build_dir| and +|g:ale_c_build_dir_names|. Also, setting |g:ale_c_build_dir| actually +overrides |g:ale_c_build_dir_names|. + + +g:ale_c_clangtidy_checks *g:ale_c_clangtidy_checks* + *b:ale_c_clangtidy_checks* + Type: |List| + Default: `['*']` + + The checks to enable for clang-tidy with the `-checks` argument. + + All options will be joined with commas, and escaped appropriately for + the shell. The `-checks` flag can be removed entirely by setting this + option to an empty List. + + Not all of clangtidy checks are applicable for C. You should consult the + clang documentation for an up-to-date list of compatible checks. + + Here's an (incomplete) list of C-compatible checks, for clang-tidy version 6: + bugprone-suspicious-memset-usage + cert-env33-c + cert-err34-c + cert-flp30-c + google-runtime-int + llvm-header-guard + llvm-include-order + misc-argument-comment + misc-assert-side-effect + misc-bool-pointer-implicit-conversion + misc-definitions-in-headers + misc-incorrect-roundings + misc-macro-parentheses + misc-macro-repeated-side-effects + misc-misplaced-const + misc-misplaced-widening-cast + misc-multiple-statement-macro + misc-non-copyable-objects + misc-redundant-expression + misc-sizeof-expression + misc-static-assert + misc-string-literal-with-embedded-nul + misc-suspicious-enum-usage + misc-suspicious-missing-comma + misc-suspicious-semicolon + misc-suspicious-string-compare + misc-swapped-arguments + modernize-redundant-void-arg + modernize-use-bool-literals + performance-type-promotion-in-math-fn + readability-braces-around-statements + readability-else-after-return + readability-function-size + readability-identifier-naming + readability-implicit-bool-cast + readability-inconsistent-declaration-parameter-name + readability-misleading-indentation + readability-misplaced-array-index + readability-named-parameter + readability-non-const-parameter + readability-redundant-control-flow + readability-redundant-declaration + readability-redundant-function-ptr-dereference + readability-simplify-boolean-expr + + +g:ale_c_clangtidy_executable *g:ale_c_clangtidy_executable* + *b:ale_c_clangtidy_executable* + Type: |String| + Default: `'clang-tidy'` + + This variable can be changed to use a different executable for clangtidy. + + +g:ale_c_clangtidy_options *g:ale_c_clangtidy_options* + *b:ale_c_clangtidy_options* + Type: |String| + Default: `''` + + This variable can be changed to modify flags given to clang-tidy. + + - Setting this variable to a non-empty string, + - and working in a buffer where no compilation database is found using + |g:ale_c_build_dir_names| or |g:ale_c_build_dir|, + will cause the `--` argument to be passed to `clang-tidy`, which will mean + that detection of `compile_commands.json` files for compile command + databases will be disabled. + Only set this option if you want to control compiler flags + entirely manually, and no `compile_commands.json` file is in one + of the |g:ale_c_build_dir_names| directories of the project tree. + + =============================================================================== cppcheck *ale-c-cppcheck* diff --git a/doc/ale.txt b/doc/ale.txt index 8647637..944431d 100644 --- a/doc/ale.txt +++ b/doc/ale.txt @@ -16,6 +16,7 @@ CONTENTS *ale-contents* gcc.................................|ale-asm-gcc| c.....................................|ale-c-options| clang...............................|ale-c-clang| + clangtidy...........................|ale-c-clangtidy| cppcheck............................|ale-c-cppcheck| gcc.................................|ale-c-gcc| chef..................................|ale-chef-options| From 70cd1d5a57318dbbe36e548f705dce4bcd5df267 Mon Sep 17 00:00:00 2001 From: Andrej Radovic Date: Sun, 6 Aug 2017 13:14:09 +0200 Subject: [PATCH 2/4] Fixed the comments, left only the doc URL --- ale_linters/c/clangtidy.vim | 47 ++--------------------------------- doc/ale-c.txt | 49 ++----------------------------------- 2 files changed, 4 insertions(+), 92 deletions(-) diff --git a/ale_linters/c/clangtidy.vim b/ale_linters/c/clangtidy.vim index e92c0c0..47faa1e 100644 --- a/ale_linters/c/clangtidy.vim +++ b/ale_linters/c/clangtidy.vim @@ -7,51 +7,8 @@ call ale#Set('c_clangtidy_executable', 'clang-tidy') " The number of checks that can be applied to C files is limited in contrast to " C++ " -" Here is an incomplete list of C-compatible checks for clang-tidy version 6: -" bugprone-suspicious-memset-usage -" cert-env33-c -" cert-err34-c -" cert-flp30-c -" google-runtime-int -" llvm-header-guard -" llvm-include-order -" misc-argument-comment -" misc-assert-side-effect -" misc-bool-pointer-implicit-conversion -" misc-definitions-in-headers -" misc-incorrect-roundings -" misc-macro-parentheses -" misc-macro-repeated-side-effects -" misc-misplaced-const -" misc-misplaced-widening-cast -" misc-multiple-statement-macro -" misc-non-copyable-objects -" misc-redundant-expression -" misc-sizeof-expression -" misc-static-assert -" misc-string-literal-with-embedded-nul -" misc-suspicious-enum-usage -" misc-suspicious-missing-comma -" misc-suspicious-semicolon -" misc-suspicious-string-compare -" misc-swapped-arguments -" modernize-redundant-void-arg -" modernize-use-bool-literals -" performance-type-promotion-in-math-fn -" readability-braces-around-statements -" readability-else-after-return -" readability-function-size -" readability-identifier-naming -" readability-implicit-bool-cast -" readability-inconsistent-declaration-parameter-name -" readability-misleading-indentation -" readability-misplaced-array-index -" readability-named-parameter -" readability-non-const-parameter -" readability-redundant-control-flow -" readability-redundant-declaration -" readability-redundant-function-ptr-dereference -" readability-simplify-boolean-expr +" Consult the check list in clang-tidy's documentation: +" http://clang.llvm.org/extra/clang-tidy/checks/list.html call ale#Set('c_clangtidy_checks', ['*']) " Set this option to manually set some options for clang-tidy. diff --git a/doc/ale-c.txt b/doc/ale-c.txt index eb52bc1..8188b87 100644 --- a/doc/ale-c.txt +++ b/doc/ale-c.txt @@ -75,53 +75,8 @@ g:ale_c_clangtidy_checks *g:ale_c_clangtidy_checks* option to an empty List. Not all of clangtidy checks are applicable for C. You should consult the - clang documentation for an up-to-date list of compatible checks. - - Here's an (incomplete) list of C-compatible checks, for clang-tidy version 6: - bugprone-suspicious-memset-usage - cert-env33-c - cert-err34-c - cert-flp30-c - google-runtime-int - llvm-header-guard - llvm-include-order - misc-argument-comment - misc-assert-side-effect - misc-bool-pointer-implicit-conversion - misc-definitions-in-headers - misc-incorrect-roundings - misc-macro-parentheses - misc-macro-repeated-side-effects - misc-misplaced-const - misc-misplaced-widening-cast - misc-multiple-statement-macro - misc-non-copyable-objects - misc-redundant-expression - misc-sizeof-expression - misc-static-assert - misc-string-literal-with-embedded-nul - misc-suspicious-enum-usage - misc-suspicious-missing-comma - misc-suspicious-semicolon - misc-suspicious-string-compare - misc-swapped-arguments - modernize-redundant-void-arg - modernize-use-bool-literals - performance-type-promotion-in-math-fn - readability-braces-around-statements - readability-else-after-return - readability-function-size - readability-identifier-naming - readability-implicit-bool-cast - readability-inconsistent-declaration-parameter-name - readability-misleading-indentation - readability-misplaced-array-index - readability-named-parameter - readability-non-const-parameter - readability-redundant-control-flow - readability-redundant-declaration - readability-redundant-function-ptr-dereference - readability-simplify-boolean-expr + clang documentation for an up-to-date list of compatible checks: + http://clang.llvm.org/extra/clang-tidy/checks/list.html g:ale_c_clangtidy_executable *g:ale_c_clangtidy_executable* From e4a6da936d68310a5bf4d744f2275e57e0a62724 Mon Sep 17 00:00:00 2001 From: Andrej Radovic Date: Sun, 6 Aug 2017 13:15:02 +0200 Subject: [PATCH 3/4] Fixed helptag alignment. --- doc/ale-c.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/ale-c.txt b/doc/ale-c.txt index 8188b87..29208bc 100644 --- a/doc/ale-c.txt +++ b/doc/ale-c.txt @@ -53,7 +53,7 @@ g:ale_c_clang_options *g:ale_c_clang_options* =============================================================================== -clangtidy *ale-c-clangtidy* +clangtidy *ale-c-clangtidy* `clang-tidy` will be run only when files are saved to disk, so that `compile_commands.json` files can be used. It is recommended to use this @@ -79,16 +79,16 @@ g:ale_c_clangtidy_checks *g:ale_c_clangtidy_checks* http://clang.llvm.org/extra/clang-tidy/checks/list.html -g:ale_c_clangtidy_executable *g:ale_c_clangtidy_executable* - *b:ale_c_clangtidy_executable* +g:ale_c_clangtidy_executable *g:ale_c_clangtidy_executable* + *b:ale_c_clangtidy_executable* Type: |String| Default: `'clang-tidy'` This variable can be changed to use a different executable for clangtidy. -g:ale_c_clangtidy_options *g:ale_c_clangtidy_options* - *b:ale_c_clangtidy_options* +g:ale_c_clangtidy_options *g:ale_c_clangtidy_options* + *b:ale_c_clangtidy_options* Type: |String| Default: `''` From 9958a8d32ed505275b3bb374cb87e722a9557eed Mon Sep 17 00:00:00 2001 From: w0rp Date: Wed, 30 Aug 2017 22:11:04 +0100 Subject: [PATCH 4/4] Add tests for the c version of clang-tidy --- .../test_c_clang_tidy_command_callback.vader | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 test/command_callback/test_c_clang_tidy_command_callback.vader diff --git a/test/command_callback/test_c_clang_tidy_command_callback.vader b/test/command_callback/test_c_clang_tidy_command_callback.vader new file mode 100644 index 0000000..722a14f --- /dev/null +++ b/test/command_callback/test_c_clang_tidy_command_callback.vader @@ -0,0 +1,97 @@ +Before: + Save g:ale_c_clangtidy_checks + Save g:ale_c_clangtidy_options + Save g:ale_c_build_dir + + unlet! g:ale_c_build_dir + unlet! b:ale_c_build_dir + unlet! g:ale_c_clangtidy_checks + unlet! b:ale_c_clangtidy_checks + unlet! g:ale_c_clangtidy_options + unlet! b:ale_c_clangtidy_options + + runtime ale_linters/c/clangtidy.vim + + call ale#test#SetFilename('test.c') + +After: + unlet! b:ale_c_build_dir + unlet! b:ale_c_clangtidy_checks + unlet! b:ale_c_clangtidy_options + unlet! b:ale_c_clangtidy_executable + + Restore + call ale#linter#Reset() + +Execute(The clangtidy command default should be correct): + AssertEqual + \ ale#Escape('clang-tidy') + \ . ' -checks=''*'' %s', + \ ale_linters#c#clangtidy#GetCommand(bufnr('')) + +Execute(You should be able to remove the -checks option for clang-tidy): + let b:ale_c_clangtidy_checks = [] + + AssertEqual + \ ale#Escape('clang-tidy') + \ . ' %s', + \ ale_linters#c#clangtidy#GetCommand(bufnr('')) + +Execute(You should be able to set other checks for clang-tidy): + let b:ale_c_clangtidy_checks = ['-*', 'clang-analyzer-*'] + + AssertEqual + \ ale#Escape('clang-tidy') + \ . ' -checks=''-*,clang-analyzer-*'' %s', + \ ale_linters#c#clangtidy#GetCommand(bufnr('')) + +Execute(You should be able to manually set compiler flags for clang-tidy): + let b:ale_c_clangtidy_options = '-Wall' + + AssertEqual + \ ale#Escape('clang-tidy') + \ . ' -checks=''*'' %s -- -Wall', + \ ale_linters#c#clangtidy#GetCommand(bufnr('')) + \ +Execute(The build directory should be configurable): + let b:ale_c_build_dir = '/foo/bar' + + AssertEqual + \ ale#Escape('clang-tidy') + \ . ' -checks=''*'' %s -p ' . ale#Escape('/foo/bar'), + \ ale_linters#c#clangtidy#GetCommand(bufnr('')) + +Execute(The build directory setting should override the options): + let b:ale_c_build_dir = '/foo/bar' + let b:ale_c_clangtidy_options = '-Wall' + + AssertEqual + \ ale#Escape('clang-tidy') + \ . ' -checks=''*'' %s -p ' . ale#Escape('/foo/bar'), + \ ale_linters#c#clangtidy#GetCommand(bufnr('')) + +Execute(The build directory should be ignored for header files): + call ale#test#SetFilename('test.h') + + let b:ale_c_build_dir = '/foo/bar' + let b:ale_c_clangtidy_options = '-Wall' + + AssertEqual + \ ale#Escape('clang-tidy') + \ . ' -checks=''*'' %s -- -Wall', + \ ale_linters#c#clangtidy#GetCommand(bufnr('')) + \ + call ale#test#SetFilename('test.h') + + AssertEqual + \ ale#Escape('clang-tidy') + \ . ' -checks=''*'' %s -- -Wall', + \ ale_linters#c#clangtidy#GetCommand(bufnr('')) + +Execute(The executable should be configurable): + let b:ale_c_clangtidy_executable = 'foobar' + + AssertEqual + \ ale#Escape('foobar') + \ . ' -checks=''*'' %s', + \ ale_linters#c#clangtidy#GetCommand(bufnr(''))