Detailed debugging.

New variables: g:syntastic_debug_file, the name of a file where to write
debugging messages, in addition to adding them to the message history.

The old g:syntastic_debug is now a sum of flags:

*  1 - trace checker calls
*  2 - dump loclists
*  4 - trace notifiers
*  8 - trace autocommands
* 16 - dump syntastic variables (not implemented yet)
This commit is contained in:
LCD 47 2013-11-13 10:58:33 +02:00
parent bdc4b0f177
commit bbd382ba5d
11 changed files with 145 additions and 21 deletions

View File

@ -225,9 +225,60 @@ function! syntastic#util#redrawHandler()
endif
endfunction
function! syntastic#util#debug(msg)
if g:syntastic_debug
echomsg "syntastic: debug: " . a:msg
function! syntastic#util#debug(level, msg, ...)
" poor man's bit test for bit N, assuming a:level == 2**N
if (g:syntastic_debug / a:level) % 2
if has('reltime')
let leader = 'syntastic: ' . split(reltimestr(reltime(g:syntastic_start)))[0] . ': '
else
let leader = 'syntastic: debug: '
endif
if exists("g:syntastic_debug_file")
try
execute 'redir >> ' . fnameescape(expand(g:syntastic_debug_file))
catch /^Vim\%((\a\+)\)\=:/
unlet g:syntastic_debug_file
silent! redir END
endtry
endif
if a:0 > 0
" filter out dictionary functions
echomsg leader . a:msg .
\ strtrans(string(type(a:1) == type({}) || type(a:1) == type([]) ?
\ filter(copy(a:1), 'type(v:val) != type(function("tr"))') : a:1))
else
echomsg leader . a:msg
endif
if exists("g:syntastic_debug_file")
silent! redir END
endif
endif
endfunction
function! syntastic#util#showVariables(level, names)
let vlist = type(a:names) == type("") ? [a:names] : a:names
for name in vlist
let vals = []
if exists('g:' . name)
call add(vals, 'g:' . name . ' = ' . strtrans(string(g:{name})))
endif
if exists('b:' . name)
call add(vals, 'b:' . name . ' = ' . strtrans(string(b:{name})))
endif
if !empty(vals)
call syntastic#util#debug(a:level, join(vals, ', '))
endif
endfor
endfunction
function! syntastic#util#showOptions(level, names)
let vlist = type(a:names) == type("") ? [a:names] : a:names
if !empty(vlist)
call map(vlist, "'&' . v:val . ' = ' . strtrans(string(eval('&' . v:val)))")
call syntastic#util#debug(a:level, join(vlist, ', '))
endif
endfunction

View File

@ -398,12 +398,26 @@ if you actually need it.
*'syntastic_debug'*
Default: 0
Set this to 1 to enable debugging: >
Set this to the sum of one or more of the following flags to enable
debugging:
1 - trace checker calls
2 - dump loclists
4 - trace notifiers
8 - trace autocommands
Example: >
let g:syntastic_debug = 1
<
Checkers will then add debugging messages to Vim's |message-history|. You can
Syntastic will then add debugging messages to Vim's |message-history|. You can
examine these messages with |:mes|.
*'syntastic_debug_file'*
Default: unset
When set, debugging messages are written to the file named by its value, in
addition to being added to Vim's |message-history|: >
let g:syntastic_debug_file = '~/syntastic.log'
<
==============================================================================
5. Checker Options *syntastic-checker-options*

View File

