31 """Does google-lint on c++ files. 33 The goal of this script is to identify places in the code that *may* 34 be in non-compliance with google style. It does not attempt to fix 35 up these problems -- the point is to educate. It does also not 36 attempt to find all problems, or to ensure that everything it does 37 find is legitimately a problem. 39 In particular, we can get very confused by /* and // inside strings! 40 We do a small hack, which is to ignore //'s with "'s after them on the 41 same line, but it is far from perfect (in either direction). 62 Syntax: cpplint.py [--verbose=#] [--output=vs7] [--filter=-x,+y,...] 63 [--counting=total|toplevel|detailed] [--root=subdir] 67 The style guidelines this tries to follow are those in 68 http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml 70 Every problem is given a confidence score from 1-5, with 5 meaning we are 71 certain of the problem, and 1 meaning it could be a legitimate construct. 72 This will miss some errors, and is not a substitute for a code review. 74 To suppress false-positive errors of a certain category, add a 75 'NOLINT(category)' comment to the line. NOLINT or NOLINT(*) 76 suppresses errors of all categories on that line. 78 The files passed in will be linted; at least one file must be provided. 79 Default linted extensions are .cc, .cpp, .cu, .cuh and .h. Change the 80 extensions with the --extensions flag. 85 By default, the output is formatted to ease emacs parsing. Visual Studio 86 compatible output (vs7) may also be used. Other formats are unsupported. 89 Specify a number 0-5 to restrict errors to certain verbosity levels. 92 Specify a comma-separated list of category-filters to apply: only 93 error messages whose category names pass the filters will be printed. 94 (Category names are printed with the message and look like 95 "[whitespace/indent]".) Filters are evaluated left to right. 96 "-FOO" and "FOO" means "do not print categories that start with FOO". 97 "+FOO" means "do print categories that start with FOO". 99 Examples: --filter=-whitespace,+whitespace/braces 100 --filter=whitespace,runtime/printf,+runtime/printf_format 101 --filter=-,+build/include_what_you_use 103 To see a list of all the categories used in cpplint, pass no arg: 106 counting=total|toplevel|detailed 107 The total number of errors found is always printed. If 108 'toplevel' is provided, then the count of errors in each of 109 the top-level categories like 'build' and 'whitespace' will 110 also be printed. If 'detailed' is provided, then a count 111 is provided for each category like 'build/class'. 114 The root directory used for deriving header guard CPP variable. 115 By default, the header guard CPP variable is calculated as the relative 116 path to the directory that contains .git, .hg, or .svn. When this flag 117 is specified, the relative path is calculated from the specified 118 directory. If the specified directory does not exist, this flag is 122 Assuming that src/.git exists, the header guard CPP variables for 123 src/chrome/browser/ui/browser.h are: 125 No flag => CHROME_BROWSER_UI_BROWSER_H_ 126 --root=chrome => BROWSER_UI_BROWSER_H_ 127 --root=chrome/browser => UI_BROWSER_H_ 130 This is the allowed line length for the project. The default value is 136 extensions=extension,extension,... 137 The allowed file extensions that cpplint will check 142 cpplint.py supports per-directory configurations specified in CPPLINT.cfg 143 files. CPPLINT.cfg file can contain a number of key=value pairs. 144 Currently the following options are supported: 147 filter=+filter1,-filter2,... 151 "set noparent" option prevents cpplint from traversing directory tree 152 upwards looking for more .cfg files in parent directories. This option 153 is usually placed in the top-level project directory. 155 The "filter" option is similar in function to --filter flag. It specifies 156 message filters in addition to the |_DEFAULT_FILTERS| and those specified 157 through --filter command-line flag. 159 "exclude_files" allows to specify a regular expression to be matched against 160 a file name. If the expression matches, the file is skipped and not run 163 "linelength" allows to specify the allowed line length for the project. 165 CPPLINT.cfg has an effect on files in the same directory and all 166 sub-directories, unless overridden by a nested configuration file. 169 filter=-build/include_order,+build/include_alpha 172 The above example disables build/include_order warning and enables 173 build/include_alpha as well as excludes all .cc from being 174 processed by linter, in the current directory (where the .cfg 175 file is located) and all sub-directories. 182 _ERROR_CATEGORIES = [
186 'build/endif_comment',
187 'build/explicit_make_pair',
188 'build/forward_decl',
189 'build/header_guard',
191 'build/include_alpha',
192 'build/include_order',
193 'build/include_what_you_use',
195 'build/printf_format',
196 'build/storage_class',
198 'readability/alt_tokens',
199 'readability/braces',
200 'readability/casting',
202 'readability/constructors',
203 'readability/fn_size',
204 'readability/function',
205 'readability/inheritance',
206 'readability/multiline_comment',
207 'readability/multiline_string',
208 'readability/namespace',
209 'readability/nolint',
211 'readability/strings',
219 'runtime/invalid_increment',
220 'runtime/member_string_references',
222 'runtime/indentation_namespace',
225 'runtime/printf_format',
226 'runtime/references',
228 'runtime/threadsafe_fn',
230 'whitespace/blank_line',
233 'whitespace/comments',
234 'whitespace/empty_conditional_body',
235 'whitespace/empty_loop_body',
236 'whitespace/end_of_line',
237 'whitespace/ending_newline',
238 'whitespace/forcolon',
240 'whitespace/line_length',
241 'whitespace/newline',
242 'whitespace/operators',
244 'whitespace/semicolon',
251 _LEGACY_ERROR_CATEGORIES = [
252 'readability/streams',
259 _DEFAULT_FILTERS = [
'-build/include_alpha']
266 _CPP_HEADERS = frozenset([
327 'condition_variable',
407 _THIRD_PARTY_HEADERS_PATTERN = re.compile(
408 r'^(?:[^/]*[A-Z][^/]*\.h|lua\.h|lauxlib\.h|lualib\.h)$')
416 'EXPECT_TRUE_M',
'EXPECT_TRUE',
417 'ASSERT_TRUE_M',
'ASSERT_TRUE',
418 'EXPECT_FALSE_M',
'EXPECT_FALSE',
419 'ASSERT_FALSE_M',
'ASSERT_FALSE',
423 _CHECK_REPLACEMENT = dict([(m, {})
for m
in _CHECK_MACROS])
425 for op, replacement
in [(
'==',
'EQ'), (
'!=',
'NE'),
426 (
'>=',
'GE'), (
'>',
'GT'),
427 (
'<=',
'LE'), (
'<',
'LT')]:
428 _CHECK_REPLACEMENT[
'DCHECK'][op] =
'DCHECK_%s' % replacement
429 _CHECK_REPLACEMENT[
'CHECK'][op] =
'CHECK_%s' % replacement
430 _CHECK_REPLACEMENT[
'EXPECT_TRUE'][op] =
'EXPECT_%s' % replacement
431 _CHECK_REPLACEMENT[
'ASSERT_TRUE'][op] =
'ASSERT_%s' % replacement
432 _CHECK_REPLACEMENT[
'EXPECT_TRUE_M'][op] =
'EXPECT_%s_M' % replacement
433 _CHECK_REPLACEMENT[
'ASSERT_TRUE_M'][op] =
'ASSERT_%s_M' % replacement
435 for op, inv_replacement
in [(
'==',
'NE'), (
'!=',
'EQ'),
436 (
'>=',
'LT'), (
'>',
'LE'),
437 (
'<=',
'GT'), (
'<',
'GE')]:
438 _CHECK_REPLACEMENT[
'EXPECT_FALSE'][op] =
'EXPECT_%s' % inv_replacement
439 _CHECK_REPLACEMENT[
'ASSERT_FALSE'][op] =
'ASSERT_%s' % inv_replacement
440 _CHECK_REPLACEMENT[
'EXPECT_FALSE_M'][op] =
'EXPECT_%s_M' % inv_replacement
441 _CHECK_REPLACEMENT[
'ASSERT_FALSE_M'][op] =
'ASSERT_%s_M' % inv_replacement
448 _ALT_TOKEN_REPLACEMENT = {
467 _ALT_TOKEN_REPLACEMENT_PATTERN = re.compile(
468 r'[ =()](' + (
'|'.join(_ALT_TOKEN_REPLACEMENT.keys())) +
r')(?=[ (]|$)')
475 _LIKELY_MY_HEADER = 3
476 _POSSIBLE_MY_HEADER = 4
486 _MATCH_ASM = re.compile(
r'^\s*(?:asm|_asm|__asm|__asm__)' 487 r'(?:\s+(volatile|__volatile__))?' 491 _regexp_compile_cache = {}
495 _error_suppressions = {}
507 _valid_extensions = set([
'cc',
'h',
'hpp',
'cpp',
'cu',
'cuh'])
510 """Updates the global list of error-suppressions. 512 Parses any NOLINT comments on the current line, updating the global 513 error_suppressions store. Reports an error if the NOLINT comment 517 filename: str, the name of the input file. 518 raw_line: str, the line of input text, with comments. 519 linenum: int, the number of the current line. 520 error: function, an error handler. 522 matched =
Search(
r'\bNOLINT(NEXTLINE)?\b(\([^)]+\))?', raw_line)
525 suppressed_line = linenum + 1
527 suppressed_line = linenum
528 category = matched.group(2)
529 if category
in (
None,
'(*)'):
530 _error_suppressions.setdefault(
None, set()).add(suppressed_line)
532 if category.startswith(
'(')
and category.endswith(
')'):
533 category = category[1:-1]
534 if category
in _ERROR_CATEGORIES:
535 _error_suppressions.setdefault(category, set()).add(suppressed_line)
536 elif category
not in _LEGACY_ERROR_CATEGORIES:
537 error(filename, linenum,
'readability/nolint', 5,
538 'Unknown NOLINT error category: %s' % category)
542 """Resets the set of NOLINT suppressions to empty.""" 543 _error_suppressions.clear()
547 """Returns true if the specified error category is suppressed on this line. 549 Consults the global error_suppressions map populated by 550 ParseNolintSuppressions/ResetNolintSuppressions. 553 category: str, the category of the error. 554 linenum: int, the current line number. 556 bool, True iff the error should be suppressed due to a NOLINT comment. 558 return (linenum
in _error_suppressions.get(category, set())
or 559 linenum
in _error_suppressions.get(
None, set()))
563 """Matches the string with the pattern, caching the compiled regexp.""" 567 if pattern
not in _regexp_compile_cache:
568 _regexp_compile_cache[pattern] = sre_compile.compile(pattern)
569 return _regexp_compile_cache[pattern].match(s)
573 """Replaces instances of pattern in a string with a replacement. 575 The compiled regex is kept in a cache shared by Match and Search. 578 pattern: regex pattern 579 rep: replacement text 583 string with replacements made (or original string if no replacements) 585 if pattern
not in _regexp_compile_cache:
586 _regexp_compile_cache[pattern] = sre_compile.compile(pattern)
587 return _regexp_compile_cache[pattern].sub(rep, s)
591 """Searches the string for the pattern, caching the compiled regexp.""" 592 if pattern
not in _regexp_compile_cache:
593 _regexp_compile_cache[pattern] = sre_compile.compile(pattern)
594 return _regexp_compile_cache[pattern].search(s)
598 """Tracks line numbers for includes, and the order in which includes appear. 600 include_list contains list of lists of (header, line number) pairs. 601 It's a lists of lists rather than just one flat list to make it 602 easier to update across preprocessor boundaries. 604 Call CheckNextIncludeOrder() once for each header in the file, passing 605 in the type constants defined above. Calls in an illegal order will 606 raise an _IncludeError with an appropriate error message. 618 _C_SYS_HEADER:
'C system header',
619 _CPP_SYS_HEADER:
'C++ system header',
620 _LIKELY_MY_HEADER:
'header this file implements',
621 _POSSIBLE_MY_HEADER:
'header this file may implement',
622 _OTHER_HEADER:
'other header',
625 _INITIAL_SECTION:
"... nothing. (This can't be an error.)",
626 _MY_H_SECTION:
'a header this file implements',
627 _C_SECTION:
'C system header',
628 _CPP_SECTION:
'C++ system header',
629 _OTHER_H_SECTION:
'other header',
637 """Check if a header has already been included. 640 header: header to check. 642 Line number of previous occurrence, or -1 if the header has not 646 for f
in section_list:
652 """Reset section checking for preprocessor directive. 655 directive: preprocessor directive (e.g. "if", "else"). 664 if directive
in (
'if',
'ifdef',
'ifndef'):
665 self.include_list.append([])
666 elif directive
in (
'else',
'elif'):
673 """Returns a path canonicalized for alphabetical comparison. 675 - replaces "-" with "_" so they both cmp the same. 676 - removes '-inl' since we don't require them to be after the main header. 677 - lowercase everything, just in case. 680 header_path: Path to be canonicalized. 685 return header_path.replace(
'-inl.h',
'.h').replace(
'-',
'_').lower()
688 """Check if a header is in alphabetical order with the previous header. 691 clean_lines: A CleansedLines instance containing the file. 692 linenum: The number of the line to check. 693 header_path: Canonicalized header to be checked. 696 Returns true if the header is in alphabetical order. 704 Match(
r'^\s*#\s*include\b', clean_lines.elided[linenum - 1])):
709 """Returns a non-empty error message if the next header is out of order. 711 This function also updates the internal state to be ready to check 715 header_type: One of the _XXX_HEADER constants defined above. 718 The empty string if the header is in the right order, or an 719 error message describing what's wrong. 722 error_message = (
'Found %s after %s' %
728 if header_type == _C_SYS_HEADER:
734 elif header_type == _CPP_SYS_HEADER:
740 elif header_type == _LIKELY_MY_HEADER:
745 elif header_type == _POSSIBLE_MY_HEADER:
753 assert header_type == _OTHER_HEADER
763 """Maintains module-wide state..""" 781 """Sets the output format for errors.""" 785 """Sets the module's verbosity, and returns the previous setting.""" 788 return last_verbose_level
791 """Sets the module's counting options.""" 795 """Sets the error-message filters. 797 These filters are applied when deciding whether to emit a given 801 filters: A string of comma-separated filters (eg "+whitespace/indent"). 802 Each filter should start with + or -; else we die. 805 ValueError: The comma-separated filters did not all start with '+' or '-'. 806 E.g. "-,+whitespace,-whitespace/indent,whitespace/badfilter" 809 self.
filters = _DEFAULT_FILTERS[:]
813 """ Adds more filters to the existing list of error-message filters. """ 814 for filt
in filters.split(
','):
815 clean_filt = filt.strip()
817 self.filters.append(clean_filt)
819 if not (filt.startswith(
'+')
or filt.startswith(
'-')):
820 raise ValueError(
'Every filter in --filters must start with + or -' 821 ' (%s does not)' % filt)
824 """ Saves the current filter list to backup storage.""" 828 """ Restores filters previously backed up.""" 832 """Sets the module's error statistic back to zero.""" 837 """Bumps the module's error statistic.""" 839 if self.
counting in (
'toplevel',
'detailed'):
841 category = category.split(
'/')[0]
847 """Print a summary of errors by category, and the total.""" 848 for category, count
in self.errors_by_category.iteritems():
849 sys.stderr.write(
'Category \'%s\' errors found: %d\n' %
851 sys.stderr.write(
'Total errors found: %d\n' % self.
error_count)
857 """Gets the module's output format.""" 858 return _cpplint_state.output_format
862 """Sets the module's output format.""" 863 _cpplint_state.SetOutputFormat(output_format)
867 """Returns the module's verbosity setting.""" 868 return _cpplint_state.verbose_level
872 """Sets the module's verbosity, and returns the previous setting.""" 873 return _cpplint_state.SetVerboseLevel(level)
877 """Sets the module's counting options.""" 878 _cpplint_state.SetCountingStyle(level)
882 """Returns the module's list of output filters, as a list.""" 883 return _cpplint_state.filters
887 """Sets the module's error-message filters. 889 These filters are applied when deciding whether to emit a given 893 filters: A string of comma-separated filters (eg "whitespace/indent"). 894 Each filter should start with + or -; else we die. 896 _cpplint_state.SetFilters(filters)
899 """Adds more filter overrides. 901 Unlike _SetFilters, this function does not reset the current list of filters 905 filters: A string of comma-separated filters (eg "whitespace/indent"). 906 Each filter should start with + or -; else we die. 908 _cpplint_state.AddFilters(filters)
911 """ Saves the current filter list to backup storage.""" 912 _cpplint_state.BackupFilters()
915 """ Restores filters previously backed up.""" 916 _cpplint_state.RestoreFilters()
919 """Tracks current function name and the number of lines in its body.""" 921 _NORMAL_TRIGGER = 250
930 """Start analyzing function body. 933 function_name: The name of the function being tracked. 940 """Count line in current function body.""" 944 def Check(self, error, filename, linenum):
945 """Report if too many lines in function body. 948 error: The function to call with any errors found. 949 filename: The name of the current file. 950 linenum: The number of the line to check. 963 error(filename, linenum,
'readability/fn_size', error_level,
964 'Small and focused functions are preferred:' 965 ' %s has %d non-comment lines' 966 ' (error triggered by exceeding %d lines).' % (
970 """Stop analyzing function body.""" 975 """Indicates a problem with the include order in a file.""" 979 class FileInfo(object):
980 """Provides utility functions for filenames. 982 FileInfo provides easy access to the components of a file's path 983 relative to the project root. 990 """Make Windows paths like Unix.""" 991 return os.path.abspath(self.
_filename).replace(
'\\',
'/')
994 """FullName after removing the local path to the repository. 996 If we have a real absolute path name here we can try to do something smart: 997 detecting the root of the checkout and truncating /path/to/checkout from 998 the name so that we get header guards that don't include things like 999 "C:\Documents and Settings\..." or "/home/username/..." in them and thus 1000 people on different computers who have checked the source out to different 1001 locations won't see bogus errors. 1005 if os.path.exists(fullname):
1006 project_dir = os.path.dirname(fullname)
1008 if os.path.exists(os.path.join(project_dir,
".svn")):
1011 root_dir = project_dir
1012 one_up_dir = os.path.dirname(root_dir)
1013 while os.path.exists(os.path.join(one_up_dir,
".svn")):
1014 root_dir = os.path.dirname(root_dir)
1015 one_up_dir = os.path.dirname(one_up_dir)
1017 prefix = os.path.commonprefix([root_dir, project_dir])
1018 return fullname[len(prefix) + 1:]
1022 root_dir = os.path.dirname(fullname)
1023 while (root_dir != os.path.dirname(root_dir)
and 1024 not os.path.exists(os.path.join(root_dir,
".git"))
and 1025 not os.path.exists(os.path.join(root_dir,
".hg"))
and 1026 not os.path.exists(os.path.join(root_dir,
".svn"))):
1027 root_dir = os.path.dirname(root_dir)
1029 if (os.path.exists(os.path.join(root_dir,
".git"))
or 1030 os.path.exists(os.path.join(root_dir,
".hg"))
or 1031 os.path.exists(os.path.join(root_dir,
".svn"))):
1032 prefix = os.path.commonprefix([root_dir, project_dir])
1033 return fullname[len(prefix) + 1:]
1039 """Splits the file into the directory, basename, and extension. 1041 For 'chrome/browser/browser.cc', Split() would 1042 return ('chrome/browser', 'browser', '.cc') 1045 A tuple of (directory, basename, extension). 1049 project, rest = os.path.split(googlename)
1050 return (project,) + os.path.splitext(rest)
1053 """File base name - text after the final slash, before the final period.""" 1054 return self.
Split()[1]
1057 """File extension - text following the final period.""" 1058 return self.
Split()[2]
1061 """File has no source file extension.""" 1062 return '/'.join(self.
Split()[0:2])
1065 """File has a source file extension.""" 1066 return self.
Extension()[1:]
in (
'c',
'cc',
'cpp',
'cxx')
1070 """If confidence >= verbose, category passes filter and is not suppressed.""" 1078 if confidence < _cpplint_state.verbose_level:
1083 if one_filter.startswith(
'-'):
1084 if category.startswith(one_filter[1:]):
1086 elif one_filter.startswith(
'+'):
1087 if category.startswith(one_filter[1:]):
1097 def Error(filename, linenum, category, confidence, message):
1098 """Logs the fact we've found a lint error. 1100 We log where the error was found, and also our confidence in the error, 1101 that is, how certain we are this is a legitimate style regression, and 1102 not a misidentification or a use that's sometimes justified. 1104 False positives can be suppressed by the use of 1105 "cpplint(category)" comments on the offending line. These are 1106 parsed into _error_suppressions. 1109 filename: The name of the file containing the error. 1110 linenum: The number of the line containing the error. 1111 category: A string used to describe the "category" this bug 1112 falls under: "whitespace", say, or "runtime". Categories 1113 may have a hierarchy separated by slashes: "whitespace/indent". 1114 confidence: A number from 1-5 representing a confidence score for 1115 the error, with 5 meaning that we are certain of the problem, 1116 and 1 meaning that it could be a legitimate construct. 1117 message: The error message. 1120 _cpplint_state.IncrementErrorCount(category)
1121 if _cpplint_state.output_format ==
'vs7':
1122 sys.stderr.write(
'%s(%s): %s [%s] [%d]\n' % (
1123 filename, linenum, message, category, confidence))
1124 elif _cpplint_state.output_format ==
'eclipse':
1125 sys.stderr.write(
'%s:%s: warning: %s [%s] [%d]\n' % (
1126 filename, linenum, message, category, confidence))
1128 sys.stderr.write(
'%s:%s: %s [%s] [%d]\n' % (
1129 filename, linenum, message, category, confidence))
1133 _RE_PATTERN_CLEANSE_LINE_ESCAPES = re.compile(
1134 r'\\([abfnrtv?"\\\']|\d+|x[0-9a-fA-F]+)')
1136 _RE_PATTERN_C_COMMENTS =
r'/\*(?:[^*]|\*(?!/))*\*/' 1145 _RE_PATTERN_CLEANSE_LINE_C_COMMENTS = re.compile(
1146 r'(\s*' + _RE_PATTERN_C_COMMENTS +
r'\s*$|' +
1147 _RE_PATTERN_C_COMMENTS +
r'\s+|' +
1148 r'\s+' + _RE_PATTERN_C_COMMENTS +
r'(?=\W)|' +
1149 _RE_PATTERN_C_COMMENTS +
r')')
1153 """Does line terminate so, that the next symbol is in string constant. 1155 This function does not consider single-line nor multi-line comments. 1158 line: is a partial line of code starting from the 0..n. 1161 True, if next character appended to 'line' is inside a 1165 line = line.replace(
r'\\',
'XX')
1166 return ((line.count(
'"') - line.count(
r'\"') - line.count(
"'\"'")) & 1) == 1
1170 """Removes C++11 raw strings from lines. 1173 static const char kData[] = R"( 1178 static const char kData[] = "" 1179 (replaced by blank line) 1183 raw_lines: list of raw lines. 1186 list of lines with C++11 raw strings replaced by empty strings. 1190 lines_without_raw_strings = []
1191 for line
in raw_lines:
1194 end = line.find(delimiter)
1199 leading_space =
Match(
r'^(\s*)\S', line)
1200 line = leading_space.group(1) +
'""' + line[end + len(delimiter):]
1209 while delimiter
is None:
1212 matched =
Match(
r'^(.*)\b(?:R|u8R|uR|UR|LR)"([^\s\\()]*)\((.*)$', line)
1214 delimiter =
')' + matched.group(2) +
'"' 1216 end = matched.group(3).find(delimiter)
1219 line = (matched.group(1) +
'""' +
1220 matched.group(3)[end + len(delimiter):])
1224 line = matched.group(1) +
'""' 1228 lines_without_raw_strings.append(line)
1232 return lines_without_raw_strings
1236 """Find the beginning marker for a multiline comment.""" 1237 while lineix < len(lines):
1238 if lines[lineix].strip().startswith(
'/*'):
1240 if lines[lineix].strip().find(
'*/', 2) < 0:
1247 """We are inside a comment, find the end marker.""" 1248 while lineix < len(lines):
1249 if lines[lineix].strip().endswith(
'*/'):
1256 """Clears a range of lines for multi-line comments.""" 1259 for i
in range(begin, end):
1264 """Removes multiline (c-style) comments from lines.""" 1266 while lineix < len(lines):
1268 if lineix_begin >= len(lines):
1271 if lineix_end >= len(lines):
1272 error(filename, lineix_begin + 1,
'readability/multiline_comment', 5,
1273 'Could not find end of multi-line comment')
1276 lineix = lineix_end + 1
1280 """Removes //-comments and single-line C-style /* */ comments. 1283 line: A line of C++ source. 1286 The line with single-line comments removed. 1288 commentpos = line.find(
'//')
1289 if commentpos != -1
and not IsCppString(line[:commentpos]):
1290 line = line[:commentpos].rstrip()
1292 return _RE_PATTERN_CLEANSE_LINE_C_COMMENTS.sub(
'', line)
1296 """Holds 4 copies of all lines with different preprocessing applied to them. 1298 1) elided member contains lines without strings and comments. 1299 2) lines member contains lines without comments. 1300 3) raw_lines member contains all the lines without processing. 1301 4) lines_without_raw_strings member is same as raw_lines, but with C++11 raw 1303 All these members are of <type 'list'>, and of the same length. 1319 """Returns the number of lines represented.""" 1324 """Collapses strings and chars on a line to simple "" or '' blocks. 1326 We nix strings first so we're not fooled by text like '"http://"' 1329 elided: The line being processed. 1332 The line with collapsed strings. 1334 if _RE_PATTERN_INCLUDE.match(elided):
1340 elided = _RE_PATTERN_CLEANSE_LINE_ESCAPES.sub(
'', elided)
1348 match =
Match(
r'^([^\'"]*)([\'"])(.*)$', elided)
1352 head, quote, tail = match.groups()
1356 second_quote = tail.find(
'"')
1357 if second_quote >= 0:
1358 collapsed += head +
'""' 1359 elided = tail[second_quote + 1:]
1373 if Search(
r'\b(?:0[bBxX]?|[1-9])[0-9a-fA-F]*$', head):
1374 match_literal =
Match(
r'^((?:\'?[0-9a-zA-Z_])*)(.*)$',
"'" + tail)
1375 collapsed += head + match_literal.group(1).replace(
"'",
'')
1376 elided = match_literal.group(2)
1378 second_quote = tail.find(
'\'')
1379 if second_quote >= 0:
1380 collapsed += head +
"''" 1381 elided = tail[second_quote + 1:]
1391 """Find the position just after the end of current parenthesized expression. 1394 line: a CleansedLines line. 1395 startpos: start searching at this position. 1396 stack: nesting stack at startpos. 1399 On finding matching end: (index just after matching end, None) 1400 On finding an unclosed expression: (-1, None) 1401 Otherwise: (-1, new stack at end of this line) 1403 for i
in xrange(startpos, len(line)):
1410 if i > 0
and line[i - 1] ==
'<':
1412 if stack
and stack[-1] ==
'<':
1416 elif i > 0
and Search(
r'\boperator\s*$', line[0:i]):
1427 while stack
and stack[-1] ==
'<':
1431 if ((stack[-1] ==
'(' and char ==
')')
or 1432 (stack[-1] ==
'[' and char ==
']')
or 1433 (stack[-1] ==
'{' and char ==
'}')):
1436 return (i + 1,
None)
1445 (line[i - 1] ==
'-' or Search(
r'\boperator\s*$', line[0:i - 1]))):
1451 if stack[-1] ==
'<':
1454 return (i + 1,
None)
1459 while stack
and stack[-1] ==
'<':
1469 """If input points to ( or { or [ or <, finds the position that closes it. 1471 If lines[linenum][pos] points to a '(' or '{' or '[' or '<', finds the 1472 linenum/pos that correspond to the closing of the expression. 1474 TODO(unknown): cpplint spends a fair bit of time matching parentheses. 1475 Ideally we would want to index all opening and closing parentheses once 1476 and have CloseExpression be just a simple lookup, but due to preprocessor 1477 tricks, this is not so easy. 1480 clean_lines: A CleansedLines instance containing the file. 1481 linenum: The number of the line to check. 1482 pos: A position on the line. 1485 A tuple (line, linenum, pos) pointer *past* the closing brace, or 1486 (line, len(lines), -1) if we never find a close. Note we ignore 1487 strings and comments when matching; and the line we return is the 1488 'cleansed' line at linenum. 1491 line = clean_lines.elided[linenum]
1492 if (line[pos]
not in '({[<')
or Match(
r'<[<=]', line[pos:]):
1493 return (line, clean_lines.NumLines(), -1)
1498 return (line, linenum, end_pos)
1501 while stack
and linenum < clean_lines.NumLines() - 1:
1503 line = clean_lines.elided[linenum]
1506 return (line, linenum, end_pos)
1509 return (line, clean_lines.NumLines(), -1)
1513 """Find position at the matching start of current expression. 1515 This is almost the reverse of FindEndOfExpressionInLine, but note 1516 that the input position and returned position differs by 1. 1519 line: a CleansedLines line. 1520 endpos: start searching at this position. 1521 stack: nesting stack at endpos. 1524 On finding matching start: (index at matching start, None) 1525 On finding an unclosed expression: (-1, None) 1526 Otherwise: (-1, new stack at beginning of this line) 1539 (line[i - 1] ==
'-' or 1540 Match(
r'\s>=\s', line[i - 1:])
or 1541 Search(
r'\boperator\s*$', line[0:i]))):
1547 if i > 0
and line[i - 1] ==
'<':
1553 if stack
and stack[-1] ==
'>':
1562 while stack
and stack[-1] ==
'>':
1566 if ((char ==
'(' and stack[-1] ==
')')
or 1567 (char ==
'[' and stack[-1] ==
']')
or 1568 (char ==
'{' and stack[-1] ==
'}')):
1579 while stack
and stack[-1] ==
'>':
1590 """If input points to ) or } or ] or >, finds the position that opens it. 1592 If lines[linenum][pos] points to a ')' or '}' or ']' or '>', finds the 1593 linenum/pos that correspond to the opening of the expression. 1596 clean_lines: A CleansedLines instance containing the file. 1597 linenum: The number of the line to check. 1598 pos: A position on the line. 1601 A tuple (line, linenum, pos) pointer *at* the opening brace, or 1602 (line, 0, -1) if we never find the matching opening brace. Note 1603 we ignore strings and comments when matching; and the line we 1604 return is the 'cleansed' line at linenum. 1606 line = clean_lines.elided[linenum]
1607 if line[pos]
not in ')}]>':
1608 return (line, 0, -1)
1613 return (line, linenum, start_pos)
1616 while stack
and linenum > 0:
1618 line = clean_lines.elided[linenum]
1621 return (line, linenum, start_pos)
1624 return (line, 0, -1)
1628 """Logs an error if no Copyright message appears at the top of the file.""" 1632 for line
in xrange(1, min(len(lines), 11)):
1633 if re.search(
r'Copyright', lines[line], re.I):
break 1635 error(filename, 0,
'legal/copyright', 5,
1636 'No copyright message found. ' 1637 'You should have a line: "Copyright [year] <Copyright Owner>"')
1641 """Return the number of leading spaces in line. 1644 line: A string to check. 1647 An integer count of leading spaces, possibly zero. 1649 indent =
Match(
r'^( *)\S', line)
1651 return len(indent.group(1))
1657 """Returns the CPP variable that should be used as a header guard. 1660 filename: The name of a C++ header file. 1663 The CPP variable that should be used as a header guard in the 1670 filename = re.sub(
r'_flymake\.h$',
'.h', filename)
1671 filename = re.sub(
r'/\.flymake/([^/]*)$',
r'/\1', filename)
1673 filename = filename.replace(
'C++',
'cpp').replace(
'c++',
'cpp')
1676 file_path_from_root = fileinfo.RepositoryName()
1678 file_path_from_root = re.sub(
'^' + _root + os.sep,
'', file_path_from_root)
1679 return re.sub(
r'[^a-zA-Z0-9]',
'_', file_path_from_root).upper() +
'_' 1683 """Checks that the file contains a header guard. 1685 Logs an error if no #ifndef header guard is present. For other 1686 headers, checks that the full pathname is used. 1689 filename: The name of the C++ header file. 1690 clean_lines: A CleansedLines instance containing the file. 1691 error: The function to call with any errors found. 1700 raw_lines = clean_lines.lines_without_raw_strings
1702 if Search(
r'//\s*NOLINT\(build/header_guard\)', i):
1712 for linenum, line
in enumerate(raw_lines):
1713 linesplit = line.split()
1714 if len(linesplit) >= 2:
1716 if not ifndef
and linesplit[0] ==
'#ifndef':
1718 ifndef = linesplit[1]
1719 ifndef_linenum = linenum
1720 if not define
and linesplit[0] ==
'#define':
1721 define = linesplit[1]
1723 if line.startswith(
'#endif'):
1725 endif_linenum = linenum
1727 if not ifndef
or not define
or ifndef != define:
1728 error(filename, 0,
'build/header_guard', 5,
1729 'No #ifndef header guard found, suggested CPP variable is: %s' %
1735 if ifndef != cppvar:
1737 if ifndef != cppvar +
'_':
1742 error(filename, ifndef_linenum,
'build/header_guard', error_level,
1743 '#ifndef header guard has wrong style, please use: %s' % cppvar)
1748 match =
Match(
r'#endif\s*//\s*' + cppvar +
r'(_)?\b', endif)
1750 if match.group(1) ==
'_':
1752 error(filename, endif_linenum,
'build/header_guard', 0,
1753 '#endif line should be "#endif // %s"' % cppvar)
1759 no_single_line_comments =
True 1760 for i
in xrange(1, len(raw_lines) - 1):
1762 if Match(
r'^(?:(?:\'(?:\.|[^\'])*\')|(?:"(?:\.|[^"])*")|[^\'"])*//', line):
1763 no_single_line_comments =
False 1766 if no_single_line_comments:
1767 match =
Match(
r'#endif\s*/\*\s*' + cppvar +
r'(_)?\s*\*/', endif)
1769 if match.group(1) ==
'_':
1771 error(filename, endif_linenum,
'build/header_guard', 0,
1772 '#endif line should be "#endif /* %s */"' % cppvar)
1776 error(filename, endif_linenum,
'build/header_guard', 5,
1777 '#endif line should be "#endif // %s"' % cppvar)
1781 """Logs an error if a .cc file does not include its header.""" 1784 if filename.endswith(
'_test.cc')
or filename.endswith(
'_unittest.cc'):
1788 headerfile = filename[0:len(filename) - 2] +
'h' 1789 if not os.path.exists(headerfile):
1791 headername =
FileInfo(headerfile).RepositoryName()
1793 for section_list
in include_state.include_list:
1794 for f
in section_list:
1795 if headername
in f[0]
or f[0]
in headername:
1797 if not first_include:
1798 first_include = f[1]
1800 error(filename, first_include,
'build/include', 5,
1801 '%s should include its header file %s' % (fileinfo.RepositoryName(),
1806 """Logs an error for each line containing bad characters. 1808 Two kinds of bad characters: 1810 1. Unicode replacement characters: These indicate that either the file 1811 contained invalid UTF-8 (likely) or Unicode replacement characters (which 1812 it shouldn't). Note that it's possible for this to throw off line 1813 numbering if the invalid UTF-8 occurred adjacent to a newline. 1815 2. NUL bytes. These are problematic for some tools. 1818 filename: The name of the current file. 1819 lines: An array of strings, each representing a line of the file. 1820 error: The function to call with any errors found. 1822 for linenum, line
in enumerate(lines):
1823 if u'\ufffd' in line:
1824 error(filename, linenum,
'readability/utf8', 5,
1825 'Line contains invalid UTF-8 (or Unicode replacement character).')
1827 error(filename, linenum,
'readability/nul', 5,
'Line contains NUL byte.')
1831 """Logs an error if there is no newline char at the end of the file. 1834 filename: The name of the current file. 1835 lines: An array of strings, each representing a line of the file. 1836 error: The function to call with any errors found. 1843 if len(lines) < 3
or lines[-2]:
1844 error(filename, len(lines) - 2,
'whitespace/ending_newline', 5,
1845 'Could not find a newline character at the end of the file.')
1849 """Logs an error if we see /* ... */ or "..." that extend past one line. 1851 /* ... */ comments are legit inside macros, for one line. 1852 Otherwise, we prefer // comments, so it's ok to warn about the 1853 other. Likewise, it's ok for strings to extend across multiple 1854 lines, as long as a line continuation character (backslash) 1855 terminates each line. Although not currently prohibited by the C++ 1856 style guide, it's ugly and unnecessary. We don't do well with either 1857 in this lint program, so we warn about both. 1860 filename: The name of the current file. 1861 clean_lines: A CleansedLines instance containing the file. 1862 linenum: The number of the line to check. 1863 error: The function to call with any errors found. 1865 line = clean_lines.elided[linenum]
1869 line = line.replace(
'\\\\',
'')
1871 if line.count(
'/*') > line.count(
'*/'):
1872 error(filename, linenum,
'readability/multiline_comment', 5,
1873 'Complex multi-line /*...*/-style comment found. ' 1874 'Lint may give bogus warnings. ' 1875 'Consider replacing these with //-style comments, ' 1876 'with #if 0...#endif, ' 1877 'or with more clearly structured multi-line comments.')
1879 if (line.count(
'"') - line.count(
'\\"')) % 2:
1880 error(filename, linenum,
'readability/multiline_string', 5,
1881 'Multi-line string ("...") found. This lint script doesn\'t ' 1882 'do well with such strings, and may give bogus warnings. ' 1883 'Use C++11 raw strings or concatenation instead.')
1898 _UNSAFE_FUNC_PREFIX =
r'(?:[-+*/=%^&|(<]\s*|>\s+)' 1900 (
'asctime(',
'asctime_r(', _UNSAFE_FUNC_PREFIX +
r'asctime\([^)]+\)'),
1901 (
'ctime(',
'ctime_r(', _UNSAFE_FUNC_PREFIX +
r'ctime\([^)]+\)'),
1902 (
'getgrgid(',
'getgrgid_r(', _UNSAFE_FUNC_PREFIX +
r'getgrgid\([^)]+\)'),
1903 (
'getgrnam(',
'getgrnam_r(', _UNSAFE_FUNC_PREFIX +
r'getgrnam\([^)]+\)'),
1904 (
'getlogin(',
'getlogin_r(', _UNSAFE_FUNC_PREFIX +
r'getlogin\(\)'),
1905 (
'getpwnam(',
'getpwnam_r(', _UNSAFE_FUNC_PREFIX +
r'getpwnam\([^)]+\)'),
1906 (
'getpwuid(',
'getpwuid_r(', _UNSAFE_FUNC_PREFIX +
r'getpwuid\([^)]+\)'),
1907 (
'gmtime(',
'gmtime_r(', _UNSAFE_FUNC_PREFIX +
r'gmtime\([^)]+\)'),
1908 (
'localtime(',
'localtime_r(', _UNSAFE_FUNC_PREFIX +
r'localtime\([^)]+\)'),
1909 (
'rand(',
'rand_r(', _UNSAFE_FUNC_PREFIX +
r'rand\(\)'),
1910 (
'strtok(',
'strtok_r(',
1911 _UNSAFE_FUNC_PREFIX +
r'strtok\([^)]+\)'),
1912 (
'ttyname(',
'ttyname_r(', _UNSAFE_FUNC_PREFIX +
r'ttyname\([^)]+\)'),
1917 """Checks for calls to thread-unsafe functions. 1919 Much code has been originally written without consideration of 1920 multi-threading. Also, engineers are relying on their old experience; 1921 they have learned posix before threading extensions were added. These 1922 tests guide the engineers to use thread-safe functions (when using 1926 filename: The name of the current file. 1927 clean_lines: A CleansedLines instance containing the file. 1928 linenum: The number of the line to check. 1929 error: The function to call with any errors found. 1931 line = clean_lines.elided[linenum]
1932 for single_thread_func, multithread_safe_func, pattern
in _THREADING_LIST:
1935 if Search(pattern, line):
1936 error(filename, linenum,
'runtime/threadsafe_fn', 2,
1937 'Consider using ' + multithread_safe_func +
1938 '...) instead of ' + single_thread_func +
1939 '...) for improved thread safety.')
1943 """Checks that VLOG() is only used for defining a logging level. 1945 For example, VLOG(2) is correct. VLOG(INFO), VLOG(WARNING), VLOG(ERROR), and 1946 VLOG(FATAL) are not. 1949 filename: The name of the current file. 1950 clean_lines: A CleansedLines instance containing the file. 1951 linenum: The number of the line to check. 1952 error: The function to call with any errors found. 1954 line = clean_lines.elided[linenum]
1955 if Search(
r'\bVLOG\((INFO|ERROR|WARNING|DFATAL|FATAL)\)', line):
1956 error(filename, linenum,
'runtime/vlog', 5,
1957 'VLOG() should be used with numeric verbosity level. ' 1958 'Use LOG() if you want symbolic severity levels.')
1962 _RE_PATTERN_INVALID_INCREMENT = re.compile(
1963 r'^\s*\*\w+(\+\+|--);')
1967 """Checks for invalid increment *count++. 1969 For example following function: 1970 void increment_counter(int* count) { 1973 is invalid, because it effectively does count++, moving pointer, and should 1974 be replaced with ++*count, (*count)++ or *count += 1. 1977 filename: The name of the current file. 1978 clean_lines: A CleansedLines instance containing the file. 1979 linenum: The number of the line to check. 1980 error: The function to call with any errors found. 1982 line = clean_lines.elided[linenum]
1983 if _RE_PATTERN_INVALID_INCREMENT.match(line):
1984 error(filename, linenum,
'runtime/invalid_increment', 5,
1985 'Changing pointer instead of value (or unused value of operator*).')
1989 if Search(
r'^#define', clean_lines[linenum]):
1992 if linenum > 0
and Search(
r'\\$', clean_lines[linenum - 1]):
1999 return Match(
r'^\s*(\btemplate\b)*.*class\s+\w+;\s*$', clean_lines[linenum])
2003 """Stores information about a generic block of code.""" 2012 """Run checks that applies to text up to the opening brace. 2014 This is mostly for checking the text after the class identifier 2015 and the "{", usually where the base class is specified. For other 2016 blocks, there isn't much to check, so we always pass. 2019 filename: The name of the current file. 2020 clean_lines: A CleansedLines instance containing the file. 2021 linenum: The number of the line to check. 2022 error: The function to call with any errors found. 2026 def CheckEnd(self, filename, clean_lines, linenum, error):
2027 """Run checks that applies to text after the closing brace. 2029 This is mostly used for checking end of namespace comments. 2032 filename: The name of the current file. 2033 clean_lines: A CleansedLines instance containing the file. 2034 linenum: The number of the line to check. 2035 error: The function to call with any errors found. 2040 """Returns true if this block is a _BlockInfo. 2042 This is convenient for verifying that an object is an instance of 2043 a _BlockInfo, but not an instance of any of the derived classes. 2046 True for this class, False for derived classes. 2052 """Stores information about an 'extern "C"' block.""" 2055 _BlockInfo.__init__(self,
True)
2059 """Stores information about a class.""" 2061 def __init__(self, name, class_or_struct, clean_lines, linenum):
2062 _BlockInfo.__init__(self,
False)
2067 if class_or_struct ==
'struct':
2085 for i
in range(linenum, clean_lines.NumLines()):
2086 line = clean_lines.elided[i]
2087 depth += line.count(
'{') - line.count(
'}')
2094 if Search(
'(^|[^:]):($|[^:])', clean_lines.elided[linenum]):
2097 def CheckEnd(self, filename, clean_lines, linenum, error):
2100 seen_last_thing_in_class =
False 2103 r'\b(DISALLOW_COPY_AND_ASSIGN|DISALLOW_IMPLICIT_CONSTRUCTORS)\(' +
2105 clean_lines.elided[i])
2107 if seen_last_thing_in_class:
2108 error(filename, i,
'readability/constructors', 3,
2109 match.group(1) +
' should be the last thing in the class')
2112 if not Match(
r'^\s*$', clean_lines.elided[i]):
2113 seen_last_thing_in_class =
True 2118 indent =
Match(
r'^( *)\}', clean_lines.elided[linenum])
2119 if indent
and len(indent.group(1)) != self.
class_indent:
2121 parent =
'struct ' + self.
name 2123 parent =
'class ' + self.
name 2124 error(filename, linenum,
'whitespace/indent', 3,
2125 'Closing brace should be aligned with beginning of %s' % parent)
2129 """Stores information about a namespace.""" 2132 _BlockInfo.__init__(self,
False)
2137 def CheckEnd(self, filename, clean_lines, linenum, error):
2138 """Check end of namespace comments.""" 2139 line = clean_lines.raw_lines[linenum]
2153 and not Match(
r'};*\s*(//|/\*).*\bnamespace\b', line)):
2170 if not Match((
r'};*\s*(//|/\*).*\bnamespace\s+' + re.escape(self.
name) +
2173 error(filename, linenum,
'readability/namespace', 5,
2174 'Namespace should be terminated with "// namespace %s"' %
2178 if not Match(
r'};*\s*(//|/\*).*\bnamespace[\*/\.\\\s]*$', line):
2181 if Match(
r'}.*\b(namespace anonymous|anonymous namespace)\b', line):
2182 error(filename, linenum,
'readability/namespace', 5,
2183 'Anonymous namespace should be terminated with "// namespace"' 2184 ' or "// anonymous namespace"')
2186 error(filename, linenum,
'readability/namespace', 5,
2187 'Anonymous namespace should be terminated with "// namespace"')
2191 """Stores checkpoints of nesting stacks when #if/#else is seen.""" 2205 """Holds states related to parsing braces.""" 2231 """Check if we have seen the opening brace for the innermost block. 2234 True if we have seen the opening brace, False if the innermost 2235 block is still expecting an opening brace. 2237 return (
not self.
stack)
or self.
stack[-1].seen_open_brace
2240 """Check if we are currently one level inside a namespace body. 2243 True if top of the stack is a namespace block, False otherwise. 2245 return self.
stack and isinstance(self.
stack[-1], _NamespaceInfo)
2248 """Check if we are currently one level inside an 'extern "C"' block. 2251 True if top of the stack is an extern block, False otherwise. 2253 return self.
stack and isinstance(self.
stack[-1], _ExternCInfo)
2256 """Check if we are currently one level inside a class or struct declaration. 2259 True if top of the stack is a class/struct, False otherwise. 2261 return self.
stack and isinstance(self.
stack[-1], _ClassInfo)
2264 """Check if we are currently one level inside an inline ASM block. 2267 True if the top of the stack is a block containing inline ASM. 2269 return self.
stack and self.
stack[-1].inline_asm != _NO_ASM
2272 """Check if current position is inside template argument list. 2275 clean_lines: A CleansedLines instance containing the file. 2276 linenum: The number of the line to check. 2277 pos: position just after the suspected template argument. 2279 True if (linenum, pos) is inside template arguments. 2281 while linenum < clean_lines.NumLines():
2283 line = clean_lines.elided[linenum]
2284 match =
Match(
r'^[^{};=\[\]\.<>]*(.)', line[pos:])
2289 token = match.group(1)
2290 pos += len(match.group(0))
2295 if token
in (
'{',
'}',
';'):
return False 2302 if token
in (
'>',
'=',
'[',
']',
'.'):
return True 2308 if pos >= len(line):
2315 (_, end_line, end_pos) =
CloseExpression(clean_lines, linenum, pos - 1)
2324 """Update preprocessor stack. 2326 We need to handle preprocessors due to classes like this: 2328 struct ResultDetailsPageElementExtensionPoint { 2330 struct ResultDetailsPageElementExtensionPoint : public Extension { 2333 We make the following assumptions (good enough for most files): 2334 - Preprocessor condition evaluates to true from #if up to first 2337 - Preprocessor condition evaluates to false from #else/#elif up 2338 to #endif. We still perform lint checks on these lines, but 2339 these do not affect nesting stack. 2342 line: current line to check. 2344 if Match(
r'^\s*#\s*(if|ifdef|ifndef)\b', line):
2348 elif Match(
r'^\s*#\s*(else|elif)\b', line):
2351 if not self.
pp_stack[-1].seen_else:
2356 self.
pp_stack[-1].stack_before_else = copy.deepcopy(self.
stack)
2359 self.
stack = copy.deepcopy(self.
pp_stack[-1].stack_before_if)
2363 elif Match(
r'^\s*#\s*endif\b', line):
2380 def Update(self, filename, clean_lines, linenum, error):
2381 """Update nesting state with current line. 2384 filename: The name of the current file. 2385 clean_lines: A CleansedLines instance containing the file. 2386 linenum: The number of the line to check. 2387 error: The function to call with any errors found. 2389 line = clean_lines.elided[linenum]
2407 inner_block = self.
stack[-1]
2408 depth_change = line.count(
'(') - line.count(
')')
2409 inner_block.open_parentheses += depth_change
2412 if inner_block.inline_asm
in (_NO_ASM, _END_ASM):
2413 if (depth_change != 0
and 2414 inner_block.open_parentheses == 1
and 2415 _MATCH_ASM.match(line)):
2417 inner_block.inline_asm = _INSIDE_ASM
2421 inner_block.inline_asm = _NO_ASM
2422 elif (inner_block.inline_asm == _INSIDE_ASM
and 2423 inner_block.open_parentheses == 0):
2425 inner_block.inline_asm = _END_ASM
2435 namespace_decl_match =
Match(
r'^\s*namespace\b\s*([:\w]+)?(.*)$', line)
2436 if not namespace_decl_match:
2439 new_namespace =
_NamespaceInfo(namespace_decl_match.group(1), linenum)
2440 self.stack.append(new_namespace)
2442 line = namespace_decl_match.group(2)
2443 if line.find(
'{') != -1:
2444 new_namespace.seen_open_brace =
True 2445 line = line[line.find(
'{') + 1:]
2452 class_decl_match =
Match(
2453 r'^(\s*(?:template\s*<[\w\s<>,:]*>\s*)?' 2454 r'(class|struct)\s+(?:[A-Z_]+\s+)*(\w+(?:::\w+)*))' 2456 if (class_decl_match
and 2457 (
not self.
stack or self.
stack[-1].open_parentheses == 0)):
2467 end_declaration = len(class_decl_match.group(1))
2470 class_decl_match.group(3), class_decl_match.group(2),
2471 clean_lines, linenum))
2472 line = class_decl_match.group(4)
2477 self.
stack[-1].CheckBegin(filename, clean_lines, linenum, error)
2480 if self.
stack and isinstance(self.
stack[-1], _ClassInfo):
2481 classinfo = self.
stack[-1]
2482 access_match =
Match(
2483 r'^(.*)\b(public|private|protected|signals)(\s+(?:slots\s*)?)?' 2487 classinfo.access = access_match.group(2)
2491 indent = access_match.group(1)
2492 if (len(indent) != classinfo.class_indent + 1
and 2493 Match(
r'^\s*$', indent)):
2494 if classinfo.is_struct:
2495 parent =
'struct ' + classinfo.name
2497 parent =
'class ' + classinfo.name
2499 if access_match.group(3):
2500 slots = access_match.group(3)
2501 error(filename, linenum,
'whitespace/indent', 3,
2502 '%s%s: should be indented +1 space inside %s' % (
2503 access_match.group(2), slots, parent))
2508 matched =
Match(
r'^[^{;)}]*([{;)}])(.*)$', line)
2512 token = matched.group(1)
2518 self.
stack[-1].seen_open_brace =
True 2519 elif Match(
r'^extern\s*"[^"]*"\s*\{', line):
2523 if _MATCH_ASM.match(line):
2524 self.
stack[-1].inline_asm = _BLOCK_ASM
2526 elif token ==
';' or token ==
')':
2540 self.
stack[-1].CheckEnd(filename, clean_lines, linenum, error)
2542 line = matched.group(2)
2545 """Get class info on the top of the stack. 2548 A _ClassInfo object if we are inside a class, or None otherwise. 2550 for i
in range(len(self.
stack), 0, -1):
2551 classinfo = self.
stack[i - 1]
2552 if isinstance(classinfo, _ClassInfo):
2557 """Checks that all classes and namespaces have been completely parsed. 2559 Call this when all lines in a file have been processed. 2561 filename: The name of the current file. 2562 error: The function to call with any errors found. 2567 for obj
in self.
stack:
2568 if isinstance(obj, _ClassInfo):
2569 error(filename, obj.starting_linenum,
'build/class', 5,
2570 'Failed to find complete declaration of class %s' %
2572 elif isinstance(obj, _NamespaceInfo):
2573 error(filename, obj.starting_linenum,
'build/namespaces', 5,
2574 'Failed to find complete declaration of namespace %s' %
2579 nesting_state, error):
2580 r"""Logs an error if we see certain non-ANSI constructs ignored by gcc-2. 2582 Complain about several constructs which gcc-2 accepts, but which are 2583 not standard C++. Warning about these in lint is one way to ease the 2584 transition to new compilers. 2585 - put storage class first (e.g. "static const" instead of "const static"). 2586 - "%lld" instead of %qd" in printf-type functions. 2587 - "%1$d" is non-standard in printf-type functions. 2588 - "\%" is an undefined character escape sequence. 2589 - text after #endif is not allowed. 2590 - invalid inner-style forward declaration. 2591 - >? and <? operators, and their >?= and <?= cousins. 2593 Additionally, check for constructor/destructor style violations and reference 2594 members, as it is very convenient to do so while checking for 2598 filename: The name of the current file. 2599 clean_lines: A CleansedLines instance containing the file. 2600 linenum: The number of the line to check. 2601 nesting_state: A NestingState instance which maintains information about 2602 the current stack of nested blocks being parsed. 2603 error: A callable to which errors are reported, which takes 4 arguments: 2604 filename, line number, error level, and message 2608 line = clean_lines.lines[linenum]
2610 if Search(
r'printf\s*\(.*".*%[-+ ]?\d*q', line):
2611 error(filename, linenum,
'runtime/printf_format', 3,
2612 '%q in format strings is deprecated. Use %ll instead.')
2614 if Search(
r'printf\s*\(.*".*%\d+\$', line):
2615 error(filename, linenum,
'runtime/printf_format', 2,
2616 '%N$ formats are unconventional. Try rewriting to avoid them.')
2619 line = line.replace(
'\\\\',
'')
2621 if Search(
r'("|\').*\\(%|\[|\(|{)', line):
2622 error(filename, linenum,
'build/printf_format', 3,
2623 '%, [, (, and { are undefined character escapes. Unescape them.')
2626 line = clean_lines.elided[linenum]
2628 if Search(
r'\b(const|volatile|void|char|short|int|long' 2629 r'|float|double|signed|unsigned' 2630 r'|schar|u?int8|u?int16|u?int32|u?int64)' 2631 r'\s+(register|static|extern|typedef)\b',
2633 error(filename, linenum,
'build/storage_class', 5,
2634 'Storage class (static, extern, typedef, etc) should be first.')
2636 if Match(
r'\s*#\s*endif\s*[^/\s]+', line):
2637 error(filename, linenum,
'build/endif_comment', 5,
2638 'Uncommented text after #endif is non-standard. Use a comment.')
2640 if Match(
r'\s*class\s+(\w+\s*::\s*)+\w+\s*;', line):
2641 error(filename, linenum,
'build/forward_decl', 5,
2642 'Inner-style forward declarations are invalid. Remove this line.')
2644 if Search(
r'(\w+|[+-]?\d+(\.\d*)?)\s*(<|>)\?=?\s*(\w+|[+-]?\d+)(\.\d*)?',
2646 error(filename, linenum,
'build/deprecated', 3,
2647 '>? and <? (max and min) operators are non-standard and deprecated.')
2649 if Search(
r'^\s*const\s*string\s*&\s*\w+\s*;', line):
2657 error(filename, linenum,
'runtime/member_string_references', 2,
2658 'const string& members are dangerous. It is much better to use ' 2659 'alternatives, such as pointers or simple constants.')
2664 classinfo = nesting_state.InnermostClass()
2665 if not classinfo
or not classinfo.seen_open_brace:
2670 base_classname = classinfo.name.split(
'::')[-1]
2676 explicit_constructor_match =
Match(
2677 r'\s+(?:inline\s+)?(explicit\s+)?(?:inline\s+)?%s\s*' 2678 r'\(((?:[^()]|\([^()]*\))*)\)' 2679 % re.escape(base_classname),
2682 if explicit_constructor_match:
2683 is_marked_explicit = explicit_constructor_match.group(1)
2685 if not explicit_constructor_match.group(2):
2686 constructor_args = []
2688 constructor_args = explicit_constructor_match.group(2).split(
',')
2693 while i < len(constructor_args):
2694 constructor_arg = constructor_args[i]
2695 while (constructor_arg.count(
'<') > constructor_arg.count(
'>')
or 2696 constructor_arg.count(
'(') > constructor_arg.count(
')')):
2697 constructor_arg +=
',' + constructor_args[i + 1]
2698 del constructor_args[i + 1]
2699 constructor_args[i] = constructor_arg
2702 defaulted_args = [arg
for arg
in constructor_args
if '=' in arg]
2703 noarg_constructor = (
not constructor_args
or 2705 (len(constructor_args) == 1
and 2706 constructor_args[0].strip() ==
'void'))
2707 onearg_constructor = ((len(constructor_args) == 1
and 2708 not noarg_constructor)
or 2710 (len(constructor_args) >= 1
and 2711 not noarg_constructor
and 2712 len(defaulted_args) >= len(constructor_args) - 1))
2713 initializer_list_constructor = bool(
2714 onearg_constructor
and 2715 Search(
r'\bstd\s*::\s*initializer_list\b', constructor_args[0]))
2716 copy_constructor = bool(
2717 onearg_constructor
and 2718 Match(
r'(const\s+)?%s(\s*<[^>]*>)?(\s+const)?\s*(?:<\w+>\s*)?&' 2719 % re.escape(base_classname), constructor_args[0].strip()))
2721 if (
not is_marked_explicit
and 2722 onearg_constructor
and 2723 not initializer_list_constructor
and 2724 not copy_constructor):
2726 error(filename, linenum,
'runtime/explicit', 5,
2727 'Constructors callable with one argument ' 2728 'should be marked explicit.')
2730 error(filename, linenum,
'runtime/explicit', 5,
2731 'Single-parameter constructors should be marked explicit.')
2732 elif is_marked_explicit
and not onearg_constructor:
2733 if noarg_constructor:
2734 error(filename, linenum,
'runtime/explicit', 5,
2735 'Zero-parameter constructors should not be marked explicit.')
2737 error(filename, linenum,
'runtime/explicit', 0,
2738 'Constructors that require multiple arguments ' 2739 'should not be marked explicit.')
2743 """Checks for the correctness of various spacing around function calls. 2746 filename: The name of the current file. 2747 clean_lines: A CleansedLines instance containing the file. 2748 linenum: The number of the line to check. 2749 error: The function to call with any errors found. 2751 line = clean_lines.elided[linenum]
2758 for pattern
in (
r'\bif\s*\((.*)\)\s*{',
2759 r'\bfor\s*\((.*)\)\s*{',
2760 r'\bwhile\s*\((.*)\)\s*[{;]',
2761 r'\bswitch\s*\((.*)\)\s*{'):
2762 match =
Search(pattern, line)
2764 fncall = match.group(1)
2781 not Search(
r'\b(if|for|while|switch|return|new|delete|catch|sizeof)\b',
2784 not Search(
r' \([^)]+\)\([^)]*(\)|,$)', fncall)
and 2786 not Search(
r' \([^)]+\)\[[^\]]+\]', fncall)):
2787 if Search(
r'\w\s*\(\s(?!\s*\\$)', fncall):
2788 error(filename, linenum,
'whitespace/parens', 4,
2789 'Extra space after ( in function call')
2790 elif Search(
r'\(\s+(?!(\s*\\)|\()', fncall):
2791 error(filename, linenum,
'whitespace/parens', 2,
2792 'Extra space after (')
2793 if (
Search(
r'\w\s+\(', fncall)
and 2794 not Search(
r'#\s*define|typedef|using\s+\w+\s*=', fncall)
and 2795 not Search(
r'\w\s+\((\w+::)*\*\w+\)\(', fncall)
and 2796 not Search(
r'\bcase\s+\(', fncall)):
2799 if Search(
r'\boperator_*\b', line):
2800 error(filename, linenum,
'whitespace/parens', 0,
2801 'Extra space before ( in function call')
2803 error(filename, linenum,
'whitespace/parens', 4,
2804 'Extra space before ( in function call')
2807 if Search(
r'[^)]\s+\)\s*[^{\s]', fncall):
2810 if Search(
r'^\s+\)', fncall):
2811 error(filename, linenum,
'whitespace/parens', 2,
2812 'Closing ) should be moved to the previous line')
2814 error(filename, linenum,
'whitespace/parens', 2,
2815 'Extra space before )')
2819 """Returns true if the given line is blank. 2821 We consider a line to be blank if the line is empty or consists of 2825 line: A line of a string. 2828 True, if the given line is blank. 2830 return not line
or line.isspace()
2835 is_namespace_indent_item = (
2836 len(nesting_state.stack) > 1
and 2837 nesting_state.stack[-1].check_namespace_indentation
and 2838 isinstance(nesting_state.previous_stack_top, _NamespaceInfo)
and 2839 nesting_state.previous_stack_top == nesting_state.stack[-2])
2842 clean_lines.elided, line):
2848 function_state, error):
2849 """Reports for long function bodies. 2851 For an overview why this is done, see: 2852 http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Write_Short_Functions 2854 Uses a simplistic algorithm assuming other style guidelines 2855 (especially spacing) are followed. 2856 Only checks unindented functions, so class members are unchecked. 2857 Trivial bodies are unchecked, so constructors with huge initializer lists 2859 Blank/comment lines are not counted so as to avoid encouraging the removal 2860 of vertical space and comments just to get through a lint check. 2861 NOLINT *on the last line of a function* disables this check. 2864 filename: The name of the current file. 2865 clean_lines: A CleansedLines instance containing the file. 2866 linenum: The number of the line to check. 2867 function_state: Current function name and lines in body so far. 2868 error: The function to call with any errors found. 2870 lines = clean_lines.lines
2871 line = lines[linenum]
2874 starting_func =
False 2875 regexp =
r'(\w(\w|::|\*|\&|\s)*)\(' 2876 match_result =
Match(regexp, line)
2880 function_name = match_result.group(1).split()[-1]
2881 if function_name ==
'TEST' or function_name ==
'TEST_F' or (
2882 not Match(
r'[A-Z_]+$', function_name)):
2883 starting_func =
True 2887 for start_linenum
in xrange(linenum, clean_lines.NumLines()):
2888 start_line = lines[start_linenum]
2889 joined_line +=
' ' + start_line.lstrip()
2890 if Search(
r'(;|})', start_line):
2893 elif Search(
r'{', start_line):
2895 function =
Search(
r'((\w|:)*)\(', line).group(1)
2896 if Match(
r'TEST', function):
2897 parameter_regexp =
Search(
r'(\(.*\))', joined_line)
2898 if parameter_regexp:
2899 function += parameter_regexp.group(1)
2902 function_state.Begin(function)
2906 error(filename, linenum,
'readability/fn_size', 5,
2907 'Lint failed to find start of function body.')
2908 elif Match(
r'^\}\s*$', line):
2909 function_state.Check(error, filename, linenum)
2910 function_state.End()
2911 elif not Match(
r'^\s*$', line):
2912 function_state.Count()
2915 _RE_PATTERN_TODO = re.compile(
r'^//(\s*)TODO(\(.+?\))?:?(\s|$)?')
2919 """Checks for common mistakes in comments. 2922 line: The line in question. 2923 filename: The name of the current file. 2924 linenum: The number of the line to check. 2925 next_line_start: The first non-whitespace column of the next line. 2926 error: The function to call with any errors found. 2928 commentpos = line.find(
'//')
2929 if commentpos != -1:
2932 if (line.count(
'"', 0, commentpos) -
2933 line.count(
'\\"', 0, commentpos)) % 2 == 0:
2935 if (
not (
Match(
r'^.*{ *//', line)
and next_line_start == commentpos)
and 2936 ((commentpos >= 1
and 2937 line[commentpos-1]
not in string.whitespace)
or 2938 (commentpos >= 2
and 2939 line[commentpos-2]
not in string.whitespace))):
2940 error(filename, linenum,
'whitespace/comments', 2,
2941 'At least two spaces is best between code and comments')
2944 comment = line[commentpos:]
2945 match = _RE_PATTERN_TODO.match(comment)
2948 leading_whitespace = match.group(1)
2949 if len(leading_whitespace) > 1:
2950 error(filename, linenum,
'whitespace/todo', 2,
2951 'Too many spaces before TODO')
2953 username = match.group(2)
2955 error(filename, linenum,
'readability/todo', 2,
2956 'Missing username in TODO; it should look like ' 2957 '"// TODO(my_username): Stuff."')
2959 middle_whitespace = match.group(3)
2961 if middle_whitespace !=
' ' and middle_whitespace !=
'':
2962 error(filename, linenum,
'whitespace/todo', 2,
2963 'TODO(my_username) should be followed by a space')
2968 if (
Match(
r'//[^ ]*\w', comment)
and 2969 not Match(
r'(///|//\!)(\s+|$)', comment)):
2970 error(filename, linenum,
'whitespace/comments', 4,
2971 'Should have a space between // and comment')
2974 def CheckAccess(filename, clean_lines, linenum, nesting_state, error):
2975 """Checks for improper use of DISALLOW* macros. 2978 filename: The name of the current file. 2979 clean_lines: A CleansedLines instance containing the file. 2980 linenum: The number of the line to check. 2981 nesting_state: A NestingState instance which maintains information about 2982 the current stack of nested blocks being parsed. 2983 error: The function to call with any errors found. 2985 line = clean_lines.elided[linenum]
2987 matched =
Match((
r'\s*(DISALLOW_COPY_AND_ASSIGN|' 2988 r'DISALLOW_IMPLICIT_CONSTRUCTORS)'), line)
2991 if nesting_state.stack
and isinstance(nesting_state.stack[-1], _ClassInfo):
2992 if nesting_state.stack[-1].access !=
'private':
2993 error(filename, linenum,
'readability/constructors', 3,
2994 '%s must be in the private: section' % matched.group(1))
3005 """Checks for the correctness of various spacing issues in the code. 3007 Things we check for: spaces around operators, spaces after 3008 if/for/while/switch, no spaces around parens in function calls, two 3009 spaces between code and comment, don't start a block with a blank 3010 line, don't end a function with a blank line, don't add a blank line 3011 after public/protected/private, don't have too many blank lines in a row. 3014 filename: The name of the current file. 3015 clean_lines: A CleansedLines instance containing the file. 3016 linenum: The number of the line to check. 3017 nesting_state: A NestingState instance which maintains information about 3018 the current stack of nested blocks being parsed. 3019 error: The function to call with any errors found. 3025 raw = clean_lines.lines_without_raw_strings
3044 not nesting_state.InNamespaceBody()
and 3045 not nesting_state.InExternC()):
3046 elided = clean_lines.elided
3047 prev_line = elided[linenum - 1]
3048 prevbrace = prev_line.rfind(
'{')
3053 if prevbrace != -1
and prev_line[prevbrace:].find(
'}') == -1:
3062 if Match(
r' {6}\w', prev_line):
3065 search_position = linenum-2
3066 while (search_position >= 0
3067 and Match(
r' {6}\w', elided[search_position])):
3068 search_position -= 1
3069 exception = (search_position >= 0
3070 and elided[search_position][:5] ==
' :')
3078 exception = (
Match(
r' {4}\w[^\(]*\)\s*(const\s*)?(\{\s*$|:)',
3080 or Match(
r' {4}:', prev_line))
3083 error(filename, linenum,
'whitespace/blank_line', 2,
3084 'Redundant blank line at the start of a code block ' 3085 'should be deleted.')
3094 if linenum + 1 < clean_lines.NumLines():
3095 next_line = raw[linenum + 1]
3097 and Match(
r'\s*}', next_line)
3098 and next_line.find(
'} else ') == -1):
3099 error(filename, linenum,
'whitespace/blank_line', 3,
3100 'Redundant blank line at the end of a code block ' 3101 'should be deleted.')
3103 matched =
Match(
r'\s*(public|protected|private):', prev_line)
3105 error(filename, linenum,
'whitespace/blank_line', 3,
3106 'Do not leave a blank line after "%s:"' % matched.group(1))
3110 if linenum + 1 < clean_lines.NumLines():
3111 next_line = raw[linenum + 1]
3112 next_line_start = len(next_line) - len(next_line.lstrip())
3113 CheckComment(line, filename, linenum, next_line_start, error)
3116 line = clean_lines.elided[linenum]
3120 if Search(
r'\w\s+\[', line)
and not Search(
r'(?:delete|return)\s+\[', line):
3121 error(filename, linenum,
'whitespace/braces', 5,
3122 'Extra space before [')
3126 if (
Search(
r'for *\(.*[^:]:[^: ]', line)
or 3127 Search(
r'for *\(.*[^: ]:[^:]', line)):
3128 error(filename, linenum,
'whitespace/forcolon', 2,
3129 'Missing space around colon in range-based for loop')
3133 """Checks for horizontal spacing around operators. 3136 filename: The name of the current file. 3137 clean_lines: A CleansedLines instance containing the file. 3138 linenum: The number of the line to check. 3139 error: The function to call with any errors found. 3141 line = clean_lines.elided[linenum]
3150 match =
Match(
r'^(.*\boperator\b)(\S+)(\s*\(.*)$', line)
3152 line = match.group(1) + (
'_' * len(match.group(2))) + match.group(3)
3160 if ((
Search(
r'[\w.]=', line)
or 3162 and not Search(
r'\b(if|while|for) ', line)
3164 and not Search(
r'(>=|<=|==|!=|&=|\^=|\|=|\+=|\*=|\/=|\%=)', line)
3165 and not Search(
r'operator=', line)):
3166 error(filename, linenum,
'whitespace/operators', 4,
3167 'Missing spaces around =')
3184 match =
Search(
r'[^<>=!\s](==|!=|<=|>=|\|\|)[^<>=!\s,;\)]', line)
3186 error(filename, linenum,
'whitespace/operators', 3,
3187 'Missing spaces around %s' % match.group(1))
3188 elif not Match(
r'#.*include', line):
3193 match =
Match(
r'^(.*[^\s<])<[^\s=<,]', line)
3196 clean_lines, linenum, len(match.group(1)))
3198 error(filename, linenum,
'whitespace/operators', 3,
3199 'Missing spaces around <')
3204 match =
Match(
r'^(.*[^-\s>])>[^\s=>,]', line)
3207 clean_lines, linenum, len(match.group(1)))
3209 error(filename, linenum,
'whitespace/operators', 3,
3210 'Missing spaces around >')
3217 match =
Search(
r'(operator|[^\s(<])(?:L|UL|ULL|l|ul|ull)?<<([^\s,=<])', line)
3218 if (match
and not (match.group(1).isdigit()
and match.group(2).isdigit())
and 3219 not (match.group(1) ==
'operator' and match.group(2) ==
';')):
3220 error(filename, linenum,
'whitespace/operators', 3,
3221 'Missing spaces around <<')
3235 match =
Search(
r'>>[a-zA-Z_]', line)
3237 error(filename, linenum,
'whitespace/operators', 3,
3238 'Missing spaces around >>')
3241 match =
Search(
r'(!\s|~\s|[\s]--[\s;]|[\s]\+\+[\s;])', line)
3243 error(filename, linenum,
'whitespace/operators', 4,
3244 'Extra space for operator %s' % match.group(1))
3248 """Checks for horizontal spacing around parentheses. 3251 filename: The name of the current file. 3252 clean_lines: A CleansedLines instance containing the file. 3253 linenum: The number of the line to check. 3254 error: The function to call with any errors found. 3256 line = clean_lines.elided[linenum]
3259 match =
Search(
r' (if\(|for\(|while\(|switch\()', line)
3261 error(filename, linenum,
'whitespace/parens', 5,
3262 'Missing space before ( in %s' % match.group(1))
3269 match =
Search(
r'\b(if|for|while|switch)\s*' 3270 r'\(([ ]*)(.).*[^ ]+([ ]*)\)\s*{\s*$',
3273 if len(match.group(2)) != len(match.group(4)):
3274 if not (match.group(3) ==
';' and 3275 len(match.group(2)) == 1 + len(match.group(4))
or 3276 not match.group(2)
and Search(
r'\bfor\s*\(.*; \)', line)):
3277 error(filename, linenum,
'whitespace/parens', 5,
3278 'Mismatching spaces inside () in %s' % match.group(1))
3279 if len(match.group(2))
not in [0, 1]:
3280 error(filename, linenum,
'whitespace/parens', 5,
3281 'Should have zero or one spaces inside ( and ) in %s' %
3286 """Checks for horizontal spacing near commas and semicolons. 3289 filename: The name of the current file. 3290 clean_lines: A CleansedLines instance containing the file. 3291 linenum: The number of the line to check. 3292 error: The function to call with any errors found. 3294 raw = clean_lines.lines_without_raw_strings
3295 line = clean_lines.elided[linenum]
3308 Search(
r',[^,\s]', raw[linenum])):
3309 error(filename, linenum,
'whitespace/comma', 3,
3310 'Missing space after ,')
3316 if Search(
r';[^\s};\\)/]', line):
3317 error(filename, linenum,
'whitespace/semicolon', 3,
3318 'Missing space after ;')
3322 """Checks for horizontal spacing near commas. 3325 filename: The name of the current file. 3326 clean_lines: A CleansedLines instance containing the file. 3327 linenum: The number of the line to check. 3328 error: The function to call with any errors found. 3330 line = clean_lines.elided[linenum]
3336 match =
Match(
r'^(.*[^ ({>]){', line)
3367 clean_lines, linenum, len(match.group(1)))
3370 trailing_text = endline[endpos:]
3371 for offset
in xrange(endlinenum + 1,
3372 min(endlinenum + 3, clean_lines.NumLines() - 1)):
3373 trailing_text += clean_lines.elided[offset]
3374 if not Match(
r'^[\s}]*[{.;,)<>\]:]', trailing_text):
3375 error(filename, linenum,
'whitespace/braces', 5,
3376 'Missing space before {')
3379 if Search(
r'}else', line):
3380 error(filename, linenum,
'whitespace/braces', 5,
3381 'Missing space before else')
3386 if Search(
r':\s*;\s*$', line):
3387 error(filename, linenum,
'whitespace/semicolon', 5,
3388 'Semicolon defining empty statement. Use {} instead.')
3389 elif Search(
r'^\s*;\s*$', line):
3390 error(filename, linenum,
'whitespace/semicolon', 5,
3391 'Line contains only semicolon. If this should be an empty statement, ' 3393 elif (
Search(
r'\s+;\s*$', line)
and 3394 not Search(
r'\bfor\b', line)):
3395 error(filename, linenum,
'whitespace/semicolon', 5,
3396 'Extra space before last semicolon. If this should be an empty ' 3397 'statement, use {} instead.')
3401 """Check if the token ending on (linenum, column) is decltype(). 3404 clean_lines: A CleansedLines instance containing the file. 3405 linenum: the number of the line to check. 3406 column: end column of the token to check. 3408 True if this token is decltype() expression, False otherwise. 3413 if Search(
r'\bdecltype\s*$', text[0:start_col]):
3419 """Check if the token ending on (linenum, column) is the end of template<>. 3422 clean_lines: A CleansedLines instance containing the file. 3423 linenum: the number of the line to check. 3424 column: end column of the token to check. 3426 True if this token is end of a template parameter list, False otherwise. 3429 clean_lines, linenum, column)
3430 if (startpos > -1
and 3431 Search(
r'\btemplate\s*$', clean_lines.elided[startline][0:startpos])):
3437 """Check if the token ending on (linenum, column) is a type. 3439 Assumes that text to the right of the column is "&&" or a function 3443 typenames: set of type names from template-argument-list. 3444 clean_lines: A CleansedLines instance containing the file. 3445 nesting_state: A NestingState instance which maintains information about 3446 the current stack of nested blocks being parsed. 3447 linenum: the number of the line to check. 3448 column: end column of the token to check. 3450 True if this token is a type, False if we are not sure. 3452 prefix = clean_lines.elided[linenum][0:column]
3457 match =
Match(
r'^(.*)(\b\w+|[>*)&])\s*$', prefix)
3463 suffix = clean_lines.elided[linenum][column:]
3464 if Match(
r'&&\s*(?:[>,]|\.\.\.)', suffix):
3475 if (match.group(2)
in typenames
or 3476 match.group(2)
in [
'char',
'char16_t',
'char32_t',
'wchar_t',
'bool',
3477 'short',
'int',
'long',
'signed',
'unsigned',
3478 'float',
'double',
'void',
'auto',
'>',
'*',
'&']):
3484 if match.group(2) ==
')':
3486 clean_lines, linenum, len(match.group(1)) + len(match.group(2)) - 1)
3494 if Search(
r'\b(?:const_cast\s*<|static_cast\s*<|dynamic_cast\s*<|' 3495 r'reinterpret_cast\s*<|\w+\s)\s*$',
3514 line = match.group(1)
3520 match_symbol =
Match(
r'^(.*)([^\w\s,])[\w\s,]*$', line)
3524 line = clean_lines.elided[start]
3526 if not match_symbol:
3530 if match_symbol.group(2) ==
'}':
3535 if match_symbol.group(2) ==
';':
3541 before_text = match_symbol.group(1)
3542 for i
in xrange(start - 1, max(start - 6, 0), -1):
3543 before_text = clean_lines.elided[i] + before_text
3544 if Search(
r'for\s*\([^{};]*$', before_text):
3552 if match_symbol.group(2) ==
'{':
3559 line = clean_lines.elided[start][0:len(match_symbol.group(1)) + 1]
3573 if end >= clean_lines.NumLines():
3575 line = clean_lines.elided[end]
3579 if match_symbol.group(2) ==
'(':
3582 before_text = match_symbol.group(1)
3584 before_text = clean_lines.elided[linenum - 1] + before_text
3585 before_text = match_symbol.group(1)
3593 if Search(
r'(?:\]|\bfor|\bsizeof|\boperator\s*\S+\s*)\s*$', before_text):
3606 if Search(
r'(?:\bif|\bwhile|[-+=%^(<!?:,&*]\s*)$', before_text):
3611 match_func =
Match(
r'^(.*\S.*)\s+\w(?:\w|::)*(?:<[^<>]*>)?\s*$',
3612 match_symbol.group(1))
3615 if Search(
r'\b(?:explicit|inline)$', match_func.group(1)):
3617 implicit_constructor =
Match(
r'\s*(\w+)\((?:const\s+)?(\w+)', prefix)
3618 if (implicit_constructor
and 3619 implicit_constructor.group(1) == implicit_constructor.group(2)):
3621 return IsRValueType(typenames, clean_lines, nesting_state, linenum,
3622 len(match_func.group(1)))
3626 return not (nesting_state.previous_stack_top
and 3627 nesting_state.previous_stack_top.IsBlockInfo())
3629 if match_symbol.group(2) ==
'>':
3633 clean_lines, start, len(match_symbol.group(1)))
3641 """Check if current constructor or operator is deleted or default. 3644 clean_lines: A CleansedLines instance containing the file. 3645 linenum: The number of the line to check. 3647 True if this is a deleted or default constructor. 3649 open_paren = clean_lines.elided[linenum].find(
'(')
3653 clean_lines, linenum, open_paren)
3656 return Match(
r'\s*=\s*(?:delete|default)\b', close_line[close_paren:])
3660 """Check if RValue reference is allowed on a particular line. 3663 clean_lines: A CleansedLines instance containing the file. 3664 linenum: The number of the line to check. 3665 typenames: set of type names from template-argument-list. 3667 True if line is within the region where RValue references are allowed. 3670 for i
in xrange(linenum, 0, -1):
3671 line = clean_lines.elided[i]
3672 if Match(
r'GOOGLE_ALLOW_RVALUE_REFERENCES_(?:PUSH|POP)', line):
3673 if not line.endswith(
'PUSH'):
3675 for j
in xrange(linenum, clean_lines.NumLines(), 1):
3676 line = clean_lines.elided[j]
3677 if Match(
r'GOOGLE_ALLOW_RVALUE_REFERENCES_(?:PUSH|POP)', line):
3678 return line.endswith(
'POP')
3681 line = clean_lines.elided[linenum]
3682 if Search(
r'\boperator\s*=\s*\(', line):
3686 match =
Match(
r'\s*(?:[\w<>]+::)*([\w<>]+)\s*::\s*([\w<>]+)\s*\(', line)
3687 if match
and match.group(1) == match.group(2):
3689 if Search(
r'\b(?:explicit|inline)\s+[\w<>]+\s*\(', line):
3692 if Match(
r'\s*[\w<>]+\s*\(', line):
3693 previous_line =
'ReturnType' 3695 previous_line = clean_lines.elided[linenum - 1]
3696 if Match(
r'^\s*$', previous_line)
or Search(
r'[{}:;]\s*$', previous_line):
3701 match =
Match(
r'^.*?(\w+)\s*&&(.*)$', line)
3704 if match.group(1)
not in typenames:
3706 line = match.group(2)
3714 return line.find(
'&&') < 0
3718 """Find list of template arguments associated with this function declaration. 3721 clean_lines: A CleansedLines instance containing the file. 3722 linenum: Line number containing the start of the function declaration, 3723 usually one line after the end of the template-argument-list. 3725 Set of type names, or empty set if this does not appear to have 3726 any template parameters. 3730 while func_line > 0:
3731 line = clean_lines.elided[func_line]
3732 if Match(
r'^\s*$', line):
3734 if line.find(
'(') >= 0:
3742 match =
Match(
r'^(\s*template\s*)<', clean_lines.elided[func_line])
3745 start_col = len(match.group(1))
3746 _, end_line, end_col =
CloseExpression(clean_lines, func_line, start_col)
3747 if end_col > -1
and end_line == func_line:
3749 argument_list = clean_lines.elided[func_line][start_col:end_col]
3753 match =
Match(
r'^(.*)>\s*$', clean_lines.elided[func_line - 1])
3755 end_col = len(match.group(1))
3757 clean_lines, func_line - 1, end_col)
3760 while start_line < func_line - 1:
3761 argument_list += clean_lines.elided[start_line][start_col:]
3764 argument_list += clean_lines.elided[func_line - 1][start_col:end_col]
3766 if not argument_list:
3772 match =
Match(
r'^[,\s]*(?:typename|class)(?:\.\.\.)?\s+(\w+)(.*)$',
3776 typenames.add(match.group(1))
3777 argument_list = match.group(2)
3782 """Check for rvalue references. 3785 filename: The name of the current file. 3786 clean_lines: A CleansedLines instance containing the file. 3787 linenum: The number of the line to check. 3788 nesting_state: A NestingState instance which maintains information about 3789 the current stack of nested blocks being parsed. 3790 error: The function to call with any errors found. 3796 line = clean_lines.elided[linenum]
3797 match =
Match(
r'^(.*\S)&&', line)
3799 match =
Match(
r'(.*)&&\S', line)
3800 if (
not match)
or '(&&)' in line
or Search(
r'\boperator\s*$', match.group(1)):
3807 and_pos = len(match.group(1))
3808 if IsRValueType(typenames, clean_lines, nesting_state, linenum, and_pos):
3810 error(filename, linenum,
'build/c++11', 3,
3811 'RValue references are an unapproved C++ feature.')
3813 error(filename, linenum,
'whitespace/operators', 3,
3814 'Missing spaces around &&')
3818 """Checks for additional blank line issues related to sections. 3820 Currently the only thing checked here is blank line before protected/private. 3823 filename: The name of the current file. 3824 clean_lines: A CleansedLines instance containing the file. 3825 class_info: A _ClassInfo objects. 3826 linenum: The number of the line to check. 3827 error: The function to call with any errors found. 3840 if (class_info.last_line - class_info.starting_linenum <= 24
or 3841 linenum <= class_info.starting_linenum):
3844 matched =
Match(
r'\s*(public|protected|private):', clean_lines.lines[linenum])
3854 prev_line = clean_lines.lines[linenum - 1]
3856 not Search(
r'\b(class|struct)\b', prev_line)
and 3857 not Search(
r'\\$', prev_line)):
3862 end_class_head = class_info.starting_linenum
3863 for i
in range(class_info.starting_linenum, linenum):
3864 if Search(
r'\{\s*$', clean_lines.lines[i]):
3867 if end_class_head < linenum - 1:
3868 error(filename, linenum,
'whitespace/blank_line', 3,
3869 '"%s:" should be preceded by a blank line' % matched.group(1))
3873 """Return the most recent non-blank line and its line number. 3876 clean_lines: A CleansedLines instance containing the file contents. 3877 linenum: The number of the line to check. 3880 A tuple with two elements. The first element is the contents of the last 3881 non-blank line before the current line, or the empty string if this is the 3882 first non-blank line. The second is the line number of that line, or -1 3883 if this is the first non-blank line. 3886 prevlinenum = linenum - 1
3887 while prevlinenum >= 0:
3888 prevline = clean_lines.elided[prevlinenum]
3890 return (prevline, prevlinenum)
3896 """Looks for misplaced braces (e.g. at the end of line). 3899 filename: The name of the current file. 3900 clean_lines: A CleansedLines instance containing the file. 3901 linenum: The number of the line to check. 3902 error: The function to call with any errors found. 3905 line = clean_lines.elided[linenum]
3907 if Match(
r'\s*{\s*$', line):
3916 if (
not Search(
r'[,;:}{(]\s*$', prevline)
and 3917 not Match(
r'\s*#', prevline)):
3918 error(filename, linenum,
'whitespace/braces', 4,
3919 '{ should almost always be at the end of the previous line')
3922 if Match(
r'\s*else\b\s*(?:if\b|\{|$)', line):
3924 if Match(
r'\s*}\s*$', prevline):
3925 error(filename, linenum,
'whitespace/newline', 4,
3926 'An else should appear on the same line as the preceding }')
3930 if Search(
r'else if\s*\(', line):
3931 brace_on_left = bool(
Search(
r'}\s*else if\s*\(', line))
3933 pos = line.find(
'else if')
3934 pos = line.find(
'(', pos)
3937 brace_on_right = endline[endpos:].find(
'{') != -1
3938 if brace_on_left != brace_on_right:
3939 error(filename, linenum,
'readability/braces', 5,
3940 'If an else has a brace on one side, it should have it on both')
3941 elif Search(
r'}\s*else[^{]*$', line)
or Match(
r'[^}]*else\s*{', line):
3942 error(filename, linenum,
'readability/braces', 5,
3943 'If an else has a brace on one side, it should have it on both')
3946 if Search(
r'\belse [^\s{]', line)
and not Search(
r'\belse if\b', line):
3947 error(filename, linenum,
'whitespace/newline', 4,
3948 'Else clause should never be on same line as else (use 2 lines)')
3951 if Match(
r'\s*do [^\s{]', line):
3952 error(filename, linenum,
'whitespace/newline', 4,
3953 'do/while clauses should not be on a single line')
3962 if_else_match =
Search(
r'\b(if\s*\(|else\b)', line)
3963 if if_else_match
and not Match(
r'\s*#', line):
3965 endline, endlinenum, endpos = line, linenum, if_else_match.end()
3966 if_match =
Search(
r'\bif\s*\(', line)
3969 pos = if_match.end() - 1
3970 (endline, endlinenum, endpos) =
CloseExpression(clean_lines, linenum, pos)
3973 if (
not Match(
r'\s*{', endline[endpos:])
3974 and not (
Match(
r'\s*$', endline[endpos:])
3975 and endlinenum < (len(clean_lines.elided) - 1)
3976 and Match(
r'\s*{', clean_lines.elided[endlinenum + 1]))):
3977 while (endlinenum < len(clean_lines.elided)
3978 and ';' not in clean_lines.elided[endlinenum][endpos:]):
3981 if endlinenum < len(clean_lines.elided):
3982 endline = clean_lines.elided[endlinenum]
3985 endpos = endline.find(
';')
3986 if not Match(
r';[\s}]*(\\?)$', endline[endpos:]):
3990 if not Match(
r'^[^{};]*\[[^\[\]]*\][^{}]*\{[^{}]*\}\s*\)*[;,]\s*$',
3992 error(filename, linenum,
'readability/braces', 4,
3993 'If/else bodies with multiple statements require braces')
3994 elif endlinenum < len(clean_lines.elided) - 1:
3996 next_line = clean_lines.elided[endlinenum + 1]
4001 if (if_match
and Match(
r'\s*else\b', next_line)
4002 and next_indent != if_indent):
4003 error(filename, linenum,
'readability/braces', 4,
4004 'Else clause should be indented at the same level as if. ' 4005 'Ambiguous nested if/else chains require braces.')
4006 elif next_indent > if_indent:
4007 error(filename, linenum,
'readability/braces', 4,
4008 'If/else bodies with multiple statements require braces')
4012 """Looks for redundant trailing semicolon. 4015 filename: The name of the current file. 4016 clean_lines: A CleansedLines instance containing the file. 4017 linenum: The number of the line to check. 4018 error: The function to call with any errors found. 4021 line = clean_lines.elided[linenum]
4067 match =
Match(
r'^(.*\)\s*)\{', line)
4094 closing_brace_pos = match.group(1).rfind(
')')
4096 clean_lines, linenum, closing_brace_pos)
4097 if opening_parenthesis[2] > -1:
4098 line_prefix = opening_parenthesis[0][0:opening_parenthesis[2]]
4099 macro =
Search(
r'\b([A-Z_]+)\s*$', line_prefix)
4100 func =
Match(
r'^(.*\])\s*$', line_prefix)
4102 macro.group(1)
not in (
4103 'TEST',
'TEST_F',
'MATCHER',
'MATCHER_P',
'TYPED_TEST',
4104 'EXCLUSIVE_LOCKS_REQUIRED',
'SHARED_LOCKS_REQUIRED',
4105 'LOCKS_EXCLUDED',
'INTERFACE_DEF'))
or 4106 (func
and not Search(
r'\boperator\s*\[\s*\]', func.group(1)))
or 4107 Search(
r'\b(?:struct|union)\s+alignas\s*$', line_prefix)
or 4108 Search(
r'\s+=\s*$', line_prefix)):
4111 opening_parenthesis[1] > 1
and 4112 Search(
r'\]\s*$', clean_lines.elided[opening_parenthesis[1] - 1])):
4118 match =
Match(
r'^(.*(?:else|\)\s*const)\s*)\{', line)
4129 if prevline
and Search(
r'[;{}]\s*$', prevline):
4130 match =
Match(
r'^(\s*)\{', line)
4135 clean_lines, linenum, len(match.group(1)))
4136 if endpos > -1
and Match(
r'^\s*;', endline[endpos:]):
4144 error(filename, endlinenum,
'readability/braces', 4,
4145 "You don't need a ; after a }")
4149 """Look for empty loop/conditional body with only a single semicolon. 4152 filename: The name of the current file. 4153 clean_lines: A CleansedLines instance containing the file. 4154 linenum: The number of the line to check. 4155 error: The function to call with any errors found. 4164 line = clean_lines.elided[linenum]
4165 matched =
Match(
r'\s*(for|while|if)\s*\(', line)
4169 clean_lines, linenum, line.find(
'('))
4174 if end_pos >= 0
and Match(
r';', end_line[end_pos:]):
4175 if matched.group(1) ==
'if':
4176 error(filename, end_linenum,
'whitespace/empty_conditional_body', 5,
4177 'Empty conditional bodies should use {}')
4179 error(filename, end_linenum,
'whitespace/empty_loop_body', 5,
4180 'Empty loop bodies should use {} or continue')
4184 """Find a replaceable CHECK-like macro. 4187 line: line to search on. 4189 (macro name, start position), or (None, -1) if no replaceable 4192 for macro
in _CHECK_MACROS:
4193 i = line.find(macro)
4199 matched =
Match(
r'^(.*\b' + macro +
r'\s*)\(', line)
4202 return (macro, len(matched.group(1)))
4207 """Checks the use of CHECK and EXPECT macros. 4210 filename: The name of the current file. 4211 clean_lines: A CleansedLines instance containing the file. 4212 linenum: The number of the line to check. 4213 error: The function to call with any errors found. 4217 lines = clean_lines.elided
4224 clean_lines, linenum, start_pos)
4231 if not Match(
r'\s*;', last_line[end_pos:]):
4234 if linenum == end_line:
4235 expression = lines[linenum][start_pos + 1:end_pos - 1]
4237 expression = lines[linenum][start_pos + 1:]
4238 for i
in xrange(linenum + 1, end_line):
4239 expression += lines[i]
4240 expression += last_line[0:end_pos - 1]
4249 matched =
Match(
r'^\s*(<<|<<=|>>|>>=|->\*|->|&&|\|\||' 4250 r'==|!=|>=|>|<=|<|\()(.*)$', expression)
4252 token = matched.group(1)
4255 expression = matched.group(2)
4259 lhs +=
'(' + expression[0:end]
4260 expression = expression[end:]
4261 elif token
in (
'&&',
'||'):
4268 elif token
in (
'<<',
'<<=',
'>>',
'>>=',
'->*',
'->'):
4271 expression = matched.group(2)
4275 rhs = matched.group(2)
4283 matched =
Match(
r'^([^-=!<>()&|]+)(.*)$', expression)
4285 matched =
Match(
r'^(\s*\S)(.*)$', expression)
4288 lhs += matched.group(1)
4289 expression = matched.group(2)
4292 if not (lhs
and operator
and rhs):
4297 if rhs.find(
'&&') > -1
or rhs.find(
'||') > -1:
4308 match_constant =
r'^([-+]?(\d+|0[xX][0-9a-fA-F]+)[lLuU]{0,3}|".*"|\'.*\')$' 4309 if Match(match_constant, lhs)
or Match(match_constant, rhs):
4318 error(filename, linenum,
'readability/check', 2,
4319 'Consider using %s instead of %s(a %s b)' % (
4320 _CHECK_REPLACEMENT[check_macro][operator],
4321 check_macro, operator))
4325 """Check alternative keywords being used in boolean expressions. 4328 filename: The name of the current file. 4329 clean_lines: A CleansedLines instance containing the file. 4330 linenum: The number of the line to check. 4331 error: The function to call with any errors found. 4333 line = clean_lines.elided[linenum]
4336 if Match(
r'^\s*#', line):
4347 if line.find(
'/*') >= 0
or line.find(
'*/') >= 0:
4350 for match
in _ALT_TOKEN_REPLACEMENT_PATTERN.finditer(line):
4351 error(filename, linenum,
'readability/alt_tokens', 2,
4352 'Use operator %s instead of %s' % (
4353 _ALT_TOKEN_REPLACEMENT[match.group(1)], match.group(1)))
4357 """Determines the width of the line in column positions. 4360 line: A string, which may be a Unicode string. 4363 The width of the line in column positions, accounting for Unicode 4364 combining characters and wide characters. 4366 if isinstance(line, unicode):
4368 for uc
in unicodedata.normalize(
'NFC', line):
4369 if unicodedata.east_asian_width(uc)
in (
'W',
'F'):
4371 elif not unicodedata.combining(uc):
4378 def CheckStyle(filename, clean_lines, linenum, file_extension, nesting_state,
4380 """Checks rules from the 'C++ style rules' section of cppguide.html. 4382 Most of these rules are hard to test (naming, comment style), but we 4383 do what we can. In particular we check for 2-space indents, line lengths, 4384 tab usage, spaces inside code, etc. 4387 filename: The name of the current file. 4388 clean_lines: A CleansedLines instance containing the file. 4389 linenum: The number of the line to check. 4390 file_extension: The extension (without the dot) of the filename. 4391 nesting_state: A NestingState instance which maintains information about 4392 the current stack of nested blocks being parsed. 4393 error: The function to call with any errors found. 4399 raw_lines = clean_lines.lines_without_raw_strings
4400 line = raw_lines[linenum]
4402 if line.find(
'\t') != -1:
4403 error(filename, linenum,
'whitespace/tab', 1,
4404 'Tab found; better to use spaces')
4418 scope_or_label_pattern =
r'\s*\w+\s*:\s*\\?$' 4419 classinfo = nesting_state.InnermostClass()
4421 cleansed_line = clean_lines.elided[linenum]
4422 while initial_spaces < len(line)
and line[initial_spaces] ==
' ':
4424 if line
and line[-1].isspace():
4425 error(filename, linenum,
'whitespace/end_of_line', 4,
4426 'Line ends in whitespace. Consider deleting these extra spaces.')
4429 elif ((initial_spaces == 1
or initial_spaces == 3)
and 4430 not Match(scope_or_label_pattern, cleansed_line)
and 4431 not (clean_lines.raw_lines[linenum] != line
and 4432 Match(
r'^\s*""', line))):
4433 error(filename, linenum,
'whitespace/indent', 3,
4434 'Weird number of spaces at line-start. ' 4435 'Are you using a 2-space indent?')
4438 is_header_guard =
False 4439 if file_extension ==
'h':
4441 if (line.startswith(
'#ifndef %s' % cppvar)
or 4442 line.startswith(
'#define %s' % cppvar)
or 4443 line.startswith(
'#endif // %s' % cppvar)):
4444 is_header_guard =
True 4453 if (
not line.startswith(
'#include')
and not is_header_guard
and 4454 not Match(
r'^\s*//.*http(s?)://\S*$', line)
and 4455 not Match(
r'^// \$Id:.*#[0-9]+ \$$', line)):
4457 extended_length = int((_line_length * 1.25))
4458 if line_width > extended_length:
4459 error(filename, linenum,
'whitespace/line_length', 4,
4460 'Lines should very rarely be longer than %i characters' %
4462 elif line_width > _line_length:
4463 error(filename, linenum,
'whitespace/line_length', 2,
4464 'Lines should be <= %i characters long' % _line_length)
4466 if (cleansed_line.count(
';') > 1
and 4468 cleansed_line.find(
'for') == -1
and 4472 not ((cleansed_line.find(
'case ') != -1
or 4473 cleansed_line.find(
'default:') != -1)
and 4474 cleansed_line.find(
'break;') != -1)):
4475 error(filename, linenum,
'whitespace/newline', 0,
4476 'More than one command on the same line')
4479 CheckBraces(filename, clean_lines, linenum, error)
4482 CheckAccess(filename, clean_lines, linenum, nesting_state, error)
4483 CheckSpacing(filename, clean_lines, linenum, nesting_state, error)
4490 CheckCheck(filename, clean_lines, linenum, error)
4492 classinfo = nesting_state.InnermostClass()
4497 _RE_PATTERN_INCLUDE = re.compile(
r'^\s*#\s*include\s*([<"])([^>"]*)[>"].*$')
4503 _RE_FIRST_COMPONENT = re.compile(
r'^[^-_.]+')
4507 """Drops common suffixes like _test.cc or -inl.h from filename. 4510 >>> _DropCommonSuffixes('foo/foo-inl.h') 4512 >>> _DropCommonSuffixes('foo/bar/foo.cc') 4514 >>> _DropCommonSuffixes('foo/foo_internal.h') 4516 >>> _DropCommonSuffixes('foo/foo_unusualinternal.h') 4517 'foo/foo_unusualinternal' 4520 filename: The input filename. 4523 The filename with the common suffix removed. 4525 for suffix
in (
'test.cc',
'regtest.cc',
'unittest.cc',
4526 'inl.h',
'impl.h',
'internal.h'):
4527 if (filename.endswith(suffix)
and len(filename) > len(suffix)
and 4528 filename[-len(suffix) - 1]
in (
'-',
'_')):
4529 return filename[:-len(suffix) - 1]
4530 return os.path.splitext(filename)[0]
4534 """Determines if the given filename has a suffix that identifies it as a test. 4537 filename: The input filename. 4540 True if 'filename' looks like a test, False otherwise. 4542 if (filename.endswith(
'_test.cc')
or 4543 filename.endswith(
'_unittest.cc')
or 4544 filename.endswith(
'_regtest.cc')):
4551 """Figures out what kind of header 'include' is. 4554 fileinfo: The current file cpplint is running over. A FileInfo instance. 4555 include: The path to a #included file. 4556 is_system: True if the #include used <> rather than "". 4559 One of the _XXX_HEADER constants. 4562 >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'stdio.h', True) 4564 >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'string', True) 4566 >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'foo/foo.h', False) 4568 >>> _ClassifyInclude(FileInfo('foo/foo_unknown_extension.cc'), 4569 ... 'bar/foo_other_ext.h', False) 4571 >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'foo/bar.h', False) 4576 is_cpp_h = include
in _CPP_HEADERS
4580 return _CPP_SYS_HEADER
4582 return _C_SYS_HEADER
4587 target_dir, target_base = (
4590 if target_base == include_base
and (
4591 include_dir == target_dir
or 4592 include_dir == os.path.normpath(target_dir +
'/../public')):
4593 return _LIKELY_MY_HEADER
4599 target_first_component = _RE_FIRST_COMPONENT.match(target_base)
4600 include_first_component = _RE_FIRST_COMPONENT.match(include_base)
4601 if (target_first_component
and include_first_component
and 4602 target_first_component.group(0) ==
4603 include_first_component.group(0)):
4604 return _POSSIBLE_MY_HEADER
4606 return _OTHER_HEADER
4611 """Check rules that are applicable to #include lines. 4613 Strings on #include lines are NOT removed from elided line, to make 4614 certain tasks easier. However, to prevent false positives, checks 4615 applicable to #include lines in CheckLanguage must be put here. 4618 filename: The name of the current file. 4619 clean_lines: A CleansedLines instance containing the file. 4620 linenum: The number of the line to check. 4621 include_state: An _IncludeState instance in which the headers are inserted. 4622 error: The function to call with any errors found. 4625 line = clean_lines.lines[linenum]
4634 match =
Match(
r'#include\s*"([^/]+\.h)"', line)
4635 if match
and not _THIRD_PARTY_HEADERS_PATTERN.match(match.group(1)):
4636 error(filename, linenum,
'build/include', 4,
4637 'Include the directory when naming .h files')
4642 match = _RE_PATTERN_INCLUDE.search(line)
4644 include = match.group(2)
4645 is_system = (match.group(1) ==
'<')
4646 duplicate_line = include_state.FindHeader(include)
4647 if duplicate_line >= 0:
4648 error(filename, linenum,
'build/include', 4,
4649 '"%s" already included at %s:%s' %
4650 (include, filename, duplicate_line))
4651 elif (include.endswith(
'.cc')
and 4652 os.path.dirname(fileinfo.RepositoryName()) != os.path.dirname(include)):
4653 error(filename, linenum,
'build/include', 4,
4654 'Do not include .cc files from other packages')
4655 elif not _THIRD_PARTY_HEADERS_PATTERN.match(include):
4656 include_state.include_list[-1].append((include, linenum))
4669 error_message = include_state.CheckNextIncludeOrder(
4672 error(filename, linenum,
'build/include_order', 4,
4673 '%s. Should be: %s.h, c system, c++ system, other.' %
4674 (error_message, fileinfo.BaseName()))
4675 canonical_include = include_state.CanonicalizeAlphabeticalOrder(include)
4676 if not include_state.IsInAlphabeticalOrder(
4677 clean_lines, linenum, canonical_include):
4678 error(filename, linenum,
'build/include_alpha', 4,
4679 'Include "%s" not in alphabetical order' % include)
4680 include_state.SetLastHeader(canonical_include)
4685 r"""Retrieves all the text between matching open and close parentheses. 4687 Given a string of lines and a regular expression string, retrieve all the text 4688 following the expression and between opening punctuation symbols like 4689 (, [, or {, and the matching close-punctuation symbol. This properly nested 4690 occurrences of the punctuations, so for the text like 4691 printf(a(), b(c())); 4692 a call to _GetTextInside(text, r'printf\(') will return 'a(), b(c())'. 4693 start_pattern must match string having an open punctuation symbol at the end. 4696 text: The lines to extract text. Its comments and strings must be elided. 4697 It can be single line and can span multiple lines. 4698 start_pattern: The regexp string indicating where to start extracting 4702 None if either the opening string or ending punctuation could not be found. 4708 matching_punctuation = {
'(':
')',
'{':
'}',
'[':
']'}
4709 closing_punctuation = set(matching_punctuation.itervalues())
4712 match = re.search(start_pattern, text, re.M)
4715 start_position = match.end(0)
4717 assert start_position > 0, (
4718 'start_pattern must ends with an opening punctuation.')
4719 assert text[start_position - 1]
in matching_punctuation, (
4720 'start_pattern must ends with an opening punctuation.')
4722 punctuation_stack = [matching_punctuation[text[start_position - 1]]]
4723 position = start_position
4724 while punctuation_stack
and position < len(text):
4725 if text[position] == punctuation_stack[-1]:
4726 punctuation_stack.pop()
4727 elif text[position]
in closing_punctuation:
4730 elif text[position]
in matching_punctuation:
4731 punctuation_stack.append(matching_punctuation[text[position]])
4733 if punctuation_stack:
4737 return text[start_position:position - 1]
4749 _RE_PATTERN_IDENT =
r'[_a-zA-Z]\w*' 4750 _RE_PATTERN_TYPE = (
4751 r'(?:const\s+)?(?:typename\s+|class\s+|struct\s+|union\s+|enum\s+)?' 4753 r'\s*<(?:<(?:<[^<>]*>|[^<>])*>|[^<>])*>|' 4756 _RE_PATTERN_REF_PARAM = re.compile(
4757 r'(' + _RE_PATTERN_TYPE +
r'(?:\s*(?:\bconst\b|[*]))*\s*' 4758 r'&\s*' + _RE_PATTERN_IDENT +
r')\s*(?:=[^,()]+)?[,)]')
4761 _RE_PATTERN_CONST_REF_PARAM = (
4762 r'(?:.*\s*\bconst\s*&\s*' + _RE_PATTERN_IDENT +
4763 r'|const\s+' + _RE_PATTERN_TYPE +
r'\s*&\s*' + _RE_PATTERN_IDENT +
r')')
4766 def CheckLanguage(filename, clean_lines, linenum, file_extension,
4767 include_state, nesting_state, error):
4768 """Checks rules from the 'C++ language rules' section of cppguide.html. 4770 Some of these rules are hard to test (function overloading, using 4771 uint32 inappropriately), but we do the best we can. 4774 filename: The name of the current file. 4775 clean_lines: A CleansedLines instance containing the file. 4776 linenum: The number of the line to check. 4777 file_extension: The extension (without the dot) of the filename. 4778 include_state: An _IncludeState instance in which the headers are inserted. 4779 nesting_state: A NestingState instance which maintains information about 4780 the current stack of nested blocks being parsed. 4781 error: The function to call with any errors found. 4785 line = clean_lines.elided[linenum]
4789 match = _RE_PATTERN_INCLUDE.search(line)
4796 match =
Match(
r'^\s*#\s*(if|ifdef|ifndef|elif|else|endif)\b', line)
4798 include_state.ResetSection(match.group(1))
4801 fullname = os.path.abspath(filename).replace(
'\\',
'/')
4804 CheckCasts(filename, clean_lines, linenum, error)
4806 CheckPrintf(filename, clean_lines, linenum, error)
4808 if file_extension ==
'h':
4818 if Search(
r'\bshort port\b', line):
4819 if not Search(
r'\bunsigned short port\b', line):
4820 error(filename, linenum,
'runtime/int', 4,
4821 'Use "unsigned short" for ports, not "short"')
4823 match =
Search(
r'\b(short|long(?! +double)|long long)\b', line)
4825 error(filename, linenum,
'runtime/int', 4,
4826 'Use int16/int64/etc, rather than the C type %s' % match.group(1))
4834 if Search(
r'\boperator\s*&\s*\(\s*\)', line):
4835 error(filename, linenum,
'runtime/operator', 4,
4836 'Unary operator& is dangerous. Do not use it.')
4840 if Search(
r'\}\s*if\s*\(', line):
4841 error(filename, linenum,
'readability/braces', 4,
4842 'Did you mean "else if"? If not, start a new line for "if".')
4851 printf_args =
_GetTextInside(line,
r'(?i)\b(string)?printf\s*\(')
4853 match =
Match(
r'([\w.\->()]+)$', printf_args)
4854 if match
and match.group(1) !=
'__VA_ARGS__':
4855 function_name = re.search(
r'\b((?:string)?printf)\s*\(',
4856 line, re.I).group(1)
4857 error(filename, linenum,
'runtime/printf', 4,
4858 'Potential format string bug. Do %s("%%s", %s) instead.' 4859 % (function_name, match.group(1)))
4862 match =
Search(
r'memset\s*\(([^,]*),\s*([^,]*),\s*0\s*\)', line)
4863 if match
and not Match(
r"^''|-?[0-9]+|0x[0-9A-Fa-f]$", match.group(2)):
4864 error(filename, linenum,
'runtime/memset', 4,
4865 'Did you mean "memset(%s, 0, %s)"?' 4866 % (match.group(1), match.group(2)))
4868 if Search(
r'\busing namespace\b', line):
4869 error(filename, linenum,
'build/namespaces', 5,
4870 'Do not use namespace using-directives. ' 4871 'Use using-declarations instead.')
4874 match =
Match(
r'\s*(.+::)?(\w+) [a-z]\w*\[(.+)];', line)
4875 if (match
and match.group(2) !=
'return' and match.group(2) !=
'delete' and 4876 match.group(3).find(
']') == -1):
4880 tokens = re.split(
r'\s|\+|\-|\*|\/|<<|>>]', match.group(3))
4888 if Search(
r'sizeof\(.+\)', tok):
continue 4889 if Search(
r'arraysize\(\w+\)', tok):
continue 4891 tok = tok.lstrip(
'(')
4892 tok = tok.rstrip(
')')
4893 if not tok:
continue 4894 if Match(
r'\d+', tok):
continue 4895 if Match(
r'0[xX][0-9a-fA-F]+', tok):
continue 4896 if Match(
r'k[A-Z0-9]\w*', tok):
continue 4897 if Match(
r'(.+::)?k[A-Z0-9]\w*', tok):
continue 4898 if Match(
r'(.+::)?[A-Z][A-Z0-9_]*', tok):
continue 4902 if tok.startswith(
'sizeof'):
4908 error(filename, linenum,
'runtime/arrays', 1,
4909 'Do not use variable-length arrays. Use an appropriately named ' 4910 "('k' followed by CamelCase) compile-time constant for the size.")
4915 if (file_extension ==
'h' 4916 and Search(
r'\bnamespace\s*{', line)
4917 and line[-1] !=
'\\'):
4918 error(filename, linenum,
'build/namespaces', 4,
4919 'Do not use unnamed namespaces in header files. See ' 4920 'http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Namespaces' 4921 ' for more information.')
4925 """Check for unsafe global or static objects. 4928 filename: The name of the current file. 4929 clean_lines: A CleansedLines instance containing the file. 4930 linenum: The number of the line to check. 4931 error: The function to call with any errors found. 4933 line = clean_lines.elided[linenum]
4936 if linenum + 1 < clean_lines.NumLines()
and not Search(
r'[;({]', line):
4937 line += clean_lines.elided[linenum + 1].strip()
4943 r'((?:|static +)(?:|const +))string +([a-zA-Z0-9_:]+)\b(.*)',
4963 not Search(
r'\bstring\b(\s+const)?\s*\*\s*(const\s+)?\w', line)
and 4964 not Search(
r'\boperator\W', line)
and 4965 not Match(
r'\s*(<.*>)?(::[a-zA-Z0-9_]+)*\s*\(([^"]|$)', match.group(3))):
4966 error(filename, linenum,
'runtime/string', 4,
4967 'For a static/global string constant, use a C style string instead: ' 4969 (match.group(1), match.group(2)))
4971 if Search(
r'\b([A-Za-z0-9_]*_)\(\1\)', line):
4972 error(filename, linenum,
'runtime/init', 4,
4973 'You seem to be initializing a member variable with itself.')
4977 """Check for printf related issues. 4980 filename: The name of the current file. 4981 clean_lines: A CleansedLines instance containing the file. 4982 linenum: The number of the line to check. 4983 error: The function to call with any errors found. 4985 line = clean_lines.elided[linenum]
4988 match =
Search(
r'snprintf\s*\(([^,]*),\s*([0-9]*)\s*,', line)
4989 if match
and match.group(2) !=
'0':
4991 error(filename, linenum,
'runtime/printf', 3,
4992 'If you can, use sizeof(%s) instead of %s as the 2nd arg ' 4993 'to snprintf.' % (match.group(1), match.group(2)))
4996 if Search(
r'\bsprintf\s*\(', line):
4997 error(filename, linenum,
'runtime/printf', 5,
4998 'Never use sprintf. Use snprintf instead.')
4999 match =
Search(
r'\b(strcpy|strcat)\s*\(', line)
5001 error(filename, linenum,
'runtime/printf', 4,
5002 'Almost always, snprintf is better than %s' % match.group(1))
5006 """Check if current line contains an inherited function. 5009 clean_lines: A CleansedLines instance containing the file. 5010 linenum: The number of the line to check. 5012 True if current line contains a function with "override" 5016 for i
in xrange(linenum, max(-1, linenum - 10), -1):
5017 match =
Match(
r'^([^()]*\w+)\(', clean_lines.elided[i])
5021 clean_lines, i, len(match.group(1)))
5022 return (closing_paren >= 0
and 5023 Search(
r'\boverride\b', line[closing_paren:]))
5028 """Check if current line contains an out-of-line method definition. 5031 clean_lines: A CleansedLines instance containing the file. 5032 linenum: The number of the line to check. 5034 True if current line contains an out-of-line method definition. 5037 for i
in xrange(linenum, max(-1, linenum - 10), -1):
5038 if Match(
r'^([^()]*\w+)\(', clean_lines.elided[i]):
5039 return Match(
r'^[^()]*\w+::\w+\(', clean_lines.elided[i])
is not None 5044 """Check if current line is inside constructor initializer list. 5047 clean_lines: A CleansedLines instance containing the file. 5048 linenum: The number of the line to check. 5050 True if current line appears to be inside constructor initializer 5051 list, False otherwise. 5053 for i
in xrange(linenum, 1, -1):
5054 line = clean_lines.elided[i]
5056 remove_function_body =
Match(
r'^(.*)\{\s*$', line)
5057 if remove_function_body:
5058 line = remove_function_body.group(1)
5060 if Search(
r'\s:\s*\w+[({]', line):
5066 if Search(
r'\}\s*,\s*$', line):
5070 if Search(
r'[{};]\s*$', line):
5086 nesting_state, error):
5087 """Check for non-const references. 5089 Separate from CheckLanguage since it scans backwards from current 5090 line, instead of scanning forward. 5093 filename: The name of the current file. 5094 clean_lines: A CleansedLines instance containing the file. 5095 linenum: The number of the line to check. 5096 nesting_state: A NestingState instance which maintains information about 5097 the current stack of nested blocks being parsed. 5098 error: The function to call with any errors found. 5101 line = clean_lines.elided[linenum]
5134 if Match(
r'\s*::(?:[\w<>]|::)+\s*&\s*\S', line):
5136 previous =
Search(
r'\b((?:const\s*)?(?:[\w<>]|::)+[\w<>])\s*$',
5137 clean_lines.elided[linenum - 1])
5138 elif Match(
r'\s*[a-zA-Z_]([\w<>]|::)+\s*&\s*\S', line):
5140 previous =
Search(
r'\b((?:const\s*)?(?:[\w<>]|::)+::)\s*$',
5141 clean_lines.elided[linenum - 1])
5143 line = previous.group(1) + line.lstrip()
5146 endpos = line.rfind(
'>')
5149 clean_lines, linenum, endpos)
5150 if startpos > -1
and startline < linenum:
5154 for i
in xrange(startline, linenum + 1):
5155 line += clean_lines.elided[i].strip()
5165 if (nesting_state.previous_stack_top
and 5166 not (isinstance(nesting_state.previous_stack_top, _ClassInfo)
or 5167 isinstance(nesting_state.previous_stack_top, _NamespaceInfo))):
5178 for i
in xrange(linenum - 1, max(0, linenum - 10), -1):
5179 previous_line = clean_lines.elided[i]
5180 if not Search(
r'[),]\s*$', previous_line):
5182 if Match(
r'^\s*:\s+\S', previous_line):
5186 if Search(
r'\\\s*$', line):
5199 whitelisted_functions = (
r'(?:[sS]wap(?:<\w:+>)?|' 5200 r'operator\s*[<>][<>]|' 5201 r'static_assert|COMPILE_ASSERT' 5203 if Search(whitelisted_functions, line):
5205 elif not Search(
r'\S+\([^)]*$', line):
5211 Search(whitelisted_functions, clean_lines.elided[linenum - i - 1])):
5215 for parameter
in re.findall(_RE_PATTERN_REF_PARAM, decls):
5216 if not Match(_RE_PATTERN_CONST_REF_PARAM, parameter):
5217 error(filename, linenum,
'runtime/references', 2,
5218 'Is this a non-const reference? ' 5219 'If so, make const or use a pointer: ' +
5224 """Various cast related checks. 5227 filename: The name of the current file. 5228 clean_lines: A CleansedLines instance containing the file. 5229 linenum: The number of the line to check. 5230 error: The function to call with any errors found. 5232 line = clean_lines.elided[linenum]
5239 r'(\bnew\s+|\S<\s*(?:const\s+)?)?\b' 5240 r'(int|float|double|bool|char|int32|uint32|int64|uint64)' 5241 r'(\([^)].*)', line)
5243 if match
and not expecting_function:
5244 matched_type = match.group(2)
5258 matched_new_or_template = match.group(1)
5262 if Match(
r'\([^()]+\)\s*\[', match.group(3)):
5270 matched_funcptr = match.group(3)
5271 if (matched_new_or_template
is None and 5272 not (matched_funcptr
and 5273 (
Match(
r'\((?:[^() ]+::\s*\*\s*)?[^() ]+\)\s*\(',
5275 matched_funcptr.startswith(
'(*)')))
and 5276 not Match(
r'\s*using\s+\S+\s*=\s*' + matched_type, line)
and 5277 not Search(
r'new\(\S+\)\s*' + matched_type, line)):
5278 error(filename, linenum,
'readability/casting', 4,
5279 'Using deprecated casting style. ' 5280 'Use static_cast<%s>(...) instead' %
5283 if not expecting_function:
5285 r'\((int|float|double|bool|char|u?int(16|32|64))\)', error)
5292 r'\((char\s?\*+\s?)\)\s*"', error):
5297 r'\((\w+\s?\*+\s?)\)', error)
5311 r'(?:[^\w]&\(([^)*][^)]*)\)[\w(])|' 5312 r'(?:[^\w]&(static|dynamic|down|reinterpret)_cast\b)', line)
5317 parenthesis_error =
False 5318 match =
Match(
r'^(.*&(?:static|dynamic|down|reinterpret)_cast\b)<', line)
5320 _, y1, x1 =
CloseExpression(clean_lines, linenum, len(match.group(1)))
5321 if x1 >= 0
and clean_lines.elided[y1][x1] ==
'(':
5324 extended_line = clean_lines.elided[y2][x2:]
5325 if y2 < clean_lines.NumLines() - 1:
5326 extended_line += clean_lines.elided[y2 + 1]
5327 if Match(
r'\s*(?:->|\[)', extended_line):
5328 parenthesis_error =
True 5330 if parenthesis_error:
5331 error(filename, linenum,
'readability/casting', 4,
5332 (
'Are you taking an address of something dereferenced ' 5333 'from a cast? Wrapping the dereferenced expression in ' 5334 'parentheses will make the binding more obvious'))
5336 error(filename, linenum,
'runtime/casting', 4,
5337 (
'Are you taking an address of a cast? ' 5338 'This is dangerous: could be a temp var. ' 5339 'Take the address before doing the cast, rather than after'))
5343 """Checks for a C-style cast by looking for the pattern. 5346 filename: The name of the current file. 5347 clean_lines: A CleansedLines instance containing the file. 5348 linenum: The number of the line to check. 5349 cast_type: The string for the C++ cast to recommend. This is either 5350 reinterpret_cast, static_cast, or const_cast, depending. 5351 pattern: The regular expression used to find C-style casts. 5352 error: The function to call with any errors found. 5355 True if an error was emitted. 5358 line = clean_lines.elided[linenum]
5359 match =
Search(pattern, line)
5364 context = line[0:match.start(1) - 1]
5365 if Match(
r'.*\b(?:sizeof|alignof|alignas|[_A-Z][_A-Z0-9]*)\s*$', context):
5371 for i
in xrange(linenum - 1, max(0, linenum - 5), -1):
5372 context = clean_lines.elided[i] + context
5373 if Match(
r'.*\b[_A-Z][_A-Z0-9]*\s*\((?:\([^()]*\)|[^()])*$', context):
5377 if context.endswith(
' operator++')
or context.endswith(
' operator--'):
5405 remainder = line[match.end(0):]
5406 if Match(
r'^\s*(?:;|const\b|throw\b|final\b|override\b|[=>{),]|->)',
5411 if Match(
r'^\s*>', remainder):
5418 matched_zero =
Match(
r'^\s=\s*(\S+)\s*;', remainder)
5419 if matched_zero
and matched_zero.group(1) !=
'0':
5424 if Match(
r'.*\)\s*$', line[0:match.start(0)]):
5429 raw_line = clean_lines.raw_lines[linenum]
5430 if '/*' in raw_line:
5434 error(filename, linenum,
'readability/function', 3,
5435 'All parameters should be named in a function')
5439 error(filename, linenum,
'readability/casting', 4,
5440 'Using C-style cast. Use %s<%s>(...) instead' %
5441 (cast_type, match.group(1)))
5447 """Checks whether where function type arguments are expected. 5450 clean_lines: A CleansedLines instance containing the file. 5451 linenum: The number of the line to check. 5454 True if the line at 'linenum' is inside something that expects arguments 5457 line = clean_lines.elided[linenum]
5458 return (
Match(
r'^\s*MOCK_(CONST_)?METHOD\d+(_T)?\(', line)
or 5460 (
Match(
r'^\s*MOCK_(?:CONST_)?METHOD\d+(?:_T)?\((?:\S+,)?\s*$',
5461 clean_lines.elided[linenum - 1])
or 5462 Match(
r'^\s*MOCK_(?:CONST_)?METHOD\d+(?:_T)?\(\s*$',
5463 clean_lines.elided[linenum - 2])
or 5464 Search(
r'\bstd::m?function\s*<\s*$',
5465 clean_lines.elided[linenum - 1]))))
5468 _HEADERS_CONTAINING_TEMPLATES = (
5469 (
'<deque>', (
'deque',)),
5470 (
'<functional>', (
'unary_function',
'binary_function',
5471 'plus',
'minus',
'multiplies',
'divides',
'modulus',
5473 'equal_to',
'not_equal_to',
'greater',
'less',
5474 'greater_equal',
'less_equal',
5475 'logical_and',
'logical_or',
'logical_not',
5476 'unary_negate',
'not1',
'binary_negate',
'not2',
5477 'bind1st',
'bind2nd',
5478 'pointer_to_unary_function',
5479 'pointer_to_binary_function',
5481 'mem_fun_t',
'mem_fun',
'mem_fun1_t',
'mem_fun1_ref_t',
5483 'const_mem_fun_t',
'const_mem_fun1_t',
5484 'const_mem_fun_ref_t',
'const_mem_fun1_ref_t',
5487 (
'<limits>', (
'numeric_limits',)),
5488 (
'<list>', (
'list',)),
5489 (
'<map>', (
'map',
'multimap',)),
5490 (
'<memory>', (
'allocator',)),
5491 (
'<queue>', (
'queue',
'priority_queue',)),
5492 (
'<set>', (
'set',
'multiset',)),
5493 (
'<stack>', (
'stack',)),
5494 (
'<string>', (
'char_traits',
'basic_string',)),
5495 (
'<tuple>', (
'tuple',)),
5496 (
'<utility>', (
'pair',)),
5497 (
'<vector>', (
'vector',)),
5501 (
'<hash_map>', (
'hash_map',
'hash_multimap',)),
5502 (
'<hash_set>', (
'hash_set',
'hash_multiset',)),
5503 (
'<slist>', (
'slist',)),
5506 _RE_PATTERN_STRING = re.compile(
r'\bstring\b')
5508 _re_pattern_algorithm_header = []
5509 for _template
in (
'copy',
'max',
'min',
'min_element',
'sort',
'swap',
5513 _re_pattern_algorithm_header.append(
5514 (re.compile(
r'[^>.]\b' + _template +
r'(<.*?>)?\([^\)]'),
5518 _re_pattern_templates = []
5519 for _header, _templates
in _HEADERS_CONTAINING_TEMPLATES:
5520 for _template
in _templates:
5521 _re_pattern_templates.append(
5522 (re.compile(
r'(<|\b)' + _template +
r'\s*<'),
5528 """Check if these two filenames belong to the same module. 5530 The concept of a 'module' here is a as follows: 5531 foo.h, foo-inl.h, foo.cc, foo_test.cc and foo_unittest.cc belong to the 5532 same 'module' if they are in the same directory. 5533 some/path/public/xyzzy and some/path/internal/xyzzy are also considered 5534 to belong to the same module here. 5536 If the filename_cc contains a longer path than the filename_h, for example, 5537 '/absolute/path/to/base/sysinfo.cc', and this file would include 5538 'base/sysinfo.h', this function also produces the prefix needed to open the 5539 header. This is used by the caller of this function to more robustly open the 5540 header file. We don't have access to the real include paths in this context, 5541 so we need this guesswork here. 5543 Known bugs: tools/base/bar.cc and base/bar.h belong to the same module 5544 according to this implementation. Because of this, this function gives 5545 some false positives. This should be sufficiently rare in practice. 5548 filename_cc: is the path for the .cc file 5549 filename_h: is the path for the header path 5552 Tuple with a bool and a string: 5553 bool: True if filename_cc and filename_h belong to the same module. 5554 string: the additional prefix needed to open the header file. 5557 if not filename_cc.endswith(
'.cc'):
5559 filename_cc = filename_cc[:-len(
'.cc')]
5560 if filename_cc.endswith(
'_unittest'):
5561 filename_cc = filename_cc[:-len(
'_unittest')]
5562 elif filename_cc.endswith(
'_test'):
5563 filename_cc = filename_cc[:-len(
'_test')]
5564 filename_cc = filename_cc.replace(
'/public/',
'/')
5565 filename_cc = filename_cc.replace(
'/internal/',
'/')
5567 if not filename_h.endswith(
'.h'):
5569 filename_h = filename_h[:-len(
'.h')]
5570 if filename_h.endswith(
'-inl'):
5571 filename_h = filename_h[:-len(
'-inl')]
5572 filename_h = filename_h.replace(
'/public/',
'/')
5573 filename_h = filename_h.replace(
'/internal/',
'/')
5575 files_belong_to_same_module = filename_cc.endswith(filename_h)
5577 if files_belong_to_same_module:
5578 common_path = filename_cc[:-len(filename_h)]
5579 return files_belong_to_same_module, common_path
5583 """Fill up the include_dict with new includes found from the file. 5586 filename: the name of the header to read. 5587 include_dict: a dictionary in which the headers are inserted. 5588 io: The io factory to use to read the file. Provided for testability. 5591 True if a header was successfully added. False otherwise. 5595 headerfile = io.open(filename,
'r', 'utf8', 'replace')
5599 for line
in headerfile:
5602 match = _RE_PATTERN_INCLUDE.search(clean_line)
5604 include = match.group(2)
5605 include_dict.setdefault(include, linenum)
5611 """Reports for missing stl includes. 5613 This function will output warnings to make sure you are including the headers 5614 necessary for the stl containers and functions that you use. We only give one 5615 reason to include a header. For example, if you use both equal_to<> and 5616 less<> in a .h file, only one (the latter in the file) of these will be 5617 reported as a reason to include the <functional>. 5620 filename: The name of the current file. 5621 clean_lines: A CleansedLines instance containing the file. 5622 include_state: An _IncludeState instance. 5623 error: The function to call with any errors found. 5624 io: The IO factory to use to read the header file. Provided for unittest 5630 for linenum
in xrange(clean_lines.NumLines()):
5631 line = clean_lines.elided[linenum]
5632 if not line
or line[0] ==
'#':
5636 matched = _RE_PATTERN_STRING.search(line)
5640 prefix = line[:matched.start()]
5641 if prefix.endswith(
'std::')
or not prefix.endswith(
'::'):
5642 required[
'<string>'] = (linenum,
'string')
5644 for pattern, template, header
in _re_pattern_algorithm_header:
5645 if pattern.search(line):
5646 required[header] = (linenum, template)
5652 for pattern, template, header
in _re_pattern_templates:
5653 if pattern.search(line):
5654 required[header] = (linenum, template)
5659 include_dict = dict([item
for sublist
in include_state.include_list
5660 for item
in sublist])
5663 header_found =
False 5666 abs_filename =
FileInfo(filename).FullName()
5675 abs_filename = re.sub(
r'_flymake\.cc$',
'.cc', abs_filename)
5679 header_keys = include_dict.keys()
5680 for header
in header_keys:
5682 fullpath = common_path + header
5691 if filename.endswith(
'.cc')
and not header_found:
5695 for required_header_unstripped
in required:
5696 template = required[required_header_unstripped][1]
5697 if required_header_unstripped.strip(
'<>"')
not in include_dict:
5698 error(filename, required[required_header_unstripped][0],
5699 'build/include_what_you_use', 4,
5700 'Add #include ' + required_header_unstripped +
' for ' + template)
5703 _RE_PATTERN_EXPLICIT_MAKEPAIR = re.compile(
r'\bmake_pair\s*<')
5707 """Check that make_pair's template arguments are deduced. 5709 G++ 4.6 in C++11 mode fails badly if make_pair's template arguments are 5710 specified explicitly, and such use isn't intended in any case. 5713 filename: The name of the current file. 5714 clean_lines: A CleansedLines instance containing the file. 5715 linenum: The number of the line to check. 5716 error: The function to call with any errors found. 5718 line = clean_lines.elided[linenum]
5719 match = _RE_PATTERN_EXPLICIT_MAKEPAIR.search(line)
5721 error(filename, linenum,
'build/explicit_make_pair',
5723 'For C++11-compatibility, omit template arguments from make_pair' 5724 ' OR use pair directly OR if appropriate, construct a pair directly')
5728 """Check that default lambda captures are not used. 5731 filename: The name of the current file. 5732 clean_lines: A CleansedLines instance containing the file. 5733 linenum: The number of the line to check. 5734 error: The function to call with any errors found. 5736 line = clean_lines.elided[linenum]
5740 match =
Match(
r'^(.*)\[\s*(?:=|&[^\w])', line)
5745 line, _, pos =
CloseExpression(clean_lines, linenum, len(match.group(1)))
5746 if pos >= 0
and Match(
r'^\s*[{(]', line[pos:]):
5747 error(filename, linenum,
'build/c++11',
5749 'Default lambda captures are an unapproved C++ feature.')
5753 """Check if line contains a redundant "virtual" function-specifier. 5756 filename: The name of the current file. 5757 clean_lines: A CleansedLines instance containing the file. 5758 linenum: The number of the line to check. 5759 error: The function to call with any errors found. 5762 line = clean_lines.elided[linenum]
5763 virtual =
Match(
r'^(.*)(\bvirtual\b)(.*)$', line)
5764 if not virtual:
return 5769 if (
Search(
r'\b(public|protected|private)\s+$', virtual.group(1))
or 5770 Match(
r'^\s+(public|protected|private)\b', virtual.group(3))):
5776 if Match(
r'^.*[^:]:[^:].*$', line):
return 5785 start_col = len(virtual.group(2))
5786 for start_line
in xrange(linenum, min(linenum + 3, clean_lines.NumLines())):
5787 line = clean_lines.elided[start_line][start_col:]
5788 parameter_list =
Match(
r'^([^(]*)\(', line)
5792 clean_lines, start_line, start_col + len(parameter_list.group(1)))
5801 for i
in xrange(end_line, min(end_line + 3, clean_lines.NumLines())):
5802 line = clean_lines.elided[i][end_col:]
5803 match =
Search(
r'\b(override|final)\b', line)
5805 error(filename, linenum,
'readability/inheritance', 4,
5806 (
'"virtual" is redundant since function is ' 5807 'already declared as "%s"' % match.group(1)))
5812 if Search(
r'[^\w]\s*$', line):
5817 """Check if line contains a redundant "override" or "final" virt-specifier. 5820 filename: The name of the current file. 5821 clean_lines: A CleansedLines instance containing the file. 5822 linenum: The number of the line to check. 5823 error: The function to call with any errors found. 5828 line = clean_lines.elided[linenum]
5829 declarator_end = line.rfind(
')')
5830 if declarator_end >= 0:
5831 fragment = line[declarator_end:]
5833 if linenum > 1
and clean_lines.elided[linenum - 1].rfind(
')') >= 0:
5839 if Search(
r'\boverride\b', fragment)
and Search(
r'\bfinal\b', fragment):
5840 error(filename, linenum,
'readability/inheritance', 4,
5841 (
'"override" is redundant since function is ' 5842 'already declared as "final"'))
5850 """Checks that the new block is directly in a namespace. 5853 nesting_state: The _NestingState object that contains info about our state. 5854 is_forward_declaration: If the class is a forward declared class. 5856 Whether or not the new block is directly in a namespace. 5858 if is_forward_declaration:
5859 if len(nesting_state.stack) >= 1
and (
5860 isinstance(nesting_state.stack[-1], _NamespaceInfo)):
5865 return (len(nesting_state.stack) > 1
and 5866 nesting_state.stack[-1].check_namespace_indentation
and 5867 isinstance(nesting_state.stack[-2], _NamespaceInfo))
5871 raw_lines_no_comments, linenum):
5872 """This method determines if we should apply our namespace indentation check. 5875 nesting_state: The current nesting state. 5876 is_namespace_indent_item: If we just put a new class on the stack, True. 5877 If the top of the stack is not a class, or we did not recently 5878 add the class, False. 5879 raw_lines_no_comments: The lines without the comments. 5880 linenum: The current line number we are processing. 5883 True if we should apply our namespace indentation check. Currently, it 5884 only works for classes and namespaces inside of a namespace. 5890 if not (is_namespace_indent_item
or is_forward_declaration):
5905 line = raw_lines_no_comments[linenum]
5906 if Match(
r'^\s+', line):
5907 error(filename, linenum,
'runtime/indentation_namespace', 4,
5908 'Do not indent within a namespace')
5911 def ProcessLine(filename, file_extension, clean_lines, line,
5912 include_state, function_state, nesting_state, error,
5913 extra_check_functions=[]):
5914 """Processes a single line in the file. 5917 filename: Filename of the file that is being processed. 5918 file_extension: The extension (dot not included) of the file. 5919 clean_lines: An array of strings, each representing a line of the file, 5920 with comments stripped. 5921 line: Number of line being processed. 5922 include_state: An _IncludeState instance in which the headers are inserted. 5923 function_state: A _FunctionState instance which counts function lines, etc. 5924 nesting_state: A NestingState instance which maintains information about 5925 the current stack of nested blocks being parsed. 5926 error: A callable to which errors are reported, which takes 4 arguments: 5927 filename, line number, error level, and message 5928 extra_check_functions: An array of additional check functions that will be 5929 run on each source line. Each function takes 4 5930 arguments: filename, clean_lines, line, error 5932 raw_lines = clean_lines.raw_lines
5934 nesting_state.Update(filename, clean_lines, line, error)
5937 if nesting_state.InAsmBlock():
return 5940 CheckStyle(filename, clean_lines, line, file_extension, nesting_state, error)
5941 CheckLanguage(filename, clean_lines, line, file_extension, include_state,
5942 nesting_state, error)
5945 nesting_state, error)
5953 for check_fn
in extra_check_functions:
5954 check_fn(filename, clean_lines, line, error)
5957 """Flag those c++11 features that we only allow in certain places. 5960 filename: The name of the current file. 5961 clean_lines: A CleansedLines instance containing the file. 5962 linenum: The number of the line to check. 5963 error: The function to call with any errors found. 5965 line = clean_lines.elided[linenum]
5968 include =
Match(
r'\s*#\s*include\s+[<"]([^<"]+)[">]', line)
5969 if include
and include.group(1)
in (
'cfenv',
5970 'condition_variable',
5980 error(filename, linenum,
'build/c++11', 5,
5981 (
'<%s> is an unapproved C++11 header.') % include.group(1))
5985 if Match(
r'\s*#', line)
and not Match(
r'\s*#\s*define\b', line):
return 5995 if Search(
r'\bstd::%s\b' % top_name, line):
5996 error(filename, linenum,
'build/c++11', 5,
5997 (
'std::%s is an unapproved C++11 class or function. Send c-style ' 5998 'an example of where it would make your code more readable, and ' 5999 'they may let you use it.') % top_name)
6003 extra_check_functions=[]):
6004 """Performs lint checks and reports any errors to the given error function. 6007 filename: Filename of the file that is being processed. 6008 file_extension: The extension (dot not included) of the file. 6009 lines: An array of strings, each representing a line of the file, with the 6010 last element being empty if the file is terminated with a newline. 6011 error: A callable to which errors are reported, which takes 4 arguments: 6012 filename, line number, error level, and message 6013 extra_check_functions: An array of additional check functions that will be 6014 run on each source line. Each function takes 4 6015 arguments: filename, clean_lines, line, error 6017 lines = ([
'// marker so line numbers and indices both start at 1'] + lines +
6018 [
'// marker so line numbers end in a known way'])
6031 if file_extension ==
'h':
6034 for line
in xrange(clean_lines.NumLines()):
6035 ProcessLine(filename, file_extension, clean_lines, line,
6036 include_state, function_state, nesting_state, error,
6037 extra_check_functions)
6039 nesting_state.CheckCompletedBlocks(filename, error)
6044 if file_extension ==
'cc':
6054 """ Loads the configuration files and processes the config overrides. 6057 filename: The name of the file being processed by the linter. 6060 False if the current |filename| should not be processed further. 6063 abs_filename = os.path.abspath(filename)
6067 abs_path, base_name = os.path.split(abs_filename)
6071 cfg_file = os.path.join(abs_path,
"CPPLINT.cfg")
6072 abs_filename = abs_path
6073 if not os.path.isfile(cfg_file):
6077 with open(cfg_file)
as file_handle:
6078 for line
in file_handle:
6079 line, _, _ = line.partition(
'#')
6080 if not line.strip():
6083 name, _, val = line.partition(
'=')
6086 if name ==
'set noparent':
6087 keep_looking =
False 6088 elif name ==
'filter':
6089 cfg_filters.append(val)
6090 elif name ==
'exclude_files':
6098 pattern = re.compile(val)
6099 if pattern.match(base_name):
6100 sys.stderr.write(
'Ignoring "%s": file excluded by "%s". ' 6101 'File path component "%s" matches ' 6103 (filename, cfg_file, base_name, val))
6105 elif name ==
'linelength':
6108 _line_length = int(val)
6110 sys.stderr.write(
'Line length must be numeric.')
6113 'Invalid configuration option (%s) in file %s\n' %
6118 "Skipping config file '%s': Can't open for reading\n" % cfg_file)
6119 keep_looking =
False 6123 for filter
in reversed(cfg_filters):
6130 """Does google-lint on a single file. 6133 filename: The name of the file to parse. 6135 vlevel: The level of errors to report. Every error of confidence 6136 >= verbose_level will be reported. 0 is a good default. 6138 extra_check_functions: An array of additional check functions that will be 6139 run on each source line. Each function takes 4 6140 arguments: filename, clean_lines, line, error 6161 lines = codecs.StreamReaderWriter(sys.stdin,
6162 codecs.getreader(
'utf8'),
6163 codecs.getwriter(
'utf8'),
6164 'replace').read().split(
'\n')
6166 lines = codecs.open(filename,
'r', 'utf8', 'replace').read().split('\n')
6170 for linenum
in range(len(lines) - 1):
6171 if lines[linenum].endswith(
'\r'):
6172 lines[linenum] = lines[linenum].rstrip(
'\r')
6173 crlf_lines.append(linenum + 1)
6175 lf_lines.append(linenum + 1)
6179 "Skipping input '%s': Can't open for reading\n" % filename)
6184 file_extension = filename[filename.rfind(
'.') + 1:]
6188 if filename !=
'-' and file_extension
not in _valid_extensions:
6189 sys.stderr.write(
'Ignoring %s; not a valid file name ' 6190 '(%s)\n' % (filename,
', '.join(_valid_extensions)))
6193 extra_check_functions)
6205 if lf_lines
and crlf_lines:
6209 for linenum
in crlf_lines:
6210 Error(filename, linenum,
'whitespace/newline', 1,
6211 'Unexpected \\r (^M) found; better to use only \\n')
6213 sys.stderr.write(
'Done processing %s\n' % filename)
6218 """Prints a brief usage string and exits, optionally with an error message. 6221 message: The optional error message. 6223 sys.stderr.write(_USAGE)
6225 sys.exit(
'\nFATAL ERROR: ' + message)
6231 """Prints a list of all the error-categories used by error messages. 6233 These are the categories used to filter messages via --filter. 6235 sys.stderr.write(
''.join(
' %s\n' % cat
for cat
in _ERROR_CATEGORIES))
6240 """Parses the command line arguments. 6242 This may set the output format and verbosity level as side-effects. 6245 args: The command line arguments: 6248 The list of filenames to lint. 6251 (opts, filenames) = getopt.getopt(args,
'', [
'help',
'output=',
'verbose=',
6257 except getopt.GetoptError:
6265 for (opt, val)
in opts:
6268 elif opt ==
'--output':
6269 if val
not in (
'emacs',
'vs7',
'eclipse'):
6270 PrintUsage(
'The only allowed output formats are emacs, vs7 and eclipse.')
6272 elif opt ==
'--verbose':
6273 verbosity = int(val)
6274 elif opt ==
'--filter':
6278 elif opt ==
'--counting':
6279 if val
not in (
'total',
'toplevel',
'detailed'):
6280 PrintUsage(
'Valid counting options are total, toplevel, and detailed')
6281 counting_style = val
6282 elif opt ==
'--root':
6285 elif opt ==
'--linelength':
6288 _line_length = int(val)
6291 elif opt ==
'--extensions':
6292 global _valid_extensions
6294 _valid_extensions = set(val.split(
','))
6296 PrintUsage(
'Extensions must be comma seperated list.')
6314 sys.stderr = codecs.StreamReaderWriter(sys.stderr,
6315 codecs.getreader(
'utf8'),
6316 codecs.getwriter(
'utf8'),
6319 _cpplint_state.ResetErrorCounts()
6320 for filename
in filenames:
6321 ProcessFile(filename, _cpplint_state.verbose_level)
6322 _cpplint_state.PrintErrorCounts()
6324 sys.exit(_cpplint_state.error_count > 0)
6327 if __name__ ==
'__main__':
def ResetNolintSuppressions()
def CheckBegin(self, filename, clean_lines, linenum, error)
def IsDeletedOrDefault(clean_lines, linenum)
def CheckRedundantVirtual(filename, clean_lines, linenum, error)
def _SetOutputFormat(output_format)
def CheckPrintf(filename, clean_lines, linenum, error)
def CheckCStyleCast(filename, clean_lines, linenum, cast_type, pattern, error)
def Error(filename, linenum, category, confidence, message)
def InTemplateArgumentList(self, clean_lines, linenum, pos)
def FindNextMultiLineCommentStart(lines, lineix)
def InNamespaceBody(self)
def CheckDefaultLambdaCaptures(filename, clean_lines, linenum, error)
def _ShouldPrintError(category, confidence, linenum)
def IsInAlphabeticalOrder(self, clean_lines, linenum, header_path)
def _DropCommonSuffixes(filename)
def CheckCommaSpacing(filename, clean_lines, linenum, error)
def CheckParenthesisSpacing(filename, clean_lines, linenum, error)
def ProcessLine(filename, file_extension, clean_lines, line, include_state, function_state, nesting_state, error, extra_check_functions=[])
def __init__(self, seen_open_brace)
def ShouldCheckNamespaceIndentation(nesting_state, is_namespace_indent_item, raw_lines_no_comments, linenum)
def ReverseCloseExpression(clean_lines, linenum, pos)
def CheckComment(line, filename, linenum, next_line_start, error)
def ParseNolintSuppressions(filename, raw_line, linenum, error)
def CheckBegin(self, filename, clean_lines, linenum, error)
def RemoveMultiLineComments(filename, lines, error)
def CheckOperatorSpacing(filename, clean_lines, linenum, error)
def CheckEnd(self, filename, clean_lines, linenum, error)
def CheckForNewlineAtEOF(filename, lines, error)
def IsDecltype(clean_lines, linenum, column)
def __init__(self, name, class_or_struct, clean_lines, linenum)
def CheckSpacingForFunctionCall(filename, clean_lines, linenum, error)
def CheckEnd(self, filename, clean_lines, linenum, error)
def AddFilters(self, filters)
check_namespace_indentation
def CheckCheck(filename, clean_lines, linenum, error)
def IsForwardClassDeclaration(clean_lines, linenum)
def CheckTrailingSemicolon(filename, clean_lines, linenum, error)
def CheckHeaderFileIncluded(filename, include_state, error)
def _ClassifyInclude(fileinfo, include, is_system)
def ResetSection(self, directive)
def FindEndOfExpressionInLine(line, startpos, stack)
def CheckBracesSpacing(filename, clean_lines, linenum, error)
def FindStartOfExpressionInLine(line, endpos, stack)
lines_without_raw_strings
def IsInitializerList(clean_lines, linenum)
def IsRValueAllowed(clean_lines, linenum, typenames)
def InClassDeclaration(self)
def CheckInvalidIncrement(filename, clean_lines, linenum, error)
def IncrementErrorCount(self, category)
def SetVerboseLevel(self, level)
def GetPreviousNonBlankLine(clean_lines, linenum)
def FindNextMultiLineCommentEnd(lines, lineix)
def IsMacroDefinition(clean_lines, linenum)
def ProcessFile(filename, vlevel, extra_check_functions=[])
def __init__(self, lines)
def CheckIncludeLine(filename, clean_lines, linenum, include_state, error)
def CheckForNamespaceIndentation(filename, nesting_state, clean_lines, line, error)
def __init__(self, stack_before_if)
def GetHeaderGuardCPPVariable(filename)
def ResetErrorCounts(self)
def CheckCompletedBlocks(self, filename, error)
def CheckForNonStandardConstructs(filename, clean_lines, linenum, nesting_state, error)
def FindHeader(self, header)
def IsTemplateParameterList(clean_lines, linenum, column)
def ReplaceAll(pattern, rep, s)
def IsOutOfLineMethodDefinition(clean_lines, linenum)
def IsBlockInNameSpace(nesting_state, is_forward_declaration)
def SetOutputFormat(self, output_format)
def CleanseRawStrings(raw_lines)
def CanonicalizeAlphabeticalOrder(self, header_path)
def IsRValueType(typenames, clean_lines, nesting_state, linenum, column)
def FilesBelongToSameModule(filename_cc, filename_h)
def Begin(self, function_name)
def CheckItemIndentationInNamespace(filename, raw_lines_no_comments, linenum, error)
def CheckPosixThreading(filename, clean_lines, linenum, error)
def __init__(self, name, linenum)
def UpdateIncludeState(filename, include_dict, io=codecs)
def CheckForNonConstReference(filename, clean_lines, linenum, nesting_state, error)
def CleanseComments(line)
def CheckForBadCharacters(filename, lines, error)
def ProcessFileData(filename, file_extension, lines, error, extra_check_functions=[])
def CheckStyle(filename, clean_lines, linenum, file_extension, nesting_state, error)
def CheckSpacing(filename, clean_lines, linenum, nesting_state, error)
def CheckAccess(filename, clean_lines, linenum, nesting_state, error)
dictionary _SECTION_NAMES
def CheckLanguage(filename, clean_lines, linenum, file_extension, include_state, nesting_state, error)
def CheckForMultilineCommentsAndStrings(filename, clean_lines, linenum, error)
def __init__(self, filename)
def CheckSectionSpacing(filename, clean_lines, class_info, linenum, error)
def CheckNextIncludeOrder(self, header_type)
def Check(self, error, filename, linenum)
def SetCountingStyle(self, counting_style)
def UpdatePreprocessor(self, line)
def SetFilters(self, filters)
def _SetVerboseLevel(level)
def IsErrorSuppressedByNolint(category, linenum)
def CheckForHeaderGuard(filename, clean_lines, error)
def ExpectingFunctionArgs(clean_lines, linenum)
def CheckForFunctionLengths(filename, clean_lines, linenum, function_state, error)
def CheckMakePairUsesDeduction(filename, clean_lines, linenum, error)
def CloseExpression(clean_lines, linenum, pos)
def PrintErrorCounts(self)
def CheckCasts(filename, clean_lines, linenum, error)
def RemoveMultiLineCommentsFromRange(lines, begin, end)
def CheckAltTokens(filename, clean_lines, linenum, error)
def CheckRedundantOverrideOrFinal(filename, clean_lines, linenum, error)
def ProcessConfigOverrides(filename)
def Update(self, filename, clean_lines, linenum, error)
def CheckRValueReference(filename, clean_lines, linenum, nesting_state, error)
def _GetTextInside(text, start_pattern)
def CheckVlogArguments(filename, clean_lines, linenum, error)
def CheckEmptyBlockBody(filename, clean_lines, linenum, error)
def CheckBraces(filename, clean_lines, linenum, error)
def IsDerivedFunction(clean_lines, linenum)
def CheckForCopyright(filename, lines, error)
def _IsTestFilename(filename)
def CheckEnd(self, filename, clean_lines, linenum, error)
def _SetCountingStyle(level)
def _CollapseStrings(elided)
def CheckGlobalStatic(filename, clean_lines, linenum, error)
def SetLastHeader(self, header_path)
def FlagCxx11Features(filename, clean_lines, linenum, error)
def GetTemplateArgs(clean_lines, linenum)
def CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error, io=codecs)