Handle multiple files localtion lists with gcc handler (#1034)
Handle multiple files in the GCC handler.
This commit is contained in:
parent
960ae62aaa
commit
25d2af0b25
@ -43,6 +43,10 @@ endfunction
|
|||||||
|
|
||||||
function! ale#handlers#gcc#HandleGCCFormat(buffer, lines) abort
|
function! ale#handlers#gcc#HandleGCCFormat(buffer, lines) abort
|
||||||
let l:include_pattern = '\v^(In file included | *)from ([^:]*):(\d+)'
|
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_lnum = 0
|
||||||
let l:include_lines = []
|
let l:include_lines = []
|
||||||
let l:included_filename = ''
|
let l:included_filename = ''
|
||||||
@ -58,51 +62,42 @@ function! ale#handlers#gcc#HandleGCCFormat(buffer, lines) abort
|
|||||||
let l:match = matchlist(l:line, l:pattern)
|
let l:match = matchlist(l:line, l:pattern)
|
||||||
|
|
||||||
if empty(l:match)
|
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)
|
let l:include_match = matchlist(l:line, l:include_pattern)
|
||||||
|
" If the line has an 'included from' pattern, store the line to
|
||||||
if empty(l:include_match)
|
" create a gutter sign at the appropriate location in linted file
|
||||||
" If this isn't another include header line, then we
|
if !empty(l:include_match)
|
||||||
" need to collect it.
|
" We don't check if l:include_match[2] is linted filename
|
||||||
call add(l:include_lines, l:line)
|
" because the last line matching include_pattern in a group
|
||||||
else
|
" of contiguous lines is probably concerning the linted file
|
||||||
" GCC and clang return the lists of files in different orders,
|
" anyway
|
||||||
" so we'll only grab the line number from lines which aren't
|
let l:include_lnum = l:include_match[3]
|
||||||
" 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
|
endif
|
||||||
|
|
||||||
let l:include_lines = []
|
|
||||||
let l:included_filename = ''
|
|
||||||
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
|
else
|
||||||
" If we hit a regular error again, then add the previously
|
" Filter out the pragma errors
|
||||||
" 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 = ''
|
|
||||||
|
|
||||||
if s:IsHeaderFile(bufname(bufnr('')))
|
if s:IsHeaderFile(bufname(bufnr('')))
|
||||||
\&& l:match[5][:len(s:pragma_error) - 1] is# s:pragma_error
|
\&& l:match[5][:len(s:pragma_error) - 1] is# s:pragma_error
|
||||||
continue
|
continue
|
||||||
endif
|
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 = {
|
let l:item = {
|
||||||
|
\ 'filename': (l:match[1][:0] is# '<') ? '' : l:match[1],
|
||||||
\ 'lnum': str2nr(l:match[2]),
|
\ '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]),
|
\ '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])
|
let l:item.col = str2nr(l:match[3])
|
||||||
endif
|
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)
|
call add(l:output, l:item)
|
||||||
|
" Reset include_lnum after an error has been added
|
||||||
|
let l:include_lnum = 0
|
||||||
endif
|
endif
|
||||||
endfor
|
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
|
return l:output
|
||||||
endfunction
|
endfunction
|
||||||
|
@ -2,15 +2,11 @@ Execute(clang errors from included files should be parsed correctly):
|
|||||||
AssertEqual
|
AssertEqual
|
||||||
\ [
|
\ [
|
||||||
\ {
|
\ {
|
||||||
\ 'lnum': 3,
|
\ 'lnum': 1,
|
||||||
|
\ 'col': 1,
|
||||||
|
\ 'filename': './b.h',
|
||||||
\ 'type': 'E',
|
\ 'type': 'E',
|
||||||
\ 'text': 'Problems were found in the header (See :ALEDetail)',
|
\ 'text': 'expected identifier or ''(''',
|
||||||
\ 'detail': join([
|
|
||||||
\ './b.h:1:1: error: expected identifier or ''(''',
|
|
||||||
\ '{{{',
|
|
||||||
\ '^',
|
|
||||||
\ '1 error generated.',
|
|
||||||
\ ], "\n"),
|
|
||||||
\ },
|
\ },
|
||||||
\ ],
|
\ ],
|
||||||
\ ale#handlers#gcc#HandleGCCFormat(347, [
|
\ ale#handlers#gcc#HandleGCCFormat(347, [
|
||||||
|
@ -2,14 +2,11 @@ Execute(GCC errors from included files should be parsed correctly):
|
|||||||
AssertEqual
|
AssertEqual
|
||||||
\ [
|
\ [
|
||||||
\ {
|
\ {
|
||||||
\ 'lnum': 3,
|
\ 'lnum': 1,
|
||||||
|
\ 'col': 1,
|
||||||
|
\ 'filename': 'broken.h',
|
||||||
\ 'type': 'E',
|
\ 'type': 'E',
|
||||||
\ 'text': 'Problems were found in the header (See :ALEDetail)',
|
\ 'text': 'expected identifier or ''('' before ''{'' token',
|
||||||
\ 'detail': join([
|
|
||||||
\ 'broken.h:1:1: error: expected identifier or ''('' before ''{'' token',
|
|
||||||
\ ' {{{',
|
|
||||||
\ ' ^',
|
|
||||||
\ ], "\n"),
|
|
||||||
\ },
|
\ },
|
||||||
\ ],
|
\ ],
|
||||||
\ ale#handlers#gcc#HandleGCCFormat(347, [
|
\ ale#handlers#gcc#HandleGCCFormat(347, [
|
||||||
@ -22,14 +19,11 @@ Execute(GCC errors from included files should be parsed correctly):
|
|||||||
AssertEqual
|
AssertEqual
|
||||||
\ [
|
\ [
|
||||||
\ {
|
\ {
|
||||||
\ 'lnum': 3,
|
\ 'lnum': 1,
|
||||||
|
\ 'col': 1,
|
||||||
|
\ 'filename': 'b.h',
|
||||||
\ 'type': 'E',
|
\ 'type': 'E',
|
||||||
\ 'text': 'Problems were found in the header (See :ALEDetail)',
|
\ 'text': 'expected identifier or ''('' before ''{'' token',
|
||||||
\ 'detail': join([
|
|
||||||
\ 'b.h:1:1: error: expected identifier or ''('' before ''{'' token',
|
|
||||||
\ ' {{{',
|
|
||||||
\ ' ^',
|
|
||||||
\ ], "\n"),
|
|
||||||
\ },
|
\ },
|
||||||
\ ],
|
\ ],
|
||||||
\ ale#handlers#gcc#HandleGCCFormat(347, [
|
\ ale#handlers#gcc#HandleGCCFormat(347, [
|
||||||
@ -43,17 +37,18 @@ Execute(GCC errors from included files should be parsed correctly):
|
|||||||
AssertEqual
|
AssertEqual
|
||||||
\ [
|
\ [
|
||||||
\ {
|
\ {
|
||||||
\ 'lnum': 3,
|
\ 'lnum': 1,
|
||||||
|
\ 'col': 1,
|
||||||
|
\ 'filename': 'b.h',
|
||||||
\ 'type': 'E',
|
\ 'type': 'E',
|
||||||
\ 'text': 'Problems were found in the header (See :ALEDetail)',
|
\ 'text': 'unknown type name ''bad_type''',
|
||||||
\ 'detail': join([
|
\ },
|
||||||
\ 'b.h:1:1: error: unknown type name ‘bad_type’',
|
\ {
|
||||||
\ ' bad_type x;',
|
\ 'lnum': 2,
|
||||||
\ ' ^',
|
\ 'col': 1,
|
||||||
\ 'b.h:2:1: error: unknown type name ‘other_bad_type’',
|
\ 'filename': 'b.h',
|
||||||
\ ' other_bad_type y;',
|
\ 'type': 'E',
|
||||||
\ ' ^',
|
\ 'text': 'unknown type name ''other_bad_type''',
|
||||||
\ ], "\n"),
|
|
||||||
\ },
|
\ },
|
||||||
\ ],
|
\ ],
|
||||||
\ ale#handlers#gcc#HandleGCCFormat(347, [
|
\ ale#handlers#gcc#HandleGCCFormat(347, [
|
||||||
|
@ -10,12 +10,14 @@ Execute(The vint handler should parse error messages correctly):
|
|||||||
\ {
|
\ {
|
||||||
\ 'lnum': 1,
|
\ 'lnum': 1,
|
||||||
\ 'col': 1,
|
\ 'col': 1,
|
||||||
|
\ 'filename': 'gcc.vim',
|
||||||
\ 'text': 'Use scriptencoding when multibyte char exists (see :help :script encoding)',
|
\ 'text': 'Use scriptencoding when multibyte char exists (see :help :script encoding)',
|
||||||
\ 'type': 'W',
|
\ 'type': 'W',
|
||||||
\ },
|
\ },
|
||||||
\ {
|
\ {
|
||||||
\ 'lnum': 3,
|
\ 'lnum': 3,
|
||||||
\ 'col': 17,
|
\ 'col': 17,
|
||||||
|
\ 'filename': 'gcc.vim',
|
||||||
\ 'end_col': 18,
|
\ 'end_col': 18,
|
||||||
\ 'text': 'Use robust operators ''==#'' or ''==?'' instead of ''=='' (see Google VimScript Style Guide (Matching))',
|
\ 'text': 'Use robust operators ''==#'' or ''==?'' instead of ''=='' (see Google VimScript Style Guide (Matching))',
|
||||||
\ 'type': 'W',
|
\ 'type': 'W',
|
||||||
@ -23,6 +25,7 @@ Execute(The vint handler should parse error messages correctly):
|
|||||||
\ {
|
\ {
|
||||||
\ 'lnum': 3,
|
\ 'lnum': 3,
|
||||||
\ 'col': 8,
|
\ 'col': 8,
|
||||||
|
\ 'filename': 'gcc.vim',
|
||||||
\ 'end_col': 15,
|
\ 'end_col': 15,
|
||||||
\ 'text': 'Make the scope explicit like ''l:filename'' (see Anti-pattern of vimrc (Scope of identifier))',
|
\ 'text': 'Make the scope explicit like ''l:filename'' (see Anti-pattern of vimrc (Scope of identifier))',
|
||||||
\ 'type': 'W',
|
\ 'type': 'W',
|
||||||
@ -30,6 +33,7 @@ Execute(The vint handler should parse error messages correctly):
|
|||||||
\ {
|
\ {
|
||||||
\ 'lnum': 7,
|
\ 'lnum': 7,
|
||||||
\ 'col': 8,
|
\ 'col': 8,
|
||||||
|
\ 'filename': 'gcc.vim',
|
||||||
\ 'end_col': 15,
|
\ 'end_col': 15,
|
||||||
\ 'text': 'Undefined variable: filename (see :help E738)',
|
\ 'text': 'Undefined variable: filename (see :help E738)',
|
||||||
\ 'type': 'W',
|
\ 'type': 'W',
|
||||||
@ -37,6 +41,7 @@ Execute(The vint handler should parse error messages correctly):
|
|||||||
\ {
|
\ {
|
||||||
\ 'lnum': 8,
|
\ 'lnum': 8,
|
||||||
\ 'col': 11,
|
\ 'col': 11,
|
||||||
|
\ 'filename': 'gcc.vim',
|
||||||
\ 'end_col': 16,
|
\ 'end_col': 16,
|
||||||
\ 'text': 'E128: Function name must start with a capital or contain a colon: foobar (see ynkdir/vim-vimlparser)',
|
\ 'text': 'E128: Function name must start with a capital or contain a colon: foobar (see ynkdir/vim-vimlparser)',
|
||||||
\ 'type': 'E',
|
\ 'type': 'E',
|
||||||
@ -44,6 +49,7 @@ Execute(The vint handler should parse error messages correctly):
|
|||||||
\ {
|
\ {
|
||||||
\ 'lnum': 9,
|
\ 'lnum': 9,
|
||||||
\ 'col': 12,
|
\ 'col': 12,
|
||||||
|
\ 'filename': 'gcc.vim',
|
||||||
\ 'end_col': 13,
|
\ 'end_col': 13,
|
||||||
\ 'text': 'Use robust operators ''=~#'' or ''=~?'' instead of ''=~'' (see Google VimScript Style Guide (Matching))',
|
\ 'text': 'Use robust operators ''=~#'' or ''=~?'' instead of ''=~'' (see Google VimScript Style Guide (Matching))',
|
||||||
\ 'type': 'W',
|
\ 'type': 'W',
|
||||||
|
@ -20,7 +20,8 @@ Before:
|
|||||||
let l:actual_sign_list = []
|
let l:actual_sign_list = []
|
||||||
|
|
||||||
for l:line in split(l:output, "\n")
|
for l:line in split(l:output, "\n")
|
||||||
let l:match = matchlist(l:line, 'line=\(\d\+\).*name=\(ALE[a-zA-Z]\+\)')
|
let l:match = matchlist(l:line, '\m\s*line=\(\d\+\).*name=\(ALE[a-zA-Z]\+\)')
|
||||||
|
|
||||||
|
|
||||||
if len(l:match) > 0
|
if len(l:match) > 0
|
||||||
call add(l:actual_sign_list, [l:match[1], l:match[2]])
|
call add(l:actual_sign_list, [l:match[1], l:match[2]])
|
||||||
|
Loading…
Reference in New Issue
Block a user