Skip to content
This repository was archived by the owner on Sep 20, 2023. It is now read-only.

Syntax Checker Guide

Doug Ireton edited this page May 8, 2013 · 66 revisions

So you wanna write a syntax checker? Read this page to find out how.

Checker directory structure

Checkers go in syntax_checkers/<filetype>/<checker_name>.vim

<checker_name> can be anything but is usually named after the checker exe.

Checker anatomy

We will use a (slightly simplified) 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

function! SyntaxCheckers_ruby_mri_IsAvailable()
    return executable("ruby")
endfunction

function! SyntaxCheckers_ruby_mri_GetHighlightRegex(i)
    if match(a:i['text'], 'assigned but unused variable') > -1
        let term = split(a:i['text'], ' - ')[1]
        return '\V\<'.term.'\>'
    endif

    return ''
endfunction

function! SyntaxCheckers_ruby_mri_GetLocList()
    let makeprg = syntastic#makeprg#build({
                \ 'exe': "ruby",
                \ 'args': '-w -T1 -c',
                \ 'subchecker': 'mri' })

    "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'})

Lets go over the parts of this file in detail.

IsAvailable() callback

This callback is used by the core to determine whether the checker can be used. It should check that the checker exe is installed and that any other environment dependencies are met.

In the above example, we simply check that the ruby executable is present.

GetLocList() callback

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.

GetHighlightRegex() callback

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 param that gets passed in is an element from a quickfix list. See :help getqflist() for the contents.

Call to g:SyntasticRegistry.CreateAndRegisterChecker()

Every checker needs to call this function to tell syntastic that it exists. The params that are passed in will determine the filetype the checker is used for, and the names of the functions that syntastic looks for.

In the above example, if we had passed in { 'filetype': 'java', 'name': 'foobar' } then syntastic would use the checker for java files, and would look for functions named SyntaxCheckers_java_foobar_IsAvailable etc.

Helper functions

SyntasticMake

Almost every checker calls this function to actually perform the check. The header comments for the code:

A wrapper for the :lmake command. Sets up the make environment according to
the options given, runs make, resets the environment, returns the location
list

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 dont 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

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.

syntastic#makeprg#build

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. See the comments here for parameter details.

Clone this wiki locally