aboutsummaryrefslogtreecommitdiff
path: root/lib/sanitizer_common/scripts/litlint.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sanitizer_common/scripts/litlint.py')
-rwxr-xr-xlib/sanitizer_common/scripts/litlint.py72
1 files changed, 72 insertions, 0 deletions
diff --git a/lib/sanitizer_common/scripts/litlint.py b/lib/sanitizer_common/scripts/litlint.py
new file mode 100755
index 000000000000..1e78448b63d4
--- /dev/null
+++ b/lib/sanitizer_common/scripts/litlint.py
@@ -0,0 +1,72 @@
+#!/usr/bin/python
+#
+# litlint
+#
+# Ensure RUN commands in lit tests are free of common errors.
+#
+# If any errors are detected, litlint returns a nonzero exit code.
+#
+
+import optparse
+import re
+import sys
+
+# Compile regex once for all files
+runRegex = re.compile(r'(?<!-o)(?<!%run) %t\s')
+
+def LintLine(s):
+ """ Validate a line
+
+ Args:
+ s: str, the line to validate
+
+ Returns:
+ Returns an error message and a 1-based column number if an error was
+ detected, otherwise (None, None).
+ """
+
+ # Check that RUN command can be executed with an emulator
+ m = runRegex.search(s)
+ if m:
+ start, end = m.span()
+ return ('missing %run before %t', start + 2)
+
+ # No errors
+ return (None, None)
+
+
+def LintFile(p):
+ """ Check that each RUN command can be executed with an emulator
+
+ Args:
+ p: str, valid path to a file
+
+ Returns:
+ The number of errors detected.
+ """
+ errs = 0
+ with open(p, 'r') as f:
+ for i, s in enumerate(f.readlines(), start=1):
+ msg, col = LintLine(s)
+ if msg != None:
+ errs += 1
+ errorMsg = 'litlint: {}:{}:{}: error: {}.\n{}{}\n'
+ arrow = (col-1) * ' ' + '^'
+ sys.stderr.write(errorMsg.format(p, i, col, msg, s, arrow))
+ return errs
+
+
+if __name__ == "__main__":
+ # Parse args
+ parser = optparse.OptionParser()
+ parser.add_option('--filter') # ignored
+ (options, filenames) = parser.parse_args()
+
+ # Lint each file
+ errs = 0
+ for p in filenames:
+ errs += LintFile(p)
+
+ # If errors, return nonzero
+ if errs > 0:
+ sys.exit(1)