-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Syntax Checker Guide
So you wanna write a syntax checker? Read this page to find out how.
Checkers go in syntax_checkers/<filetype>/<checker_name>.vim
<checker_name>
can be essentially anything, but is usually named after the checker exe.
We will use a (slightly modified) version of the ruby/mri checker as an example:
if exists("g:loaded_syntastic_ruby_mri_checker")
finish
endif
let g:loaded_syntastic_ruby_mri_checker = 1
let s:save_cpo = &cpo
set cpo&vim
function! SyntaxCheckers_ruby_mri_IsAvailable() dict
return executable(self.getExec())
endfunction
function! SyntaxCheckers_ruby_mri_GetHighlightRegex(item)
if match(a:item['text'], 'assigned but unused variable') > -1
let term = split(a:item['text'], ' - ')[1]
return '\V\\<'.term.'\\>'
endif
return ''
endfunction
function! SyntaxCheckers_ruby_mri_GetLocList() dict
let makeprg = self.makeprgBuild({ 'args': '-w -T1 -c' })
"this is a hack to filter out a repeated useless warning in rspec files
"containing lines like
"
" foo.should == 'bar'
"
"Which always generate the warning below. Note that ruby >= 1.9.3 includes
"the word "possibly" in the warning
let errorformat = '%-G%.%#warning: %\(possibly %\)%\?useless use of == in void context,'
" filter out lines starting with ...
" long lines are truncated and wrapped in ... %p then returns the wrong
" column offset
let errorformat .= '%-G%\%.%\%.%\%.%.%#,'
let errorformat .= '%-GSyntax OK,' .
\ '%E%f:%l: syntax error\, %m,' .
\ '%Z%p^,' .
\ '%W%f:%l: warning: %m,' .
\ '%Z%p^,' .
\ '%W%f:%l: %m,' .
\ '%-C%.%#'
return SyntasticMake({ 'makeprg': makeprg, 'errorformat': errorformat })
endfunction
call g:SyntasticRegistry.CreateAndRegisterChecker({
\ 'filetype': 'ruby',
\ 'name': 'mri',
\ 'exec': 'ruby' })
let &cpo = s:save_cpo
unlet s:save_cpo
" vim: set et sts=4 sw=4:
Lets go over the parts of this file in detail.
This callback is used by the core to determine whether the checker is available. It should verify that the checker exe is installed and that any other environment dependencies are met. The checker exe's is defined below as the checker's exec
attribute, and is available here as self.getExec()
.
If the callback simply checks that the checker exe is present, the callback may be omitted (there is a default function that just returns executable(self.getExec())
).
This callback should perform the syntax check and return the results in the form of a quickfix list. See :help getqflist()
for details of the format.
The function usually follows the same format for all checkers:
- Build a
makeprg
(the program that performs the syntax check). - Build an
errorformat
string (the string that tells syntastic how to parse the output from the checker program. - Call
SyntasticMake()
with both of the above.
Notice how unexpected/strange parts of the errorformat string are documented on their own. This is good practice for maintenance reasons.
Syntastic can highlight the erroneous parts of lines, and this callback is used to determine what those parts are.
This callback is optional.
For example, in ruby, this is a common warning:
warning: assigned but unused variable - SomeVariable
The above example would return \V\<SomeVariable\>
which would cause occurrences of SomeVariable
to be highlighted on the line in question.
The parameter that gets passed in is an element from a quickfix list; see :help getqflist()
for the contents. The callback should return a regular expression pattern matching the current error. At runtime a \%l
is prepended to this pattern (see :help /\%l
), in order to localise the match to the relevant line.
Please note that, unlike the above callbacks, GetHighlightRegex()
is not a dictionary function.
Every checker needs to call this function to tell syntastic that it exists. The parameters that are passed in will determine the filetype the checker is used for, the names of the functions that syntastic looks for, and the name of the checker's exe.
The exec
attribute determines the checker's exe, and it can be omitted if it is the same as name
. The user can override its value by setting the variable g:syntastic_<filetype>_<name>_exec
.
In the above example, if we had passed in { 'filetype': 'java', 'name': 'foobar' }
then syntastic would use the checker for java files, the checker's exe would be foobar
, and syntastic would look for functions named SyntaxCheckers_java_foobar_GetLocList
etc.
Almost every checker calls this function to actually perform the check.
The function sets up the environment according to the options given, runs the checker, resets the environment, and returns the location list.
The argument a:options
can contain the following keys:
makeprg
errorformat
The corresponding options are set for the duration of the function call. They are set with :let, so don't escape spaces.
a:options
may also contain:
-
defaults
- a dict containing default values for the returned errors -
subtype
- all errors will be assigned the given subtype -
preprocess
- a function to be applied to the checker's output before being parsed by syntastic -
postprocess
- a list of functions to be applied to the parsed error list -
cwd
- change directory to the given path before running the checker -
returns
- a list of valid exit codes for the checker
The defaults
option is useful in situations where e.g. the error output doesn't contain a filename or a meaningful message. In this case you could pass in 'defaults': { 'bufnr': bufnr(''), 'text': 'Syntax error' }
. This would cause all items in the returned loclist to have the given bufnr
and text
values.
Pass in 'subtype': 'Style'
to cause all location list items to be marked as "Style" errors rather than syntax errors. This is useful for tools like PHP mess detector.
Currently, the postprocessing functions that can be specified are:
-
sort
- groups errors by file, then sorts them by line number, then type, and column number -
compressWhitespace
- replaces runs of whitespace in error text with single blanks -
cygwinRemoveCR
- removes carriage return characters from error text -
filterForeignErrors
- filters out the errors referencing other files.
Use this function to build a makeprg
. This function is preferable to manually building the makeprg string as it allows users to override parts of it as they like.
The argument a:options
can contain the following keys:
exe
args
filename
post_args
tail
The function returns a makeprg
of the form <exe> <args> <filename> <post_args> <tail>
.
All arguments are optional, and can be overridden by the user at runtime by setting global variables g:syntastic_<filetype>_<checker-name>_<option-name>
.
If omitted, exe
defaults to self.getExec()
(which is the checker's exe set by CreateAndRegisterChecker()
), and filename
is the name of the file being checked, properly escaped.