summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorw0rp <devw0rp@gmail.com>2017-08-09 00:05:55 +0100
committerw0rp <devw0rp@gmail.com>2017-08-09 00:05:55 +0100
commit670858f7743ad42ee83d6f9aab162b16069e4395 (patch)
tree0001bd18c3ee2eb231856535c47a1d31e9b0aaa4
parentac8cc6d9911376472ed85928f15b89a7cfa62516 (diff)
downloadale-670858f7743ad42ee83d6f9aab162b16069e4395.zip
Fix #468 - Add a cool down period for when things go wrong
-rw-r--r--autoload/ale.vim75
-rw-r--r--doc/ale.txt6
-rw-r--r--test/test_lint_error_delay.vader18
3 files changed, 82 insertions, 17 deletions
diff --git a/autoload/ale.vim b/autoload/ale.vim
index 55125a04..6e16a8ee 100644
--- a/autoload/ale.vim
+++ b/autoload/ale.vim
@@ -5,6 +5,15 @@
let s:lint_timer = -1
let s:queued_buffer_number = -1
let s:should_lint_file_for_buffer = {}
+let s:queue_error_delay_ms = 1000 * 60 * 2
+
+if !exists('s:dont_queue_until')
+ let s:dont_queue_until = -1
+endif
+
+if !exists('s:dont_lint_until')
+ let s:dont_lint_until = -1
+endif
" Return 1 if a file is too large for ALE to handle.
function! ale#FileTooLarge() abort
@@ -31,26 +40,39 @@ function! ale#Queue(delay, ...) abort
throw 'too many arguments!'
endif
+ let l:now = ale#util#ClockMilliseconds()
+
+ if l:now < s:dont_queue_until
+ return
+ endif
+
+ let s:dont_queue_until = l:now + s:queue_error_delay_ms
+
" Default linting_flag to ''
let l:linting_flag = get(a:000, 0, '')
+ let l:buffer = get(a:000, 1, bufnr(''))
+
+ call s:ALEQueueImpl(a:delay, l:linting_flag, l:buffer)
- if l:linting_flag !=# '' && l:linting_flag !=# 'lint_file'
+ let s:dont_queue_until = -1
+endfunction
+
+function! s:ALEQueueImpl(delay, linting_flag, buffer) abort
+ if a:linting_flag !=# '' && a:linting_flag !=# 'lint_file'
throw "linting_flag must be either '' or 'lint_file'"
endif
- let l:buffer = get(a:000, 1, bufnr(''))
-
- if type(l:buffer) != type(0)
+ if type(a:buffer) != type(0)
throw 'buffer_number must be a Number'
endif
- if ale#ShouldDoNothing(l:buffer)
+ if ale#ShouldDoNothing(a:buffer)
return
endif
" Remember that we want to check files for this buffer.
" We will remember this until we finally run the linters, via any event.
- if l:linting_flag is# 'lint_file'
+ if a:linting_flag is# 'lint_file'
let s:should_lint_file_for_buffer[bufnr('%')] = 1
endif
@@ -59,24 +81,24 @@ function! ale#Queue(delay, ...) abort
let s:lint_timer = -1
endif
- let l:linters = ale#linter#Get(getbufvar(l:buffer, '&filetype'))
+ let l:linters = ale#linter#Get(getbufvar(a: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)
+ if has_key(g:ale_buffer_info, a:buffer)
+ call ale#engine#RunLinters(a:buffer, [], 1)
endif
return
endif
if a:delay > 0
- let s:queued_buffer_number = l:buffer
+ let s:queued_buffer_number = a:buffer
let s:lint_timer = timer_start(a:delay, function('ale#Lint'))
else
- call ale#Lint(-1, l:buffer)
+ call ale#Lint(-1, a:buffer)
endif
endfunction
@@ -92,22 +114,36 @@ function! ale#Lint(...) abort
let l:buffer = bufnr('')
endif
- if ale#ShouldDoNothing(l:buffer)
+ let l:now = ale#util#ClockMilliseconds()
+
+ if l:now < s:dont_lint_until
+ return
+ endif
+
+ let s:dont_lint_until = l:now + s:queue_error_delay_ms
+
+ call s:ALELintImpl(l:buffer)
+
+ let s:dont_lint_until = -1
+endfunction
+
+function! s:ALELintImpl(buffer) abort
+ if ale#ShouldDoNothing(a:buffer)
return
endif
" Use the filetype from the buffer
- let l:linters = ale#linter#Get(getbufvar(l:buffer, '&filetype'))
+ let l:linters = ale#linter#Get(getbufvar(a:buffer, '&filetype'))
let l:should_lint_file = 0
" Check if we previously requested checking the file.
- if has_key(s:should_lint_file_for_buffer, l:buffer)
- unlet s:should_lint_file_for_buffer[l:buffer]
+ if has_key(s:should_lint_file_for_buffer, a:buffer)
+ unlet s:should_lint_file_for_buffer[a:buffer]
" Lint files if they exist.
- let l:should_lint_file = filereadable(expand('#' . l:buffer . ':p'))
+ let l:should_lint_file = filereadable(expand('#' . a:buffer . ':p'))
endif
- call ale#engine#RunLinters(l:buffer, l:linters, l:should_lint_file)
+ call ale#engine#RunLinters(a:buffer, l:linters, l:should_lint_file)
endfunction
" Reset flags indicating that files should be checked for all buffers.
@@ -115,6 +151,11 @@ function! ale#ResetLintFileMarkers() abort
let s:should_lint_file_for_buffer = {}
endfunction
+function! ale#ResetErrorDelays() abort
+ let s:dont_queue_until = -1
+ let s:dont_lint_until = -1
+endfunction
+
let g:ale_has_override = get(g:, 'ale_has_override', {})
" Call has(), but check a global Dictionary so we can force flags on or off
diff --git a/doc/ale.txt b/doc/ale.txt
index 0550e4de..b0323f85 100644
--- a/doc/ale.txt
+++ b/doc/ale.txt
@@ -1180,6 +1180,12 @@ ale#Queue(delay, [linting_flag, buffer_number]) *ale#Queue()*
An optional `buffer_number` argument can be given for specifying the buffer
to check. The active buffer (`bufnr('')`) will be checked by default.
+ *ale-cool-down*
+ If an exception is thrown when queuing/running ALE linters, ALE will enter
+ a cool down period where it will stop checking anything for a short period
+ of time. This is to prevent ALE from seriously annoying users if a linter
+ is broken, or when developing ALE itself.
+
ale#engine#CreateDirectory(buffer) *ale#engine#CreateDirectory()*
diff --git a/test/test_lint_error_delay.vader b/test/test_lint_error_delay.vader
new file mode 100644
index 00000000..32d82715
--- /dev/null
+++ b/test/test_lint_error_delay.vader
@@ -0,0 +1,18 @@
+Before:
+ Save g:ale_filetype_blacklist
+
+ " Delete some variable which should be defined.
+ unlet! g:ale_filetype_blacklist
+
+After:
+ Restore
+
+ call ale#ResetErrorDelays()
+
+Execute(ALE should stop queuing for a while after exceptions are thrown):
+ AssertThrows call ale#Queue(100)
+ call ale#Queue(100)
+
+Execute(ALE should stop linting for a while after exceptions are thrown):
+ AssertThrows call ale#Lint()
+ call ale#Lint()