" Vim syntax file
" Language: Vala
" Maintainers: Emmanuele Bassi <ebassi@gnome.org>
"              Hans Vercammen <hveso3@gmail.com>
"              pancake <pancake@nopcode.org>
" Filenames: *.vala *.vapi
"
" REFERENCES:
" [1] http://live.gnome.org/Vala
"
" TODO: Possibly when reaching vala 1.0 release
"         - validate code attributes
"         - better error checking for known errors
"         - full support for valadoc

if exists("b:current_syntax")
    finish
endif

let s:vala_cpo_save = &cpo
set cpo&vim

" Types
syn keyword valaType                 bool char double float size_t ssize_t string unichar void
syn keyword valaType                 int int8 int16 int32 int64 long short
syn keyword valaType                 uint uint8 uint16 uint32 uint64 ulong ushort
" Storage keyword
syn keyword valaStorage              class delegate enum errordomain interface namespace struct
" repeat / condition / label
syn keyword valaRepeat               break continue do for foreach return while
syn keyword valaConditional          else if switch assert
" User Labels
syn keyword valaLabel                case default

" Modifiers
syn keyword valaModifier             abstract const dynamic ensures extern inline internal override 
syn keyword valaModifier             private protected public requires signal static virtual volatile weak
syn keyword valaModifier             async owned unowned
" Constants
syn keyword valaConstant             false null true
" Exceptions
syn keyword valaException	     try catch finally throw
" Unspecified Statements
syn keyword valaUnspecifiedStatement as base construct delete get in is lock new out params ref sizeof set this throws typeof using value var yield

" Comments
syn cluster valaCommentGroup contains=valaTodo
syn keyword valaTodo contained TODO FIXME XXX NOTE

" valadoc Comments (ported from javadoc comments in java.vim)
" TODO: need to verify valadoc syntax
if !exists("vala_ignore_valadoc")
  syn cluster valaDocCommentGroup contains=valaDocTags,valaDocSeeTag
  syn region valaDocTags          contained start="{@\(link\|linkplain\|inherit[Dd]oc\|doc[rR]oot\|value\)" end="}"
  syn match valaDocTags           contained "@\(param\|exception\|throws\|since\)\s\+\S\+" contains=valaDocParam
  syn match valaDocParam          contained "\s\S\+"
  syn match valaDocTags           contained "@\(author\|brief\|version\|return\|deprecated\)\>"
  syn region valaDocSeeTag        contained matchgroup=valaDocTags start="@see\s\+" matchgroup=NONE end="\_."re=e-1 contains=valaDocSeeTagParam
  syn match valaDocSeeTagParam    contained @"\_[^"]\+"\|<a\s\+\_.\{-}</a>\|\(\k\|\.\)*\(#\k\+\((\_[^)]\+)\)\=\)\=@ extend
endif

" Comment Strings (ported from c.vim)
if exists("vala_comment_strings")
  syn match valaCommentSkip          contained "^\s*\*\($\|\s\+\)"
  syn region valaCommentString       contained start=+L\=\\\@<!"+ skip=+\\\\\|\\"+ end=+"+ end=+\*/+me=s-1 contains=valaSpecialChar,valaCommentSkip
  syn region valaComment2String      contained start=+L\=\\\@<!"+ skip=+\\\\\|\\"+ end=+"+ end="$" contains=valaSpecialChar
  syn cluster valaCommentStringGroup contains=valaCommentString,valaCharacter,valaNumber

  syn region valaCommentL            start="//" end="$" keepend contains=@valaCommentGroup,valaComment2String,valaCharacter,valaNumber,valaSpaceError,@Spell
  syn region valaComment             matchgroup=valaCommentStart start="/\*" end="\*/" contains=@valaCommentGroup,@valaCommentStringGroup,valaCommentStartError,valaSpaceError,@Spell extend
  if !exists("vala_ignore_valadoc")
    syn region valaDocComment        matchgroup=valaCommentStart start="/\*\*" end="\*/" keepend contains=@valaCommentGroup,@valaDocCommentGroup,@valaCommentStringGroup,valaCommentStartError,valaSpaceError,@Spell
  endif
