|
|
#!/usr/bin/env python3
import glob import os import re import sys
MAX_LINE_LENGTH = 100
# Files with any of these as a substring of their filename are excluded from # consideration. FILES_TO_EXCLUDE = [ '/obj/', '/bin/', '/AssemblyInfo.cs', '/Resource.Designer.cs', 'Shared/Levels.cs']
num_errors = 0
def emit_error(filename, line_num, error): global num_errors num_errors += 1 print('%s:%d: %s' % (filename, line_num, error))
def lint_csharp(filename): with open(filename) as f: for i, line in enumerate(f): line_num = i + 1 line = line[:-1] # Strip trailing newline. if len(line) > MAX_LINE_LENGTH: if not re.match(r'\s*// https?:', line): emit_error(filename, line_num, 'line too long') if re.match(r'\s*//\S', line): emit_error(filename, line_num, 'no space between // and comment') match = re.match(r'\s*const.* (\w+) =', line) if match: identifier = match.group(1) if not re.fullmatch(r'[A-Z_]+', identifier): emit_error(filename, line_num, 'const field %s should be in ALL_CAPS' % identifier) if re.search(r'\t', line): emit_error(filename, line_num, 'illegal \\t character') if re.search(r'\r', line): emit_error(filename, line_num, 'illegal \\r character') if re.search(r'\s+$', line): emit_error(filename, line_num, 'trailing whitespace')
def main(args): this_dir = os.path.dirname(os.path.realpath(__file__)) sneak_root = os.path.join(this_dir, '..', '..') os.chdir(sneak_root)
csharp_files = sorted(glob.glob('**/*.cs', recursive=True)) # Remove generated files (of which there's lots). for exclusion_pattern in FILES_TO_EXCLUDE: csharp_files = [x for x in csharp_files if exclusion_pattern not in x]
for filename in csharp_files: lint_csharp(filename)
print('lint.py checked %d files and found %d errors' % ( len(csharp_files), num_errors))
if num_errors: return 1 return 0
if __name__ == '__main__': sys.exit(main(sys.argv[1:]))
|