5252import sys
5353import unicodedata
5454
55+ # Files with any of these extensions are considered to be
56+ # header files (and will undergo different style checks).
57+ # This set can be extended by using the --headers
58+ # option (also supported in CPPLINT.cfg)
59+ _header_extensions = ['h' , 'hpp' , 'hxx' , 'h++' , 'cuh' ]
60+ _nonheader_extensions = ['c' , 'cc' , 'cpp' , 'cxx' , 'c++' , 'cu' ]
61+
62+
5563# The allowed extensions for file names
5664# This is set by --extensions flag.
57- _valid_extensions = set (['c' , 'cc' , 'cpp' , 'cxx' , 'c++' , 'h' , 'hpp' , 'hxx' ,
58- 'h++' ])
65+ _valid_extensions = set (_nonheader_extensions + _header_extensions )
66+
67+ # files with this suffix before the extension will be treated as test files
68+ _test_suffixes = set (['_unittest' , '_test' , '_regtest' ])
5969
6070_USAGE = """
6171Syntax: cpplint.py [--verbose=#] [--output=vs7] [--filter=-x,+y,...]
@@ -1073,7 +1083,7 @@ def BaseName(self):
10731083 return self .Split ()[1 ]
10741084
10751085 def Extension (self ):
1076- """File extension - text following the final period."""
1086+ """File extension - text following the final period, includes that period ."""
10771087 return self .Split ()[2 ]
10781088
10791089 def NoExtension (self ):
@@ -1800,25 +1810,26 @@ def CheckHeaderFileIncluded(filename, include_state, error):
18001810 """Logs an error if a .cc file does not include its header."""
18011811
18021812 # Do not check test files
1803- if filename . endswith ( '_test.cc' ) or filename . endswith ( '_unittest.cc' ):
1813+ if _IsTestFilename ( filename ):
18041814 return
18051815
18061816 fileinfo = FileInfo (filename )
1807- headerfile = filename [0 :len (filename ) - 2 ] + 'h'
1808- if not os .path .exists (headerfile ):
1809- return
1810- headername = FileInfo (headerfile ).RepositoryName ()
1811- first_include = 0
1812- for section_list in include_state .include_list :
1813- for f in section_list :
1814- if headername in f [0 ] or f [0 ] in headername :
1815- return
1816- if not first_include :
1817- first_include = f [1 ]
1817+ for ext in _header_extensions :
1818+ headerfile = filename [:filename .rfind ('.' ) + 1 ] + ext
1819+ if not os .path .exists (headerfile ):
1820+ continue
1821+ headername = FileInfo (headerfile ).RepositoryName ()
1822+ first_include = None
1823+ for section_list in include_state .include_list :
1824+ for f in section_list :
1825+ if headername in f [0 ] or f [0 ] in headername :
1826+ return
1827+ if not first_include :
1828+ first_include = f [1 ]
18181829
1819- error (filename , first_include , 'build/include' , 5 ,
1820- '%s should include its header file %s' % (fileinfo .RepositoryName (),
1821- headername ))
1830+ error (filename , first_include , 'build/include' , 5 ,
1831+ '%s should include its header file %s' % (fileinfo .RepositoryName (),
1832+ headername ))
18221833
18231834
18241835def CheckForBadCharacters (filename , lines , error ):
@@ -4459,7 +4470,7 @@ def CheckStyle(filename, clean_lines, linenum, file_extension, nesting_state,
44594470
44604471 # Check if the line is a header guard.
44614472 is_header_guard = False
4462- if file_extension == 'h' :
4473+ if file_extension in _header_extensions :
44634474 cppvar = GetHeaderGuardCPPVariable (filename )
44644475 if (line .startswith ('#ifndef %s' % cppvar ) or
44654476 line .startswith ('#define %s' % cppvar ) or
@@ -4548,8 +4559,16 @@ def _DropCommonSuffixes(filename):
45484559 Returns:
45494560 The filename with the common suffix removed.
45504561 """
4551- for suffix in ('test.cc' , 'regtest.cc' , 'unittest.cc' ,
4552- 'inl.h' , 'impl.h' , 'internal.h' ):
4562+ bad_suffixes = []
4563+ for suffix in _test_suffixes :
4564+ for extension in _nonheader_extensions :
4565+ ## not sure why first _ char of suffix not considered here, maybe bug
4566+ bad_suffixes .append (suffix [1 :] + '.' + extension )
4567+ for extension in _header_extensions :
4568+ bad_suffixes .append ('inl.' + extension )
4569+ bad_suffixes .append ('impl.' + extension )
4570+ bad_suffixes .append ('internal.' + extension )
4571+ for suffix in bad_suffixes :
45534572 if (filename .endswith (suffix ) and len (filename ) > len (suffix ) and
45544573 filename [- len (suffix ) - 1 ] in ('-' , '_' )):
45554574 return filename [:- len (suffix ) - 1 ]
@@ -4565,12 +4584,11 @@ def _IsTestFilename(filename):
45654584 Returns:
45664585 True if 'filename' looks like a test, False otherwise.
45674586 """
4568- if (filename .endswith ('_test.cc' ) or
4569- filename .endswith ('_unittest.cc' ) or
4570- filename .endswith ('_regtest.cc' )):
4571- return True
4572- else :
4573- return False
4587+ for suffix in _test_suffixes :
4588+ for extension in _nonheader_extensions :
4589+ if filename .endswith (suffix + '.' + extension ):
4590+ return True
4591+ return False
45744592
45754593
45764594def _ClassifyInclude (fileinfo , include , is_system ):
@@ -4674,11 +4692,16 @@ def CheckIncludeLine(filename, clean_lines, linenum, include_state, error):
46744692 error (filename , linenum , 'build/include' , 4 ,
46754693 '"%s" already included at %s:%s' %
46764694 (include , filename , duplicate_line ))
4677- elif (include .endswith ('.cc' ) and
4695+ return
4696+
4697+ for extension in _nonheader_extensions :
4698+ if (include .endswith ('.' + extension ) and
46784699 os .path .dirname (fileinfo .RepositoryName ()) != os .path .dirname (include )):
4679- error (filename , linenum , 'build/include' , 4 ,
4680- 'Do not include .cc files from other packages' )
4681- elif not _THIRD_PARTY_HEADERS_PATTERN .match (include ):
4700+ error (filename , linenum , 'build/include' , 4 ,
4701+ 'Do not include .' + extension + ' files from other packages' )
4702+ return
4703+
4704+ if not _THIRD_PARTY_HEADERS_PATTERN .match (include ):
46824705 include_state .include_list [- 1 ].append ((include , linenum ))
46834706
46844707 # We want to ensure that headers appear in the right order:
@@ -4828,7 +4851,7 @@ def CheckLanguage(filename, clean_lines, linenum, file_extension,
48284851 CheckGlobalStatic (filename , clean_lines , linenum , error )
48294852 CheckPrintf (filename , clean_lines , linenum , error )
48304853
4831- if file_extension == 'h' :
4854+ if file_extension in _header_extensions :
48324855 # TODO(unknown): check that 1-arg constructors are explicit.
48334856 # How to tell it's a constructor?
48344857 # (handled in CheckForNonStandardConstructs for now)
@@ -4935,7 +4958,7 @@ def CheckLanguage(filename, clean_lines, linenum, file_extension,
49354958 # Check for use of unnamed namespaces in header files. Registration
49364959 # macros are typically OK, so we allow use of "namespace {" on lines
49374960 # that end with backslashes.
4938- if (file_extension == 'h'
4961+ if (file_extension in _header_extensions
49394962 and Search (r'\bnamespace\s*{' , line )
49404963 and line [- 1 ] != '\\ ' ):
49414964 error (filename , linenum , 'build/namespaces' , 4 ,
@@ -5576,20 +5599,24 @@ def FilesBelongToSameModule(filename_cc, filename_h):
55765599 bool: True if filename_cc and filename_h belong to the same module.
55775600 string: the additional prefix needed to open the header file.
55785601 """
5602+ fileinfo_cc = FileInfo (filename_cc )
5603+ if not fileinfo_cc .Extension ().lstrip ('.' ) in _nonheader_extensions :
5604+ return (False , '' )
55795605
5580- if not filename_cc .endswith ('.cc' ):
5606+ fileinfo_h = FileInfo (filename_h )
5607+ if not fileinfo_h .Extension ().lstrip ('.' ) in _header_extensions :
55815608 return (False , '' )
5582- filename_cc = filename_cc [:- len ('.cc' )]
5583- if filename_cc .endswith ('_unittest' ):
5584- filename_cc = filename_cc [:- len ('_unittest' )]
5585- elif filename_cc .endswith ('_test' ):
5586- filename_cc = filename_cc [:- len ('_test' )]
5609+
5610+ filename_cc = filename_cc [:- (len (fileinfo_cc .Extension ()))]
5611+ for suffix in _test_suffixes :
5612+ if filename_cc .endswith (suffix ):
5613+ filename_cc = filename_cc [:- len (suffix )]
5614+ break
5615+
55875616 filename_cc = filename_cc .replace ('/public/' , '/' )
55885617 filename_cc = filename_cc .replace ('/internal/' , '/' )
55895618
5590- if not filename_h .endswith ('.h' ):
5591- return (False , '' )
5592- filename_h = filename_h [:- len ('.h' )]
5619+ filename_h = filename_h [:- (len (fileinfo_h .Extension ()))]
55935620 if filename_h .endswith ('-inl' ):
55945621 filename_h = filename_h [:- len ('-inl' )]
55955622 filename_h = filename_h .replace ('/public/' , '/' )
@@ -5711,8 +5738,10 @@ def CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error,
57115738 # didn't include it in the .h file.
57125739 # TODO(unknown): Do a better job of finding .h files so we are confident that
57135740 # not having the .h file means there isn't one.
5714- if filename .endswith ('.cc' ) and not header_found :
5715- return
5741+ if not header_found :
5742+ for extension in _nonheader_extensions :
5743+ if filename .endswith ('.' + extension ):
5744+ return
57165745
57175746 # All the lines have been processed, report the errors found.
57185747 for required_header_unstripped in required :
@@ -6051,7 +6080,7 @@ def ProcessFileData(filename, file_extension, lines, error,
60516080 RemoveMultiLineComments (filename , lines , error )
60526081 clean_lines = CleansedLines (lines )
60536082
6054- if file_extension == 'h' :
6083+ if file_extension in _header_extensions :
60556084 CheckForHeaderGuard (filename , clean_lines , error )
60566085
60576086 for line in range (clean_lines .NumLines ()):
@@ -6064,7 +6093,7 @@ def ProcessFileData(filename, file_extension, lines, error,
60646093 CheckForIncludeWhatYouUse (filename , clean_lines , include_state , error )
60656094
60666095 # Check that the .cc file has included its header if it exists.
6067- if file_extension == 'cc' :
6096+ if file_extension in _nonheader_extensions :
60686097 CheckHeaderFileIncluded (filename , include_state , error )
60696098
60706099 # We check here rather than inside ProcessLine so that we see raw
0 commit comments