OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # | 2 # |
3 # Copyright (c) 2009 Google Inc. All rights reserved. | 3 # Copyright (c) 2009 Google Inc. All rights reserved. |
4 # | 4 # |
5 # Redistribution and use in source and binary forms, with or without | 5 # Redistribution and use in source and binary forms, with or without |
6 # modification, are permitted provided that the following conditions are | 6 # modification, are permitted provided that the following conditions are |
7 # met: | 7 # met: |
8 # | 8 # |
9 # * Redistributions of source code must retain the above copyright | 9 # * Redistributions of source code must retain the above copyright |
10 # notice, this list of conditions and the following disclaimer. | 10 # notice, this list of conditions and the following disclaimer. |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
107 | 107 |
108 root=subdir | 108 root=subdir |
109 The root directory used for deriving header guard CPP variable. | 109 The root directory used for deriving header guard CPP variable. |
110 By default, the header guard CPP variable is calculated as the relative | 110 By default, the header guard CPP variable is calculated as the relative |
111 path to the directory that contains .git, .hg, or .svn. When this flag | 111 path to the directory that contains .git, .hg, or .svn. When this flag |
112 is specified, the relative path is calculated from the specified | 112 is specified, the relative path is calculated from the specified |
113 directory. If the specified directory does not exist, this flag is | 113 directory. If the specified directory does not exist, this flag is |
114 ignored. | 114 ignored. |
115 | 115 |
116 Examples: | 116 Examples: |
117 Assuing that src/.git exists, the header guard CPP variables for | 117 Assuming that src/.git exists, the header guard CPP variables for |
118 src/chrome/browser/ui/browser.h are: | 118 src/chrome/browser/ui/browser.h are: |
119 | 119 |
120 No flag => CHROME_BROWSER_UI_BROWSER_H_ | 120 No flag => CHROME_BROWSER_UI_BROWSER_H_ |
121 --root=chrome => BROWSER_UI_BROWSER_H_ | 121 --root=chrome => BROWSER_UI_BROWSER_H_ |
122 --root=chrome/browser => UI_BROWSER_H_ | 122 --root=chrome/browser => UI_BROWSER_H_ |
123 | 123 |
124 linelength=digits | 124 linelength=digits |
125 This is the allowed line length for the project. The default value is | 125 This is the allowed line length for the project. The default value is |
126 80 characters. | 126 80 characters. |
127 | 127 |
128 Examples: | 128 Examples: |
129 --linelength=120 | 129 --linelength=120 |
130 | 130 |
131 extensions=extension,extension,... | 131 extensions=extension,extension,... |
132 The allowed file extensions that cpplint will check | 132 The allowed file extensions that cpplint will check |
133 | 133 |
134 Examples: | 134 Examples: |
135 --extensions=hpp,cpp | 135 --extensions=hpp,cpp |
136 """ | 136 """ |
137 | 137 |
138 # We categorize each error message we print. Here are the categories. | 138 # We categorize each error message we print. Here are the categories. |
139 # We want an explicit list so we can list them all in cpplint --filter=. | 139 # We want an explicit list so we can list them all in cpplint --filter=. |
140 # If you add a new error message with a new category, add it to the list | 140 # If you add a new error message with a new category, add it to the list |
141 # here! cpplint_unittest.py should tell you if you forget to do this. | 141 # here! cpplint_unittest.py should tell you if you forget to do this. |
142 _ERROR_CATEGORIES = [ | 142 _ERROR_CATEGORIES = [ |
143 'build/class', | 143 'build/class', |
| 144 'build/c++11', |
144 'build/deprecated', | 145 'build/deprecated', |
145 'build/endif_comment', | 146 'build/endif_comment', |
146 'build/explicit_make_pair', | 147 'build/explicit_make_pair', |
147 'build/forward_decl', | 148 'build/forward_decl', |
148 'build/header_guard', | 149 'build/header_guard', |
149 'build/include', | 150 'build/include', |
150 'build/include_alpha', | 151 'build/include_alpha', |
151 'build/include_order', | 152 'build/include_order', |
152 'build/include_what_you_use', | 153 'build/include_what_you_use', |
153 'build/namespaces', | 154 'build/namespaces', |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
196 'whitespace/indent', | 197 'whitespace/indent', |
197 'whitespace/line_length', | 198 'whitespace/line_length', |
198 'whitespace/newline', | 199 'whitespace/newline', |
199 'whitespace/operators', | 200 'whitespace/operators', |
200 'whitespace/parens', | 201 'whitespace/parens', |
201 'whitespace/semicolon', | 202 'whitespace/semicolon', |
202 'whitespace/tab', | 203 'whitespace/tab', |
203 'whitespace/todo' | 204 'whitespace/todo' |
204 ] | 205 ] |
205 | 206 |
206 # The default state of the category filter. This is overrided by the --filter= | 207 # The default state of the category filter. This is overridden by the --filter= |
207 # flag. By default all errors are on, so only add here categories that should be | 208 # flag. By default all errors are on, so only add here categories that should be |
208 # off by default (i.e., categories that must be enabled by the --filter= flags). | 209 # off by default (i.e., categories that must be enabled by the --filter= flags). |
209 # All entries here should start with a '-' or '+', as in the --filter= flag. | 210 # All entries here should start with a '-' or '+', as in the --filter= flag. |
210 _DEFAULT_FILTERS = ['-build/include_alpha'] | 211 _DEFAULT_FILTERS = ['-build/include_alpha'] |
211 | 212 |
212 # We used to check for high-bit characters, but after much discussion we | 213 # We used to check for high-bit characters, but after much discussion we |
213 # decided those were OK, as long as they were in UTF-8 and didn't represent | 214 # decided those were OK, as long as they were in UTF-8 and didn't represent |
214 # hard-coded international strings, which belong in a separate i18n file. | 215 # hard-coded international strings, which belong in a separate i18n file. |
215 | 216 |
216 | |
217 # C++ headers | 217 # C++ headers |
218 _CPP_HEADERS = frozenset([ | 218 _CPP_HEADERS = frozenset([ |
219 # Legacy | 219 # Legacy |
220 'algobase.h', | 220 'algobase.h', |
221 'algo.h', | 221 'algo.h', |
222 'alloc.h', | 222 'alloc.h', |
223 'builtinbuf.h', | 223 'builtinbuf.h', |
224 'bvector.h', | 224 'bvector.h', |
225 'complex.h', | 225 'complex.h', |
226 'defalloc.h', | 226 'defalloc.h', |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
343 'cstdio', | 343 'cstdio', |
344 'cstdlib', | 344 'cstdlib', |
345 'cstring', | 345 'cstring', |
346 'ctgmath', | 346 'ctgmath', |
347 'ctime', | 347 'ctime', |
348 'cuchar', | 348 'cuchar', |
349 'cwchar', | 349 'cwchar', |
350 'cwctype', | 350 'cwctype', |
351 ]) | 351 ]) |
352 | 352 |
| 353 |
353 # Assertion macros. These are defined in base/logging.h and | 354 # Assertion macros. These are defined in base/logging.h and |
354 # testing/base/gunit.h. Note that the _M versions need to come first | 355 # testing/base/gunit.h. Note that the _M versions need to come first |
355 # for substring matching to work. | 356 # for substring matching to work. |
356 _CHECK_MACROS = [ | 357 _CHECK_MACROS = [ |
357 'DCHECK', 'CHECK', | 358 'DCHECK', 'CHECK', |
358 'EXPECT_TRUE_M', 'EXPECT_TRUE', | 359 'EXPECT_TRUE_M', 'EXPECT_TRUE', |
359 'ASSERT_TRUE_M', 'ASSERT_TRUE', | 360 'ASSERT_TRUE_M', 'ASSERT_TRUE', |
360 'EXPECT_FALSE_M', 'EXPECT_FALSE', | 361 'EXPECT_FALSE_M', 'EXPECT_FALSE', |
361 'ASSERT_FALSE_M', 'ASSERT_FALSE', | 362 'ASSERT_FALSE_M', 'ASSERT_FALSE', |
362 ] | 363 ] |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
493 | 494 |
494 Args: | 495 Args: |
495 category: str, the category of the error. | 496 category: str, the category of the error. |
496 linenum: int, the current line number. | 497 linenum: int, the current line number. |
497 Returns: | 498 Returns: |
498 bool, True iff the error should be suppressed due to a NOLINT comment. | 499 bool, True iff the error should be suppressed due to a NOLINT comment. |
499 """ | 500 """ |
500 return (linenum in _error_suppressions.get(category, set()) or | 501 return (linenum in _error_suppressions.get(category, set()) or |
501 linenum in _error_suppressions.get(None, set())) | 502 linenum in _error_suppressions.get(None, set())) |
502 | 503 |
| 504 |
503 def Match(pattern, s): | 505 def Match(pattern, s): |
504 """Matches the string with the pattern, caching the compiled regexp.""" | 506 """Matches the string with the pattern, caching the compiled regexp.""" |
505 # The regexp compilation caching is inlined in both Match and Search for | 507 # The regexp compilation caching is inlined in both Match and Search for |
506 # performance reasons; factoring it out into a separate function turns out | 508 # performance reasons; factoring it out into a separate function turns out |
507 # to be noticeably expensive. | 509 # to be noticeably expensive. |
508 if pattern not in _regexp_compile_cache: | 510 if pattern not in _regexp_compile_cache: |
509 _regexp_compile_cache[pattern] = sre_compile.compile(pattern) | 511 _regexp_compile_cache[pattern] = sre_compile.compile(pattern) |
510 return _regexp_compile_cache[pattern].match(s) | 512 return _regexp_compile_cache[pattern].match(s) |
511 | 513 |
512 | 514 |
(...skipping 434 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
947 | 949 |
948 | 950 |
949 def _ShouldPrintError(category, confidence, linenum): | 951 def _ShouldPrintError(category, confidence, linenum): |
950 """If confidence >= verbose, category passes filter and is not suppressed.""" | 952 """If confidence >= verbose, category passes filter and is not suppressed.""" |
951 | 953 |
952 # There are three ways we might decide not to print an error message: | 954 # There are three ways we might decide not to print an error message: |
953 # a "NOLINT(category)" comment appears in the source, | 955 # a "NOLINT(category)" comment appears in the source, |
954 # the verbosity level isn't high enough, or the filters filter it out. | 956 # the verbosity level isn't high enough, or the filters filter it out. |
955 if IsErrorSuppressedByNolint(category, linenum): | 957 if IsErrorSuppressedByNolint(category, linenum): |
956 return False | 958 return False |
| 959 |
957 if confidence < _cpplint_state.verbose_level: | 960 if confidence < _cpplint_state.verbose_level: |
958 return False | 961 return False |
959 | 962 |
960 is_filtered = False | 963 is_filtered = False |
961 for one_filter in _Filters(): | 964 for one_filter in _Filters(): |
962 if one_filter.startswith('-'): | 965 if one_filter.startswith('-'): |
963 if category.startswith(one_filter[1:]): | 966 if category.startswith(one_filter[1:]): |
964 is_filtered = True | 967 is_filtered = True |
965 elif one_filter.startswith('+'): | 968 elif one_filter.startswith('+'): |
966 if category.startswith(one_filter[1:]): | 969 if category.startswith(one_filter[1:]): |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1004 sys.stderr.write('%s:%s: warning: %s [%s] [%d]\n' % ( | 1007 sys.stderr.write('%s:%s: warning: %s [%s] [%d]\n' % ( |
1005 filename, linenum, message, category, confidence)) | 1008 filename, linenum, message, category, confidence)) |
1006 else: | 1009 else: |
1007 sys.stderr.write('%s:%s: %s [%s] [%d]\n' % ( | 1010 sys.stderr.write('%s:%s: %s [%s] [%d]\n' % ( |
1008 filename, linenum, message, category, confidence)) | 1011 filename, linenum, message, category, confidence)) |
1009 | 1012 |
1010 | 1013 |
1011 # Matches standard C++ escape sequences per 2.13.2.3 of the C++ standard. | 1014 # Matches standard C++ escape sequences per 2.13.2.3 of the C++ standard. |
1012 _RE_PATTERN_CLEANSE_LINE_ESCAPES = re.compile( | 1015 _RE_PATTERN_CLEANSE_LINE_ESCAPES = re.compile( |
1013 r'\\([abfnrtv?"\\\']|\d+|x[0-9a-fA-F]+)') | 1016 r'\\([abfnrtv?"\\\']|\d+|x[0-9a-fA-F]+)') |
1014 # Matches strings. Escape codes should already be removed by ESCAPES. | 1017 # Match a single C style comment on the same line. |
1015 _RE_PATTERN_CLEANSE_LINE_DOUBLE_QUOTES = re.compile(r'"[^"]*"') | 1018 _RE_PATTERN_C_COMMENTS = r'/\*(?:[^*]|\*(?!/))*\*/' |
1016 # Matches characters. Escape codes should already be removed by ESCAPES. | 1019 # Matches multi-line C style comments. |
1017 _RE_PATTERN_CLEANSE_LINE_SINGLE_QUOTES = re.compile(r"'.'") | |
1018 # Matches multi-line C++ comments. | |
1019 # This RE is a little bit more complicated than one might expect, because we | 1020 # This RE is a little bit more complicated than one might expect, because we |
1020 # have to take care of space removals tools so we can handle comments inside | 1021 # have to take care of space removals tools so we can handle comments inside |
1021 # statements better. | 1022 # statements better. |
1022 # The current rule is: We only clear spaces from both sides when we're at the | 1023 # The current rule is: We only clear spaces from both sides when we're at the |
1023 # end of the line. Otherwise, we try to remove spaces from the right side, | 1024 # end of the line. Otherwise, we try to remove spaces from the right side, |
1024 # if this doesn't work we try on left side but only if there's a non-character | 1025 # if this doesn't work we try on left side but only if there's a non-character |
1025 # on the right. | 1026 # on the right. |
1026 _RE_PATTERN_CLEANSE_LINE_C_COMMENTS = re.compile( | 1027 _RE_PATTERN_CLEANSE_LINE_C_COMMENTS = re.compile( |
1027 r"""(\s*/\*.*\*/\s*$| | 1028 r'(\s*' + _RE_PATTERN_C_COMMENTS + r'\s*$|' + |
1028 /\*.*\*/\s+| | 1029 _RE_PATTERN_C_COMMENTS + r'\s+|' + |
1029 \s+/\*.*\*/(?=\W)| | 1030 r'\s+' + _RE_PATTERN_C_COMMENTS + r'(?=\W)|' + |
1030 /\*.*\*/)""", re.VERBOSE) | 1031 _RE_PATTERN_C_COMMENTS + r')') |
1031 | 1032 |
1032 | 1033 |
1033 def IsCppString(line): | 1034 def IsCppString(line): |
1034 """Does line terminate so, that the next symbol is in string constant. | 1035 """Does line terminate so, that the next symbol is in string constant. |
1035 | 1036 |
1036 This function does not consider single-line nor multi-line comments. | 1037 This function does not consider single-line nor multi-line comments. |
1037 | 1038 |
1038 Args: | 1039 Args: |
1039 line: is a partial line of code starting from the 0..n. | 1040 line: is a partial line of code starting from the 0..n. |
1040 | 1041 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1075 end = line.find(delimiter) | 1076 end = line.find(delimiter) |
1076 if end >= 0: | 1077 if end >= 0: |
1077 # Found the end of the string, match leading space for this | 1078 # Found the end of the string, match leading space for this |
1078 # line and resume copying the original lines, and also insert | 1079 # line and resume copying the original lines, and also insert |
1079 # a "" on the last line. | 1080 # a "" on the last line. |
1080 leading_space = Match(r'^(\s*)\S', line) | 1081 leading_space = Match(r'^(\s*)\S', line) |
1081 line = leading_space.group(1) + '""' + line[end + len(delimiter):] | 1082 line = leading_space.group(1) + '""' + line[end + len(delimiter):] |
1082 delimiter = None | 1083 delimiter = None |
1083 else: | 1084 else: |
1084 # Haven't found the end yet, append a blank line. | 1085 # Haven't found the end yet, append a blank line. |
1085 line = '' | 1086 line = '""' |
1086 | 1087 |
1087 else: | 1088 # Look for beginning of a raw string, and replace them with |
| 1089 # empty strings. This is done in a loop to handle multiple raw |
| 1090 # strings on the same line. |
| 1091 while delimiter is None: |
1088 # Look for beginning of a raw string. | 1092 # Look for beginning of a raw string. |
1089 # See 2.14.15 [lex.string] for syntax. | 1093 # See 2.14.15 [lex.string] for syntax. |
1090 matched = Match(r'^(.*)\b(?:R|u8R|uR|UR|LR)"([^\s\\()]*)\((.*)$', line) | 1094 matched = Match(r'^(.*)\b(?:R|u8R|uR|UR|LR)"([^\s\\()]*)\((.*)$', line) |
1091 if matched: | 1095 if matched: |
1092 delimiter = ')' + matched.group(2) + '"' | 1096 delimiter = ')' + matched.group(2) + '"' |
1093 | 1097 |
1094 end = matched.group(3).find(delimiter) | 1098 end = matched.group(3).find(delimiter) |
1095 if end >= 0: | 1099 if end >= 0: |
1096 # Raw string ended on same line | 1100 # Raw string ended on same line |
1097 line = (matched.group(1) + '""' + | 1101 line = (matched.group(1) + '""' + |
1098 matched.group(3)[end + len(delimiter):]) | 1102 matched.group(3)[end + len(delimiter):]) |
1099 delimiter = None | 1103 delimiter = None |
1100 else: | 1104 else: |
1101 # Start of a multi-line raw string | 1105 # Start of a multi-line raw string |
1102 line = matched.group(1) + '""' | 1106 line = matched.group(1) + '""' |
| 1107 else: |
| 1108 break |
1103 | 1109 |
1104 lines_without_raw_strings.append(line) | 1110 lines_without_raw_strings.append(line) |
1105 | 1111 |
1106 # TODO(unknown): if delimiter is not None here, we might want to | 1112 # TODO(unknown): if delimiter is not None here, we might want to |
1107 # emit a warning for unterminated string. | 1113 # emit a warning for unterminated string. |
1108 return lines_without_raw_strings | 1114 return lines_without_raw_strings |
1109 | 1115 |
1110 | 1116 |
1111 def FindNextMultiLineCommentStart(lines, lineix): | 1117 def FindNextMultiLineCommentStart(lines, lineix): |
1112 """Find the beginning marker for a multiline comment.""" | 1118 """Find the beginning marker for a multiline comment.""" |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1198 """Collapses strings and chars on a line to simple "" or '' blocks. | 1204 """Collapses strings and chars on a line to simple "" or '' blocks. |
1199 | 1205 |
1200 We nix strings first so we're not fooled by text like '"http://"' | 1206 We nix strings first so we're not fooled by text like '"http://"' |
1201 | 1207 |
1202 Args: | 1208 Args: |
1203 elided: The line being processed. | 1209 elided: The line being processed. |
1204 | 1210 |
1205 Returns: | 1211 Returns: |
1206 The line with collapsed strings. | 1212 The line with collapsed strings. |
1207 """ | 1213 """ |
1208 if not _RE_PATTERN_INCLUDE.match(elided): | 1214 if _RE_PATTERN_INCLUDE.match(elided): |
1209 # Remove escaped characters first to make quote/single quote collapsing | 1215 return elided |
1210 # basic. Things that look like escaped characters shouldn't occur | 1216 |
1211 # outside of strings and chars. | 1217 # Remove escaped characters first to make quote/single quote collapsing |
1212 elided = _RE_PATTERN_CLEANSE_LINE_ESCAPES.sub('', elided) | 1218 # basic. Things that look like escaped characters shouldn't occur |
1213 elided = _RE_PATTERN_CLEANSE_LINE_SINGLE_QUOTES.sub("''", elided) | 1219 # outside of strings and chars. |
1214 elided = _RE_PATTERN_CLEANSE_LINE_DOUBLE_QUOTES.sub('""', elided) | 1220 elided = _RE_PATTERN_CLEANSE_LINE_ESCAPES.sub('', elided) |
1215 return elided | 1221 |
| 1222 # Replace quoted strings and digit separators. Both single quotes |
| 1223 # and double quotes are processed in the same loop, otherwise |
| 1224 # nested quotes wouldn't work. |
| 1225 collapsed = '' |
| 1226 while True: |
| 1227 # Find the first quote character |
| 1228 match = Match(r'^([^\'"]*)([\'"])(.*)$', elided) |
| 1229 if not match: |
| 1230 collapsed += elided |
| 1231 break |
| 1232 head, quote, tail = match.groups() |
| 1233 |
| 1234 if quote == '"': |
| 1235 # Collapse double quoted strings |
| 1236 second_quote = tail.find('"') |
| 1237 if second_quote >= 0: |
| 1238 collapsed += head + '""' |
| 1239 elided = tail[second_quote + 1:] |
| 1240 else: |
| 1241 # Unmatched double quote, don't bother processing the rest |
| 1242 # of the line since this is probably a multiline string. |
| 1243 collapsed += elided |
| 1244 break |
| 1245 else: |
| 1246 # Found single quote, check nearby text to eliminate digit separators. |
| 1247 # |
| 1248 # There is no special handling for floating point here, because |
| 1249 # the integer/fractional/exponent parts would all be parsed |
| 1250 # correctly as long as there are digits on both sides of the |
| 1251 # separator. So we are fine as long as we don't see something |
| 1252 # like "0.'3" (gcc 4.9.0 will not allow this literal). |
| 1253 if Search(r'\b(?:0[bBxX]?|[1-9])[0-9a-fA-F]*$', head): |
| 1254 match_literal = Match(r'^((?:\'?[0-9a-zA-Z_])*)(.*)$', "'" + tail) |
| 1255 collapsed += head + match_literal.group(1).replace("'", '') |
| 1256 elided = match_literal.group(2) |
| 1257 else: |
| 1258 second_quote = tail.find('\'') |
| 1259 if second_quote >= 0: |
| 1260 collapsed += head + "''" |
| 1261 elided = tail[second_quote + 1:] |
| 1262 else: |
| 1263 # Unmatched single quote |
| 1264 collapsed += elided |
| 1265 break |
| 1266 |
| 1267 return collapsed |
1216 | 1268 |
1217 | 1269 |
1218 def FindEndOfExpressionInLine(line, startpos, depth, startchar, endchar): | 1270 def FindEndOfExpressionInLine(line, startpos, stack): |
1219 """Find the position just after the matching endchar. | 1271 """Find the position just after the end of current parenthesized expression. |
1220 | 1272 |
1221 Args: | 1273 Args: |
1222 line: a CleansedLines line. | 1274 line: a CleansedLines line. |
1223 startpos: start searching at this position. | 1275 startpos: start searching at this position. |
1224 depth: nesting level at startpos. | 1276 stack: nesting stack at startpos. |
1225 startchar: expression opening character. | |
1226 endchar: expression closing character. | |
1227 | 1277 |
1228 Returns: | 1278 Returns: |
1229 On finding matching endchar: (index just after matching endchar, 0) | 1279 On finding matching end: (index just after matching end, None) |
1230 Otherwise: (-1, new depth at end of this line) | 1280 On finding an unclosed expression: (-1, None) |
| 1281 Otherwise: (-1, new stack at end of this line) |
1231 """ | 1282 """ |
1232 for i in xrange(startpos, len(line)): | 1283 for i in xrange(startpos, len(line)): |
1233 if line[i] == startchar: | 1284 char = line[i] |
1234 depth += 1 | 1285 if char in '([{': |
1235 elif line[i] == endchar: | 1286 # Found start of parenthesized expression, push to expression stack |
1236 depth -= 1 | 1287 stack.append(char) |
1237 if depth == 0: | 1288 elif char == '<': |
1238 return (i + 1, 0) | 1289 # Found potential start of template argument list |
1239 return (-1, depth) | 1290 if i > 0 and line[i - 1] == '<': |
| 1291 # Left shift operator |
| 1292 if stack and stack[-1] == '<': |
| 1293 stack.pop() |
| 1294 if not stack: |
| 1295 return (-1, None) |
| 1296 elif i > 0 and Search(r'\boperator\s*$', line[0:i]): |
| 1297 # operator<, don't add to stack |
| 1298 continue |
| 1299 else: |
| 1300 # Tentative start of template argument list |
| 1301 stack.append('<') |
| 1302 elif char in ')]}': |
| 1303 # Found end of parenthesized expression. |
| 1304 # |
| 1305 # If we are currently expecting a matching '>', the pending '<' |
| 1306 # must have been an operator. Remove them from expression stack. |
| 1307 while stack and stack[-1] == '<': |
| 1308 stack.pop() |
| 1309 if not stack: |
| 1310 return (-1, None) |
| 1311 if ((stack[-1] == '(' and char == ')') or |
| 1312 (stack[-1] == '[' and char == ']') or |
| 1313 (stack[-1] == '{' and char == '}')): |
| 1314 stack.pop() |
| 1315 if not stack: |
| 1316 return (i + 1, None) |
| 1317 else: |
| 1318 # Mismatched parentheses |
| 1319 return (-1, None) |
| 1320 elif char == '>': |
| 1321 # Found potential end of template argument list. |
| 1322 |
| 1323 # Ignore "->" and operator functions |
| 1324 if (i > 0 and |
| 1325 (line[i - 1] == '-' or Search(r'\boperator\s*$', line[0:i - 1]))): |
| 1326 continue |
| 1327 |
| 1328 # Pop the stack if there is a matching '<'. Otherwise, ignore |
| 1329 # this '>' since it must be an operator. |
| 1330 if stack: |
| 1331 if stack[-1] == '<': |
| 1332 stack.pop() |
| 1333 if not stack: |
| 1334 return (i + 1, None) |
| 1335 elif char == ';': |
| 1336 # Found something that look like end of statements. If we are currently |
| 1337 # expecting a '>', the matching '<' must have been an operator, since |
| 1338 # template argument list should not contain statements. |
| 1339 while stack and stack[-1] == '<': |
| 1340 stack.pop() |
| 1341 if not stack: |
| 1342 return (-1, None) |
| 1343 |
| 1344 # Did not find end of expression or unbalanced parentheses on this line |
| 1345 return (-1, stack) |
1240 | 1346 |
1241 | 1347 |
1242 def CloseExpression(clean_lines, linenum, pos): | 1348 def CloseExpression(clean_lines, linenum, pos): |
1243 """If input points to ( or { or [ or <, finds the position that closes it. | 1349 """If input points to ( or { or [ or <, finds the position that closes it. |
1244 | 1350 |
1245 If lines[linenum][pos] points to a '(' or '{' or '[' or '<', finds the | 1351 If lines[linenum][pos] points to a '(' or '{' or '[' or '<', finds the |
1246 linenum/pos that correspond to the closing of the expression. | 1352 linenum/pos that correspond to the closing of the expression. |
1247 | 1353 |
| 1354 TODO(unknown): cpplint spends a fair bit of time matching parentheses. |
| 1355 Ideally we would want to index all opening and closing parentheses once |
| 1356 and have CloseExpression be just a simple lookup, but due to preprocessor |
| 1357 tricks, this is not so easy. |
| 1358 |
1248 Args: | 1359 Args: |
1249 clean_lines: A CleansedLines instance containing the file. | 1360 clean_lines: A CleansedLines instance containing the file. |
1250 linenum: The number of the line to check. | 1361 linenum: The number of the line to check. |
1251 pos: A position on the line. | 1362 pos: A position on the line. |
1252 | 1363 |
1253 Returns: | 1364 Returns: |
1254 A tuple (line, linenum, pos) pointer *past* the closing brace, or | 1365 A tuple (line, linenum, pos) pointer *past* the closing brace, or |
1255 (line, len(lines), -1) if we never find a close. Note we ignore | 1366 (line, len(lines), -1) if we never find a close. Note we ignore |
1256 strings and comments when matching; and the line we return is the | 1367 strings and comments when matching; and the line we return is the |
1257 'cleansed' line at linenum. | 1368 'cleansed' line at linenum. |
1258 """ | 1369 """ |
1259 | 1370 |
1260 line = clean_lines.elided[linenum] | 1371 line = clean_lines.elided[linenum] |
1261 startchar = line[pos] | 1372 if (line[pos] not in '({[<') or Match(r'<[<=]', line[pos:]): |
1262 if startchar not in '({[<': | |
1263 return (line, clean_lines.NumLines(), -1) | 1373 return (line, clean_lines.NumLines(), -1) |
1264 if startchar == '(': endchar = ')' | |
1265 if startchar == '[': endchar = ']' | |
1266 if startchar == '{': endchar = '}' | |
1267 if startchar == '<': endchar = '>' | |
1268 | 1374 |
1269 # Check first line | 1375 # Check first line |
1270 (end_pos, num_open) = FindEndOfExpressionInLine( | 1376 (end_pos, stack) = FindEndOfExpressionInLine(line, pos, []) |
1271 line, pos, 0, startchar, endchar) | |
1272 if end_pos > -1: | 1377 if end_pos > -1: |
1273 return (line, linenum, end_pos) | 1378 return (line, linenum, end_pos) |
1274 | 1379 |
1275 # Continue scanning forward | 1380 # Continue scanning forward |
1276 while linenum < clean_lines.NumLines() - 1: | 1381 while stack and linenum < clean_lines.NumLines() - 1: |
1277 linenum += 1 | 1382 linenum += 1 |
1278 line = clean_lines.elided[linenum] | 1383 line = clean_lines.elided[linenum] |
1279 (end_pos, num_open) = FindEndOfExpressionInLine( | 1384 (end_pos, stack) = FindEndOfExpressionInLine(line, 0, stack) |
1280 line, 0, num_open, startchar, endchar) | |
1281 if end_pos > -1: | 1385 if end_pos > -1: |
1282 return (line, linenum, end_pos) | 1386 return (line, linenum, end_pos) |
1283 | 1387 |
1284 # Did not find endchar before end of file, give up | 1388 # Did not find end of expression before end of file, give up |
1285 return (line, clean_lines.NumLines(), -1) | 1389 return (line, clean_lines.NumLines(), -1) |
1286 | 1390 |
1287 | 1391 |
1288 def FindStartOfExpressionInLine(line, endpos, depth, startchar, endchar): | 1392 def FindStartOfExpressionInLine(line, endpos, stack): |
1289 """Find position at the matching startchar. | 1393 """Find position at the matching start of current expression. |
1290 | 1394 |
1291 This is almost the reverse of FindEndOfExpressionInLine, but note | 1395 This is almost the reverse of FindEndOfExpressionInLine, but note |
1292 that the input position and returned position differs by 1. | 1396 that the input position and returned position differs by 1. |
1293 | 1397 |
1294 Args: | 1398 Args: |
1295 line: a CleansedLines line. | 1399 line: a CleansedLines line. |
1296 endpos: start searching at this position. | 1400 endpos: start searching at this position. |
1297 depth: nesting level at endpos. | 1401 stack: nesting stack at endpos. |
1298 startchar: expression opening character. | |
1299 endchar: expression closing character. | |
1300 | 1402 |
1301 Returns: | 1403 Returns: |
1302 On finding matching startchar: (index at matching startchar, 0) | 1404 On finding matching start: (index at matching start, None) |
1303 Otherwise: (-1, new depth at beginning of this line) | 1405 On finding an unclosed expression: (-1, None) |
| 1406 Otherwise: (-1, new stack at beginning of this line) |
1304 """ | 1407 """ |
1305 for i in xrange(endpos, -1, -1): | 1408 i = endpos |
1306 if line[i] == endchar: | 1409 while i >= 0: |
1307 depth += 1 | 1410 char = line[i] |
1308 elif line[i] == startchar: | 1411 if char in ')]}': |
1309 depth -= 1 | 1412 # Found end of expression, push to expression stack |
1310 if depth == 0: | 1413 stack.append(char) |
1311 return (i, 0) | 1414 elif char == '>': |
1312 return (-1, depth) | 1415 # Found potential end of template argument list. |
| 1416 # |
| 1417 # Ignore it if it's a "->" or ">=" or "operator>" |
| 1418 if (i > 0 and |
| 1419 (line[i - 1] == '-' or |
| 1420 Match(r'\s>=\s', line[i - 1:]) or |
| 1421 Search(r'\boperator\s*$', line[0:i]))): |
| 1422 i -= 1 |
| 1423 else: |
| 1424 stack.append('>') |
| 1425 elif char == '<': |
| 1426 # Found potential start of template argument list |
| 1427 if i > 0 and line[i - 1] == '<': |
| 1428 # Left shift operator |
| 1429 i -= 1 |
| 1430 else: |
| 1431 # If there is a matching '>', we can pop the expression stack. |
| 1432 # Otherwise, ignore this '<' since it must be an operator. |
| 1433 if stack and stack[-1] == '>': |
| 1434 stack.pop() |
| 1435 if not stack: |
| 1436 return (i, None) |
| 1437 elif char in '([{': |
| 1438 # Found start of expression. |
| 1439 # |
| 1440 # If there are any unmatched '>' on the stack, they must be |
| 1441 # operators. Remove those. |
| 1442 while stack and stack[-1] == '>': |
| 1443 stack.pop() |
| 1444 if not stack: |
| 1445 return (-1, None) |
| 1446 if ((char == '(' and stack[-1] == ')') or |
| 1447 (char == '[' and stack[-1] == ']') or |
| 1448 (char == '{' and stack[-1] == '}')): |
| 1449 stack.pop() |
| 1450 if not stack: |
| 1451 return (i, None) |
| 1452 else: |
| 1453 # Mismatched parentheses |
| 1454 return (-1, None) |
| 1455 elif char == ';': |
| 1456 # Found something that look like end of statements. If we are currently |
| 1457 # expecting a '<', the matching '>' must have been an operator, since |
| 1458 # template argument list should not contain statements. |
| 1459 while stack and stack[-1] == '>': |
| 1460 stack.pop() |
| 1461 if not stack: |
| 1462 return (-1, None) |
| 1463 |
| 1464 i -= 1 |
| 1465 |
| 1466 return (-1, stack) |
1313 | 1467 |
1314 | 1468 |
1315 def ReverseCloseExpression(clean_lines, linenum, pos): | 1469 def ReverseCloseExpression(clean_lines, linenum, pos): |
1316 """If input points to ) or } or ] or >, finds the position that opens it. | 1470 """If input points to ) or } or ] or >, finds the position that opens it. |
1317 | 1471 |
1318 If lines[linenum][pos] points to a ')' or '}' or ']' or '>', finds the | 1472 If lines[linenum][pos] points to a ')' or '}' or ']' or '>', finds the |
1319 linenum/pos that correspond to the opening of the expression. | 1473 linenum/pos that correspond to the opening of the expression. |
1320 | 1474 |
1321 Args: | 1475 Args: |
1322 clean_lines: A CleansedLines instance containing the file. | 1476 clean_lines: A CleansedLines instance containing the file. |
1323 linenum: The number of the line to check. | 1477 linenum: The number of the line to check. |
1324 pos: A position on the line. | 1478 pos: A position on the line. |
1325 | 1479 |
1326 Returns: | 1480 Returns: |
1327 A tuple (line, linenum, pos) pointer *at* the opening brace, or | 1481 A tuple (line, linenum, pos) pointer *at* the opening brace, or |
1328 (line, 0, -1) if we never find the matching opening brace. Note | 1482 (line, 0, -1) if we never find the matching opening brace. Note |
1329 we ignore strings and comments when matching; and the line we | 1483 we ignore strings and comments when matching; and the line we |
1330 return is the 'cleansed' line at linenum. | 1484 return is the 'cleansed' line at linenum. |
1331 """ | 1485 """ |
1332 line = clean_lines.elided[linenum] | 1486 line = clean_lines.elided[linenum] |
1333 endchar = line[pos] | 1487 if line[pos] not in ')}]>': |
1334 if endchar not in ')}]>': | |
1335 return (line, 0, -1) | 1488 return (line, 0, -1) |
1336 if endchar == ')': startchar = '(' | |
1337 if endchar == ']': startchar = '[' | |
1338 if endchar == '}': startchar = '{' | |
1339 if endchar == '>': startchar = '<' | |
1340 | 1489 |
1341 # Check last line | 1490 # Check last line |
1342 (start_pos, num_open) = FindStartOfExpressionInLine( | 1491 (start_pos, stack) = FindStartOfExpressionInLine(line, pos, []) |
1343 line, pos, 0, startchar, endchar) | |
1344 if start_pos > -1: | 1492 if start_pos > -1: |
1345 return (line, linenum, start_pos) | 1493 return (line, linenum, start_pos) |
1346 | 1494 |
1347 # Continue scanning backward | 1495 # Continue scanning backward |
1348 while linenum > 0: | 1496 while stack and linenum > 0: |
1349 linenum -= 1 | 1497 linenum -= 1 |
1350 line = clean_lines.elided[linenum] | 1498 line = clean_lines.elided[linenum] |
1351 (start_pos, num_open) = FindStartOfExpressionInLine( | 1499 (start_pos, stack) = FindStartOfExpressionInLine(line, len(line) - 1, stack) |
1352 line, len(line) - 1, num_open, startchar, endchar) | |
1353 if start_pos > -1: | 1500 if start_pos > -1: |
1354 return (line, linenum, start_pos) | 1501 return (line, linenum, start_pos) |
1355 | 1502 |
1356 # Did not find startchar before beginning of file, give up | 1503 # Did not find start of expression before beginning of file, give up |
1357 return (line, 0, -1) | 1504 return (line, 0, -1) |
1358 | 1505 |
1359 | 1506 |
1360 def CheckForCopyright(filename, lines, error): | 1507 def CheckForCopyright(filename, lines, error): |
1361 """Logs an error if no Copyright message appears at the top of the file.""" | 1508 """Logs an error if no Copyright message appears at the top of the file.""" |
1362 | 1509 |
1363 # We'll say it should occur by line 10. Don't forget there's a | 1510 # We'll say it should occur by line 10. Don't forget there's a |
1364 # dummy line at the front. | 1511 # dummy line at the front. |
1365 for line in xrange(1, min(len(lines), 11)): | 1512 for line in xrange(1, min(len(lines), 11)): |
1366 if re.search(r'Copyright', lines[line], re.I): break | 1513 if re.search(r'Copyright', lines[line], re.I): break |
1367 else: # means no copyright line was found | 1514 else: # means no copyright line was found |
1368 error(filename, 0, 'legal/copyright', 5, | 1515 error(filename, 0, 'legal/copyright', 5, |
1369 'No copyright message found. ' | 1516 'No copyright message found. ' |
1370 'You should have a line: "Copyright [year] <Copyright Owner>"') | 1517 'You should have a line: "Copyright [year] <Copyright Owner>"') |
1371 | 1518 |
1372 | 1519 |
| 1520 def GetIndentLevel(line): |
| 1521 """Return the number of leading spaces in line. |
| 1522 |
| 1523 Args: |
| 1524 line: A string to check. |
| 1525 |
| 1526 Returns: |
| 1527 An integer count of leading spaces, possibly zero. |
| 1528 """ |
| 1529 indent = Match(r'^( *)\S', line) |
| 1530 if indent: |
| 1531 return len(indent.group(1)) |
| 1532 else: |
| 1533 return 0 |
| 1534 |
| 1535 |
1373 def GetHeaderGuardCPPVariable(filename): | 1536 def GetHeaderGuardCPPVariable(filename): |
1374 """Returns the CPP variable that should be used as a header guard. | 1537 """Returns the CPP variable that should be used as a header guard. |
1375 | 1538 |
1376 Args: | 1539 Args: |
1377 filename: The name of a C++ header file. | 1540 filename: The name of a C++ header file. |
1378 | 1541 |
1379 Returns: | 1542 Returns: |
1380 The CPP variable that should be used as a header guard in the | 1543 The CPP variable that should be used as a header guard in the |
1381 named file. | 1544 named file. |
1382 | 1545 |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1543 'with #if 0...#endif, ' | 1706 'with #if 0...#endif, ' |
1544 'or with more clearly structured multi-line comments.') | 1707 'or with more clearly structured multi-line comments.') |
1545 | 1708 |
1546 if (line.count('"') - line.count('\\"')) % 2: | 1709 if (line.count('"') - line.count('\\"')) % 2: |
1547 error(filename, linenum, 'readability/multiline_string', 5, | 1710 error(filename, linenum, 'readability/multiline_string', 5, |
1548 'Multi-line string ("...") found. This lint script doesn\'t ' | 1711 'Multi-line string ("...") found. This lint script doesn\'t ' |
1549 'do well with such strings, and may give bogus warnings. ' | 1712 'do well with such strings, and may give bogus warnings. ' |
1550 'Use C++11 raw strings or concatenation instead.') | 1713 'Use C++11 raw strings or concatenation instead.') |
1551 | 1714 |
1552 | 1715 |
1553 threading_list = ( | 1716 # (non-threadsafe name, thread-safe alternative, validation pattern) |
1554 ('asctime(', 'asctime_r('), | 1717 # |
1555 ('ctime(', 'ctime_r('), | 1718 # The validation pattern is used to eliminate false positives such as: |
1556 ('getgrgid(', 'getgrgid_r('), | 1719 # _rand(); // false positive due to substring match. |
1557 ('getgrnam(', 'getgrnam_r('), | 1720 # ->rand(); // some member function rand(). |
1558 ('getlogin(', 'getlogin_r('), | 1721 # ACMRandom rand(seed); // some variable named rand. |
1559 ('getpwnam(', 'getpwnam_r('), | 1722 # ISAACRandom rand(); // another variable named rand. |
1560 ('getpwuid(', 'getpwuid_r('), | 1723 # |
1561 ('gmtime(', 'gmtime_r('), | 1724 # Basically we require the return value of these functions to be used |
1562 ('localtime(', 'localtime_r('), | 1725 # in some expression context on the same line by matching on some |
1563 ('rand(', 'rand_r('), | 1726 # operator before the function name. This eliminates constructors and |
1564 ('strtok(', 'strtok_r('), | 1727 # member function calls. |
1565 ('ttyname(', 'ttyname_r('), | 1728 _UNSAFE_FUNC_PREFIX = r'(?:[-+*/=%^&|(<]\s*|>\s+)' |
| 1729 _THREADING_LIST = ( |
| 1730 ('asctime(', 'asctime_r(', _UNSAFE_FUNC_PREFIX + r'asctime\([^)]+\)'), |
| 1731 ('ctime(', 'ctime_r(', _UNSAFE_FUNC_PREFIX + r'ctime\([^)]+\)'), |
| 1732 ('getgrgid(', 'getgrgid_r(', _UNSAFE_FUNC_PREFIX + r'getgrgid\([^)]+\)'), |
| 1733 ('getgrnam(', 'getgrnam_r(', _UNSAFE_FUNC_PREFIX + r'getgrnam\([^)]+\)'), |
| 1734 ('getlogin(', 'getlogin_r(', _UNSAFE_FUNC_PREFIX + r'getlogin\(\)'), |
| 1735 ('getpwnam(', 'getpwnam_r(', _UNSAFE_FUNC_PREFIX + r'getpwnam\([^)]+\)'), |
| 1736 ('getpwuid(', 'getpwuid_r(', _UNSAFE_FUNC_PREFIX + r'getpwuid\([^)]+\)'), |
| 1737 ('gmtime(', 'gmtime_r(', _UNSAFE_FUNC_PREFIX + r'gmtime\([^)]+\)'), |
| 1738 ('localtime(', 'localtime_r(', _UNSAFE_FUNC_PREFIX + r'localtime\([^)]+\)'), |
| 1739 ('rand(', 'rand_r(', _UNSAFE_FUNC_PREFIX + r'rand\(\)'), |
| 1740 ('strtok(', 'strtok_r(', |
| 1741 _UNSAFE_FUNC_PREFIX + r'strtok\([^)]+\)'), |
| 1742 ('ttyname(', 'ttyname_r(', _UNSAFE_FUNC_PREFIX + r'ttyname\([^)]+\)'), |
1566 ) | 1743 ) |
1567 | 1744 |
1568 | 1745 |
1569 def CheckPosixThreading(filename, clean_lines, linenum, error): | 1746 def CheckPosixThreading(filename, clean_lines, linenum, error): |
1570 """Checks for calls to thread-unsafe functions. | 1747 """Checks for calls to thread-unsafe functions. |
1571 | 1748 |
1572 Much code has been originally written without consideration of | 1749 Much code has been originally written without consideration of |
1573 multi-threading. Also, engineers are relying on their old experience; | 1750 multi-threading. Also, engineers are relying on their old experience; |
1574 they have learned posix before threading extensions were added. These | 1751 they have learned posix before threading extensions were added. These |
1575 tests guide the engineers to use thread-safe functions (when using | 1752 tests guide the engineers to use thread-safe functions (when using |
1576 posix directly). | 1753 posix directly). |
1577 | 1754 |
1578 Args: | 1755 Args: |
1579 filename: The name of the current file. | 1756 filename: The name of the current file. |
1580 clean_lines: A CleansedLines instance containing the file. | 1757 clean_lines: A CleansedLines instance containing the file. |
1581 linenum: The number of the line to check. | 1758 linenum: The number of the line to check. |
1582 error: The function to call with any errors found. | 1759 error: The function to call with any errors found. |
1583 """ | 1760 """ |
1584 line = clean_lines.elided[linenum] | 1761 line = clean_lines.elided[linenum] |
1585 for single_thread_function, multithread_safe_function in threading_list: | 1762 for single_thread_func, multithread_safe_func, pattern in _THREADING_LIST: |
1586 ix = line.find(single_thread_function) | 1763 # Additional pattern matching check to confirm that this is the |
1587 # Comparisons made explicit for clarity -- pylint: disable=g-explicit-bool-c
omparison | 1764 # function we are looking for |
1588 if ix >= 0 and (ix == 0 or (not line[ix - 1].isalnum() and | 1765 if Search(pattern, line): |
1589 line[ix - 1] not in ('_', '.', '>'))): | |
1590 error(filename, linenum, 'runtime/threadsafe_fn', 2, | 1766 error(filename, linenum, 'runtime/threadsafe_fn', 2, |
1591 'Consider using ' + multithread_safe_function + | 1767 'Consider using ' + multithread_safe_func + |
1592 '...) instead of ' + single_thread_function + | 1768 '...) instead of ' + single_thread_func + |
1593 '...) for improved thread safety.') | 1769 '...) for improved thread safety.') |
1594 | 1770 |
1595 | 1771 |
1596 def CheckVlogArguments(filename, clean_lines, linenum, error): | 1772 def CheckVlogArguments(filename, clean_lines, linenum, error): |
1597 """Checks that VLOG() is only used for defining a logging level. | 1773 """Checks that VLOG() is only used for defining a logging level. |
1598 | 1774 |
1599 For example, VLOG(2) is correct. VLOG(INFO), VLOG(WARNING), VLOG(ERROR), and | 1775 For example, VLOG(2) is correct. VLOG(INFO), VLOG(WARNING), VLOG(ERROR), and |
1600 VLOG(FATAL) are not. | 1776 VLOG(FATAL) are not. |
1601 | 1777 |
1602 Args: | 1778 Args: |
1603 filename: The name of the current file. | 1779 filename: The name of the current file. |
1604 clean_lines: A CleansedLines instance containing the file. | 1780 clean_lines: A CleansedLines instance containing the file. |
1605 linenum: The number of the line to check. | 1781 linenum: The number of the line to check. |
1606 error: The function to call with any errors found. | 1782 error: The function to call with any errors found. |
1607 """ | 1783 """ |
1608 line = clean_lines.elided[linenum] | 1784 line = clean_lines.elided[linenum] |
1609 if Search(r'\bVLOG\((INFO|ERROR|WARNING|DFATAL|FATAL)\)', line): | 1785 if Search(r'\bVLOG\((INFO|ERROR|WARNING|DFATAL|FATAL)\)', line): |
1610 error(filename, linenum, 'runtime/vlog', 5, | 1786 error(filename, linenum, 'runtime/vlog', 5, |
1611 'VLOG() should be used with numeric verbosity level. ' | 1787 'VLOG() should be used with numeric verbosity level. ' |
1612 'Use LOG() if you want symbolic severity levels.') | 1788 'Use LOG() if you want symbolic severity levels.') |
1613 | 1789 |
1614 | |
1615 # Matches invalid increment: *count++, which moves pointer instead of | 1790 # Matches invalid increment: *count++, which moves pointer instead of |
1616 # incrementing a value. | 1791 # incrementing a value. |
1617 _RE_PATTERN_INVALID_INCREMENT = re.compile( | 1792 _RE_PATTERN_INVALID_INCREMENT = re.compile( |
1618 r'^\s*\*\w+(\+\+|--);') | 1793 r'^\s*\*\w+(\+\+|--);') |
1619 | 1794 |
1620 | 1795 |
1621 def CheckInvalidIncrement(filename, clean_lines, linenum, error): | 1796 def CheckInvalidIncrement(filename, clean_lines, linenum, error): |
1622 """Checks for invalid increment *count++. | 1797 """Checks for invalid increment *count++. |
1623 | 1798 |
1624 For example following function: | 1799 For example following function: |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1669 This is mostly used for checking end of namespace comments. | 1844 This is mostly used for checking end of namespace comments. |
1670 | 1845 |
1671 Args: | 1846 Args: |
1672 filename: The name of the current file. | 1847 filename: The name of the current file. |
1673 clean_lines: A CleansedLines instance containing the file. | 1848 clean_lines: A CleansedLines instance containing the file. |
1674 linenum: The number of the line to check. | 1849 linenum: The number of the line to check. |
1675 error: The function to call with any errors found. | 1850 error: The function to call with any errors found. |
1676 """ | 1851 """ |
1677 pass | 1852 pass |
1678 | 1853 |
| 1854 def IsBlockInfo(self): |
| 1855 """Returns true if this block is a _BlockInfo. |
| 1856 |
| 1857 This is convenient for verifying that an object is an instance of |
| 1858 a _BlockInfo, but not an instance of any of the derived classes. |
| 1859 |
| 1860 Returns: |
| 1861 True for this class, False for derived classes. |
| 1862 """ |
| 1863 return self.__class__ == _BlockInfo |
| 1864 |
| 1865 |
| 1866 class _ExternCInfo(_BlockInfo): |
| 1867 """Stores information about an 'extern "C"' block.""" |
| 1868 |
| 1869 def __init__(self): |
| 1870 _BlockInfo.__init__(self, True) |
| 1871 |
1679 | 1872 |
1680 class _ClassInfo(_BlockInfo): | 1873 class _ClassInfo(_BlockInfo): |
1681 """Stores information about a class.""" | 1874 """Stores information about a class.""" |
1682 | 1875 |
1683 def __init__(self, name, class_or_struct, clean_lines, linenum): | 1876 def __init__(self, name, class_or_struct, clean_lines, linenum): |
1684 _BlockInfo.__init__(self, False) | 1877 _BlockInfo.__init__(self, False) |
1685 self.name = name | 1878 self.name = name |
1686 self.starting_linenum = linenum | 1879 self.starting_linenum = linenum |
1687 self.is_derived = False | 1880 self.is_derived = False |
1688 if class_or_struct == 'struct': | 1881 if class_or_struct == 'struct': |
1689 self.access = 'public' | 1882 self.access = 'public' |
1690 self.is_struct = True | 1883 self.is_struct = True |
1691 else: | 1884 else: |
1692 self.access = 'private' | 1885 self.access = 'private' |
1693 self.is_struct = False | 1886 self.is_struct = False |
1694 | 1887 |
1695 # Remember initial indentation level for this class. Using raw_lines here | 1888 # Remember initial indentation level for this class. Using raw_lines here |
1696 # instead of elided to account for leading comments. | 1889 # instead of elided to account for leading comments. |
1697 initial_indent = Match(r'^( *)\S', clean_lines.raw_lines[linenum]) | 1890 self.class_indent = GetIndentLevel(clean_lines.raw_lines[linenum]) |
1698 if initial_indent: | |
1699 self.class_indent = len(initial_indent.group(1)) | |
1700 else: | |
1701 self.class_indent = 0 | |
1702 | 1891 |
1703 # Try to find the end of the class. This will be confused by things like: | 1892 # Try to find the end of the class. This will be confused by things like: |
1704 # class A { | 1893 # class A { |
1705 # } *x = { ... | 1894 # } *x = { ... |
1706 # | 1895 # |
1707 # But it's still good enough for CheckSectionSpacing. | 1896 # But it's still good enough for CheckSectionSpacing. |
1708 self.last_line = 0 | 1897 self.last_line = 0 |
1709 depth = 0 | 1898 depth = 0 |
1710 for i in range(linenum, clean_lines.NumLines()): | 1899 for i in range(linenum, clean_lines.NumLines()): |
1711 line = clean_lines.elided[i] | 1900 line = clean_lines.elided[i] |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1776 # Named namespace | 1965 # Named namespace |
1777 if not Match((r'};*\s*(//|/\*).*\bnamespace\s+' + re.escape(self.name) + | 1966 if not Match((r'};*\s*(//|/\*).*\bnamespace\s+' + re.escape(self.name) + |
1778 r'[\*/\.\\\s]*$'), | 1967 r'[\*/\.\\\s]*$'), |
1779 line): | 1968 line): |
1780 error(filename, linenum, 'readability/namespace', 5, | 1969 error(filename, linenum, 'readability/namespace', 5, |
1781 'Namespace should be terminated with "// namespace %s"' % | 1970 'Namespace should be terminated with "// namespace %s"' % |
1782 self.name) | 1971 self.name) |
1783 else: | 1972 else: |
1784 # Anonymous namespace | 1973 # Anonymous namespace |
1785 if not Match(r'};*\s*(//|/\*).*\bnamespace[\*/\.\\\s]*$', line): | 1974 if not Match(r'};*\s*(//|/\*).*\bnamespace[\*/\.\\\s]*$', line): |
1786 error(filename, linenum, 'readability/namespace', 5, | 1975 # If "// namespace anonymous" or "// anonymous namespace (more text)", |
1787 'Namespace should be terminated with "// namespace"') | 1976 # mention "// anonymous namespace" as an acceptable form |
| 1977 if Match(r'}.*\b(namespace anonymous|anonymous namespace)\b', line): |
| 1978 error(filename, linenum, 'readability/namespace', 5, |
| 1979 'Anonymous namespace should be terminated with "// namespace"' |
| 1980 ' or "// anonymous namespace"') |
| 1981 else: |
| 1982 error(filename, linenum, 'readability/namespace', 5, |
| 1983 'Anonymous namespace should be terminated with "// namespace"') |
1788 | 1984 |
1789 | 1985 |
1790 class _PreprocessorInfo(object): | 1986 class _PreprocessorInfo(object): |
1791 """Stores checkpoints of nesting stacks when #if/#else is seen.""" | 1987 """Stores checkpoints of nesting stacks when #if/#else is seen.""" |
1792 | 1988 |
1793 def __init__(self, stack_before_if): | 1989 def __init__(self, stack_before_if): |
1794 # The entire nesting stack before #if | 1990 # The entire nesting stack before #if |
1795 self.stack_before_if = stack_before_if | 1991 self.stack_before_if = stack_before_if |
1796 | 1992 |
1797 # The entire nesting stack up to #else | 1993 # The entire nesting stack up to #else |
1798 self.stack_before_else = [] | 1994 self.stack_before_else = [] |
1799 | 1995 |
1800 # Whether we have already seen #else or #elif | 1996 # Whether we have already seen #else or #elif |
1801 self.seen_else = False | 1997 self.seen_else = False |
1802 | 1998 |
1803 | 1999 |
1804 class _NestingState(object): | 2000 class NestingState(object): |
1805 """Holds states related to parsing braces.""" | 2001 """Holds states related to parsing braces.""" |
1806 | 2002 |
1807 def __init__(self): | 2003 def __init__(self): |
1808 # Stack for tracking all braces. An object is pushed whenever we | 2004 # Stack for tracking all braces. An object is pushed whenever we |
1809 # see a "{", and popped when we see a "}". Only 3 types of | 2005 # see a "{", and popped when we see a "}". Only 3 types of |
1810 # objects are possible: | 2006 # objects are possible: |
1811 # - _ClassInfo: a class or struct. | 2007 # - _ClassInfo: a class or struct. |
1812 # - _NamespaceInfo: a namespace. | 2008 # - _NamespaceInfo: a namespace. |
1813 # - _BlockInfo: some other type of block. | 2009 # - _BlockInfo: some other type of block. |
1814 self.stack = [] | 2010 self.stack = [] |
1815 | 2011 |
| 2012 # Top of the previous stack before each Update(). |
| 2013 # |
| 2014 # Because the nesting_stack is updated at the end of each line, we |
| 2015 # had to do some convoluted checks to find out what is the current |
| 2016 # scope at the beginning of the line. This check is simplified by |
| 2017 # saving the previous top of nesting stack. |
| 2018 # |
| 2019 # We could save the full stack, but we only need the top. Copying |
| 2020 # the full nesting stack would slow down cpplint by ~10%. |
| 2021 self.previous_stack_top = [] |
| 2022 |
1816 # Stack of _PreprocessorInfo objects. | 2023 # Stack of _PreprocessorInfo objects. |
1817 self.pp_stack = [] | 2024 self.pp_stack = [] |
1818 | 2025 |
1819 def SeenOpenBrace(self): | 2026 def SeenOpenBrace(self): |
1820 """Check if we have seen the opening brace for the innermost block. | 2027 """Check if we have seen the opening brace for the innermost block. |
1821 | 2028 |
1822 Returns: | 2029 Returns: |
1823 True if we have seen the opening brace, False if the innermost | 2030 True if we have seen the opening brace, False if the innermost |
1824 block is still expecting an opening brace. | 2031 block is still expecting an opening brace. |
1825 """ | 2032 """ |
1826 return (not self.stack) or self.stack[-1].seen_open_brace | 2033 return (not self.stack) or self.stack[-1].seen_open_brace |
1827 | 2034 |
1828 def InNamespaceBody(self): | 2035 def InNamespaceBody(self): |
1829 """Check if we are currently one level inside a namespace body. | 2036 """Check if we are currently one level inside a namespace body. |
1830 | 2037 |
1831 Returns: | 2038 Returns: |
1832 True if top of the stack is a namespace block, False otherwise. | 2039 True if top of the stack is a namespace block, False otherwise. |
1833 """ | 2040 """ |
1834 return self.stack and isinstance(self.stack[-1], _NamespaceInfo) | 2041 return self.stack and isinstance(self.stack[-1], _NamespaceInfo) |
1835 | 2042 |
| 2043 def InExternC(self): |
| 2044 """Check if we are currently one level inside an 'extern "C"' block. |
| 2045 |
| 2046 Returns: |
| 2047 True if top of the stack is an extern block, False otherwise. |
| 2048 """ |
| 2049 return self.stack and isinstance(self.stack[-1], _ExternCInfo) |
| 2050 |
| 2051 def InClassDeclaration(self): |
| 2052 """Check if we are currently one level inside a class or struct declaration. |
| 2053 |
| 2054 Returns: |
| 2055 True if top of the stack is a class/struct, False otherwise. |
| 2056 """ |
| 2057 return self.stack and isinstance(self.stack[-1], _ClassInfo) |
| 2058 |
| 2059 def InAsmBlock(self): |
| 2060 """Check if we are currently one level inside an inline ASM block. |
| 2061 |
| 2062 Returns: |
| 2063 True if the top of the stack is a block containing inline ASM. |
| 2064 """ |
| 2065 return self.stack and self.stack[-1].inline_asm != _NO_ASM |
| 2066 |
| 2067 def InTemplateArgumentList(self, clean_lines, linenum, pos): |
| 2068 """Check if current position is inside template argument list. |
| 2069 |
| 2070 Args: |
| 2071 clean_lines: A CleansedLines instance containing the file. |
| 2072 linenum: The number of the line to check. |
| 2073 pos: position just after the suspected template argument. |
| 2074 Returns: |
| 2075 True if (linenum, pos) is inside template arguments. |
| 2076 """ |
| 2077 while linenum < clean_lines.NumLines(): |
| 2078 # Find the earliest character that might indicate a template argument |
| 2079 line = clean_lines.elided[linenum] |
| 2080 match = Match(r'^[^{};=\[\]\.<>]*(.)', line[pos:]) |
| 2081 if not match: |
| 2082 linenum += 1 |
| 2083 pos = 0 |
| 2084 continue |
| 2085 token = match.group(1) |
| 2086 pos += len(match.group(0)) |
| 2087 |
| 2088 # These things do not look like template argument list: |
| 2089 # class Suspect { |
| 2090 # class Suspect x; } |
| 2091 if token in ('{', '}', ';'): return False |
| 2092 |
| 2093 # These things look like template argument list: |
| 2094 # template <class Suspect> |
| 2095 # template <class Suspect = default_value> |
| 2096 # template <class Suspect[]> |
| 2097 # template <class Suspect...> |
| 2098 if token in ('>', '=', '[', ']', '.'): return True |
| 2099 |
| 2100 # Check if token is an unmatched '<'. |
| 2101 # If not, move on to the next character. |
| 2102 if token != '<': |
| 2103 pos += 1 |
| 2104 if pos >= len(line): |
| 2105 linenum += 1 |
| 2106 pos = 0 |
| 2107 continue |
| 2108 |
| 2109 # We can't be sure if we just find a single '<', and need to |
| 2110 # find the matching '>'. |
| 2111 (_, end_line, end_pos) = CloseExpression(clean_lines, linenum, pos - 1) |
| 2112 if end_pos < 0: |
| 2113 # Not sure if template argument list or syntax error in file |
| 2114 return False |
| 2115 linenum = end_line |
| 2116 pos = end_pos |
| 2117 return False |
| 2118 |
1836 def UpdatePreprocessor(self, line): | 2119 def UpdatePreprocessor(self, line): |
1837 """Update preprocessor stack. | 2120 """Update preprocessor stack. |
1838 | 2121 |
1839 We need to handle preprocessors due to classes like this: | 2122 We need to handle preprocessors due to classes like this: |
1840 #ifdef SWIG | 2123 #ifdef SWIG |
1841 struct ResultDetailsPageElementExtensionPoint { | 2124 struct ResultDetailsPageElementExtensionPoint { |
1842 #else | 2125 #else |
1843 struct ResultDetailsPageElementExtensionPoint : public Extension { | 2126 struct ResultDetailsPageElementExtensionPoint : public Extension { |
1844 #endif | 2127 #endif |
1845 | 2128 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1882 if self.pp_stack[-1].seen_else: | 2165 if self.pp_stack[-1].seen_else: |
1883 # Here we can just use a shallow copy since we are the last | 2166 # Here we can just use a shallow copy since we are the last |
1884 # reference to it. | 2167 # reference to it. |
1885 self.stack = self.pp_stack[-1].stack_before_else | 2168 self.stack = self.pp_stack[-1].stack_before_else |
1886 # Drop the corresponding #if | 2169 # Drop the corresponding #if |
1887 self.pp_stack.pop() | 2170 self.pp_stack.pop() |
1888 else: | 2171 else: |
1889 # TODO(unknown): unexpected #endif, issue warning? | 2172 # TODO(unknown): unexpected #endif, issue warning? |
1890 pass | 2173 pass |
1891 | 2174 |
| 2175 # TODO(unknown): Update() is too long, but we will refactor later. |
1892 def Update(self, filename, clean_lines, linenum, error): | 2176 def Update(self, filename, clean_lines, linenum, error): |
1893 """Update nesting state with current line. | 2177 """Update nesting state with current line. |
1894 | 2178 |
1895 Args: | 2179 Args: |
1896 filename: The name of the current file. | 2180 filename: The name of the current file. |
1897 clean_lines: A CleansedLines instance containing the file. | 2181 clean_lines: A CleansedLines instance containing the file. |
1898 linenum: The number of the line to check. | 2182 linenum: The number of the line to check. |
1899 error: The function to call with any errors found. | 2183 error: The function to call with any errors found. |
1900 """ | 2184 """ |
1901 line = clean_lines.elided[linenum] | 2185 line = clean_lines.elided[linenum] |
1902 | 2186 |
1903 # Update pp_stack first | 2187 # Remember top of the previous nesting stack. |
| 2188 # |
| 2189 # The stack is always pushed/popped and not modified in place, so |
| 2190 # we can just do a shallow copy instead of copy.deepcopy. Using |
| 2191 # deepcopy would slow down cpplint by ~28%. |
| 2192 if self.stack: |
| 2193 self.previous_stack_top = self.stack[-1] |
| 2194 else: |
| 2195 self.previous_stack_top = None |
| 2196 |
| 2197 # Update pp_stack |
1904 self.UpdatePreprocessor(line) | 2198 self.UpdatePreprocessor(line) |
1905 | 2199 |
1906 # Count parentheses. This is to avoid adding struct arguments to | 2200 # Count parentheses. This is to avoid adding struct arguments to |
1907 # the nesting stack. | 2201 # the nesting stack. |
1908 if self.stack: | 2202 if self.stack: |
1909 inner_block = self.stack[-1] | 2203 inner_block = self.stack[-1] |
1910 depth_change = line.count('(') - line.count(')') | 2204 depth_change = line.count('(') - line.count(')') |
1911 inner_block.open_parentheses += depth_change | 2205 inner_block.open_parentheses += depth_change |
1912 | 2206 |
1913 # Also check if we are starting or ending an inline assembly block. | 2207 # Also check if we are starting or ending an inline assembly block. |
(...skipping 30 matching lines...) Expand all Loading... |
1944 line = namespace_decl_match.group(2) | 2238 line = namespace_decl_match.group(2) |
1945 if line.find('{') != -1: | 2239 if line.find('{') != -1: |
1946 new_namespace.seen_open_brace = True | 2240 new_namespace.seen_open_brace = True |
1947 line = line[line.find('{') + 1:] | 2241 line = line[line.find('{') + 1:] |
1948 | 2242 |
1949 # Look for a class declaration in whatever is left of the line | 2243 # Look for a class declaration in whatever is left of the line |
1950 # after parsing namespaces. The regexp accounts for decorated classes | 2244 # after parsing namespaces. The regexp accounts for decorated classes |
1951 # such as in: | 2245 # such as in: |
1952 # class LOCKABLE API Object { | 2246 # class LOCKABLE API Object { |
1953 # }; | 2247 # }; |
1954 # | |
1955 # Templates with class arguments may confuse the parser, for example: | |
1956 # template <class T | |
1957 # class Comparator = less<T>, | |
1958 # class Vector = vector<T> > | |
1959 # class HeapQueue { | |
1960 # | |
1961 # Because this parser has no nesting state about templates, by the | |
1962 # time it saw "class Comparator", it may think that it's a new class. | |
1963 # Nested templates have a similar problem: | |
1964 # template < | |
1965 # typename ExportedType, | |
1966 # typename TupleType, | |
1967 # template <typename, typename> class ImplTemplate> | |
1968 # | |
1969 # To avoid these cases, we ignore classes that are followed by '=' or '>' | |
1970 class_decl_match = Match( | 2248 class_decl_match = Match( |
1971 r'\s*(template\s*<[\w\s<>,:]*>\s*)?' | 2249 r'^(\s*(?:template\s*<[\w\s<>,:]*>\s*)?' |
1972 r'(class|struct)\s+([A-Z_]+\s+)*(\w+(?:::\w+)*)' | 2250 r'(class|struct)\s+(?:[A-Z_]+\s+)*(\w+(?:::\w+)*))' |
1973 r'(([^=>]|<[^<>]*>|<[^<>]*<[^<>]*>\s*>)*)$', line) | 2251 r'(.*)$', line) |
1974 if (class_decl_match and | 2252 if (class_decl_match and |
1975 (not self.stack or self.stack[-1].open_parentheses == 0)): | 2253 (not self.stack or self.stack[-1].open_parentheses == 0)): |
1976 self.stack.append(_ClassInfo( | 2254 # We do not want to accept classes that are actually template arguments: |
1977 class_decl_match.group(4), class_decl_match.group(2), | 2255 # template <class Ignore1, |
1978 clean_lines, linenum)) | 2256 # class Ignore2 = Default<Args>, |
1979 line = class_decl_match.group(5) | 2257 # template <Args> class Ignore3> |
| 2258 # void Function() {}; |
| 2259 # |
| 2260 # To avoid template argument cases, we scan forward and look for |
| 2261 # an unmatched '>'. If we see one, assume we are inside a |
| 2262 # template argument list. |
| 2263 end_declaration = len(class_decl_match.group(1)) |
| 2264 if not self.InTemplateArgumentList(clean_lines, linenum, end_declaration): |
| 2265 self.stack.append(_ClassInfo( |
| 2266 class_decl_match.group(3), class_decl_match.group(2), |
| 2267 clean_lines, linenum)) |
| 2268 line = class_decl_match.group(4) |
1980 | 2269 |
1981 # If we have not yet seen the opening brace for the innermost block, | 2270 # If we have not yet seen the opening brace for the innermost block, |
1982 # run checks here. | 2271 # run checks here. |
1983 if not self.SeenOpenBrace(): | 2272 if not self.SeenOpenBrace(): |
1984 self.stack[-1].CheckBegin(filename, clean_lines, linenum, error) | 2273 self.stack[-1].CheckBegin(filename, clean_lines, linenum, error) |
1985 | 2274 |
1986 # Update access control if we are inside a class/struct | 2275 # Update access control if we are inside a class/struct |
1987 if self.stack and isinstance(self.stack[-1], _ClassInfo): | 2276 if self.stack and isinstance(self.stack[-1], _ClassInfo): |
1988 classinfo = self.stack[-1] | 2277 classinfo = self.stack[-1] |
1989 access_match = Match( | 2278 access_match = Match( |
(...skipping 26 matching lines...) Expand all Loading... |
2016 if not matched: | 2305 if not matched: |
2017 break | 2306 break |
2018 | 2307 |
2019 token = matched.group(1) | 2308 token = matched.group(1) |
2020 if token == '{': | 2309 if token == '{': |
2021 # If namespace or class hasn't seen a opening brace yet, mark | 2310 # If namespace or class hasn't seen a opening brace yet, mark |
2022 # namespace/class head as complete. Push a new block onto the | 2311 # namespace/class head as complete. Push a new block onto the |
2023 # stack otherwise. | 2312 # stack otherwise. |
2024 if not self.SeenOpenBrace(): | 2313 if not self.SeenOpenBrace(): |
2025 self.stack[-1].seen_open_brace = True | 2314 self.stack[-1].seen_open_brace = True |
| 2315 elif Match(r'^extern\s*"[^"]*"\s*\{', line): |
| 2316 self.stack.append(_ExternCInfo()) |
2026 else: | 2317 else: |
2027 self.stack.append(_BlockInfo(True)) | 2318 self.stack.append(_BlockInfo(True)) |
2028 if _MATCH_ASM.match(line): | 2319 if _MATCH_ASM.match(line): |
2029 self.stack[-1].inline_asm = _BLOCK_ASM | 2320 self.stack[-1].inline_asm = _BLOCK_ASM |
| 2321 |
2030 elif token == ';' or token == ')': | 2322 elif token == ';' or token == ')': |
2031 # If we haven't seen an opening brace yet, but we already saw | 2323 # If we haven't seen an opening brace yet, but we already saw |
2032 # a semicolon, this is probably a forward declaration. Pop | 2324 # a semicolon, this is probably a forward declaration. Pop |
2033 # the stack for these. | 2325 # the stack for these. |
2034 # | 2326 # |
2035 # Similarly, if we haven't seen an opening brace yet, but we | 2327 # Similarly, if we haven't seen an opening brace yet, but we |
2036 # already saw a closing parenthesis, then these are probably | 2328 # already saw a closing parenthesis, then these are probably |
2037 # function arguments with extra "class" or "struct" keywords. | 2329 # function arguments with extra "class" or "struct" keywords. |
2038 # Also pop these stack for these. | 2330 # Also pop these stack for these. |
2039 if not self.SeenOpenBrace(): | 2331 if not self.SeenOpenBrace(): |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2095 - >? and <? operators, and their >?= and <?= cousins. | 2387 - >? and <? operators, and their >?= and <?= cousins. |
2096 | 2388 |
2097 Additionally, check for constructor/destructor style violations and reference | 2389 Additionally, check for constructor/destructor style violations and reference |
2098 members, as it is very convenient to do so while checking for | 2390 members, as it is very convenient to do so while checking for |
2099 gcc-2 compliance. | 2391 gcc-2 compliance. |
2100 | 2392 |
2101 Args: | 2393 Args: |
2102 filename: The name of the current file. | 2394 filename: The name of the current file. |
2103 clean_lines: A CleansedLines instance containing the file. | 2395 clean_lines: A CleansedLines instance containing the file. |
2104 linenum: The number of the line to check. | 2396 linenum: The number of the line to check. |
2105 nesting_state: A _NestingState instance which maintains information about | 2397 nesting_state: A NestingState instance which maintains information about |
2106 the current stack of nested blocks being parsed. | 2398 the current stack of nested blocks being parsed. |
2107 error: A callable to which errors are reported, which takes 4 arguments: | 2399 error: A callable to which errors are reported, which takes 4 arguments: |
2108 filename, line number, error level, and message | 2400 filename, line number, error level, and message |
2109 """ | 2401 """ |
2110 | 2402 |
2111 # Remove comments from the line, but leave in strings for now. | 2403 # Remove comments from the line, but leave in strings for now. |
2112 line = clean_lines.lines[linenum] | 2404 line = clean_lines.lines[linenum] |
2113 | 2405 |
2114 if Search(r'printf\s*\(.*".*%[-+ ]?\d*q', line): | 2406 if Search(r'printf\s*\(.*".*%[-+ ]?\d*q', line): |
2115 error(filename, linenum, 'runtime/printf_format', 3, | 2407 error(filename, linenum, 'runtime/printf_format', 3, |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2173 # The constructor and destructor will not have those qualifiers. | 2465 # The constructor and destructor will not have those qualifiers. |
2174 base_classname = classinfo.name.split('::')[-1] | 2466 base_classname = classinfo.name.split('::')[-1] |
2175 | 2467 |
2176 # Look for single-argument constructors that aren't marked explicit. | 2468 # Look for single-argument constructors that aren't marked explicit. |
2177 # Technically a valid construct, but against style. | 2469 # Technically a valid construct, but against style. |
2178 args = Match(r'\s+(?:inline\s+)?%s\s*\(([^,()]+)\)' | 2470 args = Match(r'\s+(?:inline\s+)?%s\s*\(([^,()]+)\)' |
2179 % re.escape(base_classname), | 2471 % re.escape(base_classname), |
2180 line) | 2472 line) |
2181 if (args and | 2473 if (args and |
2182 args.group(1) != 'void' and | 2474 args.group(1) != 'void' and |
| 2475 not Search(r'\bstd::initializer_list\b', args.group(1)) and |
2183 not Match(r'(const\s+)?%s(\s+const)?\s*(?:<\w+>\s*)?&' | 2476 not Match(r'(const\s+)?%s(\s+const)?\s*(?:<\w+>\s*)?&' |
2184 % re.escape(base_classname), args.group(1).strip())): | 2477 % re.escape(base_classname), args.group(1).strip())): |
2185 error(filename, linenum, 'runtime/explicit', 5, | 2478 error(filename, linenum, 'runtime/explicit', 5, |
2186 'Single-argument constructors should be marked explicit.') | 2479 'Single-argument constructors should be marked explicit.') |
2187 | 2480 |
2188 | 2481 |
2189 def CheckSpacingForFunctionCall(filename, line, linenum, error): | 2482 def CheckSpacingForFunctionCall(filename, clean_lines, linenum, error): |
2190 """Checks for the correctness of various spacing around function calls. | 2483 """Checks for the correctness of various spacing around function calls. |
2191 | 2484 |
2192 Args: | 2485 Args: |
2193 filename: The name of the current file. | 2486 filename: The name of the current file. |
2194 line: The text of the line to check. | 2487 clean_lines: A CleansedLines instance containing the file. |
2195 linenum: The number of the line to check. | 2488 linenum: The number of the line to check. |
2196 error: The function to call with any errors found. | 2489 error: The function to call with any errors found. |
2197 """ | 2490 """ |
| 2491 line = clean_lines.elided[linenum] |
2198 | 2492 |
2199 # Since function calls often occur inside if/for/while/switch | 2493 # Since function calls often occur inside if/for/while/switch |
2200 # expressions - which have their own, more liberal conventions - we | 2494 # expressions - which have their own, more liberal conventions - we |
2201 # first see if we should be looking inside such an expression for a | 2495 # first see if we should be looking inside such an expression for a |
2202 # function call, to which we can apply more strict standards. | 2496 # function call, to which we can apply more strict standards. |
2203 fncall = line # if there's no control flow construct, look at whole line | 2497 fncall = line # if there's no control flow construct, look at whole line |
2204 for pattern in (r'\bif\s*\((.*)\)\s*{', | 2498 for pattern in (r'\bif\s*\((.*)\)\s*{', |
2205 r'\bfor\s*\((.*)\)\s*{', | 2499 r'\bfor\s*\((.*)\)\s*{', |
2206 r'\bwhile\s*\((.*)\)\s*[{;]', | 2500 r'\bwhile\s*\((.*)\)\s*[{;]', |
2207 r'\bswitch\s*\((.*)\)\s*{'): | 2501 r'\bswitch\s*\((.*)\)\s*{'): |
(...skipping 22 matching lines...) Expand all Loading... |
2230 not Search(r' \([^)]+\)\([^)]*(\)|,$)', fncall) and | 2524 not Search(r' \([^)]+\)\([^)]*(\)|,$)', fncall) and |
2231 # Ignore pointers/references to arrays. | 2525 # Ignore pointers/references to arrays. |
2232 not Search(r' \([^)]+\)\[[^\]]+\]', fncall)): | 2526 not Search(r' \([^)]+\)\[[^\]]+\]', fncall)): |
2233 if Search(r'\w\s*\(\s(?!\s*\\$)', fncall): # a ( used for a fn call | 2527 if Search(r'\w\s*\(\s(?!\s*\\$)', fncall): # a ( used for a fn call |
2234 error(filename, linenum, 'whitespace/parens', 4, | 2528 error(filename, linenum, 'whitespace/parens', 4, |
2235 'Extra space after ( in function call') | 2529 'Extra space after ( in function call') |
2236 elif Search(r'\(\s+(?!(\s*\\)|\()', fncall): | 2530 elif Search(r'\(\s+(?!(\s*\\)|\()', fncall): |
2237 error(filename, linenum, 'whitespace/parens', 2, | 2531 error(filename, linenum, 'whitespace/parens', 2, |
2238 'Extra space after (') | 2532 'Extra space after (') |
2239 if (Search(r'\w\s+\(', fncall) and | 2533 if (Search(r'\w\s+\(', fncall) and |
2240 not Search(r'#\s*define|typedef', fncall) and | 2534 not Search(r'#\s*define|typedef|using\s+\w+\s*=', fncall) and |
2241 not Search(r'\w\s+\((\w+::)*\*\w+\)\(', fncall)): | 2535 not Search(r'\w\s+\((\w+::)*\*\w+\)\(', fncall)): |
2242 error(filename, linenum, 'whitespace/parens', 4, | 2536 # TODO(unknown): Space after an operator function seem to be a common |
2243 'Extra space before ( in function call') | 2537 # error, silence those for now by restricting them to highest verbosity. |
| 2538 if Search(r'\boperator_*\b', line): |
| 2539 error(filename, linenum, 'whitespace/parens', 0, |
| 2540 'Extra space before ( in function call') |
| 2541 else: |
| 2542 error(filename, linenum, 'whitespace/parens', 4, |
| 2543 'Extra space before ( in function call') |
2244 # If the ) is followed only by a newline or a { + newline, assume it's | 2544 # If the ) is followed only by a newline or a { + newline, assume it's |
2245 # part of a control statement (if/while/etc), and don't complain | 2545 # part of a control statement (if/while/etc), and don't complain |
2246 if Search(r'[^)]\s+\)\s*[^{\s]', fncall): | 2546 if Search(r'[^)]\s+\)\s*[^{\s]', fncall): |
2247 # If the closing parenthesis is preceded by only whitespaces, | 2547 # If the closing parenthesis is preceded by only whitespaces, |
2248 # try to give a more descriptive error message. | 2548 # try to give a more descriptive error message. |
2249 if Search(r'^\s+\)', fncall): | 2549 if Search(r'^\s+\)', fncall): |
2250 error(filename, linenum, 'whitespace/parens', 2, | 2550 error(filename, linenum, 'whitespace/parens', 2, |
2251 'Closing ) should be moved to the previous line') | 2551 'Closing ) should be moved to the previous line') |
2252 else: | 2552 else: |
2253 error(filename, linenum, 'whitespace/parens', 2, | 2553 error(filename, linenum, 'whitespace/parens', 2, |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2287 | 2587 |
2288 Args: | 2588 Args: |
2289 filename: The name of the current file. | 2589 filename: The name of the current file. |
2290 clean_lines: A CleansedLines instance containing the file. | 2590 clean_lines: A CleansedLines instance containing the file. |
2291 linenum: The number of the line to check. | 2591 linenum: The number of the line to check. |
2292 function_state: Current function name and lines in body so far. | 2592 function_state: Current function name and lines in body so far. |
2293 error: The function to call with any errors found. | 2593 error: The function to call with any errors found. |
2294 """ | 2594 """ |
2295 lines = clean_lines.lines | 2595 lines = clean_lines.lines |
2296 line = lines[linenum] | 2596 line = lines[linenum] |
2297 raw = clean_lines.raw_lines | |
2298 raw_line = raw[linenum] | |
2299 joined_line = '' | 2597 joined_line = '' |
2300 | 2598 |
2301 starting_func = False | 2599 starting_func = False |
2302 regexp = r'(\w(\w|::|\*|\&|\s)*)\(' # decls * & space::name( ... | 2600 regexp = r'(\w(\w|::|\*|\&|\s)*)\(' # decls * & space::name( ... |
2303 match_result = Match(regexp, line) | 2601 match_result = Match(regexp, line) |
2304 if match_result: | 2602 if match_result: |
2305 # If the name is all caps and underscores, figure it's a macro and | 2603 # If the name is all caps and underscores, figure it's a macro and |
2306 # ignore it, unless it's TEST or TEST_F. | 2604 # ignore it, unless it's TEST or TEST_F. |
2307 function_name = match_result.group(1).split()[-1] | 2605 function_name = match_result.group(1).split()[-1] |
2308 if function_name == 'TEST' or function_name == 'TEST_F' or ( | 2606 if function_name == 'TEST' or function_name == 'TEST_F' or ( |
(...skipping 26 matching lines...) Expand all Loading... |
2335 elif Match(r'^\}\s*$', line): # function end | 2633 elif Match(r'^\}\s*$', line): # function end |
2336 function_state.Check(error, filename, linenum) | 2634 function_state.Check(error, filename, linenum) |
2337 function_state.End() | 2635 function_state.End() |
2338 elif not Match(r'^\s*$', line): | 2636 elif not Match(r'^\s*$', line): |
2339 function_state.Count() # Count non-blank/non-comment lines. | 2637 function_state.Count() # Count non-blank/non-comment lines. |
2340 | 2638 |
2341 | 2639 |
2342 _RE_PATTERN_TODO = re.compile(r'^//(\s*)TODO(\(.+?\))?:?(\s|$)?') | 2640 _RE_PATTERN_TODO = re.compile(r'^//(\s*)TODO(\(.+?\))?:?(\s|$)?') |
2343 | 2641 |
2344 | 2642 |
2345 def CheckComment(comment, filename, linenum, error): | 2643 def CheckComment(line, filename, linenum, next_line_start, error): |
2346 """Checks for common mistakes in TODO comments. | 2644 """Checks for common mistakes in comments. |
2347 | 2645 |
2348 Args: | 2646 Args: |
2349 comment: The text of the comment from the line in question. | 2647 line: The line in question. |
2350 filename: The name of the current file. | 2648 filename: The name of the current file. |
2351 linenum: The number of the line to check. | 2649 linenum: The number of the line to check. |
| 2650 next_line_start: The first non-whitespace column of the next line. |
2352 error: The function to call with any errors found. | 2651 error: The function to call with any errors found. |
2353 """ | 2652 """ |
2354 match = _RE_PATTERN_TODO.match(comment) | 2653 commentpos = line.find('//') |
2355 if match: | 2654 if commentpos != -1: |
2356 # One whitespace is correct; zero whitespace is handled elsewhere. | 2655 # Check if the // may be in quotes. If so, ignore it |
2357 leading_whitespace = match.group(1) | 2656 # Comparisons made explicit for clarity -- pylint: disable=g-explicit-bool-c
omparison |
2358 if len(leading_whitespace) > 1: | 2657 if (line.count('"', 0, commentpos) - |
2359 error(filename, linenum, 'whitespace/todo', 2, | 2658 line.count('\\"', 0, commentpos)) % 2 == 0: # not in quotes |
2360 'Too many spaces before TODO') | 2659 # Allow one space for new scopes, two spaces otherwise: |
| 2660 if (not (Match(r'^.*{ *//', line) and next_line_start == commentpos) and |
| 2661 ((commentpos >= 1 and |
| 2662 line[commentpos-1] not in string.whitespace) or |
| 2663 (commentpos >= 2 and |
| 2664 line[commentpos-2] not in string.whitespace))): |
| 2665 error(filename, linenum, 'whitespace/comments', 2, |
| 2666 'At least two spaces is best between code and comments') |
2361 | 2667 |
2362 username = match.group(2) | 2668 # Checks for common mistakes in TODO comments. |
2363 if not username: | 2669 comment = line[commentpos:] |
2364 error(filename, linenum, 'readability/todo', 2, | 2670 match = _RE_PATTERN_TODO.match(comment) |
2365 'Missing username in TODO; it should look like ' | 2671 if match: |
2366 '"// TODO(my_username): Stuff."') | 2672 # One whitespace is correct; zero whitespace is handled elsewhere. |
| 2673 leading_whitespace = match.group(1) |
| 2674 if len(leading_whitespace) > 1: |
| 2675 error(filename, linenum, 'whitespace/todo', 2, |
| 2676 'Too many spaces before TODO') |
2367 | 2677 |
2368 middle_whitespace = match.group(3) | 2678 username = match.group(2) |
2369 # Comparisons made explicit for correctness -- pylint: disable=g-explicit-bo
ol-comparison | 2679 if not username: |
2370 if middle_whitespace != ' ' and middle_whitespace != '': | 2680 error(filename, linenum, 'readability/todo', 2, |
2371 error(filename, linenum, 'whitespace/todo', 2, | 2681 'Missing username in TODO; it should look like ' |
2372 'TODO(my_username) should be followed by a space') | 2682 '"// TODO(my_username): Stuff."') |
| 2683 |
| 2684 middle_whitespace = match.group(3) |
| 2685 # Comparisons made explicit for correctness -- pylint: disable=g-explici
t-bool-comparison |
| 2686 if middle_whitespace != ' ' and middle_whitespace != '': |
| 2687 error(filename, linenum, 'whitespace/todo', 2, |
| 2688 'TODO(my_username) should be followed by a space') |
| 2689 |
| 2690 # If the comment contains an alphanumeric character, there |
| 2691 # should be a space somewhere between it and the //. |
| 2692 if Match(r'//[^ ]*\w', comment): |
| 2693 error(filename, linenum, 'whitespace/comments', 4, |
| 2694 'Should have a space between // and comment') |
2373 | 2695 |
2374 def CheckAccess(filename, clean_lines, linenum, nesting_state, error): | 2696 def CheckAccess(filename, clean_lines, linenum, nesting_state, error): |
2375 """Checks for improper use of DISALLOW* macros. | 2697 """Checks for improper use of DISALLOW* macros. |
2376 | 2698 |
2377 Args: | 2699 Args: |
2378 filename: The name of the current file. | 2700 filename: The name of the current file. |
2379 clean_lines: A CleansedLines instance containing the file. | 2701 clean_lines: A CleansedLines instance containing the file. |
2380 linenum: The number of the line to check. | 2702 linenum: The number of the line to check. |
2381 nesting_state: A _NestingState instance which maintains information about | 2703 nesting_state: A NestingState instance which maintains information about |
2382 the current stack of nested blocks being parsed. | 2704 the current stack of nested blocks being parsed. |
2383 error: The function to call with any errors found. | 2705 error: The function to call with any errors found. |
2384 """ | 2706 """ |
2385 line = clean_lines.elided[linenum] # get rid of comments and strings | 2707 line = clean_lines.elided[linenum] # get rid of comments and strings |
2386 | 2708 |
2387 matched = Match((r'\s*(DISALLOW_COPY_AND_ASSIGN|' | 2709 matched = Match((r'\s*(DISALLOW_COPY_AND_ASSIGN|' |
2388 r'DISALLOW_EVIL_CONSTRUCTORS|' | 2710 r'DISALLOW_EVIL_CONSTRUCTORS|' |
2389 r'DISALLOW_IMPLICIT_CONSTRUCTORS)'), line) | 2711 r'DISALLOW_IMPLICIT_CONSTRUCTORS)'), line) |
2390 if not matched: | 2712 if not matched: |
2391 return | 2713 return |
2392 if nesting_state.stack and isinstance(nesting_state.stack[-1], _ClassInfo): | 2714 if nesting_state.stack and isinstance(nesting_state.stack[-1], _ClassInfo): |
2393 if nesting_state.stack[-1].access != 'private': | 2715 if nesting_state.stack[-1].access != 'private': |
2394 error(filename, linenum, 'readability/constructors', 3, | 2716 error(filename, linenum, 'readability/constructors', 3, |
2395 '%s must be in the private: section' % matched.group(1)) | 2717 '%s must be in the private: section' % matched.group(1)) |
2396 | 2718 |
2397 else: | 2719 else: |
2398 # Found DISALLOW* macro outside a class declaration, or perhaps it | 2720 # Found DISALLOW* macro outside a class declaration, or perhaps it |
2399 # was used inside a function when it should have been part of the | 2721 # was used inside a function when it should have been part of the |
2400 # class declaration. We could issue a warning here, but it | 2722 # class declaration. We could issue a warning here, but it |
2401 # probably resulted in a compiler error already. | 2723 # probably resulted in a compiler error already. |
2402 pass | 2724 pass |
2403 | 2725 |
2404 | 2726 |
2405 def FindNextMatchingAngleBracket(clean_lines, linenum, init_suffix): | |
2406 """Find the corresponding > to close a template. | |
2407 | |
2408 Args: | |
2409 clean_lines: A CleansedLines instance containing the file. | |
2410 linenum: Current line number. | |
2411 init_suffix: Remainder of the current line after the initial <. | |
2412 | |
2413 Returns: | |
2414 True if a matching bracket exists. | |
2415 """ | |
2416 line = init_suffix | |
2417 nesting_stack = ['<'] | |
2418 while True: | |
2419 # Find the next operator that can tell us whether < is used as an | |
2420 # opening bracket or as a less-than operator. We only want to | |
2421 # warn on the latter case. | |
2422 # | |
2423 # We could also check all other operators and terminate the search | |
2424 # early, e.g. if we got something like this "a<b+c", the "<" is | |
2425 # most likely a less-than operator, but then we will get false | |
2426 # positives for default arguments and other template expressions. | |
2427 match = Search(r'^[^<>(),;\[\]]*([<>(),;\[\]])(.*)$', line) | |
2428 if match: | |
2429 # Found an operator, update nesting stack | |
2430 operator = match.group(1) | |
2431 line = match.group(2) | |
2432 | |
2433 if nesting_stack[-1] == '<': | |
2434 # Expecting closing angle bracket | |
2435 if operator in ('<', '(', '['): | |
2436 nesting_stack.append(operator) | |
2437 elif operator == '>': | |
2438 nesting_stack.pop() | |
2439 if not nesting_stack: | |
2440 # Found matching angle bracket | |
2441 return True | |
2442 elif operator == ',': | |
2443 # Got a comma after a bracket, this is most likely a template | |
2444 # argument. We have not seen a closing angle bracket yet, but | |
2445 # it's probably a few lines later if we look for it, so just | |
2446 # return early here. | |
2447 return True | |
2448 else: | |
2449 # Got some other operator. | |
2450 return False | |
2451 | |
2452 else: | |
2453 # Expecting closing parenthesis or closing bracket | |
2454 if operator in ('<', '(', '['): | |
2455 nesting_stack.append(operator) | |
2456 elif operator in (')', ']'): | |
2457 # We don't bother checking for matching () or []. If we got | |
2458 # something like (] or [), it would have been a syntax error. | |
2459 nesting_stack.pop() | |
2460 | |
2461 else: | |
2462 # Scan the next line | |
2463 linenum += 1 | |
2464 if linenum >= len(clean_lines.elided): | |
2465 break | |
2466 line = clean_lines.elided[linenum] | |
2467 | |
2468 # Exhausted all remaining lines and still no matching angle bracket. | |
2469 # Most likely the input was incomplete, otherwise we should have | |
2470 # seen a semicolon and returned early. | |
2471 return True | |
2472 | |
2473 | |
2474 def FindPreviousMatchingAngleBracket(clean_lines, linenum, init_prefix): | |
2475 """Find the corresponding < that started a template. | |
2476 | |
2477 Args: | |
2478 clean_lines: A CleansedLines instance containing the file. | |
2479 linenum: Current line number. | |
2480 init_prefix: Part of the current line before the initial >. | |
2481 | |
2482 Returns: | |
2483 True if a matching bracket exists. | |
2484 """ | |
2485 line = init_prefix | |
2486 nesting_stack = ['>'] | |
2487 while True: | |
2488 # Find the previous operator | |
2489 match = Search(r'^(.*)([<>(),;\[\]])[^<>(),;\[\]]*$', line) | |
2490 if match: | |
2491 # Found an operator, update nesting stack | |
2492 operator = match.group(2) | |
2493 line = match.group(1) | |
2494 | |
2495 if nesting_stack[-1] == '>': | |
2496 # Expecting opening angle bracket | |
2497 if operator in ('>', ')', ']'): | |
2498 nesting_stack.append(operator) | |
2499 elif operator == '<': | |
2500 nesting_stack.pop() | |
2501 if not nesting_stack: | |
2502 # Found matching angle bracket | |
2503 return True | |
2504 elif operator == ',': | |
2505 # Got a comma before a bracket, this is most likely a | |
2506 # template argument. The opening angle bracket is probably | |
2507 # there if we look for it, so just return early here. | |
2508 return True | |
2509 else: | |
2510 # Got some other operator. | |
2511 return False | |
2512 | |
2513 else: | |
2514 # Expecting opening parenthesis or opening bracket | |
2515 if operator in ('>', ')', ']'): | |
2516 nesting_stack.append(operator) | |
2517 elif operator in ('(', '['): | |
2518 nesting_stack.pop() | |
2519 | |
2520 else: | |
2521 # Scan the previous line | |
2522 linenum -= 1 | |
2523 if linenum < 0: | |
2524 break | |
2525 line = clean_lines.elided[linenum] | |
2526 | |
2527 # Exhausted all earlier lines and still no matching angle bracket. | |
2528 return False | |
2529 | |
2530 | |
2531 def CheckSpacing(filename, clean_lines, linenum, nesting_state, error): | 2727 def CheckSpacing(filename, clean_lines, linenum, nesting_state, error): |
2532 """Checks for the correctness of various spacing issues in the code. | 2728 """Checks for the correctness of various spacing issues in the code. |
2533 | 2729 |
2534 Things we check for: spaces around operators, spaces after | 2730 Things we check for: spaces around operators, spaces after |
2535 if/for/while/switch, no spaces around parens in function calls, two | 2731 if/for/while/switch, no spaces around parens in function calls, two |
2536 spaces between code and comment, don't start a block with a blank | 2732 spaces between code and comment, don't start a block with a blank |
2537 line, don't end a function with a blank line, don't add a blank line | 2733 line, don't end a function with a blank line, don't add a blank line |
2538 after public/protected/private, don't have too many blank lines in a row. | 2734 after public/protected/private, don't have too many blank lines in a row. |
2539 | 2735 |
2540 Args: | 2736 Args: |
2541 filename: The name of the current file. | 2737 filename: The name of the current file. |
2542 clean_lines: A CleansedLines instance containing the file. | 2738 clean_lines: A CleansedLines instance containing the file. |
2543 linenum: The number of the line to check. | 2739 linenum: The number of the line to check. |
2544 nesting_state: A _NestingState instance which maintains information about | 2740 nesting_state: A NestingState instance which maintains information about |
2545 the current stack of nested blocks being parsed. | 2741 the current stack of nested blocks being parsed. |
2546 error: The function to call with any errors found. | 2742 error: The function to call with any errors found. |
2547 """ | 2743 """ |
2548 | 2744 |
2549 # Don't use "elided" lines here, otherwise we can't check commented lines. | 2745 # Don't use "elided" lines here, otherwise we can't check commented lines. |
2550 # Don't want to use "raw" either, because we don't want to check inside C++11 | 2746 # Don't want to use "raw" either, because we don't want to check inside C++11 |
2551 # raw strings, | 2747 # raw strings, |
2552 raw = clean_lines.lines_without_raw_strings | 2748 raw = clean_lines.lines_without_raw_strings |
2553 line = raw[linenum] | 2749 line = raw[linenum] |
2554 | 2750 |
2555 # Before nixing comments, check if the line is blank for no good | 2751 # Before nixing comments, check if the line is blank for no good |
2556 # reason. This includes the first line after a block is opened, and | 2752 # reason. This includes the first line after a block is opened, and |
2557 # blank lines at the end of a function (ie, right before a line like '}' | 2753 # blank lines at the end of a function (ie, right before a line like '}' |
2558 # | 2754 # |
2559 # Skip all the blank line checks if we are immediately inside a | 2755 # Skip all the blank line checks if we are immediately inside a |
2560 # namespace body. In other words, don't issue blank line warnings | 2756 # namespace body. In other words, don't issue blank line warnings |
2561 # for this block: | 2757 # for this block: |
2562 # namespace { | 2758 # namespace { |
2563 # | 2759 # |
2564 # } | 2760 # } |
2565 # | 2761 # |
2566 # A warning about missing end of namespace comments will be issued instead. | 2762 # A warning about missing end of namespace comments will be issued instead. |
2567 if IsBlankLine(line) and not nesting_state.InNamespaceBody(): | 2763 # |
| 2764 # Also skip blank line checks for 'extern "C"' blocks, which are formatted |
| 2765 # like namespaces. |
| 2766 if (IsBlankLine(line) and |
| 2767 not nesting_state.InNamespaceBody() and |
| 2768 not nesting_state.InExternC()): |
2568 elided = clean_lines.elided | 2769 elided = clean_lines.elided |
2569 prev_line = elided[linenum - 1] | 2770 prev_line = elided[linenum - 1] |
2570 prevbrace = prev_line.rfind('{') | 2771 prevbrace = prev_line.rfind('{') |
2571 # TODO(unknown): Don't complain if line before blank line, and line after, | 2772 # TODO(unknown): Don't complain if line before blank line, and line after, |
2572 # both start with alnums and are indented the same amount. | 2773 # both start with alnums and are indented the same amount. |
2573 # This ignores whitespace at the start of a namespace block | 2774 # This ignores whitespace at the start of a namespace block |
2574 # because those are not usually indented. | 2775 # because those are not usually indented. |
2575 if prevbrace != -1 and prev_line[prevbrace:].find('}') == -1: | 2776 if prevbrace != -1 and prev_line[prevbrace:].find('}') == -1: |
2576 # OK, we have a blank line at the start of a code block. Before we | 2777 # OK, we have a blank line at the start of a code block. Before we |
2577 # complain, we check if it is an exception to the rule: The previous | 2778 # complain, we check if it is an exception to the rule: The previous |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2620 and next_line.find('} else ') == -1): | 2821 and next_line.find('} else ') == -1): |
2621 error(filename, linenum, 'whitespace/blank_line', 3, | 2822 error(filename, linenum, 'whitespace/blank_line', 3, |
2622 'Redundant blank line at the end of a code block ' | 2823 'Redundant blank line at the end of a code block ' |
2623 'should be deleted.') | 2824 'should be deleted.') |
2624 | 2825 |
2625 matched = Match(r'\s*(public|protected|private):', prev_line) | 2826 matched = Match(r'\s*(public|protected|private):', prev_line) |
2626 if matched: | 2827 if matched: |
2627 error(filename, linenum, 'whitespace/blank_line', 3, | 2828 error(filename, linenum, 'whitespace/blank_line', 3, |
2628 'Do not leave a blank line after "%s:"' % matched.group(1)) | 2829 'Do not leave a blank line after "%s:"' % matched.group(1)) |
2629 | 2830 |
2630 # Next, we complain if there's a comment too near the text | 2831 # Next, check comments |
2631 commentpos = line.find('//') | 2832 next_line_start = 0 |
2632 if commentpos != -1: | 2833 if linenum + 1 < clean_lines.NumLines(): |
2633 # Check if the // may be in quotes. If so, ignore it | 2834 next_line = raw[linenum + 1] |
2634 # Comparisons made explicit for clarity -- pylint: disable=g-explicit-bool-c
omparison | 2835 next_line_start = len(next_line) - len(next_line.lstrip()) |
2635 if (line.count('"', 0, commentpos) - | 2836 CheckComment(line, filename, linenum, next_line_start, error) |
2636 line.count('\\"', 0, commentpos)) % 2 == 0: # not in quotes | |
2637 # Allow one space for new scopes, two spaces otherwise: | |
2638 if (not Match(r'^\s*{ //', line) and | |
2639 ((commentpos >= 1 and | |
2640 line[commentpos-1] not in string.whitespace) or | |
2641 (commentpos >= 2 and | |
2642 line[commentpos-2] not in string.whitespace))): | |
2643 error(filename, linenum, 'whitespace/comments', 2, | |
2644 'At least two spaces is best between code and comments') | |
2645 # There should always be a space between the // and the comment | |
2646 commentend = commentpos + 2 | |
2647 if commentend < len(line) and not line[commentend] == ' ': | |
2648 # but some lines are exceptions -- e.g. if they're big | |
2649 # comment delimiters like: | |
2650 # //---------------------------------------------------------- | |
2651 # or are an empty C++ style Doxygen comment, like: | |
2652 # /// | |
2653 # or C++ style Doxygen comments placed after the variable: | |
2654 # ///< Header comment | |
2655 # //!< Header comment | |
2656 # or they begin with multiple slashes followed by a space: | |
2657 # //////// Header comment | |
2658 match = (Search(r'[=/-]{4,}\s*$', line[commentend:]) or | |
2659 Search(r'^/$', line[commentend:]) or | |
2660 Search(r'^!< ', line[commentend:]) or | |
2661 Search(r'^/< ', line[commentend:]) or | |
2662 Search(r'^/+ ', line[commentend:])) | |
2663 if not match: | |
2664 error(filename, linenum, 'whitespace/comments', 4, | |
2665 'Should have a space between // and comment') | |
2666 CheckComment(line[commentpos:], filename, linenum, error) | |
2667 | 2837 |
2668 line = clean_lines.elided[linenum] # get rid of comments and strings | 2838 # get rid of comments and strings |
| 2839 line = clean_lines.elided[linenum] |
2669 | 2840 |
2670 # Don't try to do spacing checks for operator methods | 2841 # You shouldn't have spaces before your brackets, except maybe after |
2671 line = re.sub(r'operator(==|!=|<|<<|<=|>=|>>|>)\(', 'operator\(', line) | 2842 # 'delete []' or 'return []() {};' |
| 2843 if Search(r'\w\s+\[', line) and not Search(r'(?:delete|return)\s+\[', line): |
| 2844 error(filename, linenum, 'whitespace/braces', 5, |
| 2845 'Extra space before [') |
| 2846 |
| 2847 # In range-based for, we wanted spaces before and after the colon, but |
| 2848 # not around "::" tokens that might appear. |
| 2849 if (Search(r'for *\(.*[^:]:[^: ]', line) or |
| 2850 Search(r'for *\(.*[^: ]:[^:]', line)): |
| 2851 error(filename, linenum, 'whitespace/forcolon', 2, |
| 2852 'Missing space around colon in range-based for loop') |
| 2853 |
| 2854 |
| 2855 def CheckOperatorSpacing(filename, clean_lines, linenum, error): |
| 2856 """Checks for horizontal spacing around operators. |
| 2857 |
| 2858 Args: |
| 2859 filename: The name of the current file. |
| 2860 clean_lines: A CleansedLines instance containing the file. |
| 2861 linenum: The number of the line to check. |
| 2862 error: The function to call with any errors found. |
| 2863 """ |
| 2864 line = clean_lines.elided[linenum] |
| 2865 |
| 2866 # Don't try to do spacing checks for operator methods. Do this by |
| 2867 # replacing the troublesome characters with something else, |
| 2868 # preserving column position for all other characters. |
| 2869 # |
| 2870 # The replacement is done repeatedly to avoid false positives from |
| 2871 # operators that call operators. |
| 2872 while True: |
| 2873 match = Match(r'^(.*\boperator\b)(\S+)(\s*\(.*)$', line) |
| 2874 if match: |
| 2875 line = match.group(1) + ('_' * len(match.group(2))) + match.group(3) |
| 2876 else: |
| 2877 break |
2672 | 2878 |
2673 # We allow no-spaces around = within an if: "if ( (a=Foo()) == 0 )". | 2879 # We allow no-spaces around = within an if: "if ( (a=Foo()) == 0 )". |
2674 # Otherwise not. Note we only check for non-spaces on *both* sides; | 2880 # Otherwise not. Note we only check for non-spaces on *both* sides; |
2675 # sometimes people put non-spaces on one side when aligning ='s among | 2881 # sometimes people put non-spaces on one side when aligning ='s among |
2676 # many lines (not that this is behavior that I approve of...) | 2882 # many lines (not that this is behavior that I approve of...) |
2677 if Search(r'[\w.]=[\w.]', line) and not Search(r'\b(if|while) ', line): | 2883 if Search(r'[\w.]=[\w.]', line) and not Search(r'\b(if|while) ', line): |
2678 error(filename, linenum, 'whitespace/operators', 4, | 2884 error(filename, linenum, 'whitespace/operators', 4, |
2679 'Missing spaces around =') | 2885 'Missing spaces around =') |
2680 | 2886 |
2681 # It's ok not to have spaces around binary operators like + - * /, but if | 2887 # It's ok not to have spaces around binary operators like + - * /, but if |
2682 # there's too little whitespace, we get concerned. It's hard to tell, | 2888 # there's too little whitespace, we get concerned. It's hard to tell, |
2683 # though, so we punt on this one for now. TODO. | 2889 # though, so we punt on this one for now. TODO. |
2684 | 2890 |
2685 # You should always have whitespace around binary operators. | 2891 # You should always have whitespace around binary operators. |
2686 # | 2892 # |
2687 # Check <= and >= first to avoid false positives with < and >, then | 2893 # Check <= and >= first to avoid false positives with < and >, then |
2688 # check non-include lines for spacing around < and >. | 2894 # check non-include lines for spacing around < and >. |
2689 match = Search(r'[^<>=!\s](==|!=|<=|>=)[^<>=!\s]', line) | 2895 # |
| 2896 # If the operator is followed by a comma, assume it's be used in a |
| 2897 # macro context and don't do any checks. This avoids false |
| 2898 # positives. |
| 2899 # |
| 2900 # Note that && is not included here. Those are checked separately |
| 2901 # in CheckRValueReference |
| 2902 match = Search(r'[^<>=!\s](==|!=|<=|>=|\|\|)[^<>=!\s,;\)]', line) |
2690 if match: | 2903 if match: |
2691 error(filename, linenum, 'whitespace/operators', 3, | 2904 error(filename, linenum, 'whitespace/operators', 3, |
2692 'Missing spaces around %s' % match.group(1)) | 2905 'Missing spaces around %s' % match.group(1)) |
| 2906 elif not Match(r'#.*include', line): |
| 2907 # Look for < that is not surrounded by spaces. This is only |
| 2908 # triggered if both sides are missing spaces, even though |
| 2909 # technically should should flag if at least one side is missing a |
| 2910 # space. This is done to avoid some false positives with shifts. |
| 2911 match = Match(r'^(.*[^\s<])<[^\s=<,]', line) |
| 2912 if match: |
| 2913 (_, _, end_pos) = CloseExpression( |
| 2914 clean_lines, linenum, len(match.group(1))) |
| 2915 if end_pos <= -1: |
| 2916 error(filename, linenum, 'whitespace/operators', 3, |
| 2917 'Missing spaces around <') |
| 2918 |
| 2919 # Look for > that is not surrounded by spaces. Similar to the |
| 2920 # above, we only trigger if both sides are missing spaces to avoid |
| 2921 # false positives with shifts. |
| 2922 match = Match(r'^(.*[^-\s>])>[^\s=>,]', line) |
| 2923 if match: |
| 2924 (_, _, start_pos) = ReverseCloseExpression( |
| 2925 clean_lines, linenum, len(match.group(1))) |
| 2926 if start_pos <= -1: |
| 2927 error(filename, linenum, 'whitespace/operators', 3, |
| 2928 'Missing spaces around >') |
| 2929 |
2693 # We allow no-spaces around << when used like this: 10<<20, but | 2930 # We allow no-spaces around << when used like this: 10<<20, but |
2694 # not otherwise (particularly, not when used as streams) | 2931 # not otherwise (particularly, not when used as streams) |
2695 # Also ignore using ns::operator<<; | 2932 # We also allow operators following an opening parenthesis, since |
2696 match = Search(r'(operator|\S)(?:L|UL|ULL|l|ul|ull)?<<(\S)', line) | 2933 # those tend to be macros that deal with operators. |
2697 if (match and | 2934 match = Search(r'(operator|\S)(?:L|UL|ULL|l|ul|ull)?<<([^\s,=])', line) |
| 2935 if (match and match.group(1) != '(' and |
2698 not (match.group(1).isdigit() and match.group(2).isdigit()) and | 2936 not (match.group(1).isdigit() and match.group(2).isdigit()) and |
2699 not (match.group(1) == 'operator' and match.group(2) == ';')): | 2937 not (match.group(1) == 'operator' and match.group(2) == ';')): |
2700 error(filename, linenum, 'whitespace/operators', 3, | 2938 error(filename, linenum, 'whitespace/operators', 3, |
2701 'Missing spaces around <<') | 2939 'Missing spaces around <<') |
2702 elif not Match(r'#.*include', line): | |
2703 # Avoid false positives on -> | |
2704 reduced_line = line.replace('->', '') | |
2705 | |
2706 # Look for < that is not surrounded by spaces. This is only | |
2707 # triggered if both sides are missing spaces, even though | |
2708 # technically should should flag if at least one side is missing a | |
2709 # space. This is done to avoid some false positives with shifts. | |
2710 match = Search(r'[^\s<]<([^\s=<].*)', reduced_line) | |
2711 if (match and | |
2712 not FindNextMatchingAngleBracket(clean_lines, linenum, match.group(1))): | |
2713 error(filename, linenum, 'whitespace/operators', 3, | |
2714 'Missing spaces around <') | |
2715 | |
2716 # Look for > that is not surrounded by spaces. Similar to the | |
2717 # above, we only trigger if both sides are missing spaces to avoid | |
2718 # false positives with shifts. | |
2719 match = Search(r'^(.*[^\s>])>[^\s=>]', reduced_line) | |
2720 if (match and | |
2721 not FindPreviousMatchingAngleBracket(clean_lines, linenum, | |
2722 match.group(1))): | |
2723 error(filename, linenum, 'whitespace/operators', 3, | |
2724 'Missing spaces around >') | |
2725 | 2940 |
2726 # We allow no-spaces around >> for almost anything. This is because | 2941 # We allow no-spaces around >> for almost anything. This is because |
2727 # C++11 allows ">>" to close nested templates, which accounts for | 2942 # C++11 allows ">>" to close nested templates, which accounts for |
2728 # most cases when ">>" is not followed by a space. | 2943 # most cases when ">>" is not followed by a space. |
2729 # | 2944 # |
2730 # We still warn on ">>" followed by alpha character, because that is | 2945 # We still warn on ">>" followed by alpha character, because that is |
2731 # likely due to ">>" being used for right shifts, e.g.: | 2946 # likely due to ">>" being used for right shifts, e.g.: |
2732 # value >> alpha | 2947 # value >> alpha |
2733 # | 2948 # |
2734 # When ">>" is used to close templates, the alphanumeric letter that | 2949 # When ">>" is used to close templates, the alphanumeric letter that |
2735 # follows would be part of an identifier, and there should still be | 2950 # follows would be part of an identifier, and there should still be |
2736 # a space separating the template type and the identifier. | 2951 # a space separating the template type and the identifier. |
2737 # type<type<type>> alpha | 2952 # type<type<type>> alpha |
2738 match = Search(r'>>[a-zA-Z_]', line) | 2953 match = Search(r'>>[a-zA-Z_]', line) |
2739 if match: | 2954 if match: |
2740 error(filename, linenum, 'whitespace/operators', 3, | 2955 error(filename, linenum, 'whitespace/operators', 3, |
2741 'Missing spaces around >>') | 2956 'Missing spaces around >>') |
2742 | 2957 |
2743 # There shouldn't be space around unary operators | 2958 # There shouldn't be space around unary operators |
2744 match = Search(r'(!\s|~\s|[\s]--[\s;]|[\s]\+\+[\s;])', line) | 2959 match = Search(r'(!\s|~\s|[\s]--[\s;]|[\s]\+\+[\s;])', line) |
2745 if match: | 2960 if match: |
2746 error(filename, linenum, 'whitespace/operators', 4, | 2961 error(filename, linenum, 'whitespace/operators', 4, |
2747 'Extra space for operator %s' % match.group(1)) | 2962 'Extra space for operator %s' % match.group(1)) |
2748 | 2963 |
2749 # A pet peeve of mine: no spaces after an if, while, switch, or for | 2964 |
| 2965 def CheckParenthesisSpacing(filename, clean_lines, linenum, error): |
| 2966 """Checks for horizontal spacing around parentheses. |
| 2967 |
| 2968 Args: |
| 2969 filename: The name of the current file. |
| 2970 clean_lines: A CleansedLines instance containing the file. |
| 2971 linenum: The number of the line to check. |
| 2972 error: The function to call with any errors found. |
| 2973 """ |
| 2974 line = clean_lines.elided[linenum] |
| 2975 |
| 2976 # No spaces after an if, while, switch, or for |
2750 match = Search(r' (if\(|for\(|while\(|switch\()', line) | 2977 match = Search(r' (if\(|for\(|while\(|switch\()', line) |
2751 if match: | 2978 if match: |
2752 error(filename, linenum, 'whitespace/parens', 5, | 2979 error(filename, linenum, 'whitespace/parens', 5, |
2753 'Missing space before ( in %s' % match.group(1)) | 2980 'Missing space before ( in %s' % match.group(1)) |
2754 | 2981 |
2755 # For if/for/while/switch, the left and right parens should be | 2982 # For if/for/while/switch, the left and right parens should be |
2756 # consistent about how many spaces are inside the parens, and | 2983 # consistent about how many spaces are inside the parens, and |
2757 # there should either be zero or one spaces inside the parens. | 2984 # there should either be zero or one spaces inside the parens. |
2758 # We don't want: "if ( foo)" or "if ( foo )". | 2985 # We don't want: "if ( foo)" or "if ( foo )". |
2759 # Exception: "for ( ; foo; bar)" and "for (foo; bar; )" are allowed. | 2986 # Exception: "for ( ; foo; bar)" and "for (foo; bar; )" are allowed. |
2760 match = Search(r'\b(if|for|while|switch)\s*' | 2987 match = Search(r'\b(if|for|while|switch)\s*' |
2761 r'\(([ ]*)(.).*[^ ]+([ ]*)\)\s*{\s*$', | 2988 r'\(([ ]*)(.).*[^ ]+([ ]*)\)\s*{\s*$', |
2762 line) | 2989 line) |
2763 if match: | 2990 if match: |
2764 if len(match.group(2)) != len(match.group(4)): | 2991 if len(match.group(2)) != len(match.group(4)): |
2765 if not (match.group(3) == ';' and | 2992 if not (match.group(3) == ';' and |
2766 len(match.group(2)) == 1 + len(match.group(4)) or | 2993 len(match.group(2)) == 1 + len(match.group(4)) or |
2767 not match.group(2) and Search(r'\bfor\s*\(.*; \)', line)): | 2994 not match.group(2) and Search(r'\bfor\s*\(.*; \)', line)): |
2768 error(filename, linenum, 'whitespace/parens', 5, | 2995 error(filename, linenum, 'whitespace/parens', 5, |
2769 'Mismatching spaces inside () in %s' % match.group(1)) | 2996 'Mismatching spaces inside () in %s' % match.group(1)) |
2770 if len(match.group(2)) not in [0, 1]: | 2997 if len(match.group(2)) not in [0, 1]: |
2771 error(filename, linenum, 'whitespace/parens', 5, | 2998 error(filename, linenum, 'whitespace/parens', 5, |
2772 'Should have zero or one spaces inside ( and ) in %s' % | 2999 'Should have zero or one spaces inside ( and ) in %s' % |
2773 match.group(1)) | 3000 match.group(1)) |
2774 | 3001 |
| 3002 |
| 3003 def CheckCommaSpacing(filename, clean_lines, linenum, error): |
| 3004 """Checks for horizontal spacing near commas and semicolons. |
| 3005 |
| 3006 Args: |
| 3007 filename: The name of the current file. |
| 3008 clean_lines: A CleansedLines instance containing the file. |
| 3009 linenum: The number of the line to check. |
| 3010 error: The function to call with any errors found. |
| 3011 """ |
| 3012 raw = clean_lines.lines_without_raw_strings |
| 3013 line = clean_lines.elided[linenum] |
| 3014 |
2775 # You should always have a space after a comma (either as fn arg or operator) | 3015 # You should always have a space after a comma (either as fn arg or operator) |
2776 # | 3016 # |
2777 # This does not apply when the non-space character following the | 3017 # This does not apply when the non-space character following the |
2778 # comma is another comma, since the only time when that happens is | 3018 # comma is another comma, since the only time when that happens is |
2779 # for empty macro arguments. | 3019 # for empty macro arguments. |
2780 # | 3020 # |
2781 # We run this check in two passes: first pass on elided lines to | 3021 # We run this check in two passes: first pass on elided lines to |
2782 # verify that lines contain missing whitespaces, second pass on raw | 3022 # verify that lines contain missing whitespaces, second pass on raw |
2783 # lines to confirm that those missing whitespaces are not due to | 3023 # lines to confirm that those missing whitespaces are not due to |
2784 # elided comments. | 3024 # elided comments. |
2785 if Search(r',[^,\s]', line) and Search(r',[^,\s]', raw[linenum]): | 3025 if Search(r',[^,\s]', line) and Search(r',[^,\s]', raw[linenum]): |
2786 error(filename, linenum, 'whitespace/comma', 3, | 3026 error(filename, linenum, 'whitespace/comma', 3, |
2787 'Missing space after ,') | 3027 'Missing space after ,') |
2788 | 3028 |
2789 # You should always have a space after a semicolon | 3029 # You should always have a space after a semicolon |
2790 # except for few corner cases | 3030 # except for few corner cases |
2791 # TODO(unknown): clarify if 'if (1) { return 1;}' is requires one more | 3031 # TODO(unknown): clarify if 'if (1) { return 1;}' is requires one more |
2792 # space after ; | 3032 # space after ; |
2793 if Search(r';[^\s};\\)/]', line): | 3033 if Search(r';[^\s};\\)/]', line): |
2794 error(filename, linenum, 'whitespace/semicolon', 3, | 3034 error(filename, linenum, 'whitespace/semicolon', 3, |
2795 'Missing space after ;') | 3035 'Missing space after ;') |
2796 | 3036 |
2797 # Next we will look for issues with function calls. | 3037 |
2798 CheckSpacingForFunctionCall(filename, line, linenum, error) | 3038 def CheckBracesSpacing(filename, clean_lines, linenum, error): |
| 3039 """Checks for horizontal spacing near commas. |
| 3040 |
| 3041 Args: |
| 3042 filename: The name of the current file. |
| 3043 clean_lines: A CleansedLines instance containing the file. |
| 3044 linenum: The number of the line to check. |
| 3045 error: The function to call with any errors found. |
| 3046 """ |
| 3047 line = clean_lines.elided[linenum] |
2799 | 3048 |
2800 # Except after an opening paren, or after another opening brace (in case of | 3049 # Except after an opening paren, or after another opening brace (in case of |
2801 # an initializer list, for instance), you should have spaces before your | 3050 # an initializer list, for instance), you should have spaces before your |
2802 # braces. And since you should never have braces at the beginning of a line, | 3051 # braces. And since you should never have braces at the beginning of a line, |
2803 # this is an easy test. | 3052 # this is an easy test. |
2804 match = Match(r'^(.*[^ ({]){', line) | 3053 match = Match(r'^(.*[^ ({]){', line) |
2805 if match: | 3054 if match: |
2806 # Try a bit harder to check for brace initialization. This | 3055 # Try a bit harder to check for brace initialization. This |
2807 # happens in one of the following forms: | 3056 # happens in one of the following forms: |
2808 # Constructor() : initializer_list_{} { ... } | 3057 # Constructor() : initializer_list_{} { ... } |
2809 # Constructor{}.MemberFunction() | 3058 # Constructor{}.MemberFunction() |
2810 # Type variable{}; | 3059 # Type variable{}; |
2811 # FunctionCall(type{}, ...); | 3060 # FunctionCall(type{}, ...); |
2812 # LastArgument(..., type{}); | 3061 # LastArgument(..., type{}); |
2813 # LOG(INFO) << type{} << " ..."; | 3062 # LOG(INFO) << type{} << " ..."; |
2814 # map_of_type[{...}] = ...; | 3063 # map_of_type[{...}] = ...; |
| 3064 # ternary = expr ? new type{} : nullptr; |
| 3065 # OuterTemplate<InnerTemplateConstructor<Type>{}> |
2815 # | 3066 # |
2816 # We check for the character following the closing brace, and | 3067 # We check for the character following the closing brace, and |
2817 # silence the warning if it's one of those listed above, i.e. | 3068 # silence the warning if it's one of those listed above, i.e. |
2818 # "{.;,)<]". | 3069 # "{.;,)<>]:". |
2819 # | 3070 # |
2820 # To account for nested initializer list, we allow any number of | 3071 # To account for nested initializer list, we allow any number of |
2821 # closing braces up to "{;,)<". We can't simply silence the | 3072 # closing braces up to "{;,)<". We can't simply silence the |
2822 # warning on first sight of closing brace, because that would | 3073 # warning on first sight of closing brace, because that would |
2823 # cause false negatives for things that are not initializer lists. | 3074 # cause false negatives for things that are not initializer lists. |
2824 # Silence this: But not this: | 3075 # Silence this: But not this: |
2825 # Outer{ if (...) { | 3076 # Outer{ if (...) { |
2826 # Inner{...} if (...){ // Missing space before { | 3077 # Inner{...} if (...){ // Missing space before { |
2827 # }; } | 3078 # }; } |
2828 # | 3079 # |
2829 # There is a false negative with this approach if people inserted | 3080 # There is a false negative with this approach if people inserted |
2830 # spurious semicolons, e.g. "if (cond){};", but we will catch the | 3081 # spurious semicolons, e.g. "if (cond){};", but we will catch the |
2831 # spurious semicolon with a separate check. | 3082 # spurious semicolon with a separate check. |
2832 (endline, endlinenum, endpos) = CloseExpression( | 3083 (endline, endlinenum, endpos) = CloseExpression( |
2833 clean_lines, linenum, len(match.group(1))) | 3084 clean_lines, linenum, len(match.group(1))) |
2834 trailing_text = '' | 3085 trailing_text = '' |
2835 if endpos > -1: | 3086 if endpos > -1: |
2836 trailing_text = endline[endpos:] | 3087 trailing_text = endline[endpos:] |
2837 for offset in xrange(endlinenum + 1, | 3088 for offset in xrange(endlinenum + 1, |
2838 min(endlinenum + 3, clean_lines.NumLines() - 1)): | 3089 min(endlinenum + 3, clean_lines.NumLines() - 1)): |
2839 trailing_text += clean_lines.elided[offset] | 3090 trailing_text += clean_lines.elided[offset] |
2840 if not Match(r'^[\s}]*[{.;,)<\]]', trailing_text): | 3091 if not Match(r'^[\s}]*[{.;,)<>\]:]', trailing_text): |
2841 error(filename, linenum, 'whitespace/braces', 5, | 3092 error(filename, linenum, 'whitespace/braces', 5, |
2842 'Missing space before {') | 3093 'Missing space before {') |
2843 | 3094 |
2844 # Make sure '} else {' has spaces. | 3095 # Make sure '} else {' has spaces. |
2845 if Search(r'}else', line): | 3096 if Search(r'}else', line): |
2846 error(filename, linenum, 'whitespace/braces', 5, | 3097 error(filename, linenum, 'whitespace/braces', 5, |
2847 'Missing space before else') | 3098 'Missing space before else') |
2848 | 3099 |
2849 # You shouldn't have spaces before your brackets, except maybe after | |
2850 # 'delete []' or 'new char * []'. | |
2851 if Search(r'\w\s+\[', line) and not Search(r'delete\s+\[', line): | |
2852 error(filename, linenum, 'whitespace/braces', 5, | |
2853 'Extra space before [') | |
2854 | |
2855 # You shouldn't have a space before a semicolon at the end of the line. | 3100 # You shouldn't have a space before a semicolon at the end of the line. |
2856 # There's a special case for "for" since the style guide allows space before | 3101 # There's a special case for "for" since the style guide allows space before |
2857 # the semicolon there. | 3102 # the semicolon there. |
2858 if Search(r':\s*;\s*$', line): | 3103 if Search(r':\s*;\s*$', line): |
2859 error(filename, linenum, 'whitespace/semicolon', 5, | 3104 error(filename, linenum, 'whitespace/semicolon', 5, |
2860 'Semicolon defining empty statement. Use {} instead.') | 3105 'Semicolon defining empty statement. Use {} instead.') |
2861 elif Search(r'^\s*;\s*$', line): | 3106 elif Search(r'^\s*;\s*$', line): |
2862 error(filename, linenum, 'whitespace/semicolon', 5, | 3107 error(filename, linenum, 'whitespace/semicolon', 5, |
2863 'Line contains only semicolon. If this should be an empty statement, ' | 3108 'Line contains only semicolon. If this should be an empty statement, ' |
2864 'use {} instead.') | 3109 'use {} instead.') |
2865 elif (Search(r'\s+;\s*$', line) and | 3110 elif (Search(r'\s+;\s*$', line) and |
2866 not Search(r'\bfor\b', line)): | 3111 not Search(r'\bfor\b', line)): |
2867 error(filename, linenum, 'whitespace/semicolon', 5, | 3112 error(filename, linenum, 'whitespace/semicolon', 5, |
2868 'Extra space before last semicolon. If this should be an empty ' | 3113 'Extra space before last semicolon. If this should be an empty ' |
2869 'statement, use {} instead.') | 3114 'statement, use {} instead.') |
2870 | 3115 |
2871 # In range-based for, we wanted spaces before and after the colon, but | 3116 |
2872 # not around "::" tokens that might appear. | 3117 def IsDecltype(clean_lines, linenum, column): |
2873 if (Search('for *\(.*[^:]:[^: ]', line) or | 3118 """Check if the token ending on (linenum, column) is decltype(). |
2874 Search('for *\(.*[^: ]:[^:]', line)): | 3119 |
2875 error(filename, linenum, 'whitespace/forcolon', 2, | 3120 Args: |
2876 'Missing space around colon in range-based for loop') | 3121 clean_lines: A CleansedLines instance containing the file. |
| 3122 linenum: the number of the line to check. |
| 3123 column: end column of the token to check. |
| 3124 Returns: |
| 3125 True if this token is decltype() expression, False otherwise. |
| 3126 """ |
| 3127 (text, _, start_col) = ReverseCloseExpression(clean_lines, linenum, column) |
| 3128 if start_col < 0: |
| 3129 return False |
| 3130 if Search(r'\bdecltype\s*$', text[0:start_col]): |
| 3131 return True |
| 3132 return False |
| 3133 |
| 3134 |
| 3135 def IsTemplateParameterList(clean_lines, linenum, column): |
| 3136 """Check if the token ending on (linenum, column) is the end of template<>. |
| 3137 |
| 3138 Args: |
| 3139 clean_lines: A CleansedLines instance containing the file. |
| 3140 linenum: the number of the line to check. |
| 3141 column: end column of the token to check. |
| 3142 Returns: |
| 3143 True if this token is end of a template parameter list, False otherwise. |
| 3144 """ |
| 3145 (_, startline, startpos) = ReverseCloseExpression( |
| 3146 clean_lines, linenum, column) |
| 3147 if (startpos > -1 and |
| 3148 Search(r'\btemplate\s*$', clean_lines.elided[startline][0:startpos])): |
| 3149 return True |
| 3150 return False |
| 3151 |
| 3152 |
| 3153 def IsRValueType(clean_lines, nesting_state, linenum, column): |
| 3154 """Check if the token ending on (linenum, column) is a type. |
| 3155 |
| 3156 Assumes that text to the right of the column is "&&" or a function |
| 3157 name. |
| 3158 |
| 3159 Args: |
| 3160 clean_lines: A CleansedLines instance containing the file. |
| 3161 nesting_state: A NestingState instance which maintains information about |
| 3162 the current stack of nested blocks being parsed. |
| 3163 linenum: the number of the line to check. |
| 3164 column: end column of the token to check. |
| 3165 Returns: |
| 3166 True if this token is a type, False if we are not sure. |
| 3167 """ |
| 3168 prefix = clean_lines.elided[linenum][0:column] |
| 3169 |
| 3170 # Get one word to the left. If we failed to do so, this is most |
| 3171 # likely not a type, since it's unlikely that the type name and "&&" |
| 3172 # would be split across multiple lines. |
| 3173 match = Match(r'^(.*)(\b\w+|[>*)&])\s*$', prefix) |
| 3174 if not match: |
| 3175 return False |
| 3176 |
| 3177 # Check text following the token. If it's "&&>" or "&&," or "&&...", it's |
| 3178 # most likely a rvalue reference used inside a template. |
| 3179 suffix = clean_lines.elided[linenum][column:] |
| 3180 if Match(r'&&\s*(?:[>,]|\.\.\.)', suffix): |
| 3181 return True |
| 3182 |
| 3183 # Check for simple type and end of templates: |
| 3184 # int&& variable |
| 3185 # vector<int>&& variable |
| 3186 # |
| 3187 # Because this function is called recursively, we also need to |
| 3188 # recognize pointer and reference types: |
| 3189 # int* Function() |
| 3190 # int& Function() |
| 3191 if match.group(2) in ['char', 'char16_t', 'char32_t', 'wchar_t', 'bool', |
| 3192 'short', 'int', 'long', 'signed', 'unsigned', |
| 3193 'float', 'double', 'void', 'auto', '>', '*', '&']: |
| 3194 return True |
| 3195 |
| 3196 # If we see a close parenthesis, look for decltype on the other side. |
| 3197 # decltype would unambiguously identify a type, anything else is |
| 3198 # probably a parenthesized expression and not a type. |
| 3199 if match.group(2) == ')': |
| 3200 return IsDecltype( |
| 3201 clean_lines, linenum, len(match.group(1)) + len(match.group(2)) - 1) |
| 3202 |
| 3203 # Check for casts and cv-qualifiers. |
| 3204 # match.group(1) remainder |
| 3205 # -------------- --------- |
| 3206 # const_cast< type&& |
| 3207 # const type&& |
| 3208 # type const&& |
| 3209 if Search(r'\b(?:const_cast\s*<|static_cast\s*<|dynamic_cast\s*<|' |
| 3210 r'reinterpret_cast\s*<|\w+\s)\s*$', |
| 3211 match.group(1)): |
| 3212 return True |
| 3213 |
| 3214 # Look for a preceding symbol that might help differentiate the context. |
| 3215 # These are the cases that would be ambiguous: |
| 3216 # match.group(1) remainder |
| 3217 # -------------- --------- |
| 3218 # Call ( expression && |
| 3219 # Declaration ( type&& |
| 3220 # sizeof ( type&& |
| 3221 # if ( expression && |
| 3222 # while ( expression && |
| 3223 # for ( type&& |
| 3224 # for( ; expression && |
| 3225 # statement ; type&& |
| 3226 # block { type&& |
| 3227 # constructor { expression && |
| 3228 start = linenum |
| 3229 line = match.group(1) |
| 3230 match_symbol = None |
| 3231 while start >= 0: |
| 3232 # We want to skip over identifiers and commas to get to a symbol. |
| 3233 # Commas are skipped so that we can find the opening parenthesis |
| 3234 # for function parameter lists. |
| 3235 match_symbol = Match(r'^(.*)([^\w\s,])[\w\s,]*$', line) |
| 3236 if match_symbol: |
| 3237 break |
| 3238 start -= 1 |
| 3239 line = clean_lines.elided[start] |
| 3240 |
| 3241 if not match_symbol: |
| 3242 # Probably the first statement in the file is an rvalue reference |
| 3243 return True |
| 3244 |
| 3245 if match_symbol.group(2) == '}': |
| 3246 # Found closing brace, probably an indicate of this: |
| 3247 # block{} type&& |
| 3248 return True |
| 3249 |
| 3250 if match_symbol.group(2) == ';': |
| 3251 # Found semicolon, probably one of these: |
| 3252 # for(; expression && |
| 3253 # statement; type&& |
| 3254 |
| 3255 # Look for the previous 'for(' in the previous lines. |
| 3256 before_text = match_symbol.group(1) |
| 3257 for i in xrange(start - 1, max(start - 6, 0), -1): |
| 3258 before_text = clean_lines.elided[i] + before_text |
| 3259 if Search(r'for\s*\([^{};]*$', before_text): |
| 3260 # This is the condition inside a for-loop |
| 3261 return False |
| 3262 |
| 3263 # Did not find a for-init-statement before this semicolon, so this |
| 3264 # is probably a new statement and not a condition. |
| 3265 return True |
| 3266 |
| 3267 if match_symbol.group(2) == '{': |
| 3268 # Found opening brace, probably one of these: |
| 3269 # block{ type&& = ... ; } |
| 3270 # constructor{ expression && expression } |
| 3271 |
| 3272 # Look for a closing brace or a semicolon. If we see a semicolon |
| 3273 # first, this is probably a rvalue reference. |
| 3274 line = clean_lines.elided[start][0:len(match_symbol.group(1)) + 1] |
| 3275 end = start |
| 3276 depth = 1 |
| 3277 while True: |
| 3278 for ch in line: |
| 3279 if ch == ';': |
| 3280 return True |
| 3281 elif ch == '{': |
| 3282 depth += 1 |
| 3283 elif ch == '}': |
| 3284 depth -= 1 |
| 3285 if depth == 0: |
| 3286 return False |
| 3287 end += 1 |
| 3288 if end >= clean_lines.NumLines(): |
| 3289 break |
| 3290 line = clean_lines.elided[end] |
| 3291 # Incomplete program? |
| 3292 return False |
| 3293 |
| 3294 if match_symbol.group(2) == '(': |
| 3295 # Opening parenthesis. Need to check what's to the left of the |
| 3296 # parenthesis. Look back one extra line for additional context. |
| 3297 before_text = match_symbol.group(1) |
| 3298 if linenum > 1: |
| 3299 before_text = clean_lines.elided[linenum - 1] + before_text |
| 3300 before_text = match_symbol.group(1) |
| 3301 |
| 3302 # Patterns that are likely to be types: |
| 3303 # [](type&& |
| 3304 # for (type&& |
| 3305 # sizeof(type&& |
| 3306 # operator=(type&& |
| 3307 # |
| 3308 if Search(r'(?:\]|\bfor|\bsizeof|\boperator\s*\S+\s*)\s*$', before_text): |
| 3309 return True |
| 3310 |
| 3311 # Patterns that are likely to be expressions: |
| 3312 # if (expression && |
| 3313 # while (expression && |
| 3314 # : initializer(expression && |
| 3315 # , initializer(expression && |
| 3316 # ( FunctionCall(expression && |
| 3317 # + FunctionCall(expression && |
| 3318 # + (expression && |
| 3319 # |
| 3320 # The last '+' represents operators such as '+' and '-'. |
| 3321 if Search(r'(?:\bif|\bwhile|[-+=%^(<!?:,&*]\s*)$', before_text): |
| 3322 return False |
| 3323 |
| 3324 # Something else. Check that tokens to the left look like |
| 3325 # return_type function_name |
| 3326 match_func = Match(r'^(.*)\s+\w(?:\w|::)*(?:<[^<>]*>)?\s*$', |
| 3327 match_symbol.group(1)) |
| 3328 if match_func: |
| 3329 # Check for constructors, which don't have return types. |
| 3330 if Search(r'\bexplicit$', match_func.group(1)): |
| 3331 return True |
| 3332 implicit_constructor = Match(r'\s*(\w+)\((?:const\s+)?(\w+)', prefix) |
| 3333 if (implicit_constructor and |
| 3334 implicit_constructor.group(1) == implicit_constructor.group(2)): |
| 3335 return True |
| 3336 return IsRValueType(clean_lines, nesting_state, linenum, |
| 3337 len(match_func.group(1))) |
| 3338 |
| 3339 # Nothing before the function name. If this is inside a block scope, |
| 3340 # this is probably a function call. |
| 3341 return not (nesting_state.previous_stack_top and |
| 3342 nesting_state.previous_stack_top.IsBlockInfo()) |
| 3343 |
| 3344 if match_symbol.group(2) == '>': |
| 3345 # Possibly a closing bracket, check that what's on the other side |
| 3346 # looks like the start of a template. |
| 3347 return IsTemplateParameterList( |
| 3348 clean_lines, start, len(match_symbol.group(1))) |
| 3349 |
| 3350 # Some other symbol, usually something like "a=b&&c". This is most |
| 3351 # likely not a type. |
| 3352 return False |
| 3353 |
| 3354 |
| 3355 def IsRValueAllowed(clean_lines, linenum): |
| 3356 """Check if RValue reference is allowed within some range of lines. |
| 3357 |
| 3358 Args: |
| 3359 clean_lines: A CleansedLines instance containing the file. |
| 3360 linenum: The number of the line to check. |
| 3361 Returns: |
| 3362 True if line is within the region where RValue references are allowed. |
| 3363 """ |
| 3364 for i in xrange(linenum, 0, -1): |
| 3365 line = clean_lines.elided[i] |
| 3366 if Match(r'GOOGLE_ALLOW_RVALUE_REFERENCES_(?:PUSH|POP)', line): |
| 3367 if not line.endswith('PUSH'): |
| 3368 return False |
| 3369 for j in xrange(linenum, clean_lines.NumLines(), 1): |
| 3370 line = clean_lines.elided[j] |
| 3371 if Match(r'GOOGLE_ALLOW_RVALUE_REFERENCES_(?:PUSH|POP)', line): |
| 3372 return line.endswith('POP') |
| 3373 return False |
| 3374 |
| 3375 |
| 3376 def CheckRValueReference(filename, clean_lines, linenum, nesting_state, error): |
| 3377 """Check for rvalue references. |
| 3378 |
| 3379 Args: |
| 3380 filename: The name of the current file. |
| 3381 clean_lines: A CleansedLines instance containing the file. |
| 3382 linenum: The number of the line to check. |
| 3383 nesting_state: A NestingState instance which maintains information about |
| 3384 the current stack of nested blocks being parsed. |
| 3385 error: The function to call with any errors found. |
| 3386 """ |
| 3387 # Find lines missing spaces around &&. |
| 3388 # TODO(unknown): currently we don't check for rvalue references |
| 3389 # with spaces surrounding the && to avoid false positives with |
| 3390 # boolean expressions. |
| 3391 line = clean_lines.elided[linenum] |
| 3392 match = Match(r'^(.*\S)&&', line) |
| 3393 if not match: |
| 3394 match = Match(r'(.*)&&\S', line) |
| 3395 if (not match) or '(&&)' in line or Search(r'\boperator\s*$', match.group(1)): |
| 3396 return |
| 3397 |
| 3398 # Either poorly formed && or an rvalue reference, check the context |
| 3399 # to get a more accurate error message. Mostly we want to determine |
| 3400 # if what's to the left of "&&" is a type or not. |
| 3401 and_pos = len(match.group(1)) |
| 3402 if IsRValueType(clean_lines, nesting_state, linenum, and_pos): |
| 3403 if not IsRValueAllowed(clean_lines, linenum): |
| 3404 error(filename, linenum, 'build/c++11', 3, |
| 3405 'RValue references are an unapproved C++ feature.') |
| 3406 else: |
| 3407 error(filename, linenum, 'whitespace/operators', 3, |
| 3408 'Missing spaces around &&') |
2877 | 3409 |
2878 | 3410 |
2879 def CheckSectionSpacing(filename, clean_lines, class_info, linenum, error): | 3411 def CheckSectionSpacing(filename, clean_lines, class_info, linenum, error): |
2880 """Checks for additional blank line issues related to sections. | 3412 """Checks for additional blank line issues related to sections. |
2881 | 3413 |
2882 Currently the only thing checked here is blank line before protected/private. | 3414 Currently the only thing checked here is blank line before protected/private. |
2883 | 3415 |
2884 Args: | 3416 Args: |
2885 filename: The name of the current file. | 3417 filename: The name of the current file. |
2886 clean_lines: A CleansedLines instance containing the file. | 3418 clean_lines: A CleansedLines instance containing the file. |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2974 # perfectly: we just don't complain if the last non-whitespace character on | 3506 # perfectly: we just don't complain if the last non-whitespace character on |
2975 # the previous non-blank line is ',', ';', ':', '(', '{', or '}', or if the | 3507 # the previous non-blank line is ',', ';', ':', '(', '{', or '}', or if the |
2976 # previous line starts a preprocessor block. | 3508 # previous line starts a preprocessor block. |
2977 prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0] | 3509 prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0] |
2978 if (not Search(r'[,;:}{(]\s*$', prevline) and | 3510 if (not Search(r'[,;:}{(]\s*$', prevline) and |
2979 not Match(r'\s*#', prevline)): | 3511 not Match(r'\s*#', prevline)): |
2980 error(filename, linenum, 'whitespace/braces', 4, | 3512 error(filename, linenum, 'whitespace/braces', 4, |
2981 '{ should almost always be at the end of the previous line') | 3513 '{ should almost always be at the end of the previous line') |
2982 | 3514 |
2983 # An else clause should be on the same line as the preceding closing brace. | 3515 # An else clause should be on the same line as the preceding closing brace. |
2984 if Match(r'\s*else\s*', line): | 3516 if Match(r'\s*else\b\s*(?:if\b|\{|$)', line): |
2985 prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0] | 3517 prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0] |
2986 if Match(r'\s*}\s*$', prevline): | 3518 if Match(r'\s*}\s*$', prevline): |
2987 error(filename, linenum, 'whitespace/newline', 4, | 3519 error(filename, linenum, 'whitespace/newline', 4, |
2988 'An else should appear on the same line as the preceding }') | 3520 'An else should appear on the same line as the preceding }') |
2989 | 3521 |
2990 # If braces come on one side of an else, they should be on both. | 3522 # If braces come on one side of an else, they should be on both. |
2991 # However, we have to worry about "else if" that spans multiple lines! | 3523 # However, we have to worry about "else if" that spans multiple lines! |
2992 if Search(r'}\s*else[^{]*$', line) or Match(r'[^}]*else\s*{', line): | 3524 if Search(r'else if\s*\(', line): # could be multi-line if |
2993 if Search(r'}\s*else if([^{]*)$', line): # could be multi-line if | 3525 brace_on_left = bool(Search(r'}\s*else if\s*\(', line)) |
2994 # find the ( after the if | 3526 # find the ( after the if |
2995 pos = line.find('else if') | 3527 pos = line.find('else if') |
2996 pos = line.find('(', pos) | 3528 pos = line.find('(', pos) |
2997 if pos > 0: | 3529 if pos > 0: |
2998 (endline, _, endpos) = CloseExpression(clean_lines, linenum, pos) | 3530 (endline, _, endpos) = CloseExpression(clean_lines, linenum, pos) |
2999 if endline[endpos:].find('{') == -1: # must be brace after if | 3531 brace_on_right = endline[endpos:].find('{') != -1 |
3000 error(filename, linenum, 'readability/braces', 5, | 3532 if brace_on_left != brace_on_right: # must be brace after if |
3001 'If an else has a brace on one side, it should have it on both') | 3533 error(filename, linenum, 'readability/braces', 5, |
3002 else: # common case: else not followed by a multi-line if | 3534 'If an else has a brace on one side, it should have it on both') |
3003 error(filename, linenum, 'readability/braces', 5, | 3535 elif Search(r'}\s*else[^{]*$', line) or Match(r'[^}]*else\s*{', line): |
3004 'If an else has a brace on one side, it should have it on both') | 3536 error(filename, linenum, 'readability/braces', 5, |
| 3537 'If an else has a brace on one side, it should have it on both') |
3005 | 3538 |
3006 # Likewise, an else should never have the else clause on the same line | 3539 # Likewise, an else should never have the else clause on the same line |
3007 if Search(r'\belse [^\s{]', line) and not Search(r'\belse if\b', line): | 3540 if Search(r'\belse [^\s{]', line) and not Search(r'\belse if\b', line): |
3008 error(filename, linenum, 'whitespace/newline', 4, | 3541 error(filename, linenum, 'whitespace/newline', 4, |
3009 'Else clause should never be on same line as else (use 2 lines)') | 3542 'Else clause should never be on same line as else (use 2 lines)') |
3010 | 3543 |
3011 # In the same way, a do/while should never be on one line | 3544 # In the same way, a do/while should never be on one line |
3012 if Match(r'\s*do [^\s{]', line): | 3545 if Match(r'\s*do [^\s{]', line): |
3013 error(filename, linenum, 'whitespace/newline', 4, | 3546 error(filename, linenum, 'whitespace/newline', 4, |
3014 'do/while clauses should not be on a single line') | 3547 'do/while clauses should not be on a single line') |
3015 | 3548 |
| 3549 # Check single-line if/else bodies. The style guide says 'curly braces are not |
| 3550 # required for single-line statements'. We additionally allow multi-line, |
| 3551 # single statements, but we reject anything with more than one semicolon in |
| 3552 # it. This means that the first semicolon after the if should be at the end of |
| 3553 # its line, and the line after that should have an indent level equal to or |
| 3554 # lower than the if. We also check for ambiguous if/else nesting without |
| 3555 # braces. |
| 3556 if_else_match = Search(r'\b(if\s*\(|else\b)', line) |
| 3557 if if_else_match and not Match(r'\s*#', line): |
| 3558 if_indent = GetIndentLevel(line) |
| 3559 endline, endlinenum, endpos = line, linenum, if_else_match.end() |
| 3560 if_match = Search(r'\bif\s*\(', line) |
| 3561 if if_match: |
| 3562 # This could be a multiline if condition, so find the end first. |
| 3563 pos = if_match.end() - 1 |
| 3564 (endline, endlinenum, endpos) = CloseExpression(clean_lines, linenum, pos) |
| 3565 # Check for an opening brace, either directly after the if or on the next |
| 3566 # line. If found, this isn't a single-statement conditional. |
| 3567 if (not Match(r'\s*{', endline[endpos:]) |
| 3568 and not (Match(r'\s*$', endline[endpos:]) |
| 3569 and endlinenum < (len(clean_lines.elided) - 1) |
| 3570 and Match(r'\s*{', clean_lines.elided[endlinenum + 1]))): |
| 3571 while (endlinenum < len(clean_lines.elided) |
| 3572 and ';' not in clean_lines.elided[endlinenum][endpos:]): |
| 3573 endlinenum += 1 |
| 3574 endpos = 0 |
| 3575 if endlinenum < len(clean_lines.elided): |
| 3576 endline = clean_lines.elided[endlinenum] |
| 3577 # We allow a mix of whitespace and closing braces (e.g. for one-liner |
| 3578 # methods) and a single \ after the semicolon (for macros) |
| 3579 endpos = endline.find(';') |
| 3580 if not Match(r';[\s}]*(\\?)$', endline[endpos:]): |
| 3581 # Semicolon isn't the last character, there's something trailing |
| 3582 error(filename, linenum, 'readability/braces', 4, |
| 3583 'If/else bodies with multiple statements require braces') |
| 3584 elif endlinenum < len(clean_lines.elided) - 1: |
| 3585 # Make sure the next line is dedented |
| 3586 next_line = clean_lines.elided[endlinenum + 1] |
| 3587 next_indent = GetIndentLevel(next_line) |
| 3588 # With ambiguous nested if statements, this will error out on the |
| 3589 # if that *doesn't* match the else, regardless of whether it's the |
| 3590 # inner one or outer one. |
| 3591 if (if_match and Match(r'\s*else\b', next_line) |
| 3592 and next_indent != if_indent): |
| 3593 error(filename, linenum, 'readability/braces', 4, |
| 3594 'Else clause should be indented at the same level as if. ' |
| 3595 'Ambiguous nested if/else chains require braces.') |
| 3596 elif next_indent > if_indent: |
| 3597 error(filename, linenum, 'readability/braces', 4, |
| 3598 'If/else bodies with multiple statements require braces') |
| 3599 |
| 3600 |
| 3601 def CheckTrailingSemicolon(filename, clean_lines, linenum, error): |
| 3602 """Looks for redundant trailing semicolon. |
| 3603 |
| 3604 Args: |
| 3605 filename: The name of the current file. |
| 3606 clean_lines: A CleansedLines instance containing the file. |
| 3607 linenum: The number of the line to check. |
| 3608 error: The function to call with any errors found. |
| 3609 """ |
| 3610 |
| 3611 line = clean_lines.elided[linenum] |
| 3612 |
3016 # Block bodies should not be followed by a semicolon. Due to C++11 | 3613 # Block bodies should not be followed by a semicolon. Due to C++11 |
3017 # brace initialization, there are more places where semicolons are | 3614 # brace initialization, there are more places where semicolons are |
3018 # required than not, so we use a whitelist approach to check these | 3615 # required than not, so we use a whitelist approach to check these |
3019 # rather than a blacklist. These are the places where "};" should | 3616 # rather than a blacklist. These are the places where "};" should |
3020 # be replaced by just "}": | 3617 # be replaced by just "}": |
3021 # 1. Some flavor of block following closing parenthesis: | 3618 # 1. Some flavor of block following closing parenthesis: |
3022 # for (;;) {}; | 3619 # for (;;) {}; |
3023 # while (...) {}; | 3620 # while (...) {}; |
3024 # switch (...) {}; | 3621 # switch (...) {}; |
3025 # Function(...) {}; | 3622 # Function(...) {}; |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3074 # - EXCLUSIVE_LOCKS_REQUIRED, SHARED_LOCKS_REQUIRED, LOCKS_EXCLUDED: | 3671 # - EXCLUSIVE_LOCKS_REQUIRED, SHARED_LOCKS_REQUIRED, LOCKS_EXCLUDED: |
3075 # | 3672 # |
3076 # We implement a whitelist of safe macros instead of a blacklist of | 3673 # We implement a whitelist of safe macros instead of a blacklist of |
3077 # unsafe macros, even though the latter appears less frequently in | 3674 # unsafe macros, even though the latter appears less frequently in |
3078 # google code and would have been easier to implement. This is because | 3675 # google code and would have been easier to implement. This is because |
3079 # the downside for getting the whitelist wrong means some extra | 3676 # the downside for getting the whitelist wrong means some extra |
3080 # semicolons, while the downside for getting the blacklist wrong | 3677 # semicolons, while the downside for getting the blacklist wrong |
3081 # would result in compile errors. | 3678 # would result in compile errors. |
3082 # | 3679 # |
3083 # In addition to macros, we also don't want to warn on compound | 3680 # In addition to macros, we also don't want to warn on compound |
3084 # literals. | 3681 # literals and lambdas. |
3085 closing_brace_pos = match.group(1).rfind(')') | 3682 closing_brace_pos = match.group(1).rfind(')') |
3086 opening_parenthesis = ReverseCloseExpression( | 3683 opening_parenthesis = ReverseCloseExpression( |
3087 clean_lines, linenum, closing_brace_pos) | 3684 clean_lines, linenum, closing_brace_pos) |
3088 if opening_parenthesis[2] > -1: | 3685 if opening_parenthesis[2] > -1: |
3089 line_prefix = opening_parenthesis[0][0:opening_parenthesis[2]] | 3686 line_prefix = opening_parenthesis[0][0:opening_parenthesis[2]] |
3090 macro = Search(r'\b([A-Z_]+)\s*$', line_prefix) | 3687 macro = Search(r'\b([A-Z_]+)\s*$', line_prefix) |
| 3688 func = Match(r'^(.*\])\s*$', line_prefix) |
3091 if ((macro and | 3689 if ((macro and |
3092 macro.group(1) not in ( | 3690 macro.group(1) not in ( |
3093 'TEST', 'TEST_F', 'MATCHER', 'MATCHER_P', 'TYPED_TEST', | 3691 'TEST', 'TEST_F', 'MATCHER', 'MATCHER_P', 'TYPED_TEST', |
3094 'EXCLUSIVE_LOCKS_REQUIRED', 'SHARED_LOCKS_REQUIRED', | 3692 'EXCLUSIVE_LOCKS_REQUIRED', 'SHARED_LOCKS_REQUIRED', |
3095 'LOCKS_EXCLUDED', 'INTERFACE_DEF')) or | 3693 'LOCKS_EXCLUDED', 'INTERFACE_DEF')) or |
| 3694 (func and not Search(r'\boperator\s*\[\s*\]', func.group(1))) or |
3096 Search(r'\s+=\s*$', line_prefix)): | 3695 Search(r'\s+=\s*$', line_prefix)): |
3097 match = None | 3696 match = None |
| 3697 if (match and |
| 3698 opening_parenthesis[1] > 1 and |
| 3699 Search(r'\]\s*$', clean_lines.elided[opening_parenthesis[1] - 1])): |
| 3700 # Multi-line lambda-expression |
| 3701 match = None |
3098 | 3702 |
3099 else: | 3703 else: |
3100 # Try matching cases 2-3. | 3704 # Try matching cases 2-3. |
3101 match = Match(r'^(.*(?:else|\)\s*const)\s*)\{', line) | 3705 match = Match(r'^(.*(?:else|\)\s*const)\s*)\{', line) |
3102 if not match: | 3706 if not match: |
3103 # Try matching cases 4-6. These are always matched on separate lines. | 3707 # Try matching cases 4-6. These are always matched on separate lines. |
3104 # | 3708 # |
3105 # Note that we can't simply concatenate the previous line to the | 3709 # Note that we can't simply concatenate the previous line to the |
3106 # current line and do a single match, otherwise we may output | 3710 # current line and do a single match, otherwise we may output |
3107 # duplicate warnings for the blank line case: | 3711 # duplicate warnings for the blank line case: |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3156 # have a separate check for semicolons preceded by whitespace. | 3760 # have a separate check for semicolons preceded by whitespace. |
3157 if end_pos >= 0 and Match(r';', end_line[end_pos:]): | 3761 if end_pos >= 0 and Match(r';', end_line[end_pos:]): |
3158 if matched.group(1) == 'if': | 3762 if matched.group(1) == 'if': |
3159 error(filename, end_linenum, 'whitespace/empty_conditional_body', 5, | 3763 error(filename, end_linenum, 'whitespace/empty_conditional_body', 5, |
3160 'Empty conditional bodies should use {}') | 3764 'Empty conditional bodies should use {}') |
3161 else: | 3765 else: |
3162 error(filename, end_linenum, 'whitespace/empty_loop_body', 5, | 3766 error(filename, end_linenum, 'whitespace/empty_loop_body', 5, |
3163 'Empty loop bodies should use {} or continue') | 3767 'Empty loop bodies should use {} or continue') |
3164 | 3768 |
3165 | 3769 |
| 3770 def FindCheckMacro(line): |
| 3771 """Find a replaceable CHECK-like macro. |
| 3772 |
| 3773 Args: |
| 3774 line: line to search on. |
| 3775 Returns: |
| 3776 (macro name, start position), or (None, -1) if no replaceable |
| 3777 macro is found. |
| 3778 """ |
| 3779 for macro in _CHECK_MACROS: |
| 3780 i = line.find(macro) |
| 3781 if i >= 0: |
| 3782 # Find opening parenthesis. Do a regular expression match here |
| 3783 # to make sure that we are matching the expected CHECK macro, as |
| 3784 # opposed to some other macro that happens to contain the CHECK |
| 3785 # substring. |
| 3786 matched = Match(r'^(.*\b' + macro + r'\s*)\(', line) |
| 3787 if not matched: |
| 3788 continue |
| 3789 return (macro, len(matched.group(1))) |
| 3790 return (None, -1) |
| 3791 |
| 3792 |
3166 def CheckCheck(filename, clean_lines, linenum, error): | 3793 def CheckCheck(filename, clean_lines, linenum, error): |
3167 """Checks the use of CHECK and EXPECT macros. | 3794 """Checks the use of CHECK and EXPECT macros. |
3168 | 3795 |
3169 Args: | 3796 Args: |
3170 filename: The name of the current file. | 3797 filename: The name of the current file. |
3171 clean_lines: A CleansedLines instance containing the file. | 3798 clean_lines: A CleansedLines instance containing the file. |
3172 linenum: The number of the line to check. | 3799 linenum: The number of the line to check. |
3173 error: The function to call with any errors found. | 3800 error: The function to call with any errors found. |
3174 """ | 3801 """ |
3175 | 3802 |
3176 # Decide the set of replacement macros that should be suggested | 3803 # Decide the set of replacement macros that should be suggested |
3177 lines = clean_lines.elided | 3804 lines = clean_lines.elided |
3178 check_macro = None | 3805 (check_macro, start_pos) = FindCheckMacro(lines[linenum]) |
3179 start_pos = -1 | 3806 if not check_macro: |
3180 for macro in _CHECK_MACROS: | |
3181 i = lines[linenum].find(macro) | |
3182 if i >= 0: | |
3183 check_macro = macro | |
3184 | |
3185 # Find opening parenthesis. Do a regular expression match here | |
3186 # to make sure that we are matching the expected CHECK macro, as | |
3187 # opposed to some other macro that happens to contain the CHECK | |
3188 # substring. | |
3189 matched = Match(r'^(.*\b' + check_macro + r'\s*)\(', lines[linenum]) | |
3190 if not matched: | |
3191 continue | |
3192 start_pos = len(matched.group(1)) | |
3193 break | |
3194 if not check_macro or start_pos < 0: | |
3195 # Don't waste time here if line doesn't contain 'CHECK' or 'EXPECT' | |
3196 return | 3807 return |
3197 | 3808 |
3198 # Find end of the boolean expression by matching parentheses | 3809 # Find end of the boolean expression by matching parentheses |
3199 (last_line, end_line, end_pos) = CloseExpression( | 3810 (last_line, end_line, end_pos) = CloseExpression( |
3200 clean_lines, linenum, start_pos) | 3811 clean_lines, linenum, start_pos) |
3201 if end_pos < 0: | 3812 if end_pos < 0: |
3202 return | 3813 return |
3203 if linenum == end_line: | 3814 if linenum == end_line: |
3204 expression = lines[linenum][start_pos + 1:end_pos - 1] | 3815 expression = lines[linenum][start_pos + 1:end_pos - 1] |
3205 else: | 3816 else: |
3206 expression = lines[linenum][start_pos + 1:] | 3817 expression = lines[linenum][start_pos + 1:] |
3207 for i in xrange(linenum + 1, end_line): | 3818 for i in xrange(linenum + 1, end_line): |
3208 expression += lines[i] | 3819 expression += lines[i] |
3209 expression += last_line[0:end_pos - 1] | 3820 expression += last_line[0:end_pos - 1] |
3210 | 3821 |
3211 # Parse expression so that we can take parentheses into account. | 3822 # Parse expression so that we can take parentheses into account. |
3212 # This avoids false positives for inputs like "CHECK((a < 4) == b)", | 3823 # This avoids false positives for inputs like "CHECK((a < 4) == b)", |
3213 # which is not replaceable by CHECK_LE. | 3824 # which is not replaceable by CHECK_LE. |
3214 lhs = '' | 3825 lhs = '' |
3215 rhs = '' | 3826 rhs = '' |
3216 operator = None | 3827 operator = None |
3217 while expression: | 3828 while expression: |
3218 matched = Match(r'^\s*(<<|<<=|>>|>>=|->\*|->|&&|\|\||' | 3829 matched = Match(r'^\s*(<<|<<=|>>|>>=|->\*|->|&&|\|\||' |
3219 r'==|!=|>=|>|<=|<|\()(.*)$', expression) | 3830 r'==|!=|>=|>|<=|<|\()(.*)$', expression) |
3220 if matched: | 3831 if matched: |
3221 token = matched.group(1) | 3832 token = matched.group(1) |
3222 if token == '(': | 3833 if token == '(': |
3223 # Parenthesized operand | 3834 # Parenthesized operand |
3224 expression = matched.group(2) | 3835 expression = matched.group(2) |
3225 (end, _) = FindEndOfExpressionInLine(expression, 0, 1, '(', ')') | 3836 (end, _) = FindEndOfExpressionInLine(expression, 0, ['(']) |
3226 if end < 0: | 3837 if end < 0: |
3227 return # Unmatched parenthesis | 3838 return # Unmatched parenthesis |
3228 lhs += '(' + expression[0:end] | 3839 lhs += '(' + expression[0:end] |
3229 expression = expression[end:] | 3840 expression = expression[end:] |
3230 elif token in ('&&', '||'): | 3841 elif token in ('&&', '||'): |
3231 # Logical and/or operators. This means the expression | 3842 # Logical and/or operators. This means the expression |
3232 # contains more than one term, for example: | 3843 # contains more than one term, for example: |
3233 # CHECK(42 < a && a < b); | 3844 # CHECK(42 < a && a < b); |
3234 # | 3845 # |
3235 # These are not replaceable with CHECK_LE, so bail out early. | 3846 # These are not replaceable with CHECK_LE, so bail out early. |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3350 | 3961 |
3351 Most of these rules are hard to test (naming, comment style), but we | 3962 Most of these rules are hard to test (naming, comment style), but we |
3352 do what we can. In particular we check for 2-space indents, line lengths, | 3963 do what we can. In particular we check for 2-space indents, line lengths, |
3353 tab usage, spaces inside code, etc. | 3964 tab usage, spaces inside code, etc. |
3354 | 3965 |
3355 Args: | 3966 Args: |
3356 filename: The name of the current file. | 3967 filename: The name of the current file. |
3357 clean_lines: A CleansedLines instance containing the file. | 3968 clean_lines: A CleansedLines instance containing the file. |
3358 linenum: The number of the line to check. | 3969 linenum: The number of the line to check. |
3359 file_extension: The extension (without the dot) of the filename. | 3970 file_extension: The extension (without the dot) of the filename. |
3360 nesting_state: A _NestingState instance which maintains information about | 3971 nesting_state: A NestingState instance which maintains information about |
3361 the current stack of nested blocks being parsed. | 3972 the current stack of nested blocks being parsed. |
3362 error: The function to call with any errors found. | 3973 error: The function to call with any errors found. |
3363 """ | 3974 """ |
3364 | 3975 |
3365 # Don't use "elided" lines here, otherwise we can't check commented lines. | 3976 # Don't use "elided" lines here, otherwise we can't check commented lines. |
3366 # Don't want to use "raw" either, because we don't want to check inside C++11 | 3977 # Don't want to use "raw" either, because we don't want to check inside C++11 |
3367 # raw strings, | 3978 # raw strings, |
3368 raw_lines = clean_lines.lines_without_raw_strings | 3979 raw_lines = clean_lines.lines_without_raw_strings |
3369 line = raw_lines[linenum] | 3980 line = raw_lines[linenum] |
3370 | 3981 |
3371 if line.find('\t') != -1: | 3982 if line.find('\t') != -1: |
3372 error(filename, linenum, 'whitespace/tab', 1, | 3983 error(filename, linenum, 'whitespace/tab', 1, |
3373 'Tab found; better to use spaces') | 3984 'Tab found; better to use spaces') |
3374 | 3985 |
3375 # One or three blank spaces at the beginning of the line is weird; it's | 3986 # One or three blank spaces at the beginning of the line is weird; it's |
3376 # hard to reconcile that with 2-space indents. | 3987 # hard to reconcile that with 2-space indents. |
3377 # NOTE: here are the conditions rob pike used for his tests. Mine aren't | 3988 # NOTE: here are the conditions rob pike used for his tests. Mine aren't |
3378 # as sophisticated, but it may be worth becoming so: RLENGTH==initial_spaces | 3989 # as sophisticated, but it may be worth becoming so: RLENGTH==initial_spaces |
3379 # if(RLENGTH > 20) complain = 0; | 3990 # if(RLENGTH > 20) complain = 0; |
3380 # if(match($0, " +(error|private|public|protected):")) complain = 0; | 3991 # if(match($0, " +(error|private|public|protected):")) complain = 0; |
3381 # if(match(prev, "&& *$")) complain = 0; | 3992 # if(match(prev, "&& *$")) complain = 0; |
3382 # if(match(prev, "\\|\\| *$")) complain = 0; | 3993 # if(match(prev, "\\|\\| *$")) complain = 0; |
3383 # if(match(prev, "[\",=><] *$")) complain = 0; | 3994 # if(match(prev, "[\",=><] *$")) complain = 0; |
3384 # if(match($0, " <<")) complain = 0; | 3995 # if(match($0, " <<")) complain = 0; |
3385 # if(match(prev, " +for \\(")) complain = 0; | 3996 # if(match(prev, " +for \\(")) complain = 0; |
3386 # if(prevodd && match(prevprev, " +for \\(")) complain = 0; | 3997 # if(prevodd && match(prevprev, " +for \\(")) complain = 0; |
| 3998 scope_or_label_pattern = r'\s*\w+\s*:\s*\\?$' |
| 3999 classinfo = nesting_state.InnermostClass() |
3387 initial_spaces = 0 | 4000 initial_spaces = 0 |
3388 cleansed_line = clean_lines.elided[linenum] | 4001 cleansed_line = clean_lines.elided[linenum] |
3389 while initial_spaces < len(line) and line[initial_spaces] == ' ': | 4002 while initial_spaces < len(line) and line[initial_spaces] == ' ': |
3390 initial_spaces += 1 | 4003 initial_spaces += 1 |
3391 if line and line[-1].isspace(): | 4004 if line and line[-1].isspace(): |
3392 error(filename, linenum, 'whitespace/end_of_line', 4, | 4005 error(filename, linenum, 'whitespace/end_of_line', 4, |
3393 'Line ends in whitespace. Consider deleting these extra spaces.') | 4006 'Line ends in whitespace. Consider deleting these extra spaces.') |
3394 # There are certain situations we allow one space, notably for section labels | 4007 # There are certain situations we allow one space, notably for |
| 4008 # section labels, and also lines containing multi-line raw strings. |
3395 elif ((initial_spaces == 1 or initial_spaces == 3) and | 4009 elif ((initial_spaces == 1 or initial_spaces == 3) and |
3396 not Match(r'\s*\w+\s*:\s*$', cleansed_line)): | 4010 not Match(scope_or_label_pattern, cleansed_line) and |
| 4011 not (clean_lines.raw_lines[linenum] != line and |
| 4012 Match(r'^\s*""', line))): |
3397 error(filename, linenum, 'whitespace/indent', 3, | 4013 error(filename, linenum, 'whitespace/indent', 3, |
3398 'Weird number of spaces at line-start. ' | 4014 'Weird number of spaces at line-start. ' |
3399 'Are you using a 2-space indent?') | 4015 'Are you using a 2-space indent?') |
3400 | 4016 |
3401 # Check if the line is a header guard. | 4017 # Check if the line is a header guard. |
3402 is_header_guard = False | 4018 is_header_guard = False |
3403 if file_extension == 'h': | 4019 if file_extension == 'h': |
3404 cppvar = GetHeaderGuardCPPVariable(filename) | 4020 cppvar = GetHeaderGuardCPPVariable(filename) |
3405 if (line.startswith('#ifndef %s' % cppvar) or | 4021 if (line.startswith('#ifndef %s' % cppvar) or |
3406 line.startswith('#define %s' % cppvar) or | 4022 line.startswith('#define %s' % cppvar) or |
(...skipping 27 matching lines...) Expand all Loading... |
3434 GetPreviousNonBlankLine(clean_lines, linenum)[0].find(';') != -1) and | 4050 GetPreviousNonBlankLine(clean_lines, linenum)[0].find(';') != -1) and |
3435 # It's ok to have many commands in a switch case that fits in 1 line | 4051 # It's ok to have many commands in a switch case that fits in 1 line |
3436 not ((cleansed_line.find('case ') != -1 or | 4052 not ((cleansed_line.find('case ') != -1 or |
3437 cleansed_line.find('default:') != -1) and | 4053 cleansed_line.find('default:') != -1) and |
3438 cleansed_line.find('break;') != -1)): | 4054 cleansed_line.find('break;') != -1)): |
3439 error(filename, linenum, 'whitespace/newline', 0, | 4055 error(filename, linenum, 'whitespace/newline', 0, |
3440 'More than one command on the same line') | 4056 'More than one command on the same line') |
3441 | 4057 |
3442 # Some more style checks | 4058 # Some more style checks |
3443 CheckBraces(filename, clean_lines, linenum, error) | 4059 CheckBraces(filename, clean_lines, linenum, error) |
| 4060 CheckTrailingSemicolon(filename, clean_lines, linenum, error) |
3444 CheckEmptyBlockBody(filename, clean_lines, linenum, error) | 4061 CheckEmptyBlockBody(filename, clean_lines, linenum, error) |
3445 CheckAccess(filename, clean_lines, linenum, nesting_state, error) | 4062 CheckAccess(filename, clean_lines, linenum, nesting_state, error) |
3446 CheckSpacing(filename, clean_lines, linenum, nesting_state, error) | 4063 CheckSpacing(filename, clean_lines, linenum, nesting_state, error) |
| 4064 CheckOperatorSpacing(filename, clean_lines, linenum, error) |
| 4065 CheckParenthesisSpacing(filename, clean_lines, linenum, error) |
| 4066 CheckCommaSpacing(filename, clean_lines, linenum, error) |
| 4067 CheckBracesSpacing(filename, clean_lines, linenum, error) |
| 4068 CheckSpacingForFunctionCall(filename, clean_lines, linenum, error) |
| 4069 CheckRValueReference(filename, clean_lines, linenum, nesting_state, error) |
3447 CheckCheck(filename, clean_lines, linenum, error) | 4070 CheckCheck(filename, clean_lines, linenum, error) |
3448 CheckAltTokens(filename, clean_lines, linenum, error) | 4071 CheckAltTokens(filename, clean_lines, linenum, error) |
3449 classinfo = nesting_state.InnermostClass() | 4072 classinfo = nesting_state.InnermostClass() |
3450 if classinfo: | 4073 if classinfo: |
3451 CheckSectionSpacing(filename, clean_lines, classinfo, linenum, error) | 4074 CheckSectionSpacing(filename, clean_lines, classinfo, linenum, error) |
3452 | 4075 |
3453 | 4076 |
3454 _RE_PATTERN_INCLUDE_NEW_STYLE = re.compile(r'#include +"[^/]+\.h"') | 4077 _RE_PATTERN_INCLUDE_NEW_STYLE = re.compile(r'#include +"[^/]+\.h"') |
3455 _RE_PATTERN_INCLUDE = re.compile(r'^\s*#\s*include\s*([<"])([^>"]*)[>"].*$') | 4078 _RE_PATTERN_INCLUDE = re.compile(r'^\s*#\s*include\s*([<"])([^>"]*)[>"].*$') |
3456 # Matches the first component of a filename delimited by -s and _s. That is: | 4079 # Matches the first component of a filename delimited by -s and _s. That is: |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3573 applicable to #include lines in CheckLanguage must be put here. | 4196 applicable to #include lines in CheckLanguage must be put here. |
3574 | 4197 |
3575 Args: | 4198 Args: |
3576 filename: The name of the current file. | 4199 filename: The name of the current file. |
3577 clean_lines: A CleansedLines instance containing the file. | 4200 clean_lines: A CleansedLines instance containing the file. |
3578 linenum: The number of the line to check. | 4201 linenum: The number of the line to check. |
3579 include_state: An _IncludeState instance in which the headers are inserted. | 4202 include_state: An _IncludeState instance in which the headers are inserted. |
3580 error: The function to call with any errors found. | 4203 error: The function to call with any errors found. |
3581 """ | 4204 """ |
3582 fileinfo = FileInfo(filename) | 4205 fileinfo = FileInfo(filename) |
3583 | |
3584 line = clean_lines.lines[linenum] | 4206 line = clean_lines.lines[linenum] |
3585 | 4207 |
3586 # "include" should use the new style "foo/bar.h" instead of just "bar.h" | 4208 # "include" should use the new style "foo/bar.h" instead of just "bar.h" |
3587 if _RE_PATTERN_INCLUDE_NEW_STYLE.search(line): | 4209 if _RE_PATTERN_INCLUDE_NEW_STYLE.search(line): |
3588 error(filename, linenum, 'build/include', 4, | 4210 error(filename, linenum, 'build/include', 4, |
3589 'Include the directory when naming .h files') | 4211 'Include the directory when naming .h files') |
3590 | 4212 |
3591 # we shouldn't include a file more than once. actually, there are a | 4213 # we shouldn't include a file more than once. actually, there are a |
3592 # handful of instances where doing so is okay, but in general it's | 4214 # handful of instances where doing so is okay, but in general it's |
3593 # not. | 4215 # not. |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3626 'Include "%s" not in alphabetical order' % include) | 4248 'Include "%s" not in alphabetical order' % include) |
3627 include_state.SetLastHeader(canonical_include) | 4249 include_state.SetLastHeader(canonical_include) |
3628 | 4250 |
3629 # Look for any of the stream classes that are part of standard C++. | 4251 # Look for any of the stream classes that are part of standard C++. |
3630 match = _RE_PATTERN_INCLUDE.match(line) | 4252 match = _RE_PATTERN_INCLUDE.match(line) |
3631 if match: | 4253 if match: |
3632 include = match.group(2) | 4254 include = match.group(2) |
3633 if Match(r'(f|ind|io|i|o|parse|pf|stdio|str|)?stream$', include): | 4255 if Match(r'(f|ind|io|i|o|parse|pf|stdio|str|)?stream$', include): |
3634 # Many unit tests use cout, so we exempt them. | 4256 # Many unit tests use cout, so we exempt them. |
3635 if not _IsTestFilename(filename): | 4257 if not _IsTestFilename(filename): |
3636 error(filename, linenum, 'readability/streams', 3, | 4258 # Suggest a different header for ostream |
3637 'Streams are highly discouraged.') | 4259 if include == 'ostream': |
| 4260 error(filename, linenum, 'readability/streams', 3, |
| 4261 'For logging, include "base/logging.h" instead of <ostream>.') |
| 4262 else: |
| 4263 error(filename, linenum, 'readability/streams', 3, |
| 4264 'Streams are highly discouraged.') |
3638 | 4265 |
3639 | 4266 |
3640 def _GetTextInside(text, start_pattern): | 4267 def _GetTextInside(text, start_pattern): |
3641 r"""Retrieves all the text between matching open and close parentheses. | 4268 r"""Retrieves all the text between matching open and close parentheses. |
3642 | 4269 |
3643 Given a string of lines and a regular expression string, retrieve all the text | 4270 Given a string of lines and a regular expression string, retrieve all the text |
3644 following the expression and between opening punctuation symbols like | 4271 following the expression and between opening punctuation symbols like |
3645 (, [, or {, and the matching close-punctuation symbol. This properly nested | 4272 (, [, or {, and the matching close-punctuation symbol. This properly nested |
3646 occurrences of the punctuations, so for the text like | 4273 occurrences of the punctuations, so for the text like |
3647 printf(a(), b(c())); | 4274 printf(a(), b(c())); |
3648 a call to _GetTextInside(text, r'printf\(') will return 'a(), b(c())'. | 4275 a call to _GetTextInside(text, r'printf\(') will return 'a(), b(c())'. |
3649 start_pattern must match string having an open punctuation symbol at the end. | 4276 start_pattern must match string having an open punctuation symbol at the end. |
3650 | 4277 |
3651 Args: | 4278 Args: |
3652 text: The lines to extract text. Its comments and strings must be elided. | 4279 text: The lines to extract text. Its comments and strings must be elided. |
3653 It can be single line and can span multiple lines. | 4280 It can be single line and can span multiple lines. |
3654 start_pattern: The regexp string indicating where to start extracting | 4281 start_pattern: The regexp string indicating where to start extracting |
3655 the text. | 4282 the text. |
3656 Returns: | 4283 Returns: |
3657 The extracted text. | 4284 The extracted text. |
3658 None if either the opening string or ending punctuation could not be found. | 4285 None if either the opening string or ending punctuation could not be found. |
3659 """ | 4286 """ |
3660 # TODO(sugawarayu): Audit cpplint.py to see what places could be profitably | 4287 # TODO(unknown): Audit cpplint.py to see what places could be profitably |
3661 # rewritten to use _GetTextInside (and use inferior regexp matching today). | 4288 # rewritten to use _GetTextInside (and use inferior regexp matching today). |
3662 | 4289 |
3663 # Give opening punctuations to get the matching close-punctuations. | 4290 # Give opening punctuations to get the matching close-punctuations. |
3664 matching_punctuation = {'(': ')', '{': '}', '[': ']'} | 4291 matching_punctuation = {'(': ')', '{': '}', '[': ']'} |
3665 closing_punctuation = set(matching_punctuation.itervalues()) | 4292 closing_punctuation = set(matching_punctuation.itervalues()) |
3666 | 4293 |
3667 # Find the position to start extracting text. | 4294 # Find the position to start extracting text. |
3668 match = re.search(start_pattern, text, re.M) | 4295 match = re.search(start_pattern, text, re.M) |
3669 if not match: # start_pattern not found in text. | 4296 if not match: # start_pattern not found in text. |
3670 return None | 4297 return None |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3725 | 4352 |
3726 Some of these rules are hard to test (function overloading, using | 4353 Some of these rules are hard to test (function overloading, using |
3727 uint32 inappropriately), but we do the best we can. | 4354 uint32 inappropriately), but we do the best we can. |
3728 | 4355 |
3729 Args: | 4356 Args: |
3730 filename: The name of the current file. | 4357 filename: The name of the current file. |
3731 clean_lines: A CleansedLines instance containing the file. | 4358 clean_lines: A CleansedLines instance containing the file. |
3732 linenum: The number of the line to check. | 4359 linenum: The number of the line to check. |
3733 file_extension: The extension (without the dot) of the filename. | 4360 file_extension: The extension (without the dot) of the filename. |
3734 include_state: An _IncludeState instance in which the headers are inserted. | 4361 include_state: An _IncludeState instance in which the headers are inserted. |
3735 nesting_state: A _NestingState instance which maintains information about | 4362 nesting_state: A NestingState instance which maintains information about |
3736 the current stack of nested blocks being parsed. | 4363 the current stack of nested blocks being parsed. |
3737 error: The function to call with any errors found. | 4364 error: The function to call with any errors found. |
3738 """ | 4365 """ |
3739 # If the line is empty or consists of entirely a comment, no need to | 4366 # If the line is empty or consists of entirely a comment, no need to |
3740 # check it. | 4367 # check it. |
3741 line = clean_lines.elided[linenum] | 4368 line = clean_lines.elided[linenum] |
3742 if not line: | 4369 if not line: |
3743 return | 4370 return |
3744 | 4371 |
3745 match = _RE_PATTERN_INCLUDE.search(line) | 4372 match = _RE_PATTERN_INCLUDE.search(line) |
3746 if match: | 4373 if match: |
3747 CheckIncludeLine(filename, clean_lines, linenum, include_state, error) | 4374 CheckIncludeLine(filename, clean_lines, linenum, include_state, error) |
3748 return | 4375 return |
3749 | 4376 |
3750 # Reset include state across preprocessor directives. This is meant | 4377 # Reset include state across preprocessor directives. This is meant |
3751 # to silence warnings for conditional includes. | 4378 # to silence warnings for conditional includes. |
3752 if Match(r'^\s*#\s*(?:ifdef|elif|else|endif)\b', line): | 4379 if Match(r'^\s*#\s*(?:ifdef|elif|else|endif)\b', line): |
3753 include_state.ResetSection() | 4380 include_state.ResetSection() |
3754 | 4381 |
3755 # Make Windows paths like Unix. | 4382 # Make Windows paths like Unix. |
3756 fullname = os.path.abspath(filename).replace('\\', '/') | 4383 fullname = os.path.abspath(filename).replace('\\', '/') |
3757 | 4384 |
3758 # TODO(unknown): figure out if they're using default arguments in fn proto. | 4385 # Perform other checks now that we are sure that this is not an include line |
3759 | 4386 CheckCasts(filename, clean_lines, linenum, error) |
3760 # Check to see if they're using an conversion function cast. | 4387 CheckGlobalStatic(filename, clean_lines, linenum, error) |
3761 # I just try to capture the most common basic types, though there are more. | 4388 CheckPrintf(filename, clean_lines, linenum, error) |
3762 # Parameterless conversion functions, such as bool(), are allowed as they are | |
3763 # probably a member operator declaration or default constructor. | |
3764 match = Search( | |
3765 r'(\bnew\s+)?\b' # Grab 'new' operator, if it's there | |
3766 r'(int|float|double|bool|char|int32|uint32|int64|uint64)' | |
3767 r'(\([^)].*)', line) | |
3768 if match: | |
3769 matched_new = match.group(1) | |
3770 matched_type = match.group(2) | |
3771 matched_funcptr = match.group(3) | |
3772 | |
3773 # gMock methods are defined using some variant of MOCK_METHODx(name, type) | |
3774 # where type may be float(), int(string), etc. Without context they are | |
3775 # virtually indistinguishable from int(x) casts. Likewise, gMock's | |
3776 # MockCallback takes a template parameter of the form return_type(arg_type), | |
3777 # which looks much like the cast we're trying to detect. | |
3778 # | |
3779 # std::function<> wrapper has a similar problem. | |
3780 # | |
3781 # Return types for function pointers also look like casts if they | |
3782 # don't have an extra space. | |
3783 if (matched_new is None and # If new operator, then this isn't a cast | |
3784 not (Match(r'^\s*MOCK_(CONST_)?METHOD\d+(_T)?\(', line) or | |
3785 Search(r'\bMockCallback<.*>', line) or | |
3786 Search(r'\bstd::function<.*>', line)) and | |
3787 not (matched_funcptr and | |
3788 Match(r'\((?:[^() ]+::\s*\*\s*)?[^() ]+\)\s*\(', | |
3789 matched_funcptr))): | |
3790 # Try a bit harder to catch gmock lines: the only place where | |
3791 # something looks like an old-style cast is where we declare the | |
3792 # return type of the mocked method, and the only time when we | |
3793 # are missing context is if MOCK_METHOD was split across | |
3794 # multiple lines. The missing MOCK_METHOD is usually one or two | |
3795 # lines back, so scan back one or two lines. | |
3796 # | |
3797 # It's not possible for gmock macros to appear in the first 2 | |
3798 # lines, since the class head + section name takes up 2 lines. | |
3799 if (linenum < 2 or | |
3800 not (Match(r'^\s*MOCK_(?:CONST_)?METHOD\d+(?:_T)?\((?:\S+,)?\s*$', | |
3801 clean_lines.elided[linenum - 1]) or | |
3802 Match(r'^\s*MOCK_(?:CONST_)?METHOD\d+(?:_T)?\(\s*$', | |
3803 clean_lines.elided[linenum - 2]))): | |
3804 error(filename, linenum, 'readability/casting', 4, | |
3805 'Using deprecated casting style. ' | |
3806 'Use static_cast<%s>(...) instead' % | |
3807 matched_type) | |
3808 | |
3809 CheckCStyleCast(filename, linenum, line, clean_lines.raw_lines[linenum], | |
3810 'static_cast', | |
3811 r'\((int|float|double|bool|char|u?int(16|32|64))\)', error) | |
3812 | |
3813 # This doesn't catch all cases. Consider (const char * const)"hello". | |
3814 # | |
3815 # (char *) "foo" should always be a const_cast (reinterpret_cast won't | |
3816 # compile). | |
3817 if CheckCStyleCast(filename, linenum, line, clean_lines.raw_lines[linenum], | |
3818 'const_cast', r'\((char\s?\*+\s?)\)\s*"', error): | |
3819 pass | |
3820 else: | |
3821 # Check pointer casts for other than string constants | |
3822 CheckCStyleCast(filename, linenum, line, clean_lines.raw_lines[linenum], | |
3823 'reinterpret_cast', r'\((\w+\s?\*+\s?)\)', error) | |
3824 | |
3825 # In addition, we look for people taking the address of a cast. This | |
3826 # is dangerous -- casts can assign to temporaries, so the pointer doesn't | |
3827 # point where you think. | |
3828 match = Search( | |
3829 r'(?:&\(([^)]+)\)[\w(])|' | |
3830 r'(?:&(static|dynamic|down|reinterpret)_cast\b)', line) | |
3831 if match and match.group(1) != '*': | |
3832 error(filename, linenum, 'runtime/casting', 4, | |
3833 ('Are you taking an address of a cast? ' | |
3834 'This is dangerous: could be a temp var. ' | |
3835 'Take the address before doing the cast, rather than after')) | |
3836 | |
3837 # Create an extended_line, which is the concatenation of the current and | |
3838 # next lines, for more effective checking of code that may span more than one | |
3839 # line. | |
3840 if linenum + 1 < clean_lines.NumLines(): | |
3841 extended_line = line + clean_lines.elided[linenum + 1] | |
3842 else: | |
3843 extended_line = line | |
3844 | |
3845 # Check for people declaring static/global STL strings at the top level. | |
3846 # This is dangerous because the C++ language does not guarantee that | |
3847 # globals with constructors are initialized before the first access. | |
3848 match = Match( | |
3849 r'((?:|static +)(?:|const +))string +([a-zA-Z0-9_:]+)\b(.*)', | |
3850 line) | |
3851 # Make sure it's not a function. | |
3852 # Function template specialization looks like: "string foo<Type>(...". | |
3853 # Class template definitions look like: "string Foo<Type>::Method(...". | |
3854 # | |
3855 # Also ignore things that look like operators. These are matched separately | |
3856 # because operator names cross non-word boundaries. If we change the pattern | |
3857 # above, we would decrease the accuracy of matching identifiers. | |
3858 if (match and | |
3859 not Search(r'\boperator\W', line) and | |
3860 not Match(r'\s*(<.*>)?(::[a-zA-Z0-9_]+)?\s*\(([^"]|$)', match.group(3))): | |
3861 error(filename, linenum, 'runtime/string', 4, | |
3862 'For a static/global string constant, use a C style string instead: ' | |
3863 '"%schar %s[]".' % | |
3864 (match.group(1), match.group(2))) | |
3865 | |
3866 if Search(r'\b([A-Za-z0-9_]*_)\(\1\)', line): | |
3867 error(filename, linenum, 'runtime/init', 4, | |
3868 'You seem to be initializing a member variable with itself.') | |
3869 | 4389 |
3870 if file_extension == 'h': | 4390 if file_extension == 'h': |
3871 # TODO(unknown): check that 1-arg constructors are explicit. | 4391 # TODO(unknown): check that 1-arg constructors are explicit. |
3872 # How to tell it's a constructor? | 4392 # How to tell it's a constructor? |
3873 # (handled in CheckForNonStandardConstructs for now) | 4393 # (handled in CheckForNonStandardConstructs for now) |
3874 # TODO(unknown): check that classes have DISALLOW_EVIL_CONSTRUCTORS | 4394 # TODO(unknown): check that classes have DISALLOW_EVIL_CONSTRUCTORS |
3875 # (level 1 error) | 4395 # (level 1 error) |
3876 pass | 4396 pass |
3877 | 4397 |
3878 # Check if people are using the verboten C basic types. The only exception | 4398 # Check if people are using the verboten C basic types. The only exception |
3879 # we regularly allow is "unsigned short port" for port. | 4399 # we regularly allow is "unsigned short port" for port. |
3880 if Search(r'\bshort port\b', line): | 4400 if Search(r'\bshort port\b', line): |
3881 if not Search(r'\bunsigned short port\b', line): | 4401 if not Search(r'\bunsigned short port\b', line): |
3882 error(filename, linenum, 'runtime/int', 4, | 4402 error(filename, linenum, 'runtime/int', 4, |
3883 'Use "unsigned short" for ports, not "short"') | 4403 'Use "unsigned short" for ports, not "short"') |
3884 else: | 4404 else: |
3885 match = Search(r'\b(short|long(?! +double)|long long)\b', line) | 4405 match = Search(r'\b(short|long(?! +double)|long long)\b', line) |
3886 if match: | 4406 if match: |
3887 error(filename, linenum, 'runtime/int', 4, | 4407 error(filename, linenum, 'runtime/int', 4, |
3888 'Use int16/int64/etc, rather than the C type %s' % match.group(1)) | 4408 'Use int16/int64/etc, rather than the C type %s' % match.group(1)) |
3889 | 4409 |
3890 # When snprintf is used, the second argument shouldn't be a literal. | |
3891 match = Search(r'snprintf\s*\(([^,]*),\s*([0-9]*)\s*,', line) | |
3892 if match and match.group(2) != '0': | |
3893 # If 2nd arg is zero, snprintf is used to calculate size. | |
3894 error(filename, linenum, 'runtime/printf', 3, | |
3895 'If you can, use sizeof(%s) instead of %s as the 2nd arg ' | |
3896 'to snprintf.' % (match.group(1), match.group(2))) | |
3897 | |
3898 # Check if some verboten C functions are being used. | |
3899 if Search(r'\bsprintf\b', line): | |
3900 error(filename, linenum, 'runtime/printf', 5, | |
3901 'Never use sprintf. Use snprintf instead.') | |
3902 match = Search(r'\b(strcpy|strcat)\b', line) | |
3903 if match: | |
3904 error(filename, linenum, 'runtime/printf', 4, | |
3905 'Almost always, snprintf is better than %s' % match.group(1)) | |
3906 | |
3907 # Check if some verboten operator overloading is going on | 4410 # Check if some verboten operator overloading is going on |
3908 # TODO(unknown): catch out-of-line unary operator&: | 4411 # TODO(unknown): catch out-of-line unary operator&: |
3909 # class X {}; | 4412 # class X {}; |
3910 # int operator&(const X& x) { return 42; } // unary operator& | 4413 # int operator&(const X& x) { return 42; } // unary operator& |
3911 # The trick is it's hard to tell apart from binary operator&: | 4414 # The trick is it's hard to tell apart from binary operator&: |
3912 # class Y { int operator&(const Y& x) { return 23; } }; // binary operator& | 4415 # class Y { int operator&(const Y& x) { return 23; } }; // binary operator& |
3913 if Search(r'\boperator\s*&\s*\(\s*\)', line): | 4416 if Search(r'\boperator\s*&\s*\(\s*\)', line): |
3914 error(filename, linenum, 'runtime/operator', 4, | 4417 error(filename, linenum, 'runtime/operator', 4, |
3915 'Unary operator& is dangerous. Do not use it.') | 4418 'Unary operator& is dangerous. Do not use it.') |
3916 | 4419 |
3917 # Check for suspicious usage of "if" like | 4420 # Check for suspicious usage of "if" like |
3918 # } if (a == b) { | 4421 # } if (a == b) { |
3919 if Search(r'\}\s*if\s*\(', line): | 4422 if Search(r'\}\s*if\s*\(', line): |
3920 error(filename, linenum, 'readability/braces', 4, | 4423 error(filename, linenum, 'readability/braces', 4, |
3921 'Did you mean "else if"? If not, start a new line for "if".') | 4424 'Did you mean "else if"? If not, start a new line for "if".') |
3922 | 4425 |
3923 # Check for potential format string bugs like printf(foo). | 4426 # Check for potential format string bugs like printf(foo). |
3924 # We constrain the pattern not to pick things like DocidForPrintf(foo). | 4427 # We constrain the pattern not to pick things like DocidForPrintf(foo). |
3925 # Not perfect but it can catch printf(foo.c_str()) and printf(foo->c_str()) | 4428 # Not perfect but it can catch printf(foo.c_str()) and printf(foo->c_str()) |
3926 # TODO(sugawarayu): Catch the following case. Need to change the calling | 4429 # TODO(unknown): Catch the following case. Need to change the calling |
3927 # convention of the whole function to process multiple line to handle it. | 4430 # convention of the whole function to process multiple line to handle it. |
3928 # printf( | 4431 # printf( |
3929 # boy_this_is_a_really_long_variable_that_cannot_fit_on_the_prev_line); | 4432 # boy_this_is_a_really_long_variable_that_cannot_fit_on_the_prev_line); |
3930 printf_args = _GetTextInside(line, r'(?i)\b(string)?printf\s*\(') | 4433 printf_args = _GetTextInside(line, r'(?i)\b(string)?printf\s*\(') |
3931 if printf_args: | 4434 if printf_args: |
3932 match = Match(r'([\w.\->()]+)$', printf_args) | 4435 match = Match(r'([\w.\->()]+)$', printf_args) |
3933 if match and match.group(1) != '__VA_ARGS__': | 4436 if match and match.group(1) != '__VA_ARGS__': |
3934 function_name = re.search(r'\b((?:string)?printf)\s*\(', | 4437 function_name = re.search(r'\b((?:string)?printf)\s*\(', |
3935 line, re.I).group(1) | 4438 line, re.I).group(1) |
3936 error(filename, linenum, 'runtime/printf', 4, | 4439 error(filename, linenum, 'runtime/printf', 4, |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4012 # macros are typically OK, so we allow use of "namespace {" on lines | 4515 # macros are typically OK, so we allow use of "namespace {" on lines |
4013 # that end with backslashes. | 4516 # that end with backslashes. |
4014 if (file_extension == 'h' | 4517 if (file_extension == 'h' |
4015 and Search(r'\bnamespace\s*{', line) | 4518 and Search(r'\bnamespace\s*{', line) |
4016 and line[-1] != '\\'): | 4519 and line[-1] != '\\'): |
4017 error(filename, linenum, 'build/namespaces', 4, | 4520 error(filename, linenum, 'build/namespaces', 4, |
4018 'Do not use unnamed namespaces in header files. See ' | 4521 'Do not use unnamed namespaces in header files. See ' |
4019 'http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Namesp
aces' | 4522 'http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Namesp
aces' |
4020 ' for more information.') | 4523 ' for more information.') |
4021 | 4524 |
| 4525 |
| 4526 def CheckGlobalStatic(filename, clean_lines, linenum, error): |
| 4527 """Check for unsafe global or static objects. |
| 4528 |
| 4529 Args: |
| 4530 filename: The name of the current file. |
| 4531 clean_lines: A CleansedLines instance containing the file. |
| 4532 linenum: The number of the line to check. |
| 4533 error: The function to call with any errors found. |
| 4534 """ |
| 4535 line = clean_lines.elided[linenum] |
| 4536 |
| 4537 # Check for people declaring static/global STL strings at the top level. |
| 4538 # This is dangerous because the C++ language does not guarantee that |
| 4539 # globals with constructors are initialized before the first access. |
| 4540 match = Match( |
| 4541 r'((?:|static +)(?:|const +))string +([a-zA-Z0-9_:]+)\b(.*)', |
| 4542 line) |
| 4543 # Remove false positives: |
| 4544 # - String pointers (as opposed to values). |
| 4545 # string *pointer |
| 4546 # const string *pointer |
| 4547 # string const *pointer |
| 4548 # string *const pointer |
| 4549 # |
| 4550 # - Functions and template specializations. |
| 4551 # string Function<Type>(... |
| 4552 # string Class<Type>::Method(... |
| 4553 # |
| 4554 # - Operators. These are matched separately because operator names |
| 4555 # cross non-word boundaries, and trying to match both operators |
| 4556 # and functions at the same time would decrease accuracy of |
| 4557 # matching identifiers. |
| 4558 # string Class::operator*() |
| 4559 if (match and |
| 4560 not Search(r'\bstring\b(\s+const)?\s*\*\s*(const\s+)?\w', line) and |
| 4561 not Search(r'\boperator\W', line) and |
| 4562 not Match(r'\s*(<.*>)?(::[a-zA-Z0-9_]+)?\s*\(([^"]|$)', match.group(3))): |
| 4563 error(filename, linenum, 'runtime/string', 4, |
| 4564 'For a static/global string constant, use a C style string instead: ' |
| 4565 '"%schar %s[]".' % |
| 4566 (match.group(1), match.group(2))) |
| 4567 |
| 4568 if Search(r'\b([A-Za-z0-9_]*_)\(\1\)', line): |
| 4569 error(filename, linenum, 'runtime/init', 4, |
| 4570 'You seem to be initializing a member variable with itself.') |
| 4571 |
| 4572 |
| 4573 def CheckPrintf(filename, clean_lines, linenum, error): |
| 4574 """Check for printf related issues. |
| 4575 |
| 4576 Args: |
| 4577 filename: The name of the current file. |
| 4578 clean_lines: A CleansedLines instance containing the file. |
| 4579 linenum: The number of the line to check. |
| 4580 error: The function to call with any errors found. |
| 4581 """ |
| 4582 line = clean_lines.elided[linenum] |
| 4583 |
| 4584 # When snprintf is used, the second argument shouldn't be a literal. |
| 4585 match = Search(r'snprintf\s*\(([^,]*),\s*([0-9]*)\s*,', line) |
| 4586 if match and match.group(2) != '0': |
| 4587 # If 2nd arg is zero, snprintf is used to calculate size. |
| 4588 error(filename, linenum, 'runtime/printf', 3, |
| 4589 'If you can, use sizeof(%s) instead of %s as the 2nd arg ' |
| 4590 'to snprintf.' % (match.group(1), match.group(2))) |
| 4591 |
| 4592 # Check if some verboten C functions are being used. |
| 4593 if Search(r'\bsprintf\b', line): |
| 4594 error(filename, linenum, 'runtime/printf', 5, |
| 4595 'Never use sprintf. Use snprintf instead.') |
| 4596 match = Search(r'\b(strcpy|strcat)\b', line) |
| 4597 if match: |
| 4598 error(filename, linenum, 'runtime/printf', 4, |
| 4599 'Almost always, snprintf is better than %s' % match.group(1)) |
| 4600 |
| 4601 |
| 4602 def IsDerivedFunction(clean_lines, linenum): |
| 4603 """Check if current line contains an inherited function. |
| 4604 |
| 4605 Args: |
| 4606 clean_lines: A CleansedLines instance containing the file. |
| 4607 linenum: The number of the line to check. |
| 4608 Returns: |
| 4609 True if current line contains a function with "override" |
| 4610 virt-specifier. |
| 4611 """ |
| 4612 # Look for leftmost opening parenthesis on current line |
| 4613 opening_paren = clean_lines.elided[linenum].find('(') |
| 4614 if opening_paren < 0: return False |
| 4615 |
| 4616 # Look for "override" after the matching closing parenthesis |
| 4617 line, _, closing_paren = CloseExpression(clean_lines, linenum, opening_paren) |
| 4618 return closing_paren >= 0 and Search(r'\boverride\b', line[closing_paren:]) |
| 4619 |
| 4620 |
| 4621 def IsInitializerList(clean_lines, linenum): |
| 4622 """Check if current line is inside constructor initializer list. |
| 4623 |
| 4624 Args: |
| 4625 clean_lines: A CleansedLines instance containing the file. |
| 4626 linenum: The number of the line to check. |
| 4627 Returns: |
| 4628 True if current line appears to be inside constructor initializer |
| 4629 list, False otherwise. |
| 4630 """ |
| 4631 for i in xrange(linenum, 1, -1): |
| 4632 line = clean_lines.elided[i] |
| 4633 if i == linenum: |
| 4634 remove_function_body = Match(r'^(.*)\{\s*$', line) |
| 4635 if remove_function_body: |
| 4636 line = remove_function_body.group(1) |
| 4637 |
| 4638 if Search(r'\s:\s*\w+[({]', line): |
| 4639 # A lone colon tend to indicate the start of a constructor |
| 4640 # initializer list. It could also be a ternary operator, which |
| 4641 # also tend to appear in constructor initializer lists as |
| 4642 # opposed to parameter lists. |
| 4643 return True |
| 4644 if Search(r'\}\s*,\s*$', line): |
| 4645 # A closing brace followed by a comma is probably the end of a |
| 4646 # brace-initialized member in constructor initializer list. |
| 4647 return True |
| 4648 if Search(r'[{};]\s*$', line): |
| 4649 # Found one of the following: |
| 4650 # - A closing brace or semicolon, probably the end of the previous |
| 4651 # function. |
| 4652 # - An opening brace, probably the start of current class or namespace. |
| 4653 # |
| 4654 # Current line is probably not inside an initializer list since |
| 4655 # we saw one of those things without seeing the starting colon. |
| 4656 return False |
| 4657 |
| 4658 # Got to the beginning of the file without seeing the start of |
| 4659 # constructor initializer list. |
| 4660 return False |
| 4661 |
| 4662 |
4022 def CheckForNonConstReference(filename, clean_lines, linenum, | 4663 def CheckForNonConstReference(filename, clean_lines, linenum, |
4023 nesting_state, error): | 4664 nesting_state, error): |
4024 """Check for non-const references. | 4665 """Check for non-const references. |
4025 | 4666 |
4026 Separate from CheckLanguage since it scans backwards from current | 4667 Separate from CheckLanguage since it scans backwards from current |
4027 line, instead of scanning forward. | 4668 line, instead of scanning forward. |
4028 | 4669 |
4029 Args: | 4670 Args: |
4030 filename: The name of the current file. | 4671 filename: The name of the current file. |
4031 clean_lines: A CleansedLines instance containing the file. | 4672 clean_lines: A CleansedLines instance containing the file. |
4032 linenum: The number of the line to check. | 4673 linenum: The number of the line to check. |
4033 nesting_state: A _NestingState instance which maintains information about | 4674 nesting_state: A NestingState instance which maintains information about |
4034 the current stack of nested blocks being parsed. | 4675 the current stack of nested blocks being parsed. |
4035 error: The function to call with any errors found. | 4676 error: The function to call with any errors found. |
4036 """ | 4677 """ |
4037 # Do nothing if there is no '&' on current line. | 4678 # Do nothing if there is no '&' on current line. |
4038 line = clean_lines.elided[linenum] | 4679 line = clean_lines.elided[linenum] |
4039 if '&' not in line: | 4680 if '&' not in line: |
4040 return | 4681 return |
4041 | 4682 |
| 4683 # If a function is inherited, current function doesn't have much of |
| 4684 # a choice, so any non-const references should not be blamed on |
| 4685 # derived function. |
| 4686 if IsDerivedFunction(clean_lines, linenum): |
| 4687 return |
| 4688 |
4042 # Long type names may be broken across multiple lines, usually in one | 4689 # Long type names may be broken across multiple lines, usually in one |
4043 # of these forms: | 4690 # of these forms: |
4044 # LongType | 4691 # LongType |
4045 # ::LongTypeContinued &identifier | 4692 # ::LongTypeContinued &identifier |
4046 # LongType:: | 4693 # LongType:: |
4047 # LongTypeContinued &identifier | 4694 # LongTypeContinued &identifier |
4048 # LongType< | 4695 # LongType< |
4049 # ...>::LongTypeContinued &identifier | 4696 # ...>::LongTypeContinued &identifier |
4050 # | 4697 # |
4051 # If we detected a type split across two lines, join the previous | 4698 # If we detected a type split across two lines, join the previous |
(...skipping 28 matching lines...) Expand all Loading... |
4080 for i in xrange(startline, linenum + 1): | 4727 for i in xrange(startline, linenum + 1): |
4081 line += clean_lines.elided[i].strip() | 4728 line += clean_lines.elided[i].strip() |
4082 | 4729 |
4083 # Check for non-const references in function parameters. A single '&' may | 4730 # Check for non-const references in function parameters. A single '&' may |
4084 # found in the following places: | 4731 # found in the following places: |
4085 # inside expression: binary & for bitwise AND | 4732 # inside expression: binary & for bitwise AND |
4086 # inside expression: unary & for taking the address of something | 4733 # inside expression: unary & for taking the address of something |
4087 # inside declarators: reference parameter | 4734 # inside declarators: reference parameter |
4088 # We will exclude the first two cases by checking that we are not inside a | 4735 # We will exclude the first two cases by checking that we are not inside a |
4089 # function body, including one that was just introduced by a trailing '{'. | 4736 # function body, including one that was just introduced by a trailing '{'. |
4090 # TODO(unknwon): Doesn't account for preprocessor directives. | |
4091 # TODO(unknown): Doesn't account for 'catch(Exception& e)' [rare]. | 4737 # TODO(unknown): Doesn't account for 'catch(Exception& e)' [rare]. |
4092 check_params = False | 4738 if (nesting_state.previous_stack_top and |
4093 if not nesting_state.stack: | 4739 not (isinstance(nesting_state.previous_stack_top, _ClassInfo) or |
4094 check_params = True # top level | 4740 isinstance(nesting_state.previous_stack_top, _NamespaceInfo))): |
4095 elif (isinstance(nesting_state.stack[-1], _ClassInfo) or | 4741 # Not at toplevel, not within a class, and not within a namespace |
4096 isinstance(nesting_state.stack[-1], _NamespaceInfo)): | 4742 return |
4097 check_params = True # within class or namespace | 4743 |
4098 elif Match(r'.*{\s*$', line): | 4744 # Avoid preprocessors |
4099 if (len(nesting_state.stack) == 1 or | 4745 if Search(r'\\\s*$', line): |
4100 isinstance(nesting_state.stack[-2], _ClassInfo) or | 4746 return |
4101 isinstance(nesting_state.stack[-2], _NamespaceInfo)): | 4747 |
4102 check_params = True # just opened global/class/namespace block | 4748 # Avoid constructor initializer lists |
| 4749 if IsInitializerList(clean_lines, linenum): |
| 4750 return |
| 4751 |
4103 # We allow non-const references in a few standard places, like functions | 4752 # We allow non-const references in a few standard places, like functions |
4104 # called "swap()" or iostream operators like "<<" or ">>". Do not check | 4753 # called "swap()" or iostream operators like "<<" or ">>". Do not check |
4105 # those function parameters. | 4754 # those function parameters. |
4106 # | 4755 # |
4107 # We also accept & in static_assert, which looks like a function but | 4756 # We also accept & in static_assert, which looks like a function but |
4108 # it's actually a declaration expression. | 4757 # it's actually a declaration expression. |
4109 whitelisted_functions = (r'(?:[sS]wap(?:<\w:+>)?|' | 4758 whitelisted_functions = (r'(?:[sS]wap(?:<\w:+>)?|' |
4110 r'operator\s*[<>][<>]|' | 4759 r'operator\s*[<>][<>]|' |
4111 r'static_assert|COMPILE_ASSERT' | 4760 r'static_assert|COMPILE_ASSERT' |
4112 r')\s*\(') | 4761 r')\s*\(') |
4113 if Search(whitelisted_functions, line): | 4762 if Search(whitelisted_functions, line): |
4114 check_params = False | 4763 return |
4115 elif not Search(r'\S+\([^)]*$', line): | 4764 elif not Search(r'\S+\([^)]*$', line): |
4116 # Don't see a whitelisted function on this line. Actually we | 4765 # Don't see a whitelisted function on this line. Actually we |
4117 # didn't see any function name on this line, so this is likely a | 4766 # didn't see any function name on this line, so this is likely a |
4118 # multi-line parameter list. Try a bit harder to catch this case. | 4767 # multi-line parameter list. Try a bit harder to catch this case. |
4119 for i in xrange(2): | 4768 for i in xrange(2): |
4120 if (linenum > i and | 4769 if (linenum > i and |
4121 Search(whitelisted_functions, clean_lines.elided[linenum - i - 1])): | 4770 Search(whitelisted_functions, clean_lines.elided[linenum - i - 1])): |
4122 check_params = False | 4771 return |
4123 break | |
4124 | 4772 |
4125 if check_params: | 4773 decls = ReplaceAll(r'{[^}]*}', ' ', line) # exclude function body |
4126 decls = ReplaceAll(r'{[^}]*}', ' ', line) # exclude function body | 4774 for parameter in re.findall(_RE_PATTERN_REF_PARAM, decls): |
4127 for parameter in re.findall(_RE_PATTERN_REF_PARAM, decls): | 4775 if not Match(_RE_PATTERN_CONST_REF_PARAM, parameter): |
4128 if not Match(_RE_PATTERN_CONST_REF_PARAM, parameter): | 4776 error(filename, linenum, 'runtime/references', 2, |
4129 error(filename, linenum, 'runtime/references', 2, | 4777 'Is this a non-const reference? ' |
4130 'Is this a non-const reference? ' | 4778 'If so, make const or use a pointer: ' + |
4131 'If so, make const or use a pointer: ' + | 4779 ReplaceAll(' *<', '<', parameter)) |
4132 ReplaceAll(' *<', '<', parameter)) | 4780 |
| 4781 |
| 4782 def CheckCasts(filename, clean_lines, linenum, error): |
| 4783 """Various cast related checks. |
| 4784 |
| 4785 Args: |
| 4786 filename: The name of the current file. |
| 4787 clean_lines: A CleansedLines instance containing the file. |
| 4788 linenum: The number of the line to check. |
| 4789 error: The function to call with any errors found. |
| 4790 """ |
| 4791 line = clean_lines.elided[linenum] |
| 4792 |
| 4793 # Check to see if they're using an conversion function cast. |
| 4794 # I just try to capture the most common basic types, though there are more. |
| 4795 # Parameterless conversion functions, such as bool(), are allowed as they are |
| 4796 # probably a member operator declaration or default constructor. |
| 4797 match = Search( |
| 4798 r'(\bnew\s+|\S<\s*(?:const\s+)?)?\b' |
| 4799 r'(int|float|double|bool|char|int32|uint32|int64|uint64)' |
| 4800 r'(\([^)].*)', line) |
| 4801 expecting_function = ExpectingFunctionArgs(clean_lines, linenum) |
| 4802 if match and not expecting_function: |
| 4803 matched_type = match.group(2) |
| 4804 |
| 4805 # matched_new_or_template is used to silence two false positives: |
| 4806 # - New operators |
| 4807 # - Template arguments with function types |
| 4808 # |
| 4809 # For template arguments, we match on types immediately following |
| 4810 # an opening bracket without any spaces. This is a fast way to |
| 4811 # silence the common case where the function type is the first |
| 4812 # template argument. False negative with less-than comparison is |
| 4813 # avoided because those operators are usually followed by a space. |
| 4814 # |
| 4815 # function<double(double)> // bracket + no space = false positive |
| 4816 # value < double(42) // bracket + space = true positive |
| 4817 matched_new_or_template = match.group(1) |
| 4818 |
| 4819 # Other things to ignore: |
| 4820 # - Function pointers |
| 4821 # - Casts to pointer types |
| 4822 # - Placement new |
| 4823 # - Alias declarations |
| 4824 matched_funcptr = match.group(3) |
| 4825 if (matched_new_or_template is None and |
| 4826 not (matched_funcptr and |
| 4827 (Match(r'\((?:[^() ]+::\s*\*\s*)?[^() ]+\)\s*\(', |
| 4828 matched_funcptr) or |
| 4829 matched_funcptr.startswith('(*)'))) and |
| 4830 not Match(r'\s*using\s+\S+\s*=\s*' + matched_type, line) and |
| 4831 not Search(r'new\(\S+\)\s*' + matched_type, line)): |
| 4832 error(filename, linenum, 'readability/casting', 4, |
| 4833 'Using deprecated casting style. ' |
| 4834 'Use static_cast<%s>(...) instead' % |
| 4835 matched_type) |
| 4836 |
| 4837 if not expecting_function: |
| 4838 CheckCStyleCast(filename, linenum, line, clean_lines.raw_lines[linenum], |
| 4839 'static_cast', |
| 4840 r'\((int|float|double|bool|char|u?int(16|32|64))\)', error) |
| 4841 |
| 4842 # This doesn't catch all cases. Consider (const char * const)"hello". |
| 4843 # |
| 4844 # (char *) "foo" should always be a const_cast (reinterpret_cast won't |
| 4845 # compile). |
| 4846 if CheckCStyleCast(filename, linenum, line, clean_lines.raw_lines[linenum], |
| 4847 'const_cast', r'\((char\s?\*+\s?)\)\s*"', error): |
| 4848 pass |
| 4849 else: |
| 4850 # Check pointer casts for other than string constants |
| 4851 CheckCStyleCast(filename, linenum, line, clean_lines.raw_lines[linenum], |
| 4852 'reinterpret_cast', r'\((\w+\s?\*+\s?)\)', error) |
| 4853 |
| 4854 # In addition, we look for people taking the address of a cast. This |
| 4855 # is dangerous -- casts can assign to temporaries, so the pointer doesn't |
| 4856 # point where you think. |
| 4857 match = Search( |
| 4858 r'(?:&\(([^)]+)\)[\w(])|' |
| 4859 r'(?:&(static|dynamic|down|reinterpret)_cast\b)', line) |
| 4860 if match and match.group(1) != '*': |
| 4861 # Try a better error message when the & is bound to something |
| 4862 # dereferenced by the casted pointer, as opposed to the casted |
| 4863 # pointer itself. |
| 4864 parenthesis_error = False |
| 4865 match = Match(r'^(.*&(?:static|dynamic|down|reinterpret)_cast\b)<', line) |
| 4866 if match: |
| 4867 _, y1, x1 = CloseExpression(clean_lines, linenum, len(match.group(1))) |
| 4868 if x1 >= 0 and clean_lines.elided[y1][x1] == '(': |
| 4869 _, y2, x2 = CloseExpression(clean_lines, y1, x1) |
| 4870 if x2 >= 0: |
| 4871 extended_line = clean_lines.elided[y2][x2:] |
| 4872 if y2 < clean_lines.NumLines() - 1: |
| 4873 extended_line += clean_lines.elided[y2 + 1] |
| 4874 if Match(r'\s*(?:->|\[)', extended_line): |
| 4875 parenthesis_error = True |
| 4876 |
| 4877 if parenthesis_error: |
| 4878 error(filename, linenum, 'readability/casting', 4, |
| 4879 ('Are you taking an address of something dereferenced ' |
| 4880 'from a cast? Wrapping the dereferenced expression in ' |
| 4881 'parentheses will make the binding more obvious')) |
| 4882 else: |
| 4883 error(filename, linenum, 'runtime/casting', 4, |
| 4884 ('Are you taking an address of a cast? ' |
| 4885 'This is dangerous: could be a temp var. ' |
| 4886 'Take the address before doing the cast, rather than after')) |
4133 | 4887 |
4134 | 4888 |
4135 def CheckCStyleCast(filename, linenum, line, raw_line, cast_type, pattern, | 4889 def CheckCStyleCast(filename, linenum, line, raw_line, cast_type, pattern, |
4136 error): | 4890 error): |
4137 """Checks for a C-style cast by looking for the pattern. | 4891 """Checks for a C-style cast by looking for the pattern. |
4138 | 4892 |
4139 Args: | 4893 Args: |
4140 filename: The name of the current file. | 4894 filename: The name of the current file. |
4141 linenum: The number of the line to check. | 4895 linenum: The number of the line to check. |
4142 line: The line of code to check. | 4896 line: The line of code to check. |
4143 raw_line: The raw line of code to check, with comments. | 4897 raw_line: The raw line of code to check, with comments. |
4144 cast_type: The string for the C++ cast to recommend. This is either | 4898 cast_type: The string for the C++ cast to recommend. This is either |
4145 reinterpret_cast, static_cast, or const_cast, depending. | 4899 reinterpret_cast, static_cast, or const_cast, depending. |
4146 pattern: The regular expression used to find C-style casts. | 4900 pattern: The regular expression used to find C-style casts. |
4147 error: The function to call with any errors found. | 4901 error: The function to call with any errors found. |
4148 | 4902 |
4149 Returns: | 4903 Returns: |
4150 True if an error was emitted. | 4904 True if an error was emitted. |
4151 False otherwise. | 4905 False otherwise. |
4152 """ | 4906 """ |
4153 match = Search(pattern, line) | 4907 match = Search(pattern, line) |
4154 if not match: | 4908 if not match: |
4155 return False | 4909 return False |
4156 | 4910 |
4157 # Exclude lines with sizeof, since sizeof looks like a cast. | 4911 # Exclude lines with keywords that tend to look like casts, and also |
4158 sizeof_match = Match(r'.*sizeof\s*$', line[0:match.start(1) - 1]) | 4912 # macros which are generally troublesome. |
4159 if sizeof_match: | 4913 if Match(r'.*\b(?:sizeof|alignof|alignas|[A-Z_]+)\s*$', |
| 4914 line[0:match.start(1) - 1]): |
4160 return False | 4915 return False |
4161 | 4916 |
4162 # operator++(int) and operator--(int) | 4917 # operator++(int) and operator--(int) |
4163 if (line[0:match.start(1) - 1].endswith(' operator++') or | 4918 if (line[0:match.start(1) - 1].endswith(' operator++') or |
4164 line[0:match.start(1) - 1].endswith(' operator--')): | 4919 line[0:match.start(1) - 1].endswith(' operator--')): |
4165 return False | 4920 return False |
4166 | 4921 |
4167 # A single unnamed argument for a function tends to look like old | 4922 # A single unnamed argument for a function tends to look like old |
4168 # style cast. If we see those, don't issue warnings for deprecated | 4923 # style cast. If we see those, don't issue warnings for deprecated |
4169 # casts, instead issue warnings for unnamed arguments where | 4924 # casts, instead issue warnings for unnamed arguments where |
(...skipping 11 matching lines...) Expand all Loading... |
4181 # | 4936 # |
4182 # These are functions of some sort, where the compiler would be fine | 4937 # These are functions of some sort, where the compiler would be fine |
4183 # if they had named parameters, but people often omit those | 4938 # if they had named parameters, but people often omit those |
4184 # identifiers to reduce clutter: | 4939 # identifiers to reduce clutter: |
4185 # (FunctionPointer)(int); | 4940 # (FunctionPointer)(int); |
4186 # (FunctionPointer)(int) = value; | 4941 # (FunctionPointer)(int) = value; |
4187 # Function((function_pointer_arg)(int)) | 4942 # Function((function_pointer_arg)(int)) |
4188 # <TemplateArgument(int)>; | 4943 # <TemplateArgument(int)>; |
4189 # <(FunctionPointerTemplateArgument)(int)>; | 4944 # <(FunctionPointerTemplateArgument)(int)>; |
4190 remainder = line[match.end(0):] | 4945 remainder = line[match.end(0):] |
4191 if Match(r'^\s*(?:;|const\b|throw\b|=|>|\{|\))', remainder): | 4946 if Match(r'^\s*(?:;|const\b|throw\b|final\b|override\b|=|>|\{|\))', |
| 4947 remainder): |
4192 # Looks like an unnamed parameter. | 4948 # Looks like an unnamed parameter. |
4193 | 4949 |
4194 # Don't warn on any kind of template arguments. | 4950 # Don't warn on any kind of template arguments. |
4195 if Match(r'^\s*>', remainder): | 4951 if Match(r'^\s*>', remainder): |
4196 return False | 4952 return False |
4197 | 4953 |
4198 # Don't warn on assignments to function pointers, but keep warnings for | 4954 # Don't warn on assignments to function pointers, but keep warnings for |
4199 # unnamed parameters to pure virtual functions. Note that this pattern | 4955 # unnamed parameters to pure virtual functions. Note that this pattern |
4200 # will also pass on assignments of "0" to function pointers, but the | 4956 # will also pass on assignments of "0" to function pointers, but the |
4201 # preferred values for those would be "nullptr" or "NULL". | 4957 # preferred values for those would be "nullptr" or "NULL". |
(...skipping 17 matching lines...) Expand all Loading... |
4219 return True | 4975 return True |
4220 | 4976 |
4221 # At this point, all that should be left is actual casts. | 4977 # At this point, all that should be left is actual casts. |
4222 error(filename, linenum, 'readability/casting', 4, | 4978 error(filename, linenum, 'readability/casting', 4, |
4223 'Using C-style cast. Use %s<%s>(...) instead' % | 4979 'Using C-style cast. Use %s<%s>(...) instead' % |
4224 (cast_type, match.group(1))) | 4980 (cast_type, match.group(1))) |
4225 | 4981 |
4226 return True | 4982 return True |
4227 | 4983 |
4228 | 4984 |
| 4985 def ExpectingFunctionArgs(clean_lines, linenum): |
| 4986 """Checks whether where function type arguments are expected. |
| 4987 |
| 4988 Args: |
| 4989 clean_lines: A CleansedLines instance containing the file. |
| 4990 linenum: The number of the line to check. |
| 4991 |
| 4992 Returns: |
| 4993 True if the line at 'linenum' is inside something that expects arguments |
| 4994 of function types. |
| 4995 """ |
| 4996 line = clean_lines.elided[linenum] |
| 4997 return (Match(r'^\s*MOCK_(CONST_)?METHOD\d+(_T)?\(', line) or |
| 4998 (linenum >= 2 and |
| 4999 (Match(r'^\s*MOCK_(?:CONST_)?METHOD\d+(?:_T)?\((?:\S+,)?\s*$', |
| 5000 clean_lines.elided[linenum - 1]) or |
| 5001 Match(r'^\s*MOCK_(?:CONST_)?METHOD\d+(?:_T)?\(\s*$', |
| 5002 clean_lines.elided[linenum - 2]) or |
| 5003 Search(r'\bstd::m?function\s*\<\s*$', |
| 5004 clean_lines.elided[linenum - 1])))) |
| 5005 |
| 5006 |
4229 _HEADERS_CONTAINING_TEMPLATES = ( | 5007 _HEADERS_CONTAINING_TEMPLATES = ( |
4230 ('<deque>', ('deque',)), | 5008 ('<deque>', ('deque',)), |
4231 ('<functional>', ('unary_function', 'binary_function', | 5009 ('<functional>', ('unary_function', 'binary_function', |
4232 'plus', 'minus', 'multiplies', 'divides', 'modulus', | 5010 'plus', 'minus', 'multiplies', 'divides', 'modulus', |
4233 'negate', | 5011 'negate', |
4234 'equal_to', 'not_equal_to', 'greater', 'less', | 5012 'equal_to', 'not_equal_to', 'greater', 'less', |
4235 'greater_equal', 'less_equal', | 5013 'greater_equal', 'less_equal', |
4236 'logical_and', 'logical_or', 'logical_not', | 5014 'logical_and', 'logical_or', 'logical_not', |
4237 'unary_negate', 'not1', 'binary_negate', 'not2', | 5015 'unary_negate', 'not1', 'binary_negate', 'not2', |
4238 'bind1st', 'bind2nd', | 5016 'bind1st', 'bind2nd', |
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4460 'build/include_what_you_use', 4, | 5238 'build/include_what_you_use', 4, |
4461 'Add #include ' + required_header_unstripped + ' for ' + template) | 5239 'Add #include ' + required_header_unstripped + ' for ' + template) |
4462 | 5240 |
4463 | 5241 |
4464 _RE_PATTERN_EXPLICIT_MAKEPAIR = re.compile(r'\bmake_pair\s*<') | 5242 _RE_PATTERN_EXPLICIT_MAKEPAIR = re.compile(r'\bmake_pair\s*<') |
4465 | 5243 |
4466 | 5244 |
4467 def CheckMakePairUsesDeduction(filename, clean_lines, linenum, error): | 5245 def CheckMakePairUsesDeduction(filename, clean_lines, linenum, error): |
4468 """Check that make_pair's template arguments are deduced. | 5246 """Check that make_pair's template arguments are deduced. |
4469 | 5247 |
4470 G++ 4.6 in C++0x mode fails badly if make_pair's template arguments are | 5248 G++ 4.6 in C++11 mode fails badly if make_pair's template arguments are |
4471 specified explicitly, and such use isn't intended in any case. | 5249 specified explicitly, and such use isn't intended in any case. |
4472 | 5250 |
4473 Args: | 5251 Args: |
4474 filename: The name of the current file. | 5252 filename: The name of the current file. |
4475 clean_lines: A CleansedLines instance containing the file. | 5253 clean_lines: A CleansedLines instance containing the file. |
4476 linenum: The number of the line to check. | 5254 linenum: The number of the line to check. |
4477 error: The function to call with any errors found. | 5255 error: The function to call with any errors found. |
4478 """ | 5256 """ |
4479 line = clean_lines.elided[linenum] | 5257 line = clean_lines.elided[linenum] |
4480 match = _RE_PATTERN_EXPLICIT_MAKEPAIR.search(line) | 5258 match = _RE_PATTERN_EXPLICIT_MAKEPAIR.search(line) |
4481 if match: | 5259 if match: |
4482 error(filename, linenum, 'build/explicit_make_pair', | 5260 error(filename, linenum, 'build/explicit_make_pair', |
4483 4, # 4 = high confidence | 5261 4, # 4 = high confidence |
4484 'For C++11-compatibility, omit template arguments from make_pair' | 5262 'For C++11-compatibility, omit template arguments from make_pair' |
4485 ' OR use pair directly OR if appropriate, construct a pair directly') | 5263 ' OR use pair directly OR if appropriate, construct a pair directly') |
| 5264 def CheckDefaultLambdaCaptures(filename, clean_lines, linenum, error): |
| 5265 """Check that default lambda captures are not used. |
| 5266 |
| 5267 Args: |
| 5268 filename: The name of the current file. |
| 5269 clean_lines: A CleansedLines instance containing the file. |
| 5270 linenum: The number of the line to check. |
| 5271 error: The function to call with any errors found. |
| 5272 """ |
| 5273 line = clean_lines.elided[linenum] |
| 5274 |
| 5275 # A lambda introducer specifies a default capture if it starts with "[=" |
| 5276 # or if it starts with "[&" _not_ followed by an identifier. |
| 5277 match = Match(r'^(.*)\[\s*(?:=|&[^\w])', line) |
| 5278 if match: |
| 5279 # Found a potential error, check what comes after the lambda-introducer. |
| 5280 # If it's not open parenthesis (for lambda-declarator) or open brace |
| 5281 # (for compound-statement), it's not a lambda. |
| 5282 line, _, pos = CloseExpression(clean_lines, linenum, len(match.group(1))) |
| 5283 if pos >= 0 and Match(r'^\s*[{(]', line[pos:]): |
| 5284 error(filename, linenum, 'build/c++11', |
| 5285 4, # 4 = high confidence |
| 5286 'Default lambda captures are an unapproved C++ feature.') |
| 5287 |
| 5288 |
4486 | 5289 |
4487 | 5290 |
4488 def ProcessLine(filename, file_extension, clean_lines, line, | 5291 def ProcessLine(filename, file_extension, clean_lines, line, |
4489 include_state, function_state, nesting_state, error, | 5292 include_state, function_state, nesting_state, error, |
4490 extra_check_functions=[]): | 5293 extra_check_functions=[]): |
4491 """Processes a single line in the file. | 5294 """Processes a single line in the file. |
4492 | 5295 |
4493 Args: | 5296 Args: |
4494 filename: Filename of the file that is being processed. | 5297 filename: Filename of the file that is being processed. |
4495 file_extension: The extension (dot not included) of the file. | 5298 file_extension: The extension (dot not included) of the file. |
4496 clean_lines: An array of strings, each representing a line of the file, | 5299 clean_lines: An array of strings, each representing a line of the file, |
4497 with comments stripped. | 5300 with comments stripped. |
4498 line: Number of line being processed. | 5301 line: Number of line being processed. |
4499 include_state: An _IncludeState instance in which the headers are inserted. | 5302 include_state: An _IncludeState instance in which the headers are inserted. |
4500 function_state: A _FunctionState instance which counts function lines, etc. | 5303 function_state: A _FunctionState instance which counts function lines, etc. |
4501 nesting_state: A _NestingState instance which maintains information about | 5304 nesting_state: A NestingState instance which maintains information about |
4502 the current stack of nested blocks being parsed. | 5305 the current stack of nested blocks being parsed. |
4503 error: A callable to which errors are reported, which takes 4 arguments: | 5306 error: A callable to which errors are reported, which takes 4 arguments: |
4504 filename, line number, error level, and message | 5307 filename, line number, error level, and message |
4505 extra_check_functions: An array of additional check functions that will be | 5308 extra_check_functions: An array of additional check functions that will be |
4506 run on each source line. Each function takes 4 | 5309 run on each source line. Each function takes 4 |
4507 arguments: filename, clean_lines, line, error | 5310 arguments: filename, clean_lines, line, error |
4508 """ | 5311 """ |
4509 raw_lines = clean_lines.raw_lines | 5312 raw_lines = clean_lines.raw_lines |
4510 ParseNolintSuppressions(filename, raw_lines[line], line, error) | 5313 ParseNolintSuppressions(filename, raw_lines[line], line, error) |
4511 nesting_state.Update(filename, clean_lines, line, error) | 5314 nesting_state.Update(filename, clean_lines, line, error) |
4512 if nesting_state.stack and nesting_state.stack[-1].inline_asm != _NO_ASM: | 5315 if nesting_state.InAsmBlock(): return |
4513 return | |
4514 CheckForFunctionLengths(filename, clean_lines, line, function_state, error) | 5316 CheckForFunctionLengths(filename, clean_lines, line, function_state, error) |
4515 CheckForMultilineCommentsAndStrings(filename, clean_lines, line, error) | 5317 CheckForMultilineCommentsAndStrings(filename, clean_lines, line, error) |
4516 CheckStyle(filename, clean_lines, line, file_extension, nesting_state, error) | 5318 CheckStyle(filename, clean_lines, line, file_extension, nesting_state, error) |
4517 CheckLanguage(filename, clean_lines, line, file_extension, include_state, | 5319 CheckLanguage(filename, clean_lines, line, file_extension, include_state, |
4518 nesting_state, error) | 5320 nesting_state, error) |
4519 CheckForNonConstReference(filename, clean_lines, line, nesting_state, error) | 5321 CheckForNonConstReference(filename, clean_lines, line, nesting_state, error) |
4520 CheckForNonStandardConstructs(filename, clean_lines, line, | 5322 CheckForNonStandardConstructs(filename, clean_lines, line, |
4521 nesting_state, error) | 5323 nesting_state, error) |
4522 CheckVlogArguments(filename, clean_lines, line, error) | 5324 CheckVlogArguments(filename, clean_lines, line, error) |
4523 CheckPosixThreading(filename, clean_lines, line, error) | 5325 CheckPosixThreading(filename, clean_lines, line, error) |
4524 CheckInvalidIncrement(filename, clean_lines, line, error) | 5326 CheckInvalidIncrement(filename, clean_lines, line, error) |
4525 CheckMakePairUsesDeduction(filename, clean_lines, line, error) | 5327 CheckMakePairUsesDeduction(filename, clean_lines, line, error) |
| 5328 CheckDefaultLambdaCaptures(filename, clean_lines, line, error) |
4526 for check_fn in extra_check_functions: | 5329 for check_fn in extra_check_functions: |
4527 check_fn(filename, clean_lines, line, error) | 5330 check_fn(filename, clean_lines, line, error) |
| 5331 |
| 5332 def FlagCxx11Features(filename, clean_lines, linenum, error): |
| 5333 """Flag those c++11 features that we only allow in certain places. |
| 5334 |
| 5335 Args: |
| 5336 filename: The name of the current file. |
| 5337 clean_lines: A CleansedLines instance containing the file. |
| 5338 linenum: The number of the line to check. |
| 5339 error: The function to call with any errors found. |
| 5340 """ |
| 5341 line = clean_lines.elided[linenum] |
| 5342 |
| 5343 # Flag unapproved C++11 headers. |
| 5344 include = Match(r'\s*#\s*include\s+[<"]([^<"]+)[">]', line) |
| 5345 if include and include.group(1) in ('cfenv', |
| 5346 'condition_variable', |
| 5347 'fenv.h', |
| 5348 'future', |
| 5349 'mutex', |
| 5350 'thread', |
| 5351 'chrono', |
| 5352 'ratio', |
| 5353 'regex', |
| 5354 'system_error', |
| 5355 ): |
| 5356 error(filename, linenum, 'build/c++11', 5, |
| 5357 ('<%s> is an unapproved C++11 header.') % include.group(1)) |
| 5358 |
| 5359 # The only place where we need to worry about C++11 keywords and library |
| 5360 # features in preprocessor directives is in macro definitions. |
| 5361 if Match(r'\s*#', line) and not Match(r'\s*#\s*define\b', line): return |
| 5362 |
| 5363 # These are classes and free functions. The classes are always |
| 5364 # mentioned as std::*, but we only catch the free functions if |
| 5365 # they're not found by ADL. They're alphabetical by header. |
| 5366 for top_name in ( |
| 5367 # type_traits |
| 5368 'alignment_of', |
| 5369 'aligned_union', |
| 5370 |
| 5371 # utility |
| 5372 'forward', |
| 5373 ): |
| 5374 if Search(r'\bstd::%s\b' % top_name, line): |
| 5375 error(filename, linenum, 'build/c++11', 5, |
| 5376 ('std::%s is an unapproved C++11 class or function. Send c-style ' |
| 5377 'an example of where it would make your code more readable, and ' |
| 5378 'they may let you use it.') % top_name) |
| 5379 |
4528 | 5380 |
4529 def ProcessFileData(filename, file_extension, lines, error, | 5381 def ProcessFileData(filename, file_extension, lines, error, |
4530 extra_check_functions=[]): | 5382 extra_check_functions=[]): |
4531 """Performs lint checks and reports any errors to the given error function. | 5383 """Performs lint checks and reports any errors to the given error function. |
4532 | 5384 |
4533 Args: | 5385 Args: |
4534 filename: Filename of the file that is being processed. | 5386 filename: Filename of the file that is being processed. |
4535 file_extension: The extension (dot not included) of the file. | 5387 file_extension: The extension (dot not included) of the file. |
4536 lines: An array of strings, each representing a line of the file, with the | 5388 lines: An array of strings, each representing a line of the file, with the |
4537 last element being empty if the file is terminated with a newline. | 5389 last element being empty if the file is terminated with a newline. |
4538 error: A callable to which errors are reported, which takes 4 arguments: | 5390 error: A callable to which errors are reported, which takes 4 arguments: |
4539 filename, line number, error level, and message | 5391 filename, line number, error level, and message |
4540 extra_check_functions: An array of additional check functions that will be | 5392 extra_check_functions: An array of additional check functions that will be |
4541 run on each source line. Each function takes 4 | 5393 run on each source line. Each function takes 4 |
4542 arguments: filename, clean_lines, line, error | 5394 arguments: filename, clean_lines, line, error |
4543 """ | 5395 """ |
4544 lines = (['// marker so line numbers and indices both start at 1'] + lines + | 5396 lines = (['// marker so line numbers and indices both start at 1'] + lines + |
4545 ['// marker so line numbers end in a known way']) | 5397 ['// marker so line numbers end in a known way']) |
4546 | 5398 |
4547 include_state = _IncludeState() | 5399 include_state = _IncludeState() |
4548 function_state = _FunctionState() | 5400 function_state = _FunctionState() |
4549 nesting_state = _NestingState() | 5401 nesting_state = NestingState() |
4550 | 5402 |
4551 ResetNolintSuppressions() | 5403 ResetNolintSuppressions() |
4552 | 5404 |
4553 CheckForCopyright(filename, lines, error) | 5405 CheckForCopyright(filename, lines, error) |
4554 | 5406 |
4555 if file_extension == 'h': | 5407 if file_extension == 'h': |
4556 CheckForHeaderGuard(filename, lines, error) | 5408 CheckForHeaderGuard(filename, lines, error) |
4557 | 5409 |
4558 RemoveMultiLineComments(filename, lines, error) | 5410 RemoveMultiLineComments(filename, lines, error) |
4559 clean_lines = CleansedLines(lines) | 5411 clean_lines = CleansedLines(lines) |
4560 for line in xrange(clean_lines.NumLines()): | 5412 for line in xrange(clean_lines.NumLines()): |
4561 ProcessLine(filename, file_extension, clean_lines, line, | 5413 ProcessLine(filename, file_extension, clean_lines, line, |
4562 include_state, function_state, nesting_state, error, | 5414 include_state, function_state, nesting_state, error, |
4563 extra_check_functions) | 5415 extra_check_functions) |
| 5416 FlagCxx11Features(filename, clean_lines, line, error) |
4564 nesting_state.CheckCompletedBlocks(filename, error) | 5417 nesting_state.CheckCompletedBlocks(filename, error) |
4565 | 5418 |
4566 CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error) | 5419 CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error) |
4567 | 5420 |
4568 # We check here rather than inside ProcessLine so that we see raw | 5421 # We check here rather than inside ProcessLine so that we see raw |
4569 # lines rather than "cleaned" lines. | 5422 # lines rather than "cleaned" lines. |
4570 CheckForBadCharacters(filename, lines, error) | 5423 CheckForBadCharacters(filename, lines, error) |
4571 | 5424 |
4572 CheckForNewlineAtEOF(filename, lines, error) | 5425 CheckForNewlineAtEOF(filename, lines, error) |
4573 | 5426 |
| 5427 |
4574 def ProcessFile(filename, vlevel, extra_check_functions=[]): | 5428 def ProcessFile(filename, vlevel, extra_check_functions=[]): |
4575 """Does google-lint on a single file. | 5429 """Does google-lint on a single file. |
4576 | 5430 |
4577 Args: | 5431 Args: |
4578 filename: The name of the file to parse. | 5432 filename: The name of the file to parse. |
4579 | 5433 |
4580 vlevel: The level of errors to report. Every error of confidence | 5434 vlevel: The level of errors to report. Every error of confidence |
4581 >= verbose_level will be reported. 0 is a good default. | 5435 >= verbose_level will be reported. 0 is a good default. |
4582 | 5436 |
4583 extra_check_functions: An array of additional check functions that will be | 5437 extra_check_functions: An array of additional check functions that will be |
4584 run on each source line. Each function takes 4 | 5438 run on each source line. Each function takes 4 |
4585 arguments: filename, clean_lines, line, error | 5439 arguments: filename, clean_lines, line, error |
4586 """ | 5440 """ |
4587 | 5441 |
4588 _SetVerboseLevel(vlevel) | 5442 _SetVerboseLevel(vlevel) |
4589 | 5443 |
| 5444 lf_lines = [] |
| 5445 crlf_lines = [] |
4590 try: | 5446 try: |
4591 # Support the UNIX convention of using "-" for stdin. Note that | 5447 # Support the UNIX convention of using "-" for stdin. Note that |
4592 # we are not opening the file with universal newline support | 5448 # we are not opening the file with universal newline support |
4593 # (which codecs doesn't support anyway), so the resulting lines do | 5449 # (which codecs doesn't support anyway), so the resulting lines do |
4594 # contain trailing '\r' characters if we are reading a file that | 5450 # contain trailing '\r' characters if we are reading a file that |
4595 # has CRLF endings. | 5451 # has CRLF endings. |
4596 # If after the split a trailing '\r' is present, it is removed | 5452 # If after the split a trailing '\r' is present, it is removed |
4597 # below. If it is not expected to be present (i.e. os.linesep != | 5453 # below. |
4598 # '\r\n' as in Windows), a warning is issued below if this file | |
4599 # is processed. | |
4600 | |
4601 if filename == '-': | 5454 if filename == '-': |
4602 lines = codecs.StreamReaderWriter(sys.stdin, | 5455 lines = codecs.StreamReaderWriter(sys.stdin, |
4603 codecs.getreader('utf8'), | 5456 codecs.getreader('utf8'), |
4604 codecs.getwriter('utf8'), | 5457 codecs.getwriter('utf8'), |
4605 'replace').read().split('\n') | 5458 'replace').read().split('\n') |
4606 else: | 5459 else: |
4607 lines = codecs.open(filename, 'r', 'utf8', 'replace').read().split('\n') | 5460 lines = codecs.open(filename, 'r', 'utf8', 'replace').read().split('\n') |
4608 | 5461 |
4609 carriage_return_found = False | |
4610 # Remove trailing '\r'. | 5462 # Remove trailing '\r'. |
4611 for linenum in range(len(lines)): | 5463 # The -1 accounts for the extra trailing blank line we get from split() |
| 5464 for linenum in range(len(lines) - 1): |
4612 if lines[linenum].endswith('\r'): | 5465 if lines[linenum].endswith('\r'): |
4613 lines[linenum] = lines[linenum].rstrip('\r') | 5466 lines[linenum] = lines[linenum].rstrip('\r') |
4614 carriage_return_found = True | 5467 crlf_lines.append(linenum + 1) |
| 5468 else: |
| 5469 lf_lines.append(linenum + 1) |
4615 | 5470 |
4616 except IOError: | 5471 except IOError: |
4617 sys.stderr.write( | 5472 sys.stderr.write( |
4618 "Skipping input '%s': Can't open for reading\n" % filename) | 5473 "Skipping input '%s': Can't open for reading\n" % filename) |
4619 return | 5474 return |
4620 | 5475 |
4621 # Note, if no dot is found, this will give the entire filename as the ext. | 5476 # Note, if no dot is found, this will give the entire filename as the ext. |
4622 file_extension = filename[filename.rfind('.') + 1:] | 5477 file_extension = filename[filename.rfind('.') + 1:] |
4623 | 5478 |
4624 # When reading from stdin, the extension is unknown, so no cpplint tests | 5479 # When reading from stdin, the extension is unknown, so no cpplint tests |
4625 # should rely on the extension. | 5480 # should rely on the extension. |
4626 if filename != '-' and file_extension not in _valid_extensions: | 5481 if filename != '-' and file_extension not in _valid_extensions: |
4627 sys.stderr.write('Ignoring %s; not a valid file name ' | 5482 sys.stderr.write('Ignoring %s; not a valid file name ' |
4628 '(%s)\n' % (filename, ', '.join(_valid_extensions))) | 5483 '(%s)\n' % (filename, ', '.join(_valid_extensions))) |
4629 else: | 5484 else: |
4630 ProcessFileData(filename, file_extension, lines, Error, | 5485 ProcessFileData(filename, file_extension, lines, Error, |
4631 extra_check_functions) | 5486 extra_check_functions) |
4632 if carriage_return_found and os.linesep != '\r\n': | 5487 |
4633 # Use 0 for linenum since outputting only one error for potentially | 5488 # If end-of-line sequences are a mix of LF and CR-LF, issue |
4634 # several lines. | 5489 # warnings on the lines with CR. |
4635 Error(filename, 0, 'whitespace/newline', 1, | 5490 # |
4636 'One or more unexpected \\r (^M) found;' | 5491 # Don't issue any warnings if all lines are uniformly LF or CR-LF, |
4637 'better to use only a \\n') | 5492 # since critique can handle these just fine, and the style guide |
| 5493 # doesn't dictate a particular end of line sequence. |
| 5494 # |
| 5495 # We can't depend on os.linesep to determine what the desired |
| 5496 # end-of-line sequence should be, since that will return the |
| 5497 # server-side end-of-line sequence. |
| 5498 if lf_lines and crlf_lines: |
| 5499 # Warn on every line with CR. An alternative approach might be to |
| 5500 # check whether the file is mostly CRLF or just LF, and warn on the |
| 5501 # minority, we bias toward LF here since most tools prefer LF. |
| 5502 for linenum in crlf_lines: |
| 5503 Error(filename, linenum, 'whitespace/newline', 1, |
| 5504 'Unexpected \\r (^M) found; better to use only \\n') |
4638 | 5505 |
4639 sys.stderr.write('Done processing %s\n' % filename) | 5506 sys.stderr.write('Done processing %s\n' % filename) |
4640 | 5507 |
4641 | 5508 |
4642 def PrintUsage(message): | 5509 def PrintUsage(message): |
4643 """Prints a brief usage string and exits, optionally with an error message. | 5510 """Prints a brief usage string and exits, optionally with an error message. |
4644 | 5511 |
4645 Args: | 5512 Args: |
4646 message: The optional error message. | 5513 message: The optional error message. |
4647 """ | 5514 """ |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4744 _cpplint_state.ResetErrorCounts() | 5611 _cpplint_state.ResetErrorCounts() |
4745 for filename in filenames: | 5612 for filename in filenames: |
4746 ProcessFile(filename, _cpplint_state.verbose_level) | 5613 ProcessFile(filename, _cpplint_state.verbose_level) |
4747 _cpplint_state.PrintErrorCounts() | 5614 _cpplint_state.PrintErrorCounts() |
4748 | 5615 |
4749 sys.exit(_cpplint_state.error_count > 0) | 5616 sys.exit(_cpplint_state.error_count > 0) |
4750 | 5617 |
4751 | 5618 |
4752 if __name__ == '__main__': | 5619 if __name__ == '__main__': |
4753 main() | 5620 main() |
OLD | NEW |