@ -15,6 +15,10 @@ if exists("g:loaded_syntastic_plugin")
endif
let g:loaded_syntastic_plugin = 1
if has('reltime')
let g:syntastic_start = reltime()
endif
runtime! plugin/syntastic/*.vim
let s:running_windows = has("win16") || has("win32")
@ -89,6 +93,13 @@ if !exists("g:syntastic_reuse_loc_lists")
let g:syntastic_reuse_loc_lists = (v:version >= 704)
endif
" debug constants
let g:SyntasticDebugTrace = 1
let g:SyntasticDebugLoclist = 2
let g:SyntasticDebugNotifications = 4
let g:SyntasticDebugAutocommands = 8
let g:SyntasticDebugVariables = 16
let s:registry = g:SyntasticRegistry.Instance()
let s:notifiers = g:SyntasticNotifiers.Instance()
let s:modemap = g:SyntasticModeMap.Instance()
@ -119,12 +130,12 @@ highlight link SyntasticError SpellBad
highlight link SyntasticWarning SpellCap
augroup syntastic
autocmd BufReadPost * if g:syntastic_check_on_open | call s:UpdateErrors(1) | endif
autocmd BufWritePost * call s:UpdateErrors(1)
autocmd BufReadPost * call s:BufReadPostHook()
autocmd BufWritePost * call s:BufWritePostHook()
autocmd BufWinEnter * call s:BufWinEnterHook()
" TODO: the next autocmd should be "autocmd BufWinLeave * if empty(&bt) | lclose | endif"
" TODO: the next autocmd should be "autocmd BufWinLeave * if empty(&buftype) | lclose | endif"
" but in recent versions of Vim lclose can no longer be called from BufWinLeave
autocmd BufEnter * call s:BufEnterHook()
augroup END
@ -137,23 +148,45 @@ if v:version > 703 || (v:version == 703 && has('patch544'))
endif
function! s:BufReadPostHook()
if g:syntastic_check_on_open
call syntastic#util#debug(g:SyntasticDebugAutocommands,
\ 'autocmd: BufReadPost, buffer ' . bufnr("") . ' = ' . string(bufname(str2nr(bufnr("")))))
call s:UpdateErrors(1)
endif
endfunction
function! s:BufWritePostHook()
call syntastic#util#debug(g:SyntasticDebugAutocommands,
\ 'autocmd: BufWritePost, buffer ' . bufnr("") . ' = ' . string(bufname(str2nr(bufnr("")))))
call s:UpdateErrors(1)
endfunction
function! s:BufWinEnterHook()
if empty(&bt)
call syntastic#util#debug(g:SyntasticDebugAutocommands,
\ 'autocmd: BufWinEnter, buffer ' . bufnr("") . ' = ' . string(bufname(str2nr(bufnr("")))) .
\ ', &buftype = ' . string(&buftype))
if empty(&buftype)
let loclist = g:SyntasticLoclist.current()
call s:notifiers.refresh(loclist)
endif
endfunction
function! s:BufEnterHook()
call syntastic#util#debug(g:SyntasticDebugAutocommands,
\ 'autocmd: BufEnter, buffer ' . bufnr("") . ' = ' . string(bufname(str2nr(bufnr("")))) .
\ ', &buftype = ' . string(&buftype))
" TODO: at this point there is no b:syntastic_loclist
let loclist = filter(getloclist(0), 'v:val["valid"] == 1')
let buffers = syntastic#util#unique(map( loclist, 'v:val["bufnr"]' ))
if &bt=='quickfix' && !empty(loclist) && empty(filter( buffers, 'syntastic#util#bufIsActive(v:val)' ))
if &buftype == 'quickfix' && !empty(loclist) && empty(filter( buffers, 'syntastic#util#bufIsActive(v:val)' ))
call g:SyntasticLoclistHide()
endif
endfunction
function! s:QuitPreHook()
call syntastic#util#debug(g:SyntasticDebugAutocommands,
\ 'autocmd: QuitPre, buffer ' . bufnr("") . ' = ' . string(bufname(str2nr(bufnr("")))))
let b:syntastic_skip_checks = !g:syntastic_check_on_wq
call g:SyntasticLoclistHide()
endfunction
@ -207,10 +240,9 @@ function! s:CacheErrors(...)
let active_checkers = 0
let names = []
call syntastic#util#debug("CacheErrors: g:syntastic_aggregate_errors = " . g:syntastic_aggregate_errors)
if exists('b:syntastic_aggregate_errors')
call syntastic#util#debug("CacheErrors: b:syntastic_aggregate_errors = " . b:syntastic_aggregate_errors)
endif
call syntastic#util#showOptions(g:SyntasticDebugTrace,
\ ['shell', 'shellcmdflag', 'shellxquote', 'shellredir', 'shellslash'])
call syntastic#util#showVariables(g:SyntasticDebugTrace, 'syntastic_aggregate_errors')
let aggregate_errors =
\ exists('b:syntastic_aggregate_errors') ? b:syntastic_aggregate_errors : g:syntastic_aggregate_errors
@ -227,7 +259,7 @@ function! s:CacheErrors(...)
for checker in checkers
let active_checkers += 1
call syntastic#util#debug("CacheErrors: Invoking checker: " . checker.getName())
call syntastic#util#debug(g:SyntasticDebugTrace, "CacheErrors: Invoking checker: " . checker.getName())
let loclist = checker.getLocList()
@ -262,9 +294,11 @@ function! s:CacheErrors(...)
if a:0
call syntastic#util#warn('checker ' . a:1 . ' is not active for filetype ' . &filetype)
else
call syntastic#util#debug('no active checkers for filetype ' . &filetype)
call syntastic#util#debug(g:SyntasticDebugTrace, 'CacheErrors: no active checkers for filetype ' . &filetype)
endif
endif
call syntastic#util#debug(g:SyntasticDebugLoclist, "aggregated:", newLoclist)
endif
let b:syntastic_loclist = newLoclist
@ -382,7 +416,7 @@ endfunction
" 'cwd' - change directory to the given path before running the checker
" 'returns' - a list of valid exit codes for the checker
function! SyntasticMake(options)
call syntastic#util#debug('SyntasticMake: called with options: '. string(a:options))
call syntastic#util#debug(g:SyntasticDebugTrace, 'SyntasticMake: called with options:', a:options)
let old_shell = &shell
let old_shellredir = &shellredir
@ -413,8 +447,11 @@ function! SyntasticMake(options)
let $LC_ALL = old_lc_all
let $LC_MESSAGES = old_lc_messages
call syntastic#util#debug(g:SyntasticDebugLoclist, "checker output:", err_lines)
if has_key(a:options, 'preprocess')
let err_lines = call(a:options['preprocess'], [err_lines])
call syntastic#util#debug(g:SyntasticDebugLoclist, "preprocess:", err_lines)
endif
lgetexpr err_lines
@ -434,6 +471,8 @@ function! SyntasticMake(options)
call syntastic#util#redraw(g:syntastic_full_redraws)
endif
call syntastic#util#debug(g:SyntasticDebugLoclist, "raw loclist:", errors)
if has_key(a:options, 'returns') && index(a:options['returns'], v:shell_error) == -1
throw 'Syntastic: checker error'
endif
@ -443,11 +482,16 @@ function! SyntasticMake(options)
endif
" Apply ignore patterns
let ignore = {}
let ignored = {}
let do_ignore = 0
for buf in syntastic#util#unique(map(copy(errors), 'v:val["bufnr"]'))
let ignore[buf] = s:IgnoreFile(bufname(str2nr(buf)))
let ignored[buf] = s:IgnoreFile(bufname(str2nr(buf)))
let do_ignore = do_ignore || ignored[buf]
endfor
call filter(errors, '!ignore[v:val["bufnr"]]')
if do_ignore
call filter(errors, '!ignored[v:val["bufnr"]]')
call syntastic#util#debug(g:SyntasticDebugLoclist, "filtered loclist:", errors)
endif
" Add subtype info if present.
if has_key(a:options, 'subtype')
@ -458,6 +502,7 @@ function! SyntasticMake(options)
for rule in a:options['postprocess']
let errors = call('syntastic#postprocess#' . rule, [errors])
endfor
call syntastic#util#debug(g:SyntasticDebugLoclist, "postprocess:", errors)
endif
return errors

View File

@ -17,10 +17,12 @@ function! g:SyntasticAutoloclistNotifier.New()
endfunction
function! g:SyntasticAutoloclistNotifier.refresh(loclist)
call syntastic#util#debug(g:SyntasticDebugNotifications, 'autoloclist: refresh')
call g:SyntasticAutoloclistNotifier.AutoToggle(a:loclist)
endfunction
function! g:SyntasticAutoloclistNotifier.AutoToggle(loclist)
call syntastic#util#debug(g:SyntasticDebugNotifications, 'autoloclist: toggle')
if a:loclist.hasErrorsOrWarningsToDisplay()
if g:syntastic_auto_loc_list == 1
call a:loclist.show()

View File

@ -30,6 +30,7 @@ endfunction
function! g:SyntasticBalloonsNotifier.refresh(loclist)
let b:syntastic_balloons = {}
if self.enabled() && a:loclist.hasErrorsOrWarningsToDisplay()
call syntastic#util#debug(g:SyntasticDebugNotifications, 'balloons: refresh')
let buf = bufnr('')
let issues = filter(a:loclist.filteredRaw(), 'v:val["bufnr"] == buf')
if !empty(issues)
@ -48,6 +49,7 @@ endfunction
" Reset the error balloons
function! g:SyntasticBalloonsNotifier.reset(loclist)
if has('balloon_eval')
call syntastic#util#debug(g:SyntasticDebugNotifications, 'balloons: reset')
set nobeval
endif
endfunction

View File

@ -58,7 +58,8 @@ endfunction
function! g:SyntasticChecker.getLocList()
try
let list = self._locListFunc()
call syntastic#util#debug('getLocList: checker ' . self._filetype . '/' . self._name . ' returned ' . v:shell_error)
call syntastic#util#debug(g:SyntasticDebugTrace,
\ 'getLocList: checker ' . self._filetype . '/' . self._name . ' returned ' . v:shell_error)
catch /\m\C^Syntastic: checker error$/
let list = []
call syntastic#util#error('checker ' . self._filetype . '/' . self._name . ' returned abnormal status ' . v:shell_error)

View File

@ -22,6 +22,7 @@ endfunction
function! g:SyntasticCursorNotifier.refresh(loclist)
if self.enabled() && a:loclist.hasErrorsOrWarningsToDisplay()
call syntastic#util#debug(g:SyntasticDebugNotifications, 'cursor: refresh')
let b:syntastic_messages = copy(a:loclist.messages(bufnr('')))
let b:oldLine = -1
autocmd! syntastic CursorMoved
@ -30,6 +31,7 @@ function! g:SyntasticCursorNotifier.refresh(loclist)
endfunction
function! g:SyntasticCursorNotifier.reset(loclist)
call syntastic#util#debug(g:SyntasticDebugNotifications, 'cursor: reset')
autocmd! syntastic CursorMoved
unlet! b:syntastic_messages
let b:oldLine = -1

View File

@ -29,6 +29,7 @@ endfunction
function! g:SyntasticHighlightingNotifier.refresh(loclist)
if self.enabled()
call self.reset(a:loclist)
call syntastic#util#debug(g:SyntasticDebugNotifications, 'highlighting: refresh')
let buf = bufnr('')
let issues = filter(a:loclist.filteredRaw(), 'v:val["bufnr"] == buf')
for item in issues
@ -55,6 +56,7 @@ endfunction
" Remove all error highlights from the window
function! g:SyntasticHighlightingNotifier.reset(loclist)
if s:has_highlighting
call syntastic#util#debug(g:SyntasticDebugNotifications, 'highlighting: reset')
for match in getmatches()
if stridx(match['group'], 'Syntastic') == 0
call matchdelete(match['id'])

View File

@ -149,6 +149,7 @@ endfunction
"display the cached errors for this buf in the location list
function! g:SyntasticLoclist.show()
call syntastic#util#debug(g:SyntasticDebugNotifications, 'loclist: show')
if !exists('w:syntastic_loclist_set')
let w:syntastic_loclist_set = 0
endif
@ -184,6 +185,7 @@ endfunction
" Non-method functions {{{1
function! g:SyntasticLoclistHide()
call syntastic#util#debug(g:SyntasticDebugNotifications, 'loclist: hide')
silent! lclose
endfunction

View File

@ -19,6 +19,7 @@ function! g:SyntasticNotifiers.Instance()
endfunction
function! g:SyntasticNotifiers.refresh(loclist)
call syntastic#util#debug(g:SyntasticDebugNotifications, 'notifiers: refresh')
for type in self._enabled_types
let class = substitute(type, '\m.*', 'Syntastic\u&Notifier', '')
if !has_key(g:{class}, 'enabled') || self._notifier[type].enabled()
@ -28,6 +29,7 @@ function! g:SyntasticNotifiers.refresh(loclist)
endfunction
function! g:SyntasticNotifiers.reset(loclist)
call syntastic#util#debug(g:SyntasticDebugNotifications, 'notifiers: reset')
for type in self._enabled_types
let class = substitute(type, '\m.*', 'Syntastic\u&Notifier', '')

View File

@ -54,6 +54,7 @@ function! g:SyntasticSignsNotifier.enabled()
endfunction
function! g:SyntasticSignsNotifier.refresh(loclist)
call syntastic#util#debug(g:SyntasticDebugNotifications, 'signs: refresh')
let old_signs = copy(self._bufSignIds())
if self.enabled()
call self._signErrors(a:loclist)