35 """Does google-lint on c++ files. 37 The goal of this script is to identify places in the code that *may* 38 be in non-compliance with google style. It does not attempt to fix 39 up these problems -- the point is to educate. It does also not 40 attempt to find all problems, or to ensure that everything it does 41 find is legitimately a problem. 43 In particular, we can get very confused by /* and // inside strings! 44 We do a small hack, which is to ignore //'s with "'s after them on the 45 same line, but it is far from perfect (in either direction). 61 Syntax: cpplint.py [--verbose=#] [--output=vs7] [--filter=-x,+y,...] 62 [--counting=total|toplevel|detailed] [--root=subdir] 66 The style guidelines this tries to follow are those in 67 http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml 69 Every problem is given a confidence score from 1-5, with 5 meaning we are 70 certain of the problem, and 1 meaning it could be a legitimate construct. 71 This will miss some errors, and is not a substitute for a code review. 73 To suppress false-positive errors of a certain category, add a 74 'NOLINT(category)' comment to the line. NOLINT or NOLINT(*) 75 suppresses errors of all categories on that line. 77 The files passed in will be linted; at least one file must be provided. 78 Default linted extensions are .cc, .cpp, .cu, .cuh and .h. Change the 79 extensions with the --extensions flag. 84 By default, the output is formatted to ease emacs parsing. Visual Studio 85 compatible output (vs7) may also be used. Other formats are unsupported. 88 Specify a number 0-5 to restrict errors to certain verbosity levels. 91 Specify a comma-separated list of category-filters to apply: only 92 error messages whose category names pass the filters will be printed. 93 (Category names are printed with the message and look like 94 "[whitespace/indent]".) Filters are evaluated left to right. 95 "-FOO" and "FOO" means "do not print categories that start with FOO". 96 "+FOO" means "do print categories that start with FOO". 98 Examples: --filter=-whitespace,+whitespace/braces 99 --filter=whitespace,runtime/printf,+runtime/printf_format 100 --filter=-,+build/include_what_you_use 102 To see a list of all the categories used in cpplint, pass no arg: 105 counting=total|toplevel|detailed 106 The total number of errors found is always printed. If 107 'toplevel' is provided, then the count of errors in each of 108 the top-level categories like 'build' and 'whitespace' will 109 also be printed. If 'detailed' is provided, then a count 110 is provided for each category like 'build/class'. 113 The root directory used for deriving header guard CPP variable. 114 By default, the header guard CPP variable is calculated as the relative 115 path to the directory that contains .git, .hg, or .svn. When this flag 116 is specified, the relative path is calculated from the specified 117 directory. If the specified directory does not exist, this flag is 121 Assuing that src/.git exists, the header guard CPP variables for 122 src/chrome/browser/ui/browser.h are: 124 No flag => CHROME_BROWSER_UI_BROWSER_H_ 125 --root=chrome => BROWSER_UI_BROWSER_H_ 126 --root=chrome/browser => UI_BROWSER_H_ 129 This is the allowed line length for the project. The default value is 135 extensions=extension,extension,... 136 The allowed file extensions that cpplint will check 146 _ERROR_CATEGORIES = [
149 'build/endif_comment',
150 'build/explicit_make_pair',
151 'build/forward_decl',
152 'build/header_guard',
154 'build/include_alpha',
155 'build/include_order',
156 'build/include_what_you_use',
158 'build/printf_format',
159 'build/storage_class',
161 'readability/alt_tokens',
162 'readability/braces',
163 'readability/casting',
165 'readability/constructors',
166 'readability/fn_size',
167 'readability/function',
168 'readability/multiline_comment',
169 'readability/multiline_string',
170 'readability/namespace',
171 'readability/nolint',
173 'readability/streams',
181 'runtime/invalid_increment',
182 'runtime/member_string_references',
186 'runtime/printf_format',
187 'runtime/references',
189 'runtime/threadsafe_fn',
191 'whitespace/blank_line',
194 'whitespace/comments',
195 'whitespace/empty_conditional_body',
196 'whitespace/empty_loop_body',
197 'whitespace/end_of_line',
198 'whitespace/ending_newline',
199 'whitespace/forcolon',
201 'whitespace/line_length',
202 'whitespace/newline',
203 'whitespace/operators',
205 'whitespace/semicolon',
214 _DEFAULT_FILTERS = [
'-build/include_alpha']
222 _CPP_HEADERS = frozenset([
283 'condition_variable',
362 'EXPECT_TRUE_M',
'EXPECT_TRUE',
363 'ASSERT_TRUE_M',
'ASSERT_TRUE',
364 'EXPECT_FALSE_M',
'EXPECT_FALSE',
365 'ASSERT_FALSE_M',
'ASSERT_FALSE',
369 _CHECK_REPLACEMENT = dict([(m, {})
for m
in _CHECK_MACROS])
371 for op, replacement
in [(
'==',
'EQ'), (
'!=',
'NE'),
372 (
'>=',
'GE'), (
'>',
'GT'),
373 (
'<=',
'LE'), (
'<',
'LT')]:
374 _CHECK_REPLACEMENT[
'DCHECK'][op] =
'DCHECK_%s' % replacement
375 _CHECK_REPLACEMENT[
'CHECK'][op] =
'CHECK_%s' % replacement
376 _CHECK_REPLACEMENT[
'EXPECT_TRUE'][op] =
'EXPECT_%s' % replacement
377 _CHECK_REPLACEMENT[
'ASSERT_TRUE'][op] =
'ASSERT_%s' % replacement
378 _CHECK_REPLACEMENT[
'EXPECT_TRUE_M'][op] =
'EXPECT_%s_M' % replacement
379 _CHECK_REPLACEMENT[
'ASSERT_TRUE_M'][op] =
'ASSERT_%s_M' % replacement
381 for op, inv_replacement
in [(
'==',
'NE'), (
'!=',
'EQ'),
382 (
'>=',
'LT'), (
'>',
'LE'),
383 (
'<=',
'GT'), (
'<',
'GE')]:
384 _CHECK_REPLACEMENT[
'EXPECT_FALSE'][op] =
'EXPECT_%s' % inv_replacement
385 _CHECK_REPLACEMENT[
'ASSERT_FALSE'][op] =
'ASSERT_%s' % inv_replacement
386 _CHECK_REPLACEMENT[
'EXPECT_FALSE_M'][op] =
'EXPECT_%s_M' % inv_replacement
387 _CHECK_REPLACEMENT[
'ASSERT_FALSE_M'][op] =
'ASSERT_%s_M' % inv_replacement
394 _ALT_TOKEN_REPLACEMENT = {
413 _ALT_TOKEN_REPLACEMENT_PATTERN = re.compile(
414 r'[ =()](' + (
'|'.join(_ALT_TOKEN_REPLACEMENT.keys())) +
r')(?=[ (]|$)')
421 _LIKELY_MY_HEADER = 3
422 _POSSIBLE_MY_HEADER = 4
432 _MATCH_ASM = re.compile(
r'^\s*(?:asm|_asm|__asm|__asm__)' 433 r'(?:\s+(volatile|__volatile__))?' 437 _regexp_compile_cache = {}
440 _RE_SUPPRESSION = re.compile(
r'\bNOLINT\b(\([^)]*\))?')
444 _error_suppressions = {}
456 _valid_extensions = set([
'cc',
'h',
'cpp',
'cu',
'cuh'])
459 """Updates the global list of error-suppressions. 461 Parses any NOLINT comments on the current line, updating the global 462 error_suppressions store. Reports an error if the NOLINT comment 466 filename: str, the name of the input file. 467 raw_line: str, the line of input text, with comments. 468 linenum: int, the number of the current line. 469 error: function, an error handler. 472 matched = _RE_SUPPRESSION.search(raw_line)
474 category = matched.group(1)
475 if category
in (
None,
'(*)'):
476 _error_suppressions.setdefault(
None, set()).add(linenum)
478 if category.startswith(
'(')
and category.endswith(
')'):
479 category = category[1:-1]
480 if category
in _ERROR_CATEGORIES:
481 _error_suppressions.setdefault(category, set()).add(linenum)
483 error(filename, linenum,
'readability/nolint', 5,
484 'Unknown NOLINT error category: %s' % category)
488 "Resets the set of NOLINT suppressions to empty." 489 _error_suppressions.clear()
493 """Returns true if the specified error category is suppressed on this line. 495 Consults the global error_suppressions map populated by 496 ParseNolintSuppressions/ResetNolintSuppressions. 499 category: str, the category of the error. 500 linenum: int, the current line number. 502 bool, True iff the error should be suppressed due to a NOLINT comment. 504 return (linenum
in _error_suppressions.get(category, set())
or 505 linenum
in _error_suppressions.get(
None, set()))
508 """Matches the string with the pattern, caching the compiled regexp.""" 512 if pattern
not in _regexp_compile_cache:
513 _regexp_compile_cache[pattern] = sre_compile.compile(pattern)
514 return _regexp_compile_cache[pattern].match(s)
518 """Replaces instances of pattern in a string with a replacement. 520 The compiled regex is kept in a cache shared by Match and Search. 523 pattern: regex pattern 524 rep: replacement text 528 string with replacements made (or original string if no replacements) 530 if pattern
not in _regexp_compile_cache:
531 _regexp_compile_cache[pattern] = sre_compile.compile(pattern)
532 return _regexp_compile_cache[pattern].sub(rep, s)
536 """Searches the string for the pattern, caching the compiled regexp.""" 537 if pattern
not in _regexp_compile_cache:
538 _regexp_compile_cache[pattern] = sre_compile.compile(pattern)
539 return _regexp_compile_cache[pattern].search(s)
543 """Tracks line numbers for includes, and the order in which includes appear. 545 As a dict, an _IncludeState object serves as a mapping between include 546 filename and line number on which that file was included. 548 Call CheckNextIncludeOrder() once for each header in the file, passing 549 in the type constants defined above. Calls in an illegal order will 550 raise an _IncludeError with an appropriate error message. 562 _C_SYS_HEADER:
'C system header',
563 _CPP_SYS_HEADER:
'C++ system header',
564 _LIKELY_MY_HEADER:
'header this file implements',
565 _POSSIBLE_MY_HEADER:
'header this file may implement',
566 _OTHER_HEADER:
'other header',
569 _INITIAL_SECTION:
"... nothing. (This can't be an error.)",
570 _MY_H_SECTION:
'a header this file implements',
571 _C_SECTION:
'C system header',
572 _CPP_SECTION:
'C++ system header',
573 _OTHER_H_SECTION:
'other header',
590 """Returns a path canonicalized for alphabetical comparison. 592 - replaces "-" with "_" so they both cmp the same. 593 - removes '-inl' since we don't require them to be after the main header. 594 - lowercase everything, just in case. 597 header_path: Path to be canonicalized. 602 return header_path.replace(
'-inl.h',
'.h').replace(
'-',
'_').lower()
605 """Check if a header is in alphabetical order with the previous header. 608 clean_lines: A CleansedLines instance containing the file. 609 linenum: The number of the line to check. 610 header_path: Canonicalized header to be checked. 613 Returns true if the header is in alphabetical order. 621 not Match(
r'^\s*$', clean_lines.elided[linenum - 1])):
626 """Returns a non-empty error message if the next header is out of order. 628 This function also updates the internal state to be ready to check 632 header_type: One of the _XXX_HEADER constants defined above. 635 The empty string if the header is in the right order, or an 636 error message describing what's wrong. 639 error_message = (
'Found %s after %s' %
645 if header_type == _C_SYS_HEADER:
651 elif header_type == _CPP_SYS_HEADER:
657 elif header_type == _LIKELY_MY_HEADER:
662 elif header_type == _POSSIBLE_MY_HEADER:
670 assert header_type == _OTHER_HEADER
680 """Maintains module-wide state..""" 696 """Sets the output format for errors.""" 700 """Sets the module's verbosity, and returns the previous setting.""" 703 return last_verbose_level
706 """Sets the module's counting options.""" 710 """Sets the error-message filters. 712 These filters are applied when deciding whether to emit a given 716 filters: A string of comma-separated filters (eg "+whitespace/indent"). 717 Each filter should start with + or -; else we die. 720 ValueError: The comma-separated filters did not all start with '+' or '-'. 721 E.g. "-,+whitespace,-whitespace/indent,whitespace/badfilter" 724 self.
filters = _DEFAULT_FILTERS[:]
725 for filt
in filters.split(
','):
726 clean_filt = filt.strip()
728 self.filters.append(clean_filt)
730 if not (filt.startswith(
'+')
or filt.startswith(
'-')):
731 raise ValueError(
'Every filter in --filters must start with + or -' 732 ' (%s does not)' % filt)
735 """Sets the module's error statistic back to zero.""" 740 """Bumps the module's error statistic.""" 742 if self.
counting in (
'toplevel',
'detailed'):
744 category = category.split(
'/')[0]
750 """Print a summary of errors by category, and the total.""" 751 for category, count
in self.errors_by_category.iteritems():
752 sys.stderr.write(
'Category \'%s\' errors found: %d\n' %
754 sys.stderr.write(
'Total errors found: %d\n' % self.
error_count)
760 """Gets the module's output format.""" 761 return _cpplint_state.output_format
765 """Sets the module's output format.""" 766 _cpplint_state.SetOutputFormat(output_format)
770 """Returns the module's verbosity setting.""" 771 return _cpplint_state.verbose_level
775 """Sets the module's verbosity, and returns the previous setting.""" 776 return _cpplint_state.SetVerboseLevel(level)
780 """Sets the module's counting options.""" 781 _cpplint_state.SetCountingStyle(level)
785 """Returns the module's list of output filters, as a list.""" 786 return _cpplint_state.filters
790 """Sets the module's error-message filters. 792 These filters are applied when deciding whether to emit a given 796 filters: A string of comma-separated filters (eg "whitespace/indent"). 797 Each filter should start with + or -; else we die. 799 _cpplint_state.SetFilters(filters)
803 """Tracks current function name and the number of lines in its body.""" 805 _NORMAL_TRIGGER = 250
814 """Start analyzing function body. 817 function_name: The name of the function being tracked. 824 """Count line in current function body.""" 828 def Check(self, error, filename, linenum):
829 """Report if too many lines in function body. 832 error: The function to call with any errors found. 833 filename: The name of the current file. 834 linenum: The number of the line to check. 847 error(filename, linenum,
'readability/fn_size', error_level,
848 'Small and focused functions are preferred:' 849 ' %s has %d non-comment lines' 850 ' (error triggered by exceeding %d lines).' % (
854 """Stop analyzing function body.""" 859 """Indicates a problem with the include order in a file.""" 864 """Provides utility functions for filenames. 866 FileInfo provides easy access to the components of a file's path 867 relative to the project root. 874 """Make Windows paths like Unix.""" 875 return os.path.abspath(self.
_filename).replace(
'\\',
'/')
878 """FullName after removing the local path to the repository. 880 If we have a real absolute path name here we can try to do something smart: 881 detecting the root of the checkout and truncating /path/to/checkout from 882 the name so that we get header guards that don't include things like 883 "C:\Documents and Settings\..." or "/home/username/..." in them and thus 884 people on different computers who have checked the source out to different 885 locations won't see bogus errors. 889 if os.path.exists(fullname):
890 project_dir = os.path.dirname(fullname)
892 if os.path.exists(os.path.join(project_dir,
".svn")):
895 root_dir = project_dir
896 one_up_dir = os.path.dirname(root_dir)
897 while os.path.exists(os.path.join(one_up_dir,
".svn")):
898 root_dir = os.path.dirname(root_dir)
899 one_up_dir = os.path.dirname(one_up_dir)
901 prefix = os.path.commonprefix([root_dir, project_dir])
902 return fullname[len(prefix) + 1:]
906 root_dir = os.path.dirname(fullname)
907 while (root_dir != os.path.dirname(root_dir)
and 908 not os.path.exists(os.path.join(root_dir,
".git"))
and 909 not os.path.exists(os.path.join(root_dir,
".hg"))
and 910 not os.path.exists(os.path.join(root_dir,
".svn"))):
911 root_dir = os.path.dirname(root_dir)
913 if (os.path.exists(os.path.join(root_dir,
".git"))
or 914 os.path.exists(os.path.join(root_dir,
".hg"))
or 915 os.path.exists(os.path.join(root_dir,
".svn"))):
916 prefix = os.path.commonprefix([root_dir, project_dir])
917 return fullname[len(prefix) + 1:]
923 """Splits the file into the directory, basename, and extension. 925 For 'chrome/browser/browser.cc', Split() would 926 return ('chrome/browser', 'browser', '.cc') 929 A tuple of (directory, basename, extension). 933 project, rest = os.path.split(googlename)
934 return (project,) + os.path.splitext(rest)
937 """File base name - text after the final slash, before the final period.""" 938 return self.
Split()[1]
941 """File extension - text following the final period.""" 942 return self.
Split()[2]
945 """File has no source file extension.""" 946 return '/'.join(self.
Split()[0:2])
949 """File has a source file extension.""" 950 return self.
Extension()[1:]
in (
'c',
'cc',
'cpp',
'cxx')
954 """If confidence >= verbose, category passes filter and is not suppressed.""" 961 if confidence < _cpplint_state.verbose_level:
966 if one_filter.startswith(
'-'):
967 if category.startswith(one_filter[1:]):
969 elif one_filter.startswith(
'+'):
970 if category.startswith(one_filter[1:]):
980 def Error(filename, linenum, category, confidence, message):
981 """Logs the fact we've found a lint error. 983 We log where the error was found, and also our confidence in the error, 984 that is, how certain we are this is a legitimate style regression, and 985 not a misidentification or a use that's sometimes justified. 987 False positives can be suppressed by the use of 988 "cpplint(category)" comments on the offending line. These are 989 parsed into _error_suppressions. 992 filename: The name of the file containing the error. 993 linenum: The number of the line containing the error. 994 category: A string used to describe the "category" this bug 995 falls under: "whitespace", say, or "runtime". Categories 996 may have a hierarchy separated by slashes: "whitespace/indent". 997 confidence: A number from 1-5 representing a confidence score for 998 the error, with 5 meaning that we are certain of the problem, 999 and 1 meaning that it could be a legitimate construct. 1000 message: The error message. 1003 _cpplint_state.IncrementErrorCount(category)
1004 if _cpplint_state.output_format ==
'vs7':
1005 sys.stderr.write(
'%s(%s): %s [%s] [%d]\n' % (
1006 filename, linenum, message, category, confidence))
1007 elif _cpplint_state.output_format ==
'eclipse':
1008 sys.stderr.write(
'%s:%s: warning: %s [%s] [%d]\n' % (
1009 filename, linenum, message, category, confidence))
1011 sys.stderr.write(
'%s:%s: %s [%s] [%d]\n' % (
1012 filename, linenum, message, category, confidence))
1016 _RE_PATTERN_CLEANSE_LINE_ESCAPES = re.compile(
1017 r'\\([abfnrtv?"\\\']|\d+|x[0-9a-fA-F]+)')
1019 _RE_PATTERN_CLEANSE_LINE_DOUBLE_QUOTES = re.compile(
r'"[^"]*"')
1021 _RE_PATTERN_CLEANSE_LINE_SINGLE_QUOTES = re.compile(
r"'.'")
1030 _RE_PATTERN_CLEANSE_LINE_C_COMMENTS = re.compile(
1031 r"""(\s*/\*.*\*/\s*$| 1034 /\*.*\*/)""", re.VERBOSE)
1038 """Does line terminate so, that the next symbol is in string constant. 1040 This function does not consider single-line nor multi-line comments. 1043 line: is a partial line of code starting from the 0..n. 1046 True, if next character appended to 'line' is inside a 1050 line = line.replace(
r'\\',
'XX')
1051 return ((line.count(
'"') - line.count(
r'\"') - line.count(
"'\"'")) & 1) == 1
1055 """Removes C++11 raw strings from lines. 1058 static const char kData[] = R"( 1063 static const char kData[] = "" 1064 (replaced by blank line) 1068 raw_lines: list of raw lines. 1071 list of lines with C++11 raw strings replaced by empty strings. 1075 lines_without_raw_strings = []
1076 for line
in raw_lines:
1079 end = line.find(delimiter)
1084 leading_space =
Match(
r'^(\s*)\S', line)
1085 line = leading_space.group(1) +
'""' + line[end + len(delimiter):]
1094 matched =
Match(
r'^(.*)\b(?:R|u8R|uR|UR|LR)"([^\s\\()]*)\((.*)$', line)
1096 delimiter =
')' + matched.group(2) +
'"' 1098 end = matched.group(3).find(delimiter)
1101 line = (matched.group(1) +
'""' +
1102 matched.group(3)[end + len(delimiter):])
1106 line = matched.group(1) +
'""' 1108 lines_without_raw_strings.append(line)
1112 return lines_without_raw_strings
1116 """Find the beginning marker for a multiline comment.""" 1117 while lineix < len(lines):
1118 if lines[lineix].strip().startswith(
'/*'):
1120 if lines[lineix].strip().find(
'*/', 2) < 0:
1127 """We are inside a comment, find the end marker.""" 1128 while lineix < len(lines):
1129 if lines[lineix].strip().endswith(
'*/'):
1136 """Clears a range of lines for multi-line comments.""" 1139 for i
in range(begin, end):
1140 lines[i] =
'// dummy' 1144 """Removes multiline (c-style) comments from lines.""" 1146 while lineix < len(lines):
1148 if lineix_begin >= len(lines):
1151 if lineix_end >= len(lines):
1152 error(filename, lineix_begin + 1,
'readability/multiline_comment', 5,
1153 'Could not find end of multi-line comment')
1156 lineix = lineix_end + 1
1160 """Removes //-comments and single-line C-style /* */ comments. 1163 line: A line of C++ source. 1166 The line with single-line comments removed. 1168 commentpos = line.find(
'//')
1169 if commentpos != -1
and not IsCppString(line[:commentpos]):
1170 line = line[:commentpos].rstrip()
1172 return _RE_PATTERN_CLEANSE_LINE_C_COMMENTS.sub(
'', line)
1176 """Holds 3 copies of all lines with different preprocessing applied to them. 1178 1) elided member contains lines without strings and comments, 1179 2) lines member contains lines without comments, and 1180 3) raw_lines member contains all the lines without processing. 1181 All these three members are of <type 'list'>, and of the same length. 1197 """Returns the number of lines represented.""" 1202 """Collapses strings and chars on a line to simple "" or '' blocks. 1204 We nix strings first so we're not fooled by text like '"http://"' 1207 elided: The line being processed. 1210 The line with collapsed strings. 1212 if not _RE_PATTERN_INCLUDE.match(elided):
1216 elided = _RE_PATTERN_CLEANSE_LINE_ESCAPES.sub(
'', elided)
1217 elided = _RE_PATTERN_CLEANSE_LINE_SINGLE_QUOTES.sub(
"''", elided)
1218 elided = _RE_PATTERN_CLEANSE_LINE_DOUBLE_QUOTES.sub(
'""', elided)
1223 """Find the position just after the matching endchar. 1226 line: a CleansedLines line. 1227 startpos: start searching at this position. 1228 depth: nesting level at startpos. 1229 startchar: expression opening character. 1230 endchar: expression closing character. 1233 On finding matching endchar: (index just after matching endchar, 0) 1234 Otherwise: (-1, new depth at end of this line) 1236 for i
in xrange(startpos, len(line)):
1237 if line[i] == startchar:
1239 elif line[i] == endchar:
1247 """If input points to ( or { or [ or <, finds the position that closes it. 1249 If lines[linenum][pos] points to a '(' or '{' or '[' or '<', finds the 1250 linenum/pos that correspond to the closing of the expression. 1253 clean_lines: A CleansedLines instance containing the file. 1254 linenum: The number of the line to check. 1255 pos: A position on the line. 1258 A tuple (line, linenum, pos) pointer *past* the closing brace, or 1259 (line, len(lines), -1) if we never find a close. Note we ignore 1260 strings and comments when matching; and the line we return is the 1261 'cleansed' line at linenum. 1264 line = clean_lines.elided[linenum]
1265 startchar = line[pos]
1266 if startchar
not in '({[<':
1267 return (line, clean_lines.NumLines(), -1)
1268 if startchar ==
'(': endchar =
')' 1269 if startchar ==
'[': endchar =
']' 1270 if startchar ==
'{': endchar =
'}' 1271 if startchar ==
'<': endchar =
'>' 1275 line, pos, 0, startchar, endchar)
1277 return (line, linenum, end_pos)
1280 while linenum < clean_lines.NumLines() - 1:
1282 line = clean_lines.elided[linenum]
1284 line, 0, num_open, startchar, endchar)
1286 return (line, linenum, end_pos)
1289 return (line, clean_lines.NumLines(), -1)
1293 """Find position at the matching startchar. 1295 This is almost the reverse of FindEndOfExpressionInLine, but note 1296 that the input position and returned position differs by 1. 1299 line: a CleansedLines line. 1300 endpos: start searching at this position. 1301 depth: nesting level at endpos. 1302 startchar: expression opening character. 1303 endchar: expression closing character. 1306 On finding matching startchar: (index at matching startchar, 0) 1307 Otherwise: (-1, new depth at beginning of this line) 1309 for i
in xrange(endpos, -1, -1):
1310 if line[i] == endchar:
1312 elif line[i] == startchar:
1320 """If input points to ) or } or ] or >, finds the position that opens it. 1322 If lines[linenum][pos] points to a ')' or '}' or ']' or '>', finds the 1323 linenum/pos that correspond to the opening of the expression. 1326 clean_lines: A CleansedLines instance containing the file. 1327 linenum: The number of the line to check. 1328 pos: A position on the line. 1331 A tuple (line, linenum, pos) pointer *at* the opening brace, or 1332 (line, 0, -1) if we never find the matching opening brace. Note 1333 we ignore strings and comments when matching; and the line we 1334 return is the 'cleansed' line at linenum. 1336 line = clean_lines.elided[linenum]
1338 if endchar
not in ')}]>':
1339 return (line, 0, -1)
1340 if endchar ==
')': startchar =
'(' 1341 if endchar ==
']': startchar =
'[' 1342 if endchar ==
'}': startchar =
'{' 1343 if endchar ==
'>': startchar =
'<' 1347 line, pos, 0, startchar, endchar)
1349 return (line, linenum, start_pos)
1354 line = clean_lines.elided[linenum]
1356 line, len(line) - 1, num_open, startchar, endchar)
1358 return (line, linenum, start_pos)
1361 return (line, 0, -1)
1365 """Logs an error if no Copyright message appears at the top of the file.""" 1369 for line
in xrange(1, min(len(lines), 11)):
1370 if re.search(
r'Copyright', lines[line], re.I):
break 1372 error(filename, 0,
'legal/copyright', 5,
1373 'No copyright message found. ' 1374 'You should have a line: "Copyright [year] <Copyright Owner>"')
1378 """Returns the CPP variable that should be used as a header guard. 1381 filename: The name of a C++ header file. 1384 The CPP variable that should be used as a header guard in the 1391 filename = re.sub(
r'_flymake\.h$',
'.h', filename)
1392 filename = re.sub(
r'/\.flymake/([^/]*)$',
r'/\1', filename)
1395 file_path_from_root = fileinfo.RepositoryName()
1397 file_path_from_root = re.sub(
'^' + _root + os.sep,
'', file_path_from_root)
1398 return re.sub(
r'[-./\s]',
'_', file_path_from_root).upper() +
'_' 1402 """Checks that the file contains a header guard. 1404 Logs an error if no #ifndef header guard is present. For other 1405 headers, checks that the full pathname is used. 1408 filename: The name of the C++ header file. 1409 lines: An array of strings, each representing a line of the file. 1410 error: The function to call with any errors found. 1420 for linenum, line
in enumerate(lines):
1421 linesplit = line.split()
1422 if len(linesplit) >= 2:
1424 if not ifndef
and linesplit[0] ==
'#ifndef':
1426 ifndef = linesplit[1]
1427 ifndef_linenum = linenum
1428 if not define
and linesplit[0] ==
'#define':
1429 define = linesplit[1]
1431 if line.startswith(
'#endif'):
1433 endif_linenum = linenum
1436 error(filename, 0,
'build/header_guard', 5,
1437 'No #ifndef header guard found, suggested CPP variable is: %s' %
1442 error(filename, 0,
'build/header_guard', 5,
1443 'No #define header guard found, suggested CPP variable is: %s' %
1449 if ifndef != cppvar:
1451 if ifndef != cppvar +
'_':
1456 error(filename, ifndef_linenum,
'build/header_guard', error_level,
1457 '#ifndef header guard has wrong style, please use: %s' % cppvar)
1459 if define != ifndef:
1460 error(filename, 0,
'build/header_guard', 5,
1461 '#ifndef and #define don\'t match, suggested CPP variable is: %s' %
1465 if endif != (
'#endif // %s' % cppvar):
1467 if endif != (
'#endif // %s' % (cppvar +
'_')):
1472 error(filename, endif_linenum,
'build/header_guard', error_level,
1473 '#endif line should be "#endif // %s"' % cppvar)
1477 """Logs an error for each line containing bad characters. 1479 Two kinds of bad characters: 1481 1. Unicode replacement characters: These indicate that either the file 1482 contained invalid UTF-8 (likely) or Unicode replacement characters (which 1483 it shouldn't). Note that it's possible for this to throw off line 1484 numbering if the invalid UTF-8 occurred adjacent to a newline. 1486 2. NUL bytes. These are problematic for some tools. 1489 filename: The name of the current file. 1490 lines: An array of strings, each representing a line of the file. 1491 error: The function to call with any errors found. 1493 for linenum, line
in enumerate(lines):
1494 if u'\ufffd' in line:
1495 error(filename, linenum,
'readability/utf8', 5,
1496 'Line contains invalid UTF-8 (or Unicode replacement character).')
1498 error(filename, linenum,
'readability/nul', 5,
'Line contains NUL byte.')
1502 """Logs an error if there is no newline char at the end of the file. 1505 filename: The name of the current file. 1506 lines: An array of strings, each representing a line of the file. 1507 error: The function to call with any errors found. 1514 if len(lines) < 3
or lines[-2]:
1515 error(filename, len(lines) - 2,
'whitespace/ending_newline', 5,
1516 'Could not find a newline character at the end of the file.')
1520 """Logs an error if we see /* ... */ or "..." that extend past one line. 1522 /* ... */ comments are legit inside macros, for one line. 1523 Otherwise, we prefer // comments, so it's ok to warn about the 1524 other. Likewise, it's ok for strings to extend across multiple 1525 lines, as long as a line continuation character (backslash) 1526 terminates each line. Although not currently prohibited by the C++ 1527 style guide, it's ugly and unnecessary. We don't do well with either 1528 in this lint program, so we warn about both. 1531 filename: The name of the current file. 1532 clean_lines: A CleansedLines instance containing the file. 1533 linenum: The number of the line to check. 1534 error: The function to call with any errors found. 1536 line = clean_lines.elided[linenum]
1540 line = line.replace(
'\\\\',
'')
1542 if line.count(
'/*') > line.count(
'*/'):
1543 error(filename, linenum,
'readability/multiline_comment', 5,
1544 'Complex multi-line /*...*/-style comment found. ' 1545 'Lint may give bogus warnings. ' 1546 'Consider replacing these with //-style comments, ' 1547 'with #if 0...#endif, ' 1548 'or with more clearly structured multi-line comments.')
1550 if (line.count(
'"') - line.count(
'\\"')) % 2:
1551 error(filename, linenum,
'readability/multiline_string', 5,
1552 'Multi-line string ("...") found. This lint script doesn\'t ' 1553 'do well with such strings, and may give bogus warnings. ' 1554 'Use C++11 raw strings or concatenation instead.')
1558 (
'asctime(',
'asctime_r('),
1559 (
'ctime(',
'ctime_r('),
1560 (
'getgrgid(',
'getgrgid_r('),
1561 (
'getgrnam(',
'getgrnam_r('),
1562 (
'getlogin(',
'getlogin_r('),
1563 (
'getpwnam(',
'getpwnam_r('),
1564 (
'getpwuid(',
'getpwuid_r('),
1565 (
'gmtime(',
'gmtime_r('),
1566 (
'localtime(',
'localtime_r('),
1567 (
'rand(',
'rand_r('),
1568 (
'strtok(',
'strtok_r('),
1569 (
'ttyname(',
'ttyname_r('),
1574 """Checks for calls to thread-unsafe functions. 1576 Much code has been originally written without consideration of 1577 multi-threading. Also, engineers are relying on their old experience; 1578 they have learned posix before threading extensions were added. These 1579 tests guide the engineers to use thread-safe functions (when using 1583 filename: The name of the current file. 1584 clean_lines: A CleansedLines instance containing the file. 1585 linenum: The number of the line to check. 1586 error: The function to call with any errors found. 1588 line = clean_lines.elided[linenum]
1589 for single_thread_function, multithread_safe_function
in threading_list:
1590 ix = line.find(single_thread_function)
1592 if ix >= 0
and (ix == 0
or (
not line[ix - 1].isalnum()
and 1593 line[ix - 1]
not in (
'_',
'.',
'>'))):
1594 error(filename, linenum,
'runtime/threadsafe_fn', 2,
1595 'Consider using ' + multithread_safe_function +
1596 '...) instead of ' + single_thread_function +
1597 '...) for improved thread safety.')
1601 """Checks that VLOG() is only used for defining a logging level. 1603 For example, VLOG(2) is correct. VLOG(INFO), VLOG(WARNING), VLOG(ERROR), and 1604 VLOG(FATAL) are not. 1607 filename: The name of the current file. 1608 clean_lines: A CleansedLines instance containing the file. 1609 linenum: The number of the line to check. 1610 error: The function to call with any errors found. 1612 line = clean_lines.elided[linenum]
1613 if Search(
r'\bVLOG\((INFO|ERROR|WARNING|DFATAL|FATAL)\)', line):
1614 error(filename, linenum,
'runtime/vlog', 5,
1615 'VLOG() should be used with numeric verbosity level. ' 1616 'Use LOG() if you want symbolic severity levels.')
1621 _RE_PATTERN_INVALID_INCREMENT = re.compile(
1622 r'^\s*\*\w+(\+\+|--);')
1626 """Checks for invalid increment *count++. 1628 For example following function: 1629 void increment_counter(int* count) { 1632 is invalid, because it effectively does count++, moving pointer, and should 1633 be replaced with ++*count, (*count)++ or *count += 1. 1636 filename: The name of the current file. 1637 clean_lines: A CleansedLines instance containing the file. 1638 linenum: The number of the line to check. 1639 error: The function to call with any errors found. 1641 line = clean_lines.elided[linenum]
1642 if _RE_PATTERN_INVALID_INCREMENT.match(line):
1643 error(filename, linenum,
'runtime/invalid_increment', 5,
1644 'Changing pointer instead of value (or unused value of operator*).')
1648 """Stores information about a generic block of code.""" 1656 """Run checks that applies to text up to the opening brace. 1658 This is mostly for checking the text after the class identifier 1659 and the "{", usually where the base class is specified. For other 1660 blocks, there isn't much to check, so we always pass. 1663 filename: The name of the current file. 1664 clean_lines: A CleansedLines instance containing the file. 1665 linenum: The number of the line to check. 1666 error: The function to call with any errors found. 1670 def CheckEnd(self, filename, clean_lines, linenum, error):
1671 """Run checks that applies to text after the closing brace. 1673 This is mostly used for checking end of namespace comments. 1676 filename: The name of the current file. 1677 clean_lines: A CleansedLines instance containing the file. 1678 linenum: The number of the line to check. 1679 error: The function to call with any errors found. 1684 class _ClassInfo(_BlockInfo):
1685 """Stores information about a class.""" 1687 def __init__(self, name, class_or_struct, clean_lines, linenum):
1688 _BlockInfo.__init__(self,
False)
1692 if class_or_struct ==
'struct':
1701 initial_indent =
Match(
r'^( *)\S', clean_lines.raw_lines[linenum])
1714 for i
in range(linenum, clean_lines.NumLines()):
1715 line = clean_lines.elided[i]
1716 depth += line.count(
'{') - line.count(
'}')
1723 if Search(
'(^|[^:]):($|[^:])', clean_lines.elided[linenum]):
1726 def CheckEnd(self, filename, clean_lines, linenum, error):
1730 indent =
Match(
r'^( *)\}', clean_lines.elided[linenum])
1731 if indent
and len(indent.group(1)) != self.
class_indent:
1733 parent =
'struct ' + self.
name 1735 parent =
'class ' + self.
name 1736 error(filename, linenum,
'whitespace/indent', 3,
1737 'Closing brace should be aligned with beginning of %s' % parent)
1741 """Stores information about a namespace.""" 1744 _BlockInfo.__init__(self,
False)
1748 def CheckEnd(self, filename, clean_lines, linenum, error):
1749 """Check end of namespace comments.""" 1750 line = clean_lines.raw_lines[linenum]
1764 and not Match(
r'};*\s*(//|/\*).*\bnamespace\b', line)):
1781 if not Match((
r'};*\s*(//|/\*).*\bnamespace\s+' + re.escape(self.
name) +
1784 error(filename, linenum,
'readability/namespace', 5,
1785 'Namespace should be terminated with "// namespace %s"' %
1789 if not Match(
r'};*\s*(//|/\*).*\bnamespace[\*/\.\\\s]*$', line):
1790 error(filename, linenum,
'readability/namespace', 5,
1791 'Namespace should be terminated with "// namespace"')
1795 """Stores checkpoints of nesting stacks when #if/#else is seen.""" 1809 """Holds states related to parsing braces.""" 1824 """Check if we have seen the opening brace for the innermost block. 1827 True if we have seen the opening brace, False if the innermost 1828 block is still expecting an opening brace. 1830 return (
not self.
stack)
or self.
stack[-1].seen_open_brace
1833 """Check if we are currently one level inside a namespace body. 1836 True if top of the stack is a namespace block, False otherwise. 1838 return self.
stack and isinstance(self.
stack[-1], _NamespaceInfo)
1841 """Update preprocessor stack. 1843 We need to handle preprocessors due to classes like this: 1845 struct ResultDetailsPageElementExtensionPoint { 1847 struct ResultDetailsPageElementExtensionPoint : public Extension { 1850 We make the following assumptions (good enough for most files): 1851 - Preprocessor condition evaluates to true from #if up to first 1854 - Preprocessor condition evaluates to false from #else/#elif up 1855 to #endif. We still perform lint checks on these lines, but 1856 these do not affect nesting stack. 1859 line: current line to check. 1861 if Match(
r'^\s*#\s*(if|ifdef|ifndef)\b', line):
1865 elif Match(
r'^\s*#\s*(else|elif)\b', line):
1868 if not self.
pp_stack[-1].seen_else:
1873 self.
pp_stack[-1].stack_before_else = copy.deepcopy(self.
stack)
1876 self.
stack = copy.deepcopy(self.
pp_stack[-1].stack_before_if)
1880 elif Match(
r'^\s*#\s*endif\b', line):
1896 def Update(self, filename, clean_lines, linenum, error):
1897 """Update nesting state with current line. 1900 filename: The name of the current file. 1901 clean_lines: A CleansedLines instance containing the file. 1902 linenum: The number of the line to check. 1903 error: The function to call with any errors found. 1905 line = clean_lines.elided[linenum]
1913 inner_block = self.
stack[-1]
1914 depth_change = line.count(
'(') - line.count(
')')
1915 inner_block.open_parentheses += depth_change
1918 if inner_block.inline_asm
in (_NO_ASM, _END_ASM):
1919 if (depth_change != 0
and 1920 inner_block.open_parentheses == 1
and 1921 _MATCH_ASM.match(line)):
1923 inner_block.inline_asm = _INSIDE_ASM
1927 inner_block.inline_asm = _NO_ASM
1928 elif (inner_block.inline_asm == _INSIDE_ASM
and 1929 inner_block.open_parentheses == 0):
1931 inner_block.inline_asm = _END_ASM
1941 namespace_decl_match =
Match(
r'^\s*namespace\b\s*([:\w]+)?(.*)$', line)
1942 if not namespace_decl_match:
1945 new_namespace =
_NamespaceInfo(namespace_decl_match.group(1), linenum)
1946 self.stack.append(new_namespace)
1948 line = namespace_decl_match.group(2)
1949 if line.find(
'{') != -1:
1950 new_namespace.seen_open_brace =
True 1951 line = line[line.find(
'{') + 1:]
1974 class_decl_match =
Match(
1975 r'\s*(template\s*<[\w\s<>,:]*>\s*)?' 1976 r'(class|struct)\s+([A-Z_]+\s+)*(\w+(?:::\w+)*)' 1977 r'(([^=>]|<[^<>]*>|<[^<>]*<[^<>]*>\s*>)*)$', line)
1978 if (class_decl_match
and 1979 (
not self.
stack or self.
stack[-1].open_parentheses == 0)):
1981 class_decl_match.group(4), class_decl_match.group(2),
1982 clean_lines, linenum))
1983 line = class_decl_match.group(5)
1988 self.
stack[-1].CheckBegin(filename, clean_lines, linenum, error)
1991 if self.
stack and isinstance(self.
stack[-1], _ClassInfo):
1992 classinfo = self.
stack[-1]
1993 access_match =
Match(
1994 r'^(.*)\b(public|private|protected|signals)(\s+(?:slots\s*)?)?' 1998 classinfo.access = access_match.group(2)
2002 indent = access_match.group(1)
2003 if (len(indent) != classinfo.class_indent + 1
and 2004 Match(
r'^\s*$', indent)):
2005 if classinfo.is_struct:
2006 parent =
'struct ' + classinfo.name
2008 parent =
'class ' + classinfo.name
2010 if access_match.group(3):
2011 slots = access_match.group(3)
2012 error(filename, linenum,
'whitespace/indent', 3,
2013 '%s%s: should be indented +1 space inside %s' % (
2014 access_match.group(2), slots, parent))
2019 matched =
Match(
r'^[^{;)}]*([{;)}])(.*)$', line)
2023 token = matched.group(1)
2029 self.
stack[-1].seen_open_brace =
True 2032 if _MATCH_ASM.match(line):
2033 self.
stack[-1].inline_asm = _BLOCK_ASM
2034 elif token ==
';' or token ==
')':
2048 self.
stack[-1].CheckEnd(filename, clean_lines, linenum, error)
2050 line = matched.group(2)
2053 """Get class info on the top of the stack. 2056 A _ClassInfo object if we are inside a class, or None otherwise. 2058 for i
in range(len(self.
stack), 0, -1):
2059 classinfo = self.
stack[i - 1]
2060 if isinstance(classinfo, _ClassInfo):
2065 """Checks that all classes and namespaces have been completely parsed. 2067 Call this when all lines in a file have been processed. 2069 filename: The name of the current file. 2070 error: The function to call with any errors found. 2075 for obj
in self.
stack:
2076 if isinstance(obj, _ClassInfo):
2077 error(filename, obj.starting_linenum,
'build/class', 5,
2078 'Failed to find complete declaration of class %s' %
2080 elif isinstance(obj, _NamespaceInfo):
2081 error(filename, obj.starting_linenum,
'build/namespaces', 5,
2082 'Failed to find complete declaration of namespace %s' %
2087 nesting_state, error):
2088 r"""Logs an error if we see certain non-ANSI constructs ignored by gcc-2. 2090 Complain about several constructs which gcc-2 accepts, but which are 2091 not standard C++. Warning about these in lint is one way to ease the 2092 transition to new compilers. 2093 - put storage class first (e.g. "static const" instead of "const static"). 2094 - "%lld" instead of %qd" in printf-type functions. 2095 - "%1$d" is non-standard in printf-type functions. 2096 - "\%" is an undefined character escape sequence. 2097 - text after #endif is not allowed. 2098 - invalid inner-style forward declaration. 2099 - >? and <? operators, and their >?= and <?= cousins. 2101 Additionally, check for constructor/destructor style violations and reference 2102 members, as it is very convenient to do so while checking for 2106 filename: The name of the current file. 2107 clean_lines: A CleansedLines instance containing the file. 2108 linenum: The number of the line to check. 2109 nesting_state: A _NestingState instance which maintains information about 2110 the current stack of nested blocks being parsed. 2111 error: A callable to which errors are reported, which takes 4 arguments: 2112 filename, line number, error level, and message 2116 line = clean_lines.lines[linenum]
2118 if Search(
r'printf\s*\(.*".*%[-+ ]?\d*q', line):
2119 error(filename, linenum,
'runtime/printf_format', 3,
2120 '%q in format strings is deprecated. Use %ll instead.')
2122 if Search(
r'printf\s*\(.*".*%\d+\$', line):
2123 error(filename, linenum,
'runtime/printf_format', 2,
2124 '%N$ formats are unconventional. Try rewriting to avoid them.')
2127 line = line.replace(
'\\\\',
'')
2129 if Search(
r'("|\').*\\(%|\[|\(|{)', line):
2130 error(filename, linenum,
'build/printf_format', 3,
2131 '%, [, (, and { are undefined character escapes. Unescape them.')
2134 line = clean_lines.elided[linenum]
2136 if Search(
r'\b(const|volatile|void|char|short|int|long' 2137 r'|float|double|signed|unsigned' 2138 r'|schar|u?int8|u?int16|u?int32|u?int64)' 2139 r'\s+(register|static|extern|typedef)\b',
2141 error(filename, linenum,
'build/storage_class', 5,
2142 'Storage class (static, extern, typedef, etc) should be first.')
2144 if Match(
r'\s*#\s*endif\s*[^/\s]+', line):
2145 error(filename, linenum,
'build/endif_comment', 5,
2146 'Uncommented text after #endif is non-standard. Use a comment.')
2148 if Match(
r'\s*class\s+(\w+\s*::\s*)+\w+\s*;', line):
2149 error(filename, linenum,
'build/forward_decl', 5,
2150 'Inner-style forward declarations are invalid. Remove this line.')
2152 if Search(
r'(\w+|[+-]?\d+(\.\d*)?)\s*(<|>)\?=?\s*(\w+|[+-]?\d+)(\.\d*)?',
2154 error(filename, linenum,
'build/deprecated', 3,
2155 '>? and <? (max and min) operators are non-standard and deprecated.')
2157 if Search(
r'^\s*const\s*string\s*&\s*\w+\s*;', line):
2165 error(filename, linenum,
'runtime/member_string_references', 2,
2166 'const string& members are dangerous. It is much better to use ' 2167 'alternatives, such as pointers or simple constants.')
2172 classinfo = nesting_state.InnermostClass()
2173 if not classinfo
or not classinfo.seen_open_brace:
2178 base_classname = classinfo.name.split(
'::')[-1]
2182 args =
Match(
r'\s+(?:inline\s+)?%s\s*\(([^,()]+)\)' 2183 % re.escape(base_classname),
2186 args.group(1) !=
'void' and 2187 not Match(
r'(const\s+)?%s(\s+const)?\s*(?:<\w+>\s*)?&' 2188 % re.escape(base_classname), args.group(1).strip())):
2189 error(filename, linenum,
'runtime/explicit', 5,
2190 'Single-argument constructors should be marked explicit.')
2194 """Checks for the correctness of various spacing around function calls. 2197 filename: The name of the current file. 2198 line: The text of the line to check. 2199 linenum: The number of the line to check. 2200 error: The function to call with any errors found. 2208 for pattern
in (
r'\bif\s*\((.*)\)\s*{',
2209 r'\bfor\s*\((.*)\)\s*{',
2210 r'\bwhile\s*\((.*)\)\s*[{;]',
2211 r'\bswitch\s*\((.*)\)\s*{'):
2212 match =
Search(pattern, line)
2214 fncall = match.group(1)
2231 not Search(
r'\b(if|for|while|switch|return|new|delete|catch|sizeof)\b',
2234 not Search(
r' \([^)]+\)\([^)]*(\)|,$)', fncall)
and 2236 not Search(
r' \([^)]+\)\[[^\]]+\]', fncall)):
2237 if Search(
r'\w\s*\(\s(?!\s*\\$)', fncall):
2238 error(filename, linenum,
'whitespace/parens', 4,
2239 'Extra space after ( in function call')
2240 elif Search(
r'\(\s+(?!(\s*\\)|\()', fncall):
2241 error(filename, linenum,
'whitespace/parens', 2,
2242 'Extra space after (')
2243 if (
Search(
r'\w\s+\(', fncall)
and 2244 not Search(
r'#\s*define|typedef', fncall)
and 2245 not Search(
r'\w\s+\((\w+::)*\*\w+\)\(', fncall)):
2246 error(filename, linenum,
'whitespace/parens', 4,
2247 'Extra space before ( in function call')
2250 if Search(
r'[^)]\s+\)\s*[^{\s]', fncall):
2253 if Search(
r'^\s+\)', fncall):
2254 error(filename, linenum,
'whitespace/parens', 2,
2255 'Closing ) should be moved to the previous line')
2257 error(filename, linenum,
'whitespace/parens', 2,
2258 'Extra space before )')
2262 """Returns true if the given line is blank. 2264 We consider a line to be blank if the line is empty or consists of 2268 line: A line of a string. 2271 True, if the given line is blank. 2273 return not line
or line.isspace()
2277 function_state, error):
2278 """Reports for long function bodies. 2280 For an overview why this is done, see: 2281 http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Write_Short_Functions 2283 Uses a simplistic algorithm assuming other style guidelines 2284 (especially spacing) are followed. 2285 Only checks unindented functions, so class members are unchecked. 2286 Trivial bodies are unchecked, so constructors with huge initializer lists 2288 Blank/comment lines are not counted so as to avoid encouraging the removal 2289 of vertical space and comments just to get through a lint check. 2290 NOLINT *on the last line of a function* disables this check. 2293 filename: The name of the current file. 2294 clean_lines: A CleansedLines instance containing the file. 2295 linenum: The number of the line to check. 2296 function_state: Current function name and lines in body so far. 2297 error: The function to call with any errors found. 2299 lines = clean_lines.lines
2300 line = lines[linenum]
2301 raw = clean_lines.raw_lines
2302 raw_line = raw[linenum]
2305 starting_func =
False 2306 regexp =
r'(\w(\w|::|\*|\&|\s)*)\(' 2307 match_result =
Match(regexp, line)
2311 function_name = match_result.group(1).split()[-1]
2312 if function_name ==
'TEST' or function_name ==
'TEST_F' or (
2313 not Match(
r'[A-Z_]+$', function_name)):
2314 starting_func =
True 2318 for start_linenum
in xrange(linenum, clean_lines.NumLines()):
2319 start_line = lines[start_linenum]
2320 joined_line +=
' ' + start_line.lstrip()
2321 if Search(
r'(;|})', start_line):
2324 elif Search(
r'{', start_line):
2326 function =
Search(
r'((\w|:)*)\(', line).group(1)
2327 if Match(
r'TEST', function):
2328 parameter_regexp =
Search(
r'(\(.*\))', joined_line)
2329 if parameter_regexp:
2330 function += parameter_regexp.group(1)
2333 function_state.Begin(function)
2337 error(filename, linenum,
'readability/fn_size', 5,
2338 'Lint failed to find start of function body.')
2339 elif Match(
r'^\}\s*$', line):
2340 function_state.Check(error, filename, linenum)
2341 function_state.End()
2342 elif not Match(
r'^\s*$', line):
2343 function_state.Count()
2346 _RE_PATTERN_TODO = re.compile(
r'^//(\s*)TODO(\(.+?\))?:?(\s|$)?')
2350 """Checks for common mistakes in TODO comments. 2353 comment: The text of the comment from the line in question. 2354 filename: The name of the current file. 2355 linenum: The number of the line to check. 2356 error: The function to call with any errors found. 2358 match = _RE_PATTERN_TODO.match(comment)
2361 leading_whitespace = match.group(1)
2362 if len(leading_whitespace) > 1:
2363 error(filename, linenum,
'whitespace/todo', 2,
2364 'Too many spaces before TODO')
2366 username = match.group(2)
2368 error(filename, linenum,
'readability/todo', 2,
2369 'Missing username in TODO; it should look like ' 2370 '"// TODO(my_username): Stuff."')
2372 middle_whitespace = match.group(3)
2374 if middle_whitespace !=
' ' and middle_whitespace !=
'':
2375 error(filename, linenum,
'whitespace/todo', 2,
2376 'TODO(my_username) should be followed by a space')
2378 def CheckAccess(filename, clean_lines, linenum, nesting_state, error):
2379 """Checks for improper use of DISALLOW* macros. 2382 filename: The name of the current file. 2383 clean_lines: A CleansedLines instance containing the file. 2384 linenum: The number of the line to check. 2385 nesting_state: A _NestingState instance which maintains information about 2386 the current stack of nested blocks being parsed. 2387 error: The function to call with any errors found. 2389 line = clean_lines.elided[linenum]
2391 matched =
Match((
r'\s*(DISALLOW_COPY_AND_ASSIGN|' 2392 r'DISALLOW_EVIL_CONSTRUCTORS|' 2393 r'DISALLOW_IMPLICIT_CONSTRUCTORS)'), line)
2396 if nesting_state.stack
and isinstance(nesting_state.stack[-1], _ClassInfo):
2397 if nesting_state.stack[-1].access !=
'private':
2398 error(filename, linenum,
'readability/constructors', 3,
2399 '%s must be in the private: section' % matched.group(1))
2410 """Find the corresponding > to close a template. 2413 clean_lines: A CleansedLines instance containing the file. 2414 linenum: Current line number. 2415 init_suffix: Remainder of the current line after the initial <. 2418 True if a matching bracket exists. 2421 nesting_stack = [
'<']
2431 match =
Search(
r'^[^<>(),;\[\]]*([<>(),;\[\]])(.*)$', line)
2434 operator = match.group(1)
2435 line = match.group(2)
2437 if nesting_stack[-1] ==
'<':
2439 if operator
in (
'<',
'(',
'['):
2440 nesting_stack.append(operator)
2441 elif operator ==
'>':
2443 if not nesting_stack:
2446 elif operator ==
',':
2458 if operator
in (
'<',
'(',
'['):
2459 nesting_stack.append(operator)
2460 elif operator
in (
')',
']'):
2468 if linenum >= len(clean_lines.elided):
2470 line = clean_lines.elided[linenum]
2479 """Find the corresponding < that started a template. 2482 clean_lines: A CleansedLines instance containing the file. 2483 linenum: Current line number. 2484 init_prefix: Part of the current line before the initial >. 2487 True if a matching bracket exists. 2490 nesting_stack = [
'>']
2493 match =
Search(
r'^(.*)([<>(),;\[\]])[^<>(),;\[\]]*$', line)
2496 operator = match.group(2)
2497 line = match.group(1)
2499 if nesting_stack[-1] ==
'>':
2501 if operator
in (
'>',
')',
']'):
2502 nesting_stack.append(operator)
2503 elif operator ==
'<':
2505 if not nesting_stack:
2508 elif operator ==
',':
2519 if operator
in (
'>',
')',
']'):
2520 nesting_stack.append(operator)
2521 elif operator
in (
'(',
'['):
2529 line = clean_lines.elided[linenum]
2536 """Checks for the correctness of various spacing issues in the code. 2538 Things we check for: spaces around operators, spaces after 2539 if/for/while/switch, no spaces around parens in function calls, two 2540 spaces between code and comment, don't start a block with a blank 2541 line, don't end a function with a blank line, don't add a blank line 2542 after public/protected/private, don't have too many blank lines in a row. 2545 filename: The name of the current file. 2546 clean_lines: A CleansedLines instance containing the file. 2547 linenum: The number of the line to check. 2548 nesting_state: A _NestingState instance which maintains information about 2549 the current stack of nested blocks being parsed. 2550 error: The function to call with any errors found. 2556 raw = clean_lines.lines_without_raw_strings
2571 if IsBlankLine(line)
and not nesting_state.InNamespaceBody():
2572 elided = clean_lines.elided
2573 prev_line = elided[linenum - 1]
2574 prevbrace = prev_line.rfind(
'{')
2579 if prevbrace != -1
and prev_line[prevbrace:].find(
'}') == -1:
2588 if Match(
r' {6}\w', prev_line):
2591 search_position = linenum-2
2592 while (search_position >= 0
2593 and Match(
r' {6}\w', elided[search_position])):
2594 search_position -= 1
2595 exception = (search_position >= 0
2596 and elided[search_position][:5] ==
' :')
2604 exception = (
Match(
r' {4}\w[^\(]*\)\s*(const\s*)?(\{\s*$|:)',
2606 or Match(
r' {4}:', prev_line))
2609 error(filename, linenum,
'whitespace/blank_line', 2,
2610 'Redundant blank line at the start of a code block ' 2611 'should be deleted.')
2620 if linenum + 1 < clean_lines.NumLines():
2621 next_line = raw[linenum + 1]
2623 and Match(
r'\s*}', next_line)
2624 and next_line.find(
'} else ') == -1):
2625 error(filename, linenum,
'whitespace/blank_line', 3,
2626 'Redundant blank line at the end of a code block ' 2627 'should be deleted.')
2629 matched =
Match(
r'\s*(public|protected|private):', prev_line)
2631 error(filename, linenum,
'whitespace/blank_line', 3,
2632 'Do not leave a blank line after "%s:"' % matched.group(1))
2635 commentpos = line.find(
'//')
2636 if commentpos != -1:
2639 if (line.count(
'"', 0, commentpos) -
2640 line.count(
'\\"', 0, commentpos)) % 2 == 0:
2642 if (
not Match(
r'^\s*{ //', line)
and 2643 ((commentpos >= 1
and 2644 line[commentpos-1]
not in string.whitespace)
or 2645 (commentpos >= 2
and 2646 line[commentpos-2]
not in string.whitespace))):
2647 error(filename, linenum,
'whitespace/comments', 2,
2648 'At least two spaces is best between code and comments')
2650 commentend = commentpos + 2
2651 if commentend < len(line)
and not line[commentend] ==
' ':
2662 match = (
Search(
r'[=/-]{4,}\s*$', line[commentend:])
or 2663 Search(
r'^/$', line[commentend:])
or 2664 Search(
r'^!< ', line[commentend:])
or 2665 Search(
r'^/< ', line[commentend:])
or 2666 Search(
r'^/+ ', line[commentend:]))
2668 error(filename, linenum,
'whitespace/comments', 4,
2669 'Should have a space between // and comment')
2670 CheckComment(line[commentpos:], filename, linenum, error)
2672 line = clean_lines.elided[linenum]
2675 line = re.sub(
r'operator(==|!=|<|<<|<=|>=|>>|>)\(',
'operator\(', line)
2681 if Search(
r'[\w.]=[\w.]', line)
and not Search(
r'\b(if|while) ', line):
2682 error(filename, linenum,
'whitespace/operators', 4,
2683 'Missing spaces around =')
2693 match =
Search(
r'[^<>=!\s](==|!=|<=|>=)[^<>=!\s]', line)
2695 error(filename, linenum,
'whitespace/operators', 3,
2696 'Missing spaces around %s' % match.group(1))
2700 match =
Search(
r'(operator|\S)(?:L|UL|ULL|l|ul|ull)?<<(\S)', line)
2702 not (match.group(1).isdigit()
and match.group(2).isdigit())
and 2703 not (match.group(1) ==
'operator' and match.group(2) ==
';')):
2704 error(filename, linenum,
'whitespace/operators', 3,
2705 'Missing spaces around <<')
2706 elif not Match(
r'#.*include', line):
2708 reduced_line = line.replace(
'->',
'')
2714 match =
Search(
r'[^\s<]<([^\s=<].*)', reduced_line)
2717 error(filename, linenum,
'whitespace/operators', 3,
2718 'Missing spaces around <')
2723 match =
Search(
r'^(.*[^\s>])>[^\s=>]', reduced_line)
2727 error(filename, linenum,
'whitespace/operators', 3,
2728 'Missing spaces around >')
2742 match =
Search(
r'>>[a-zA-Z_]', line)
2744 error(filename, linenum,
'whitespace/operators', 3,
2745 'Missing spaces around >>')
2748 match =
Search(
r'(!\s|~\s|[\s]--[\s;]|[\s]\+\+[\s;])', line)
2750 error(filename, linenum,
'whitespace/operators', 4,
2751 'Extra space for operator %s' % match.group(1))
2754 match =
Search(
r' (if\(|for\(|while\(|switch\()', line)
2756 error(filename, linenum,
'whitespace/parens', 5,
2757 'Missing space before ( in %s' % match.group(1))
2764 match =
Search(
r'\b(if|for|while|switch)\s*' 2765 r'\(([ ]*)(.).*[^ ]+([ ]*)\)\s*{\s*$',
2768 if len(match.group(2)) != len(match.group(4)):
2769 if not (match.group(3) ==
';' and 2770 len(match.group(2)) == 1 + len(match.group(4))
or 2771 not match.group(2)
and Search(
r'\bfor\s*\(.*; \)', line)):
2772 error(filename, linenum,
'whitespace/parens', 5,
2773 'Mismatching spaces inside () in %s' % match.group(1))
2774 if len(match.group(2))
not in [0, 1]:
2775 error(filename, linenum,
'whitespace/parens', 5,
2776 'Should have zero or one spaces inside ( and ) in %s' %
2789 if Search(
r',[^,\s]', line)
and Search(
r',[^,\s]', raw[linenum]):
2790 error(filename, linenum,
'whitespace/comma', 3,
2791 'Missing space after ,')
2797 if Search(
r';[^\s};\\)/]', line):
2798 error(filename, linenum,
'whitespace/semicolon', 3,
2799 'Missing space after ;')
2808 match =
Match(
r'^(.*[^ ({]){', line)
2837 clean_lines, linenum, len(match.group(1)))
2840 trailing_text = endline[endpos:]
2841 for offset
in xrange(endlinenum + 1,
2842 min(endlinenum + 3, clean_lines.NumLines() - 1)):
2843 trailing_text += clean_lines.elided[offset]
2844 if not Match(
r'^[\s}]*[{.;,)<\]]', trailing_text):
2845 error(filename, linenum,
'whitespace/braces', 5,
2846 'Missing space before {')
2849 if Search(
r'}else', line):
2850 error(filename, linenum,
'whitespace/braces', 5,
2851 'Missing space before else')
2855 if Search(
r'\w\s+\[', line)
and not Search(
r'delete\s+\[', line):
2856 error(filename, linenum,
'whitespace/braces', 5,
2857 'Extra space before [')
2862 if Search(
r':\s*;\s*$', line):
2863 error(filename, linenum,
'whitespace/semicolon', 5,
2864 'Semicolon defining empty statement. Use {} instead.')
2865 elif Search(
r'^\s*;\s*$', line):
2866 error(filename, linenum,
'whitespace/semicolon', 5,
2867 'Line contains only semicolon. If this should be an empty statement, ' 2869 elif (
Search(
r'\s+;\s*$', line)
and 2870 not Search(
r'\bfor\b', line)):
2871 error(filename, linenum,
'whitespace/semicolon', 5,
2872 'Extra space before last semicolon. If this should be an empty ' 2873 'statement, use {} instead.')
2877 if (
Search(
'for *\(.*[^:]:[^: ]', line)
or 2878 Search(
'for *\(.*[^: ]:[^:]', line)):
2879 error(filename, linenum,
'whitespace/forcolon', 2,
2880 'Missing space around colon in range-based for loop')
2884 """Checks for additional blank line issues related to sections. 2886 Currently the only thing checked here is blank line before protected/private. 2889 filename: The name of the current file. 2890 clean_lines: A CleansedLines instance containing the file. 2891 class_info: A _ClassInfo objects. 2892 linenum: The number of the line to check. 2893 error: The function to call with any errors found. 2906 if (class_info.last_line - class_info.starting_linenum <= 24
or 2907 linenum <= class_info.starting_linenum):
2910 matched =
Match(
r'\s*(public|protected|private):', clean_lines.lines[linenum])
2920 prev_line = clean_lines.lines[linenum - 1]
2922 not Search(
r'\b(class|struct)\b', prev_line)
and 2923 not Search(
r'\\$', prev_line)):
2928 end_class_head = class_info.starting_linenum
2929 for i
in range(class_info.starting_linenum, linenum):
2930 if Search(
r'\{\s*$', clean_lines.lines[i]):
2933 if end_class_head < linenum - 1:
2934 error(filename, linenum,
'whitespace/blank_line', 3,
2935 '"%s:" should be preceded by a blank line' % matched.group(1))
2939 """Return the most recent non-blank line and its line number. 2942 clean_lines: A CleansedLines instance containing the file contents. 2943 linenum: The number of the line to check. 2946 A tuple with two elements. The first element is the contents of the last 2947 non-blank line before the current line, or the empty string if this is the 2948 first non-blank line. The second is the line number of that line, or -1 2949 if this is the first non-blank line. 2952 prevlinenum = linenum - 1
2953 while prevlinenum >= 0:
2954 prevline = clean_lines.elided[prevlinenum]
2956 return (prevline, prevlinenum)
2962 """Looks for misplaced braces (e.g. at the end of line). 2965 filename: The name of the current file. 2966 clean_lines: A CleansedLines instance containing the file. 2967 linenum: The number of the line to check. 2968 error: The function to call with any errors found. 2971 line = clean_lines.elided[linenum]
2973 if Match(
r'\s*{\s*$', line):
2982 if (
not Search(
r'[,;:}{(]\s*$', prevline)
and 2983 not Match(
r'\s*#', prevline)):
2984 error(filename, linenum,
'whitespace/braces', 4,
2985 '{ should almost always be at the end of the previous line')
2988 if Match(
r'\s*else\s*', line):
2990 if Match(
r'\s*}\s*$', prevline):
2991 error(filename, linenum,
'whitespace/newline', 4,
2992 'An else should appear on the same line as the preceding }')
2996 if Search(
r'}\s*else[^{]*$', line)
or Match(
r'[^}]*else\s*{', line):
2997 if Search(
r'}\s*else if([^{]*)$', line):
2999 pos = line.find(
'else if')
3000 pos = line.find(
'(', pos)
3003 if endline[endpos:].find(
'{') == -1:
3004 error(filename, linenum,
'readability/braces', 5,
3005 'If an else has a brace on one side, it should have it on both')
3007 error(filename, linenum,
'readability/braces', 5,
3008 'If an else has a brace on one side, it should have it on both')
3011 if Search(
r'\belse [^\s{]', line)
and not Search(
r'\belse if\b', line):
3012 error(filename, linenum,
'whitespace/newline', 4,
3013 'Else clause should never be on same line as else (use 2 lines)')
3016 if Match(
r'\s*do [^\s{]', line):
3017 error(filename, linenum,
'whitespace/newline', 4,
3018 'do/while clauses should not be on a single line')
3064 match =
Match(
r'^(.*\)\s*)\{', line)
3089 closing_brace_pos = match.group(1).rfind(
')')
3091 clean_lines, linenum, closing_brace_pos)
3092 if opening_parenthesis[2] > -1:
3093 line_prefix = opening_parenthesis[0][0:opening_parenthesis[2]]
3094 macro =
Search(
r'\b([A-Z_]+)\s*$', line_prefix)
3096 macro.group(1)
not in (
3097 'TEST',
'TEST_F',
'MATCHER',
'MATCHER_P',
'TYPED_TEST',
3098 'EXCLUSIVE_LOCKS_REQUIRED',
'SHARED_LOCKS_REQUIRED',
3099 'LOCKS_EXCLUDED',
'INTERFACE_DEF'))
or 3100 Search(
r'\s+=\s*$', line_prefix)):
3105 match =
Match(
r'^(.*(?:else|\)\s*const)\s*)\{', line)
3116 if prevline
and Search(
r'[;{}]\s*$', prevline):
3117 match =
Match(
r'^(\s*)\{', line)
3122 clean_lines, linenum, len(match.group(1)))
3123 if endpos > -1
and Match(
r'^\s*;', endline[endpos:]):
3131 error(filename, endlinenum,
'readability/braces', 4,
3132 "You don't need a ; after a }")
3136 """Look for empty loop/conditional body with only a single semicolon. 3139 filename: The name of the current file. 3140 clean_lines: A CleansedLines instance containing the file. 3141 linenum: The number of the line to check. 3142 error: The function to call with any errors found. 3151 line = clean_lines.elided[linenum]
3152 matched =
Match(
r'\s*(for|while|if)\s*\(', line)
3156 clean_lines, linenum, line.find(
'('))
3161 if end_pos >= 0
and Match(
r';', end_line[end_pos:]):
3162 if matched.group(1) ==
'if':
3163 error(filename, end_linenum,
'whitespace/empty_conditional_body', 5,
3164 'Empty conditional bodies should use {}')
3166 error(filename, end_linenum,
'whitespace/empty_loop_body', 5,
3167 'Empty loop bodies should use {} or continue')
3171 """Checks the use of CHECK and EXPECT macros. 3174 filename: The name of the current file. 3175 clean_lines: A CleansedLines instance containing the file. 3176 linenum: The number of the line to check. 3177 error: The function to call with any errors found. 3181 lines = clean_lines.elided
3184 for macro
in _CHECK_MACROS:
3185 i = lines[linenum].find(macro)
3193 matched =
Match(
r'^(.*\b' + check_macro +
r'\s*)\(', lines[linenum])
3196 start_pos = len(matched.group(1))
3198 if not check_macro
or start_pos < 0:
3204 clean_lines, linenum, start_pos)
3207 if linenum == end_line:
3208 expression = lines[linenum][start_pos + 1:end_pos - 1]
3210 expression = lines[linenum][start_pos + 1:]
3211 for i
in xrange(linenum + 1, end_line):
3212 expression += lines[i]
3213 expression += last_line[0:end_pos - 1]
3222 matched =
Match(
r'^\s*(<<|<<=|>>|>>=|->\*|->|&&|\|\||' 3223 r'==|!=|>=|>|<=|<|\()(.*)$', expression)
3225 token = matched.group(1)
3228 expression = matched.group(2)
3232 lhs +=
'(' + expression[0:end]
3233 expression = expression[end:]
3234 elif token
in (
'&&',
'||'):
3241 elif token
in (
'<<',
'<<=',
'>>',
'>>=',
'->*',
'->'):
3244 expression = matched.group(2)
3248 rhs = matched.group(2)
3256 matched =
Match(
r'^([^-=!<>()&|]+)(.*)$', expression)
3258 matched =
Match(
r'^(\s*\S)(.*)$', expression)
3261 lhs += matched.group(1)
3262 expression = matched.group(2)
3265 if not (lhs
and operator
and rhs):
3270 if rhs.find(
'&&') > -1
or rhs.find(
'||') > -1:
3281 match_constant =
r'^([-+]?(\d+|0[xX][0-9a-fA-F]+)[lLuU]{0,3}|".*"|\'.*\')$' 3282 if Match(match_constant, lhs)
or Match(match_constant, rhs):
3291 error(filename, linenum,
'readability/check', 2,
3292 'Consider using %s instead of %s(a %s b)' % (
3293 _CHECK_REPLACEMENT[check_macro][operator],
3294 check_macro, operator))
3298 """Check alternative keywords being used in boolean expressions. 3301 filename: The name of the current file. 3302 clean_lines: A CleansedLines instance containing the file. 3303 linenum: The number of the line to check. 3304 error: The function to call with any errors found. 3306 line = clean_lines.elided[linenum]
3309 if Match(
r'^\s*#', line):
3320 if line.find(
'/*') >= 0
or line.find(
'*/') >= 0:
3323 for match
in _ALT_TOKEN_REPLACEMENT_PATTERN.finditer(line):
3324 error(filename, linenum,
'readability/alt_tokens', 2,
3325 'Use operator %s instead of %s' % (
3326 _ALT_TOKEN_REPLACEMENT[match.group(1)], match.group(1)))
3330 """Determines the width of the line in column positions. 3333 line: A string, which may be a Unicode string. 3336 The width of the line in column positions, accounting for Unicode 3337 combining characters and wide characters. 3339 if isinstance(line, unicode):
3341 for uc
in unicodedata.normalize(
'NFC', line):
3342 if unicodedata.east_asian_width(uc)
in (
'W',
'F'):
3344 elif not unicodedata.combining(uc):
3351 def CheckStyle(filename, clean_lines, linenum, file_extension, nesting_state,
3353 """Checks rules from the 'C++ style rules' section of cppguide.html. 3355 Most of these rules are hard to test (naming, comment style), but we 3356 do what we can. In particular we check for 2-space indents, line lengths, 3357 tab usage, spaces inside code, etc. 3360 filename: The name of the current file. 3361 clean_lines: A CleansedLines instance containing the file. 3362 linenum: The number of the line to check. 3363 file_extension: The extension (without the dot) of the filename. 3364 nesting_state: A _NestingState instance which maintains information about 3365 the current stack of nested blocks being parsed. 3366 error: The function to call with any errors found. 3372 raw_lines = clean_lines.lines_without_raw_strings
3373 line = raw_lines[linenum]
3375 if line.find(
'\t') != -1:
3376 error(filename, linenum,
'whitespace/tab', 1,
3377 'Tab found; better to use spaces')
3392 cleansed_line = clean_lines.elided[linenum]
3393 while initial_spaces < len(line)
and line[initial_spaces] ==
' ':
3395 if line
and line[-1].isspace():
3396 error(filename, linenum,
'whitespace/end_of_line', 4,
3397 'Line ends in whitespace. Consider deleting these extra spaces.')
3399 elif ((initial_spaces == 1
or initial_spaces == 3)
and 3400 not Match(
r'\s*\w+\s*:\s*$', cleansed_line)):
3401 error(filename, linenum,
'whitespace/indent', 3,
3402 'Weird number of spaces at line-start. ' 3403 'Are you using a 2-space indent?')
3406 is_header_guard =
False 3407 if file_extension ==
'h':
3409 if (line.startswith(
'#ifndef %s' % cppvar)
or 3410 line.startswith(
'#define %s' % cppvar)
or 3411 line.startswith(
'#endif // %s' % cppvar)):
3412 is_header_guard =
True 3421 if (
not line.startswith(
'#include')
and not is_header_guard
and 3422 not Match(
r'^\s*//.*http(s?)://\S*$', line)
and 3423 not Match(
r'^// \$Id:.*#[0-9]+ \$$', line)):
3425 extended_length = int((_line_length * 1.25))
3426 if line_width > extended_length:
3427 error(filename, linenum,
'whitespace/line_length', 4,
3428 'Lines should very rarely be longer than %i characters' %
3430 elif line_width > _line_length:
3431 error(filename, linenum,
'whitespace/line_length', 2,
3432 'Lines should be <= %i characters long' % _line_length)
3434 if (cleansed_line.count(
';') > 1
and 3436 cleansed_line.find(
'for') == -1
and 3440 not ((cleansed_line.find(
'case ') != -1
or 3441 cleansed_line.find(
'default:') != -1)
and 3442 cleansed_line.find(
'break;') != -1)):
3443 error(filename, linenum,
'whitespace/newline', 0,
3444 'More than one command on the same line')
3447 CheckBraces(filename, clean_lines, linenum, error)
3449 CheckAccess(filename, clean_lines, linenum, nesting_state, error)
3450 CheckSpacing(filename, clean_lines, linenum, nesting_state, error)
3451 CheckCheck(filename, clean_lines, linenum, error)
3453 classinfo = nesting_state.InnermostClass()
3458 _RE_PATTERN_INCLUDE_NEW_STYLE = re.compile(
r'#include +"[^/]+\.h"')
3459 _RE_PATTERN_INCLUDE = re.compile(
r'^\s*#\s*include\s*([<"])([^>"]*)[>"].*$')
3465 _RE_FIRST_COMPONENT = re.compile(
r'^[^-_.]+')
3469 """Drops common suffixes like _test.cc or -inl.h from filename. 3472 >>> _DropCommonSuffixes('foo/foo-inl.h') 3474 >>> _DropCommonSuffixes('foo/bar/foo.cc') 3476 >>> _DropCommonSuffixes('foo/foo_internal.h') 3478 >>> _DropCommonSuffixes('foo/foo_unusualinternal.h') 3479 'foo/foo_unusualinternal' 3482 filename: The input filename. 3485 The filename with the common suffix removed. 3487 for suffix
in (
'test.cc',
'regtest.cc',
'unittest.cc',
3488 'inl.h',
'impl.h',
'internal.h'):
3489 if (filename.endswith(suffix)
and len(filename) > len(suffix)
and 3490 filename[-len(suffix) - 1]
in (
'-',
'_')):
3491 return filename[:-len(suffix) - 1]
3492 return os.path.splitext(filename)[0]
3496 """Determines if the given filename has a suffix that identifies it as a test. 3499 filename: The input filename. 3502 True if 'filename' looks like a test, False otherwise. 3504 if (filename.endswith(
'_test.cc')
or 3505 filename.endswith(
'_unittest.cc')
or 3506 filename.endswith(
'_regtest.cc')):
3513 """Figures out what kind of header 'include' is. 3516 fileinfo: The current file cpplint is running over. A FileInfo instance. 3517 include: The path to a #included file. 3518 is_system: True if the #include used <> rather than "". 3521 One of the _XXX_HEADER constants. 3524 >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'stdio.h', True) 3526 >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'string', True) 3528 >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'foo/foo.h', False) 3530 >>> _ClassifyInclude(FileInfo('foo/foo_unknown_extension.cc'), 3531 ... 'bar/foo_other_ext.h', False) 3533 >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'foo/bar.h', False) 3538 is_cpp_h = include
in _CPP_HEADERS
3542 return _CPP_SYS_HEADER
3544 return _C_SYS_HEADER
3549 target_dir, target_base = (
3552 if target_base == include_base
and (
3553 include_dir == target_dir
or 3554 include_dir == os.path.normpath(target_dir +
'/../public')):
3555 return _LIKELY_MY_HEADER
3561 target_first_component = _RE_FIRST_COMPONENT.match(target_base)
3562 include_first_component = _RE_FIRST_COMPONENT.match(include_base)
3563 if (target_first_component
and include_first_component
and 3564 target_first_component.group(0) ==
3565 include_first_component.group(0)):
3566 return _POSSIBLE_MY_HEADER
3568 return _OTHER_HEADER
3573 """Check rules that are applicable to #include lines. 3575 Strings on #include lines are NOT removed from elided line, to make 3576 certain tasks easier. However, to prevent false positives, checks 3577 applicable to #include lines in CheckLanguage must be put here. 3580 filename: The name of the current file. 3581 clean_lines: A CleansedLines instance containing the file. 3582 linenum: The number of the line to check. 3583 include_state: An _IncludeState instance in which the headers are inserted. 3584 error: The function to call with any errors found. 3588 line = clean_lines.lines[linenum]
3591 if _RE_PATTERN_INCLUDE_NEW_STYLE.search(line):
3592 error(filename, linenum,
'build/include', 4,
3593 'Include the directory when naming .h files')
3598 match = _RE_PATTERN_INCLUDE.search(line)
3600 include = match.group(2)
3601 is_system = (match.group(1) ==
'<')
3602 if include
in include_state:
3603 error(filename, linenum,
'build/include', 4,
3604 '"%s" already included at %s:%s' %
3605 (include, filename, include_state[include]))
3607 include_state[include] = linenum
3620 error_message = include_state.CheckNextIncludeOrder(
3623 error(filename, linenum,
'build/include_order', 4,
3624 '%s. Should be: %s.h, c system, c++ system, other.' %
3625 (error_message, fileinfo.BaseName()))
3626 canonical_include = include_state.CanonicalizeAlphabeticalOrder(include)
3627 if not include_state.IsInAlphabeticalOrder(
3628 clean_lines, linenum, canonical_include):
3629 error(filename, linenum,
'build/include_alpha', 4,
3630 'Include "%s" not in alphabetical order' % include)
3631 include_state.SetLastHeader(canonical_include)
3634 match = _RE_PATTERN_INCLUDE.match(line)
3636 include = match.group(2)
3637 if Match(
r'(f|ind|io|i|o|parse|pf|stdio|str|)?stream$', include):
3640 error(filename, linenum,
'readability/streams', 3,
3641 'Streams are highly discouraged.')
3645 r"""Retrieves all the text between matching open and close parentheses. 3647 Given a string of lines and a regular expression string, retrieve all the text 3648 following the expression and between opening punctuation symbols like 3649 (, [, or {, and the matching close-punctuation symbol. This properly nested 3650 occurrences of the punctuations, so for the text like 3651 printf(a(), b(c())); 3652 a call to _GetTextInside(text, r'printf\(') will return 'a(), b(c())'. 3653 start_pattern must match string having an open punctuation symbol at the end. 3656 text: The lines to extract text. Its comments and strings must be elided. 3657 It can be single line and can span multiple lines. 3658 start_pattern: The regexp string indicating where to start extracting 3662 None if either the opening string or ending punctuation could not be found. 3668 matching_punctuation = {
'(':
')',
'{':
'}',
'[':
']'}
3669 closing_punctuation = set(matching_punctuation.itervalues())
3672 match = re.search(start_pattern, text, re.M)
3675 start_position = match.end(0)
3677 assert start_position > 0, (
3678 'start_pattern must ends with an opening punctuation.')
3679 assert text[start_position - 1]
in matching_punctuation, (
3680 'start_pattern must ends with an opening punctuation.')
3682 punctuation_stack = [matching_punctuation[text[start_position - 1]]]
3683 position = start_position
3684 while punctuation_stack
and position < len(text):
3685 if text[position] == punctuation_stack[-1]:
3686 punctuation_stack.pop()
3687 elif text[position]
in closing_punctuation:
3690 elif text[position]
in matching_punctuation:
3691 punctuation_stack.append(matching_punctuation[text[position]])
3693 if punctuation_stack:
3697 return text[start_position:position - 1]
3709 _RE_PATTERN_IDENT =
r'[_a-zA-Z]\w*' 3710 _RE_PATTERN_TYPE = (
3711 r'(?:const\s+)?(?:typename\s+|class\s+|struct\s+|union\s+|enum\s+)?' 3713 r'\s*<(?:<(?:<[^<>]*>|[^<>])*>|[^<>])*>|' 3716 _RE_PATTERN_REF_PARAM = re.compile(
3717 r'(' + _RE_PATTERN_TYPE +
r'(?:\s*(?:\bconst\b|[*]))*\s*' 3718 r'&\s*' + _RE_PATTERN_IDENT +
r')\s*(?:=[^,()]+)?[,)]')
3721 _RE_PATTERN_CONST_REF_PARAM = (
3722 r'(?:.*\s*\bconst\s*&\s*' + _RE_PATTERN_IDENT +
3723 r'|const\s+' + _RE_PATTERN_TYPE +
r'\s*&\s*' + _RE_PATTERN_IDENT +
r')')
3726 def CheckLanguage(filename, clean_lines, linenum, file_extension,
3727 include_state, nesting_state, error):
3728 """Checks rules from the 'C++ language rules' section of cppguide.html. 3730 Some of these rules are hard to test (function overloading, using 3731 uint32 inappropriately), but we do the best we can. 3734 filename: The name of the current file. 3735 clean_lines: A CleansedLines instance containing the file. 3736 linenum: The number of the line to check. 3737 file_extension: The extension (without the dot) of the filename. 3738 include_state: An _IncludeState instance in which the headers are inserted. 3739 nesting_state: A _NestingState instance which maintains information about 3740 the current stack of nested blocks being parsed. 3741 error: The function to call with any errors found. 3745 line = clean_lines.elided[linenum]
3749 match = _RE_PATTERN_INCLUDE.search(line)
3756 if Match(
r'^\s*#\s*(?:ifdef|elif|else|endif)\b', line):
3757 include_state.ResetSection()
3760 fullname = os.path.abspath(filename).replace(
'\\',
'/')
3770 r'(int|float|double|bool|char|int32|uint32|int64|uint64)' 3771 r'(\([^)].*)', line)
3773 matched_new = match.group(1)
3774 matched_type = match.group(2)
3775 matched_funcptr = match.group(3)
3787 if (matched_new
is None and 3788 not (
Match(
r'^\s*MOCK_(CONST_)?METHOD\d+(_T)?\(', line)
or 3789 Search(
r'\bMockCallback<.*>', line)
or 3790 Search(
r'\bstd::function<.*>', line))
and 3791 not (matched_funcptr
and 3792 Match(
r'\((?:[^() ]+::\s*\*\s*)?[^() ]+\)\s*\(',
3804 not (
Match(
r'^\s*MOCK_(?:CONST_)?METHOD\d+(?:_T)?\((?:\S+,)?\s*$',
3805 clean_lines.elided[linenum - 1])
or 3806 Match(
r'^\s*MOCK_(?:CONST_)?METHOD\d+(?:_T)?\(\s*$',
3807 clean_lines.elided[linenum - 2]))):
3808 error(filename, linenum,
'readability/casting', 4,
3809 'Using deprecated casting style. ' 3810 'Use static_cast<%s>(...) instead' %
3813 CheckCStyleCast(filename, linenum, line, clean_lines.raw_lines[linenum],
3815 r'\((int|float|double|bool|char|u?int(16|32|64))\)', error)
3821 if CheckCStyleCast(filename, linenum, line, clean_lines.raw_lines[linenum],
3822 'const_cast',
r'\((char\s?\*+\s?)\)\s*"', error):
3826 CheckCStyleCast(filename, linenum, line, clean_lines.raw_lines[linenum],
3827 'reinterpret_cast',
r'\((\w+\s?\*+\s?)\)', error)
3833 r'(?:&\(([^)]+)\)[\w(])|' 3834 r'(?:&(static|dynamic|down|reinterpret)_cast\b)', line)
3835 if match
and match.group(1) !=
'*':
3836 error(filename, linenum,
'runtime/casting', 4,
3837 (
'Are you taking an address of a cast? ' 3838 'This is dangerous: could be a temp var. ' 3839 'Take the address before doing the cast, rather than after'))
3844 if linenum + 1 < clean_lines.NumLines():
3845 extended_line = line + clean_lines.elided[linenum + 1]
3847 extended_line = line
3853 r'((?:|static +)(?:|const +))string +([a-zA-Z0-9_:]+)\b(.*)',
3863 not Search(
r'\boperator\W', line)
and 3864 not Match(
r'\s*(<.*>)?(::[a-zA-Z0-9_]+)?\s*\(([^"]|$)', match.group(3))):
3865 error(filename, linenum,
'runtime/string', 4,
3866 'For a static/global string constant, use a C style string instead: ' 3868 (match.group(1), match.group(2)))
3870 if Search(
r'\b([A-Za-z0-9_]*_)\(\1\)', line):
3871 error(filename, linenum,
'runtime/init', 4,
3872 'You seem to be initializing a member variable with itself.')
3874 if file_extension ==
'h':
3884 if Search(
r'\bshort port\b', line):
3885 if not Search(
r'\bunsigned short port\b', line):
3886 error(filename, linenum,
'runtime/int', 4,
3887 'Use "unsigned short" for ports, not "short"')
3889 match =
Search(
r'\b(short|long(?! +double)|long long)\b', line)
3891 error(filename, linenum,
'runtime/int', 4,
3892 'Use int16/int64/etc, rather than the C type %s' % match.group(1))
3895 match =
Search(
r'snprintf\s*\(([^,]*),\s*([0-9]*)\s*,', line)
3896 if match
and match.group(2) !=
'0':
3898 error(filename, linenum,
'runtime/printf', 3,
3899 'If you can, use sizeof(%s) instead of %s as the 2nd arg ' 3900 'to snprintf.' % (match.group(1), match.group(2)))
3903 if Search(
r'\bsprintf\b', line):
3904 error(filename, linenum,
'runtime/printf', 5,
3905 'Never use sprintf. Use snprintf instead.')
3906 match =
Search(
r'\b(strcpy|strcat)\b', line)
3908 error(filename, linenum,
'runtime/printf', 4,
3909 'Almost always, snprintf is better than %s' % match.group(1))
3917 if Search(
r'\boperator\s*&\s*\(\s*\)', line):
3918 error(filename, linenum,
'runtime/operator', 4,
3919 'Unary operator& is dangerous. Do not use it.')
3923 if Search(
r'\}\s*if\s*\(', line):
3924 error(filename, linenum,
'readability/braces', 4,
3925 'Did you mean "else if"? If not, start a new line for "if".')
3934 printf_args =
_GetTextInside(line,
r'(?i)\b(string)?printf\s*\(')
3936 match =
Match(
r'([\w.\->()]+)$', printf_args)
3937 if match
and match.group(1) !=
'__VA_ARGS__':
3938 function_name = re.search(
r'\b((?:string)?printf)\s*\(',
3939 line, re.I).group(1)
3940 error(filename, linenum,
'runtime/printf', 4,
3941 'Potential format string bug. Do %s("%%s", %s) instead.' 3942 % (function_name, match.group(1)))
3945 match =
Search(
r'memset\s*\(([^,]*),\s*([^,]*),\s*0\s*\)', line)
3946 if match
and not Match(
r"^''|-?[0-9]+|0x[0-9A-Fa-f]$", match.group(2)):
3947 error(filename, linenum,
'runtime/memset', 4,
3948 'Did you mean "memset(%s, 0, %s)"?' 3949 % (match.group(1), match.group(2)))
3951 if Search(
r'\busing namespace\b', line):
3952 error(filename, linenum,
'build/namespaces', 5,
3953 'Do not use namespace using-directives. ' 3954 'Use using-declarations instead.')
3957 match =
Match(
r'\s*(.+::)?(\w+) [a-z]\w*\[(.+)];', line)
3958 if (match
and match.group(2) !=
'return' and match.group(2) !=
'delete' and 3959 match.group(3).find(
']') == -1):
3963 tokens = re.split(
r'\s|\+|\-|\*|\/|<<|>>]', match.group(3))
3971 if Search(
r'sizeof\(.+\)', tok):
continue 3972 if Search(
r'arraysize\(\w+\)', tok):
continue 3974 tok = tok.lstrip(
'(')
3975 tok = tok.rstrip(
')')
3976 if not tok:
continue 3977 if Match(
r'\d+', tok):
continue 3978 if Match(
r'0[xX][0-9a-fA-F]+', tok):
continue 3979 if Match(
r'k[A-Z0-9]\w*', tok):
continue 3980 if Match(
r'(.+::)?k[A-Z0-9]\w*', tok):
continue 3981 if Match(
r'(.+::)?[A-Z][A-Z0-9_]*', tok):
continue 3985 if tok.startswith(
'sizeof'):
3991 error(filename, linenum,
'runtime/arrays', 1,
3992 'Do not use variable-length arrays. Use an appropriately named ' 3993 "('k' followed by CamelCase) compile-time constant for the size.")
4000 r'(DISALLOW_(EVIL_CONSTRUCTORS|COPY_AND_ASSIGN|IMPLICIT_CONSTRUCTORS))' 4003 if match
and linenum + 1 < clean_lines.NumLines():
4004 next_line = clean_lines.elided[linenum + 1]
4011 if not Search(
r'^\s*}[\w\*,\s]*;', next_line):
4012 error(filename, linenum,
'readability/constructors', 3,
4013 match.group(1) +
' should be the last thing in the class')
4018 if (file_extension ==
'h' 4019 and Search(
r'\bnamespace\s*{', line)
4020 and line[-1] !=
'\\'):
4021 error(filename, linenum,
'build/namespaces', 4,
4022 'Do not use unnamed namespaces in header files. See ' 4023 'http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Namespaces' 4024 ' for more information.')
4027 nesting_state, error):
4028 """Check for non-const references. 4030 Separate from CheckLanguage since it scans backwards from current 4031 line, instead of scanning forward. 4034 filename: The name of the current file. 4035 clean_lines: A CleansedLines instance containing the file. 4036 linenum: The number of the line to check. 4037 nesting_state: A _NestingState instance which maintains information about 4038 the current stack of nested blocks being parsed. 4039 error: The function to call with any errors found. 4042 line = clean_lines.elided[linenum]
4064 if Match(
r'\s*::(?:[\w<>]|::)+\s*&\s*\S', line):
4066 previous =
Search(
r'\b((?:const\s*)?(?:[\w<>]|::)+[\w<>])\s*$',
4067 clean_lines.elided[linenum - 1])
4068 elif Match(
r'\s*[a-zA-Z_]([\w<>]|::)+\s*&\s*\S', line):
4070 previous =
Search(
r'\b((?:const\s*)?(?:[\w<>]|::)+::)\s*$',
4071 clean_lines.elided[linenum - 1])
4073 line = previous.group(1) + line.lstrip()
4076 endpos = line.rfind(
'>')
4079 clean_lines, linenum, endpos)
4080 if startpos > -1
and startline < linenum:
4084 for i
in xrange(startline, linenum + 1):
4085 line += clean_lines.elided[i].strip()
4096 check_params =
False 4097 if not nesting_state.stack:
4099 elif (isinstance(nesting_state.stack[-1], _ClassInfo)
or 4100 isinstance(nesting_state.stack[-1], _NamespaceInfo)):
4102 elif Match(
r'.*{\s*$', line):
4103 if (len(nesting_state.stack) == 1
or 4104 isinstance(nesting_state.stack[-2], _ClassInfo)
or 4105 isinstance(nesting_state.stack[-2], _NamespaceInfo)):
4113 whitelisted_functions = (
r'(?:[sS]wap(?:<\w:+>)?|' 4114 r'operator\s*[<>][<>]|' 4115 r'static_assert|COMPILE_ASSERT' 4117 if Search(whitelisted_functions, line):
4118 check_params =
False 4119 elif not Search(
r'\S+\([^)]*$', line):
4125 Search(whitelisted_functions, clean_lines.elided[linenum - i - 1])):
4126 check_params =
False 4131 for parameter
in re.findall(_RE_PATTERN_REF_PARAM, decls):
4132 if not Match(_RE_PATTERN_CONST_REF_PARAM, parameter):
4133 error(filename, linenum,
'runtime/references', 2,
4134 'Is this a non-const reference? ' 4135 'If so, make const or use a pointer: ' +
4139 def CheckCStyleCast(filename, linenum, line, raw_line, cast_type, pattern,
4141 """Checks for a C-style cast by looking for the pattern. 4144 filename: The name of the current file. 4145 linenum: The number of the line to check. 4146 line: The line of code to check. 4147 raw_line: The raw line of code to check, with comments. 4148 cast_type: The string for the C++ cast to recommend. This is either 4149 reinterpret_cast, static_cast, or const_cast, depending. 4150 pattern: The regular expression used to find C-style casts. 4151 error: The function to call with any errors found. 4154 True if an error was emitted. 4157 match =
Search(pattern, line)
4162 sizeof_match =
Match(
r'.*sizeof\s*$', line[0:match.start(1) - 1])
4167 if (line[0:match.start(1) - 1].endswith(
' operator++')
or 4168 line[0:match.start(1) - 1].endswith(
' operator--')):
4194 remainder = line[match.end(0):]
4195 if Match(
r'^\s*(?:;|const\b|throw\b|=|>|\{|\))', remainder):
4199 if Match(
r'^\s*>', remainder):
4206 matched_zero =
Match(
r'^\s=\s*(\S+)\s*;', remainder)
4207 if matched_zero
and matched_zero.group(1) !=
'0':
4212 if Match(
r'.*\)\s*$', line[0:match.start(0)]):
4217 if '/*' in raw_line:
4221 error(filename, linenum,
'readability/function', 3,
4222 'All parameters should be named in a function')
4226 error(filename, linenum,
'readability/casting', 4,
4227 'Using C-style cast. Use %s<%s>(...) instead' %
4228 (cast_type, match.group(1)))
4233 _HEADERS_CONTAINING_TEMPLATES = (
4234 (
'<deque>', (
'deque',)),
4235 (
'<functional>', (
'unary_function',
'binary_function',
4236 'plus',
'minus',
'multiplies',
'divides',
'modulus',
4238 'equal_to',
'not_equal_to',
'greater',
'less',
4239 'greater_equal',
'less_equal',
4240 'logical_and',
'logical_or',
'logical_not',
4241 'unary_negate',
'not1',
'binary_negate',
'not2',
4242 'bind1st',
'bind2nd',
4243 'pointer_to_unary_function',
4244 'pointer_to_binary_function',
4246 'mem_fun_t',
'mem_fun',
'mem_fun1_t',
'mem_fun1_ref_t',
4248 'const_mem_fun_t',
'const_mem_fun1_t',
4249 'const_mem_fun_ref_t',
'const_mem_fun1_ref_t',
4252 (
'<limits>', (
'numeric_limits',)),
4253 (
'<list>', (
'list',)),
4254 (
'<map>', (
'map',
'multimap',)),
4255 (
'<memory>', (
'allocator',)),
4256 (
'<queue>', (
'queue',
'priority_queue',)),
4257 (
'<set>', (
'set',
'multiset',)),
4258 (
'<stack>', (
'stack',)),
4259 (
'<string>', (
'char_traits',
'basic_string',)),
4260 (
'<utility>', (
'pair',)),
4261 (
'<vector>', (
'vector',)),
4265 (
'<hash_map>', (
'hash_map',
'hash_multimap',)),
4266 (
'<hash_set>', (
'hash_set',
'hash_multiset',)),
4267 (
'<slist>', (
'slist',)),
4270 _RE_PATTERN_STRING = re.compile(
r'\bstring\b')
4272 _re_pattern_algorithm_header = []
4273 for _template
in (
'copy',
'max',
'min',
'min_element',
'sort',
'swap',
4277 _re_pattern_algorithm_header.append(
4278 (re.compile(
r'[^>.]\b' + _template +
r'(<.*?>)?\([^\)]'),
4282 _re_pattern_templates = []
4283 for _header, _templates
in _HEADERS_CONTAINING_TEMPLATES:
4284 for _template
in _templates:
4285 _re_pattern_templates.append(
4286 (re.compile(
r'(<|\b)' + _template +
r'\s*<'),
4292 """Check if these two filenames belong to the same module. 4294 The concept of a 'module' here is a as follows: 4295 foo.h, foo-inl.h, foo.cc, foo_test.cc and foo_unittest.cc belong to the 4296 same 'module' if they are in the same directory. 4297 some/path/public/xyzzy and some/path/internal/xyzzy are also considered 4298 to belong to the same module here. 4300 If the filename_cc contains a longer path than the filename_h, for example, 4301 '/absolute/path/to/base/sysinfo.cc', and this file would include 4302 'base/sysinfo.h', this function also produces the prefix needed to open the 4303 header. This is used by the caller of this function to more robustly open the 4304 header file. We don't have access to the real include paths in this context, 4305 so we need this guesswork here. 4307 Known bugs: tools/base/bar.cc and base/bar.h belong to the same module 4308 according to this implementation. Because of this, this function gives 4309 some false positives. This should be sufficiently rare in practice. 4312 filename_cc: is the path for the .cc file 4313 filename_h: is the path for the header path 4316 Tuple with a bool and a string: 4317 bool: True if filename_cc and filename_h belong to the same module. 4318 string: the additional prefix needed to open the header file. 4321 if not filename_cc.endswith(
'.cc'):
4323 filename_cc = filename_cc[:-len(
'.cc')]
4324 if filename_cc.endswith(
'_unittest'):
4325 filename_cc = filename_cc[:-len(
'_unittest')]
4326 elif filename_cc.endswith(
'_test'):
4327 filename_cc = filename_cc[:-len(
'_test')]
4328 filename_cc = filename_cc.replace(
'/public/',
'/')
4329 filename_cc = filename_cc.replace(
'/internal/',
'/')
4331 if not filename_h.endswith(
'.h'):
4333 filename_h = filename_h[:-len(
'.h')]
4334 if filename_h.endswith(
'-inl'):
4335 filename_h = filename_h[:-len(
'-inl')]
4336 filename_h = filename_h.replace(
'/public/',
'/')
4337 filename_h = filename_h.replace(
'/internal/',
'/')
4339 files_belong_to_same_module = filename_cc.endswith(filename_h)
4341 if files_belong_to_same_module:
4342 common_path = filename_cc[:-len(filename_h)]
4343 return files_belong_to_same_module, common_path
4347 """Fill up the include_state with new includes found from the file. 4350 filename: the name of the header to read. 4351 include_state: an _IncludeState instance in which the headers are inserted. 4352 io: The io factory to use to read the file. Provided for testability. 4355 True if a header was succesfully added. False otherwise. 4359 headerfile = io.open(filename,
'r', 'utf8', 'replace')
4363 for line
in headerfile:
4366 match = _RE_PATTERN_INCLUDE.search(clean_line)
4368 include = match.group(2)
4371 include_state.setdefault(include,
'%s:%d' % (filename, linenum))
4377 """Reports for missing stl includes. 4379 This function will output warnings to make sure you are including the headers 4380 necessary for the stl containers and functions that you use. We only give one 4381 reason to include a header. For example, if you use both equal_to<> and 4382 less<> in a .h file, only one (the latter in the file) of these will be 4383 reported as a reason to include the <functional>. 4386 filename: The name of the current file. 4387 clean_lines: A CleansedLines instance containing the file. 4388 include_state: An _IncludeState instance. 4389 error: The function to call with any errors found. 4390 io: The IO factory to use to read the header file. Provided for unittest 4396 for linenum
in xrange(clean_lines.NumLines()):
4397 line = clean_lines.elided[linenum]
4398 if not line
or line[0] ==
'#':
4402 matched = _RE_PATTERN_STRING.search(line)
4406 prefix = line[:matched.start()]
4407 if prefix.endswith(
'std::')
or not prefix.endswith(
'::'):
4408 required[
'<string>'] = (linenum,
'string')
4410 for pattern, template, header
in _re_pattern_algorithm_header:
4411 if pattern.search(line):
4412 required[header] = (linenum, template)
4418 for pattern, template, header
in _re_pattern_templates:
4419 if pattern.search(line):
4420 required[header] = (linenum, template)
4425 include_state = include_state.copy()
4428 header_found =
False 4431 abs_filename =
FileInfo(filename).FullName()
4440 abs_filename = re.sub(
r'_flymake\.cc$',
'.cc', abs_filename)
4444 header_keys = include_state.keys()
4445 for header
in header_keys:
4447 fullpath = common_path + header
4456 if filename.endswith(
'.cc')
and not header_found:
4460 for required_header_unstripped
in required:
4461 template = required[required_header_unstripped][1]
4462 if required_header_unstripped.strip(
'<>"')
not in include_state:
4463 error(filename, required[required_header_unstripped][0],
4464 'build/include_what_you_use', 4,
4465 'Add #include ' + required_header_unstripped +
' for ' + template)
4468 _RE_PATTERN_EXPLICIT_MAKEPAIR = re.compile(
r'\bmake_pair\s*<')
4472 """Check that make_pair's template arguments are deduced. 4474 G++ 4.6 in C++0x mode fails badly if make_pair's template arguments are 4475 specified explicitly, and such use isn't intended in any case. 4478 filename: The name of the current file. 4479 clean_lines: A CleansedLines instance containing the file. 4480 linenum: The number of the line to check. 4481 error: The function to call with any errors found. 4483 line = clean_lines.elided[linenum]
4484 match = _RE_PATTERN_EXPLICIT_MAKEPAIR.search(line)
4486 error(filename, linenum,
'build/explicit_make_pair',
4488 'For C++11-compatibility, omit template arguments from make_pair' 4489 ' OR use pair directly OR if appropriate, construct a pair directly')
4492 def ProcessLine(filename, file_extension, clean_lines, line,
4493 include_state, function_state, nesting_state, error,
4494 extra_check_functions=[]):
4495 """Processes a single line in the file. 4498 filename: Filename of the file that is being processed. 4499 file_extension: The extension (dot not included) of the file. 4500 clean_lines: An array of strings, each representing a line of the file, 4501 with comments stripped. 4502 line: Number of line being processed. 4503 include_state: An _IncludeState instance in which the headers are inserted. 4504 function_state: A _FunctionState instance which counts function lines, etc. 4505 nesting_state: A _NestingState instance which maintains information about 4506 the current stack of nested blocks being parsed. 4507 error: A callable to which errors are reported, which takes 4 arguments: 4508 filename, line number, error level, and message 4509 extra_check_functions: An array of additional check functions that will be 4510 run on each source line. Each function takes 4 4511 arguments: filename, clean_lines, line, error 4513 raw_lines = clean_lines.raw_lines
4515 nesting_state.Update(filename, clean_lines, line, error)
4516 if nesting_state.stack
and nesting_state.stack[-1].inline_asm != _NO_ASM:
4520 CheckStyle(filename, clean_lines, line, file_extension, nesting_state, error)
4521 CheckLanguage(filename, clean_lines, line, file_extension, include_state,
4522 nesting_state, error)
4525 nesting_state, error)
4530 for check_fn
in extra_check_functions:
4531 check_fn(filename, clean_lines, line, error)
4534 extra_check_functions=[]):
4535 """Performs lint checks and reports any errors to the given error function. 4538 filename: Filename of the file that is being processed. 4539 file_extension: The extension (dot not included) of the file. 4540 lines: An array of strings, each representing a line of the file, with the 4541 last element being empty if the file is terminated with a newline. 4542 error: A callable to which errors are reported, which takes 4 arguments: 4543 filename, line number, error level, and message 4544 extra_check_functions: An array of additional check functions that will be 4545 run on each source line. Each function takes 4 4546 arguments: filename, clean_lines, line, error 4548 lines = ([
'// marker so line numbers and indices both start at 1'] + lines +
4549 [
'// marker so line numbers end in a known way'])
4559 if file_extension ==
'h':
4564 for line
in xrange(clean_lines.NumLines()):
4565 ProcessLine(filename, file_extension, clean_lines, line,
4566 include_state, function_state, nesting_state, error,
4567 extra_check_functions)
4568 nesting_state.CheckCompletedBlocks(filename, error)
4579 """Does google-lint on a single file. 4582 filename: The name of the file to parse. 4584 vlevel: The level of errors to report. Every error of confidence 4585 >= verbose_level will be reported. 0 is a good default. 4587 extra_check_functions: An array of additional check functions that will be 4588 run on each source line. Each function takes 4 4589 arguments: filename, clean_lines, line, error 4606 lines = codecs.StreamReaderWriter(sys.stdin,
4607 codecs.getreader(
'utf8'),
4608 codecs.getwriter(
'utf8'),
4609 'replace').read().split(
'\n')
4611 lines = codecs.open(filename,
'r', 'utf8', 'replace').read().split('\n')
4613 carriage_return_found =
False 4615 for linenum
in range(len(lines)):
4616 if lines[linenum].endswith(
'\r'):
4617 lines[linenum] = lines[linenum].rstrip(
'\r')
4618 carriage_return_found =
True 4622 "Skipping input '%s': Can't open for reading\n" % filename)
4626 file_extension = filename[filename.rfind(
'.') + 1:]
4630 if filename !=
'-' and file_extension
not in _valid_extensions:
4631 sys.stderr.write(
'Ignoring %s; not a valid file name ' 4632 '(%s)\n' % (filename,
', '.join(_valid_extensions)))
4635 extra_check_functions)
4636 if carriage_return_found
and os.linesep !=
'\r\n':
4639 Error(filename, 0,
'whitespace/newline', 1,
4640 'One or more unexpected \\r (^M) found;' 4641 'better to use only a \\n')
4648 """Prints a brief usage string and exits, optionally with an error message. 4651 message: The optional error message. 4653 sys.stderr.write(_USAGE)
4655 sys.exit(
'\nFATAL ERROR: ' + message)
4661 """Prints a list of all the error-categories used by error messages. 4663 These are the categories used to filter messages via --filter. 4665 sys.stderr.write(
''.join(
' %s\n' % cat
for cat
in _ERROR_CATEGORIES))
4670 """Parses the command line arguments. 4672 This may set the output format and verbosity level as side-effects. 4675 args: The command line arguments: 4678 The list of filenames to lint. 4681 (opts, filenames) = getopt.getopt(args,
'', [
'help',
'output=',
'verbose=',
4687 except getopt.GetoptError:
4695 for (opt, val)
in opts:
4698 elif opt ==
'--output':
4699 if val
not in (
'emacs',
'vs7',
'eclipse'):
4700 PrintUsage(
'The only allowed output formats are emacs, vs7 and eclipse.')
4702 elif opt ==
'--verbose':
4703 verbosity = int(val)
4704 elif opt ==
'--filter':
4708 elif opt ==
'--counting':
4709 if val
not in (
'total',
'toplevel',
'detailed'):
4710 PrintUsage(
'Valid counting options are total, toplevel, and detailed')
4711 counting_style = val
4712 elif opt ==
'--root':
4715 elif opt ==
'--linelength':
4718 _line_length = int(val)
4721 elif opt ==
'--extensions':
4722 global _valid_extensions
4724 _valid_extensions = set(val.split(
','))
4726 PrintUsage(
'Extensions must be comma seperated list.')
4744 sys.stderr = codecs.StreamReaderWriter(sys.stderr,
4745 codecs.getreader(
'utf8'),
4746 codecs.getwriter(
'utf8'),
4749 _cpplint_state.ResetErrorCounts()
4750 for filename
in filenames:
4751 ProcessFile(filename, _cpplint_state.verbose_level)
4752 _cpplint_state.PrintErrorCounts()
4754 sys.exit(_cpplint_state.error_count > 0)
4757 if __name__ ==
'__main__':
def CheckForNonStandardConstructs(filename, clean_lines, linenum, nesting_state, error)
def FindNextMatchingAngleBracket(clean_lines, linenum, init_suffix)
def CheckSpacingForFunctionCall(filename, line, linenum, error)
def UpdatePreprocessor(self, line)
def IsErrorSuppressedByNolint(category, linenum)
def CheckForNewlineAtEOF(filename, lines, error)
def CheckForBadCharacters(filename, lines, error)
def _ClassifyInclude(fileinfo, include, is_system)
def PrintErrorCounts(self)
def GetHeaderGuardCPPVariable(filename)
def ProcessLine(filename, file_extension, clean_lines, line, include_state, function_state, nesting_state, error, extra_check_functions=[])
def CheckForMultilineCommentsAndStrings(filename, clean_lines, linenum, error)
def CheckForHeaderGuard(filename, lines, error)
def CheckNextIncludeOrder(self, header_type)
def CheckCheck(filename, clean_lines, linenum, error)
def IsInAlphabeticalOrder(self, clean_lines, linenum, header_path)
def ResetNolintSuppressions()
def FilesBelongToSameModule(filename_cc, filename_h)
def FindEndOfExpressionInLine(line, startpos, depth, startchar, endchar)
def CleanseComments(line)
def SetOutputFormat(self, output_format)
def CheckEnd(self, filename, clean_lines, linenum, error)
dictionary _SECTION_NAMES
def __init__(self, name, linenum)
def CheckBegin(self, filename, clean_lines, linenum, error)
def ReplaceAll(pattern, rep, s)
def CheckVlogArguments(filename, clean_lines, linenum, error)
def CheckSectionSpacing(filename, clean_lines, class_info, linenum, error)
def CheckBraces(filename, clean_lines, linenum, error)
def CheckCompletedBlocks(self, filename, error)
def Error(filename, linenum, category, confidence, message)
def CheckCStyleCast(filename, linenum, line, raw_line, cast_type, pattern, error)
def RemoveMultiLineComments(filename, lines, error)
def CloseExpression(clean_lines, linenum, pos)
def CheckAltTokens(filename, clean_lines, linenum, error)
def RemoveMultiLineCommentsFromRange(lines, begin, end)
def ReverseCloseExpression(clean_lines, linenum, pos)
lines_without_raw_strings
def _SetOutputFormat(output_format)
def _SetCountingStyle(level)
def FindPreviousMatchingAngleBracket(clean_lines, linenum, init_prefix)
def CheckStyle(filename, clean_lines, linenum, file_extension, nesting_state, error)
def ParseNolintSuppressions(filename, raw_line, linenum, error)
def __init__(self, filename)
def _CollapseStrings(elided)
def SetCountingStyle(self, counting_style)
def ProcessFile(filename, vlevel, extra_check_functions=[])
def CheckForCopyright(filename, lines, error)
def SetLastHeader(self, header_path)
def __init__(self, lines)
def CheckBegin(self, filename, clean_lines, linenum, error)
def CleanseRawStrings(raw_lines)
def _SetVerboseLevel(level)
def CheckForFunctionLengths(filename, clean_lines, linenum, function_state, error)
def SetVerboseLevel(self, level)
def __init__(self, seen_open_brace)
def CheckEnd(self, filename, clean_lines, linenum, error)
def IncrementErrorCount(self, category)
def InNamespaceBody(self)
def FindStartOfExpressionInLine(line, endpos, depth, startchar, endchar)
def CheckPosixThreading(filename, clean_lines, linenum, error)
def CheckLanguage(filename, clean_lines, linenum, file_extension, include_state, nesting_state, error)
def CheckEmptyBlockBody(filename, clean_lines, linenum, error)
def Check(self, error, filename, linenum)
def CheckSpacing(filename, clean_lines, linenum, nesting_state, error)
def CheckMakePairUsesDeduction(filename, clean_lines, linenum, error)
def CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error, io=codecs)
def ProcessFileData(filename, file_extension, lines, error, extra_check_functions=[])
def CheckAccess(filename, clean_lines, linenum, nesting_state, error)
def GetPreviousNonBlankLine(clean_lines, linenum)
def FindNextMultiLineCommentEnd(lines, lineix)
def _ShouldPrintError(category, confidence, linenum)
def _IsTestFilename(filename)
def CheckComment(comment, filename, linenum, error)
def CanonicalizeAlphabeticalOrder(self, header_path)
def __init__(self, stack_before_if)
def SetFilters(self, filters)
def CheckIncludeLine(filename, clean_lines, linenum, include_state, error)
def _DropCommonSuffixes(filename)
def __init__(self, name, class_or_struct, clean_lines, linenum)
def CheckInvalidIncrement(filename, clean_lines, linenum, error)
def Update(self, filename, clean_lines, linenum, error)
def ResetErrorCounts(self)
def CheckForNonConstReference(filename, clean_lines, linenum, nesting_state, error)
def UpdateIncludeState(filename, include_state, io=codecs)
def FindNextMultiLineCommentStart(lines, lineix)
def CheckEnd(self, filename, clean_lines, linenum, error)
def Begin(self, function_name)
def _GetTextInside(text, start_pattern)