summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen Robinson <sblazerobinson@gmail.com>2020-04-02 15:49:03 -0700
committerStephen Robinson <sblazerobinson@gmail.com>2020-05-20 18:15:52 -0700
commitb20931571484108d1ec29eaab5b731e754649664 (patch)
tree625ca0665083c3653d264d4235b0c9b735cb80a8
parent7ff87a942b8a6c2cf50b7cf34f9b98421508f542 (diff)
downloadale-b20931571484108d1ec29eaab5b731e754649664.zip
Fixes #3092 - Implement loading `@file` c arguments
-rw-r--r--autoload/ale/c.vim50
-rw-r--r--test/test_c_flag_parsing.vader11
-rw-r--r--test/test_c_projects/makefile_project/args3
-rw-r--r--test/test_c_projects/makefile_project/subdir/args1
4 files changed, 64 insertions, 1 deletions
diff --git a/autoload/ale/c.vim b/autoload/ale/c.vim
index 9b428700..e8212dcd 100644
--- a/autoload/ale/c.vim
+++ b/autoload/ale/c.vim
@@ -68,10 +68,58 @@ function! ale#c#ShellSplit(line) abort
return l:args
endfunction
+" Takes the path prefix and a list of cflags and expands @file arguments to
+" the contents of the file.
+"
+" @file arguments are command line arguments recognised by gcc and clang. For
+" instance, if @./path/to/file was given to gcc, it would load .path/to/file
+" and use the contents of that file as arguments.
+function! ale#c#ExpandAtArgs(path_prefix, raw_split_lines) abort
+ let l:out_lines = []
+
+ for l:option in a:raw_split_lines
+ if stridx(l:option, '@') == 0
+ " This is an argument specifying a location of a file containing other arguments
+ let l:path = join(split(l:option, '\zs')[1:], '')
+
+ " Make path absolute
+ if stridx(l:path, s:sep) != 0 && stridx(l:path, '/') != 0
+ let l:rel_path = substitute(l:path, '"', '', 'g')
+ let l:rel_path = substitute(l:rel_path, '''', '', 'g')
+ let l:path = a:path_prefix . s:sep . l:rel_path
+ endif
+
+ " Read the file and add all the arguments
+ try
+ let l:additional_args = readfile(l:path)
+ catch
+ continue " All we can really do is skip this argument
+ endtry
+
+ let l:file_lines = []
+
+ for l:line in l:additional_args
+ let l:file_lines += ale#c#ShellSplit(l:line)
+ endfor
+
+ " @file arguments can include other @file arguments, so we must
+ " recurse.
+ let l:out_lines += ale#c#ExpandAtArgs(a:path_prefix, l:file_lines)
+ else
+ " This is not an @file argument, so don't touch it.
+ let l:out_lines += [l:option]
+ endif
+ endfor
+
+ return l:out_lines
+endfunction
+
function! ale#c#ParseCFlags(path_prefix, cflag_line) abort
let l:cflags_list = []
- let l:split_lines = ale#c#ShellSplit(a:cflag_line)
+ let l:raw_split_lines = ale#c#ShellSplit(a:cflag_line)
+ " Expand @file arguments now before parsing
+ let l:split_lines = ale#c#ExpandAtArgs(a:path_prefix, l:raw_split_lines)
let l:option_index = 0
while l:option_index < len(l:split_lines)
diff --git a/test/test_c_flag_parsing.vader b/test/test_c_flag_parsing.vader
index 8ae6f9dc..dff19aa3 100644
--- a/test/test_c_flag_parsing.vader
+++ b/test/test_c_flag_parsing.vader
@@ -366,3 +366,14 @@ Execute(CFlags we dont want to pass):
\ 'gcc -Wl,option -Wa,option -Wp,option filename.c somelib.a '
\ . '-fdump-file=name -fdiagnostics-arg -fno-show-column'
\ )
+
+Execute(Expanding @file in CFlags):
+ AssertEqual
+ \ '-DARGS1 -DARGS2 -O2',
+ \ ale#c#ParseCFlags(
+ \ ale#path#Simplify(g:dir. '/test_c_projects/makefile_project'),
+ \ 'gcc'
+ \ . ' -g'
+ \ . ' @./args'
+ \ . ' -O2',
+ \ )
diff --git a/test/test_c_projects/makefile_project/args b/test/test_c_projects/makefile_project/args
new file mode 100644
index 00000000..ccaf82ad
--- /dev/null
+++ b/test/test_c_projects/makefile_project/args
@@ -0,0 +1,3 @@
+foolib.a
+-DARGS1
+@subdir/args
diff --git a/test/test_c_projects/makefile_project/subdir/args b/test/test_c_projects/makefile_project/subdir/args
new file mode 100644
index 00000000..3fe9c3fe
--- /dev/null
+++ b/test/test_c_projects/makefile_project/subdir/args
@@ -0,0 +1 @@
+-DARGS2