diff --git a/README.md b/README.md index 8c4f8138..4fd109ff 100644 --- a/README.md +++ b/README.md @@ -98,7 +98,7 @@ formatting. | Bash | [language-server](https://github.com/mads-hartmann/bash-language-server), shell [-n flag](https://www.gnu.org/software/bash/manual/bash.html#index-set), [shellcheck](https://www.shellcheck.net/), [shfmt](https://github.com/mvdan/sh) | | Bourne Shell | shell [-n flag](http://linux.die.net/man/1/sh), [shellcheck](https://www.shellcheck.net/), [shfmt](https://github.com/mvdan/sh) | | C | [cppcheck](http://cppcheck.sourceforge.net), [cpplint](https://github.com/google/styleguide/tree/gh-pages/cpplint), [clang](http://clang.llvm.org/), [clangd](https://clang.llvm.org/extra/clangd.html), [clangtidy](http://clang.llvm.org/extra/clang-tidy/) !!, [clang-format](https://clang.llvm.org/docs/ClangFormat.html), [cquery](https://github.com/cquery-project/cquery), [flawfinder](https://www.dwheeler.com/flawfinder/), [gcc](https://gcc.gnu.org/) | -| C++ (filetype cpp) | [clang](http://clang.llvm.org/), [clangd](https://clang.llvm.org/extra/clangd.html), [clangcheck](http://clang.llvm.org/docs/ClangCheck.html) !!, [clangtidy](http://clang.llvm.org/extra/clang-tidy/) !!, [clang-format](https://clang.llvm.org/docs/ClangFormat.html), [cppcheck](http://cppcheck.sourceforge.net), [cpplint](https://github.com/google/styleguide/tree/gh-pages/cpplint) !!, [cquery](https://github.com/cquery-project/cquery), [flawfinder](https://www.dwheeler.com/flawfinder/), [gcc](https://gcc.gnu.org/) | +| C++ (filetype cpp) | [clang](http://clang.llvm.org/), [clangd](https://clang.llvm.org/extra/clangd.html), [clangcheck](http://clang.llvm.org/docs/ClangCheck.html) !!, [clangtidy](http://clang.llvm.org/extra/clang-tidy/) !!, [clang-format](https://clang.llvm.org/docs/ClangFormat.html), [clazy](https://github.com/KDE/clazy) !!, [cppcheck](http://cppcheck.sourceforge.net), [cpplint](https://github.com/google/styleguide/tree/gh-pages/cpplint) !!, [cquery](https://github.com/cquery-project/cquery), [flawfinder](https://www.dwheeler.com/flawfinder/), [gcc](https://gcc.gnu.org/) | | CUDA | [nvcc](http://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/index.html) | | C# | [mcs](http://www.mono-project.com/docs/about-mono/languages/csharp/) see:`help ale-cs-mcs` for details, [mcsc](http://www.mono-project.com/docs/about-mono/languages/csharp/) !! see:`help ale-cs-mcsc` for details and configuration| | Chef | [foodcritic](http://www.foodcritic.io/) | diff --git a/ale_linters/c/clangtidy.vim b/ale_linters/c/clangtidy.vim index 84c103e6..54137480 100644 --- a/ale_linters/c/clangtidy.vim +++ b/ale_linters/c/clangtidy.vim @@ -16,27 +16,9 @@ call ale#Set('c_clangtidy_checks', ['*']) call ale#Set('c_clangtidy_options', '') call ale#Set('c_build_dir', '') -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#path#Dirname(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) + let l:build_dir = ale#c#GetBuildDirectory(a:buffer) " Get the extra options if we couldn't find a build directory. let l:options = empty(l:build_dir) diff --git a/ale_linters/cpp/clangtidy.vim b/ale_linters/cpp/clangtidy.vim index 930087a8..2f3089b4 100644 --- a/ale_linters/cpp/clangtidy.vim +++ b/ale_linters/cpp/clangtidy.vim @@ -10,27 +10,9 @@ call ale#Set('cpp_clangtidy_checks', ['*']) call ale#Set('cpp_clangtidy_options', '') call ale#Set('c_build_dir', '') -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#path#Dirname(ale#c#FindCompileCommands(a:buffer)) -endfunction - function! ale_linters#cpp#clangtidy#GetCommand(buffer) abort let l:checks = join(ale#Var(a:buffer, 'cpp_clangtidy_checks'), ',') - let l:build_dir = s:GetBuildDirectory(a:buffer) + let l:build_dir = ale#c#GetBuildDirectory(a:buffer) " Get the extra options if we couldn't find a build directory. let l:options = empty(l:build_dir) diff --git a/ale_linters/cpp/clazy.vim b/ale_linters/cpp/clazy.vim new file mode 100644 index 00000000..cbbd0ccf --- /dev/null +++ b/ale_linters/cpp/clazy.vim @@ -0,0 +1,32 @@ +" Description: clazy linter for cpp files (clang-based and Qt-oriented) + +call ale#Set('cpp_clazy_executable', 'clazy-standalone') +" Set this option to check the checks clazy will apply. +call ale#Set('cpp_clazy_checks', ['level1']) +" Set this option to manually set some options for clazy. +" This will disable compile_commands.json detection. +call ale#Set('cpp_clazy_options', '') +call ale#Set('c_build_dir', '') + +function! ale_linters#cpp#clazy#GetCommand(buffer) abort + let l:checks = join(ale#Var(a:buffer, 'cpp_clazy_checks'), ',') + let l:build_dir = ale#c#GetBuildDirectory(a:buffer) + + " Get the extra options if we couldn't find a build directory. + let l:options = ale#Var(a:buffer, 'cpp_clazy_options') + + return '%e' + \ . (!empty(l:checks) ? ' -checks=' . ale#Escape(l:checks) : '') + \ . (!empty(l:build_dir) ? ' -p ' . ale#Escape(l:build_dir) : '') + \ . (!empty(l:options) ? ' ' . l:options : '') + \ . ' %s' +endfunction + +call ale#linter#Define('cpp', { +\ 'name': 'clazy', +\ 'output_stream': 'stderr', +\ 'executable_callback': ale#VarFunc('cpp_clazy_executable'), +\ 'command_callback': 'ale_linters#cpp#clazy#GetCommand', +\ 'callback': 'ale#handlers#gcc#HandleGCCFormat', +\ 'lint_file': 1, +\}) diff --git a/autoload/ale/c.vim b/autoload/ale/c.vim index ae428692..5ec62011 100644 --- a/autoload/ale/c.vim +++ b/autoload/ale/c.vim @@ -8,6 +8,25 @@ let s:sep = has('win32') ? '\' : '/' " Set just so tests can override it. let g:__ale_c_project_filenames = ['.git/HEAD', 'configure', 'Makefile', 'CMakeLists.txt'] +function! ale#c#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#path#Dirname(ale#c#FindCompileCommands(a:buffer)) +endfunction + + function! ale#c#FindProjectRoot(buffer) abort for l:project_filename in g:__ale_c_project_filenames let l:full_path = ale#path#FindNearestFile(a:buffer, l:project_filename) diff --git a/doc/ale-cpp.txt b/doc/ale-cpp.txt index c42d20a2..e582ae6e 100644 --- a/doc/ale-cpp.txt +++ b/doc/ale-cpp.txt @@ -138,6 +138,37 @@ g:ale_cpp_clangtidy_options *g:ale_cpp_clangtidy_options* of the |g:ale_c_build_dir_names| directories of the project tree. +=============================================================================== +clazy *ale-cpp-clazy* + +g:ale_cpp_clazy_executable *g:ale_cpp_clazy_executable* + *b:ale_cpp_clazy_executable* + Type: |String| + Default: `'clazy-standalone'` + + This variable can be changed to use a different executable for clazy. + + +g:ale_cpp_clazy_checks *g:ale_cpp_clazy_checks* + *b:ale_cpp_clazy_checks* + Type: |List| + Default: `['level1']` + + The checks to enable for clazy 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. + + +g:ale_cpp_clazy_options *g:ale_cpp_clazy_options* + *b:ale_cpp_clazy_options* + Type: |String| + Default: `''` + + This variable can be changed to modify flags given to clazy. + + =============================================================================== cppcheck *ale-cpp-cppcheck* diff --git a/doc/ale.txt b/doc/ale.txt index d1e6d0b0..2a78a9de 100644 --- a/doc/ale.txt +++ b/doc/ale.txt @@ -47,6 +47,7 @@ CONTENTS *ale-contents* clangcheck..........................|ale-cpp-clangcheck| clang-format........................|ale-cpp-clangformat| clangtidy...........................|ale-cpp-clangtidy| + clazy...............................|ale-cpp-clazy| cppcheck............................|ale-cpp-cppcheck| cpplint.............................|ale-cpp-cpplint| cquery..............................|ale-cpp-cquery| @@ -351,7 +352,7 @@ Notes: * Bash: `language-server`, `shell` (-n flag), `shellcheck`, `shfmt` * Bourne Shell: `shell` (-n flag), `shellcheck`, `shfmt` * C: `cppcheck`, `cpplint`!!, `clang`, `clangd`, `clangtidy`!!, `clang-format`, `cquery`, `flawfinder`, `gcc` -* C++ (filetype cpp): `clang`, `clangd`, `clangcheck`!!, `clangtidy`!!, `clang-format`, `cppcheck`, `cpplint`!!, `cquery`, `flawfinder`, `gcc` +* C++ (filetype cpp): `clang`, `clangd`, `clangcheck`!!, `clangtidy`!!, `clang-format`, `clazy`!!, `cppcheck`, `cpplint`!!, `cquery`, `flawfinder`, `gcc` * CUDA: `nvcc`!! * C#: `mcs`, `mcsc`!! * Chef: `foodcritic` diff --git a/test/command_callback/test_cpp_clazy_command_callback.vader b/test/command_callback/test_cpp_clazy_command_callback.vader new file mode 100644 index 00000000..f28609ee --- /dev/null +++ b/test/command_callback/test_cpp_clazy_command_callback.vader @@ -0,0 +1,63 @@ +Before: + call ale#assert#SetUpLinterTest('cpp', 'clangtidy') + call ale#test#SetFilename('test.cpp') + +After: + call ale#assert#TearDownLinterTest() + +Execute(The clangtidy command default should be correct): + AssertLinter 'clang-tidy', + \ ale#Escape('clang-tidy') . ' -checks=' . ale#Escape('*') . ' %s' + +Execute(You should be able to remove the -checks option for clang-tidy): + let b:ale_cpp_clangtidy_checks = [] + + AssertLinter 'clang-tidy', ale#Escape('clang-tidy') . ' %s' + +Execute(You should be able to set other checks for clang-tidy): + let b:ale_cpp_clangtidy_checks = ['-*', 'clang-analyzer-*'] + + AssertLinter 'clang-tidy', + \ ale#Escape('clang-tidy') + \ . ' -checks=' . ale#Escape('-*,clang-analyzer-*') . ' %s' + +Execute(You should be able to manually set compiler flags for clang-tidy): + let b:ale_cpp_clangtidy_options = '-Wall' + + AssertLinter 'clang-tidy', + \ ale#Escape('clang-tidy') . ' -checks=' . ale#Escape('*') . ' %s -- -Wall' + \ +Execute(The build directory should be configurable): + let b:ale_c_build_dir = '/foo/bar' + + AssertLinter 'clang-tidy', + \ ale#Escape('clang-tidy') + \ . ' -checks=' . ale#Escape('*') . ' %s -p ' . ale#Escape('/foo/bar') + +Execute(The build directory setting should override the options): + let b:ale_c_build_dir = '/foo/bar' + let b:ale_cpp_clangtidy_options = '-Wall' + + AssertLinter 'clang-tidy', + \ ale#Escape('clang-tidy') + \ . ' -checks=' . ale#Escape('*') . ' %s -p ' . ale#Escape('/foo/bar') + +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_cpp_clangtidy_options = '-Wall' + + AssertLinter 'clang-tidy', + \ ale#Escape('clang-tidy') . ' -checks=' . ale#Escape('*') . ' %s -- -Wall' + + call ale#test#SetFilename('test.hpp') + + AssertLinter 'clang-tidy', + \ ale#Escape('clang-tidy') . ' -checks=' . ale#Escape('*') . ' %s -- -Wall' + +Execute(The executable should be configurable): + let b:ale_cpp_clangtidy_executable = 'foobar' + + AssertLinter 'foobar', + \ ale#Escape('foobar') . ' -checks=' . ale#Escape('*') . ' %s'