@@ -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,21 @@ 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
+ found = False
5040
+ for module in module_deps :
5041
+ if deps_name .startswith (module ):
5042
+ found = True
5043
+ if not found :
5044
+ error (filename , linenum , 'build/include' , 4 ,
5045
+ 'Module `' + module_name + '` must not use `' + include + '`' )
5046
+
5032
5047
# We want to ensure that headers appear in the right order:
5033
5048
# 1) for foo.cc, foo.h (preferred location)
5034
5049
# 2) c system files
@@ -5141,7 +5156,7 @@ def _GetTextInside(text, start_pattern):
5141
5156
5142
5157
5143
5158
def CheckLanguage (filename , clean_lines , linenum , file_extension ,
5144
- include_state , nesting_state , error ):
5159
+ include_state , nesting_state , error , module_deps ):
5145
5160
"""Checks rules from the 'C++ language rules' section of cppguide.html.
5146
5161
5147
5162
Some of these rules are hard to test (function overloading, using
@@ -5165,7 +5180,7 @@ def CheckLanguage(filename, clean_lines, linenum, file_extension,
5165
5180
5166
5181
match = _RE_PATTERN_INCLUDE .search (line )
5167
5182
if match :
5168
- CheckIncludeLine (filename , clean_lines , linenum , include_state , error )
5183
+ CheckIncludeLine (filename , clean_lines , linenum , include_state , error , module_deps )
5169
5184
return
5170
5185
5171
5186
# Reset include state across preprocessor directives. This is meant
@@ -6246,7 +6261,7 @@ def CheckForEndl(filename, clean_lines, linenum, error):
6246
6261
error (filename , linenum , 'runtime/endl' , 4 , 'Do not use std::endl' )
6247
6262
6248
6263
def ProcessLine (filename , file_extension , clean_lines , line ,
6249
- include_state , function_state , nesting_state , error ,
6264
+ include_state , function_state , nesting_state , error , module_deps ,
6250
6265
extra_check_functions = []):
6251
6266
"""Processes a single line in the file.
6252
6267
@@ -6276,7 +6291,7 @@ def ProcessLine(filename, file_extension, clean_lines, line,
6276
6291
CheckForMultilineCommentsAndStrings (filename , clean_lines , line , error )
6277
6292
CheckStyle (filename , clean_lines , line , file_extension , nesting_state , error )
6278
6293
CheckLanguage (filename , clean_lines , line , file_extension , include_state ,
6279
- nesting_state , error )
6294
+ nesting_state , error , module_deps )
6280
6295
CheckForNonConstReference (filename , clean_lines , line , nesting_state , error )
6281
6296
CheckForNonStandardConstructs (filename , clean_lines , line ,
6282
6297
nesting_state , error )
@@ -6370,6 +6385,27 @@ def ProcessFileData(filename, file_extension, lines, error,
6370
6385
6371
6386
ResetNolintSuppressions ()
6372
6387
6388
+ # Load module dependencies
6389
+ module_deps_file = os .path .join (os .path .dirname (filename ), 'module_dependencies.txt' )
6390
+ module_deps = []
6391
+ if os .path .isfile (module_deps_file ):
6392
+ with open (module_deps_file , 'r' ) as f :
6393
+ module_deps = f .read ().splitlines ()
6394
+ # strip off comments and whitespace
6395
+ def strip_off_comments (s ):
6396
+ has_comment = s .find ('#' )
6397
+ if has_comment >= 0 :
6398
+ s = s [:has_comment ]
6399
+ s = s .lstrip ().rstrip ()
6400
+ return s
6401
+ module_deps = [ strip_off_comments (module ) for module in module_deps ]
6402
+ # remove empty lines
6403
+ module_deps = [ module for module in module_deps if module ]
6404
+ else :
6405
+ error (filename , 0 , 'build/include' , 4 ,
6406
+ 'module_dependencies.txt not found in `' +
6407
+ os .path .dirname (filename ) + '`' )
6408
+
6373
6409
CheckForCopyright (filename , lines , error )
6374
6410
CheckForFunctionCommentHeaders (filename , lines , error )
6375
6411
ProcessGlobalSuppresions (lines )
@@ -6381,7 +6417,7 @@ def ProcessFileData(filename, file_extension, lines, error,
6381
6417
6382
6418
for line in xrange (clean_lines .NumLines ()):
6383
6419
ProcessLine (filename , file_extension , clean_lines , line ,
6384
- include_state , function_state , nesting_state , error ,
6420
+ include_state , function_state , nesting_state , error , module_deps ,
6385
6421
extra_check_functions )
6386
6422
FlagCxx11Features (filename , clean_lines , line , error )
6387
6423
nesting_state .CheckCompletedBlocks (filename , error )
0 commit comments