2020-02-26 00:14:55 +00:00
|
|
|
#!/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']
|
|
|
|
|
|
|
|
|
2020-02-26 01:42:55 +00:00
|
|
|
num_errors = 0
|
|
|
|
|
|
|
|
|
2020-02-26 00:14:55 +00:00
|
|
|
def emit_error(filename, line_num, error):
|
2020-02-26 01:42:55 +00:00
|
|
|
global num_errors
|
|
|
|
num_errors += 1
|
2020-02-26 00:14:55 +00:00
|
|
|
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')
|
2020-02-26 01:34:19 +00:00
|
|
|
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)
|
2020-02-26 00:14:55 +00:00
|
|
|
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)
|
|
|
|
|
2020-02-26 01:42:55 +00:00
|
|
|
print('checked %d files and found %d errors' % (
|
|
|
|
len(csharp_files), num_errors))
|
|
|
|
|
|
|
|
if num_errors:
|
|
|
|
return 1
|
|
|
|
return 0
|
|
|
|
|
2020-02-26 00:14:55 +00:00
|
|
|
|
|
|
|
if __name__ == '__main__':
|
2020-02-26 01:42:55 +00:00
|
|
|
sys.exit(main(sys.argv[1:]))
|