PageRenderTime 60ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/vim/bundle/syntastic-3.8.0/plugin/syntastic/registry.vim

https://bitbucket.org/darrenlucas/dotfiles
Vim Script | 439 lines | 352 code | 60 blank | 27 comment | 46 complexity | c6a44bddd5a77f514f4aa22e6459bca7 MD5 | raw file
  1. if exists('g:loaded_syntastic_registry') || !exists('g:loaded_syntastic_plugin')
  2. finish
  3. endif
  4. let g:loaded_syntastic_registry = 1
  5. " Initialisation {{{1
  6. let s:_DEFAULT_CHECKERS = {
  7. \ 'actionscript': ['mxmlc'],
  8. \ 'ada': ['gcc'],
  9. \ 'ansible': ['ansible_lint'],
  10. \ 'apiblueprint': ['drafter'],
  11. \ 'applescript': ['osacompile'],
  12. \ 'asciidoc': ['asciidoc'],
  13. \ 'asl': ['iasl'],
  14. \ 'asm': ['gcc'],
  15. \ 'bro': ['bro'],
  16. \ 'bemhtml': ['bemhtmllint'],
  17. \ 'c': ['gcc'],
  18. \ 'cabal': ['cabal'],
  19. \ 'chef': ['foodcritic'],
  20. \ 'co': ['coco'],
  21. \ 'cobol': ['cobc'],
  22. \ 'coffee': ['coffee', 'coffeelint'],
  23. \ 'coq': ['coqtop'],
  24. \ 'cpp': ['gcc'],
  25. \ 'cs': ['mcs'],
  26. \ 'css': ['csslint'],
  27. \ 'cucumber': ['cucumber'],
  28. \ 'cuda': ['nvcc'],
  29. \ 'd': ['dmd'],
  30. \ 'dart': ['dartanalyzer'],
  31. \ 'docbk': ['xmllint'],
  32. \ 'dockerfile': ['dockerfile_lint'],
  33. \ 'dustjs': ['swiffer'],
  34. \ 'elixir': [],
  35. \ 'erlang': ['escript'],
  36. \ 'eruby': ['ruby'],
  37. \ 'fortran': ['gfortran'],
  38. \ 'glsl': ['cgc'],
  39. \ 'go': [],
  40. \ 'haml': ['haml'],
  41. \ 'handlebars': ['handlebars'],
  42. \ 'haskell': ['hdevtools', 'hlint'],
  43. \ 'haxe': ['haxe'],
  44. \ 'help': [],
  45. \ 'hss': ['hss'],
  46. \ 'html': ['tidy'],
  47. \ 'jade': ['jade_lint'],
  48. \ 'java': ['javac'],
  49. \ 'javascript': ['jshint', 'jslint'],
  50. \ 'json': ['jsonlint', 'jsonval'],
  51. \ 'less': ['lessc'],
  52. \ 'lex': ['flex'],
  53. \ 'limbo': ['limbo'],
  54. \ 'lisp': ['clisp'],
  55. \ 'llvm': ['llvm'],
  56. \ 'lua': ['luac'],
  57. \ 'markdown': ['mdl'],
  58. \ 'matlab': ['mlint'],
  59. \ 'mercury': ['mmc'],
  60. \ 'nasm': ['nasm'],
  61. \ 'nix': ['nix'],
  62. \ 'nroff': ['mandoc'],
  63. \ 'objc': ['gcc'],
  64. \ 'objcpp': ['gcc'],
  65. \ 'ocaml': ['camlp4o'],
  66. \ 'perl': ['perlcritic'],
  67. \ 'php': ['php', 'phpcs', 'phpmd'],
  68. \ 'po': ['msgfmt'],
  69. \ 'pod': ['podchecker'],
  70. \ 'puppet': ['puppet', 'puppetlint'],
  71. \ 'pug': ['pug_lint'],
  72. \ 'python': ['python', 'flake8', 'pylint'],
  73. \ 'qml': ['qmllint'],
  74. \ 'r': [],
  75. \ 'rmd': [],
  76. \ 'racket': ['racket'],
  77. \ 'rnc': ['rnv'],
  78. \ 'rst': ['rst2pseudoxml'],
  79. \ 'ruby': ['mri'],
  80. \ 'sass': ['sass'],
  81. \ 'scala': ['fsc', 'scalac'],
  82. \ 'scss': ['sass', 'scss_lint'],
  83. \ 'sh': ['sh', 'shellcheck'],
  84. \ 'slim': ['slimrb'],
  85. \ 'sml': ['smlnj'],
  86. \ 'spec': ['rpmlint'],
  87. \ 'solidity': ['solc'],
  88. \ 'sql': ['sqlint'],
  89. \ 'stylus': ['stylint'],
  90. \ 'tcl': ['nagelfar'],
  91. \ 'tex': ['lacheck', 'chktex'],
  92. \ 'texinfo': ['makeinfo'],
  93. \ 'text': [],
  94. \ 'trig': ['rapper'],
  95. \ 'turtle': ['rapper'],
  96. \ 'twig': ['twiglint'],
  97. \ 'typescript': [],
  98. \ 'vala': ['valac'],
  99. \ 'verilog': ['verilator'],
  100. \ 'vhdl': ['ghdl'],
  101. \ 'vim': ['vimlint'],
  102. \ 'xhtml': ['tidy'],
  103. \ 'xml': ['xmllint'],
  104. \ 'xslt': ['xmllint'],
  105. \ 'xquery': ['basex'],
  106. \ 'yacc': ['bison'],
  107. \ 'yaml': ['jsyaml'],
  108. \ 'yang': ['pyang'],
  109. \ 'z80': ['z80syntaxchecker'],
  110. \ 'zpt': ['zptlint'],
  111. \ 'zsh': ['zsh'],
  112. \ }
  113. lockvar! s:_DEFAULT_CHECKERS
  114. let s:_DEFAULT_FILETYPE_MAP = {
  115. \ 'gentoo-metadata': 'xml',
  116. \ 'groff': 'nroff',
  117. \ 'lhaskell': 'haskell',
  118. \ 'litcoffee': 'coffee',
  119. \ 'mail': 'text',
  120. \ 'mkd': 'markdown',
  121. \ 'pe-puppet': 'puppet',
  122. \ 'sgml': 'docbk',
  123. \ 'sgmllnx': 'docbk',
  124. \ }
  125. lockvar! s:_DEFAULT_FILETYPE_MAP
  126. let s:_ECLIM_TYPES = [
  127. \ 'c',
  128. \ 'cpp',
  129. \ 'html',
  130. \ 'java',
  131. \ 'php',
  132. \ 'python',
  133. \ 'ruby',
  134. \ ]
  135. lockvar! s:_ECLIM_TYPES
  136. let s:_YCM_TYPES = [
  137. \ 'c',
  138. \ 'cpp',
  139. \ 'objc',
  140. \ 'objcpp',
  141. \ ]
  142. lockvar! s:_YCM_TYPES
  143. let g:SyntasticRegistry = {}
  144. " }}}1
  145. " Public methods {{{1
  146. " Note: Handling of filetype aliases: all public methods take aliases as
  147. " parameters, all private methods take normalized filetypes. Public methods
  148. " are thus supposed to normalize filetypes before calling private methods.
  149. function! g:SyntasticRegistry.Instance() abort " {{{2
  150. if !exists('s:SyntasticRegistryInstance')
  151. let s:SyntasticRegistryInstance = copy(self)
  152. let s:SyntasticRegistryInstance._checkerMap = {}
  153. endif
  154. return s:SyntasticRegistryInstance
  155. endfunction " }}}2
  156. function! g:SyntasticRegistry.CreateAndRegisterChecker(args) abort " {{{2
  157. let registry = g:SyntasticRegistry.Instance()
  158. if has_key(a:args, 'redirect')
  159. let [ft, name] = split(a:args['redirect'], '/')
  160. call registry._loadCheckersFor(ft, 1)
  161. let clone = get(registry._checkerMap[ft], name, {})
  162. if empty(clone)
  163. throw 'Syntastic: Checker ' . a:args['redirect'] . ' redirects to unregistered checker ' . ft . '/' . name
  164. endif
  165. let checker = g:SyntasticChecker.New(a:args, clone)
  166. else
  167. let checker = g:SyntasticChecker.New(a:args)
  168. endif
  169. call registry._registerChecker(checker)
  170. endfunction " }}}2
  171. " Given a list of checker names hints_list, return a map name --> checker.
  172. " If hints_list is empty, user settings are are used instead. Checkers are
  173. " not checked for availability (that is, the corresponding IsAvailable() are
  174. " not run).
  175. function! g:SyntasticRegistry.getCheckers(ftalias, hints_list) abort " {{{2
  176. let ftlist = self.resolveFiletypes(a:ftalias)
  177. let names =
  178. \ !empty(a:hints_list) ? a:hints_list :
  179. \ exists('b:syntastic_checkers') ? b:syntastic_checkers : []
  180. let cnames = []
  181. if !empty(names)
  182. for name in names
  183. if name !~# '/'
  184. for ft in ftlist
  185. call add(cnames, ft . '/' . name)
  186. endfor
  187. else
  188. call add(cnames, name)
  189. endif
  190. endfor
  191. else
  192. for ft in ftlist
  193. call self._sanityCheck(ft)
  194. let defs =
  195. \ exists('g:syntastic_' . ft . '_checkers') ? g:syntastic_{ft}_checkers :
  196. \ get(s:_DEFAULT_CHECKERS, ft, [])
  197. call extend(cnames, map(copy(defs), 'stridx(v:val, "/") < 0 ? ft . "/" . v:val : v:val' ))
  198. endfor
  199. endif
  200. let cnames = syntastic#util#unique(cnames)
  201. for ft in syntastic#util#unique(map( copy(cnames), 'v:val[: stridx(v:val, "/")-1]' ))
  202. call self._loadCheckersFor(ft, 0)
  203. endfor
  204. return self._filterCheckersByName(cnames)
  205. endfunction " }}}2
  206. " Same as getCheckers(), but keep only the available checkers. This runs the
  207. " corresponding IsAvailable() functions for all checkers.
  208. function! g:SyntasticRegistry.getCheckersAvailable(ftalias, hints_list) abort " {{{2
  209. return filter(self.getCheckers(a:ftalias, a:hints_list), 'v:val.isAvailable()')
  210. endfunction " }}}2
  211. " Same as getCheckers(), but keep only the checkers that are available and
  212. " disabled. This runs the corresponding IsAvailable() functions for all checkers.
  213. function! g:SyntasticRegistry.getCheckersDisabled(ftalias, hints_list) abort " {{{2
  214. return filter(self.getCheckers(a:ftalias, a:hints_list), 'v:val.isDisabled() && v:val.isAvailable()')
  215. endfunction " }}}2
  216. function! g:SyntasticRegistry.getKnownFiletypes() abort " {{{2
  217. let types = keys(s:_DEFAULT_CHECKERS)
  218. call extend(types, keys(s:_DEFAULT_FILETYPE_MAP))
  219. if exists('g:syntastic_filetype_map')
  220. call extend(types, keys(g:syntastic_filetype_map))
  221. endif
  222. if exists('g:syntastic_extra_filetypes') && type(g:syntastic_extra_filetypes) == type([])
  223. call extend(types, g:syntastic_extra_filetypes)
  224. endif
  225. return syntastic#util#unique(types)
  226. endfunction " }}}2
  227. function! g:SyntasticRegistry.getNamesOfAvailableCheckers(ftalias) abort " {{{2
  228. let ft = s:_normalise_filetype(a:ftalias)
  229. call self._loadCheckersFor(ft, 0)
  230. return keys(filter( copy(self._checkerMap[ft]), 'v:val.isAvailable()' ))
  231. endfunction " }}}2
  232. function! g:SyntasticRegistry.resolveFiletypes(ftalias) abort " {{{2
  233. return map(split( get(g:syntastic_filetype_map, a:ftalias, a:ftalias), '\m\.' ), 's:_normalise_filetype(v:val)')
  234. endfunction " }}}2
  235. function! g:SyntasticRegistry.echoInfoFor(ftalias_list) abort " {{{2
  236. let ft_list = syntastic#util#unique(self.resolveFiletypes(empty(a:ftalias_list) ? &filetype : a:ftalias_list[0]))
  237. if len(ft_list) != 1
  238. let available = []
  239. let active = []
  240. let disabled = []
  241. for ft in ft_list
  242. call extend(available, map( self.getNamesOfAvailableCheckers(ft), 'ft . "/" . v:val' ))
  243. call extend(active, map( self.getCheckersAvailable(ft, []), 'ft . "/" . v:val.getName()' ))
  244. call extend(disabled, map( self.getCheckersDisabled(ft, []), 'ft . "/" . v:val.getName()' ))
  245. endfor
  246. else
  247. let ft = ft_list[0]
  248. let available = self.getNamesOfAvailableCheckers(ft)
  249. let active = map(self.getCheckersAvailable(ft, []), 'ft ==# v:val.getFiletype() ? v:val.getName() : v:val.getCName()')
  250. let disabled = map(self.getCheckersDisabled(ft, []), 'ft ==# v:val.getFiletype() ? v:val.getName() : v:val.getCName()')
  251. endif
  252. let cnt = len(available)
  253. let plural = cnt != 1 ? 's' : ''
  254. let cklist = cnt ? join(sort(available)) : '-'
  255. echomsg 'Available checker' . plural . ': ' . cklist
  256. let cnt = len(active)
  257. let plural = cnt != 1 ? 's' : ''
  258. let cklist = cnt ? join(active) : '-'
  259. echomsg 'Currently enabled checker' . plural . ': ' . cklist
  260. let cnt = len(disabled)
  261. let plural = cnt != 1 ? 's' : ''
  262. if len(disabled)
  263. let cklist = join(sort(disabled, 's:_compare_checker_names'))
  264. echomsg 'Checker' . plural . ' disabled for security reasons: ' . cklist
  265. endif
  266. " Eclim feels entitled to mess with syntastic's variables {{{3
  267. if exists(':EclimValidate') && get(g:, 'EclimFileTypeValidate', 1)
  268. let disabled = filter(copy(ft_list), 's:_disabled_by_eclim(v:val)')
  269. let cnt = len(disabled)
  270. if cnt
  271. let plural = cnt != 1 ? 's' : ''
  272. let cklist = join(disabled, ', ')
  273. echomsg 'Checkers for filetype' . plural . ' ' . cklist . ' possibly disabled by Eclim'
  274. endif
  275. endif
  276. " }}}3
  277. " So does YouCompleteMe {{{3
  278. if exists('g:loaded_youcompleteme') && get(g:, 'ycm_show_diagnostics_ui', get(g:, 'ycm_register_as_syntastic_checker', 1))
  279. let disabled = filter(copy(ft_list), 's:_disabled_by_ycm(v:val)')
  280. let cnt = len(disabled)
  281. if cnt
  282. let plural = cnt != 1 ? 's' : ''
  283. let cklist = join(disabled, ', ')
  284. echomsg 'Checkers for filetype' . plural . ' ' . cklist . ' possibly disabled by YouCompleteMe'
  285. endif
  286. endif
  287. " }}}3
  288. endfunction " }}}2
  289. " }}}1
  290. " Private methods {{{1
  291. function! g:SyntasticRegistry._registerChecker(checker) abort " {{{2
  292. let ft = a:checker.getFiletype()
  293. if !has_key(self._checkerMap, ft)
  294. let self._checkerMap[ft] = {}
  295. endif
  296. let name = a:checker.getName()
  297. if has_key(self._checkerMap[ft], name)
  298. throw 'Syntastic: Duplicate syntax checker name: ' . ft . '/' . name
  299. endif
  300. let self._checkerMap[ft][name] = a:checker
  301. endfunction " }}}2
  302. function! g:SyntasticRegistry._findChecker(cname) abort " {{{2
  303. let sep_idx = stridx(a:cname, '/')
  304. if sep_idx > 0
  305. let ft = a:cname[: sep_idx-1]
  306. let name = a:cname[sep_idx+1 :]
  307. else
  308. let ft = &filetype
  309. let name = a:cname
  310. endif
  311. return get(self._checkerMap[ft], name, {})
  312. endfunction "}}}2
  313. function! g:SyntasticRegistry._filterCheckersByName(cnames) abort " {{{2
  314. return filter( map(copy(a:cnames), 'self._findChecker(v:val)'), '!empty(v:val)' )
  315. endfunction " }}}2
  316. function! g:SyntasticRegistry._loadCheckersFor(filetype, force) abort " {{{2
  317. if !a:force && has_key(self._checkerMap, a:filetype)
  318. return
  319. endif
  320. execute 'runtime! syntax_checkers/' . a:filetype . '/*.vim'
  321. if !has_key(self._checkerMap, a:filetype)
  322. let self._checkerMap[a:filetype] = {}
  323. endif
  324. endfunction " }}}2
  325. " Check for obsolete variable g:syntastic_<filetype>_checker
  326. function! g:SyntasticRegistry._sanityCheck(filetype) abort " {{{2
  327. if exists('g:syntastic_' . a:filetype . '_checkers') &&
  328. \ type(g:syntastic_{a:filetype}_checkers) != type([])
  329. unlet! g:syntastic_{a:filetype}_checkers
  330. call syntastic#log#error('variable g:syntastic_' . a:filetype . '_checkers has to be a list of strings')
  331. endif
  332. if exists('g:syntastic_' . a:filetype . '_checker') &&
  333. \ !exists('g:syntastic_' . a:filetype . '_checkers') &&
  334. \ type(g:syntastic_{a:filetype}_checker) == type('')
  335. let g:syntastic_{a:filetype}_checkers = [g:syntastic_{a:filetype}_checker]
  336. call syntastic#log#oneTimeWarn('variable g:syntastic_' . a:filetype . '_checker is deprecated')
  337. endif
  338. endfunction " }}}2
  339. " }}}1
  340. " Utilities {{{1
  341. "resolve filetype aliases, and replace - with _ otherwise we cant name
  342. "syntax checker functions legally for filetypes like "gentoo-metadata"
  343. function! s:_normalise_filetype(ftalias) abort " {{{2
  344. let ft = get(s:_DEFAULT_FILETYPE_MAP, a:ftalias, a:ftalias)
  345. let ft = get(g:syntastic_filetype_map, ft, ft)
  346. let ft = substitute(ft, '\m-', '_', 'g')
  347. return ft
  348. endfunction " }}}2
  349. function! s:_disabled_by_eclim(filetype) abort " {{{2
  350. if index(s:_ECLIM_TYPES, a:filetype) >= 0
  351. let lang = toupper(a:filetype[0]) . a:filetype[1:]
  352. let ft = a:filetype !=# 'cpp' ? lang : 'C'
  353. return get(g:, 'Eclim' . lang . 'Validate', 1) && !get(g:, 'Eclim' . ft . 'SyntasticEnabled', 0)
  354. endif
  355. return 0
  356. endfunction " }}}2
  357. function! s:_disabled_by_ycm(filetype) abort " {{{2
  358. return index(s:_YCM_TYPES, a:filetype) >= 0
  359. endfunction " }}}2
  360. function! s:_compare_checker_names(a, b) abort " {{{2
  361. if a:a ==# a:b
  362. return 0
  363. endif
  364. if stridx(a:a, '/') < 0
  365. if stridx(a:b, '/') < 0
  366. return a:a < a:b ? -1 : 1
  367. else
  368. return -1
  369. endif
  370. else
  371. if stridx(a:b, '/') < 0
  372. return 1
  373. else
  374. return a:a < a:b ? -1 : 1
  375. endif
  376. endif
  377. endfunction " }}}2
  378. " }}}1
  379. " vim: set sw=4 sts=4 et fdm=marker: