diff --git a/ale_linters/cpp/clangtidy.vim b/ale_linters/cpp/clangtidy.vim index f98b0852..94f5767c 100644 --- a/ale_linters/cpp/clangtidy.vim +++ b/ale_linters/cpp/clangtidy.vim @@ -1,4 +1,5 @@ -" Author: vdeurzen , w0rp +" Author: vdeurzen , w0rp , +" gagbo " Description: clang-tidy linter for cpp files " Set this option to check the checks clang-tidy will apply. @@ -8,15 +9,36 @@ let g:ale_cpp_clangtidy_checks = get(g:, 'ale_cpp_clangtidy_checks', ['*']) " This will disable compile_commands.json detection. let g:ale_cpp_clangtidy_options = get(g:, 'ale_cpp_clangtidy_options', '') +" Set this option to manually point to the build directory for clang-tidy. +" This will disable all the other clangtidy_options, since compilation +" flags are contained in the json +let g:ale_c_build_dir = get(g:, 'ale_c_build_dir', '') + + function! ale_linters#cpp#clangtidy#GetCommand(buffer) abort let l:check_list = ale#Var(a:buffer, 'cpp_clangtidy_checks') let l:check_option = !empty(l:check_list) \ ? '-checks=' . ale#Escape(join(l:check_list, ',')) . ' ' \ : '' let l:user_options = ale#Var(a:buffer, 'cpp_clangtidy_options') - let l:extra_options = !empty(l:user_options) - \ ? ' -- ' . l:user_options - \ : '' + let l:user_build_dir = ale#Var(a:buffer, 'c_build_dir') + + " c_build_dir has the priority if defined + if empty(l:user_build_dir) + let l:user_build_dir = ale#c#FindCompileCommands(a:buffer) + endif + + " We check again if user_builddir stayed empty after the + " c_build_dir_names check + " If we found the compilation database we override the value of + " l:extra_options + if empty(l:user_build_dir) + let l:extra_options = !empty(l:user_options) + \ ? ' -- ' . l:user_options + \ : '' + else + let l:extra_options = ' -p ' . ale#Escape(l:user_build_dir) + endif return 'clang-tidy ' . l:check_option . '%s' . l:extra_options endfunction diff --git a/autoload/ale/c.vim b/autoload/ale/c.vim new file mode 100644 index 00000000..9cc2521e --- /dev/null +++ b/autoload/ale/c.vim @@ -0,0 +1,24 @@ +" Author: gagbo +" Description: Functions for integrating with C-family linters. + + +let g:ale_c_build_dir_names = get(g:, 'ale_c_build_dir_names', [ +\ 'build', +\ 'bin', +\]) + +" Given a buffer number, find the build subdirectory with compile commands +" The subdirectory is returned without the trailing / +function! ale#c#FindCompileCommands(buffer) abort + for l:path in ale#path#Upwards(expand('#' . a:buffer . ':p:h')) + for l:dirname in ale#Var(a:buffer, 'c_build_dir_names') + let l:c_build_dir = l:path . '/' . l:dirname + + if filereadable(l:c_build_dir . '/compile_commands.json') + return l:c_build_dir + endif + endfor + endfor + + return '' +endfunction diff --git a/doc/ale-cpp.txt b/doc/ale-cpp.txt index a64f87b1..27e7fe0b 100644 --- a/doc/ale-cpp.txt +++ b/doc/ale-cpp.txt @@ -2,6 +2,37 @@ ALE C++ Integration *ale-cpp-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-cpp-clang* @@ -19,6 +50,9 @@ clangtidy *ale-cpp-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_cpp_clangtidy_checks *g:ale_cpp_clangtidy_checks* @@ -32,7 +66,6 @@ g:ale_cpp_clangtidy_checks *g:ale_cpp_clangtidy_checks* the shell. The `-checks` flag can be removed entirely by setting this option to an empty List. - g:ale_cpp_clangtidy_options *g:ale_cpp_clangtidy_options* *b:ale_cpp_clangtidy_options* Type: |String| diff --git a/test/test_c_import_paths.vader b/test/test_c_import_paths.vader index 66ff6dca..b867100a 100644 --- a/test/test_c_import_paths.vader +++ b/test/test_c_import_paths.vader @@ -226,3 +226,18 @@ Execute(The C++ Clang handler should include root directories for projects with \ . ' -I' . ale#Escape(g:dir . '/test_c_projects/hpp_file_project') . ' ' \ . ' -' \ , ale_linters#cpp#clang#GetCommand(bufnr('')) + +Execute(The C++ ClangTidy handler should include json folders for projects with suitable build directory in them): + runtime! ale_linters/cpp/clangtidy.vim + + cd test_c_projects/json_project/subdir + silent noautocmd file file.cpp + + " TODO Test to move to C-family tools tests + " AssertEqual + " \ '/testplugin/test/test_c_projects/json_project/build' + " \ , ale#c#FindCompileCommands(bufnr('')) + + AssertEqual + \ 'clang-tidy -checks=''*'' %s -p ''/testplugin/test/test_c_projects/json_project/build''' + \ , ale_linters#cpp#clangtidy#GetCommand(bufnr('')) diff --git a/test/test_c_projects/build/bad_folder_to_test_priority b/test/test_c_projects/build/bad_folder_to_test_priority new file mode 100644 index 00000000..e69de29b diff --git a/test/test_c_projects/build/compile_commands.json b/test/test_c_projects/build/compile_commands.json new file mode 100644 index 00000000..e69de29b diff --git a/test/test_c_projects/json_project/build/compile_commands.json b/test/test_c_projects/json_project/build/compile_commands.json new file mode 100644 index 00000000..e69de29b diff --git a/test/test_c_projects/json_project/include/test.h b/test/test_c_projects/json_project/include/test.h new file mode 100644 index 00000000..e69de29b diff --git a/test/test_c_projects/json_project/subdir/dummy b/test/test_c_projects/json_project/subdir/dummy new file mode 100644 index 00000000..e69de29b