|
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:
|
@@ -1804,21 +1819,22 @@ def CheckHeaderFileIncluded(filename, include_state, error):
|
1804 | 1819 | return
|
1805 | 1820 |
|
1806 | 1821 | 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] |
| 1822 | + for ext in _header_extensions: |
| 1823 | + headerfile = filename[0:len(filename) - 2] + ext |
| 1824 | + if not os.path.exists(headerfile): |
| 1825 | + continue |
| 1826 | + headername = FileInfo(headerfile).RepositoryName() |
| 1827 | + first_include = None |
| 1828 | + for section_list in include_state.include_list: |
| 1829 | + for f in section_list: |
| 1830 | + if headername in f[0] or f[0] in headername: |
| 1831 | + return |
| 1832 | + if not first_include: |
| 1833 | + first_include = f[1] |
1818 | 1834 |
|
1819 |
| - error(filename, first_include, 'build/include', 5, |
1820 |
| - '%s should include its header file %s' % (fileinfo.RepositoryName(), |
1821 |
| - headername)) |
| 1835 | + error(filename, first_include, 'build/include', 5, |
| 1836 | + '%s should include its header file %s' % (fileinfo.RepositoryName(), |
| 1837 | + headername)) |
1822 | 1838 |
|
1823 | 1839 |
|
1824 | 1840 | def CheckForBadCharacters(filename, lines, error):
|
@@ -4459,7 +4475,7 @@ def CheckStyle(filename, clean_lines, linenum, file_extension, nesting_state,
|
4459 | 4475 |
|
4460 | 4476 | # Check if the line is a header guard.
|
4461 | 4477 | is_header_guard = False
|
4462 |
| - if file_extension == 'h': |
| 4478 | + if file_extension in _header_extensions: |
4463 | 4479 | cppvar = GetHeaderGuardCPPVariable(filename)
|
4464 | 4480 | if (line.startswith('#ifndef %s' % cppvar) or
|
4465 | 4481 | line.startswith('#define %s' % cppvar) or
|
@@ -4828,7 +4844,7 @@ def CheckLanguage(filename, clean_lines, linenum, file_extension,
|
4828 | 4844 | CheckGlobalStatic(filename, clean_lines, linenum, error)
|
4829 | 4845 | CheckPrintf(filename, clean_lines, linenum, error)
|
4830 | 4846 |
|
4831 |
| - if file_extension == 'h': |
| 4847 | + if file_extension in _header_extensions: |
4832 | 4848 | # TODO(unknown): check that 1-arg constructors are explicit.
|
4833 | 4849 | # How to tell it's a constructor?
|
4834 | 4850 | # (handled in CheckForNonStandardConstructs for now)
|
@@ -4935,7 +4951,7 @@ def CheckLanguage(filename, clean_lines, linenum, file_extension,
|
4935 | 4951 | # Check for use of unnamed namespaces in header files. Registration
|
4936 | 4952 | # macros are typically OK, so we allow use of "namespace {" on lines
|
4937 | 4953 | # that end with backslashes.
|
4938 |
| - if (file_extension == 'h' |
| 4954 | + if (file_extension in _header_extensions |
4939 | 4955 | and Search(r'\bnamespace\s*{', line)
|
4940 | 4956 | and line[-1] != '\\'):
|
4941 | 4957 | error(filename, linenum, 'build/namespaces', 4,
|
@@ -6051,7 +6067,7 @@ def ProcessFileData(filename, file_extension, lines, error,
|
6051 | 6067 | RemoveMultiLineComments(filename, lines, error)
|
6052 | 6068 | clean_lines = CleansedLines(lines)
|
6053 | 6069 |
|
6054 |
| - if file_extension == 'h': |
| 6070 | + if file_extension in _header_extensions: |
6055 | 6071 | CheckForHeaderGuard(filename, clean_lines, error)
|
6056 | 6072 |
|
6057 | 6073 | for line in range(clean_lines.NumLines()):
|
@@ -6131,6 +6147,22 @@ def ProcessConfigOverrides(filename):
|
6131 | 6147 | _line_length = int(val)
|
6132 | 6148 | except ValueError:
|
6133 | 6149 | sys.stderr.write('Line length must be numeric.')
|
| 6150 | + elif name == 'extensions': |
| 6151 | + global _valid_extensions |
| 6152 | + try: |
| 6153 | + extensions = [ext.strip() for ext in val.split(',')] |
| 6154 | + _valid_extensions = _valid_extensions.union(set(extensions)) |
| 6155 | + except ValueError: |
| 6156 | + sys.stderr.write('Extensions should be a comma-separated list of values;' |
| 6157 | + 'for example: extensions=hpp,cpp\n' |
| 6158 | + 'This could not be parsed: "%s"' % (val,)) |
| 6159 | + try: |
| 6160 | + extensions = [ext.strip() for ext in val.split(',')] |
| 6161 | + _valid_extensions = _valid_extensions.union(set(extensions)) |
| 6162 | + except ValueError: |
| 6163 | + sys.stderr.write('Extensions should be a comma-separated list of values;' |
| 6164 | + 'for example: extensions=hpp,cpp\n' |
| 6165 | + 'This could not be parsed: "%s"' % (values,)) |
6134 | 6166 | else:
|
6135 | 6167 | sys.stderr.write(
|
6136 | 6168 | 'Invalid configuration option (%s) in file %s\n' %
|
@@ -6277,7 +6309,8 @@ def ParseArguments(args):
|
6277 | 6309 | 'filter=',
|
6278 | 6310 | 'root=',
|
6279 | 6311 | 'linelength=',
|
6280 |
| - 'extensions=']) |
| 6312 | + 'extensions=', |
| 6313 | + 'headers=']) |
6281 | 6314 | except getopt.GetoptError:
|
6282 | 6315 | PrintUsage('Invalid arguments.')
|
6283 | 6316 |
|
@@ -6318,6 +6351,12 @@ def ParseArguments(args):
|
6318 | 6351 | _valid_extensions = set(val.split(','))
|
6319 | 6352 | except ValueError:
|
6320 | 6353 | PrintUsage('Extensions must be comma seperated list.')
|
| 6354 | + elif opt == '--headers': |
| 6355 | + global _header_extensions |
| 6356 | + try: |
| 6357 | + _header_extensions = set(val.split(',')) |
| 6358 | + except ValueError: |
| 6359 | + PrintUsage('Extensions must be comma seperated list.') |
6321 | 6360 |
|
6322 | 6361 | if not filenames:
|
6323 | 6362 | PrintUsage('No files were specified.')
|
|
0 commit comments