|
52 | 52 | import sys |
53 | 53 | import unicodedata |
54 | 54 |
|
| 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 | + |
| 61 | + |
55 | 62 | # The allowed extensions for file names |
56 | 63 | # This is set by --extensions flag. |
57 | | -_valid_extensions = set(['c', 'cc', 'cpp', 'cxx', 'c++', 'h', 'hpp', 'hxx', |
58 | | - 'h++']) |
| 64 | +_valid_extensions = set(['c', 'cc', 'cpp', 'cxx', 'c++', 'cu'] + _header_extensions) |
| 65 | + |
59 | 66 |
|
60 | 67 | _USAGE = """ |
61 | 68 | Syntax: cpplint.py [--verbose=#] [--output=vs7] [--filter=-x,+y,...] |
62 | 69 | [--counting=total|toplevel|detailed] [--root=subdir] |
63 | 70 | [--linelength=digits] |
| 71 | + [--headers=ext1,ext2] |
64 | 72 | <file> [file] ... |
65 | 73 |
|
66 | 74 | The style guidelines this tries to follow are those in |
|
139 | 147 | Examples: |
140 | 148 | --extensions=hpp,cpp |
141 | 149 |
|
| 150 | + headers=extension,extension,... |
| 151 | + The allowed header extensions that cpplint will consider to be header files |
| 152 | + (by default, only .h files will be assumed to be headers) |
| 153 | +
|
| 154 | + Examples: |
| 155 | + --headers=h,hpp |
| 156 | +
|
142 | 157 | cpplint.py supports per-directory configurations specified in CPPLINT.cfg |
143 | 158 | files. CPPLINT.cfg file can contain a number of key=value pairs. |
144 | 159 | Currently the following options are supported: |
@@ -1798,21 +1813,22 @@ def CheckHeaderFileIncluded(filename, include_state, error): |
1798 | 1813 | return |
1799 | 1814 |
|
1800 | 1815 | fileinfo = FileInfo(filename) |
1801 | | - headerfile = filename[0:len(filename) - 2] + 'h' |
1802 | | - if not os.path.exists(headerfile): |
1803 | | - return |
1804 | | - headername = FileInfo(headerfile).RepositoryName() |
1805 | | - first_include = 0 |
1806 | | - for section_list in include_state.include_list: |
1807 | | - for f in section_list: |
1808 | | - if headername in f[0] or f[0] in headername: |
1809 | | - return |
1810 | | - if not first_include: |
1811 | | - first_include = f[1] |
| 1816 | + for ext in _header_extensions: |
| 1817 | + headerfile = filename[0:len(filename) - 2] + ext |
| 1818 | + if not os.path.exists(headerfile): |
| 1819 | + continue |
| 1820 | + headername = FileInfo(headerfile).RepositoryName() |
| 1821 | + first_include = None |
| 1822 | + for section_list in include_state.include_list: |
| 1823 | + for f in section_list: |
| 1824 | + if headername in f[0] or f[0] in headername: |
| 1825 | + return |
| 1826 | + if not first_include: |
| 1827 | + first_include = f[1] |
1812 | 1828 |
|
1813 | | - error(filename, first_include, 'build/include', 5, |
1814 | | - '%s should include its header file %s' % (fileinfo.RepositoryName(), |
1815 | | - headername)) |
| 1829 | + error(filename, first_include, 'build/include', 5, |
| 1830 | + '%s should include its header file %s' % (fileinfo.RepositoryName(), |
| 1831 | + headername)) |
1816 | 1832 |
|
1817 | 1833 |
|
1818 | 1834 | def CheckForBadCharacters(filename, lines, error): |
@@ -4453,7 +4469,7 @@ def CheckStyle(filename, clean_lines, linenum, file_extension, nesting_state, |
4453 | 4469 |
|
4454 | 4470 | # Check if the line is a header guard. |
4455 | 4471 | is_header_guard = False |
4456 | | - if file_extension == 'h': |
| 4472 | + if file_extension in _header_extensions: |
4457 | 4473 | cppvar = GetHeaderGuardCPPVariable(filename) |
4458 | 4474 | if (line.startswith('#ifndef %s' % cppvar) or |
4459 | 4475 | line.startswith('#define %s' % cppvar) or |
@@ -4825,7 +4841,7 @@ def CheckLanguage(filename, clean_lines, linenum, file_extension, |
4825 | 4841 | CheckGlobalStatic(filename, clean_lines, linenum, error) |
4826 | 4842 | CheckPrintf(filename, clean_lines, linenum, error) |
4827 | 4843 |
|
4828 | | - if file_extension == 'h': |
| 4844 | + if file_extension in _header_extensions: |
4829 | 4845 | # TODO(unknown): check that 1-arg constructors are explicit. |
4830 | 4846 | # How to tell it's a constructor? |
4831 | 4847 | # (handled in CheckForNonStandardConstructs for now) |
@@ -4932,7 +4948,7 @@ def CheckLanguage(filename, clean_lines, linenum, file_extension, |
4932 | 4948 | # Check for use of unnamed namespaces in header files. Registration |
4933 | 4949 | # macros are typically OK, so we allow use of "namespace {" on lines |
4934 | 4950 | # that end with backslashes. |
4935 | | - if (file_extension == 'h' |
| 4951 | + if (file_extension in _header_extensions |
4936 | 4952 | and Search(r'\bnamespace\s*{', line) |
4937 | 4953 | and line[-1] != '\\'): |
4938 | 4954 | error(filename, linenum, 'build/namespaces', 4, |
@@ -6048,7 +6064,7 @@ def ProcessFileData(filename, file_extension, lines, error, |
6048 | 6064 | RemoveMultiLineComments(filename, lines, error) |
6049 | 6065 | clean_lines = CleansedLines(lines) |
6050 | 6066 |
|
6051 | | - if file_extension == 'h': |
| 6067 | + if file_extension in _header_extensions: |
6052 | 6068 | CheckForHeaderGuard(filename, clean_lines, error) |
6053 | 6069 |
|
6054 | 6070 | for line in range(clean_lines.NumLines()): |
@@ -6128,6 +6144,22 @@ def ProcessConfigOverrides(filename): |
6128 | 6144 | _line_length = int(val) |
6129 | 6145 | except ValueError: |
6130 | 6146 | sys.stderr.write('Line length must be numeric.') |
| 6147 | + elif name == 'extensions': |
| 6148 | + global _valid_extensions |
| 6149 | + try: |
| 6150 | + extensions = [ext.strip() for ext in val.split(',')] |
| 6151 | + _valid_extensions = _valid_extensions.union(set(extensions)) |
| 6152 | + except ValueError: |
| 6153 | + sys.stderr.write('Extensions should be a comma-separated list of values;' |
| 6154 | + 'for example: extensions=hpp,cpp\n' |
| 6155 | + 'This could not be parsed: "%s"' % (val,)) |
| 6156 | + try: |
| 6157 | + extensions = [ext.strip() for ext in val.split(',')] |
| 6158 | + _valid_extensions = _valid_extensions.union(set(extensions)) |
| 6159 | + except ValueError: |
| 6160 | + sys.stderr.write('Extensions should be a comma-separated list of values;' |
| 6161 | + 'for example: extensions=hpp,cpp\n' |
| 6162 | + 'This could not be parsed: "%s"' % (values,)) |
6131 | 6163 | else: |
6132 | 6164 | sys.stderr.write( |
6133 | 6165 | 'Invalid configuration option (%s) in file %s\n' % |
@@ -6274,7 +6306,8 @@ def ParseArguments(args): |
6274 | 6306 | 'filter=', |
6275 | 6307 | 'root=', |
6276 | 6308 | 'linelength=', |
6277 | | - 'extensions=']) |
| 6309 | + 'extensions=', |
| 6310 | + 'headers=']) |
6278 | 6311 | except getopt.GetoptError: |
6279 | 6312 | PrintUsage('Invalid arguments.') |
6280 | 6313 |
|
@@ -6315,6 +6348,12 @@ def ParseArguments(args): |
6315 | 6348 | _valid_extensions = set(val.split(',')) |
6316 | 6349 | except ValueError: |
6317 | 6350 | PrintUsage('Extensions must be comma seperated list.') |
| 6351 | + elif opt == '--headers': |
| 6352 | + global _header_extensions |
| 6353 | + try: |
| 6354 | + _header_extensions = set(val.split(',')) |
| 6355 | + except ValueError: |
| 6356 | + PrintUsage('Extensions must be comma seperated list.') |
6318 | 6357 |
|
6319 | 6358 | if not filenames: |
6320 | 6359 | PrintUsage('No files were specified.') |
|
0 commit comments