@@ -4981,7 +4981,7 @@ def _ClassifyInclude(fileinfo, include, is_system):
4981
4981
4982
4982
4983
4983
4984
- def CheckIncludeLine (filename , clean_lines , linenum , include_state , error ):
4984
+ def CheckIncludeLine (filename , clean_lines , linenum , include_state , error , module_deps ):
4985
4985
"""Check rules that are applicable to #include lines.
4986
4986
4987
4987
Strings on #include lines are NOT removed from elided line, to make
@@ -5029,6 +5029,18 @@ def CheckIncludeLine(filename, clean_lines, linenum, include_state, error):
5029
5029
elif not _THIRD_PARTY_HEADERS_PATTERN .match (include ):
5030
5030
include_state .include_list [- 1 ].append ((include , linenum ))
5031
5031
5032
+ # Check module dependencies
5033
+ module_name = os .path .dirname (filename )
5034
+ has_src = module_name .find ('src/' )
5035
+ if has_src >= 0 :
5036
+ module_name = module_name [has_src + 4 :]
5037
+ deps_name = os .path .dirname (include )
5038
+ if deps_name and module_deps :
5039
+ may_use = any (deps_name .startswith (module ) for module in module_deps )
5040
+ if not may_use :
5041
+ error (filename , linenum , 'build/include' , 4 ,
5042
+ 'Module `' + module_name + '` must not use `' + include + '`' )
5043
+
5032
5044
# We want to ensure that headers appear in the right order:
5033
5045
# 1) for foo.cc, foo.h (preferred location)
5034
5046
# 2) c system files
@@ -5141,7 +5153,7 @@ def _GetTextInside(text, start_pattern):
5141
5153
5142
5154
5143
5155
def CheckLanguage (filename , clean_lines , linenum , file_extension ,
5144
- include_state , nesting_state , error ):
5156
+ include_state , nesting_state , error , module_deps ):
5145
5157
"""Checks rules from the 'C++ language rules' section of cppguide.html.
5146
5158
5147
5159
Some of these rules are hard to test (function overloading, using
@@ -5165,7 +5177,7 @@ def CheckLanguage(filename, clean_lines, linenum, file_extension,
5165
5177
5166
5178
match = _RE_PATTERN_INCLUDE .search (line )
5167
5179
if match :
5168
- CheckIncludeLine (filename , clean_lines , linenum , include_state , error )
5180
+ CheckIncludeLine (filename , clean_lines , linenum , include_state , error , module_deps )
5169
5181
return
5170
5182
5171
5183
# Reset include state across preprocessor directives. This is meant
@@ -6246,7 +6258,7 @@ def CheckForEndl(filename, clean_lines, linenum, error):
6246
6258
error (filename , linenum , 'runtime/endl' , 4 , 'Do not use std::endl' )
6247
6259
6248
6260
def ProcessLine (filename , file_extension , clean_lines , line ,
6249
- include_state , function_state , nesting_state , error ,
6261
+ include_state , function_state , nesting_state , error , module_deps ,
6250
6262
extra_check_functions = []):
6251
6263
"""Processes a single line in the file.
6252
6264
@@ -6276,7 +6288,7 @@ def ProcessLine(filename, file_extension, clean_lines, line,
6276
6288
CheckForMultilineCommentsAndStrings (filename , clean_lines , line , error )
6277
6289
CheckStyle (filename , clean_lines , line , file_extension , nesting_state , error )
6278
6290
CheckLanguage (filename , clean_lines , line , file_extension , include_state ,
6279
- nesting_state , error )
6291
+ nesting_state , error , module_deps )
6280
6292
CheckForNonConstReference (filename , clean_lines , line , nesting_state , error )
6281
6293
CheckForNonStandardConstructs (filename , clean_lines , line ,
6282
6294
nesting_state , error )
@@ -6370,6 +6382,27 @@ def ProcessFileData(filename, file_extension, lines, error,
6370
6382
6371
6383
ResetNolintSuppressions ()
6372
6384
6385
+ # Load module dependencies
6386
+ module_deps_file = os .path .join (os .path .dirname (filename ), 'module_dependencies.txt' )
6387
+ module_deps = []
6388
+ if os .path .isfile (module_deps_file ):
6389
+ with open (module_deps_file , 'r' ) as f :
6390
+ module_deps = f .read ().splitlines ()
6391
+ # strip off comments and whitespace
6392
+ def strip_off_comments (s ):
6393
+ comment_index = s .find ('#' )
6394
+ if comment_index >= 0 :
6395
+ s = s [:comment_index ]
6396
+ s = s .strip ()
6397
+ return s
6398
+ module_deps = [strip_off_comments (module ) for module in module_deps ]
6399
+ # remove empty lines
6400
+ module_deps = [module for module in module_deps if len (module ) != 0 ]
6401
+ else :
6402
+ error (filename , 0 , 'build/include' , 4 ,
6403
+ 'module_dependencies.txt not found in `' +
6404
+ os .path .dirname (filename ) + '`' )
6405
+
6373
6406
CheckForCopyright (filename , lines , error )
6374
6407
CheckForFunctionCommentHeaders (filename , lines , error )
6375
6408
ProcessGlobalSuppresions (lines )
@@ -6381,7 +6414,7 @@ def ProcessFileData(filename, file_extension, lines, error,
6381
6414
6382
6415
for line in xrange (clean_lines .NumLines ()):
6383
6416
ProcessLine (filename , file_extension , clean_lines , line ,
6384
- include_state , function_state , nesting_state , error ,
6417
+ include_state , function_state , nesting_state , error , module_deps ,
6385
6418
extra_check_functions )
6386
6419
FlagCxx11Features (filename , clean_lines , line , error )
6387
6420
nesting_state .CheckCompletedBlocks (filename , error )
0 commit comments