@@ -4976,7 +4976,7 @@ def _ClassifyInclude(fileinfo, include, is_system):
4976
4976
4977
4977
4978
4978
4979
- def CheckIncludeLine (filename , clean_lines , linenum , include_state , error ):
4979
+ def CheckIncludeLine (filename , clean_lines , linenum , include_state , error , module_deps ):
4980
4980
"""Check rules that are applicable to #include lines.
4981
4981
4982
4982
Strings on #include lines are NOT removed from elided line, to make
@@ -5024,6 +5024,21 @@ def CheckIncludeLine(filename, clean_lines, linenum, include_state, error):
5024
5024
elif not _THIRD_PARTY_HEADERS_PATTERN .match (include ):
5025
5025
include_state .include_list [- 1 ].append ((include , linenum ))
5026
5026
5027
+ # Check module dependencies
5028
+ module_name = os .path .dirname (filename )
5029
+ has_src = module_name .find ('src/' )
5030
+ if has_src >= 0 :
5031
+ module_name = module_name [has_src + 4 :]
5032
+ deps_name = os .path .dirname (include )
5033
+ if deps_name and module_deps :
5034
+ found = False
5035
+ for module in module_deps :
5036
+ if deps_name .startswith (module ):
5037
+ found = True
5038
+ if not found :
5039
+ error (filename , linenum , 'build/include' , 4 ,
5040
+ 'Module `' + module_name + '` must not use `' + include + '`' )
5041
+
5027
5042
# We want to ensure that headers appear in the right order:
5028
5043
# 1) for foo.cc, foo.h (preferred location)
5029
5044
# 2) c system files
@@ -5136,7 +5151,7 @@ def _GetTextInside(text, start_pattern):
5136
5151
5137
5152
5138
5153
def CheckLanguage (filename , clean_lines , linenum , file_extension ,
5139
- include_state , nesting_state , error ):
5154
+ include_state , nesting_state , error , module_deps ):
5140
5155
"""Checks rules from the 'C++ language rules' section of cppguide.html.
5141
5156
5142
5157
Some of these rules are hard to test (function overloading, using
@@ -5160,7 +5175,7 @@ def CheckLanguage(filename, clean_lines, linenum, file_extension,
5160
5175
5161
5176
match = _RE_PATTERN_INCLUDE .search (line )
5162
5177
if match :
5163
- CheckIncludeLine (filename , clean_lines , linenum , include_state , error )
5178
+ CheckIncludeLine (filename , clean_lines , linenum , include_state , error , module_deps )
5164
5179
return
5165
5180
5166
5181
# Reset include state across preprocessor directives. This is meant
@@ -6241,7 +6256,7 @@ def CheckForEndl(filename, clean_lines, linenum, error):
6241
6256
error (filename , linenum , 'runtime/endl' , 4 , 'Do not use std::endl' )
6242
6257
6243
6258
def ProcessLine (filename , file_extension , clean_lines , line ,
6244
- include_state , function_state , nesting_state , error ,
6259
+ include_state , function_state , nesting_state , error , module_deps ,
6245
6260
extra_check_functions = []):
6246
6261
"""Processes a single line in the file.
6247
6262
@@ -6271,7 +6286,7 @@ def ProcessLine(filename, file_extension, clean_lines, line,
6271
6286
CheckForMultilineCommentsAndStrings (filename , clean_lines , line , error )
6272
6287
CheckStyle (filename , clean_lines , line , file_extension , nesting_state , error )
6273
6288
CheckLanguage (filename , clean_lines , line , file_extension , include_state ,
6274
- nesting_state , error )
6289
+ nesting_state , error , module_deps )
6275
6290
CheckForNonConstReference (filename , clean_lines , line , nesting_state , error )
6276
6291
CheckForNonStandardConstructs (filename , clean_lines , line ,
6277
6292
nesting_state , error )
@@ -6365,6 +6380,23 @@ def ProcessFileData(filename, file_extension, lines, error,
6365
6380
6366
6381
ResetNolintSuppressions ()
6367
6382
6383
+ # Load module dependencies
6384
+ module_deps_file = os .path .join (os .path .dirname (filename ), 'module_dependencies.txt' )
6385
+ module_deps = []
6386
+ if os .path .isfile (module_deps_file ):
6387
+ with open (module_deps_file , 'r' ) as f :
6388
+ module_deps = f .read ().splitlines ()
6389
+ # strip off comments and whitespace
6390
+ def strip_off_comments (s ):
6391
+ has_comment = s .find ('#' )
6392
+ if has_comment >= 0 :
6393
+ s = s [:has_comment ]
6394
+ s = s .lstrip ().rstrip ()
6395
+ return s
6396
+ module_deps = [ strip_off_comments (module ) for module in module_deps ]
6397
+ # remove empty lines
6398
+ module_deps = [ module for module in module_deps if module ]
6399
+
6368
6400
CheckForCopyright (filename , lines , error )
6369
6401
CheckForFunctionCommentHeaders (filename , lines , error )
6370
6402
ProcessGlobalSuppresions (lines )
@@ -6376,7 +6408,7 @@ def ProcessFileData(filename, file_extension, lines, error,
6376
6408
6377
6409
for line in xrange (clean_lines .NumLines ()):
6378
6410
ProcessLine (filename , file_extension , clean_lines , line ,
6379
- include_state , function_state , nesting_state , error ,
6411
+ include_state , function_state , nesting_state , error , module_deps ,
6380
6412
extra_check_functions )
6381
6413
FlagCxx11Features (filename , clean_lines , line , error )
6382
6414
nesting_state .CheckCompletedBlocks (filename , error )
0 commit comments