]> git.madduck.net Git - etc/vim.git/blob - .vim/bundle/ale/ale_linters/javascript/flow.vim

madduck's git repository

Every one of the projects in this repository is available at the canonical URL git://git.madduck.net/madduck/pub/<projectpath> — see each project's metadata for the exact URL.

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.

SSH access, as well as push access can be individually arranged.

If you use my repositories frequently, consider adding the following snippet to ~/.gitconfig and using the third clone URL listed for each project:

[url "git://git.madduck.net/madduck/"]
  insteadOf = madduck:

Merge commit '76265755a1add77121c8f9dabb3e9bb70fe9a972' as '.vim/bundle/ale'
[etc/vim.git] / .vim / bundle / ale / ale_linters / javascript / flow.vim
1 " Author: Zach Perrault -- @zperrault
2 " Author: Florian Beeres <yuuki@protonmail.com>
3 " Description: FlowType checking for JavaScript files
4
5 call ale#Set('javascript_flow_executable', 'flow')
6 call ale#Set('javascript_flow_use_home_config', 0)
7 call ale#Set('javascript_flow_use_global', get(g:, 'ale_use_global_executables', 0))
8 call ale#Set('javascript_flow_use_respect_pragma', 1)
9
10 function! ale_linters#javascript#flow#GetExecutable(buffer) abort
11     let l:flow_config = ale#path#FindNearestFile(a:buffer, '.flowconfig')
12
13     if empty(l:flow_config)
14         " Don't run Flow if we can't find a .flowconfig file.
15         return ''
16     endif
17
18     " Don't run Flow with a configuration file from the home directory by
19     " default, which can eat all of your RAM.
20     if fnamemodify(l:flow_config, ':h') is? $HOME
21     \&& !ale#Var(a:buffer, 'javascript_flow_use_home_config')
22         return ''
23     endif
24
25     return ale#path#FindExecutable(a:buffer, 'javascript_flow', [
26     \   'node_modules/.bin/flow',
27     \])
28 endfunction
29
30 function! ale_linters#javascript#flow#GetCommand(buffer, version) abort
31     " If we can parse the version number, then only use --respect-pragma
32     " if the version is >= 0.36.0, which added the argument.
33     let l:use_respect_pragma = ale#Var(a:buffer, 'javascript_flow_use_respect_pragma')
34     \   && (empty(a:version) || ale#semver#GTE(a:version, [0, 36]))
35
36     return '%e check-contents'
37     \   . (l:use_respect_pragma ? ' --respect-pragma': '')
38     \   . ' --json --from ale %s < %t'
39     \   . (!has('win32') ? '; echo' : '')
40 endfunction
41
42 " Filter lines of flow output until we find the first line where the JSON
43 " output starts.
44 function! s:GetJSONLines(lines) abort
45     let l:start_index = 0
46
47     for l:line in a:lines
48         if l:line[:0] is# '{'
49             break
50         endif
51
52         let l:start_index += 1
53     endfor
54
55     return a:lines[l:start_index :]
56 endfunction
57
58 function! s:ExtraErrorMsg(current, new) abort
59     let l:newMsg = ''
60
61     if a:current is# ''
62         " extra messages appear to already have a :
63         let l:newMsg = a:new
64     else
65         let l:newMsg = a:current . ' ' . a:new
66     endif
67
68     return l:newMsg
69 endfunction
70
71 function! s:GetDetails(error) abort
72     let l:detail = ''
73
74     for l:extra_error in a:error.extra
75         if has_key(l:extra_error, 'message')
76             for l:extra_message in l:extra_error.message
77                 let l:detail = s:ExtraErrorMsg(l:detail, l:extra_message.descr)
78             endfor
79         endif
80
81         if has_key(l:extra_error, 'children')
82             for l:child in l:extra_error.children
83                 for l:child_message in l:child.message
84                     let l:detail = l:detail . ' ' . l:child_message.descr
85                 endfor
86             endfor
87         endif
88     endfor
89
90     return l:detail
91 endfunction
92
93 function! ale_linters#javascript#flow#Handle(buffer, lines) abort
94     let l:str = join(s:GetJSONLines(a:lines), '')
95
96     if empty(l:str)
97         return []
98     endif
99
100     let l:flow_output = json_decode(l:str)
101     let l:output = []
102
103     for l:error in get(l:flow_output, 'errors', [])
104         " Each error is broken up into parts
105         let l:text = ''
106         let l:line = 0
107         let l:col = 0
108
109         for l:message in l:error.message
110             " Comments have no line of column information, so we skip them.
111             " In certain cases, `l:message.loc.source` points to a different path
112             " than the buffer one, thus we skip this loc information too.
113             if has_key(l:message, 'loc')
114             \&& l:line is# 0
115             \&& ale#path#IsBufferPath(a:buffer, l:message.loc.source)
116                 let l:line = l:message.loc.start.line + 0
117                 let l:col = l:message.loc.start.column + 0
118             endif
119
120             if l:text is# ''
121                 let l:text = l:message.descr . ':'
122             else
123                 let l:text = l:text . ' ' . l:message.descr
124             endif
125         endfor
126
127         if has_key(l:error, 'operation')
128             let l:text = l:text . ' See also: ' . l:error.operation.descr
129         endif
130
131         let l:errorToAdd = {
132         \   'lnum': l:line,
133         \   'col': l:col,
134         \   'text': l:text,
135         \   'type': has_key(l:error, 'level') && l:error.level is# 'error' ? 'E' : 'W',
136         \}
137
138         if has_key(l:error, 'extra')
139             let l:errorToAdd.detail = l:errorToAdd.text
140             \   . "\n" . s:GetDetails(l:error)
141         endif
142
143         call add(l:output, l:errorToAdd)
144     endfor
145
146     return l:output
147 endfunction
148
149 call ale#linter#Define('javascript', {
150 \   'name': 'flow',
151 \   'executable': function('ale_linters#javascript#flow#GetExecutable'),
152 \   'command': {buffer -> ale#semver#RunWithVersionCheck(
153 \       buffer,
154 \       ale_linters#javascript#flow#GetExecutable(buffer),
155 \       '%e --version',
156 \       function('ale_linters#javascript#flow#GetCommand'),
157 \   )},
158 \   'callback': 'ale_linters#javascript#flow#Handle',
159 \   'read_buffer': 0,
160 \})