|
64 | 64 | # if empty, use defaults |
65 | 65 | _valid_extensions = set([]) |
66 | 66 |
|
67 | | -__VERSION__ = '1.6.0' |
| 67 | +__VERSION__ = '1.6.1' |
68 | 68 |
|
69 | 69 | try: |
| 70 | + # -- pylint: disable=used-before-assignment |
70 | 71 | xrange # Python 2 |
71 | 72 | except NameError: |
72 | 73 | # -- pylint: disable=redefined-builtin |
|
97 | 98 | certain of the problem, and 1 meaning it could be a legitimate construct. |
98 | 99 | This will miss some errors, and is not a substitute for a code review. |
99 | 100 |
|
100 | | - To suppress false-positive errors of a certain category, add a |
101 | | - 'NOLINT(category)' comment to the line. NOLINT or NOLINT(*) |
102 | | - suppresses errors of all categories on that line. |
| 101 | + To suppress false-positive errors of certain categories, add a |
| 102 | + 'NOLINT(category[, category...])' comment to the line. NOLINT or NOLINT(*) |
| 103 | + suppresses errors of all categories on that line. To suppress categories |
| 104 | + on the next line use NOLINTNEXTLINE instead of NOLINT. |
103 | 105 |
|
104 | 106 | The files passed in will be linted; at least one file must be provided. |
105 | 107 | Default linted extensions are %s. |
|
300 | 302 | 'build/include', |
301 | 303 | 'build/include_subdir', |
302 | 304 | 'build/include_alpha', |
303 | | - 'build/include_inline', |
304 | 305 | 'build/include_order', |
305 | 306 | 'build/include_what_you_use', |
306 | 307 | 'build/namespaces_headers', |
|
316 | 317 | 'readability/constructors', |
317 | 318 | 'readability/fn_size', |
318 | 319 | 'readability/inheritance', |
319 | | - 'readability/pointer_notation', |
320 | 320 | 'readability/multiline_comment', |
321 | 321 | 'readability/multiline_string', |
322 | 322 | 'readability/namespace', |
323 | 323 | 'readability/nolint', |
324 | 324 | 'readability/nul', |
325 | | - 'readability/null_usage', |
326 | 325 | 'readability/strings', |
327 | 326 | 'readability/todo', |
328 | 327 | 'readability/utf8', |
|
342 | 341 | 'runtime/string', |
343 | 342 | 'runtime/threadsafe_fn', |
344 | 343 | 'runtime/vlog', |
345 | | - 'runtime/v8_persistent', |
346 | 344 | 'whitespace/blank_line', |
347 | 345 | 'whitespace/braces', |
348 | 346 | 'whitespace/comma', |
|
377 | 375 | 'readability/function', |
378 | 376 | ] |
379 | 377 |
|
| 378 | +# These prefixes for categories should be ignored since they relate to other |
| 379 | +# tools which also use the NOLINT syntax, e.g. clang-tidy. |
| 380 | +_OTHER_NOLINT_CATEGORY_PREFIXES = [ |
| 381 | + 'clang-analyzer', |
| 382 | + ] |
| 383 | + |
380 | 384 | # The default state of the category filter. This is overridden by the --filter= |
381 | 385 | # flag. By default all errors are on, so only add here categories that should be |
382 | 386 | # off by default (i.e., categories that must be enabled by the --filter= flags). |
|
405 | 409 | 'alloc.h', |
406 | 410 | 'builtinbuf.h', |
407 | 411 | 'bvector.h', |
408 | | - 'complex.h', |
| 412 | + # 'complex.h', collides with System C header "complex.h" |
409 | 413 | 'defalloc.h', |
410 | 414 | 'deque.h', |
411 | 415 | 'editbuf.h', |
|
517 | 521 | 'optional', |
518 | 522 | 'string_view', |
519 | 523 | 'variant', |
| 524 | + # 17.6.1.2 C++20 headers |
| 525 | + 'barrier', |
| 526 | + 'bit', |
| 527 | + 'compare', |
| 528 | + 'concepts', |
| 529 | + 'coroutine', |
| 530 | + 'format', |
| 531 | + 'latch' |
| 532 | + 'numbers', |
| 533 | + 'ranges', |
| 534 | + 'semaphore', |
| 535 | + 'source_location', |
| 536 | + 'span', |
| 537 | + 'stop_token', |
| 538 | + 'syncstream', |
| 539 | + 'version', |
520 | 540 | # 17.6.1.2 C++ headers for C library facilities |
521 | 541 | 'cassert', |
522 | 542 | 'ccomplex', |
|
851 | 871 | 'Missing space after ,': r's/,\([^ ]\)/, \1/g', |
852 | 872 | } |
853 | 873 |
|
854 | | -_NULL_TOKEN_PATTERN = re.compile(r'\bNULL\b') |
855 | | - |
856 | | -_V8_PERSISTENT_PATTERN = re.compile(r'\bv8::Persistent\b') |
857 | | - |
858 | | -_RIGHT_LEANING_POINTER_PATTERN = re.compile(r'[^=|(,\s><);&?:}]' |
859 | | - r'(?<!(sizeof|return))' |
860 | | - r'\s\*[a-zA-Z_][0-9a-zA-Z_]*') |
861 | | - |
862 | 874 | _regexp_compile_cache = {} |
863 | 875 |
|
864 | 876 | # {str, set(int)}: a map from error categories to sets of linenumbers |
|
889 | 901 | _include_order = "default" |
890 | 902 |
|
891 | 903 | try: |
| 904 | + # -- pylint: disable=used-before-assignment |
892 | 905 | unicode |
893 | 906 | except NameError: |
894 | 907 | # -- pylint: disable=redefined-builtin |
895 | 908 | basestring = unicode = str |
896 | 909 |
|
897 | 910 | try: |
| 911 | + # -- pylint: disable=used-before-assignment |
898 | 912 | long |
899 | 913 | except NameError: |
900 | 914 | # -- pylint: disable=redefined-builtin |
@@ -988,14 +1002,16 @@ def ParseNolintSuppressions(filename, raw_line, linenum, error): |
988 | 1002 | suppressed_line = linenum + 1 |
989 | 1003 | else: |
990 | 1004 | suppressed_line = linenum |
991 | | - category = matched.group(2) |
992 | | - if category in (None, '(*)'): # => "suppress all" |
| 1005 | + categories = matched.group(2) |
| 1006 | + if categories in (None, '(*)'): # => "suppress all" |
993 | 1007 | _error_suppressions.setdefault(None, set()).add(suppressed_line) |
994 | | - else: |
995 | | - if category.startswith('(') and category.endswith(')'): |
996 | | - category = category[1:-1] |
| 1008 | + elif categories.startswith('(') and categories.endswith(')'): |
| 1009 | + for category in set(map(lambda c: c.strip(), categories[1:-1].split(','))): |
997 | 1010 | if category in _ERROR_CATEGORIES: |
998 | 1011 | _error_suppressions.setdefault(category, set()).add(suppressed_line) |
| 1012 | + elif any(c for c in _OTHER_NOLINT_CATEGORY_PREFIXES if category.startswith(c)): |
| 1013 | + # Ignore any categories from other tools. |
| 1014 | + pass |
999 | 1015 | elif category not in _LEGACY_ERROR_CATEGORIES: |
1000 | 1016 | error(filename, linenum, 'readability/nolint', 5, |
1001 | 1017 | 'Unknown NOLINT error category: %s' % category) |
@@ -1099,11 +1115,10 @@ class _IncludeState(object): |
1099 | 1115 | # needs to move backwards, CheckNextIncludeOrder will raise an error. |
1100 | 1116 | _INITIAL_SECTION = 0 |
1101 | 1117 | _MY_H_SECTION = 1 |
1102 | | - _OTHER_H_SECTION = 2 |
1103 | | - _OTHER_SYS_SECTION = 3 |
1104 | | - _C_SECTION = 4 |
1105 | | - _CPP_SECTION = 5 |
1106 | | - |
| 1118 | + _C_SECTION = 2 |
| 1119 | + _CPP_SECTION = 3 |
| 1120 | + _OTHER_SYS_SECTION = 4 |
| 1121 | + _OTHER_H_SECTION = 5 |
1107 | 1122 |
|
1108 | 1123 | _TYPE_NAMES = { |
1109 | 1124 | _C_SYS_HEADER: 'C system header', |
@@ -2540,21 +2555,6 @@ def CheckForBadCharacters(filename, lines, error): |
2540 | 2555 | error(filename, linenum, 'readability/nul', 5, 'Line contains NUL byte.') |
2541 | 2556 |
|
2542 | 2557 |
|
2543 | | -def CheckInlineHeader(filename, include_state, error): |
2544 | | - """Logs an error if both a header and its inline variant are included.""" |
2545 | | - |
2546 | | - all_headers = dict(item for sublist in include_state.include_list |
2547 | | - for item in sublist) |
2548 | | - bad_headers = set('%s.h' % name[:-6] for name in all_headers.keys() |
2549 | | - if name.endswith('-inl.h')) |
2550 | | - bad_headers &= set(all_headers.keys()) |
2551 | | - |
2552 | | - for name in bad_headers: |
2553 | | - err = '%s includes both %s and %s-inl.h' % (filename, name, name) |
2554 | | - linenum = all_headers[name] |
2555 | | - error(filename, linenum, 'build/include_inline', 5, err) |
2556 | | - |
2557 | | - |
2558 | 2558 | def CheckForNewlineAtEOF(filename, lines, error): |
2559 | 2559 | """Logs an error if there is no newline char at the end of the file. |
2560 | 2560 |
|
@@ -3578,7 +3578,7 @@ def CheckForFunctionLengths(filename, clean_lines, linenum, |
3578 | 3578 | """Reports for long function bodies. |
3579 | 3579 |
|
3580 | 3580 | For an overview why this is done, see: |
3581 | | - https://google.github.io/styleguide/cppguide.html#Write_Short_Functions |
| 3581 | + https://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Write_Short_Functions |
3582 | 3582 |
|
3583 | 3583 | Uses a simplistic algorithm assuming other style guidelines |
3584 | 3584 | (especially spacing) are followed. |
@@ -4805,71 +4805,6 @@ def CheckAltTokens(filename, clean_lines, linenum, error): |
4805 | 4805 | 'Use operator %s instead of %s' % ( |
4806 | 4806 | _ALT_TOKEN_REPLACEMENT[match.group(1)], match.group(1))) |
4807 | 4807 |
|
4808 | | -def CheckNullTokens(filename, clean_lines, linenum, error): |
4809 | | - """Check NULL usage. |
4810 | | -
|
4811 | | - Args: |
4812 | | - filename: The name of the current file. |
4813 | | - clean_lines: A CleansedLines instance containing the file. |
4814 | | - linenum: The number of the line to check. |
4815 | | - error: The function to call with any errors found. |
4816 | | - """ |
4817 | | - line = clean_lines.elided[linenum] |
4818 | | - |
4819 | | - # Avoid preprocessor lines |
4820 | | - if Match(r'^\s*#', line): |
4821 | | - return |
4822 | | - |
4823 | | - if line.find('/*') >= 0 or line.find('*/') >= 0: |
4824 | | - return |
4825 | | - |
4826 | | - for match in _NULL_TOKEN_PATTERN.finditer(line): |
4827 | | - error(filename, linenum, 'readability/null_usage', 2, |
4828 | | - 'Use nullptr instead of NULL') |
4829 | | - |
4830 | | -def CheckV8PersistentTokens(filename, clean_lines, linenum, error): |
4831 | | - """Check v8::Persistent usage. |
4832 | | -
|
4833 | | - Args: |
4834 | | - filename: The name of the current file. |
4835 | | - clean_lines: A CleansedLines instance containing the file. |
4836 | | - linenum: The number of the line to check. |
4837 | | - error: The function to call with any errors found. |
4838 | | - """ |
4839 | | - line = clean_lines.elided[linenum] |
4840 | | - |
4841 | | - # Avoid preprocessor lines |
4842 | | - if Match(r'^\s*#', line): |
4843 | | - return |
4844 | | - |
4845 | | - if line.find('/*') >= 0 or line.find('*/') >= 0: |
4846 | | - return |
4847 | | - |
4848 | | - for match in _V8_PERSISTENT_PATTERN.finditer(line): |
4849 | | - error(filename, linenum, 'runtime/v8_persistent', 2, |
4850 | | - 'Use v8::Global instead of v8::Persistent') |
4851 | | - |
4852 | | -def CheckLeftLeaningPointer(filename, clean_lines, linenum, error): |
4853 | | - """Check for left-leaning pointer placement. |
4854 | | -
|
4855 | | - Args: |
4856 | | - filename: The name of the current file. |
4857 | | - clean_lines: A CleansedLines instance containing the file. |
4858 | | - linenum: The number of the line to check. |
4859 | | - error: The function to call with any errors found. |
4860 | | - """ |
4861 | | - line = clean_lines.elided[linenum] |
4862 | | - |
4863 | | - # Avoid preprocessor lines |
4864 | | - if Match(r'^\s*#', line): |
4865 | | - return |
4866 | | - |
4867 | | - if '/*' in line or '*/' in line: |
4868 | | - return |
4869 | | - |
4870 | | - for match in _RIGHT_LEANING_POINTER_PATTERN.finditer(line): |
4871 | | - error(filename, linenum, 'readability/pointer_notation', 2, |
4872 | | - 'Use left leaning pointer instead of right leaning') |
4873 | 4808 |
|
4874 | 4809 | def GetLineWidth(line): |
4875 | 4810 | """Determines the width of the line in column positions. |
@@ -5024,9 +4959,6 @@ def CheckStyle(filename, clean_lines, linenum, file_extension, nesting_state, |
5024 | 4959 | CheckSpacingForFunctionCall(filename, clean_lines, linenum, error) |
5025 | 4960 | CheckCheck(filename, clean_lines, linenum, error) |
5026 | 4961 | CheckAltTokens(filename, clean_lines, linenum, error) |
5027 | | - CheckNullTokens(filename, clean_lines, linenum, error) |
5028 | | - CheckV8PersistentTokens(filename, clean_lines, linenum, error) |
5029 | | - CheckLeftLeaningPointer(filename, clean_lines, linenum, error) |
5030 | 4962 | classinfo = nesting_state.InnermostClass() |
5031 | 4963 | if classinfo: |
5032 | 4964 | CheckSectionSpacing(filename, clean_lines, classinfo, linenum, error) |
@@ -5108,7 +5040,8 @@ def _ClassifyInclude(fileinfo, include, used_angle_brackets, include_order="defa |
5108 | 5040 | or Search(r'(?:%s)\/.*\.h' % "|".join(C_STANDARD_HEADER_FOLDERS), include)) |
5109 | 5041 |
|
5110 | 5042 | # Headers with C++ extensions shouldn't be considered C system headers |
5111 | | - is_system = used_angle_brackets and not os.path.splitext(include)[1] in ['.hpp', '.hxx', '.h++'] |
| 5043 | + include_ext = os.path.splitext(include)[1] |
| 5044 | + is_system = used_angle_brackets and not include_ext in ['.hh', '.hpp', '.hxx', '.h++'] |
5112 | 5045 |
|
5113 | 5046 | if is_system: |
5114 | 5047 | if is_cpp_header: |
@@ -5183,7 +5116,7 @@ def CheckIncludeLine(filename, clean_lines, linenum, include_state, error): |
5183 | 5116 | match = _RE_PATTERN_INCLUDE.search(line) |
5184 | 5117 | if match: |
5185 | 5118 | include = match.group(2) |
5186 | | - used_angle_brackets = (match.group(1) == '<') |
| 5119 | + used_angle_brackets = match.group(1) == '<' |
5187 | 5120 | duplicate_line = include_state.FindHeader(include) |
5188 | 5121 | if duplicate_line >= 0: |
5189 | 5122 | error(filename, linenum, 'build/include', 4, |
@@ -5214,10 +5147,11 @@ def CheckIncludeLine(filename, clean_lines, linenum, include_state, error): |
5214 | 5147 | include_state.include_list[-1].append((include, linenum)) |
5215 | 5148 |
|
5216 | 5149 | # We want to ensure that headers appear in the right order: |
5217 | | - # 1) for foo.cc, foo.h |
5218 | | - # 2) other project headers |
5219 | | - # 3) c system files |
5220 | | - # 4) cpp system files |
| 5150 | + # 1) for foo.cc, foo.h (preferred location) |
| 5151 | + # 2) c system files |
| 5152 | + # 3) cpp system files |
| 5153 | + # 4) for foo.cc, foo.h (deprecated location) |
| 5154 | + # 5) other google headers |
5221 | 5155 | # |
5222 | 5156 | # We classify each include statement as one of those 5 types |
5223 | 5157 | # using a number of techniques. The include_state object keeps |
@@ -5480,7 +5414,7 @@ def CheckLanguage(filename, clean_lines, linenum, file_extension, |
5480 | 5414 | and line[-1] != '\\'): |
5481 | 5415 | error(filename, linenum, 'build/namespaces_headers', 4, |
5482 | 5416 | 'Do not use unnamed namespaces in header files. See ' |
5483 | | - 'https://google.github.io/styleguide/cppguide.html#Namespaces' |
| 5417 | + 'https://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Namespaces' |
5484 | 5418 | ' for more information.') |
5485 | 5419 |
|
5486 | 5420 |
|
@@ -5947,7 +5881,8 @@ def CheckCStyleCast(filename, clean_lines, linenum, cast_type, pattern, error): |
5947 | 5881 | return False |
5948 | 5882 |
|
5949 | 5883 | # operator++(int) and operator--(int) |
5950 | | - if context.endswith(' operator++') or context.endswith(' operator--'): |
| 5884 | + if (context.endswith(' operator++') or context.endswith(' operator--') or |
| 5885 | + context.endswith('::operator++') or context.endswith('::operator--')): |
5951 | 5886 | return False |
5952 | 5887 |
|
5953 | 5888 | # A single unnamed argument for a function tends to look like old style cast. |
@@ -6602,8 +6537,6 @@ def ProcessFileData(filename, file_extension, lines, error, |
6602 | 6537 |
|
6603 | 6538 | CheckForNewlineAtEOF(filename, lines, error) |
6604 | 6539 |
|
6605 | | - CheckInlineHeader(filename, include_state, error) |
6606 | | - |
6607 | 6540 | def ProcessConfigOverrides(filename): |
6608 | 6541 | """ Loads the configuration files and processes the config overrides. |
6609 | 6542 |
|
@@ -6622,13 +6555,13 @@ def ProcessConfigOverrides(filename): |
6622 | 6555 | if not base_name: |
6623 | 6556 | break # Reached the root directory. |
6624 | 6557 |
|
6625 | | - cfg_file = os.path.join(abs_path, ".cpplint") |
| 6558 | + cfg_file = os.path.join(abs_path, "CPPLINT.cfg") |
6626 | 6559 | abs_filename = abs_path |
6627 | 6560 | if not os.path.isfile(cfg_file): |
6628 | 6561 | continue |
6629 | 6562 |
|
6630 | 6563 | try: |
6631 | | - with open(cfg_file, encoding='utf-8') as file_handle: |
| 6564 | + with codecs.open(cfg_file, 'r', 'utf8', 'replace') as file_handle: |
6632 | 6565 | for line in file_handle: |
6633 | 6566 | line, _, _ = line.partition('#') # Remove comments. |
6634 | 6567 | if not line.strip(): |
|