mirror of
https://github.com/dense-analysis/ale.git
synced 2025-12-26 14:01:10 +08:00
Improve ALE project style checking
* The project style linter now runs while you type. * Now the scripts for checking the project require blank lines. * Many style issues have been found and fixed.
This commit is contained in:
117
test/script/block-padding-checker
Executable file
117
test/script/block-padding-checker
Executable file
@@ -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()
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user