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.
1 " Author: w0rp <devw0rp@gmail.com>
2 " Description: Error handling for the format GHC outputs.
4 function! ale#handlers#haskell#GetStackExecutable(bufnr) abort
5 if ale#path#FindNearestFile(a:bufnr, 'stack.yaml') isnot# ''
9 " if there is no stack.yaml file, we don't use stack even if it exists,
10 " so we return '', because executable('') apparently always fails
14 " Remember the directory used for temporary files for Vim.
15 let s:temp_dir = fnamemodify(ale#util#Tempname(), ':h')
16 " Build part of a regular expression for matching ALE temporary filenames.
17 let s:temp_regex_prefix =
19 \ . substitute(s:temp_dir, '\\', '\\\\', 'g')
22 function! s:PanicOutput(lines) abort
26 \ 'text': 'ghc panic!',
28 \ 'detail' : join(a:lines, "\n"),
32 function! ale#handlers#haskell#HandleGHCFormat(buffer, lines) abort
33 " Look for lines like the following.
35 "Appoint/Lib.hs:8:1: warning:
37 let l:basename = expand('#' . a:buffer . ':t')
38 " Build a complete regular expression for replacing temporary filenames
39 " in Haskell error messages with the basename for this file.
40 let l:temp_filename_regex = s:temp_regex_prefix . l:basename
42 let l:pattern = '\v^\s*([a-zA-Z]?:?[^:]+):(\d+):(\d+):(.*)?$'
45 let l:corrected_lines = []
47 " If ghc panic error, put the whole message in details and exit.
48 let l:panic_position = match(a:lines,'ghc: panic!')
49 let l:panic_end = match(a:lines,'Please report this as a GHC bug:')
51 if l:panic_position >= 0
52 return s:PanicOutput(a:lines[l:panic_position : l:panic_end])
55 " Group the lines into smaller lists.
57 if len(matchlist(l:line, l:pattern)) > 0
58 call add(l:corrected_lines, [l:line])
60 call add(l:corrected_lines, [l:line])
61 elseif len(l:corrected_lines) > 0
62 call add(l:corrected_lines[-1], l:line)
66 for l:line_list in l:corrected_lines
67 " Join the smaller lists into one large line to parse.
68 let l:line = l:line_list[0]
70 for l:extra_line in l:line_list[1:]
71 let l:line .= substitute(l:extra_line, '\v^\s+', ' ', '')
74 let l:match = matchlist(l:line, l:pattern)
80 if !ale#path#IsBufferPath(a:buffer, l:match[1])
84 let l:errors = matchlist(l:match[4], '\v([wW]arning|[eE]rror): ?(.*)')
87 let l:ghc_type = l:errors[1]
88 let l:text = l:errors[2]
91 let l:text = l:match[4][:0] is# ' ' ? l:match[4][1:] : l:match[4]
94 if l:ghc_type is? 'Warning'
100 " Replace temporary filenames in problem messages with the basename
101 let l:text = substitute(l:text, l:temp_filename_regex, l:basename, 'g')
104 \ 'lnum': l:match[2] + 0,
105 \ 'col': l:match[3] + 0,
110 " Include extra lines as details if they are there.
111 if len(l:line_list) > 1
112 let l:item.detail = join(l:line_list[1:], "\n")
115 call add(l:output, l:item)