blob: 1e78448b63d4d58962ded8f033d7a32378c50886 [file] [log] [blame]
Stephen Hines2d1fdb22014-05-28 23:58:16 -07001#!/usr/bin/python
2#
3# litlint
4#
5# Ensure RUN commands in lit tests are free of common errors.
6#
7# If any errors are detected, litlint returns a nonzero exit code.
8#
9
10import optparse
11import re
12import sys
13
14# Compile regex once for all files
15runRegex = re.compile(r'(?<!-o)(?<!%run) %t\s')
16
17def LintLine(s):
18 """ Validate a line
19
20 Args:
21 s: str, the line to validate
22
23 Returns:
24 Returns an error message and a 1-based column number if an error was
25 detected, otherwise (None, None).
26 """
27
28 # Check that RUN command can be executed with an emulator
29 m = runRegex.search(s)
30 if m:
31 start, end = m.span()
32 return ('missing %run before %t', start + 2)
33
34 # No errors
35 return (None, None)
36
37
38def LintFile(p):
39 """ Check that each RUN command can be executed with an emulator
40
41 Args:
42 p: str, valid path to a file
43
44 Returns:
45 The number of errors detected.
46 """
47 errs = 0
48 with open(p, 'r') as f:
49 for i, s in enumerate(f.readlines(), start=1):
50 msg, col = LintLine(s)
51 if msg != None:
52 errs += 1
53 errorMsg = 'litlint: {}:{}:{}: error: {}.\n{}{}\n'
54 arrow = (col-1) * ' ' + '^'
55 sys.stderr.write(errorMsg.format(p, i, col, msg, s, arrow))
56 return errs
57
58
59if __name__ == "__main__":
60 # Parse args
61 parser = optparse.OptionParser()
62 parser.add_option('--filter') # ignored
63 (options, filenames) = parser.parse_args()
64
65 # Lint each file
66 errs = 0
67 for p in filenames:
68 errs += LintFile(p)
69
70 # If errors, return nonzero
71 if errs > 0:
72 sys.exit(1)