diff --git a/ale_linters/c/clang.vim b/ale_linters/c/clang.vim index 25d93715..74279b7c 100644 --- a/ale_linters/c/clang.vim +++ b/ale_linters/c/clang.vim @@ -3,7 +3,7 @@ call ale#Set('c_clang_executable', 'clang') call ale#Set('c_clang_options', '-std=c11 -Wall') -call ale#Set('c_gcc_parse_makefile', 0) +call ale#Set('c_clang_parse_makefile', 0) function! ale_linters#c#clang#GetExecutable(buffer) abort return ale#Var(a:buffer, 'c_clang_executable') @@ -11,11 +11,13 @@ endfunction function! ale_linters#c#clang#GetCommand(buffer) abort let l:cflags = [] - if g:ale_c_parse_makefile - let l:cflags = join(ale#c#ParseMakefile(a:buffer), ' ') + if g:ale_c_clang_parse_makefile + let l:cflags = join(ale#c#ParseMakefile(a:buffer), ' ') . ' ' endif if empty(l:cflags) let l:cflags = ale#c#IncludeOptions(ale#c#FindLocalHeaderPaths(a:buffer)) + else + let l:cflags .= ' ' endif " -iquote with the directory the file is in makes #include work for @@ -23,7 +25,7 @@ let l:cflags = [] return ale#Escape(ale_linters#c#clang#GetExecutable(a:buffer)) \ . ' -S -x c -fsyntax-only ' \ . '-iquote ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h')) . ' ' - \ . l:cflags . ' ' + \ . l:cflags \ . ale#Var(a:buffer, 'c_clang_options') . ' -' endfunction diff --git a/ale_linters/c/gcc.vim b/ale_linters/c/gcc.vim index 3ad243a3..3199fe8a 100644 --- a/ale_linters/c/gcc.vim +++ b/ale_linters/c/gcc.vim @@ -3,7 +3,7 @@ call ale#Set('c_gcc_executable', 'gcc') call ale#Set('c_gcc_options', '-std=c11 -Wall') -call ale#Set('c_parse_makefile', 0) +call ale#Set('c_gcc_parse_makefile', 0) function! ale_linters#c#gcc#GetExecutable(buffer) abort return ale#Var(a:buffer, 'c_gcc_executable') @@ -11,11 +11,13 @@ endfunction function! ale_linters#c#gcc#GetCommand(buffer) abort let l:cflags = [] - if g:ale_c_parse_makefile + if g:ale_c_gcc_parse_makefile let l:cflags = join(ale#c#ParseMakefile(a:buffer), ' ') endif if empty(l:cflags) let l:cflags = ale#c#IncludeOptions(ale#c#FindLocalHeaderPaths(a:buffer)) + else + let l:cflags .= ' ' endif " -iquote with the directory the file is in makes #include work for @@ -23,7 +25,7 @@ function! ale_linters#c#gcc#GetCommand(buffer) abort return ale#Escape(ale_linters#c#gcc#GetExecutable(a:buffer)) \ . ' -S -x c -fsyntax-only ' \ . '-iquote ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h')) . ' ' - \ . l:cflags . ' ' + \ . l:cflags \ . ale#Var(a:buffer, 'c_gcc_options') . ' -' endfunction diff --git a/autoload/ale/c.vim b/autoload/ale/c.vim index 4bf8ad4d..7dc532b3 100644 --- a/autoload/ale/c.vim +++ b/autoload/ale/c.vim @@ -24,42 +24,42 @@ endfunction function! ale#c#ParseCFlags(project_root, stdout_make) abort let l:cflags_list = [] - let l:cflags = split(a:stdout_make, " ") + let l:cflags = split(a:stdout_make) let l:shell_option = 0 let l:macro_option = 0 let l:previous_option = '' for l:option in l:cflags " Check if cflag contained spaces - if l:shell_option || stridx(l:option, "=`") >= 0 + if l:shell_option || stridx(l:option, '=`') >= 0 " Cflag contained shell command with spaces (ex. -D='date +%s') let l:shell_option = 1 let l:previous_option .= l:option . ' ' - if l:option[-1: -1] != "`" + if l:option[-1: -1] isnot? '`' continue endif let l:shell_option = 0 - elseif l:macro_option || stridx(l:option, "$((") > 0 + elseif l:macro_option || stridx(l:option, '$((') > 0 " Cflag contained macro with spaces (ex -Da=$(( 4 * 20 ))) let l:macro_option = 1 let l:previous_option .= l:option . ' ' - if stridx(l:option, "))") < 0 + if stridx(l:option, '))') < 0 continue endif let l:macro_option = 0 endif - if l:previous_option != '' + if l:previous_option isnot? '' let l:option = l:previous_option let l:previous_option = '' endif " Fix relative paths if needed - if stridx(l:option, "-I") >= 0 - if stridx(l:option, "-I/") < 0 + if stridx(l:option, '-I') >= 0 + if stridx(l:option, '-I' . s:sep) < 0 let l:option = '-I' . a:project_root . s:sep . l:option[2:] endif endif " Parse the cflag - if stridx(l:option, "-I") >= 0 || - \ stridx(l:option, "-D") >= 0 + if stridx(l:option, '-I') >= 0 || + \ stridx(l:option, '-D') >= 0 if index(l:cflags_list, l:option) < 0 call add(l:cflags_list, l:option) endif @@ -74,12 +74,12 @@ function! ale#c#ParseMakefile(buffer) abort if !empty(l:project_root) if !empty(globpath(l:project_root, 'Makefile', 0)) - let stdout_make = system('cd '. l:project_root . ' && make -n') - for l:object in split(l:stdout_make, '\n') - if stridx(l:object, expand("%t")) - return ale#c#ParseCFlags(l:project_root, l:object) - endif - endfor + let l:stdout_make = system('cd '. l:project_root . ' && make -n') + for l:object in split(l:stdout_make, '\n') + if stridx(l:object, expand('#' . a:buffer . '...')) + return ale#c#ParseCFlags(l:project_root, l:object) + endif + endfor endif endif return [] diff --git a/test/test_c_parse_makefile.vader b/test/test_c_parse_makefile.vader new file mode 100644 index 00000000..fac04bbe --- /dev/null +++ b/test/test_c_parse_makefile.vader @@ -0,0 +1,72 @@ +Before: + Save g:ale_c_gcc_options + Save g:ale_c_gcc_parse_makefile + Save g:ale_c_clang_options + Save g:ale_c_clang_parse_makefile + Save g:ale_cpp_gcc_options + Save g:ale_cpp_clang_options + + call ale#test#SetDirectory('/testplugin/test') + + let g:ale_c_gcc_parse_makefile=1 + let g:ale_c_clang_parse_makefile=1 + let g:ale_c_gcc_options = '' + let g:ale_c_clang_options = '' + let g:ale_cpp_gcc_options = '' + let g:ale_cpp_clang_options = '' + +After: + Restore + + call ale#test#RestoreDirectory() + call ale#linter#Reset() + +" Run this only once for this series of tests. The cleanup Execute step +" will run at the bottom of this file. +" +" We need to move .git/HEAD away so we don't match it, as we need to test +" functions which look for .git/HEAD. +Execute(Move .git/HEAD to a temp dir): + let g:temp_head_filename = tempname() + let g:head_filename = findfile('.git/HEAD', ';') + + if !empty(g:head_filename) + call writefile(readfile(g:head_filename, 'b'), g:temp_head_filename, 'b') + call delete(g:head_filename) + endif + +Execute(The C GCC handler should include directories specified in the include path for projects with a Makefile): + runtime! ale_linters/c/gcc.vim + + call ale#test#SetFilename('test_c_projects/makefile_project/subdir/file.c') + + AssertEqual + \ ale#Escape('gcc') + \ . ' -S -x c -fsyntax-only ' + \ . '-iquote ' . ale#Escape(ale#path#Simplify(g:dir . '/test_c_projects/makefile_project/subdir')) + \ . ' -I' . ale#Escape(ale#path#Simplify(g:dir . '/test_c_projects/makefile_project/subdir/'))[1:-3] . ' ' + \ . ' -' + \ , ale_linters#c#gcc#GetCommand(bufnr('')) + +Execute(The C++ Clang handler should include directories specified in the include path for projects with a Makefile): + runtime! ale_linters/c/clang.vim + + call ale#test#SetFilename('test_c_projects/makefile_project/subdir/file.c') + + AssertEqual + \ ale#Escape('clang') + \ . ' -S -x c -fsyntax-only ' + \ . '-iquote ' . ale#Escape(ale#path#Simplify(g:dir . '/test_c_projects/makefile_project/subdir')) + \ . ' -I' . ale#Escape(ale#path#Simplify(g:dir . '/test_c_projects/makefile_project/subdir'))[1:-2] . ' ' + \ . ' -' + \ , ale_linters#c#clang#GetCommand(bufnr('')) + + +Execute(Move .git/HEAD back): + if !empty(g:head_filename) + call writefile(readfile(g:temp_head_filename, 'b'), g:head_filename, 'b') + call delete(g:temp_head_filename) + endif + + unlet! g:temp_head_filename + unlet! g:head_filename diff --git a/test/test_c_projects/makefile_project/Makefile b/test/test_c_projects/makefile_project/Makefile index e69de29b..8b49a94d 100644 --- a/test/test_c_projects/makefile_project/Makefile +++ b/test/test_c_projects/makefile_project/Makefile @@ -0,0 +1,3 @@ +file.o : subdir/file.c + cc -c subdir/file.c -Isubdir + diff --git a/test/test_c_projects/makefile_project/subdir/file.c b/test/test_c_projects/makefile_project/subdir/file.c new file mode 100644 index 00000000..e69de29b