diff --git a/autoload/ale.vim b/autoload/ale.vim index 7cf1def6..5efe15ab 100644 --- a/autoload/ale.vim +++ b/autoload/ale.vim @@ -53,9 +53,17 @@ function! ale#Queue(delay, ...) abort let s:lint_timer = -1 endif - let l:linters = ale#linter#Get(&filetype) - if len(l:linters) == 0 - " There are no linters to lint with, so stop here. + let l:buffer = bufnr('') + let l:linters = ale#linter#Get(getbufvar(l:buffer, '&filetype')) + + " Don't set up buffer data and so on if there are no linters to run. + if empty(l:linters) + " If we have some previous buffer data, then stop any jobs currently + " running and clear everything. + if has_key(g:ale_buffer_info, l:buffer) + call ale#engine#RunLinters(l:buffer, [], 1) + endif + return endif @@ -68,16 +76,16 @@ function! ale#Queue(delay, ...) abort endfunction function! ale#Lint(...) abort - if ale#ShouldDoNothing() - return - endif - " Get the buffer number linting was queued for. " or else take the current one. let l:buffer = len(a:0) > 1 && a:1 == s:lint_timer \ ? s:queued_buffer_number \ : bufnr('%') + if ale#ShouldDoNothing() + return + endif + " Use the filetype from the buffer let l:linters = ale#linter#Get(getbufvar(l:buffer, '&filetype')) let l:should_lint_file = 0 @@ -89,27 +97,7 @@ function! ale#Lint(...) abort let l:should_lint_file = filereadable(expand('#' . l:buffer . ':p')) endif - " Initialise the buffer information if needed. - call ale#engine#InitBufferInfo(l:buffer) - - " Clear the new loclist again, so we will work with all new items. - let g:ale_buffer_info[l:buffer].new_loclist = [] - - if l:should_lint_file - " Clear loclist items for files if we are checking files again. - let g:ale_buffer_info[l:buffer].lint_file_loclist = [] - else - " Otherwise, don't run any `lint_file` linters - " We will continue running any linters which are currently checking - " the file, and the items will be mixed together with any new items. - call filter(l:linters, '!v:val.lint_file') - endif - - call ale#engine#StopCurrentJobs(l:buffer, l:should_lint_file) - - for l:linter in l:linters - call ale#engine#Invoke(l:buffer, l:linter) - endfor + call ale#engine#RunLinters(l:buffer, l:linters, l:should_lint_file) endfunction " Reset flags indicating that files should be checked for all buffers. diff --git a/autoload/ale/cleanup.vim b/autoload/ale/cleanup.vim deleted file mode 100644 index 4701b960..00000000 --- a/autoload/ale/cleanup.vim +++ /dev/null @@ -1,19 +0,0 @@ -" Author: w0rp -" Description: Utility functions related to cleaning state. - -function! ale#cleanup#Buffer(buffer) abort - if has_key(g:ale_buffer_info, a:buffer) - call ale#engine#RemoveManagedFiles(a:buffer) - - " When buffers are removed, clear all of the jobs. - call ale#engine#StopCurrentJobs(a:buffer, 1) - - " Clear delayed highlights for a buffer being removed. - if g:ale_set_highlights - call ale#highlight#UnqueueHighlights(a:buffer) - call ale#highlight#RemoveHighlights([]) - endif - - call remove(g:ale_buffer_info, a:buffer) - endif -endfunction diff --git a/autoload/ale/engine.vim b/autoload/ale/engine.vim index fa26a37a..1b32dc85 100644 --- a/autoload/ale/engine.vim +++ b/autoload/ale/engine.vim @@ -46,6 +46,14 @@ function! ale#engine#InitBufferInfo(buffer) abort endif endfunction +" Return 1 if ALE is busy checking a given buffer +function! ale#engine#IsCheckingBuffer(buffer) abort + let l:info = get(g:ale_buffer_info, a:buffer, {}) + + return get(l:info, 'waiting_for_tsserver') == 1 + \|| !empty(get(l:info, 'job_list')) +endfunction + " Register a temporary file to be managed with the ALE engine for " a current job run. function! ale#engine#ManageFile(buffer, filename) abort @@ -69,9 +77,7 @@ function! ale#engine#CreateDirectory(buffer) abort endfunction function! ale#engine#RemoveManagedFiles(buffer) abort - if !has_key(g:ale_buffer_info, a:buffer) - return - endif + let l:info = get(g:ale_buffer_info, a:buffer) " We can't delete anything in a sandbox, so wait until we escape from " it to delete temporary files and directories. @@ -80,21 +86,25 @@ function! ale#engine#RemoveManagedFiles(buffer) abort endif " Delete files with a call akin to a plan `rm` command. - for l:filename in g:ale_buffer_info[a:buffer].temporary_file_list - call delete(l:filename) - endfor + if has_key(l:info, 'temporary_file_list') + for l:filename in l:info.temporary_file_list + call delete(l:filename) + endfor - let g:ale_buffer_info[a:buffer].temporary_file_list = [] + let l:info.temporary_file_list = [] + endif " Delete directories like `rm -rf`. " Directories are handled differently from files, so paths that are " intended to be single files can be set up for automatic deletion without " accidentally deleting entire directories. - for l:directory in g:ale_buffer_info[a:buffer].temporary_directory_list - call delete(l:directory, 'rf') - endfor + if has_key(l:info, 'temporary_directory_list') + for l:directory in l:info.temporary_directory_list + call delete(l:directory, 'rf') + endfor - let g:ale_buffer_info[a:buffer].temporary_directory_list = [] + let l:info.temporary_directory_list = [] + endif endfunction function! s:GatherOutput(job_id, line) abort @@ -118,34 +128,11 @@ function! s:HandleLoclist(linter_name, buffer, loclist) abort " for efficient lookup of the messages in the cursor handler. call sort(g:ale_buffer_info[a:buffer].loclist, 'ale#util#LocItemCompare') - let l:linting_is_done = empty(g:ale_buffer_info[a:buffer].job_list) - \ && !get(g:ale_buffer_info[a:buffer], 'waiting_for_tsserver', 0) - - if l:linting_is_done - " Automatically remove all managed temporary files and directories - " now that all jobs have completed. - call ale#engine#RemoveManagedFiles(a:buffer) - - " Figure out which linters are still enabled, and remove - " problems for linters which are no longer enabled. - let l:name_map = {} - - for l:linter in ale#linter#Get(getbufvar(a:buffer, '&filetype')) - let l:name_map[l:linter.name] = 1 - endfor - - call filter( - \ g:ale_buffer_info[a:buffer].loclist, - \ 'get(l:name_map, v:val.linter_name)', - \) + if ale#ShouldDoNothing() + return endif call ale#engine#SetResults(a:buffer, g:ale_buffer_info[a:buffer].loclist) - - if l:linting_is_done - " Call user autocommands. This allows users to hook into ALE's lint cycle. - silent doautocmd User ALELint - endif endfunction function! s:HandleExit(job_id, exit_code) abort @@ -217,10 +204,7 @@ function! s:HandleLSPResponse(response) abort endfunction function! ale#engine#SetResults(buffer, loclist) abort - let l:info = get(g:ale_buffer_info, a:buffer, {}) - let l:job_list = get(l:info, 'job_list', []) - let l:waiting_for_tsserver = get(l:info, 'waiting_for_tsserver', 0) - let l:linting_is_done = empty(l:job_list) && !l:waiting_for_tsserver + let l:linting_is_done = !ale#engine#IsCheckingBuffer(a:buffer) " Set signs first. This could potentially fix some line numbers. " The List could be sorted again here by SetSigns. @@ -254,6 +238,15 @@ function! ale#engine#SetResults(buffer, loclist) abort " This will only do something meaningful if we're in normal mode. call ale#cursor#EchoCursorWarning() endif + + if l:linting_is_done + " Automatically remove all managed temporary files and directories + " now that all jobs have completed. + call ale#engine#RemoveManagedFiles(a:buffer) + + " Call user autocommands. This allows users to hook into ALE's lint cycle. + silent doautocmd User ALELint + endif endfunction function! s:RemapItemTypes(type_map, loclist) abort @@ -371,6 +364,9 @@ function! s:CreateTemporaryFileForJob(buffer, temporary_file) abort return 1 endfunction +" Run a job. +" +" Returns 1 when the job was started successfully. function! s:RunJob(options) abort let l:command = a:options.command let l:buffer = a:options.buffer @@ -379,6 +375,10 @@ function! s:RunJob(options) abort let l:next_chain_index = a:options.next_chain_index let l:read_buffer = a:options.read_buffer + if empty(l:command) + return 0 + endif + let [l:temporary_file, l:command] = ale#command#FormatCommand(l:buffer, l:command, l:read_buffer) if s:CreateTemporaryFileForJob(l:buffer, l:temporary_file) @@ -457,6 +457,8 @@ function! s:RunJob(options) abort call l:job_options.exit_cb(l:job_id, v:shell_error) endif + + return l:job_id != 0 endfunction " Determine which commands to run for a link in a command chain, or @@ -516,11 +518,6 @@ function! ale#engine#ProcessChain(buffer, linter, chain_index, input) abort let l:command = ale#linter#GetCommand(a:buffer, a:linter) endif - if empty(l:command) - " Don't run any jobs if the command is an empty string. - return {} - endif - return { \ 'command': l:command, \ 'buffer': a:buffer, @@ -534,16 +531,10 @@ endfunction function! s:InvokeChain(buffer, linter, chain_index, input) abort let l:options = ale#engine#ProcessChain(a:buffer, a:linter, a:chain_index, a:input) - if !empty(l:options) - call s:RunJob(l:options) - elseif empty(g:ale_buffer_info[a:buffer].job_list) - " If we cancelled running a command, and we have no jobs in progress, - " then delete the managed temporary files now. - call ale#engine#RemoveManagedFiles(a:buffer) - endif + return s:RunJob(l:options) endfunction -function! ale#engine#StopCurrentJobs(buffer, include_lint_file_jobs) abort +function! s:StopCurrentJobs(buffer, include_lint_file_jobs) abort let l:info = get(g:ale_buffer_info, a:buffer, {}) let l:new_job_list = [] @@ -562,9 +553,6 @@ function! ale#engine#StopCurrentJobs(buffer, include_lint_file_jobs) abort " Update the List, so it includes only the jobs we still need. let l:info.job_list = l:new_job_list - " Ignore current LSP commands. - " We should consider cancelling them in future. - let l:info.lsp_command_list = [] endfunction function! s:CheckWithTSServer(buffer, linter, executable) abort @@ -584,7 +572,7 @@ function! s:CheckWithTSServer(buffer, linter, executable) abort call ale#history#Add(a:buffer, 'failed', l:id, l:command) endif - return + return 0 endif if ale#lsp#OpenTSServerDocumentIfNeeded(l:id, a:buffer) @@ -603,21 +591,88 @@ function! s:CheckWithTSServer(buffer, linter, executable) abort if l:request_id != 0 let l:info.waiting_for_tsserver = 1 endif + + return l:request_id != 0 endfunction -function! ale#engine#Invoke(buffer, linter) abort +function! s:RemoveProblemsForDisabledLinters(buffer, linters) abort + " Figure out which linters are still enabled, and remove + " problems for linters which are no longer enabled. + let l:name_map = {} + + for l:linter in a:linters + let l:name_map[l:linter.name] = 1 + endfor + + call filter( + \ get(g:ale_buffer_info[a:buffer], 'loclist', []), + \ 'get(l:name_map, v:val.linter_name)', + \) +endfunction + +" Run a linter for a buffer. +" +" Returns 1 if the linter was successfully run. +function! s:RunLinter(buffer, linter) abort if empty(a:linter.lsp) || a:linter.lsp ==# 'tsserver' let l:executable = ale#linter#GetExecutable(a:buffer, a:linter) " Run this program if it can be executed. if s:IsExecutable(l:executable) if a:linter.lsp ==# 'tsserver' - call s:CheckWithTSServer(a:buffer, a:linter, l:executable) - else - call s:InvokeChain(a:buffer, a:linter, 0, []) + return s:CheckWithTSServer(a:buffer, a:linter, l:executable) endif + + return s:InvokeChain(a:buffer, a:linter, 0, []) endif endif + + return 0 +endfunction + +function! ale#engine#RunLinters(buffer, linters, should_lint_file) abort + " Initialise the buffer information if needed. + call ale#engine#InitBufferInfo(a:buffer) + call s:StopCurrentJobs(a:buffer, a:should_lint_file) + call s:RemoveProblemsForDisabledLinters(a:buffer, a:linters) + + let l:any_linter_ran = 0 + + for l:linter in a:linters + " Skip linters for checking files if we shouldn't check the file. + if l:linter.lint_file && !a:should_lint_file + continue + endif + + if s:RunLinter(a:buffer, l:linter) + let l:any_linter_ran = 1 + endif + endfor + + " If we didn't manage to start checking the buffer with anything, + " and there's nothing running currently for the buffer, then clear the + " results. + " + " We need to use both checks, as we run some tests synchronously. + if !l:any_linter_ran && !ale#engine#IsCheckingBuffer(a:buffer) + call ale#engine#SetResults(a:buffer, []) + endif +endfunction + +" Clean up a buffer. +" +" This function will stop all current jobs for the buffer, +" clear the state of everything, and remove the Dictionary for managing +" the buffer. +function! ale#engine#Cleanup(buffer) abort + call ale#engine#RunLinters(a:buffer, [], 1) + + if g:ale_set_highlights + call ale#highlight#UnqueueHighlights(a:buffer) + call ale#highlight#RemoveHighlights([]) + endif + + call remove(g:ale_buffer_info, a:buffer) endfunction " Given a buffer number, return the warnings and errors for a given buffer. diff --git a/autoload/ale/highlight.vim b/autoload/ale/highlight.vim index 2f7bf5a5..b7255b53 100644 --- a/autoload/ale/highlight.vim +++ b/autoload/ale/highlight.vim @@ -67,27 +67,11 @@ function! s:GetALEMatches() abort return filter(getmatches(), 'v:val.group =~# ''^ALE''') endfunction -function! s:GetCurrentMatchIDs(loclist) abort - let l:current_id_map = {} - - for l:item in a:loclist - for l:id in get(l:item, 'match_id_list', []) - let l:current_id_map[l:id] = 1 - endfor - endfor - - return l:current_id_map -endfunction - " Given a loclist for current items to highlight, remove all highlights " except these which have matching loclist item entries. function! ale#highlight#RemoveHighlights(loclist) abort - let l:current_id_map = s:GetCurrentMatchIDs(a:loclist) - for l:match in s:GetALEMatches() - if !has_key(l:current_id_map, l:match.id) - call matchdelete(l:match.id) - endif + call matchdelete(l:match.id) endfor endfunction @@ -100,9 +84,6 @@ function! ale#highlight#UpdateHighlights() abort call ale#highlight#RemoveHighlights(l:loclist) endif - " Remove anything with a current match_id - call filter(l:loclist, '!has_key(v:val, ''match_id_list'')') - " Restore items from the map of hidden items, " if we don't have some new items to set already. if empty(l:loclist) && has_key(s:buffer_restore_map, l:buffer) @@ -132,10 +113,7 @@ function! ale#highlight#UpdateHighlights() abort " Set all of the positions, which are chunked into Lists which " are as large as will be accepted by matchaddpos. - " - " We will remember the IDs we set, so we can preserve some - " highlights when linting buffers after linting files. - let l:item.match_id_list = map( + call map( \ ale#highlight#CreatePositions(l:line, l:col, l:end_line, l:end_col), \ 'matchaddpos(l:group, v:val)' \) @@ -148,14 +126,6 @@ function! ale#highlight#BufferHidden(buffer) abort " Remember loclist items, so they can be restored later. if !empty(l:loclist) - " Remove match_ids, as they must be re-calculated when buffers are - " shown again. - for l:item in l:loclist - if has_key(l:item, 'match_id_list') - call remove(l:item, 'match_id_list') - endif - endfor - let s:buffer_restore_map[a:buffer] = filter( \ copy(l:loclist), \ 'v:val.bufnr == a:buffer && v:val.col > 0' diff --git a/autoload/ale/test.vim b/autoload/ale/test.vim index 7f06ae91..bfc716de 100644 --- a/autoload/ale/test.vim +++ b/autoload/ale/test.vim @@ -15,5 +15,9 @@ function! ale#test#SetFilename(path) abort let l:dir = getcwd() endif - silent noautocmd execute 'file ' . fnameescape(ale#path#Simplify(l:dir . '/' . a:path)) + let l:full_path = ale#path#IsAbsolute(a:path) + \ ? a:path + \ : l:dir . '/' . a:path + + silent noautocmd execute 'file ' . fnameescape(ale#path#Simplify(l:full_path)) endfunction diff --git a/plugin/ale.vim b/plugin/ale.vim index 58ab1ece..50735753 100644 --- a/plugin/ale.vim +++ b/plugin/ale.vim @@ -293,10 +293,9 @@ function! s:ALEToggle() abort " Make sure the buffer number is a number, not a string, " otherwise things can go wrong. for l:buffer in map(keys(g:ale_buffer_info), 'str2nr(v:val)') - " Stop jobs and delete stored buffer data - call ale#cleanup#Buffer(l:buffer) - " Clear signs, loclist, quicklist - call ale#engine#SetResults(l:buffer, []) + " Stop all jobs and clear the results for everything, and delete + " all of the data we stored for the buffer. + call ale#engine#Cleanup(l:buffer) endfor " Remove highlights for the current buffer now. @@ -368,7 +367,7 @@ nnoremap (ale_fix) :ALEFix augroup ALECleanupGroup autocmd! " Clean up buffers automatically when they are unloaded. - autocmd BufUnload * call ale#cleanup#Buffer(expand('')) + autocmd BufUnload * call ale#engine#Cleanup(str2nr(expand(''))) augroup END " Backwards Compatibility diff --git a/test/command_callback/test_javac_command_callback.vader b/test/command_callback/test_javac_command_callback.vader index 2f0bc50e..706839e4 100644 --- a/test/command_callback/test_javac_command_callback.vader +++ b/test/command_callback/test_javac_command_callback.vader @@ -8,7 +8,7 @@ After: call ale#linter#Reset() " We need to clean up the buffer to remove the temporary directories created " for the command. - call ale#cleanup#Buffer(bufnr('')) + call ale#engine#Cleanup(bufnr('')) let g:ale_java_javac_options = '' let g:ale_java_javac_classpath = '' @@ -63,7 +63,7 @@ Execute(The javac callback should combine discovered classpaths and manual ones) \ 'Invalid command string: ' . b:command Execute(The javac callback should detect source directories): - call ale#cleanup#Buffer(bufnr('')) + call ale#engine#Cleanup(bufnr('')) :e! java_paths/src/main/java/com/something/dummy call ale#engine#InitBufferInfo(bufnr('')) @@ -73,7 +73,7 @@ Execute(The javac callback should detect source directories): \ 'Invalid command string: ' . b:command Execute(The javac callback should combine detected source directories and classpaths): - call ale#cleanup#Buffer(bufnr('')) + call ale#engine#Cleanup(bufnr('')) :e! java_paths/src/main/java/com/something/dummy call ale#engine#InitBufferInfo(bufnr('')) diff --git a/test/test_ale_toggle.vader b/test/test_ale_toggle.vader index 3546ad71..202d8a35 100644 --- a/test/test_ale_toggle.vader +++ b/test/test_ale_toggle.vader @@ -11,7 +11,6 @@ Before: \ 'valid': 1, \}] let g:expected_groups = [ - \ 'ALEBufferFixGroup', \ 'ALECleanupGroup', \ 'ALECursorGroup', \ 'ALEHighlightBufferGroup', @@ -43,7 +42,10 @@ Before: for l:line in split(l:output, "\n") let l:match = matchlist(l:line, '^ALE[a-zA-Z]\+Group') + " We don't care about checking for the completion or fixing groups here. if !empty(l:match) + \&& l:match[0] !=# 'ALECompletionGroup' + \&& l:match[0] !=# 'ALEBufferFixGroup' call add(l:results, l:match[0]) endif endfor @@ -94,15 +96,17 @@ Execute(ALEToggle should reset everything and then run again): \ [{'group': 'ALEError', 'pos1': [2, 3, 1]}], \ map(getmatches(), '{''group'': v:val.group, ''pos1'': v:val.pos1}') AssertEqual g:expected_groups, ParseAuGroups() + AssertEqual [{'lnum': 2, 'bufnr': bufnr(''), 'col': 3, 'linter_name': 'testlinter', 'vcol': 0, 'nr': -1, 'type': 'E', 'text': 'foo bar', 'sign_id': 1000001}], g:ale_buffer_info[bufnr('')].loclist " Now Toggle ALE off. ALEToggle " Everything should be cleared. - AssertEqual [], getloclist(0) - AssertEqual [], ale#sign#FindCurrentSigns(bufnr('%')) - AssertEqual [], getmatches() - AssertEqual ['ALEBufferFixGroup', 'ALECleanupGroup', 'ALEHighlightBufferGroup'], ParseAuGroups() + Assert !has_key(g:ale_buffer_info, bufnr('')), 'The g:ale_buffer_info Dictionary was not removed' + AssertEqual [], getloclist(0), 'The loclist was not cleared' + AssertEqual [], ale#sign#FindCurrentSigns(bufnr('%')), 'The signs were not cleared' + AssertEqual [], getmatches(), 'The highlights were not cleared' + AssertEqual ['ALECleanupGroup', 'ALEHighlightBufferGroup'], ParseAuGroups() " Toggle ALE on, everything should be set up and run again. ALEToggle @@ -114,3 +118,4 @@ Execute(ALEToggle should reset everything and then run again): \ [{'group': 'ALEError', 'pos1': [2, 3, 1]}], \ map(getmatches(), '{''group'': v:val.group, ''pos1'': v:val.pos1}') AssertEqual g:expected_groups, ParseAuGroups() + AssertEqual [{'lnum': 2, 'bufnr': bufnr(''), 'col': 3, 'linter_name': 'testlinter', 'vcol': 0, 'nr': -1, 'type': 'E', 'text': 'foo bar', 'sign_id': 1000001}], g:ale_buffer_info[bufnr('')].loclist diff --git a/test/test_errors_removed_after_filetype_changed.vader b/test/test_errors_removed_after_filetype_changed.vader new file mode 100644 index 00000000..0498a501 --- /dev/null +++ b/test/test_errors_removed_after_filetype_changed.vader @@ -0,0 +1,58 @@ +Before: + Save g:ale_run_synchronously + + let b:old_filetype = &filetype + let g:ale_run_synchronously = 1 + + noautocmd let &filetype = 'foobar' + + function! TestCallback(buffer, output) + return [{'text': 'x', 'lnum': 1}] + endfunction + + call ale#linter#Define('foobar', { + \ 'name': 'buffer_linter', + \ 'callback': 'TestCallback', + \ 'executable': 'true', + \ 'command': 'true', + \ 'read_buffer': 0, + \}) + + call ale#linter#Define('foobar2', { + \ 'name': 'buffer_linter', + \ 'callback': 'TestCallback', + \ 'executable': 'true', + \ 'command': 'true', + \ 'read_buffer': 0, + \}) + +After: + Restore + + noautocmd let &filetype = b:old_filetype + unlet b:old_filetype + delfunction TestCallback + + if has_key(g:ale_buffer_info, bufnr('')) + call remove(g:ale_buffer_info, bufnr('')) + endif + + call ale#Queue(0) + +Execute(Error should be removed when the filetype changes to something else we cannot check): + call ale#Queue(0) + + AssertEqual 1, len(getloclist(0)) + + noautocmd let &filetype = 'foobar2' + + call ale#Queue(0) + + " We should get some items from the second filetype. + AssertEqual 1, len(getloclist(0)) + + noautocmd let &filetype = 'xxx' + + call ale#Queue(0) + + AssertEqual 0, len(getloclist(0)) diff --git a/test/test_highlight_placement.vader b/test/test_highlight_placement.vader index a134916f..3fa45ed2 100644 --- a/test/test_highlight_placement.vader +++ b/test/test_highlight_placement.vader @@ -22,6 +22,18 @@ Before: \] endfunction + " We don't care what the IDs are, just that we have some matches. + " The IDs are generated. + function! GetMatchesWithoutIDs() abort + let l:list = getmatches() + + for l:item in l:list + call remove(l:item, 'id') + endfor + + return l:list + endfunction + call ale#linter#Define('testft', { \ 'name': 'x', \ 'executable': 'echo', @@ -51,33 +63,11 @@ Execute(Highlights should be set when a linter runs): AssertEqual \ [ - \ {'group': 'ALEError', 'id': 4, 'priority': 10, 'pos1': [1, 1, 1]}, - \ {'group': 'ALEWarning', 'id': 5, 'priority': 10, 'pos1': [2, 1, 1]}, - \ {'group': 'ALEError', 'id': 6, 'priority': 10, 'pos1': [3, 5, 1]} + \ {'group': 'ALEError', 'priority': 10, 'pos1': [1, 1, 1]}, + \ {'group': 'ALEWarning', 'priority': 10, 'pos1': [2, 1, 1]}, + \ {'group': 'ALEError', 'priority': 10, 'pos1': [3, 5, 1]} \ ], - \ getmatches() - - AssertEqual [[4], [5], [6]], map(copy(g:ale_buffer_info[bufnr('')].loclist), 'v:val.match_id_list') - -Execute(Existing highlights should be kept): - call matchaddpos('ALEError', [[1, 2, 1]], 10, 347) - call matchaddpos('ALEWarning', [[2, 2, 1]], 10, 348) - - call ale#highlight#SetHighlights(bufnr('%'), [ - \ {'bufnr': bufnr('%'), 'match_id_list': [347], 'type': 'E', 'lnum': 1, 'col': 2}, - \ {'bufnr': bufnr('%'), 'match_id_list': [348], 'type': 'W', 'lnum': 2, 'col': 2}, - \ {'bufnr': bufnr('%'), 'type': 'E', 'lnum': 3, 'col': 2}, - \ {'bufnr': bufnr('%'), 'type': 'W', 'lnum': 4, 'col': 1}, - \]) - - AssertEqual - \ [ - \ {'group': 'ALEError', 'id': 347, 'priority': 10, 'pos1': [1, 2, 1]}, - \ {'group': 'ALEWarning', 'id': 348, 'priority': 10, 'pos1': [2, 2, 1]}, - \ {'group': 'ALEError', 'id': 7, 'priority': 10, 'pos1': [3, 2, 1]}, - \ {'group': 'ALEWarning', 'id': 8, 'priority': 10, 'pos1': [4, 1, 1]}, - \ ], - \ getmatches() + \ GetMatchesWithoutIDs() " This test is important for preventing ALE from showing highlights for " the wrong files. @@ -89,12 +79,12 @@ Execute(Highlights set by ALE should be removed when buffer cleanup is done): \]) AssertEqual - \ [{'group': 'ALEError', 'id': 9, 'priority': 10, 'pos1': [3, 2, 1]}], - \ getmatches() + \ [{'group': 'ALEError', 'priority': 10, 'pos1': [3, 2, 1]}], + \ GetMatchesWithoutIDs() - call ale#cleanup#Buffer(bufnr('%')) + call ale#engine#Cleanup(bufnr('%')) - AssertEqual [], getmatches() + AssertEqual [], GetMatchesWithoutIDs() Execute(Highlights should be cleared when buffers are hidden): call ale#engine#InitBufferInfo(bufnr('%')) @@ -108,15 +98,15 @@ Execute(Highlights should be cleared when buffers are hidden): \ g:ale_buffer_info[bufnr('%')].loclist \) - AssertEqual 1, len(getmatches()), 'The highlights weren''t initially set!' + AssertEqual 1, len(GetMatchesWithoutIDs()), 'The highlights weren''t initially set!' call ale#highlight#BufferHidden(bufnr('%')) - AssertEqual 0, len(getmatches()), 'The highlights weren''t cleared!' + AssertEqual 0, len(GetMatchesWithoutIDs()), 'The highlights weren''t cleared!' call ale#highlight#UpdateHighlights() - AssertEqual 1, len(getmatches()), 'The highlights weren''t set again!' + AssertEqual 1, len(GetMatchesWithoutIDs()), 'The highlights weren''t set again!' Execute(Only ALE highlights should be restored when buffers are restored): call ale#engine#InitBufferInfo(bufnr('%')) @@ -131,16 +121,16 @@ Execute(Only ALE highlights should be restored when buffers are restored): call matchaddpos('SomeOtherGroup', [[1, 1, 1]]) " We should have one more match here. - AssertEqual 2, len(getmatches()), 'The highlights weren''t initially set!' + AssertEqual 2, len(GetMatchesWithoutIDs()), 'The highlights weren''t initially set!' call ale#highlight#BufferHidden(bufnr('%')) - AssertEqual 0, len(getmatches()), 'The highlights weren''t cleared!' + AssertEqual 0, len(GetMatchesWithoutIDs()), 'The highlights weren''t cleared!' call ale#highlight#UpdateHighlights() " Only our matches should appear again. - AssertEqual 1, len(getmatches()), 'The highlights weren''t set again!' + AssertEqual 1, len(GetMatchesWithoutIDs()), 'The highlights weren''t set again!' Execute(Higlight end columns should set an appropriate size): call ale#highlight#SetHighlights(bufnr('%'), [ @@ -150,10 +140,10 @@ Execute(Higlight end columns should set an appropriate size): AssertEqual \ [ - \ {'group': 'ALEError', 'id': 15, 'priority': 10, 'pos1': [3, 2, 4]}, - \ {'group': 'ALEWarning', 'id': 16, 'priority': 10, 'pos1': [4, 1, 5]}, + \ {'group': 'ALEError', 'priority': 10, 'pos1': [3, 2, 4]}, + \ {'group': 'ALEWarning', 'priority': 10, 'pos1': [4, 1, 5]}, \ ], - \ getmatches() + \ GetMatchesWithoutIDs() Execute(Higlight end columns should set an appropriate size): call ale#highlight#SetHighlights(bufnr('%'), [ @@ -168,15 +158,15 @@ Execute(Higlight end columns should set an appropriate size): AssertEqual \ [ - \ {'group': 'ALEError', 'id': 17, 'priority': 10, 'pos1': [1, 1, 1]}, - \ {'group': 'ALEError', 'id': 18, 'priority': 10, 'pos1': [2, 1, 1]}, - \ {'group': 'ALEStyleError', 'id': 19, 'priority': 10, 'pos1': [3, 1, 1]}, - \ {'group': 'ALEWarning', 'id': 20, 'priority': 10, 'pos1': [4, 1, 1]}, - \ {'group': 'ALEWarning', 'id': 21, 'priority': 10, 'pos1': [5, 1, 1]}, - \ {'group': 'ALEStyleWarning', 'id': 22, 'priority': 10, 'pos1': [6, 1, 1]}, - \ {'group': 'ALEInfo', 'id': 23, 'priority': 10, 'pos1': [7, 1, 1]}, + \ {'group': 'ALEError', 'priority': 10, 'pos1': [1, 1, 1]}, + \ {'group': 'ALEError', 'priority': 10, 'pos1': [2, 1, 1]}, + \ {'group': 'ALEStyleError', 'priority': 10, 'pos1': [3, 1, 1]}, + \ {'group': 'ALEWarning', 'priority': 10, 'pos1': [4, 1, 1]}, + \ {'group': 'ALEWarning', 'priority': 10, 'pos1': [5, 1, 1]}, + \ {'group': 'ALEStyleWarning', 'priority': 10, 'pos1': [6, 1, 1]}, + \ {'group': 'ALEInfo', 'priority': 10, 'pos1': [7, 1, 1]}, \ ], - \ getmatches() + \ GetMatchesWithoutIDs() Execute(Highlighting should support errors spanning many lines): let g:items = [ @@ -189,15 +179,13 @@ Execute(Highlighting should support errors spanning many lines): AssertEqual \ [ \ { - \ 'group': 'ALEError', 'id': 24, 'priority': 10, 'pos1': [1, 1, 1073741824], + \ 'group': 'ALEError', 'priority': 10, 'pos1': [1, 1, 1073741824], \ 'pos2': [2], 'pos3': [3], 'pos4': [4], 'pos5': [5], 'pos6': [6], \ 'pos7': [7], 'pos8': [8], \ }, \ { - \ 'group': 'ALEError', 'id': 25, 'priority': 10, + \ 'group': 'ALEError', 'priority': 10, \ 'pos1': [9], 'pos2': [10, 1, 3] \ }, \ ], - \ getmatches() - - AssertEqual [[24, 25]], map(copy(g:items), 'v:val.match_id_list') + \ GetMatchesWithoutIDs() diff --git a/test/test_lint_file_linters.vader b/test/test_lint_file_linters.vader index a02ecca3..b0dc1eb3 100644 --- a/test/test_lint_file_linters.vader +++ b/test/test_lint_file_linters.vader @@ -69,6 +69,10 @@ Before: \ 'read_buffer': 0, \}) + let g:filename = tempname() + call writefile([], g:filename) + call ale#test#SetFilename(g:filename) + After: Restore @@ -79,6 +83,12 @@ After: delfunction LintFileCallback delfunction BufferCallback + if filereadable(g:filename) + call delete(g:filename) + endif + + unlet g:filename + Given foobar (Some imaginary filetype): foo bar @@ -107,6 +117,9 @@ Execute(Running linters without 'lint_file' should run only buffer linters): Execute(Running linters with 'lint_file' should run all linters): call ale#ResetLintFileMarkers() let g:ale_buffer_info = {} + + Assert filereadable(expand('%:p')), 'The file was not readable' + call ale#Queue(0, 'lint_file') AssertEqual [ @@ -139,6 +152,9 @@ Execute(Running linters with 'lint_file' should run all linters): Execute(Linter errors from files should be kept): call ale#ResetLintFileMarkers() let g:ale_buffer_info = {} + + Assert filereadable(expand('%:p')), 'The file was not readable' + call ale#Queue(0, 'lint_file') " Change the results for the buffer callback. diff --git a/test/test_lint_on_enter_when_file_changed.vader b/test/test_lint_on_enter_when_file_changed.vader index ff4e7dd5..cfa53878 100644 --- a/test/test_lint_on_enter_when_file_changed.vader +++ b/test/test_lint_on_enter_when_file_changed.vader @@ -30,6 +30,8 @@ After: call setloclist(0, []) Execute(The file changed event function should set b:ale_file_changed): + let g:ale_lint_on_enter = 0 + if has('gui') new else diff --git a/test/test_linting_updates_loclist.vader b/test/test_linting_updates_loclist.vader index 009a4537..19adfa1f 100644 --- a/test/test_linting_updates_loclist.vader +++ b/test/test_linting_updates_loclist.vader @@ -65,8 +65,4 @@ Execute(The loclist should be updated after linting is done): call ale#engine#WaitForJobs(2000) AssertEqual ['' . bufnr('%')], keys(g:ale_buffer_info) - - let g:expected_data[0].match_id_list = [getmatches()[0].id] - let g:expected_data[1].match_id_list = [getmatches()[1].id] - AssertEqual g:expected_data, g:ale_buffer_info[bufnr('%')].loclist diff --git a/test/test_temporary_file_management.vader b/test/test_temporary_file_management.vader index 4eed345c..6d1f0dfd 100644 --- a/test/test_temporary_file_management.vader +++ b/test/test_temporary_file_management.vader @@ -84,7 +84,7 @@ Execute(ALE should delete managed files even if no command is run): Execute(ALE should delete managed files when the buffer is removed): call ale#engine#InitBufferInfo(bufnr('%')) call TestCommandCallback(bufnr('%')) - call ale#cleanup#Buffer(bufnr('%')) + call ale#engine#Cleanup(bufnr('%')) Assert !filereadable(g:filename), 'The temporary file was not deleted' Assert !isdirectory(g:directory), 'The temporary directory was not deleted' @@ -105,7 +105,7 @@ Execute(ALE should create and delete directories for ale#engine#CreateDirectory( " The two directories shouldn't be the same. AssertNotEqual b:dir2, b:dir - call ale#cleanup#Buffer(bufnr('%')) + call ale#engine#Cleanup(bufnr('%')) Assert !isdirectory(b:dir), 'The directory was not deleted' Assert !isdirectory(b:dir2), 'The second directory was not deleted'