Index: PRESUBMIT.py |
diff --git a/PRESUBMIT.py b/PRESUBMIT.py |
index 3e18813a589db12b25e0da7f0e93b7217e83e83b..ed46056be99006a882fd2e781351bfbc0a2a1436 100644 |
--- a/PRESUBMIT.py |
+++ b/PRESUBMIT.py |
@@ -1062,6 +1062,92 @@ def _CheckJavaStyle(input_api, output_api): |
input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml') |
+def _StripCommentsAndStrings(input_api, s): |
+ """Remove comments, replace string literals by a single token.""" |
+ |
+ s = input_api.re.sub(r'\r\n', r'\n', s) # Normalize line ends. |
+ s = input_api.re.sub(r'\\\n', r'', s) # Continue lines ending in backslash. |
+ |
+ out = '' |
+ i = 0 |
+ while i < len(s): |
+ c = s[i] |
+ |
+ if c == '/': |
+ mo = input_api.re.match(r'//.*', s[i:]) |
+ if mo: |
+ i += len(mo.group(0)) |
+ continue |
+ mo = input_api.re.match(r'/\*.*?\*/', s[i:], input_api.re.DOTALL) |
+ if mo: |
+ i += len(mo.group(0)) |
+ continue |
+ |
+ if c == "'": |
+ mo = input_api.re.match(r"'((\\\\)|(\\')|[^']+?)'", s[i:]) |
+ if not mo: |
+ raise Exception('bad char: ' + s[i:]) |
+ i += len(mo.group(0)) |
+ out += ' CHAR_LITERAL ' |
+ continue |
+ |
+ if c == '"': |
+ mo = input_api.re.match(r'".*?(?<!\\)(\\\\)*"', s[i:]) |
+ if not mo: |
+ raise Exception('bad string: ' + s[i:]) |
+ i += len(mo.group(0)) |
+ out += ' STRING_LITERAL ' |
+ continue |
+ |
+ out += c |
+ i += 1 |
+ |
+ return out |
+ |
M-A Ruel
2014/06/18 19:35:11
2 lines between file level symbols
Thiemo Nagel
2014/06/24 12:07:38
Done.
|
+def _CheckContradictoryNotreachedUse(input_api, output_api): |
+ file_inclusion_pattern = ( |
+ r".+\.c$", r".+\.cc$", r".+\.cpp$", r".+\.h$", r".+\.hpp$" ) |
M-A Ruel
2014/06/18 19:35:11
.m and .mm and .inl
Thiemo Nagel
2014/06/24 12:07:38
Done.
|
+ black_list = (_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST) |
+ file_filter = lambda f: input_api.FilterSourceFile( |
+ f, white_list=file_inclusion_pattern, black_list=black_list) |
+ results = [] |
+ for fpath in input_api.AffectedFiles(file_filter=file_filter): |
+ results += _CheckContradictoryNotreachedUseInFile(input_api, fpath) |
M-A Ruel
2014/06/18 19:35:11
use extend()
Thiemo Nagel
2014/06/24 12:07:38
Done.
|
+ return [ output_api.PresubmitPromptWarning(r) for r in results ] |
M-A Ruel
2014/06/18 19:35:11
no space around []
or if you want:
return map(outp
Thiemo Nagel
2014/06/24 12:07:38
Done.
|
+ |
+def _CheckContradictoryNotreachedUseInFile(input_api, f): |
+ style_url = ( |
+ 'http://www.chromium.org/developers/coding-style' |
+ '#TOC-CHECK-DCHECK-and-NOTREACHED-') |
+ contents = f.NewContents() |
+ text = '' |
+ for line in contents: |
M-A Ruel
2014/06/18 19:35:11
You don't use contents after and you just join so:
Thiemo Nagel
2014/06/24 12:07:38
Done.
|
+ text += line + '\n' |
+ text = _StripCommentsAndStrings(input_api, text) |
+ |
+ results = [] |
+ while True: |
+ mo = input_api.re.search( |
+ r'[ \t]*NOTREACHED\(\s*\).*?;(?P<between>.*?)((\bbreak\b)|})', |
M-A Ruel
2014/06/18 19:35:11
align arguments at +4
Thiemo Nagel
2014/06/24 12:07:38
Done.
|
+ text, input_api.re.DOTALL) |
+ # TODO(tnagel): Catch loops inside which NOTREACHED() is followed by break. |
+ if not mo: |
+ break |
+ text = text[mo.end():] |
+ if input_api.re.match(r'[\s;]*[\s;]*$', mo.group('between'), |
+ input_api.re.DOTALL): |
+ continue |
+ excerpt = mo.group(0).rstrip() |
+ if len(excerpt) > 100: |
+ excerpt = excerpt[:100] + ' ...' |
+ results.append( |
+ '%s: NOTREACHED() may only be used at end-of-block ' |
+ 'but is followed by code.\n%s\n' |
+ 'Offending section (comments/strings possibly stripped):\n%s' |
+ % (f, style_url, excerpt)) |
+ return results |
+ |
+ |
def _CommonChecks(input_api, output_api): |
"""Checks common to both upload and commit.""" |
results = [] |
@@ -1097,6 +1183,7 @@ def _CommonChecks(input_api, output_api): |
results.extend(_CheckForAnonymousVariables(input_api, output_api)) |
results.extend(_CheckCygwinShell(input_api, output_api)) |
results.extend(_CheckUserActionUpdate(input_api, output_api)) |
+ results.extend(_CheckContradictoryNotreachedUse(input_api, output_api)) |
if any('PRESUBMIT.py' == f.LocalPath() for f in input_api.AffectedFiles()): |
results.extend(input_api.canned_checks.RunUnitTestsInDirectory( |