diff --git a/ale_linters/go/gometalinter.vim b/ale_linters/go/gometalinter.vim index 95251303..26bef321 100644 --- a/ale_linters/go/gometalinter.vim +++ b/ale_linters/go/gometalinter.vim @@ -14,7 +14,7 @@ function! ale_linters#go#gometalinter#GetCommand(buffer) abort let l:options = ale#Var(a:buffer, 'go_gometalinter_options') return ale#Escape(l:executable) - \ . ' --include=' . ale#Escape(l:filename) + \ . ' --include=' . ale#Escape(ale#util#EscapePCRE(l:filename)) \ . (!empty(l:options) ? ' ' . l:options : '') \ . ' ' . ale#Escape(fnamemodify(l:filename, ':h')) endfunction diff --git a/autoload/ale/util.vim b/autoload/ale/util.vim index 0fc23d07..c86ac692 100644 --- a/autoload/ale/util.vim +++ b/autoload/ale/util.vim @@ -161,3 +161,9 @@ function! ale#util#FunctionArgCount(function) abort return l:count endfunction + +" Escape a string so the characters in it will be safe for use inside of PCRE +" or RE2 regular expressions without characters having special meanings. +function! ale#util#EscapePCRE(unsafe_string) abort + return substitute(a:unsafe_string, '\([\-\[\]{}()*+?.^$|]\)', '\\\1', 'g') +endfunction diff --git a/test/command_callback/test_gometalinter_command_callback.vader b/test/command_callback/test_gometalinter_command_callback.vader index f1b4e9f0..a0f4da4f 100644 --- a/test/command_callback/test_gometalinter_command_callback.vader +++ b/test/command_callback/test_gometalinter_command_callback.vader @@ -22,7 +22,7 @@ Execute(The gometalinter callback should return the right defaults): \ ale_linters#go#gometalinter#GetExecutable(bufnr('')) AssertEqual \ ale#Escape('gometalinter') - \ . ' --include=' . ale#Escape(expand('%')) + \ . ' --include=' . ale#Escape(ale#util#EscapePCRE(expand('%'))) \ . ' ' . ale#Escape(getcwd()), \ ale_linters#go#gometalinter#GetCommand(bufnr('')) @@ -34,7 +34,7 @@ Execute(The gometalinter callback should use a configured executable): \ ale_linters#go#gometalinter#GetExecutable(bufnr('')) AssertEqual \ ale#Escape('something else') - \ . ' --include=' . ale#Escape(expand('%')) + \ . ' --include=' . ale#Escape(ale#util#EscapePCRE(expand('%'))) \ . ' ' . ale#Escape(getcwd()), \ ale_linters#go#gometalinter#GetCommand(bufnr('')) @@ -43,7 +43,7 @@ Execute(The gometalinter callback should use configured options): AssertEqual \ ale#Escape('gometalinter') - \ . ' --include=' . ale#Escape(expand('%')) + \ . ' --include=' . ale#Escape(ale#util#EscapePCRE(expand('%'))) \ . ' --foobar' \ . ' ' . ale#Escape(getcwd()), \ ale_linters#go#gometalinter#GetCommand(bufnr('')) diff --git a/test/test_regex_escaping.vader b/test/test_regex_escaping.vader new file mode 100644 index 00000000..b79b8c56 --- /dev/null +++ b/test/test_regex_escaping.vader @@ -0,0 +1,4 @@ +Execute(ale#util#EscapePCRE should escape strings for PCRE or RE2 appropriately): + AssertEqual '\\\^\$\*\+\?\.\(\)\|\{\}\[\]', ale#util#EscapePCRE('\^$*+?.()|{}[]') + AssertEqual 'abcABC09', ale#util#EscapePCRE('abcABC09') + AssertEqual '/', ale#util#EscapePCRE('/')