File: test.vim

package info (click to toggle)
vim-ale 4.0.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 8,764 kB
  • sloc: sh: 499; python: 311; perl: 31; makefile: 4; xml: 4; javascript: 1
file content (205 lines) | stat: -rw-r--r-- 6,530 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
" Author: w0rp <devw0rp@gmail.com>
" Description: Functions for making testing ALE easier.
"
" This file should not typically be loaded during the normal execution of ALE.

" Change the directory for checking things in particular test directories
"
" This function will set the g:dir variable, which represents the working
" directory after changing the path. This variable allows a test to change
" directories, and then switch back to a directory at the start of the test
" run.
"
" This function should be run in a Vader Before: block.
function! ale#test#SetDirectory(docker_path) abort
    if a:docker_path[:len('/testplugin/') - 1] isnot# '/testplugin/'
        throw 'docker_path must start with /testplugin/!'
    endif

    " Try to switch directory, which will fail when running tests directly,
    " and not through the Docker image.
    silent! execute 'cd ' . fnameescape(a:docker_path)
    let g:dir = getcwd() " no-custom-checks
endfunction

" When g:dir is defined, switch back to the directory we saved, and then
" delete that variable.
"
" The filename will be reset to dummy.txt
"
" This function should be run in a Vader After: block.
function! ale#test#RestoreDirectory() abort
    call ale#test#SetFilename('dummy.txt')
    silent execute 'cd ' . fnameescape(g:dir)
    unlet! g:dir
endfunction

" Get a filename for the current buffer using a relative path to the script.
"
" If a g:dir variable is set, it will be used as the path to the directory
" containing the test file.
function! ale#test#GetFilename(path) abort
    let l:dir = get(g:, 'dir', '')

    if empty(l:dir)
        let l:dir = getcwd() " no-custom-checks
    endif

    let l:full_path = ale#path#IsAbsolute(a:path)
    \   ? a:path
    \   : l:dir . '/' . a:path

    return ale#path#Simplify(l:full_path)
endfunction

" Change the filename for the current buffer using a relative path to
" the script without running autocmd commands.
"
" If a g:dir variable is set, it will be used as the path to the directory
" containing the test file.
function! ale#test#SetFilename(path) abort
    let l:full_path = ale#test#GetFilename(a:path)
    silent! noautocmd execute 'file ' . fnameescape(l:full_path)
endfunction

function! RemoveNewerKeys(results) abort
    for l:item in a:results
        if has_key(l:item, 'module')
            call remove(l:item, 'module')
        endif

        if has_key(l:item, 'end_col')
            call remove(l:item, 'end_col')
        endif

        if has_key(l:item, 'end_lnum')
            call remove(l:item, 'end_lnum')
        endif
    endfor
endfunction

" Return loclist data with only the keys supported by the lowest Vim versions.
function! ale#test#GetLoclistWithoutNewerKeys() abort
    let l:results = getloclist(0)
    call RemoveNewerKeys(l:results)

    return l:results
endfunction

" Return quickfix data with only the keys supported by the lowest Vim versions.
function! ale#test#GetQflistWithoutNewerKeys() abort
    let l:results = getqflist()
    call RemoveNewerKeys(l:results)

    return l:results
endfunction

function! ale#test#GetPreviewWindowText() abort
    for l:window in range(1, winnr('$'))
        if getwinvar(l:window, '&previewwindow', 0)
            let l:buffer = winbufnr(l:window)

            return getbufline(l:buffer, 1, '$')
        endif
    endfor
endfunction

" This function can be called with a timeout to wait for all jobs to finish.
" If the jobs to not finish in the given number of milliseconds,
" an exception will be thrown.
"
" The time taken will be a very rough approximation, and more time may be
" permitted than is specified.
function! ale#test#WaitForJobs(deadline) abort
    let l:start_time = ale#events#ClockMilliseconds()

    if l:start_time == 0
        throw 'Failed to read milliseconds from the clock!'
    endif

    let l:job_list = []

    " Gather all of the jobs from every buffer.
    for [l:buffer, l:data] in items(ale#command#GetData())
        call extend(l:job_list, map(keys(l:data.jobs), 'str2nr(v:val)'))
    endfor

    " NeoVim has a built-in API for this, so use that.
    if has('nvim')
        let l:nvim_code_list = jobwait(l:job_list, a:deadline)

        if index(l:nvim_code_list, -1) >= 0
            throw 'Jobs did not complete on time!'
        endif

        return
    endif

    let l:should_wait_more = 1

    while l:should_wait_more
        let l:should_wait_more = 0

        for l:job_id in l:job_list
            if ale#job#IsRunning(l:job_id)
                let l:now = ale#events#ClockMilliseconds()

                if l:now - l:start_time > a:deadline
                    " Stop waiting after a timeout, so we don't wait forever.
                    throw 'Jobs did not complete on time!'
                endif

                " Wait another 10 milliseconds
                let l:should_wait_more = 1
                sleep 10ms
                break
            endif
        endfor
    endwhile

    " Sleep for a small amount of time after all jobs finish.
    " This seems to be enough to let handlers after jobs end run, and
    " prevents the occasional failure where this function exits after jobs
    " end, but before handlers are run.
    sleep 10ms

    " We must check the buffer data again to see if new jobs started for
    " linters with chained commands.
    let l:has_new_jobs = 0

    " Check again to see if any jobs are running.
    for l:info in values(g:ale_buffer_info)
        for [l:job_id, l:linter] in get(l:info, 'job_list', [])
            if ale#job#IsRunning(l:job_id)
                let l:has_new_jobs = 1
                break
            endif
        endfor
    endfor

    if l:has_new_jobs
        " We have to wait more. Offset the timeout by the time taken so far.
        let l:now = ale#events#ClockMilliseconds()
        let l:new_deadline = a:deadline - (l:now - l:start_time)

        if l:new_deadline <= 0
            " Enough time passed already, so stop immediately.
            throw 'Jobs did not complete on time!'
        endif

        call ale#test#WaitForJobs(l:new_deadline)
    endif
endfunction

function! ale#test#FlushJobs() abort
    " The variable is checked for in a loop, as calling one series of
    " callbacks can trigger a further series of callbacks.
    while exists('g:ale_run_synchronously_callbacks')
        let l:callbacks = g:ale_run_synchronously_callbacks
        unlet g:ale_run_synchronously_callbacks

        for l:Callback in l:callbacks
            call l:Callback()
        endfor
    endwhile
endfunction