Handle multiple files localtion lists with gcc handler (#1034)

Handle multiple files in the GCC handler.
This commit is contained in:
Gerry Agbobada
2017-10-25 23:29:36 +02:00
committed by w0rp
parent 960ae62aaa
commit 25d2af0b25
5 changed files with 69 additions and 71 deletions

View File

@@ -43,6 +43,10 @@ endfunction
function! ale#handlers#gcc#HandleGCCFormat(buffer, lines) abort
let l:include_pattern = '\v^(In file included | *)from ([^:]*):(\d+)'
" Include pattern looks for lines like :
"
" In file included from test.h:1:0,
" from test.cpp:1:
let l:include_lnum = 0
let l:include_lines = []
let l:included_filename = ''
@@ -58,51 +62,42 @@ function! ale#handlers#gcc#HandleGCCFormat(buffer, lines) abort
let l:match = matchlist(l:line, l:pattern)
if empty(l:match)
" Check for matches in includes.
" We will keep matching lines until we hit the last file, which
" is our file.
let l:include_match = matchlist(l:line, l:include_pattern)
if empty(l:include_match)
" If this isn't another include header line, then we
" need to collect it.
call add(l:include_lines, l:line)
else
" GCC and clang return the lists of files in different orders,
" so we'll only grab the line number from lines which aren't
" header files.
if !s:IsHeaderFile(l:include_match[2])
" Get the line number out of the parsed include line,
" and reset the other variables.
let l:include_lnum = str2nr(l:include_match[3])
endif
let l:include_lines = []
let l:included_filename = ''
" If the line has an 'included from' pattern, store the line to
" create a gutter sign at the appropriate location in linted file
if !empty(l:include_match)
" We don't check if l:include_match[2] is linted filename
" because the last line matching include_pattern in a group
" of contiguous lines is probably concerning the linted file
" anyway
let l:include_lnum = l:include_match[3]
endif
elseif l:include_lnum > 0
\&& (empty(l:included_filename) || l:included_filename is# l:match[1])
" If we hit the first error after an include header, or the
" errors below have the same name as the first filename we see,
" then include these lines, and remember what that filename was.
let l:included_filename = l:match[1]
call add(l:include_lines, l:line)
else
" If we hit a regular error again, then add the previously
" collected lines as one error, and reset the include variables.
call s:AddIncludedErrors(l:output, l:include_lnum, l:include_lines)
let l:include_lnum = 0
let l:include_lines = []
let l:included_filename = ''
" Filter out the pragma errors
if s:IsHeaderFile(bufname(bufnr('')))
\&& l:match[5][:len(s:pragma_error) - 1] is# s:pragma_error
continue
endif
" If the 'error type' is a note, make it detail related to
" the previous error parsed in output
if l:match[4] is# 'note'
let l:output[-1]['detail'] = get(l:output[-1], 'detail', '')
\ . s:RemoveUnicodeQuotes(l:match[0]) . "\n"
continue
endif
" If l:include_lnum is non-null, then the error relates to
" an included file and l:include_lnum is the line number
" where a gutter sign would be needed in linted file
" The ternary operator in filename filters out the 'dummy'
" filenames like <nopath> or <stdin> and leave the location
" handling to engine#FixLocList
let l:item = {
\ 'filename': (l:match[1][:0] is# '<') ? '' : l:match[1],
\ 'lnum': str2nr(l:match[2]),
\ 'type': l:match[4] =~# 'error' ? 'E' : 'W',
\ 'type': l:match[4] is# 'error' ? 'E' : 'W',
\ 'text': s:RemoveUnicodeQuotes(l:match[5]),
\}
@@ -110,12 +105,17 @@ function! ale#handlers#gcc#HandleGCCFormat(buffer, lines) abort
let l:item.col = str2nr(l:match[3])
endif
" Finish filtering out filename : if the key exists but is empty,
" unlet it.
if get(l:item, 'filename', 'dummy_no_key_to_unlet') is# ''
unlet l:item['filename']
endif
call add(l:output, l:item)
" Reset include_lnum after an error has been added
let l:include_lnum = 0
endif
endfor
" Add remaining include errors after we go beyond the last line.
call s:AddIncludedErrors(l:output, l:include_lnum, l:include_lines)
return l:output
endfunction