]> git.madduck.net Git - etc/vim.git/blob - autoload/ale/assert.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:

Squashed '.vim/bundle/ale/' content from commit 22185c4c
[etc/vim.git] / autoload / ale / assert.vim
1 let s:command_output = []
2
3 function! ale#assert#GivenCommandOutput(...) abort
4     let s:command_output = a:000
5 endfunction
6
7 function! s:GetLinter() abort
8     let l:linters = ale#linter#GetLintersLoaded()
9     let l:filetype_linters = get(values(l:linters), 0, [])
10
11     if len(l:linters) is 0 || len(l:filetype_linters) is 0
12         throw 'No linters were loaded'
13     endif
14
15     if len(l:linters) > 1 || len(l:filetype_linters) > 1
16         throw 'More than one linter was loaded'
17     endif
18
19     return l:filetype_linters[0]
20 endfunction
21
22 function! s:FormatExe(command, executable) abort
23     return substitute(a:command, '%e', '\=ale#Escape(a:executable)', 'g')
24 endfunction
25
26 function! s:ProcessDeferredCommands(initial_result) abort
27     let l:result = a:initial_result
28     let l:command_index = 0
29     let l:command = []
30
31     while ale#command#IsDeferred(l:result)
32         call add(l:command, s:FormatExe(l:result.command, l:result.executable))
33
34         if get(g:, 'ale_run_synchronously_emulate_commands')
35             " Don't run commands, but simulate the results.
36             let l:Callback = g:ale_run_synchronously_callbacks[0]
37             let l:output = get(s:command_output, l:command_index, [])
38             call l:Callback(0, l:output)
39             unlet g:ale_run_synchronously_callbacks
40
41             let l:command_index += 1
42         else
43             " Run the commands in the shell, synchronously.
44             call ale#test#FlushJobs()
45         endif
46
47         let l:result = l:result.value
48     endwhile
49
50     call add(l:command, l:result)
51
52     return l:command
53 endfunction
54
55 function! s:ProcessDeferredCwds(initial_command, initial_cwd) abort
56     let l:result = a:initial_command
57     let l:last_cwd = v:null
58     let l:command_index = 0
59     let l:cwd_list = []
60
61     while ale#command#IsDeferred(l:result)
62         call add(l:cwd_list, l:result.cwd)
63
64         if get(g:, 'ale_run_synchronously_emulate_commands')
65             " Don't run commands, but simulate the results.
66             let l:Callback = g:ale_run_synchronously_callbacks[0]
67             let l:output = get(s:command_output, l:command_index, [])
68             call l:Callback(0, l:output)
69             unlet g:ale_run_synchronously_callbacks
70
71             let l:command_index += 1
72         else
73             " Run the commands in the shell, synchronously.
74             call ale#test#FlushJobs()
75         endif
76
77         let l:result = l:result.value
78     endwhile
79
80     call add(l:cwd_list, a:initial_cwd is v:null ? l:last_cwd : a:initial_cwd)
81
82     return l:cwd_list
83 endfunction
84
85 " Load the currently loaded linter for a test case, and check that the command
86 " matches the given string.
87 function! ale#assert#Linter(expected_executable, expected_command) abort
88     let l:buffer = bufnr('')
89     let l:linter = s:GetLinter()
90     let l:executable = ale#linter#GetExecutable(l:buffer, l:linter)
91
92     while ale#command#IsDeferred(l:executable)
93         call ale#test#FlushJobs()
94         let l:executable = l:executable.value
95     endwhile
96
97     let l:command = s:ProcessDeferredCommands(
98     \   ale#linter#GetCommand(l:buffer, l:linter),
99     \)
100
101     if type(a:expected_command) isnot v:t_list
102         let l:command = l:command[-1]
103     endif
104
105     if type(l:command) is v:t_string
106         " Replace %e with the escaped executable, so tests keep passing after
107         " linters are changed to use %e.
108         let l:command = s:FormatExe(l:command, l:executable)
109     elseif type(l:command) is v:t_list
110         call map(l:command, 's:FormatExe(v:val, l:executable)')
111     endif
112
113     AssertEqual
114     \   [a:expected_executable, a:expected_command],
115     \   [l:executable, l:command]
116 endfunction
117
118 function! ale#assert#LinterCwd(expected_cwd) abort
119     let l:buffer = bufnr('')
120     let l:linter = s:GetLinter()
121
122     let l:initial_cwd = ale#linter#GetCwd(l:buffer, l:linter)
123     call ale#command#SetCwd(l:buffer, l:initial_cwd)
124
125     let l:cwd = s:ProcessDeferredCwds(
126     \   ale#linter#GetCommand(l:buffer, l:linter),
127     \   l:initial_cwd,
128     \)
129
130     call ale#command#ResetCwd(l:buffer)
131
132     if type(a:expected_cwd) isnot v:t_list
133         let l:cwd = l:cwd[-1]
134     endif
135
136     AssertEqual a:expected_cwd, l:cwd
137 endfunction
138
139 function! ale#assert#FixerCwd(expected_cwd) abort
140     let l:buffer = bufnr('')
141     let l:cwd = s:ProcessDeferredCwds(s:FixerFunction(l:buffer), v:null)
142
143     if type(a:expected_cwd) isnot v:t_list
144         let l:cwd = l:cwd[-1]
145     endif
146
147     AssertEqual a:expected_cwd, l:cwd
148 endfunction
149
150 function! ale#assert#Fixer(expected_result) abort
151     let l:buffer = bufnr('')
152     let l:result = s:ProcessDeferredCommands(s:FixerFunction(l:buffer))
153
154     if type(a:expected_result) isnot v:t_list
155         let l:result = l:result[-1]
156     endif
157
158     AssertEqual a:expected_result, l:result
159 endfunction
160
161 function! ale#assert#FixerNotExecuted() abort
162     let l:buffer = bufnr('')
163     let l:result = s:ProcessDeferredCommands(s:FixerFunction(l:buffer))[-1]
164
165     Assert empty(l:result), "The fixer will be executed when it shouldn't be"
166 endfunction
167
168 function! ale#assert#LinterNotExecuted() abort
169     let l:buffer = bufnr('')
170     let l:linter = s:GetLinter()
171     let l:executable = ale#linter#GetExecutable(l:buffer, l:linter)
172     let l:executed = 1
173
174     if !empty(l:executable)
175         let l:command = ale#linter#GetCommand(l:buffer, l:linter)
176
177         if type(l:command) is v:t_list
178             let l:command = l:command[-1]
179         endif
180
181         let l:executed = !empty(l:command)
182     else
183         let l:executed = 0
184     endif
185
186     Assert !l:executed, "The linter will be executed when it shouldn't be"
187 endfunction
188
189 function! ale#assert#LSPOptions(expected_options) abort
190     let l:buffer = bufnr('')
191     let l:linter = s:GetLinter()
192     let l:initialization_options = ale#lsp_linter#GetOptions(l:buffer, l:linter)
193
194     AssertEqual a:expected_options, l:initialization_options
195 endfunction
196
197 function! ale#assert#LSPConfig(expected_config) abort
198     let l:buffer = bufnr('')
199     let l:linter = s:GetLinter()
200     let l:config = ale#lsp_linter#GetConfig(l:buffer, l:linter)
201
202     AssertEqual a:expected_config, l:config
203 endfunction
204
205 function! ale#assert#LSPLanguage(expected_language) abort
206     let l:buffer = bufnr('')
207     let l:linter = s:GetLinter()
208     let l:Language = l:linter.language
209     let l:language = type(l:Language) is v:t_func
210     \   ? l:Language(l:buffer)
211     \   : l:Language
212
213     AssertEqual a:expected_language, l:language
214 endfunction
215
216 function! ale#assert#LSPProject(expected_root) abort
217     let l:buffer = bufnr('')
218     let l:linter = s:GetLinter()
219     let l:root = ale#lsp_linter#FindProjectRoot(l:buffer, l:linter)
220
221     AssertEqual a:expected_root, l:root
222 endfunction
223
224 function! ale#assert#LSPAddress(expected_address) abort
225     let l:buffer = bufnr('')
226     let l:linter = s:GetLinter()
227     let l:address = ale#linter#GetAddress(l:buffer, l:linter)
228
229     AssertEqual a:expected_address, l:address
230 endfunction
231
232 function! ale#assert#SetUpLinterTestCommands() abort
233     command! -nargs=+ GivenCommandOutput :call ale#assert#GivenCommandOutput(<args>)
234     command! -nargs=+ AssertLinterCwd :call ale#assert#LinterCwd(<args>)
235     command! -nargs=+ AssertLinter :call ale#assert#Linter(<args>)
236     command! -nargs=0 AssertLinterNotExecuted :call ale#assert#LinterNotExecuted()
237     command! -nargs=+ AssertLSPOptions :call ale#assert#LSPOptions(<args>)
238     command! -nargs=+ AssertLSPConfig :call ale#assert#LSPConfig(<args>)
239     command! -nargs=+ AssertLSPLanguage :call ale#assert#LSPLanguage(<args>)
240     command! -nargs=+ AssertLSPProject :call ale#assert#LSPProject(<args>)
241     command! -nargs=+ AssertLSPAddress :call ale#assert#LSPAddress(<args>)
242 endfunction
243
244 function! ale#assert#SetUpFixerTestCommands() abort
245     command! -nargs=+ GivenCommandOutput :call ale#assert#GivenCommandOutput(<args>)
246     command! -nargs=+ AssertFixerCwd :call ale#assert#FixerCwd(<args>)
247     command! -nargs=+ AssertFixer :call ale#assert#Fixer(<args>)
248     command! -nargs=0 AssertFixerNotExecuted :call ale#assert#FixerNotExecuted()
249 endfunction
250
251 function! ale#assert#ResetVariables(filetype, name, ...) abort
252     " If the suffix of the option names format is different, an additional
253     " argument can be used for that instead.
254     if a:0 > 1
255         throw 'Too many arguments'
256     endif
257
258     let l:option_suffix = get(a:000, 0, a:name)
259     let l:prefix = 'ale_' . a:filetype . '_'
260     \   . substitute(l:option_suffix, '-', '_', 'g')
261     let l:filter_expr = 'v:val[: len(l:prefix) - 1] is# l:prefix'
262
263     " Save and clear linter variables.
264     " We'll load the runtime file to reset them to defaults.
265     for l:key in filter(keys(g:), l:filter_expr)
266         execute 'Save g:' . l:key
267         unlet g:[l:key]
268     endfor
269
270     for l:key in filter(keys(b:), l:filter_expr)
271         unlet b:[l:key]
272     endfor
273 endfunction
274
275 " A dummy function for making sure this module is loaded.
276 function! ale#assert#SetUpLinterTest(filetype, name) abort
277     " Set up a marker so ALE doesn't create real random temporary filenames.
278     let g:ale_create_dummy_temporary_file = 1
279
280     " Remove current linters.
281     call ale#linter#Reset()
282     call ale#linter#PreventLoading(a:filetype)
283
284     Save g:ale_root
285     let g:ale_root = {}
286
287     Save b:ale_root
288     unlet! b:ale_root
289
290     call ale#assert#ResetVariables(a:filetype, a:name)
291
292     Save g:ale_c_build_dir
293     unlet! g:ale_c_build_dir
294     unlet! b:ale_c_build_dir
295
296     execute 'runtime ale_linters/' . a:filetype . '/' . a:name . '.vim'
297
298     if !exists('g:dir')
299         call ale#test#SetDirectory('/testplugin/test/linter')
300     endif
301
302     call ale#assert#SetUpLinterTestCommands()
303
304     let g:ale_run_synchronously = 1
305     let g:ale_run_synchronously_emulate_commands = 1
306 endfunction
307
308 function! ale#assert#TearDownLinterTest() abort
309     unlet! g:ale_create_dummy_temporary_file
310     unlet! g:ale_run_synchronously
311     unlet! g:ale_run_synchronously_callbacks
312     unlet! g:ale_run_synchronously_emulate_commands
313     unlet! g:ale_run_synchronously_command_results
314     let s:command_output = []
315
316     if exists(':GivenCommandOutput')
317         delcommand GivenCommandOutput
318     endif
319
320     if exists(':AssertLinterCwd')
321         delcommand AssertLinterCwd
322     endif
323
324     if exists(':AssertLinter')
325         delcommand AssertLinter
326     endif
327
328     if exists(':AssertLinterNotExecuted')
329         delcommand AssertLinterNotExecuted
330     endif
331
332     if exists(':AssertLSPOptions')
333         delcommand AssertLSPOptions
334     endif
335
336     if exists(':AssertLSPConfig')
337         delcommand AssertLSPConfig
338     endif
339
340     if exists(':AssertLSPLanguage')
341         delcommand AssertLSPLanguage
342     endif
343
344     if exists(':AssertLSPProject')
345         delcommand AssertLSPProject
346     endif
347
348     if exists(':AssertLSPAddress')
349         delcommand AssertLSPAddress
350     endif
351
352     if exists('g:dir')
353         call ale#test#RestoreDirectory()
354     endif
355
356     Restore
357
358     call ale#linter#Reset()
359
360     if exists('*ale#semver#ResetVersionCache')
361         call ale#semver#ResetVersionCache()
362     endif
363 endfunction
364
365 function! ale#assert#SetUpFixerTest(filetype, name, ...) abort
366     " If the suffix of the option names format is different, an additional
367     " argument can be used for that instead.
368     if a:0 > 1
369         throw 'Too many arguments'
370     endif
371
372     " Set up a marker so ALE doesn't create real random temporary filenames.
373     let g:ale_create_dummy_temporary_file = 1
374
375     let l:function_name = ale#fix#registry#GetFunc(a:name)
376     let s:FixerFunction = function(l:function_name)
377
378     let l:option_suffix = get(a:000, 0, a:name)
379     call ale#assert#ResetVariables(a:filetype, a:name, l:option_suffix)
380
381     execute 'runtime autoload/ale/fixers/' . substitute(a:name, '-', '_', 'g') . '.vim'
382
383     if !exists('g:dir')
384         call ale#test#SetDirectory('/testplugin/test/fixers')
385     endif
386
387     call ale#assert#SetUpFixerTestCommands()
388
389     let g:ale_run_synchronously = 1
390     let g:ale_run_synchronously_emulate_commands = 1
391 endfunction
392
393 function! ale#assert#TearDownFixerTest() abort
394     unlet! g:ale_create_dummy_temporary_file
395     unlet! g:ale_run_synchronously
396     unlet! g:ale_run_synchronously_callbacks
397     unlet! g:ale_run_synchronously_emulate_commands
398     unlet! g:ale_run_synchronously_command_results
399     let s:command_output = []
400     unlet! s:FixerFunction
401
402     if exists('g:dir')
403         call ale#test#RestoreDirectory()
404     endif
405
406     Restore
407
408     if exists('*ale#semver#ResetVersionCache')
409         call ale#semver#ResetVersionCache()
410     endif
411
412     if exists(':GivenCommandOutput')
413         delcommand GivenCommandOutput
414     endif
415
416     if exists(':AssertFixerCwd')
417         delcommand AssertFixerCwd
418     endif
419
420     if exists(':AssertFixer')
421         delcommand AssertFixer
422     endif
423
424     if exists(':AssertFixerNotExecuted')
425         delcommand AssertFixerNotExecuted
426     endif
427 endfunction