From 4bbb10b46aae7cb3f0657c981715c4abd4376412 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois-Xavier=20Carton?= Date: Wed, 9 Jan 2019 16:00:10 +0100 Subject: [PATCH 1/2] Cflags parser: fix special chars matching algorithm --- autoload/ale/c.vim | 45 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 34 insertions(+), 11 deletions(-) diff --git a/autoload/ale/c.vim b/autoload/ale/c.vim index 746d19b0..dd5cb08a 100644 --- a/autoload/ale/c.vim +++ b/autoload/ale/c.vim @@ -46,6 +46,38 @@ function! ale#c#FindProjectRoot(buffer) abort return '' endfunction +function! ale#c#AreSpecialCharsBalanced(option) abort + " Escape \" + let l:option_escaped = substitute(a:option, '\\"', '', 'g') + + " Retain special chars only + let l:special_chars = substitute(l:option_escaped, '[^"''()`]', '', 'g') + let l:special_chars = split(l:special_chars, '\zs') + + " Check if they are balanced + let l:stack = [] + + for l:char in l:special_chars + if l:char is# ')' + if len(l:stack) == 0 || get(l:stack, -1) isnot# '(' + return 0 + endif + + call remove(l:stack, -1) + elseif l:char is# '(' + call add(l:stack, l:char) + else + if len(l:stack) > 0 && get(l:stack, -1) is# l:char + call remove(l:stack, -1) + else + call add(l:stack, l:char) + endif + endif + endfor + + return len(l:stack) == 0 +endfunction + function! ale#c#ParseCFlags(path_prefix, cflag_line) abort let l:cflags_list = [] let l:previous_options = '' @@ -57,17 +89,8 @@ function! ale#c#ParseCFlags(path_prefix, cflag_line) abort let l:option = l:previous_options . l:split_lines[l:option_index] let l:option_index = l:option_index + 1 - " Check if cflag contained an unmatched characters and should not have been splitted - let l:option_special = substitute(l:option, '\\"', '', 'g') - let l:option_special = substitute(l:option_special, '[^"''()`]', '', 'g') - let l:option_special = substitute(l:option_special, '""', '', 'g') - let l:option_special = substitute(l:option_special, '''''', '', 'g') - let l:option_special = substitute(l:option_special, '``', '', 'g') - let l:option_special = substitute(l:option_special, '((', '(', 'g') - let l:option_special = substitute(l:option_special, '))', ')', 'g') - let l:option_special = substitute(l:option_special, '()', '', 'g') - - if len(l:option_special) > 0 && l:option_index < len(l:split_lines) + " Check if cflag contained an unmatched special character and should not have been splitted + if ale#c#AreSpecialCharsBalanced(l:option) == 0 && l:option_index < len(l:split_lines) let l:previous_options = l:option . ' ' continue endif From 7e7447bb93648b79b325bbfc9d6210855fd8bbb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois-Xavier=20Carton?= Date: Wed, 9 Jan 2019 16:39:05 +0100 Subject: [PATCH 2/2] Cflags: added a test case --- test/test_c_flag_parsing.vader | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/test_c_flag_parsing.vader b/test/test_c_flag_parsing.vader index 4c23c711..c33cef15 100644 --- a/test/test_c_flag_parsing.vader +++ b/test/test_c_flag_parsing.vader @@ -209,3 +209,14 @@ Execute(ParseCFlags should not merge flags): \ . ' -I'. ale#path#Simplify('kernel/include') . ' ' \ . 'subdir/somedep5.o ' . 'subdir/somedep6.o ' \ ) + +Execute(ParseCFlags should handle parenthesis and quotes): + AssertEqual + \ '-Dgoal=9 -Dtest1="('' '')" -Dtest2=''(` `)'' -Dtest3=`(" ")`', + \ ale#c#ParseCFlags( + \ ale#path#Simplify(g:dir. '/test_c_projects/makefile_project'), + \ 'gcc -Dgoal=9 -Tlinkerfile.ld blabla ' + \ . '-Dtest1="('' '')" file1.o ' + \ . '-Dtest2=''(` `)'' file2.o ' + \ . '-Dtest3=`(" ")` file3.o ' + \ )