├── .gitignore ├── .travis.yml ├── Makefile ├── README.rst ├── autoload └── syntastic_extras.vim ├── syntax_checkers ├── c │ ├── check.py │ └── check.vim ├── cfg │ ├── cfg.py │ └── cfg.vim ├── cpp │ ├── check.py │ ├── check.vim │ └── test.py ├── dosini │ └── dosini.vim ├── gitcommit │ ├── language_check.vim │ ├── proselint.vim │ └── proselint_wrapper.py ├── javascript │ ├── json_tool.py │ └── json_tool.vim ├── json │ ├── json_tool.py │ └── json_tool.vim ├── make │ └── gnumake.vim ├── python │ └── pyflakes_with_warnings.vim ├── svn │ └── language_check.vim └── yaml │ ├── check_yaml.py │ └── pyyaml.vim └── test ├── bad.cfg ├── bad.gitcommit ├── bad.ini ├── bad.json ├── bad.yaml ├── bad_with_subsections.cfg ├── compile_commands ├── bad.cpp ├── build │ └── compile_commands.json ├── good.cpp └── header_directory │ └── some_header.h ├── good.cfg ├── good.gitcommit ├── good.json ├── good.yaml ├── good_with_subsections.cfg ├── syntastic_config ├── .syntastic_c_config ├── .syntastic_cpp_config ├── bad.c ├── bad.cpp ├── bad_header.c ├── bad_header.h ├── foo │ └── bar.h ├── good.c ├── good.cpp ├── good_header.cpp └── good_header.h └── test.bash /.gitignore: -------------------------------------------------------------------------------- 1 | .*.swp 2 | *.pyc 3 | __pycache__/ 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | 3 | language: python 4 | 5 | env: 6 | - 7 | - INSTALL_CONFIGOBJ=x 8 | 9 | install: 10 | - pip install proselint pyyaml 11 | - if [ -v INSTALL_CONFIGOBJ ]; then pip install configobj; fi 12 | 13 | python: 14 | - "2.7" 15 | - "3.6" 16 | - "3.7" 17 | - "3.8" 18 | 19 | script: 20 | - ./test/test.bash 21 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | default: test 2 | 3 | test: 4 | PYTHON=python2.4 ./test/test.bash 5 | PYTHON=python3.6 ./test/test.bash 6 | 7 | .PHONY: test 8 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | ================ 2 | syntastic-extras 3 | ================ 4 | 5 | .. image:: https://travis-ci.org/myint/syntastic-extras.svg?branch=master 6 | :target: https://travis-ci.org/myint/syntastic-extras 7 | :alt: Build status 8 | 9 | Additional syntax checkers for the Vim plugin Syntastic_. 10 | 11 | .. _Syntastic: https://github.com/scrooloose/syntastic 12 | 13 | Checkers 14 | ======== 15 | 16 | - C: 17 | 18 | .. code-block:: vim 19 | 20 | " Like Syntastic's normal checker, but only checks files if there is a 21 | " `.syntastic_c_config` file existing in the directory or an ancestor 22 | " directory. It ignores warnings in included files by using `-isystem` 23 | " instead of `-I`. It also supports `compile_commands.json` files generated 24 | " by CMake. `compile_commands.json` is used if the Syntastic configuration 25 | " file is not found. `compile_commands.json` is found using an ancestor 26 | " search for `build/compile_commands.json`. 27 | let g:syntastic_c_checkers = ['check'] 28 | 29 | - C++: 30 | 31 | .. code-block:: vim 32 | 33 | " See above, but replace '.syntastic_c_config' with 34 | " `.syntastic_cpp_config`. 35 | let g:syntastic_cpp_checkers = ['check'] 36 | 37 | - ``cfg``/``dosini``: 38 | 39 | .. code-block:: vim 40 | 41 | let g:syntastic_cfg_checkers = ['cfg'] 42 | let g:syntastic_dosini_checkers = ['dosini'] 43 | 44 | - GNU Make: 45 | 46 | .. code-block:: vim 47 | 48 | let g:syntastic_make_checkers = ['gnumake'] 49 | 50 | - JSON 51 | 52 | .. code-block:: vim 53 | 54 | let g:syntastic_json_checkers = ['json_tool'] 55 | 56 | - Language check in ``gitcommit``/``svn`` (commit prompts): 57 | 58 | .. code-block:: vim 59 | 60 | let g:syntastic_gitcommit_checkers = ['language_check'] 61 | let g:syntastic_svn_checkers = ['language_check'] 62 | 63 | - ``proselint`` in ``gitcommit`` (commit prompts): 64 | 65 | .. code-block:: vim 66 | 67 | let g:syntastic_gitcommit_checkers = ['proselint'] 68 | 69 | - Python: 70 | 71 | .. code-block:: vim 72 | 73 | " Like Syntastic's pyflakes checker, but treats messages about unused 74 | " variables/imports as warnings rather than errors. 75 | let g:syntastic_python_checkers = ['pyflakes_with_warnings'] 76 | 77 | - YAML: 78 | 79 | .. code-block:: vim 80 | 81 | let g:syntastic_yaml_checkers = ['pyyaml'] 82 | 83 | Hooks 84 | ===== 85 | 86 | - Block ``ZZ`` if there are syntax errors: 87 | 88 | .. code-block:: vim 89 | 90 | nnoremap ZZ :call syntastic_extras#quit_hook() 91 | -------------------------------------------------------------------------------- /autoload/syntastic_extras.vim: -------------------------------------------------------------------------------- 1 | " For disabling ZZ if there are syntax errors. 2 | function! syntastic_extras#quit_hook() 3 | if &modified 4 | write 5 | endif 6 | 7 | echo 'Running Syntastic check' 8 | SyntasticCheck 9 | if !exists('b:syntastic_loclist') || 10 | \ empty(b:syntastic_loclist) || 11 | \ b:syntastic_loclist.isEmpty() 12 | quit 13 | else 14 | Errors 15 | endif 16 | endfun 17 | -------------------------------------------------------------------------------- /syntax_checkers/c/check.py: -------------------------------------------------------------------------------- 1 | ../cpp/check.py -------------------------------------------------------------------------------- /syntax_checkers/c/check.vim: -------------------------------------------------------------------------------- 1 | " Like Syntastic's normal checker, but only checks files if there is a 2 | " '.syntastic_c_config' file existing in the directory or an ancestor 3 | " directory. 4 | 5 | if exists('g:loaded_syntastic_c_check_checker') 6 | finish 7 | endif 8 | let g:loaded_syntastic_c_check_checker = 1 9 | 10 | if !exists('g:syntastic_c_compiler_options') 11 | let g:syntastic_c_compiler_options = '-std=gnu99' 12 | endif 13 | 14 | if !exists('g:syntastic_c_config_file') 15 | let g:syntastic_c_config_file = '.syntastic_c_config' 16 | endif 17 | 18 | let s:save_cpo = &cpo 19 | set cpo&vim 20 | 21 | let s:checker = expand(':p:h') . syntastic#util#Slash() . 'check.py' 22 | 23 | function! SyntaxCheckers_cfg_cfg_IsAvailable() dict 24 | return executable(self.getExec()) && 25 | \ syntastic#util#versionIsAtLeast( 26 | \ self.getVersion(self.getExecEscaped() . ' -V'), [2, 4]) 27 | endfunction 28 | 29 | function! SyntaxCheckers_c_check_GetLocList() dict 30 | if !exists('g:syntastic_c_compiler') 31 | let g:syntastic_c_compiler = executable('clang') ? 'clang' : 'gcc' 32 | endif 33 | 34 | let makeprg = self.makeprgBuild({ 35 | \ 'args_before': s:checker, 36 | \ 'args_after': 37 | \ g:syntastic_c_config_file . ' ' . 38 | \ g:syntastic_c_compiler . ' -x c ' . 39 | \ g:syntastic_c_compiler_options}) 40 | 41 | return SyntasticMake({ 42 | \ 'makeprg': makeprg, 43 | \ 'errorformat': 44 | \ '%-G%f:%s:,' . 45 | \ '%f:%l:%c: %trror: %m,' . 46 | \ '%f:%l:%c: %tarning: %m,' . 47 | \ '%f:%l:%c: %m,'. 48 | \ '%f:%l: %trror: %m,'. 49 | \ '%f:%l: %tarning: %m,'. 50 | \ '%f:%l: %m'}) 51 | endfunction 52 | 53 | call g:SyntasticRegistry.CreateAndRegisterChecker({ 54 | \ 'filetype': 'c', 55 | \ 'name': 'check', 56 | \ 'exec': 'python3'}) 57 | 58 | let &cpo = s:save_cpo 59 | unlet s:save_cpo 60 | -------------------------------------------------------------------------------- /syntax_checkers/cfg/cfg.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """Check config file syntax.""" 4 | 5 | try: 6 | import configparser 7 | except ImportError: 8 | import ConfigParser as configparser 9 | 10 | import re 11 | import sys 12 | 13 | try: 14 | import configobj 15 | except ImportError: 16 | configobj = None 17 | 18 | 19 | def check_configobj(filename): 20 | """Check file using configobj. 21 | 22 | Return list of (line_number, message) tuples. 23 | 24 | """ 25 | errors = [] 26 | 27 | if not configobj: 28 | return errors 29 | 30 | class Parser(configobj.ConfigObj): 31 | 32 | def _handle_error(self, text, ErrorClass, infile, cur_index): 33 | # Remove irrelevant text in old versions of configobj (<=4). 34 | text = re.sub(r' *at line "?%s"?\. *$', '', text) 35 | 36 | errors.append((cur_index + 1, text)) 37 | 38 | Parser(filename, 39 | list_values=False) # Avoid complaining about the values. 40 | 41 | return errors 42 | 43 | 44 | def check_configparser(filename): 45 | """Check file using configparser. 46 | 47 | Return list of (line_number, message) tuples. 48 | 49 | """ 50 | parser = configparser.RawConfigParser() 51 | 52 | errors = [] 53 | 54 | # Use ugly syntax to support very old versions of Python. 55 | try: 56 | parser.read(filename) 57 | except configparser.MissingSectionHeaderError: 58 | # Ignore non-standard cfg files. 59 | pass 60 | except configparser.Error: 61 | error = sys.exc_info()[1] 62 | 63 | line_number = getattr(error, 'lineno', 0) 64 | if not line_number: 65 | found = re.search(r'\[line\s+([0-9]+)\]', error.message) 66 | if found: 67 | line_number = int(found.group(1)) 68 | 69 | message = re.sub(r"^While reading from '.*' \[line *[0-9]+\]: *", 70 | '', 71 | error.message.splitlines()[0]).capitalize() 72 | 73 | errors.append((line_number, message)) 74 | 75 | return errors 76 | 77 | 78 | def might_be_configobj_format(filename): 79 | input_file = open(filename) 80 | try: 81 | for line in input_file.readlines(): 82 | # Check if there is a subsection. 83 | if re.match(r'^\s*\[\[.*\]\]\s*$', line): 84 | return True 85 | finally: 86 | input_file.close() 87 | 88 | return False 89 | 90 | 91 | def main(): 92 | if len(sys.argv) != 2: 93 | raise SystemExit('usage: %s filename' % (sys.argv[0],)) 94 | filename = sys.argv[1] 95 | 96 | try: 97 | # Use configobj only if there seems to be subsections. In such cases, 98 | # configobj is needed. Otherwise don't use it since there is syntax in 99 | # configparser that configobj does not understand. An example of this 100 | # is multiline values. configparser supports this, but configobj 101 | # requires triple quotes. 102 | if might_be_configobj_format(filename): 103 | errors = check_configobj(filename) 104 | else: 105 | errors = check_configparser(filename) 106 | 107 | for (line_number, message) in errors: 108 | sys.stderr.write('%s:%s: %s\n' % 109 | (filename, line_number, message)) 110 | return 1 111 | except IOError: 112 | # Ignore unreadable files. 113 | pass 114 | 115 | 116 | if __name__ == '__main__': 117 | sys.exit(main()) 118 | -------------------------------------------------------------------------------- /syntax_checkers/cfg/cfg.vim: -------------------------------------------------------------------------------- 1 | if exists("g:loaded_syntastic_cfg_cfg_checker") 2 | finish 3 | endif 4 | let g:loaded_syntastic_cfg_cfg_checker = 1 5 | 6 | let s:save_cpo = &cpo 7 | set cpo&vim 8 | 9 | let s:checker = expand(':p:h') . syntastic#util#Slash() . 'cfg.py' 10 | 11 | function! SyntaxCheckers_cfg_cfg_IsAvailable() dict 12 | return executable(self.getExec()) && 13 | \ syntastic#util#versionIsAtLeast( 14 | \ self.getVersion(self.getExecEscaped() . ' -V'), [2, 4]) 15 | endfunction 16 | 17 | function! SyntaxCheckers_cfg_cfg_GetLocList() dict 18 | let makeprg = self.makeprgBuild({'exe': [self.getExec(), s:checker]}) 19 | 20 | return SyntasticMake({ 21 | \ 'makeprg': makeprg, 22 | \ 'errorformat': 23 | \ '%f:%l: %m', 24 | \ 'returns': [0, 1]}) 25 | endfunction 26 | 27 | call g:SyntasticRegistry.CreateAndRegisterChecker({ 28 | \ 'filetype': 'cfg', 29 | \ 'exec': 'python3', 30 | \ 'name': 'cfg'}) 31 | 32 | let &cpo = s:save_cpo 33 | unlet s:save_cpo 34 | -------------------------------------------------------------------------------- /syntax_checkers/cpp/check.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """Check C/C++ file syntax.""" 4 | 5 | import locale 6 | import os 7 | import shlex 8 | import subprocess 9 | import sys 10 | 11 | 12 | HEADER_EXTENSIONS = frozenset(['.h', '.hh', '.hpp', '.h++', '.hxx', '.cuh']) 13 | INCLUDE_OPTION = '-I' 14 | 15 | 16 | def find_configuration(start_path, configuration_filename): 17 | """Return path to configuration. 18 | 19 | Return None if there is no configuration. 20 | 21 | """ 22 | while start_path: 23 | start_path = os.path.dirname(start_path) 24 | 25 | configuration_path = os.path.join(start_path, configuration_filename) 26 | if os.path.exists(configuration_path): 27 | return configuration_path 28 | 29 | if start_path == os.sep: 30 | break 31 | 32 | return None 33 | 34 | 35 | def read_lines(filename): 36 | """Return split lines from file without line endings.""" 37 | try: 38 | input_file = open(filename) 39 | try: 40 | lines = input_file.read().splitlines() 41 | finally: 42 | input_file.close() 43 | except IOError: 44 | return None 45 | 46 | return lines 47 | 48 | 49 | def read_configuration(start_path, configuration_filename): 50 | """Return compiler options from configuration. 51 | 52 | Return None if there is no configuration. 53 | 54 | """ 55 | configuration_path = find_configuration( 56 | os.path.abspath(start_path), 57 | configuration_filename=configuration_filename) 58 | 59 | raw_lines = None 60 | if configuration_path: 61 | raw_lines = read_lines(configuration_path) 62 | 63 | if raw_lines is None: 64 | return None 65 | 66 | options = [] 67 | for line in raw_lines: 68 | if line.startswith(INCLUDE_OPTION): 69 | options.append('-isystem') 70 | relative_path = line[len(INCLUDE_OPTION):].lstrip() 71 | options.append(os.path.join(os.path.dirname(configuration_path), 72 | relative_path)) 73 | else: 74 | for token in shlex.split(line): 75 | options.append(token) 76 | 77 | return options 78 | 79 | 80 | def find_compile_commands_json(source_filename): 81 | """Return path to `compile_commands.json` generated by CMake.""" 82 | start_path = os.path.abspath(source_filename) 83 | last_path = start_path 84 | 85 | while start_path: 86 | start_path = os.path.dirname(start_path) 87 | 88 | configuration_path = os.path.join(start_path, 89 | 'build', 90 | 'compile_commands.json') 91 | if os.path.exists(configuration_path): 92 | return configuration_path 93 | 94 | if start_path == last_path: 95 | break 96 | 97 | last_path = start_path 98 | 99 | return None 100 | 101 | 102 | def get_compile_options(command, filename): 103 | """Return compile options for syntax checking.""" 104 | options = [] 105 | 106 | index = 1 107 | while True: 108 | try: 109 | item = command[index] 110 | except IndexError: 111 | break 112 | 113 | index += 1 114 | 115 | try: 116 | if os.path.samefile(item, filename): 117 | continue 118 | except OSError: 119 | pass 120 | 121 | if item == '-o': 122 | index += 1 123 | continue 124 | 125 | options.append(item) 126 | 127 | return options 128 | 129 | 130 | def read_compile_commands_json(source_filename): 131 | """Return path to `compile_commands.json` generated by CMake.""" 132 | json_filename = find_compile_commands_json(source_filename) 133 | if json_filename is None: 134 | return None 135 | 136 | try: 137 | import json 138 | except ImportError: 139 | # Old Python. 140 | return None 141 | 142 | try: 143 | input_file = None 144 | try: 145 | input_file = open(json_filename) 146 | compile_commands = json.load(input_file) 147 | finally: 148 | if input_file: 149 | input_file.close() 150 | except OSError: 151 | return None 152 | 153 | for entry in compile_commands: 154 | try: 155 | if os.path.samefile(entry['file'], source_filename): 156 | command = entry['command'].split() 157 | return get_compile_options(command, source_filename) 158 | except OSError: 159 | pass 160 | 161 | return None 162 | 163 | 164 | 165 | def is_header_file(filename): 166 | """Return True if "filename" is a header file. 167 | 168 | >>> is_header_file('foo.c') 169 | False 170 | 171 | >>> is_header_file('foo.h') 172 | True 173 | 174 | >>> is_header_file('foo.h++') 175 | True 176 | 177 | """ 178 | extension = os.path.splitext(filename)[1] 179 | return extension.lower() in HEADER_EXTENSIONS 180 | 181 | 182 | def check(configuration_filename, command, filename, verbose_file=None): 183 | """Return list of error messages.""" 184 | options = read_configuration(filename, 185 | configuration_filename=configuration_filename) 186 | 187 | if options is None: 188 | # Otherwise look for a configuration generated by CMake. 189 | options = read_compile_commands_json(filename) 190 | if options is None: 191 | return [] 192 | 193 | if is_header_file(filename): 194 | # Avoid generating precompiled headers. 195 | options += ['-c', os.devnull] 196 | 197 | 198 | full_command = command + ['-fsyntax-only'] + options + [filename] 199 | 200 | if verbose_file: 201 | verbose_file.write(' '.join(full_command) + '\n') 202 | 203 | process = subprocess.Popen(command + ['-fsyntax-only'] + 204 | options + [filename], 205 | stderr=subprocess.PIPE) 206 | 207 | errors = process.communicate()[1] 208 | if sys.version_info[0] > 2: 209 | errors = errors.decode(locale.getpreferredencoding()) 210 | 211 | return errors.splitlines(True) 212 | 213 | 214 | def main(): 215 | if len(sys.argv) < 4: 216 | raise SystemExit('usage: %s configuration_filename command filename' % 217 | (sys.argv[0],)) 218 | 219 | exit_status = 0 220 | 221 | for line in check(configuration_filename=sys.argv[1], 222 | command=sys.argv[2:-1], 223 | filename=sys.argv[-1]): 224 | sys.stderr.write(line) 225 | exit_status = 1 226 | 227 | return exit_status 228 | 229 | 230 | if __name__ == '__main__': 231 | sys.exit(main()) 232 | -------------------------------------------------------------------------------- /syntax_checkers/cpp/check.vim: -------------------------------------------------------------------------------- 1 | " Like Syntastic's normal checker, but only checks files if there is a 2 | " '.syntastic_cpp_config' file existing in the directory or an ancestor 3 | " directory. 4 | 5 | if exists('g:loaded_syntastic_cpp_check_checker') 6 | finish 7 | endif 8 | let g:loaded_syntastic_cpp_check_checker = 1 9 | 10 | if !exists('g:syntastic_cpp_compiler_options') 11 | let g:syntastic_cpp_compiler_options = '' 12 | endif 13 | 14 | if !exists('g:syntastic_cpp_config_file') 15 | let g:syntastic_cpp_config_file = '.syntastic_cpp_config' 16 | endif 17 | 18 | let s:save_cpo = &cpo 19 | set cpo&vim 20 | 21 | let s:checker = expand(':p:h') . syntastic#util#Slash() . 'check.py' 22 | 23 | function! SyntaxCheckers_cfg_cfg_IsAvailable() dict 24 | return executable(self.getExec()) && 25 | \ syntastic#util#versionIsAtLeast( 26 | \ self.getVersion(self.getExecEscaped() . ' -V'), [2, 4]) 27 | endfunction 28 | 29 | function! SyntaxCheckers_cpp_check_GetLocList() dict 30 | if !exists('g:syntastic_cpp_compiler') 31 | let g:syntastic_cpp_compiler = 32 | \ executable('clang++') ? 'clang++' : 'g++' 33 | endif 34 | 35 | let makeprg = self.makeprgBuild({ 36 | \ 'args_before': s:checker, 37 | \ 'args_after': 38 | \ g:syntastic_cpp_config_file . ' ' . 39 | \ g:syntastic_cpp_compiler . ' -x c++ ' . 40 | \ g:syntastic_cpp_compiler_options}) 41 | 42 | return SyntasticMake({ 43 | \ 'makeprg': makeprg, 44 | \ 'errorformat': 45 | \ '%-G%f:%s:,' . 46 | \ '%f:%l:%c: %trror: %m,' . 47 | \ '%f:%l:%c: %tarning: %m,' . 48 | \ '%f:%l:%c: %m,'. 49 | \ '%f:%l: %trror: %m,'. 50 | \ '%f:%l: %tarning: %m,'. 51 | \ '%f:%l: %m'}) 52 | endfunction 53 | 54 | call g:SyntasticRegistry.CreateAndRegisterChecker({ 55 | \ 'filetype': 'cpp', 56 | \ 'name': 'check', 57 | \ 'exec': 'python3'}) 58 | 59 | let &cpo = s:save_cpo 60 | unlet s:save_cpo 61 | -------------------------------------------------------------------------------- /syntax_checkers/cpp/test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """Utility to easily use `check.py` from the command line instead of Vim.""" 4 | 5 | import os 6 | import shlex 7 | import sys 8 | 9 | import check 10 | 11 | 12 | def is_file(path): 13 | """Return True if path is a regular file. 14 | 15 | This is case sensitive. 16 | 17 | """ 18 | (directory, base_filename) = os.path.split(path) 19 | return base_filename in os.listdir(directory) 20 | 21 | 22 | def get_command(source_code_filename): 23 | if is_cpp(source_code_filename): 24 | return shlex.split(os.getenv('CXX', 'g++')) + ['-x', 'c++'] 25 | else: 26 | return shlex.split(os.getenv('CC', 'gcc')) + ['-x', 'c'] 27 | 28 | 29 | def get_configuration_base_name(source_code_filename): 30 | if is_cpp(source_code_filename): 31 | return '.syntastic_cpp_config' 32 | else: 33 | return '.syntastic_c_config' 34 | 35 | 36 | def is_cpp(filename): 37 | (root, extension) = os.path.splitext(filename) 38 | if extension == '.c': 39 | return False 40 | elif extension == '.h': 41 | # This could be C or C++. Guess based on its sibling file. 42 | # Use a case sensitive variant of `os.path.isfile()` since `.C` would 43 | # be C++. 44 | if is_file(root + '.c'): 45 | return False 46 | else: 47 | return True 48 | elif extension in ['.hh', '.hpp', '.h++', '.hxx']: 49 | return True 50 | else: 51 | return True 52 | 53 | 54 | def main(): 55 | exit_status = 0 56 | 57 | for filename in sys.argv[1:]: 58 | filename = os.path.abspath(filename) 59 | 60 | for line in check.check( 61 | configuration_filename=get_configuration_base_name(filename), 62 | command=get_command(filename), 63 | filename=filename, 64 | verbose_file=sys.stderr): 65 | sys.stderr.write(line) 66 | exit_status = 1 67 | 68 | return exit_status 69 | 70 | 71 | if __name__ == '__main__': 72 | sys.exit(main()) 73 | -------------------------------------------------------------------------------- /syntax_checkers/dosini/dosini.vim: -------------------------------------------------------------------------------- 1 | if exists("g:loaded_syntastic_dosini_dosini_checker") 2 | finish 3 | endif 4 | let g:loaded_syntastic_dosini_dosini_checker = 1 5 | 6 | runtime! syntax_checkers/cfg/cfg.vim 7 | 8 | call g:SyntasticRegistry.CreateAndRegisterChecker({ 9 | \ 'filetype': 'dosini', 10 | \ 'exec': 'python3', 11 | \ 'name': 'dosini', 12 | \ 'redirect': 'cfg/cfg'}) 13 | -------------------------------------------------------------------------------- /syntax_checkers/gitcommit/language_check.vim: -------------------------------------------------------------------------------- 1 | "============================================================================ 2 | "File: language_check.vim 3 | "Description: Grammar checker (https://github.com/myint/language-check) 4 | "============================================================================ 5 | 6 | if exists("g:loaded_syntastic_gitcommit_language_check_checker") 7 | finish 8 | endif 9 | let g:loaded_syntastic_gitcommit_language_check_checker = 1 10 | 11 | let s:save_cpo = &cpo 12 | set cpo&vim 13 | 14 | function! SyntaxCheckers_gitcommit_language_check_GetLocList() dict 15 | let makeprg = self.makeprgBuild({ 16 | \ 'args_after': 17 | \ '--disable=EN_QUOTES --disable=EN_UNPAIRED_BRACKETS ' . 18 | \ '--ignore-lines="^(#|diff --git|@@|index | |-|\+)" ' . 19 | \ '--spell-check-off'}) 20 | 21 | let errorformat = 22 | \ '%f:%l:%c: %m' 23 | 24 | return SyntasticMake({ 25 | \ 'makeprg': makeprg, 26 | \ 'errorformat': errorformat, 27 | \ 'subtype': 'Style', 28 | \ 'returns': [0, 2] }) 29 | endfunction 30 | 31 | call g:SyntasticRegistry.CreateAndRegisterChecker({ 32 | \ 'filetype': 'gitcommit', 33 | \ 'name': 'language_check', 34 | \ 'exec': 'language-check'}) 35 | 36 | let &cpo = s:save_cpo 37 | unlet s:save_cpo 38 | -------------------------------------------------------------------------------- /syntax_checkers/gitcommit/proselint.vim: -------------------------------------------------------------------------------- 1 | if exists("g:loaded_syntastic_gitcommit_proselint_checker") 2 | finish 3 | endif 4 | let g:loaded_syntastic_gitcommit_proselint_checker = 1 5 | 6 | let s:save_cpo = &cpo 7 | set cpo&vim 8 | 9 | let s:wrapper = 10 | \ expand(':p:h') . syntastic#util#Slash() . 'proselint_wrapper.py' 11 | 12 | function! SyntaxCheckers_gitcommit_proselint_IsAvailable() dict 13 | return executable(self.getExec()) && 14 | \ syntastic#util#versionIsAtLeast( 15 | \ self.getVersion(self.getExecEscaped() . ' -V'), [2, 4]) 16 | endfunction 17 | 18 | function! SyntaxCheckers_gitcommit_proselint_GetLocList() dict 19 | let makeprg = self.makeprgBuild({ 20 | \ 'args_before': s:wrapper}) 21 | 22 | let errorformat = 23 | \ '%f:%l:%c: %m' 24 | 25 | return SyntasticMake({ 26 | \ 'makeprg': makeprg, 27 | \ 'errorformat': errorformat, 28 | \ 'defaults': { 'type': 'W', 'subtype': 'Style' }, 29 | \ 'returns': [0, 1] }) 30 | endfunction 31 | 32 | call g:SyntasticRegistry.CreateAndRegisterChecker({ 33 | \ 'filetype': 'gitcommit', 34 | \ 'name': 'proselint', 35 | \ 'exec': 'python3'}) 36 | 37 | let &cpo = s:save_cpo 38 | unlet s:save_cpo 39 | -------------------------------------------------------------------------------- /syntax_checkers/gitcommit/proselint_wrapper.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """Remove comments before passing output to proselint.""" 4 | 5 | import locale 6 | import re 7 | import subprocess 8 | import sys 9 | 10 | 11 | def main(): 12 | if len(sys.argv) != 2: 13 | sys.stderr.write('Usage: ' + sys.argv[0] + ' filename\n') 14 | return 2 15 | 16 | filename = sys.argv[1] 17 | 18 | input_lines = [] 19 | try: 20 | input_file = open(filename) 21 | try: 22 | for line in input_file.readlines(): 23 | if line.startswith('#'): 24 | # Ignore everything below the comments like the diff that 25 | # shows up in verbose commit mode. 26 | break 27 | else: 28 | input_lines.append(line) 29 | finally: 30 | input_file.close() 31 | except IOError: 32 | # Ignore unreadable file. 33 | sys.stderr.write('%s\n' % (sys.exc_info()[1],)) 34 | return 1 35 | 36 | try: 37 | process = subprocess.Popen(['proselint', '-'], 38 | stdin=subprocess.PIPE, 39 | stdout=subprocess.PIPE) 40 | except OSError: 41 | # Ignore if proselint is not installed. 42 | return 0 43 | 44 | encoding = locale.getpreferredencoding() 45 | 46 | output = process.communicate(''.join(input_lines).encode(encoding))[0] 47 | 48 | if sys.version_info[0] > 2: 49 | output = output.decode(encoding) 50 | 51 | for line in output.splitlines(True): 52 | # proselint 0.10 changed the output message from `-:` to `:`. 53 | filtered_line = re.sub('^(-|):', filename + ':', line) 54 | sys.stdout.write(filtered_line) 55 | 56 | return process.returncode 57 | 58 | 59 | if __name__ == '__main__': 60 | sys.exit(main()) 61 | -------------------------------------------------------------------------------- /syntax_checkers/javascript/json_tool.py: -------------------------------------------------------------------------------- 1 | ../json/json_tool.py -------------------------------------------------------------------------------- /syntax_checkers/javascript/json_tool.vim: -------------------------------------------------------------------------------- 1 | if exists("g:loaded_syntastic_javascript_json_tool_checker") 2 | finish 3 | endif 4 | let g:loaded_syntastic_javascript_json_tool_checker = 1 5 | 6 | let s:save_cpo = &cpo 7 | set cpo&vim 8 | 9 | let s:checker = expand(':p:h') . syntastic#util#Slash() . 10 | \ 'json_tool.py' 11 | 12 | function! SyntaxCheckers_javascript_json_tool_IsAvailable() dict 13 | return executable(self.getExec()) && 14 | \ syntastic#util#versionIsAtLeast( 15 | \ self.getVersion(self.getExecEscaped() . ' -V'), [2, 4]) 16 | endfunction 17 | 18 | function! SyntaxCheckers_javascript_json_tool_GetLocList() dict 19 | let makeprg = self.makeprgBuild({'exe': [self.getExec(), s:checker]}) 20 | 21 | return SyntasticMake({ 22 | \ 'makeprg': makeprg, 23 | \ 'errorformat': 24 | \ '%f:%l:%c: %m', 25 | \ 'returns': [0, 1]}) 26 | endfunction 27 | 28 | call g:SyntasticRegistry.CreateAndRegisterChecker({ 29 | \ 'filetype': 'javascript', 30 | \ 'exec': 'python', 31 | \ 'name': 'json_tool'}) 32 | 33 | let &cpo = s:save_cpo 34 | unlet s:save_cpo 35 | -------------------------------------------------------------------------------- /syntax_checkers/json/json_tool.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """Check JSON syntax.""" 4 | 5 | import re 6 | import sys 7 | 8 | 9 | def main(): 10 | try: 11 | import json 12 | except ImportError: 13 | # Don't do anything if json module is not available. 14 | return 0 15 | 16 | if len(sys.argv) != 2: 17 | raise SystemExit('usage: %s filename' % (sys.argv[0],)) 18 | filename = sys.argv[1] 19 | 20 | try: 21 | input_file = open(filename, 'r') 22 | try: 23 | json.load(input_file) 24 | finally: 25 | input_file.close() 26 | except ValueError: 27 | message = str(sys.exc_info()[1]) 28 | line_number = 0 29 | column = 0 30 | 31 | found = re.search(r': line\s+([0-9]+) column\s+([0-9]+)[^:]*$', 32 | message) 33 | if found: 34 | line_number = int(found.group(1)) 35 | column = int(found.group(2)) 36 | 37 | sys.stderr.write('%s:%s:%s: %s\n' % 38 | (filename, 39 | line_number, 40 | column, 41 | message)) 42 | 43 | return 1 44 | except IOError: 45 | sys.stderr.write('%s\n' % (sys.exc_info()[1],)) 46 | return 1 47 | 48 | 49 | if __name__ == '__main__': 50 | sys.exit(main()) 51 | -------------------------------------------------------------------------------- /syntax_checkers/json/json_tool.vim: -------------------------------------------------------------------------------- 1 | if exists("g:loaded_syntastic_json_json_tool_checker") 2 | finish 3 | endif 4 | let g:loaded_syntastic_json_json_tool_checker = 1 5 | 6 | let s:save_cpo = &cpo 7 | set cpo&vim 8 | 9 | let s:checker = expand(':p:h') . syntastic#util#Slash() . 10 | \ 'json_tool.py' 11 | 12 | function! SyntaxCheckers_json_json_tool_IsAvailable() dict 13 | return executable(self.getExec()) && 14 | \ syntastic#util#versionIsAtLeast( 15 | \ self.getVersion(self.getExecEscaped() . ' -V'), [2, 4]) 16 | endfunction 17 | 18 | function! SyntaxCheckers_json_json_tool_GetLocList() dict 19 | let makeprg = self.makeprgBuild({'exe': [self.getExec(), s:checker]}) 20 | 21 | return SyntasticMake({ 22 | \ 'makeprg': makeprg, 23 | \ 'errorformat': 24 | \ '%f:%l:%c: %m', 25 | \ 'returns': [0, 1]}) 26 | endfunction 27 | 28 | call g:SyntasticRegistry.CreateAndRegisterChecker({ 29 | \ 'filetype': 'json', 30 | \ 'exec': 'python3', 31 | \ 'name': 'json_tool'}) 32 | 33 | let &cpo = s:save_cpo 34 | unlet s:save_cpo 35 | -------------------------------------------------------------------------------- /syntax_checkers/make/gnumake.vim: -------------------------------------------------------------------------------- 1 | "============================================================================ 2 | "File: gnumake.vim 3 | "Description: Syntax checking plugin for makefiles. 4 | "============================================================================ 5 | 6 | if exists("g:loaded_syntastic_make_gnumake_checker") 7 | finish 8 | endif 9 | let g:loaded_syntastic_make_gnumake_checker = 1 10 | 11 | let s:save_cpo = &cpo 12 | set cpo&vim 13 | 14 | function! SyntaxCheckers_make_gnumake_IsAvailable() dict 15 | return executable('timeout') && 16 | \ syntastic#util#system('make --version') =~# '^GNU Make ' && 17 | \ v:shell_error == 0 18 | endfunction 19 | 20 | function! SyntaxCheckers_make_gnumake_GetLocList() dict 21 | let makeprg = self.makeprgBuild({ 22 | \ 'args_after': '--silent --just-print', 23 | \ 'args_before': '3 make', 24 | \ 'fname_before': '--file'}) 25 | 26 | return SyntasticMake({ 27 | \ 'makeprg': makeprg, 28 | \ 'errorformat': 29 | \ '%f:%l: %tarning: %m,' . 30 | \ '%f:%l: %m', 31 | \ 'returns': [0, 2, 124]}) 32 | endfunction 33 | 34 | call g:SyntasticRegistry.CreateAndRegisterChecker({ 35 | \ 'filetype': 'make', 36 | \ 'exec': 'timeout', 37 | \ 'name': 'gnumake'}) 38 | 39 | let &cpo = s:save_cpo 40 | unlet s:save_cpo 41 | -------------------------------------------------------------------------------- /syntax_checkers/python/pyflakes_with_warnings.vim: -------------------------------------------------------------------------------- 1 | if exists("g:loaded_syntastic_python_pyflakes_with_warnings_checker") 2 | finish 3 | endif 4 | let g:loaded_syntastic_python_pyflakes_with_warnings_checker = 1 5 | 6 | let s:save_cpo = &cpo 7 | set cpo&vim 8 | 9 | function! SyntaxCheckers_python_pyflakes_with_warnings_GetHighlightRegex(i) 10 | if stridx(a:i['text'], 'is assigned to but never used') >= 0 11 | \ || stridx(a:i['text'], 'imported but unused') >= 0 12 | \ || stridx(a:i['text'], 'undefined name') >= 0 13 | \ || stridx(a:i['text'], 'redefinition of') >= 0 14 | \ || stridx(a:i['text'], 'referenced before assignment') >= 0 15 | \ || stridx(a:i['text'], 'duplicate argument') >= 0 16 | \ || stridx(a:i['text'], 'after other statements') >= 0 17 | \ || stridx(a:i['text'], 'shadowed by loop variable') >= 0 18 | 19 | " fun with Python's %r: try "..." first, then '...' 20 | let term = matchstr(a:i['text'], '\m^.\{-}"\zs.\{-1,}\ze"') 21 | if term != '' 22 | return '\V\<' . escape(term, '\') . '\>' 23 | endif 24 | 25 | let term = matchstr(a:i['text'], '\m^.\{-}''\zs.\{-1,}\ze''') 26 | if term != '' 27 | return '\V\<' . escape(term, '\') . '\>' 28 | endif 29 | endif 30 | return '' 31 | endfunction 32 | 33 | function! SyntaxCheckers_python_pyflakes_with_warnings_GetLocList() dict 34 | let makeprg = self.makeprgBuild({}) 35 | 36 | let errorformat = 37 | \ '%E%f:%l: could not compile,'. 38 | \ '%-Z%p^,'. 39 | \ '%E%f:%l:%c:%\= %m,'. 40 | \ '%E%f:%l:%\= %m,'. 41 | \ '%E%f:%l: %m,'. 42 | \ '%-G%.%#' 43 | 44 | let env = syntastic#util#isRunningWindows() ? {} : { 'TERM': 'dumb' } 45 | 46 | let loclist = SyntasticMake({ 47 | \ 'makeprg': makeprg, 48 | \ 'errorformat': errorformat, 49 | \ 'env': env, 50 | \ 'defaults': {'text': "Syntax error"} }) 51 | 52 | for e in loclist 53 | let e['vcol'] = 0 54 | endfor 55 | 56 | for e in loclist 57 | if stridx(e['text'], 'is assigned to but never used') >= 0 58 | \ || stridx(e['text'], 'imported but unused') >= 0 59 | let e['type'] = 'W' 60 | endif 61 | endfor 62 | 63 | return loclist 64 | endfunction 65 | 66 | call g:SyntasticRegistry.CreateAndRegisterChecker({ 67 | \ 'filetype': 'python', 68 | \ 'name': 'pyflakes_with_warnings', 69 | \ 'exec': 'pyflakes'}) 70 | 71 | let &cpo = s:save_cpo 72 | unlet s:save_cpo 73 | -------------------------------------------------------------------------------- /syntax_checkers/svn/language_check.vim: -------------------------------------------------------------------------------- 1 | if exists("g:loaded_syntastic_svn_language_check_checker") 2 | finish 3 | endif 4 | let g:loaded_syntastic_svn_language_check_checker = 1 5 | 6 | let s:save_cpo = &cpo 7 | set cpo&vim 8 | 9 | function! SyntaxCheckers_svn_language_check_GetLocList() dict 10 | let makeprg = self.makeprgBuild({ 11 | \ 'args_after': 12 | \ '--disable=EN_QUOTES --disable=EN_UNPAIRED_BRACKETS ' . 13 | \ '--ignore-lines="^(--|.[ CM][ L][ \+]|@@|==|-|\+|}|Index: | +|Property changes on:|r[0-9]+ |svn:)" ' . 14 | \ '--spell-check-off'}) 15 | 16 | let errorformat = 17 | \ '%f:%l:%c: %m' 18 | 19 | return SyntasticMake({ 20 | \ 'makeprg': makeprg, 21 | \ 'errorformat': errorformat, 22 | \ 'subtype': 'Style', 23 | \ 'returns': [0, 2] }) 24 | endfunction 25 | 26 | call g:SyntasticRegistry.CreateAndRegisterChecker({ 27 | \ 'filetype': 'svn', 28 | \ 'name': 'language_check', 29 | \ 'exec': 'language-check'}) 30 | 31 | let &cpo = s:save_cpo 32 | unlet s:save_cpo 33 | -------------------------------------------------------------------------------- /syntax_checkers/yaml/check_yaml.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """Check YAML syntax.""" 4 | 5 | import sys 6 | 7 | 8 | def main(): 9 | try: 10 | import yaml 11 | except ImportError: 12 | # Don't do anything if yaml module is not available. 13 | return 0 14 | 15 | if len(sys.argv) != 2: 16 | raise SystemExit('usage: %s filename' % (sys.argv[0],)) 17 | filename = sys.argv[1] 18 | 19 | try: 20 | input_file = open(filename, 'rb') 21 | try: 22 | yaml.load(input_file) 23 | finally: 24 | input_file.close() 25 | except yaml.error.YAMLError: 26 | error = sys.exc_info()[1] 27 | mark = error.problem_mark 28 | 29 | sys.stderr.write('%s:%s:%s: %s\n' % 30 | (filename, 31 | mark.line + 1, 32 | mark.column + 1, 33 | error.problem)) 34 | 35 | return 1 36 | except IOError: 37 | sys.stderr.write('%s\n' % (sys.exc_info()[1],)) 38 | return 1 39 | 40 | 41 | if __name__ == '__main__': 42 | sys.exit(main()) 43 | -------------------------------------------------------------------------------- /syntax_checkers/yaml/pyyaml.vim: -------------------------------------------------------------------------------- 1 | if exists("g:loaded_syntastic_yaml_pyyaml_checker") 2 | finish 3 | endif 4 | let g:loaded_syntastic_yaml_pyyaml_checker = 1 5 | 6 | let s:save_cpo = &cpo 7 | set cpo&vim 8 | 9 | let s:checker = expand(':p:h') . syntastic#util#Slash() . 10 | \ 'check_yaml.py' 11 | 12 | function! SyntaxCheckers_yaml_pyyaml_IsAvailable() dict 13 | return executable(self.getExec()) && 14 | \ syntastic#util#versionIsAtLeast( 15 | \ self.getVersion(self.getExecEscaped() . ' -V'), [2, 4]) 16 | endfunction 17 | 18 | function! SyntaxCheckers_yaml_pyyaml_GetLocList() dict 19 | let makeprg = self.makeprgBuild({'exe': [self.getExec(), s:checker]}) 20 | 21 | return SyntasticMake({ 22 | \ 'makeprg': makeprg, 23 | \ 'errorformat': 24 | \ '%f:%l:%c: %m', 25 | \ 'returns': [0, 1]}) 26 | endfunction 27 | 28 | call g:SyntasticRegistry.CreateAndRegisterChecker({ 29 | \ 'filetype': 'yaml', 30 | \ 'exec': 'python3', 31 | \ 'name': 'pyyaml'}) 32 | 33 | let &cpo = s:save_cpo 34 | unlet s:save_cpo 35 | -------------------------------------------------------------------------------- /test/bad.cfg: -------------------------------------------------------------------------------- 1 | [hello] 2 | world 3 | -------------------------------------------------------------------------------- /test/bad.gitcommit: -------------------------------------------------------------------------------- 1 | The cat is here 2 | 3 | The the cat is here. 4 | 5 | # Comments should be ignored. 6 | -------------------------------------------------------------------------------- /test/bad.ini: -------------------------------------------------------------------------------- 1 | [hello] 2 | world 3 | -------------------------------------------------------------------------------- /test/bad.json: -------------------------------------------------------------------------------- 1 | { 2 | 'abc': [], 3 | "def": [] 4 | } 5 | -------------------------------------------------------------------------------- /test/bad.yaml: -------------------------------------------------------------------------------- 1 | x 2 | language: 3 | -------------------------------------------------------------------------------- /test/bad_with_subsections.cfg: -------------------------------------------------------------------------------- 1 | [hello] 2 | world 3 | -------------------------------------------------------------------------------- /test/compile_commands/bad.cpp: -------------------------------------------------------------------------------- 1 | #include "some_header.h" 2 | 3 | 1 / 4 | -------------------------------------------------------------------------------- /test/compile_commands/build/compile_commands.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "directory": "/Users/myint/projects/perceptualdiff/build", 4 | "command": "c++ -isystem test/compile_commands/header_directory -o ignore_this.o -c test/compile_commands/good.cpp", 5 | "file": "test/compile_commands/good.cpp" 6 | }, 7 | { 8 | "directory": "/Users/myint/projects/perceptualdiff/build", 9 | "command": "c++ -isystem test/compile_commands/header_directory -o ignore_this.o -c test/compile_commands/bad.cpp", 10 | "file": "test/compile_commands/bad.cpp" 11 | } 12 | ] 13 | -------------------------------------------------------------------------------- /test/compile_commands/good.cpp: -------------------------------------------------------------------------------- 1 | #include "some_header.h" 2 | -------------------------------------------------------------------------------- /test/compile_commands/header_directory/some_header.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myint/syntastic-extras/1165be2d884370f31422c8b7a6d5eb3986d4ea1b/test/compile_commands/header_directory/some_header.h -------------------------------------------------------------------------------- /test/good.cfg: -------------------------------------------------------------------------------- 1 | [hello] 2 | world=1 3 | -------------------------------------------------------------------------------- /test/good.gitcommit: -------------------------------------------------------------------------------- 1 | The cat is here 2 | # Comments should be ignored. 3 | # The the cat is here 4 | # Everything below the comment block should be ignored too. 5 | The the cat is here 6 | -------------------------------------------------------------------------------- /test/good.json: -------------------------------------------------------------------------------- 1 | { 2 | "abc": [], 3 | "def": [] 4 | } 5 | -------------------------------------------------------------------------------- /test/good.yaml: -------------------------------------------------------------------------------- 1 | language: python 2 | -------------------------------------------------------------------------------- /test/good_with_subsections.cfg: -------------------------------------------------------------------------------- 1 | [hello] 2 | world=1 3 | -------------------------------------------------------------------------------- /test/syntastic_config/.syntastic_c_config: -------------------------------------------------------------------------------- 1 | -Ifoo 2 | -Wimplicit-function-declaration 3 | -------------------------------------------------------------------------------- /test/syntastic_config/.syntastic_cpp_config: -------------------------------------------------------------------------------- 1 | -Ifoo 2 | -------------------------------------------------------------------------------- /test/syntastic_config/bad.c: -------------------------------------------------------------------------------- 1 | int main() 2 | { 3 | bar_x(); 4 | } 5 | -------------------------------------------------------------------------------- /test/syntastic_config/bad.cpp: -------------------------------------------------------------------------------- 1 | int main() 2 | { 3 | bar_x(); 4 | } 5 | -------------------------------------------------------------------------------- /test/syntastic_config/bad_header.c: -------------------------------------------------------------------------------- 1 | #include "bad_header.h" 2 | -------------------------------------------------------------------------------- /test/syntastic_config/bad_header.h: -------------------------------------------------------------------------------- 1 | dfd 2 | -------------------------------------------------------------------------------- /test/syntastic_config/foo/bar.h: -------------------------------------------------------------------------------- 1 | #ifndef BAR_H 2 | #define BAR_H 3 | 4 | void bar_x(); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /test/syntastic_config/good.c: -------------------------------------------------------------------------------- 1 | #include "bar.h" 2 | 3 | 4 | int main() 5 | { 6 | bar_x(); 7 | } 8 | -------------------------------------------------------------------------------- /test/syntastic_config/good.cpp: -------------------------------------------------------------------------------- 1 | #include "bar.h" 2 | 3 | 4 | int main() 5 | { 6 | bar_x(); 7 | } 8 | -------------------------------------------------------------------------------- /test/syntastic_config/good_header.cpp: -------------------------------------------------------------------------------- 1 | #include "good_header.h" 2 | 3 | 4 | int main(int argc, char **) 5 | { 6 | std::vector vector; 7 | vector.push_back(argc); 8 | return vector.at(0); 9 | } 10 | -------------------------------------------------------------------------------- /test/syntastic_config/good_header.h: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /test/test.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -ex 4 | 5 | if [[ -z "$PYTHON" ]] 6 | then 7 | PYTHON=python3 8 | fi 9 | 10 | trap "echo -e '\x1b[01;31mFailed\x1b[0m'" ERR 11 | 12 | readonly script_directory=$(dirname "$0") 13 | cd "$script_directory"/.. 14 | 15 | # Unreadable files should be handled gracefully. 16 | touch test/unreadable.json 17 | touch test/unreadable.yaml 18 | trap 'rm -f test/unreadable.json test/unreadable.yaml' EXIT 19 | chmod ugo-r test/unreadable.json 20 | chmod ugo-r test/unreadable.yaml 21 | 22 | "$PYTHON" ./syntax_checkers/cfg/cfg.py test/good.cfg 23 | "$PYTHON" ./syntax_checkers/cfg/cfg.py test/good_with_subsections.cfg 24 | "$PYTHON" ./syntax_checkers/c/check.py .syntastic_c_config gcc test/syntastic_config/good.c 25 | "$PYTHON" ./syntax_checkers/cpp/check.py .syntastic_cpp_config g++ test/syntastic_config/good.cpp 26 | "$PYTHON" ./syntax_checkers/cpp/check.py .syntastic_c_config gcc -x c test/syntastic_config/foo/bar.h 27 | "$PYTHON" ./syntax_checkers/cpp/check.py .syntastic_cpp_config g++ -x c++ test/syntastic_config/foo/bar.h 28 | "$PYTHON" ./syntax_checkers/gitcommit/proselint_wrapper.py test/good.gitcommit 29 | 30 | "$PYTHON" ./syntax_checkers/cfg/cfg.py test/bad.cfg 2>&1 \ 31 | | grep 'test/bad.cfg:2' > /dev/null 32 | "$PYTHON" ./syntax_checkers/cfg/cfg.py test/bad_with_subsections.cfg 2>&1 \ 33 | | grep 'test/bad_with_subsections.cfg:2' > /dev/null 34 | 35 | "$PYTHON" ./syntax_checkers/cfg/cfg.py test/bad.ini 2>&1 \ 36 | | grep 'test/bad.ini:2' > /dev/null 37 | 38 | "$PYTHON" ./syntax_checkers/c/check.py .syntastic_c_config gcc test/syntastic_config/bad.c 2>&1 \ 39 | | grep 'test/syntastic_config/bad.c:3' > /dev/null 40 | 41 | "$PYTHON" ./syntax_checkers/cpp/check.py .syntastic_cpp_config g++ test/syntastic_config/bad.cpp 2>&1 \ 42 | | grep 'test/syntastic_config/bad.cpp:3' > /dev/null 43 | 44 | "$PYTHON" ./syntax_checkers/gitcommit/proselint_wrapper.py test/bad.gitcommit 2>& 1 \ 45 | | grep 'test/bad.gitcommit:3' > /dev/null 46 | 47 | if "$PYTHON" -c 'import yaml' >& /dev/null 48 | then 49 | "$PYTHON" ./syntax_checkers/yaml/check_yaml.py test/good.yaml 50 | "$PYTHON" ./syntax_checkers/yaml/check_yaml.py test/bad.yaml 2>&1 \ 51 | | grep 'test/bad.yaml:2' 52 | "$PYTHON" ./syntax_checkers/yaml/check_yaml.py test/unreadable.yaml 2>&1 \ 53 | | grep 'unreadable.yaml' 54 | fi 55 | 56 | if "$PYTHON" -c 'import json' >& /dev/null 57 | then 58 | "$PYTHON" ./syntax_checkers/json/json_tool.py test/good.json 59 | "$PYTHON" ./syntax_checkers/json/json_tool.py test/bad.json 2>&1 \ 60 | | grep 'test/bad.json:2' 61 | "$PYTHON" ./syntax_checkers/json/json_tool.py test/unreadable.json 2>&1 \ 62 | | grep 'unreadable.json' 63 | fi 64 | 65 | "$PYTHON" ./syntax_checkers/cpp/check.py unreadable echo echo 66 | 67 | # Do not run this under Python 2.4. 68 | python3 -m doctest syntax_checkers/*/*.py 69 | 70 | "$PYTHON" ./syntax_checkers/cpp/test.py test/syntastic_config/good.cpp 71 | "$PYTHON" ./syntax_checkers/cpp/test.py test/syntastic_config/bad.cpp 2>&1 \ 72 | | grep 'test/syntastic_config/bad.cpp:3' > /dev/null 73 | 74 | "$PYTHON" ./syntax_checkers/cpp/test.py test/syntastic_config/good.c 75 | "$PYTHON" ./syntax_checkers/cpp/test.py test/syntastic_config/bad.c 2>&1 \ 76 | | grep 'test/syntastic_config/bad.c:3' > /dev/null 77 | 78 | "$PYTHON" ./syntax_checkers/cpp/test.py test/syntastic_config/good_header.h 79 | "$PYTHON" ./syntax_checkers/cpp/test.py test/syntastic_config/good_header.cpp 80 | 81 | "$PYTHON" ./syntax_checkers/cpp/test.py test/syntastic_config/bad_header.h 2>&1 \ 82 | | grep 'test/syntastic_config/bad_header.h:1' > /dev/null 83 | "$PYTHON" ./syntax_checkers/cpp/test.py test/syntastic_config/bad_header.c 2>&1 \ 84 | | grep 'test/syntastic_config/bad_header.c:1' > /dev/null 85 | 86 | # Do not run this under Python 2.4 as it requires the `json` module. 87 | python3 ./syntax_checkers/cpp/test.py test/compile_commands/good.cpp 88 | python3 ./syntax_checkers/cpp/test.py test/compile_commands/bad.cpp 2>&1 \ 89 | | grep 'test/compile_commands/bad.cpp:3' > /dev/null 90 | 91 | # With `CC` or `CXX` composed of multiple arguments. 92 | CC='echo hello world' \ 93 | "$PYTHON" ./syntax_checkers/cpp/test.py test/syntastic_config/good.c \ 94 | | grep 'hello world' 95 | CXX='echo hello world' \ 96 | "$PYTHON" ./syntax_checkers/cpp/test.py test/syntastic_config/good.cpp \ 97 | | grep 'hello world' 98 | 99 | echo -e '\x1b[01;32mOkay\x1b[0m' 100 | --------------------------------------------------------------------------------