|
61 | 61 | Syntax: cpplint.py [--verbose=#] [--output=vs7] [--filter=-x,+y,...] |
62 | 62 | [--counting=total|toplevel|detailed] [--root=subdir] |
63 | 63 | [--linelength=digits] |
| 64 | + [--headers=ext1,ext2] |
64 | 65 | <file> [file] ... |
65 | 66 |
|
66 | 67 | The style guidelines this tries to follow are those in |
|
139 | 140 | Examples: |
140 | 141 | --extensions=hpp,cpp |
141 | 142 |
|
| 143 | + headers=extension,extension,... |
| 144 | + The allowed header extensions that cpplint will consider to be header files |
| 145 | + (by default, only .h files will be assumed to be headers) |
| 146 | +
|
| 147 | + Examples: |
| 148 | + --headers=h,hpp |
| 149 | +
|
142 | 150 | cpplint.py supports per-directory configurations specified in CPPLINT.cfg |
143 | 151 | files. CPPLINT.cfg file can contain a number of key=value pairs. |
144 | 152 | Currently the following options are supported: |
@@ -519,6 +527,12 @@ def u(x): |
519 | 527 | itervalues = dict.values |
520 | 528 | iteritems = dict.items |
521 | 529 |
|
| 530 | +# Files with any of these extensions are considered to be |
| 531 | +# header files (and will undergo different style checks). |
| 532 | +# This set can be extended by using the --headers |
| 533 | +# option (also supported in CPPLINT.cfg) |
| 534 | +_header_extensions = set(['h']) |
| 535 | + |
522 | 536 | def ParseNolintSuppressions(filename, raw_line, linenum, error): |
523 | 537 | """Updates the global list of error-suppressions. |
524 | 538 |
|
@@ -1798,21 +1812,22 @@ def CheckHeaderFileIncluded(filename, include_state, error): |
1798 | 1812 | return |
1799 | 1813 |
|
1800 | 1814 | 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] |
| 1815 | + for ext in _header_extensions: |
| 1816 | + headerfile = filename[0:len(filename) - 2] + ext |
| 1817 | + if not os.path.exists(headerfile): |
| 1818 | + continue |
| 1819 | + headername = FileInfo(headerfile).RepositoryName() |
| 1820 | + first_include = None |
| 1821 | + for section_list in include_state.include_list: |
| 1822 | + for f in section_list: |
| 1823 | + if headername in f[0] or f[0] in headername: |
| 1824 | + return |
| 1825 | + if not first_include: |
| 1826 | + first_include = f[1] |
1812 | 1827 |
|
1813 | | - error(filename, first_include, 'build/include', 5, |
1814 | | - '%s should include its header file %s' % (fileinfo.RepositoryName(), |
1815 | | - headername)) |
| 1828 | + error(filename, first_include, 'build/include', 5, |
| 1829 | + '%s should include its header file %s' % (fileinfo.RepositoryName(), |
| 1830 | + headername)) |
1816 | 1831 |
|
1817 | 1832 |
|
1818 | 1833 | def CheckForBadCharacters(filename, lines, error): |
@@ -4453,7 +4468,7 @@ def CheckStyle(filename, clean_lines, linenum, file_extension, nesting_state, |
4453 | 4468 |
|
4454 | 4469 | # Check if the line is a header guard. |
4455 | 4470 | is_header_guard = False |
4456 | | - if file_extension == 'h': |
| 4471 | + if file_extension in _header_extensions: |
4457 | 4472 | cppvar = GetHeaderGuardCPPVariable(filename) |
4458 | 4473 | if (line.startswith('#ifndef %s' % cppvar) or |
4459 | 4474 | line.startswith('#define %s' % cppvar) or |
@@ -4825,7 +4840,7 @@ def CheckLanguage(filename, clean_lines, linenum, file_extension, |
4825 | 4840 | CheckGlobalStatic(filename, clean_lines, linenum, error) |
4826 | 4841 | CheckPrintf(filename, clean_lines, linenum, error) |
4827 | 4842 |
|
4828 | | - if file_extension == 'h': |
| 4843 | + if file_extension in _header_extensions: |
4829 | 4844 | # TODO(unknown): check that 1-arg constructors are explicit. |
4830 | 4845 | # How to tell it's a constructor? |
4831 | 4846 | # (handled in CheckForNonStandardConstructs for now) |
@@ -4932,7 +4947,7 @@ def CheckLanguage(filename, clean_lines, linenum, file_extension, |
4932 | 4947 | # Check for use of unnamed namespaces in header files. Registration |
4933 | 4948 | # macros are typically OK, so we allow use of "namespace {" on lines |
4934 | 4949 | # that end with backslashes. |
4935 | | - if (file_extension == 'h' |
| 4950 | + if (file_extension in _header_extensions |
4936 | 4951 | and Search(r'\bnamespace\s*{', line) |
4937 | 4952 | and line[-1] != '\\'): |
4938 | 4953 | error(filename, linenum, 'build/namespaces', 4, |
@@ -6048,7 +6063,7 @@ def ProcessFileData(filename, file_extension, lines, error, |
6048 | 6063 | RemoveMultiLineComments(filename, lines, error) |
6049 | 6064 | clean_lines = CleansedLines(lines) |
6050 | 6065 |
|
6051 | | - if file_extension == 'h': |
| 6066 | + if file_extension in _header_extensions: |
6052 | 6067 | CheckForHeaderGuard(filename, clean_lines, error) |
6053 | 6068 |
|
6054 | 6069 | for line in range(clean_lines.NumLines()): |
@@ -6128,6 +6143,15 @@ def ProcessConfigOverrides(filename): |
6128 | 6143 | _line_length = int(val) |
6129 | 6144 | except ValueError: |
6130 | 6145 | sys.stderr.write('Line length must be numeric.') |
| 6146 | + elif name == 'extensions': |
| 6147 | + global _valid_extensions |
| 6148 | + try: |
| 6149 | + extensions = [ext.strip() for ext in val.split(',')] |
| 6150 | + _valid_extensions = _valid_extensions.union(set(extensions)) |
| 6151 | + except ValueError: |
| 6152 | + sys.stderr.write('Extensions should be a comma-separated list of values;' |
| 6153 | + 'for example: extensions=hpp,cpp\n' |
| 6154 | + 'This could not be parsed: "%s"' % (values,)) |
6131 | 6155 | else: |
6132 | 6156 | sys.stderr.write( |
6133 | 6157 | 'Invalid configuration option (%s) in file %s\n' % |
@@ -6274,7 +6298,8 @@ def ParseArguments(args): |
6274 | 6298 | 'filter=', |
6275 | 6299 | 'root=', |
6276 | 6300 | 'linelength=', |
6277 | | - 'extensions=']) |
| 6301 | + 'extensions=', |
| 6302 | + 'headers=']) |
6278 | 6303 | except getopt.GetoptError: |
6279 | 6304 | PrintUsage('Invalid arguments.') |
6280 | 6305 |
|
@@ -6315,6 +6340,12 @@ def ParseArguments(args): |
6315 | 6340 | _valid_extensions = set(val.split(',')) |
6316 | 6341 | except ValueError: |
6317 | 6342 | PrintUsage('Extensions must be comma seperated list.') |
| 6343 | + elif opt == '--headers': |
| 6344 | + global _header_extensions |
| 6345 | + try: |
| 6346 | + _header_extensions = set(val.split(',')) |
| 6347 | + except ValueError: |
| 6348 | + PrintUsage('Extensions must be comma seperated list.') |
6318 | 6349 |
|
6319 | 6350 | if not filenames: |
6320 | 6351 | PrintUsage('No files were specified.') |
|
0 commit comments