summaryrefslogtreecommitdiffstats
path: root/PRESUBMIT.py
diff options
context:
space:
mode:
authormarja@chromium.org <marja@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-11-14 11:40:28 +0000
committermarja@chromium.org <marja@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-11-14 11:40:28 +0000
commitcf9b78fd1ef4310e149a37a525f1871241b21eef (patch)
tree963e5faf9a59965b5a4c8ad2c7a857bb237f69dc /PRESUBMIT.py
parent840c2caee4ae7f9a892b4b647561d513771a7906 (diff)
downloadchromium_src-cf9b78fd1ef4310e149a37a525f1871241b21eef.zip
chromium_src-cf9b78fd1ef4310e149a37a525f1871241b21eef.tar.gz
chromium_src-cf9b78fd1ef4310e149a37a525f1871241b21eef.tar.bz2
PRESUBMIT.py: Check #include file order.
BUG=NONE Review URL: https://codereview.chromium.org/11364156 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@167654 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'PRESUBMIT.py')
-rw-r--r--PRESUBMIT.py123
1 files changed, 123 insertions, 0 deletions
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index 08f3452..4ddc09f 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -37,6 +37,11 @@ _TEST_ONLY_WARNING = (
'Email joi@chromium.org if you have questions.')
+_INCLUDE_ORDER_WARNING = (
+ 'Your #include order seems to be broken. Send mail to\n'
+ 'marja@chromium.org if this is not the case.')
+
+
_BANNED_OBJC_FUNCTIONS = (
(
'addTrackingRect:',
@@ -500,6 +505,123 @@ def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
return results
+def _CheckIncludeOrderForScope(scope, input_api, file_path, changed_linenums):
+ """Checks that the lines in scope occur in the right order.
+
+ 1. C system files in alphabetical order
+ 2. C++ system files in alphabetical order
+ 3. Project's .h files
+ """
+
+ c_system_include_pattern = input_api.re.compile(r'\s*#include <.*\.h>')
+ cpp_system_include_pattern = input_api.re.compile(r'\s*#include <.*>')
+ custom_include_pattern = input_api.re.compile(r'\s*#include ".*')
+
+ C_SYSTEM_INCLUDES, CPP_SYSTEM_INCLUDES, CUSTOM_INCLUDES = range(3)
+
+ state = C_SYSTEM_INCLUDES
+
+ previous_line = ''
+ problem_linenums = []
+ for line_num, line in scope:
+ if c_system_include_pattern.match(line):
+ if state != C_SYSTEM_INCLUDES:
+ problem_linenums.append(line_num)
+ elif previous_line and previous_line > line:
+ problem_linenums.append(line_num)
+ elif cpp_system_include_pattern.match(line):
+ if state == C_SYSTEM_INCLUDES:
+ state = CPP_SYSTEM_INCLUDES
+ elif state == CUSTOM_INCLUDES:
+ problem_linenums.append(line_num)
+ elif previous_line and previous_line > line:
+ problem_linenums.append(line_num)
+ elif custom_include_pattern.match(line):
+ if state != CUSTOM_INCLUDES:
+ state = CUSTOM_INCLUDES
+ elif previous_line and previous_line > line:
+ problem_linenums.append(line_num)
+ else:
+ problem_linenums.append(line_num)
+ previous_line = line
+
+ warnings = []
+ for line_num in problem_linenums:
+ if line_num in changed_linenums or line_num - 1 in changed_linenums:
+ warnings.append(' %s:%d' % (file_path, line_num))
+ return warnings
+
+
+def _CheckIncludeOrderInFile(input_api, output_api, f, is_source,
+ changed_linenums):
+ """Checks the #include order for the given file f."""
+
+ include_pattern = input_api.re.compile(r'\s*#include.*')
+ if_pattern = input_api.re.compile(r'\s*#if.*')
+ endif_pattern = input_api.re.compile(r'\s*#endif.*')
+
+ contents = f.NewContents()
+ warnings = []
+ line_num = 0
+
+ # Handle the special first include for source files.
+ if is_source:
+ for line in contents:
+ line_num += 1
+ if include_pattern.match(line):
+ expected = '#include "%s"' % f.LocalPath().replace('.cc', '.h')
+ if line != expected:
+ # Maybe there was no special first include, and that's fine. Process
+ # the line again along with the normal includes.
+ line_num -= 1
+ break
+
+ # Split into scopes: Each region between #if and #endif is its own scope.
+ scopes = []
+ current_scope = []
+ for line in contents[line_num:]:
+ line_num += 1
+ if if_pattern.match(line) or endif_pattern.match(line):
+ scopes.append(current_scope)
+ current_scope = []
+ elif include_pattern.match(line):
+ current_scope.append((line_num, line))
+ scopes.append(current_scope)
+
+ for scope in scopes:
+ warnings.extend(_CheckIncludeOrderForScope(scope, input_api, f.LocalPath(),
+ changed_linenums))
+ return warnings
+
+
+def _CheckIncludeOrder(input_api, output_api):
+ """Checks that the #include order is correct.
+
+ 1. The corresponding header for source files.
+ 2. C system files in alphabetical order
+ 3. C++ system files in alphabetical order
+ 4. Project's .h files in alphabetical order
+
+ Each region between #if and #endif follows these rules separately.
+ """
+
+ warnings = []
+ for f in input_api.AffectedFiles():
+ changed_linenums = set([line_num for line_num, _ in f.ChangedContents()])
+ if f.LocalPath().endswith('.cc'):
+ warnings = _CheckIncludeOrderInFile(input_api, output_api, f, True,
+ changed_linenums)
+ elif f.LocalPath().endswith('.h'):
+ warnings = _CheckIncludeOrderInFile(input_api, output_api, f, False,
+ changed_linenums)
+
+ results = []
+ if warnings:
+ results.append(output_api.PresubmitPromptWarning(_INCLUDE_ORDER_WARNING,
+ warnings))
+ return results
+
+
def _CommonChecks(input_api, output_api):
"""Checks common to both upload and commit."""
results = []
@@ -518,6 +640,7 @@ def _CommonChecks(input_api, output_api):
results.extend(_CheckUnwantedDependencies(input_api, output_api))
results.extend(_CheckFilePermissions(input_api, output_api))
results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
+ results.extend(_CheckIncludeOrder(input_api, output_api))
return results