All patches and comments are welcome. Please squash your changes to logical
commits before using git-format-patch and git-send-email to
patches@git.madduck.net.
If you'd read over the Git project's submission guidelines and adhered to them,
I'd be especially grateful.
2 " Author: w0rp <devw0rp@gmail.com>
3 " Description: This file defines a handler function which ought to work for
4 " any program which outputs errors in the format that GCC uses.
6 let s:pragma_error = '#pragma once in main file'
8 " Look for lines like the following.
10 " <stdin>:8:5: warning: conversion lacks type at end of format [-Wformat=]
11 " <stdin>:10:27: error: invalid operands to binary - (have ‘int’ and ‘char *’)
12 " -:189:7: note: $/${} is unnecessary on arithmetic variables. [SC2004]
13 let s:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+)?:?(\d+)?:? ([^:]+): (.+)$'
14 let s:inline_pattern = '\v inlined from .* at \<stdin\>:(\d+):(\d+):$'
16 function! s:IsHeaderFile(filename) abort
17 return a:filename =~? '\v\.(h|hpp)$'
20 function! s:RemoveUnicodeQuotes(text) abort
22 let l:text = substitute(l:text, '[`´‘’]', '''', 'g')
23 let l:text = substitute(l:text, '\v\\u2018([^\\]+)\\u2019', '''\1''', 'g')
24 let l:text = substitute(l:text, '[“”]', '"', 'g')
29 function! s:ParseInlinedFunctionProblems(buffer, lines) abort
34 let l:match = matchlist(l:line, s:pattern)
36 if !empty(l:match) && !empty(l:pos_match)
38 \ 'lnum': str2nr(l:pos_match[1]),
39 \ 'col': str2nr(l:pos_match[2]),
40 \ 'type': (l:match[4] is# 'error' || l:match[4] is# 'fatal error') ? 'E' : 'W',
41 \ 'text': s:RemoveUnicodeQuotes(l:match[5]),
45 let l:pos_match = matchlist(l:line, s:inline_pattern)
51 " Report problems inside of header files just for gcc and clang
52 function! s:ParseProblemsInHeaders(buffer, lines) abort
54 let l:include_item = {}
56 for l:line in a:lines[: -2]
57 let l:include_match = matchlist(l:line, '\v^In file included from')
59 if !empty(l:include_item)
60 let l:pattern_match = matchlist(l:line, s:pattern)
62 if !empty(l:pattern_match) && l:pattern_match[1] is# '<stdin>'
63 if has_key(l:include_item, 'lnum')
64 call add(l:output, l:include_item)
67 let l:include_item = {}
72 let l:include_item.detail .= "\n" . l:line
75 if !empty(l:include_match)
76 if empty(l:include_item)
77 let l:include_item = {
78 \ 'text': 'Error found in header. See :ALEDetail',
84 if !empty(l:include_item)
85 let l:stdin_match = matchlist(l:line, '\vfrom \<stdin\>:(\d+):(\d*):?$')
87 if !empty(l:stdin_match)
88 let l:include_item.lnum = str2nr(l:stdin_match[1])
90 if str2nr(l:stdin_match[2])
91 let l:include_item.col = str2nr(l:stdin_match[2])
97 if !empty(l:include_item) && has_key(l:include_item, 'lnum')
98 call add(l:output, l:include_item)
104 function! ale#handlers#gcc#HandleGCCFormat(buffer, lines) abort
107 for l:match in ale#util#GetMatches(a:lines, s:pattern)
108 " Filter out the pragma errors
109 if s:IsHeaderFile(bufname(bufnr('')))
110 \&& l:match[5][:len(s:pragma_error) - 1] is# s:pragma_error
114 " If the 'error type' is a note, make it detail related to
115 " the previous error parsed in output
116 if l:match[4] is# 'note'
118 if !has_key(l:output[-1], 'detail')
119 let l:output[-1].detail = l:output[-1].text
121 " handle macro expansion errors/notes
122 if l:match[5] =~? '^in expansion of macro ‘\w*\w’$'
123 " if the macro expansion is in the file we're in, add
124 " the lnum and col keys to the previous error
125 if l:match[1] is# '<stdin>'
126 \ && !has_key(l:output[-1], 'col')
127 let l:output[-1].lnum = str2nr(l:match[2])
128 let l:output[-1].col = str2nr(l:match[3])
130 " the error is not in the current file, and since
131 " macro expansion errors don't show the full path to
132 " the error from the current file, we have to just
133 " give out a generic error message
134 let l:output[-1].text = 'Error found in macro expansion. See :ALEDetail'
139 let l:output[-1].detail = l:output[-1].detail . "\n"
140 \ . s:RemoveUnicodeQuotes(l:match[0])
147 \ 'lnum': str2nr(l:match[2]),
148 \ 'type': (l:match[4] is# 'error' || l:match[4] is# 'fatal error') ? 'E' : 'W',
149 \ 'text': s:RemoveUnicodeQuotes(l:match[5]),
152 if !empty(l:match[3])
153 let l:item.col = str2nr(l:match[3])
156 " If the filename is something like <stdin>, <nofile> or -, then
157 " this is an error for the file we checked.
158 if l:match[1] isnot# '-' && l:match[1][0] isnot# '<'
159 let l:item['filename'] = l:match[1]
162 call add(l:output, l:item)
168 " Handle problems with the GCC format, but report problems inside of headers.
169 function! ale#handlers#gcc#HandleGCCFormatWithIncludes(buffer, lines) abort
170 let l:output = ale#handlers#gcc#HandleGCCFormat(a:buffer, a:lines)
172 call extend(l:output, s:ParseInlinedFunctionProblems(a:buffer, a:lines))
173 call extend(l:output, s:ParseProblemsInHeaders(a:buffer, a:lines))