diff options
author | tnagel@chromium.org <tnagel@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-06-25 11:55:21 +0000 |
---|---|---|
committer | tnagel@chromium.org <tnagel@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-06-25 11:55:21 +0000 |
commit | 264246a7e8ab75ef208ff9b10a33e72facba61d3 (patch) | |
tree | 1e98c41989a9f70b825a4842d404f1625fd4569b /PRESUBMIT.py | |
parent | 3e9b1984836264a07fe568fefd99a767a66de3ff (diff) | |
download | chromium_src-264246a7e8ab75ef208ff9b10a33e72facba61d3.zip chromium_src-264246a7e8ab75ef208ff9b10a33e72facba61d3.tar.gz chromium_src-264246a7e8ab75ef208ff9b10a33e72facba61d3.tar.bz2 |
Add PRESUBMIT.py warning for contradictory NOTREACHED() use.
As recently discussed on chromium-dev [1] and subsequently incorporated into the
Chromium Coding Style [2], NOTREACHED() followed by code is an anti-pattern.
This CL lets PRESUBMIT.py detect most of these cases and print a warning to the
developer.
[1] https://groups.google.com/a/chromium.org/d/msg/chromium-dev/c2X0D1Z6X2o/ddkFLqQP0P0J
[2] http://www.chromium.org/developers/coding-style#TOC-CHECK-DCHECK-and-NOTREACHED-
BUG=none
Review URL: https://codereview.chromium.org/344563003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@279681 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'PRESUBMIT.py')
-rw-r--r-- | PRESUBMIT.py | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/PRESUBMIT.py b/PRESUBMIT.py index c2a4c5c..0fe2e17 100644 --- a/PRESUBMIT.py +++ b/PRESUBMIT.py @@ -1229,6 +1229,94 @@ def _CheckNoDeprecatedCSS(input_api, output_api): (fpath.LocalPath(), line_num, deprecated_value, value))) return results + +def _StripCommentsAndStrings(input_api, s): + """Remove comments, replace string literals by a single token. Requires that + input data is formatted with unix-style 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 + + +def _CheckContradictoryNotreachedUse(input_api, output_api): + file_inclusion_pattern = ( + r".+\.c$", r".+\.cc$", r".+\.cpp$", r".+\.h$", r".+\.hpp$", r".+\.inl$", + r".+\.m$", r".+\.mm$" ) + 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.extend(_CheckContradictoryNotreachedUseInFile(input_api, fpath)) + return [output_api.PresubmitPromptWarning(r) for r in results] + + +def _CheckContradictoryNotreachedUseInFile(input_api, f): + style_url = ( + 'http://chromium.org/developers/coding-style' + '#TOC-CHECK-DCHECK-and-NOTREACHED-') + contents = f.NewContents() + text = ''.join(line + '\n' for line in f.NewContents()) + text = _StripCommentsAndStrings(input_api, text) + + results = [] + while True: + # Capture text between NOTREACHED(); and the next closing brace or "break". + mo = input_api.re.search( + r'[ \t]*NOTREACHED\(\s*\).*?;(?P<between>.*?)((\bbreak\b)|})', + 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;]*$', mo.group('between'), input_api.re.DOTALL): + continue + excerpt = mo.group(0).rstrip() + if len(excerpt) > 100: + excerpt = excerpt[:100] + ' \u2026' # ellipsis + 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 = [] @@ -1266,6 +1354,7 @@ def _CommonChecks(input_api, output_api): results.extend(_CheckUserActionUpdate(input_api, output_api)) results.extend(_CheckNoDeprecatedCSS(input_api, output_api)) results.extend(_CheckParseErrors(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( |