diff options
Diffstat (limited to 'test')
-rwxr-xr-x | test/script/block-padding-checker | 117 | ||||
-rwxr-xr-x | test/script/custom-linting-rules | 15 |
2 files changed, 129 insertions, 3 deletions
diff --git a/test/script/block-padding-checker b/test/script/block-padding-checker new file mode 100755 index 00000000..b13c9b92 --- /dev/null +++ b/test/script/block-padding-checker @@ -0,0 +1,117 @@ +#!/usr/bin/env python +""" +This script checks for missing or forbidden blank lines before or after +particular Vim commands. This script ensures that VimL scripts are padded +correctly, so they are easier to read. +""" + +import sys +import re + +INDENTATION_RE = re.compile(r'^ *') +COMMENT_LINE_RE = re.compile(r'^ *"') +COMMAND_RE = re.compile(r'^ *([a-zA-Z]+)') + +START_BLOCKS = set(['if', 'for', 'while', 'try', 'function']) +END_BLOCKS = set(['endif', 'endfor', 'endwhile', 'endtry', 'endfunction']) +MIDDLE_BLOCKS = set(['else', 'elseif', 'catch', 'finally']) +TERMINATORS = set(['return', 'throw']) + +WHITESPACE_BEFORE_SET = START_BLOCKS | TERMINATORS +WHITESPACE_FORBIDDEN_BEFORE_SET = END_BLOCKS | MIDDLE_BLOCKS +WHITESPACE_AFTER_SET = END_BLOCKS +WHITESPACE_FORBIDDEN_AFTER_SET = START_BLOCKS | MIDDLE_BLOCKS + + +def remove_comment_lines(line_iter): + for line_number, line in enumerate(line_iter, 1): + if not COMMENT_LINE_RE.match(line): + yield (line_number, line) + + +def check_lines(line_iter): + previous_indentation_level = None + previous_command = None + previous_line_blank = False + + for line_number, line in remove_comment_lines(line_iter): + if len(line) == 0: + # Check for commands where we shouldn't have blank lines after + # them, like `else` or the start of blocks like `function`. + if ( + previous_command is not None + and previous_command in WHITESPACE_FORBIDDEN_AFTER_SET + ): + yield ( + line_number, + 'Blank line forbidden after `%s`' % (command,) + ) + + previous_line_blank = True + previous_command = None + else: + indentation_level = INDENTATION_RE.match(line).end() + command_match = COMMAND_RE.match(line) + + if command_match: + command = command_match.group(1) + + # Check for commands requiring blank lines before them, if they + # aren't at the start of a block. + if ( + command in WHITESPACE_BEFORE_SET + and previous_indentation_level is not None + and indentation_level == previous_indentation_level + and previous_line_blank is False + ): + yield ( + line_number, + 'Blank line required before `%s`' % (command,) + ) + + # Check for commands where we shouldn't have blank lines before + # them, like `else` or the end of blocks like `endfunction`. + if ( + command in WHITESPACE_FORBIDDEN_BEFORE_SET + and previous_line_blank is True + ): + yield ( + line_number - 1, + 'Blank line forbidden before `%s`' % (command,) + ) + + # Check for commands requiring blank lines after them, if they + # aren't at the end of a block. + if ( + previous_command is not None + and previous_command in WHITESPACE_AFTER_SET + and previous_indentation_level is not None + and indentation_level == previous_indentation_level + and previous_line_blank is False + ): + yield ( + line_number - 1, + 'Blank line required after `%s`' % (command,) + ) + + previous_command = command + previous_line_blank = False + previous_indentation_level = indentation_level + + +def main(): + status = 0 + + for filename in sys.argv[1:]: + with open(filename) as vim_file: + line_iter = (line.rstrip() for line in vim_file) + + for line_number, message in check_lines(line_iter): + print('%s:%d %s' % (filename, line_number, message)) + status = 1 + + sys.exit(status) + + +if __name__ == "__main__": + main() diff --git a/test/script/custom-linting-rules b/test/script/custom-linting-rules index 7aafe995..77e87db4 100755 --- a/test/script/custom-linting-rules +++ b/test/script/custom-linting-rules @@ -60,10 +60,10 @@ check_errors() { for directory in "${directories[@]}"; do # shellcheck disable=SC2086 - while IFS= read -r match; do + while read -r; do RETURN_CODE=1 - echo "$match $message" - done < <(grep -n "$regex" $include_arg "$directory"/**/*.vim \ + echo "$REPLY $message" + done < <(grep -H -n "$regex" $include_arg "$directory"/**/*.vim \ | grep -v 'no-custom-checks' \ | grep -o '^[^:]\+:[0-9]\+' \ | sed 's:^\./::') @@ -126,4 +126,13 @@ check_errors '\(!=.\?\|isnot\) type(\[\])' "Use 'isnot v:t_list' instead" check_errors '\(!=.\?\|isnot\) type({})' "Use 'isnot v:t_dict' instead" check_errors '\(!=.\?\|isnot\) type(function([^)]\+))' "Use 'isnot v:t_func' instead" +# Run a Python script to find lines that require padding around them. For +# users without Python installed, we'll skip these checks. Travis CI will run +# the script. +if command -v python > /dev/null; then + if ! test/script/block-padding-checker "$directory"/**/*.vim; then + RETURN_CODE=1 + fi +fi + exit $RETURN_CODE |