Add presubmit check for header inclusion violation.
authormstarzinger <mstarzinger@chromium.org>
Tue, 18 Aug 2015 16:41:02 +0000 (09:41 -0700)
committerCommit bot <commit-bot@chromium.org>
Tue, 18 Aug 2015 16:41:17 +0000 (16:41 +0000)
This warns about include directives of inline headers within normal
header files. Note that this warning should not close the tree or
prevent the CQ from landing the patch.

R=jkummerow@chromium.org

Review URL: https://codereview.chromium.org/1293273005

Cr-Commit-Position: refs/heads/master@{#30228}

PRESUBMIT.py

index b0b811d..1bcd992 100644 (file)
@@ -141,6 +141,39 @@ def _CheckUnwantedDependencies(input_api, output_api):
   return results
 
 
+def _CheckNoInlineHeaderIncludesInNormalHeaders(input_api, output_api):
+  """Attempts to prevent inclusion of inline headers into normal header
+  files. This tries to establish a layering where inline headers can be
+  included by other inline headers or compilation units only."""
+  file_inclusion_pattern = r'(?!.+-inl\.h).+\.h'
+  include_directive_pattern = input_api.re.compile(r'#include ".+-inl.h"')
+  include_warning = (
+    'You might be including an inline header (e.g. foo-inl.h) within a\n'
+    'normal header (e.g. bar.h) file.  Can you avoid introducing the\n'
+    '#include?  The commit queue will not block on this warning.')
+
+  def FilterFile(affected_file):
+    black_list = (_EXCLUDED_PATHS +
+                  input_api.DEFAULT_BLACK_LIST)
+    return input_api.FilterSourceFile(
+      affected_file,
+      white_list=(file_inclusion_pattern, ),
+      black_list=black_list)
+
+  problems = []
+  for f in input_api.AffectedSourceFiles(FilterFile):
+    local_path = f.LocalPath()
+    for line_number, line in f.ChangedContents():
+      if (include_directive_pattern.search(line)):
+        problems.append(
+          '%s:%d\n    %s' % (local_path, line_number, line.strip()))
+
+  if problems:
+    return [output_api.PresubmitPromptOrNotify(include_warning, problems)]
+  else:
+    return []
+
+
 def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
   """Attempts to prevent use of functions intended only for testing in
   non-testing code. For now this is just a best-effort implementation
@@ -195,6 +228,8 @@ def _CommonChecks(input_api, output_api):
   results.extend(_CheckUnwantedDependencies(input_api, output_api))
   results.extend(
       _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
+  results.extend(
+      _CheckNoInlineHeaderIncludesInNormalHeaders(input_api, output_api))
   return results