else
  syn region valaCommentL start="//" end="$" keepend contains=@valaCommentGroup,valaSpaceError,@Spell
  syn region valaComment matchgroup=valaCommentStart start="/\*" end="\*/" contains=@valaCommentGroup,valaCommentStartError,valaSpaceError,@Spell
  if !exists("vala_ignore_valadoc")
    syn region valaDocComment 		matchgroup=valaCommentStart start="/\*\*" end="\*/" keepend contains=@valaCommentGroup,@valaDocCommentGroup,valaCommentStartError,valaSpaceError,@Spell
  endif
endif
" match comment errors
syntax match valaCommentError display "\*/"
syntax match valaCommentStartError display "/\*"me=e-1 contained
" match the special comment /**/
syn match valaComment "/\*\*/"

" Vala Code Attributes
syn region valaAttribute start="^\s*\[" end="\]$" contains=valaComment,valaString keepend
syn region valaAttribute start="\[CCode" end="\]" contains=valaComment,valaString

" Avoid escaped keyword matching
syn match valaUserContent display "@\I*"

" Strings and constants
syn match valaSpecialError     contained "\\."
syn match valaSpecialCharError contained "[^']"
syn match valaSpecialChar      contained +\\["\\'0abfnrtvx]+
syn region valaString          start=+"+ end=+"+ end=+$+ contains=valaSpecialChar,valaSpecialError,valaUnicodeNumber,@Spell
syn region valaVerbatimString  start=+"""+ end=+"""+ contains=@Spell
syn match valaUnicodeNumber    +\\\(u\x\{4}\|U\x\{8}\)+ contained contains=valaUnicodeSpecifier
syn match valaUnicodeSpecifier +\\[uU]+ contained
syn match valaCharacter        "'[^']*'" contains=valaSpecialChar,valaSpecialCharError
syn match valaCharacter        "'\\''" contains=valaSpecialChar
syn match valaCharacter        "'[^\\]'"
syn match valaNumber           display "\<\(0[0-7]*\|0[xX]\x\+\|\d\+\)[lL]\=\>"
syn match valaNumber           display "\(\<\d\+\.\d*\|\.\d\+\)\([eE][-+]\=\d\+\)\=[fFdD]\="
syn match valaNumber           display "\<\d\+[eE][-+]\=\d\+[fFdD]\=\>"
syn match valaNumber           display "\<\d\+\([eE][-+]\=\d\+\)\=[fFdD]\>"

" when wanted, highlight trailing white space
if exists("vala_space_errors")
  if !exists("vala_no_trail_space_error")
    syn match valaSpaceError display excludenl "\s\+$"
  endif
  if !exists("vala_no_tab_space_error")
    syn match valaSpaceError display " \+\t"me=e-1
  endif
endif

" when wanted, set minimum lines for comment syntax syncing
if exists("vala_minlines")
  let b:vala_minlines = vala_minlines
else
  let b:vala_minlines = 50
endif
exec "syn sync ccomment valaComment minlines=" . b:vala_minlines

" The default highlighting.
hi def link valaType                 Type
hi def link valaStorage              StorageClass
hi def link valaRepeat               Repeat
hi def link valaConditional          Conditional
hi def link valaLabel                Label
hi def link valaModifier             StorageClass
hi def link valaConstant             Constant
hi def link valaException            Exception
hi def link valaUnspecifiedStatement Statement
hi def link valaUnspecifiedKeyword   Keyword
hi def link valaContextualStatement  Statement

hi def link valaCommentError      Error
hi def link valaCommentStartError Error
hi def link valaSpecialError      Error
hi def link valaSpecialCharError  Error
hi def link valaSpaceError        Error

hi def link valaTodo           Todo
hi def link valaCommentL       valaComment
hi def link valaCommentStart   valaComment
hi def link valaCommentSkip    valaComment
hi def link valaComment        Comment
hi def link valaDocComment     Comment
hi def link valaDocTags        Special
hi def link valaDocParam       Function
hi def link valaDocSeeTagParam Function
hi def link valaAttribute      PreCondit

hi def link valaCommentString    valaString
hi def link valaComment2String   valaString
hi def link valaString           String
hi def link valaVerbatimString   String
hi def link valaCharacter        Character
hi def link valaSpecialChar      SpecialChar
hi def link valaNumber           Number
hi def link valaUnicodeNumber    SpecialChar
hi def link valaUnicodeSpecifier SpecialChar

let b:current_syntax = "vala"

let &cpo = s:vala_cpo_save
unlet s:vala_cpo_save
