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 call ale#Set('ruby_steep_executable', 'steep')
2 call ale#Set('ruby_steep_options', '')
4 " Find the nearest dir containing a Steepfile
5 function! ale_linters#ruby#steep#FindRoot(buffer) abort
6 for l:name in ['Steepfile']
7 let l:dir = fnamemodify(
8 \ ale#path#FindNearestFile(a:buffer, l:name),
12 if l:dir isnot# '.' && isdirectory(l:dir)
20 " Rename path relative to root
21 function! ale_linters#ruby#steep#RelativeToRoot(buffer, path) abort
22 let l:separator = has('win32') ? '\' : '/'
23 let l:steep_root = ale_linters#ruby#steep#FindRoot(a:buffer)
25 " path isn't under root
26 if l:steep_root is# ''
30 let l:steep_root_prefix = l:steep_root . l:separator
32 " win32 path separators get interpreted by substitute, escape them
34 let l:steep_root_pat = substitute(l:steep_root_prefix, '\\', '\\\\', 'g')
36 let l:steep_root_pat = l:steep_root_prefix
39 return substitute(a:path, l:steep_root_pat, '', '')
42 function! ale_linters#ruby#steep#GetCommand(buffer) abort
43 let l:executable = ale#Var(a:buffer, 'ruby_steep_executable')
45 " steep check needs to apply some config from the file path so:
46 " - steep check can't use stdin (no path)
47 " - steep check can't use %t (path outside of project)
48 " => we can only use %s
50 " somehow :ALEInfo shows that ALE still appends '< %t' to the command
51 " => luckily steep check ignores stdin
53 " somehow steep has a problem with absolute path to file but a path
54 " relative to Steepfile directory works:
55 " see https://github.com/soutaro/steep/pull/975
56 " => change to Steepfile directory and remove leading path
58 let l:buffer_filename = fnamemodify(bufname(a:buffer), ':p')
59 let l:buffer_filename = fnameescape(l:buffer_filename)
61 let l:relative = ale_linters#ruby#steep#RelativeToRoot(a:buffer, l:buffer_filename)
63 " if file is not under steep root, steep can't type check
69 return ale#ruby#EscapeExecutable(l:executable, 'steep')
71 \ . ale#Var(a:buffer, 'ruby_steep_options')
72 \ . ' ' . fnameescape(l:relative)
75 function! ale_linters#ruby#steep#GetType(severity) abort
76 if a:severity is? 'information'
77 \|| a:severity is? 'hint'
81 if a:severity is? 'warning'
88 " Handle output from steep
89 function! ale_linters#ruby#steep#HandleOutput(buffer, lines) abort
96 " Look for first line of a message block
97 " If not in-message (l:in == 0) that's expected
98 " If in-message (l:in > 0) that's less expected but let's recover
99 let l:match = matchlist(l:line, '^\([^:]*\):\([0-9]*\):\([0-9]*\): \[\([^]]*\)\] \(.*\)')
102 " Something is lingering: recover by pushing what is there
104 call add(l:output, l:item)
108 let l:filename = l:match[1]
110 " Steep's reported column is offset by 1 (zero-indexed?)
112 \ 'lnum': l:match[2] + 0,
113 \ 'col': l:match[3] + 1,
114 \ 'type': ale_linters#ruby#steep#GetType(l:match[4]),
115 \ 'text': l:match[5],
118 " Done with this line, mark being in-message and go on with next line
123 " We're past the first line of a message block
125 " Look for code in subsequent lines of the message block
126 if l:line =~# '^│ Diagnostic ID:'
127 let l:match = matchlist(l:line, '^│ Diagnostic ID: \(.*\)')
130 let l:item.code = l:match[1]
137 " Look for last line of the message block
139 " Done with the line, mark looking for underline and go on with the next line
144 " Look for underline right after last line
146 let l:match = matchlist(l:line, '\([~][~]*\)')
149 let l:item.end_col = l:item['col'] + len(l:match[1]) - 1
152 call add(l:output, l:item)
154 " Done with the line, mark looking for first line and go on with the next line
165 call ale#linter#Define('ruby', {
167 \ 'executable': {b -> ale#Var(b, 'ruby_steep_executable')},
168 \ 'language': 'ruby',
169 \ 'command': function('ale_linters#ruby#steep#GetCommand'),
170 \ 'project_root': function('ale_linters#ruby#steep#FindRoot'),
171 \ 'callback': 'ale_linters#ruby#steep#HandleOutput',