#!/usr/bin/env python # Copyright (c) 2016 Red Hat, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at: # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from __future__ import print_function import email import getopt import re import sys __errors = 0 __warnings = 0 print_file_name = None checking_file = False def print_file(): global print_file_name if print_file_name: print("In file %s" % print_file_name) print_file_name = None def print_error(message, lineno=None): global __errors print_file() if lineno is not None: print("E(%d): %s" % (lineno, message)) else: print("E: %s" % (message)) __errors = __errors + 1 def print_warning(message, lineno=None): global __warnings print_file() if lineno: print("W(%d): %s" % (lineno, message)) else: print("W: %s" % (message)) __warnings = __warnings + 1 __regex_added_line = re.compile(r'^\+{1,2}[^\+][\w\W]*') __regex_subtracted_line = re.compile(r'^\-{1,2}[^\-][\w\W]*') __regex_leading_with_whitespace_at_all = re.compile(r'^\s+') __regex_leading_with_spaces = re.compile(r'^ +[\S]+') __regex_trailing_whitespace = re.compile(r'[^\S]+$') __regex_single_line_feed = re.compile(r'^\f$') __regex_for_if_missing_whitespace = re.compile(r' +(if|for|while)[\(]') __regex_for_if_too_much_whitespace = re.compile(r' +(if|for|while) +[\(]') __regex_for_if_parens_whitespace = \ re.compile(r' +(if|for|while) \( +[\s\S]+\)') __regex_is_for_if_single_line_bracket = \ re.compile(r'^ +(if|for|while) \(.*\)') __regex_ends_with_bracket = \ re.compile(r'[^\s]\) {(\s+/\*[\s\Sa-zA-Z0-9\.,\?\*/+-]*)?$') __regex_ptr_declaration_missing_whitespace = re.compile(r'[a-zA-Z0-9]\*') skip_leading_whitespace_check = False skip_trailing_whitespace_check = False skip_block_whitespace_check = False skip_signoff_check = False # Don't enforce character limit on files that include these characters in their # name, as they may have legitimate reasons to have longer lines. # # Python isn't checked as flake8 performs these checks during build. line_length_blacklist = ['.am', '.at', 'etc', '.in', '.m4', '.mk', '.patch', '.py'] def is_subtracted_line(line): """Returns TRUE if the line in question has been removed.""" return __regex_subtracted_line.search(line) is not None def is_added_line(line): """Returns TRUE if the line in question is an added line. """ global checking_file return __regex_added_line.search(line) is not None or checking_file def added_line(line): """Returns the line formatted properly by removing diff syntax""" global checking_file if not checking_file: return line[1:] return line def leading_whitespace_is_spaces(line): """Returns TRUE if the leading whitespace in added lines is spaces """ if skip_leading_whitespace_check: return True if (__regex_leading_with_whitespace_at_all.search(line) is not None and __regex_single_line_feed.search(line) is None): return __regex_leading_with_spaces.search(line) is not None return True def trailing_whitespace_or_crlf(line): """Returns TRUE if the trailing characters is whitespace """ if skip_trailing_whitespace_check: return False return (__regex_trailing_whitespace.search(line) is not None and __regex_single_line_feed.search(line) is None) def if_and_for_whitespace_checks(line): """Return TRUE if there is appropriate whitespace after if, for, while """ if skip_block_whitespace_check: return True if (__regex_for_if_missing_whitespace.search(line) is not None or __regex_for_if_too_much_whitespace.search(line) is not None or __regex_for_if_parens_whitespace.search(line)): return False return True def if_and_for_end_with_bracket_check(line): """Return TRUE if there is not a bracket at the end of an if, for, while block which fits on a single line ie: 'if (foo)'""" def balanced_parens(line): """This is a rather naive counter - it won't deal with quotes""" balance = 0 for letter in line: if letter == '(': balance += 1 elif letter == ')': balance -= 1 return balance == 0 if __regex_is_for_if_single_line_bracket.search(line) is not None: if not balanced_parens(line): return True if __regex_ends_with_bracket.search(line) is None: return False return True def pointer_whitespace_check(line): """Return TRUE if there is no space between a pointer name and the asterisk that denotes this is a apionter type, ie: 'struct foo*'""" return __regex_ptr_declaration_missing_whitespace.search(line) is not None def line_length_check(line): """Return TRUE if the line length is too long""" if len(line) > 79: return True return False checks = [ {'regex': None, 'match_name': lambda x: not any([fmt in x for fmt in line_length_blacklist]), 'check': lambda x: line_length_check(x), 'print': lambda x: print_warning("Line is greater than 79-characters long", x)}, {'regex': '$(?