summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorw0rp <devw0rp@gmail.com>2018-07-30 20:09:43 +0100
committerw0rp <devw0rp@gmail.com>2018-07-30 20:09:43 +0100
commit16d0c52d24e8948b8bd8030e3fd112e0b6361c06 (patch)
tree608a4a86e1f0521830bb409d88026fe881ff6ec2
parent1e6b1d9be28495ead50e24b0d1eb93963dd92f4c (diff)
downloadale-16d0c52d24e8948b8bd8030e3fd112e0b6361c06.zip
Indicate that a C compiler failed due to problems in a header file
-rw-r--r--ale_linters/c/clang.vim2
-rw-r--r--ale_linters/c/gcc.vim2
-rw-r--r--ale_linters/cpp/clang.vim2
-rw-r--r--ale_linters/cpp/gcc.vim2
-rw-r--r--ale_linters/objc/clang.vim2
-rw-r--r--ale_linters/objcpp/clang.vim2
-rw-r--r--autoload/ale/handlers/gcc.vim77
-rw-r--r--test/handler/test_clang_handler.vader15
-rw-r--r--test/handler/test_gcc_handler.vader65
9 files changed, 141 insertions, 28 deletions
diff --git a/ale_linters/c/clang.vim b/ale_linters/c/clang.vim
index 48ea76dd..9d49fabb 100644
--- a/ale_linters/c/clang.vim
+++ b/ale_linters/c/clang.vim
@@ -28,5 +28,5 @@ call ale#linter#Define('c', {
\ {'callback': 'ale#c#GetMakeCommand', 'output_stream': 'stdout'},
\ {'callback': 'ale_linters#c#clang#GetCommand'}
\ ],
-\ 'callback': 'ale#handlers#gcc#HandleGCCFormat',
+\ 'callback': 'ale#handlers#gcc#HandleGCCFormatWithIncludes',
\})
diff --git a/ale_linters/c/gcc.vim b/ale_linters/c/gcc.vim
index 63fe87a6..e2dff65d 100644
--- a/ale_linters/c/gcc.vim
+++ b/ale_linters/c/gcc.vim
@@ -28,5 +28,5 @@ call ale#linter#Define('c', {
\ {'callback': 'ale#c#GetMakeCommand', 'output_stream': 'stdout'},
\ {'callback': 'ale_linters#c#gcc#GetCommand'}
\ ],
-\ 'callback': 'ale#handlers#gcc#HandleGCCFormat',
+\ 'callback': 'ale#handlers#gcc#HandleGCCFormatWithIncludes',
\})
diff --git a/ale_linters/cpp/clang.vim b/ale_linters/cpp/clang.vim
index 4f3c5b6f..72793a71 100644
--- a/ale_linters/cpp/clang.vim
+++ b/ale_linters/cpp/clang.vim
@@ -28,5 +28,5 @@ call ale#linter#Define('cpp', {
\ {'callback': 'ale#c#GetMakeCommand', 'output_stream': 'stdout'},
\ {'callback': 'ale_linters#cpp#clang#GetCommand'},
\ ],
-\ 'callback': 'ale#handlers#gcc#HandleGCCFormat',
+\ 'callback': 'ale#handlers#gcc#HandleGCCFormatWithIncludes',
\})
diff --git a/ale_linters/cpp/gcc.vim b/ale_linters/cpp/gcc.vim
index 242e389e..17f5acf5 100644
--- a/ale_linters/cpp/gcc.vim
+++ b/ale_linters/cpp/gcc.vim
@@ -29,5 +29,5 @@ call ale#linter#Define('cpp', {
\ {'callback': 'ale#c#GetMakeCommand', 'output_stream': 'stdout'},
\ {'callback': 'ale_linters#cpp#gcc#GetCommand'},
\ ],
-\ 'callback': 'ale#handlers#gcc#HandleGCCFormat',
+\ 'callback': 'ale#handlers#gcc#HandleGCCFormatWithIncludes',
\})
diff --git a/ale_linters/objc/clang.vim b/ale_linters/objc/clang.vim
index f4725a0e..4e80ac5c 100644
--- a/ale_linters/objc/clang.vim
+++ b/ale_linters/objc/clang.vim
@@ -19,5 +19,5 @@ call ale#linter#Define('objc', {
\ 'output_stream': 'stderr',
\ 'executable': 'clang',
\ 'command_callback': 'ale_linters#objc#clang#GetCommand',
-\ 'callback': 'ale#handlers#gcc#HandleGCCFormat',
+\ 'callback': 'ale#handlers#gcc#HandleGCCFormatWithIncludes',
\})
diff --git a/ale_linters/objcpp/clang.vim b/ale_linters/objcpp/clang.vim
index 0e9cefe9..d1474f17 100644
--- a/ale_linters/objcpp/clang.vim
+++ b/ale_linters/objcpp/clang.vim
@@ -19,5 +19,5 @@ call ale#linter#Define('objcpp', {
\ 'output_stream': 'stderr',
\ 'executable': 'clang++',
\ 'command_callback': 'ale_linters#objcpp#clang#GetCommand',
-\ 'callback': 'ale#handlers#gcc#HandleGCCFormat',
+\ 'callback': 'ale#handlers#gcc#HandleGCCFormatWithIncludes',
\})
diff --git a/autoload/ale/handlers/gcc.vim b/autoload/ale/handlers/gcc.vim
index 4b53652a..b8bac77f 100644
--- a/autoload/ale/handlers/gcc.vim
+++ b/autoload/ale/handlers/gcc.vim
@@ -5,6 +5,13 @@ scriptencoding utf-8
let s:pragma_error = '#pragma once in main file'
+" Look for lines like the following.
+"
+" <stdin>:8:5: warning: conversion lacks type at end of format [-Wformat=]
+" <stdin>:10:27: error: invalid operands to binary - (have ‘int’ and ‘char *’)
+" -:189:7: note: $/${} is unnecessary on arithmetic variables. [SC2004]
+let s:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+):(\d+)?:? ([^:]+): (.+)$'
+
function! s:IsHeaderFile(filename) abort
return a:filename =~? '\v\.(h|hpp)$'
endfunction
@@ -18,16 +25,63 @@ function! s:RemoveUnicodeQuotes(text) abort
return l:text
endfunction
+" Report problems inside of header files just for gcc and clang
+function! s:ParseProblemsInHeaders(buffer, lines) abort
+ let l:output = []
+ let l:include_item = {}
+
+ for l:line in a:lines[: -2]
+ let l:include_match = matchlist(l:line, '\v^In file included from')
+
+ if !empty(l:include_item)
+ let l:pattern_match = matchlist(l:line, s:pattern)
+
+ if !empty(l:pattern_match) && l:pattern_match[1] is# '<stdin>'
+ if has_key(l:include_item, 'lnum')
+ call add(l:output, l:include_item)
+ endif
+
+ let l:include_item = {}
+
+ continue
+ endif
+
+ let l:include_item.detail .= "\n" . l:line
+ endif
+
+ if !empty(l:include_match)
+ if empty(l:include_item)
+ let l:include_item = {
+ \ 'text': 'Error found in header. See :ALEDetail',
+ \ 'detail': l:line,
+ \}
+ endif
+ endif
+
+ if !empty(l:include_item)
+ let l:stdin_match = matchlist(l:line, '\vfrom \<stdin\>:(\d+):(\d*):?$')
+
+ if !empty(l:stdin_match)
+ let l:include_item.lnum = str2nr(l:stdin_match[1])
+
+ if str2nr(l:stdin_match[2])
+ let l:include_item.col = str2nr(l:stdin_match[2])
+ endif
+ endif
+ endif
+ endfor
+
+ if !empty(l:include_item) && has_key(l:include_item, 'lnum')
+ call add(l:output, l:include_item)
+ endif
+
+ return l:output
+endfunction
+
function! ale#handlers#gcc#HandleGCCFormat(buffer, lines) abort
- " Look for lines like the following.
- "
- " <stdin>:8:5: warning: conversion lacks type at end of format [-Wformat=]
- " <stdin>:10:27: error: invalid operands to binary - (have ‘int’ and ‘char *’)
- " -:189:7: note: $/${} is unnecessary on arithmetic variables. [SC2004]
- let l:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+):(\d+)?:? ([^:]+): (.+)$'
let l:output = []
- for l:match in ale#util#GetMatches(a:lines, l:pattern)
+ for l:match in ale#util#GetMatches(a:lines, s:pattern)
" Filter out the pragma errors
if s:IsHeaderFile(bufname(bufnr('')))
\&& l:match[5][:len(s:pragma_error) - 1] is# s:pragma_error
@@ -67,3 +121,12 @@ function! ale#handlers#gcc#HandleGCCFormat(buffer, lines) abort
return l:output
endfunction
+
+" Handle problems with the GCC format, but report problems inside of headers.
+function! ale#handlers#gcc#HandleGCCFormatWithIncludes(buffer, lines) abort
+ let l:output = ale#handlers#gcc#HandleGCCFormat(a:buffer, a:lines)
+
+ call extend(l:output, s:ParseProblemsInHeaders(a:buffer, a:lines))
+
+ return l:output
+endfunction
diff --git a/test/handler/test_clang_handler.vader b/test/handler/test_clang_handler.vader
index 278737a8..cc8eabd0 100644
--- a/test/handler/test_clang_handler.vader
+++ b/test/handler/test_clang_handler.vader
@@ -8,9 +8,20 @@ Execute(clang errors from included files should be parsed correctly):
\ 'type': 'E',
\ 'text': 'expected identifier or ''(''',
\ },
+ \ {
+ \ 'lnum': 3,
+ \ 'text': 'Error found in header. See :ALEDetail',
+ \ 'detail': join([
+ \ 'In file included from <stdin>:3:',
+ \ 'In file included from ./a.h:1:',
+ \ './b.h:1:1: error: expected identifier or ''(''',
+ \ '{{{',
+ \ '^',
+ \ ], "\n"),
+ \ },
\ ],
- \ ale#handlers#gcc#HandleGCCFormat(347, [
- \ 'In file included from test.c:3:',
+ \ ale#handlers#gcc#HandleGCCFormatWithIncludes(347, [
+ \ 'In file included from <stdin>:3:',
\ 'In file included from ./a.h:1:',
\ './b.h:1:1: error: expected identifier or ''(''',
\ '{{{',
diff --git a/test/handler/test_gcc_handler.vader b/test/handler/test_gcc_handler.vader
index 678d3f42..43b38769 100644
--- a/test/handler/test_gcc_handler.vader
+++ b/test/handler/test_gcc_handler.vader
@@ -1,7 +1,7 @@
Execute(The GCC handler should ignore other lines of output):
AssertEqual
\ [],
- \ ale#handlers#gcc#HandleGCCFormat(347, [
+ \ ale#handlers#gcc#HandleGCCFormatWithIncludes(347, [
\ 'foo',
\ 'bar',
\ 'baz',
@@ -17,12 +17,24 @@ Execute(GCC errors from included files should be parsed correctly):
\ 'type': 'E',
\ 'text': 'expected identifier or ''('' before ''{'' token',
\ },
+ \ {
+ \ 'lnum': 3,
+ \ 'col': 2,
+ \ 'text': 'Error found in header. See :ALEDetail',
+ \ 'detail': join([
+ \ 'In file included from <stdin>:3:2:',
+ \ 'broken.h:1:1: error: expected identifier or ''('' before ''{'' token',
+ \ ' {{{',
+ \ ' ^',
+ \ ], "\n"),
+ \ },
\ ],
- \ ale#handlers#gcc#HandleGCCFormat(347, [
- \ 'In file included from <stdin>:3:0:',
+ \ ale#handlers#gcc#HandleGCCFormatWithIncludes(347, [
+ \ 'In file included from <stdin>:3:2:',
\ 'broken.h:1:1: error: expected identifier or ''('' before ''{'' token',
\ ' {{{',
\ ' ^',
+ \ 'compilation terminated.',
\ ])
AssertEqual
@@ -34,13 +46,25 @@ Execute(GCC errors from included files should be parsed correctly):
\ 'type': 'E',
\ 'text': 'expected identifier or ''('' before ''{'' token',
\ },
+ \ {
+ \ 'lnum': 5,
+ \ 'text': 'Error found in header. See :ALEDetail',
+ \ 'detail': join([
+ \ 'In file included from a.h:1:0,',
+ \ ' from <stdin>:5:',
+ \ 'b.h:1:1: error: expected identifier or ''('' before ''{'' token',
+ \ ' {{{',
+ \ ' ^',
+ \ ], "\n"),
+ \ },
\ ],
- \ ale#handlers#gcc#HandleGCCFormat(347, [
+ \ ale#handlers#gcc#HandleGCCFormatWithIncludes(347, [
\ 'In file included from a.h:1:0,',
- \ ' from test.c:3:',
+ \ ' from <stdin>:5:',
\ 'b.h:1:1: error: expected identifier or ''('' before ''{'' token',
\ ' {{{',
\ ' ^',
+ \ 'compilation terminated.',
\ ])
AssertEqual
@@ -59,16 +83,31 @@ Execute(GCC errors from included files should be parsed correctly):
\ 'type': 'E',
\ 'text': 'unknown type name ''other_bad_type''',
\ },
+ \ {
+ \ 'lnum': 3,
+ \ 'text': 'Error found in header. See :ALEDetail',
+ \ 'detail': join([
+ \ 'In file included from a.h:1:0,',
+ \ ' from <stdin>:3:',
+ \ 'b.h:1:1: error: unknown type name ‘bad_type’',
+ \ ' bad_type x;',
+ \ ' ^',
+ \ 'b.h:2:1: error: unknown type name ‘other_bad_type’',
+ \ ' other_bad_type y;',
+ \ ' ^',
+ \ ], "\n"),
+ \ },
\ ],
- \ ale#handlers#gcc#HandleGCCFormat(347, [
+ \ ale#handlers#gcc#HandleGCCFormatWithIncludes(347, [
\ 'In file included from a.h:1:0,',
- \ ' from test.c:3:',
+ \ ' from <stdin>:3:',
\ 'b.h:1:1: error: unknown type name ‘bad_type’',
\ ' bad_type x;',
\ ' ^',
\ 'b.h:2:1: error: unknown type name ‘other_bad_type’',
\ ' other_bad_type y;',
\ ' ^',
+ \ 'compilation terminated.',
\ ])
Execute(The GCC handler shouldn't complain about #pragma once for headers):
@@ -76,7 +115,7 @@ Execute(The GCC handler shouldn't complain about #pragma once for headers):
AssertEqual
\ [],
- \ ale#handlers#gcc#HandleGCCFormat(347, [
+ \ ale#handlers#gcc#HandleGCCFormatWithIncludes(347, [
\ '<stdin>:1:1: warning: #pragma once in main file [enabled by default]',
\ ])
@@ -84,7 +123,7 @@ Execute(The GCC handler shouldn't complain about #pragma once for headers):
AssertEqual
\ [],
- \ ale#handlers#gcc#HandleGCCFormat(347, [
+ \ ale#handlers#gcc#HandleGCCFormatWithIncludes(347, [
\ '<stdin>:1:1: warning: #pragma once in main file [enabled by default]',
\ ])
@@ -119,7 +158,7 @@ Execute(The GCC handler should handle syntax errors):
\ 'text': 'expected '';'' before ''o'''
\ },
\ ],
- \ ale#handlers#gcc#HandleGCCFormat(347, [
+ \ ale#handlers#gcc#HandleGCCFormatWithIncludes(347, [
\ '<stdin>:6:12: error: invalid suffix "p" on integer constant',
\ '<stdin>:17:5: error: invalid suffix "n" on integer constant',
\ '<stdin>:4: error: variable or field ''foo'' declared void',
@@ -130,7 +169,7 @@ Execute(The GCC handler should handle syntax errors):
Execute(The GCC handler should handle notes with no previous message):
AssertEqual
\ [],
- \ ale#handlers#gcc#HandleGCCFormat(347, [
+ \ ale#handlers#gcc#HandleGCCFormatWithIncludes(347, [
\ '<stdin>:1:1: note: x',
\ '<stdin>:1:1: note: x',
\ ])
@@ -145,7 +184,7 @@ Execute(The GCC handler should interpret - as being the current file):
\ 'text': 'Some error',
\ },
\ ],
- \ ale#handlers#gcc#HandleGCCFormat(347, [
+ \ ale#handlers#gcc#HandleGCCFormatWithIncludes(347, [
\ '-:6:12: error: Some error',
\ ])
@@ -159,6 +198,6 @@ Execute(The GCC handler should handle fatal error messages due to missing files)
\ 'text': 'foo.h: No such file or directory'
\ },
\ ],
- \ ale#handlers#gcc#HandleGCCFormat(347, [
+ \ ale#handlers#gcc#HandleGCCFormatWithIncludes(347, [
\ '<stdin>:3:12: fatal error: foo.h: No such file or directory',
\ ])