OLD | NEW |
1 #!/usr/bin/python2.4 | 1 #!/usr/bin/python2.4 |
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 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
143 | 143 |
144 # We categorize each error message we print. Here are the categories. | 144 # We categorize each error message we print. Here are the categories. |
145 # We want an explicit list so we can list them all in cpplint --filter=. | 145 # We want an explicit list so we can list them all in cpplint --filter=. |
146 # If you add a new error message with a new category, add it to the list | 146 # If you add a new error message with a new category, add it to the list |
147 # here! cpplint_unittest.py should tell you if you forget to do this. | 147 # here! cpplint_unittest.py should tell you if you forget to do this. |
148 # \ used for clearer layout -- pylint: disable-msg=C6013 | 148 # \ used for clearer layout -- pylint: disable-msg=C6013 |
149 _ERROR_CATEGORIES = [ | 149 _ERROR_CATEGORIES = [ |
150 'build/class', | 150 'build/class', |
151 'build/deprecated', | 151 'build/deprecated', |
152 'build/endif_comment', | 152 'build/endif_comment', |
| 153 'build/explicit_make_pair', |
153 'build/forward_decl', | 154 'build/forward_decl', |
154 'build/header_guard', | 155 'build/header_guard', |
155 'build/include', | 156 'build/include', |
156 'build/include_alpha', | 157 'build/include_alpha', |
157 'build/include_order', | 158 'build/include_order', |
158 'build/include_what_you_use', | 159 'build/include_what_you_use', |
159 'build/namespaces', | 160 'build/namespaces', |
160 'build/printf_format', | 161 'build/printf_format', |
161 'build/storage_class', | 162 'build/storage_class', |
162 'legal/copyright', | 163 'legal/copyright', |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
203 'whitespace/parens', | 204 'whitespace/parens', |
204 'whitespace/semicolon', | 205 'whitespace/semicolon', |
205 'whitespace/tab', | 206 'whitespace/tab', |
206 'whitespace/todo' | 207 'whitespace/todo' |
207 ] | 208 ] |
208 | 209 |
209 # The default state of the category filter. This is overrided by the --filter= | 210 # The default state of the category filter. This is overrided by the --filter= |
210 # flag. By default all errors are on, so only add here categories that should be | 211 # flag. By default all errors are on, so only add here categories that should be |
211 # off by default (i.e., categories that must be enabled by the --filter= flags). | 212 # off by default (i.e., categories that must be enabled by the --filter= flags). |
212 # All entries here should start with a '-' or '+', as in the --filter= flag. | 213 # All entries here should start with a '-' or '+', as in the --filter= flag. |
213 _DEFAULT_FILTERS = [ '-build/include_alpha' ] | 214 _DEFAULT_FILTERS = ['-build/include_alpha'] |
214 | 215 |
215 # We used to check for high-bit characters, but after much discussion we | 216 # We used to check for high-bit characters, but after much discussion we |
216 # decided those were OK, as long as they were in UTF-8 and didn't represent | 217 # decided those were OK, as long as they were in UTF-8 and didn't represent |
217 # hard-coded international strings, which belong in a seperate i18n file. | 218 # hard-coded international strings, which belong in a separate i18n file. |
218 | 219 |
219 # Headers that we consider STL headers. | 220 # Headers that we consider STL headers. |
220 _STL_HEADERS = frozenset([ | 221 _STL_HEADERS = frozenset([ |
221 'algobase.h', 'algorithm', 'alloc.h', 'bitset', 'deque', 'exception', | 222 'algobase.h', 'algorithm', 'alloc.h', 'bitset', 'deque', 'exception', |
222 'function.h', 'functional', 'hash_map', 'hash_map.h', 'hash_set', | 223 'function.h', 'functional', 'hash_map', 'hash_map.h', 'hash_set', |
223 'hash_set.h', 'iterator', 'list', 'list.h', 'map', 'memory', 'new', | 224 'hash_set.h', 'iterator', 'list', 'list.h', 'map', 'memory', 'new', |
224 'pair.h', 'pthread_alloc', 'queue', 'set', 'set.h', 'sstream', 'stack', | 225 'pair.h', 'pthread_alloc', 'queue', 'set', 'set.h', 'sstream', 'stack', |
225 'stl_alloc.h', 'stl_relops.h', 'type_traits.h', | 226 'stl_alloc.h', 'stl_relops.h', 'type_traits.h', |
226 'utility', 'vector', 'vector.h', | 227 'utility', 'vector', 'vector.h', |
227 ]) | 228 ]) |
228 | 229 |
229 | 230 |
230 # Non-STL C++ system headers. | 231 # Non-STL C++ system headers. |
231 _CPP_HEADERS = frozenset([ | 232 _CPP_HEADERS = frozenset([ |
232 'algo.h', 'builtinbuf.h', 'bvector.h', 'cassert', 'cctype', | 233 'algo.h', 'builtinbuf.h', 'bvector.h', 'cassert', 'cctype', |
233 'cerrno', 'cfloat', 'ciso646', 'climits', 'clocale', 'cmath', | 234 'cerrno', 'cfloat', 'ciso646', 'climits', 'clocale', 'cmath', |
234 'complex', 'complex.h', 'csetjmp', 'csignal', 'cstdarg', 'cstddef', | 235 'complex', 'complex.h', 'csetjmp', 'csignal', 'cstdarg', 'cstddef', |
235 'cstdio', 'cstdlib', 'cstring', 'ctime', 'cwchar', 'cwctype', | 236 'cstdio', 'cstdlib', 'cstring', 'ctime', 'cwchar', 'cwctype', |
236 'defalloc.h', 'deque.h', 'editbuf.h', 'exception', 'fstream', | 237 'defalloc.h', 'deque.h', 'editbuf.h', 'exception', 'fstream', |
237 'fstream.h', 'hashtable.h', 'heap.h', 'indstream.h', 'iomanip', | 238 'fstream.h', 'hashtable.h', 'heap.h', 'indstream.h', 'iomanip', |
238 'iomanip.h', 'ios', 'iosfwd', 'iostream', 'iostream.h', 'istream.h', | 239 'iomanip.h', 'ios', 'iosfwd', 'iostream', 'iostream.h', 'istream', |
239 'iterator.h', 'limits', 'map.h', 'multimap.h', 'multiset.h', | 240 'istream.h', 'iterator.h', 'limits', 'map.h', 'multimap.h', 'multiset.h', |
240 'numeric', 'ostream.h', 'parsestream.h', 'pfstream.h', 'PlotFile.h', | 241 'numeric', 'ostream', 'ostream.h', 'parsestream.h', 'pfstream.h', |
241 'procbuf.h', 'pthread_alloc.h', 'rope', 'rope.h', 'ropeimpl.h', | 242 'PlotFile.h', 'procbuf.h', 'pthread_alloc.h', 'rope', 'rope.h', |
242 'SFile.h', 'slist', 'slist.h', 'stack.h', 'stdexcept', | 243 'ropeimpl.h', 'SFile.h', 'slist', 'slist.h', 'stack.h', 'stdexcept', |
243 'stdiostream.h', 'streambuf.h', 'stream.h', 'strfile.h', 'string', | 244 'stdiostream.h', 'streambuf.h', 'stream.h', 'strfile.h', 'string', |
244 'strstream', 'strstream.h', 'tempbuf.h', 'tree.h', 'typeinfo', 'valarray', | 245 'strstream', 'strstream.h', 'tempbuf.h', 'tree.h', 'typeinfo', 'valarray', |
245 ]) | 246 ]) |
246 | 247 |
247 | 248 |
248 # Assertion macros. These are defined in base/logging.h and | 249 # Assertion macros. These are defined in base/logging.h and |
249 # testing/base/gunit.h. Note that the _M versions need to come first | 250 # testing/base/gunit.h. Note that the _M versions need to come first |
250 # for substring matching to work. | 251 # for substring matching to work. |
251 _CHECK_MACROS = [ | 252 _CHECK_MACROS = [ |
252 'DCHECK', 'CHECK', | 253 'DCHECK', 'CHECK', |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
303 error_suppressions store. Reports an error if the NOLINT comment | 304 error_suppressions store. Reports an error if the NOLINT comment |
304 was malformed. | 305 was malformed. |
305 | 306 |
306 Args: | 307 Args: |
307 filename: str, the name of the input file. | 308 filename: str, the name of the input file. |
308 raw_line: str, the line of input text, with comments. | 309 raw_line: str, the line of input text, with comments. |
309 linenum: int, the number of the current line. | 310 linenum: int, the number of the current line. |
310 error: function, an error handler. | 311 error: function, an error handler. |
311 """ | 312 """ |
312 # FIXME(adonovan): "NOLINT(" is misparsed as NOLINT(*). | 313 # FIXME(adonovan): "NOLINT(" is misparsed as NOLINT(*). |
313 m = _RE_SUPPRESSION.search(raw_line) | 314 matched = _RE_SUPPRESSION.search(raw_line) |
314 if m: | 315 if matched: |
315 category = m.group(1) | 316 category = matched.group(1) |
316 if category in (None, '(*)'): # => "suppress all" | 317 if category in (None, '(*)'): # => "suppress all" |
317 _error_suppressions.setdefault(None, set()).add(linenum) | 318 _error_suppressions.setdefault(None, set()).add(linenum) |
318 else: | 319 else: |
319 if category.startswith('(') and category.endswith(')'): | 320 if category.startswith('(') and category.endswith(')'): |
320 category = category[1:-1] | 321 category = category[1:-1] |
321 if category in _ERROR_CATEGORIES: | 322 if category in _ERROR_CATEGORIES: |
322 _error_suppressions.setdefault(category, set()).add(linenum) | 323 _error_suppressions.setdefault(category, set()).add(linenum) |
323 else: | 324 else: |
324 error(filename, linenum, 'readability/nolint', 5, | 325 error(filename, linenum, 'readability/nolint', 5, |
325 'Unknown NOLINT error category: %s' % category) | 326 'Unknown NOLINT error category: %s' % category) |
326 | 327 |
327 | 328 |
328 def ResetNolintSuppressions(): | 329 def ResetNolintSuppressions(): |
329 "Resets the set of NOLINT suppressions to empty." | 330 "Resets the set of NOLINT suppressions to empty." |
330 _error_suppressions.clear() | 331 _error_suppressions.clear() |
331 | 332 |
332 | 333 |
333 def IsErrorSuppressedByNolint(category, linenum): | 334 def IsErrorSuppressedByNolint(category, linenum): |
334 """Returns true if the specified error category is suppressed on this line. | 335 """Returns true if the specified error category is suppressed on this line. |
335 | 336 |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
397 } | 398 } |
398 | 399 |
399 def __init__(self): | 400 def __init__(self): |
400 dict.__init__(self) | 401 dict.__init__(self) |
401 # The name of the current section. | 402 # The name of the current section. |
402 self._section = self._INITIAL_SECTION | 403 self._section = self._INITIAL_SECTION |
403 # The path of last found header. | 404 # The path of last found header. |
404 self._last_header = '' | 405 self._last_header = '' |
405 | 406 |
406 def CanonicalizeAlphabeticalOrder(self, header_path): | 407 def CanonicalizeAlphabeticalOrder(self, header_path): |
407 """Returns a path canonicalized for alphabetical comparisson. | 408 """Returns a path canonicalized for alphabetical comparison. |
408 | 409 |
409 - replaces "-" with "_" so they both cmp the same. | 410 - replaces "-" with "_" so they both cmp the same. |
410 - removes '-inl' since we don't require them to be after the main header. | 411 - removes '-inl' since we don't require them to be after the main header. |
411 - lowercase everything, just in case. | 412 - lowercase everything, just in case. |
412 | 413 |
413 Args: | 414 Args: |
414 header_path: Path to be canonicalized. | 415 header_path: Path to be canonicalized. |
415 | 416 |
416 Returns: | 417 Returns: |
417 Canonicalized path. | 418 Canonicalized path. |
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
655 # 50 => 0, 100 => 1, 200 => 2, 400 => 3, 800 => 4, 1600 => 5, ... | 656 # 50 => 0, 100 => 1, 200 => 2, 400 => 3, 800 => 4, 1600 => 5, ... |
656 if error_level > 5: | 657 if error_level > 5: |
657 error_level = 5 | 658 error_level = 5 |
658 error(filename, linenum, 'readability/fn_size', error_level, | 659 error(filename, linenum, 'readability/fn_size', error_level, |
659 'Small and focused functions are preferred:' | 660 'Small and focused functions are preferred:' |
660 ' %s has %d non-comment lines' | 661 ' %s has %d non-comment lines' |
661 ' (error triggered by exceeding %d lines).' % ( | 662 ' (error triggered by exceeding %d lines).' % ( |
662 self.current_function, self.lines_in_function, trigger)) | 663 self.current_function, self.lines_in_function, trigger)) |
663 | 664 |
664 def End(self): | 665 def End(self): |
665 """Stop analizing function body.""" | 666 """Stop analyzing function body.""" |
666 self.in_a_function = False | 667 self.in_a_function = False |
667 | 668 |
668 | 669 |
669 class _IncludeError(Exception): | 670 class _IncludeError(Exception): |
670 """Indicates a problem with the include order in a file.""" | 671 """Indicates a problem with the include order in a file.""" |
671 pass | 672 pass |
672 | 673 |
673 | 674 |
674 class FileInfo: | 675 class FileInfo: |
675 """Provides utility functions for filenames. | 676 """Provides utility functions for filenames. |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
753 def NoExtension(self): | 754 def NoExtension(self): |
754 """File has no source file extension.""" | 755 """File has no source file extension.""" |
755 return '/'.join(self.Split()[0:2]) | 756 return '/'.join(self.Split()[0:2]) |
756 | 757 |
757 def IsSource(self): | 758 def IsSource(self): |
758 """File has a source file extension.""" | 759 """File has a source file extension.""" |
759 return self.Extension()[1:] in ('c', 'cc', 'cpp', 'cxx') | 760 return self.Extension()[1:] in ('c', 'cc', 'cpp', 'cxx') |
760 | 761 |
761 | 762 |
762 def _ShouldPrintError(category, confidence, linenum): | 763 def _ShouldPrintError(category, confidence, linenum): |
763 """Returns true iff confidence >= verbose, category passes | 764 """If confidence >= verbose, category passes filter and is not suppressed.""" |
764 filter and is not NOLINT-suppressed.""" | |
765 | 765 |
766 # There are three ways we might decide not to print an error message: | 766 # There are three ways we might decide not to print an error message: |
767 # a "NOLINT(category)" comment appears in the source, | 767 # a "NOLINT(category)" comment appears in the source, |
768 # the verbosity level isn't high enough, or the filters filter it out. | 768 # the verbosity level isn't high enough, or the filters filter it out. |
769 if IsErrorSuppressedByNolint(category, linenum): | 769 if IsErrorSuppressedByNolint(category, linenum): |
770 return False | 770 return False |
771 if confidence < _cpplint_state.verbose_level: | 771 if confidence < _cpplint_state.verbose_level: |
772 return False | 772 return False |
773 | 773 |
774 is_filtered = False | 774 is_filtered = False |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
906 """Removes //-comments and single-line C-style /* */ comments. | 906 """Removes //-comments and single-line C-style /* */ comments. |
907 | 907 |
908 Args: | 908 Args: |
909 line: A line of C++ source. | 909 line: A line of C++ source. |
910 | 910 |
911 Returns: | 911 Returns: |
912 The line with single-line comments removed. | 912 The line with single-line comments removed. |
913 """ | 913 """ |
914 commentpos = line.find('//') | 914 commentpos = line.find('//') |
915 if commentpos != -1 and not IsCppString(line[:commentpos]): | 915 if commentpos != -1 and not IsCppString(line[:commentpos]): |
916 line = line[:commentpos] | 916 line = line[:commentpos].rstrip() |
917 # get rid of /* ... */ | 917 # get rid of /* ... */ |
918 return _RE_PATTERN_CLEANSE_LINE_C_COMMENTS.sub('', line) | 918 return _RE_PATTERN_CLEANSE_LINE_C_COMMENTS.sub('', line) |
919 | 919 |
920 | 920 |
921 class CleansedLines(object): | 921 class CleansedLines(object): |
922 """Holds 3 copies of all lines with different preprocessing applied to them. | 922 """Holds 3 copies of all lines with different preprocessing applied to them. |
923 | 923 |
924 1) elided member contains lines without strings and comments, | 924 1) elided member contains lines without strings and comments, |
925 2) lines member contains lines without comments, and | 925 2) lines member contains lines without comments, and |
926 3) raw member contains all the lines without processing. | 926 3) raw member contains all the lines without processing. |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
959 # outside of strings and chars. | 959 # outside of strings and chars. |
960 elided = _RE_PATTERN_CLEANSE_LINE_ESCAPES.sub('', elided) | 960 elided = _RE_PATTERN_CLEANSE_LINE_ESCAPES.sub('', elided) |
961 elided = _RE_PATTERN_CLEANSE_LINE_SINGLE_QUOTES.sub("''", elided) | 961 elided = _RE_PATTERN_CLEANSE_LINE_SINGLE_QUOTES.sub("''", elided) |
962 elided = _RE_PATTERN_CLEANSE_LINE_DOUBLE_QUOTES.sub('""', elided) | 962 elided = _RE_PATTERN_CLEANSE_LINE_DOUBLE_QUOTES.sub('""', elided) |
963 return elided | 963 return elided |
964 | 964 |
965 | 965 |
966 def CloseExpression(clean_lines, linenum, pos): | 966 def CloseExpression(clean_lines, linenum, pos): |
967 """If input points to ( or { or [, finds the position that closes it. | 967 """If input points to ( or { or [, finds the position that closes it. |
968 | 968 |
969 If lines[linenum][pos] points to a '(' or '{' or '[', finds the the | 969 If lines[linenum][pos] points to a '(' or '{' or '[', finds the |
970 linenum/pos that correspond to the closing of the expression. | 970 linenum/pos that correspond to the closing of the expression. |
971 | 971 |
972 Args: | 972 Args: |
973 clean_lines: A CleansedLines instance containing the file. | 973 clean_lines: A CleansedLines instance containing the file. |
974 linenum: The number of the line to check. | 974 linenum: The number of the line to check. |
975 pos: A position on the line. | 975 pos: A position on the line. |
976 | 976 |
977 Returns: | 977 Returns: |
978 A tuple (line, linenum, pos) pointer *past* the closing brace, or | 978 A tuple (line, linenum, pos) pointer *past* the closing brace, or |
979 (line, len(lines), -1) if we never find a close. Note we ignore | 979 (line, len(lines), -1) if we never find a close. Note we ignore |
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1241 """ | 1241 """ |
1242 line = clean_lines.elided[linenum] | 1242 line = clean_lines.elided[linenum] |
1243 if _RE_PATTERN_INVALID_INCREMENT.match(line): | 1243 if _RE_PATTERN_INVALID_INCREMENT.match(line): |
1244 error(filename, linenum, 'runtime/invalid_increment', 5, | 1244 error(filename, linenum, 'runtime/invalid_increment', 5, |
1245 'Changing pointer instead of value (or unused value of operator*).') | 1245 'Changing pointer instead of value (or unused value of operator*).') |
1246 | 1246 |
1247 | 1247 |
1248 class _ClassInfo(object): | 1248 class _ClassInfo(object): |
1249 """Stores information about a class.""" | 1249 """Stores information about a class.""" |
1250 | 1250 |
1251 def __init__(self, name, linenum): | 1251 def __init__(self, name, clean_lines, linenum): |
1252 self.name = name | 1252 self.name = name |
1253 self.linenum = linenum | 1253 self.linenum = linenum |
1254 self.seen_open_brace = False | 1254 self.seen_open_brace = False |
1255 self.is_derived = False | 1255 self.is_derived = False |
1256 self.virtual_method_linenumber = None | 1256 self.virtual_method_linenumber = None |
1257 self.has_virtual_destructor = False | 1257 self.has_virtual_destructor = False |
1258 self.brace_depth = 0 | 1258 self.brace_depth = 0 |
1259 | 1259 |
| 1260 # Try to find the end of the class. This will be confused by things like: |
| 1261 # class A { |
| 1262 # } *x = { ... |
| 1263 # |
| 1264 # But it's still good enough for CheckSectionSpacing. |
| 1265 self.last_line = 0 |
| 1266 depth = 0 |
| 1267 for i in range(linenum, clean_lines.NumLines()): |
| 1268 line = clean_lines.lines[i] |
| 1269 depth += line.count('{') - line.count('}') |
| 1270 if not depth: |
| 1271 self.last_line = i |
| 1272 break |
| 1273 |
1260 | 1274 |
1261 class _ClassState(object): | 1275 class _ClassState(object): |
1262 """Holds the current state of the parse relating to class declarations. | 1276 """Holds the current state of the parse relating to class declarations. |
1263 | 1277 |
1264 It maintains a stack of _ClassInfos representing the parser's guess | 1278 It maintains a stack of _ClassInfos representing the parser's guess |
1265 as to the current nesting of class declarations. The innermost class | 1279 as to the current nesting of class declarations. The innermost class |
1266 is at the top (back) of the stack. Typically, the stack will either | 1280 is at the top (back) of the stack. Typically, the stack will either |
1267 be empty or have exactly one entry. | 1281 be empty or have exactly one entry. |
1268 """ | 1282 """ |
1269 | 1283 |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1371 error(filename, linenum, 'runtime/member_string_references', 2, | 1385 error(filename, linenum, 'runtime/member_string_references', 2, |
1372 'const string& members are dangerous. It is much better to use ' | 1386 'const string& members are dangerous. It is much better to use ' |
1373 'alternatives, such as pointers or simple constants.') | 1387 'alternatives, such as pointers or simple constants.') |
1374 | 1388 |
1375 # Track class entry and exit, and attempt to find cases within the | 1389 # Track class entry and exit, and attempt to find cases within the |
1376 # class declaration that don't meet the C++ style | 1390 # class declaration that don't meet the C++ style |
1377 # guidelines. Tracking is very dependent on the code matching Google | 1391 # guidelines. Tracking is very dependent on the code matching Google |
1378 # style guidelines, but it seems to perform well enough in testing | 1392 # style guidelines, but it seems to perform well enough in testing |
1379 # to be a worthwhile addition to the checks. | 1393 # to be a worthwhile addition to the checks. |
1380 classinfo_stack = class_state.classinfo_stack | 1394 classinfo_stack = class_state.classinfo_stack |
1381 # Look for a class declaration | 1395 # Look for a class declaration. The regexp accounts for decorated classes |
| 1396 # such as in: |
| 1397 # class LOCKABLE API Object { |
| 1398 # }; |
1382 class_decl_match = Match( | 1399 class_decl_match = Match( |
1383 r'\s*(template\s*<[\w\s<>,:]*>\s*)?(class|struct)\s+(\w+(::\w+)*)', line) | 1400 r'\s*(template\s*<[\w\s<>,:]*>\s*)?' |
| 1401 '(class|struct)\s+([A-Z_]+\s+)*(\w+(::\w+)*)', line) |
1384 if class_decl_match: | 1402 if class_decl_match: |
1385 classinfo_stack.append(_ClassInfo(class_decl_match.group(3), linenum)) | 1403 classinfo_stack.append(_ClassInfo( |
| 1404 class_decl_match.group(4), clean_lines, linenum)) |
1386 | 1405 |
1387 # Everything else in this function uses the top of the stack if it's | 1406 # Everything else in this function uses the top of the stack if it's |
1388 # not empty. | 1407 # not empty. |
1389 if not classinfo_stack: | 1408 if not classinfo_stack: |
1390 return | 1409 return |
1391 | 1410 |
1392 classinfo = classinfo_stack[-1] | 1411 classinfo = classinfo_stack[-1] |
1393 | 1412 |
1394 # If the opening brace hasn't been seen look for it and also | 1413 # If the opening brace hasn't been seen look for it and also |
1395 # parent class declarations. | 1414 # parent class declarations. |
1396 if not classinfo.seen_open_brace: | 1415 if not classinfo.seen_open_brace: |
1397 # If the line has a ';' in it, assume it's a forward declaration or | 1416 # If the line has a ';' in it, assume it's a forward declaration or |
1398 # a single-line class declaration, which we won't process. | 1417 # a single-line class declaration, which we won't process. |
1399 if line.find(';') != -1: | 1418 if line.find(';') != -1: |
1400 classinfo_stack.pop() | 1419 classinfo_stack.pop() |
1401 return | 1420 return |
1402 classinfo.seen_open_brace = (line.find('{') != -1) | 1421 classinfo.seen_open_brace = (line.find('{') != -1) |
1403 # Look for a bare ':' | 1422 # Look for a bare ':' |
1404 if Search('(^|[^:]):($|[^:])', line): | 1423 if Search('(^|[^:]):($|[^:])', line): |
1405 classinfo.is_derived = True | 1424 classinfo.is_derived = True |
1406 if not classinfo.seen_open_brace: | 1425 if not classinfo.seen_open_brace: |
1407 return # Everything else in this function is for after open brace | 1426 return # Everything else in this function is for after open brace |
1408 | 1427 |
1409 # The class may have been declared with namespace or classname qualifiers. | 1428 # The class may have been declared with namespace or classname qualifiers. |
1410 # The constructor and destructor will not have those qualifiers. | 1429 # The constructor and destructor will not have those qualifiers. |
1411 base_classname = classinfo.name.split('::')[-1] | 1430 base_classname = classinfo.name.split('::')[-1] |
1412 | 1431 |
1413 # Look for single-argument constructors that aren't marked explicit. | 1432 # Look for single-argument constructors that aren't marked explicit. |
1414 # Technically a valid construct, but against style. | 1433 # Technically a valid construct, but against style. |
1415 args = Match(r'(?<!explicit)\s+%s\s*\(([^,()]+)\)' | 1434 args = Match(r'\s+(?:inline\s+)?%s\s*\(([^,()]+)\)' |
1416 % re.escape(base_classname), | 1435 % re.escape(base_classname), |
1417 line) | 1436 line) |
1418 if (args and | 1437 if (args and |
1419 args.group(1) != 'void' and | 1438 args.group(1) != 'void' and |
1420 not Match(r'(const\s+)?%s\s*&' % re.escape(base_classname), | 1439 not Match(r'(const\s+)?%s\s*(?:<\w+>\s*)?&' % re.escape(base_classname), |
1421 args.group(1).strip())): | 1440 args.group(1).strip())): |
1422 error(filename, linenum, 'runtime/explicit', 5, | 1441 error(filename, linenum, 'runtime/explicit', 5, |
1423 'Single-argument constructors should be marked explicit.') | 1442 'Single-argument constructors should be marked explicit.') |
1424 | 1443 |
1425 # Look for methods declared virtual. | 1444 # Look for methods declared virtual. |
1426 if Search(r'\bvirtual\b', line): | 1445 if Search(r'\bvirtual\b', line): |
1427 classinfo.virtual_method_linenumber = linenum | 1446 classinfo.virtual_method_linenumber = linenum |
1428 # Only look for a destructor declaration on the same line. It would | 1447 # Only look for a destructor declaration on the same line. It would |
1429 # be extremely unlikely for the destructor declaration to occupy | 1448 # be extremely unlikely for the destructor declaration to occupy |
1430 # more than one line. | 1449 # more than one line. |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1501 elif Search(r'\(\s+(?!(\s*\\)|\()', fncall): | 1520 elif Search(r'\(\s+(?!(\s*\\)|\()', fncall): |
1502 error(filename, linenum, 'whitespace/parens', 2, | 1521 error(filename, linenum, 'whitespace/parens', 2, |
1503 'Extra space after (') | 1522 'Extra space after (') |
1504 if (Search(r'\w\s+\(', fncall) and | 1523 if (Search(r'\w\s+\(', fncall) and |
1505 not Search(r'#\s*define|typedef', fncall)): | 1524 not Search(r'#\s*define|typedef', fncall)): |
1506 error(filename, linenum, 'whitespace/parens', 4, | 1525 error(filename, linenum, 'whitespace/parens', 4, |
1507 'Extra space before ( in function call') | 1526 'Extra space before ( in function call') |
1508 # If the ) is followed only by a newline or a { + newline, assume it's | 1527 # If the ) is followed only by a newline or a { + newline, assume it's |
1509 # part of a control statement (if/while/etc), and don't complain | 1528 # part of a control statement (if/while/etc), and don't complain |
1510 if Search(r'[^)]\s+\)\s*[^{\s]', fncall): | 1529 if Search(r'[^)]\s+\)\s*[^{\s]', fncall): |
1511 error(filename, linenum, 'whitespace/parens', 2, | 1530 # If the closing parenthesis is preceded by only whitespaces, |
1512 'Extra space before )') | 1531 # try to give a more descriptive error message. |
| 1532 if Search(r'^\s+\)', fncall): |
| 1533 error(filename, linenum, 'whitespace/parens', 2, |
| 1534 'Closing ) should be moved to the previous line') |
| 1535 else: |
| 1536 error(filename, linenum, 'whitespace/parens', 2, |
| 1537 'Extra space before )') |
1513 | 1538 |
1514 | 1539 |
1515 def IsBlankLine(line): | 1540 def IsBlankLine(line): |
1516 """Returns true if the given line is blank. | 1541 """Returns true if the given line is blank. |
1517 | 1542 |
1518 We consider a line to be blank if the line is empty or consists of | 1543 We consider a line to be blank if the line is empty or consists of |
1519 only white spaces. | 1544 only white spaces. |
1520 | 1545 |
1521 Args: | 1546 Args: |
1522 line: A line of a string. | 1547 line: A line of a string. |
(...skipping 10 matching lines...) Expand all Loading... |
1533 | 1558 |
1534 For an overview why this is done, see: | 1559 For an overview why this is done, see: |
1535 http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Write_Short_Fun
ctions | 1560 http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Write_Short_Fun
ctions |
1536 | 1561 |
1537 Uses a simplistic algorithm assuming other style guidelines | 1562 Uses a simplistic algorithm assuming other style guidelines |
1538 (especially spacing) are followed. | 1563 (especially spacing) are followed. |
1539 Only checks unindented functions, so class members are unchecked. | 1564 Only checks unindented functions, so class members are unchecked. |
1540 Trivial bodies are unchecked, so constructors with huge initializer lists | 1565 Trivial bodies are unchecked, so constructors with huge initializer lists |
1541 may be missed. | 1566 may be missed. |
1542 Blank/comment lines are not counted so as to avoid encouraging the removal | 1567 Blank/comment lines are not counted so as to avoid encouraging the removal |
1543 of vertical space and commments just to get through a lint check. | 1568 of vertical space and comments just to get through a lint check. |
1544 NOLINT *on the last line of a function* disables this check. | 1569 NOLINT *on the last line of a function* disables this check. |
1545 | 1570 |
1546 Args: | 1571 Args: |
1547 filename: The name of the current file. | 1572 filename: The name of the current file. |
1548 clean_lines: A CleansedLines instance containing the file. | 1573 clean_lines: A CleansedLines instance containing the file. |
1549 linenum: The number of the line to check. | 1574 linenum: The number of the line to check. |
1550 function_state: Current function name and lines in body so far. | 1575 function_state: Current function name and lines in body so far. |
1551 error: The function to call with any errors found. | 1576 error: The function to call with any errors found. |
1552 """ | 1577 """ |
1553 lines = clean_lines.lines | 1578 lines = clean_lines.lines |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1629 error(filename, linenum, 'whitespace/todo', 2, | 1654 error(filename, linenum, 'whitespace/todo', 2, |
1630 'TODO(my_username) should be followed by a space') | 1655 'TODO(my_username) should be followed by a space') |
1631 | 1656 |
1632 | 1657 |
1633 def CheckSpacing(filename, clean_lines, linenum, error): | 1658 def CheckSpacing(filename, clean_lines, linenum, error): |
1634 """Checks for the correctness of various spacing issues in the code. | 1659 """Checks for the correctness of various spacing issues in the code. |
1635 | 1660 |
1636 Things we check for: spaces around operators, spaces after | 1661 Things we check for: spaces around operators, spaces after |
1637 if/for/while/switch, no spaces around parens in function calls, two | 1662 if/for/while/switch, no spaces around parens in function calls, two |
1638 spaces between code and comment, don't start a block with a blank | 1663 spaces between code and comment, don't start a block with a blank |
1639 line, don't end a function with a blank line, don't have too many | 1664 line, don't end a function with a blank line, don't add a blank line |
1640 blank lines in a row. | 1665 after public/protected/private, don't have too many blank lines in a row. |
1641 | 1666 |
1642 Args: | 1667 Args: |
1643 filename: The name of the current file. | 1668 filename: The name of the current file. |
1644 clean_lines: A CleansedLines instance containing the file. | 1669 clean_lines: A CleansedLines instance containing the file. |
1645 linenum: The number of the line to check. | 1670 linenum: The number of the line to check. |
1646 error: The function to call with any errors found. | 1671 error: The function to call with any errors found. |
1647 """ | 1672 """ |
1648 | 1673 |
1649 raw = clean_lines.raw_lines | 1674 raw = clean_lines.raw_lines |
1650 line = raw[linenum] | 1675 line = raw[linenum] |
1651 | 1676 |
1652 # Before nixing comments, check if the line is blank for no good | 1677 # Before nixing comments, check if the line is blank for no good |
1653 # reason. This includes the first line after a block is opened, and | 1678 # reason. This includes the first line after a block is opened, and |
1654 # blank lines at the end of a function (ie, right before a line like '}' | 1679 # blank lines at the end of a function (ie, right before a line like '}' |
1655 if IsBlankLine(line): | 1680 if IsBlankLine(line): |
1656 elided = clean_lines.elided | 1681 elided = clean_lines.elided |
1657 prev_line = elided[linenum - 1] | 1682 prev_line = elided[linenum - 1] |
1658 prevbrace = prev_line.rfind('{') | 1683 prevbrace = prev_line.rfind('{') |
1659 # TODO(unknown): Don't complain if line before blank line, and line after, | 1684 # TODO(unknown): Don't complain if line before blank line, and line after, |
1660 # both start with alnums and are indented the same amount. | 1685 # both start with alnums and are indented the same amount. |
1661 # This ignores whitespace at the start of a namespace block | 1686 # This ignores whitespace at the start of a namespace block |
1662 # because those are not usually indented. | 1687 # because those are not usually indented. |
1663 if (prevbrace != -1 and prev_line[prevbrace:].find('}') == -1 | 1688 if (prevbrace != -1 and prev_line[prevbrace:].find('}') == -1 |
1664 and prev_line[:prevbrace].find('namespace') == -1): | 1689 and prev_line[:prevbrace].find('namespace') == -1): |
1665 # OK, we have a blank line at the start of a code block. Before we | 1690 # OK, we have a blank line at the start of a code block. Before we |
1666 # complain, we check if it is an exception to the rule: The previous | 1691 # complain, we check if it is an exception to the rule: The previous |
1667 # non-empty line has the paramters of a function header that are indented | 1692 # non-empty line has the parameters of a function header that are indented |
1668 # 4 spaces (because they did not fit in a 80 column line when placed on | 1693 # 4 spaces (because they did not fit in a 80 column line when placed on |
1669 # the same line as the function name). We also check for the case where | 1694 # the same line as the function name). We also check for the case where |
1670 # the previous line is indented 6 spaces, which may happen when the | 1695 # the previous line is indented 6 spaces, which may happen when the |
1671 # initializers of a constructor do not fit into a 80 column line. | 1696 # initializers of a constructor do not fit into a 80 column line. |
1672 exception = False | 1697 exception = False |
1673 if Match(r' {6}\w', prev_line): # Initializer list? | 1698 if Match(r' {6}\w', prev_line): # Initializer list? |
1674 # We are looking for the opening column of initializer list, which | 1699 # We are looking for the opening column of initializer list, which |
1675 # should be indented 4 spaces to cause 6 space indentation afterwards. | 1700 # should be indented 4 spaces to cause 6 space indentation afterwards. |
1676 search_position = linenum-2 | 1701 search_position = linenum-2 |
1677 while (search_position >= 0 | 1702 while (search_position >= 0 |
(...skipping 30 matching lines...) Expand all Loading... |
1708 # } | 1733 # } |
1709 if linenum + 1 < clean_lines.NumLines(): | 1734 if linenum + 1 < clean_lines.NumLines(): |
1710 next_line = raw[linenum + 1] | 1735 next_line = raw[linenum + 1] |
1711 if (next_line | 1736 if (next_line |
1712 and Match(r'\s*}', next_line) | 1737 and Match(r'\s*}', next_line) |
1713 and next_line.find('namespace') == -1 | 1738 and next_line.find('namespace') == -1 |
1714 and next_line.find('} else ') == -1): | 1739 and next_line.find('} else ') == -1): |
1715 error(filename, linenum, 'whitespace/blank_line', 3, | 1740 error(filename, linenum, 'whitespace/blank_line', 3, |
1716 'Blank line at the end of a code block. Is this needed?') | 1741 'Blank line at the end of a code block. Is this needed?') |
1717 | 1742 |
| 1743 matched = Match(r'\s*(public|protected|private):', prev_line) |
| 1744 if matched: |
| 1745 error(filename, linenum, 'whitespace/blank_line', 3, |
| 1746 'Do not leave a blank line after "%s:"' % matched.group(1)) |
| 1747 |
1718 # Next, we complain if there's a comment too near the text | 1748 # Next, we complain if there's a comment too near the text |
1719 commentpos = line.find('//') | 1749 commentpos = line.find('//') |
1720 if commentpos != -1: | 1750 if commentpos != -1: |
1721 # Check if the // may be in quotes. If so, ignore it | 1751 # Check if the // may be in quotes. If so, ignore it |
1722 # Comparisons made explicit for clarity -- pylint: disable-msg=C6403 | 1752 # Comparisons made explicit for clarity -- pylint: disable-msg=C6403 |
1723 if (line.count('"', 0, commentpos) - | 1753 if (line.count('"', 0, commentpos) - |
1724 line.count('\\"', 0, commentpos)) % 2 == 0: # not in quotes | 1754 line.count('\\"', 0, commentpos)) % 2 == 0: # not in quotes |
1725 # Allow one space for new scopes, two spaces otherwise: | 1755 # Allow one space for new scopes, two spaces otherwise: |
1726 if (not Match(r'^\s*{ //', line) and | 1756 if (not Match(r'^\s*{ //', line) and |
1727 ((commentpos >= 1 and | 1757 ((commentpos >= 1 and |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1817 if not len(match.group(2)) in [0, 1]: | 1847 if not len(match.group(2)) in [0, 1]: |
1818 error(filename, linenum, 'whitespace/parens', 5, | 1848 error(filename, linenum, 'whitespace/parens', 5, |
1819 'Should have zero or one spaces inside ( and ) in %s' % | 1849 'Should have zero or one spaces inside ( and ) in %s' % |
1820 match.group(1)) | 1850 match.group(1)) |
1821 | 1851 |
1822 # You should always have a space after a comma (either as fn arg or operator) | 1852 # You should always have a space after a comma (either as fn arg or operator) |
1823 if Search(r',[^\s]', line): | 1853 if Search(r',[^\s]', line): |
1824 error(filename, linenum, 'whitespace/comma', 3, | 1854 error(filename, linenum, 'whitespace/comma', 3, |
1825 'Missing space after ,') | 1855 'Missing space after ,') |
1826 | 1856 |
| 1857 # You should always have a space after a semicolon |
| 1858 # except for few corner cases |
| 1859 # TODO(unknown): clarify if 'if (1) { return 1;}' is requires one more |
| 1860 # space after ; |
| 1861 if Search(r';[^\s};\\)/]', line): |
| 1862 error(filename, linenum, 'whitespace/semicolon', 3, |
| 1863 'Missing space after ;') |
| 1864 |
1827 # Next we will look for issues with function calls. | 1865 # Next we will look for issues with function calls. |
1828 CheckSpacingForFunctionCall(filename, line, linenum, error) | 1866 CheckSpacingForFunctionCall(filename, line, linenum, error) |
1829 | 1867 |
1830 # Except after an opening paren, you should have spaces before your braces. | 1868 # Except after an opening paren, or after another opening brace (in case of |
1831 # And since you should never have braces at the beginning of a line, this is | 1869 # an initializer list, for instance), you should have spaces before your |
1832 # an easy test. | 1870 # braces. And since you should never have braces at the beginning of a line, |
1833 if Search(r'[^ (]{', line): | 1871 # this is an easy test. |
| 1872 if Search(r'[^ ({]{', line): |
1834 error(filename, linenum, 'whitespace/braces', 5, | 1873 error(filename, linenum, 'whitespace/braces', 5, |
1835 'Missing space before {') | 1874 'Missing space before {') |
1836 | 1875 |
1837 # Make sure '} else {' has spaces. | 1876 # Make sure '} else {' has spaces. |
1838 if Search(r'}else', line): | 1877 if Search(r'}else', line): |
1839 error(filename, linenum, 'whitespace/braces', 5, | 1878 error(filename, linenum, 'whitespace/braces', 5, |
1840 'Missing space before else') | 1879 'Missing space before else') |
1841 | 1880 |
1842 # You shouldn't have spaces before your brackets, except maybe after | 1881 # You shouldn't have spaces before your brackets, except maybe after |
1843 # 'delete []' or 'new char * []'. | 1882 # 'delete []' or 'new char * []'. |
(...skipping 11 matching lines...) Expand all Loading... |
1855 error(filename, linenum, 'whitespace/semicolon', 5, | 1894 error(filename, linenum, 'whitespace/semicolon', 5, |
1856 'Line contains only semicolon. If this should be an empty statement, ' | 1895 'Line contains only semicolon. If this should be an empty statement, ' |
1857 'use { } instead.') | 1896 'use { } instead.') |
1858 elif (Search(r'\s+;\s*$', line) and | 1897 elif (Search(r'\s+;\s*$', line) and |
1859 not Search(r'\bfor\b', line)): | 1898 not Search(r'\bfor\b', line)): |
1860 error(filename, linenum, 'whitespace/semicolon', 5, | 1899 error(filename, linenum, 'whitespace/semicolon', 5, |
1861 'Extra space before last semicolon. If this should be an empty ' | 1900 'Extra space before last semicolon. If this should be an empty ' |
1862 'statement, use { } instead.') | 1901 'statement, use { } instead.') |
1863 | 1902 |
1864 | 1903 |
| 1904 def CheckSectionSpacing(filename, clean_lines, class_info, linenum, error): |
| 1905 """Checks for additional blank line issues related to sections. |
| 1906 |
| 1907 Currently the only thing checked here is blank line before protected/private. |
| 1908 |
| 1909 Args: |
| 1910 filename: The name of the current file. |
| 1911 clean_lines: A CleansedLines instance containing the file. |
| 1912 class_info: A _ClassInfo objects. |
| 1913 linenum: The number of the line to check. |
| 1914 error: The function to call with any errors found. |
| 1915 """ |
| 1916 # Skip checks if the class is small, where small means 25 lines or less. |
| 1917 # 25 lines seems like a good cutoff since that's the usual height of |
| 1918 # terminals, and any class that can't fit in one screen can't really |
| 1919 # be considered "small". |
| 1920 # |
| 1921 # Also skip checks if we are on the first line. This accounts for |
| 1922 # classes that look like |
| 1923 # class Foo { public: ... }; |
| 1924 # |
| 1925 # If we didn't find the end of the class, last_line would be zero, |
| 1926 # and the check will be skipped by the first condition. |
| 1927 if (class_info.last_line - class_info.linenum <= 24 or |
| 1928 linenum <= class_info.linenum): |
| 1929 return |
| 1930 |
| 1931 matched = Match(r'\s*(public|protected|private):', clean_lines.lines[linenum]) |
| 1932 if matched: |
| 1933 # Issue warning if the line before public/protected/private was |
| 1934 # not a blank line, but don't do this if the previous line contains |
| 1935 # "class" or "struct". This can happen two ways: |
| 1936 # - We are at the beginning of the class. |
| 1937 # - We are forward-declaring an inner class that is semantically |
| 1938 # private, but needed to be public for implementation reasons. |
| 1939 prev_line = clean_lines.lines[linenum - 1] |
| 1940 if (not IsBlankLine(prev_line) and |
| 1941 not Search(r'\b(class|struct)\b', prev_line)): |
| 1942 # Try a bit harder to find the beginning of the class. This is to |
| 1943 # account for multi-line base-specifier lists, e.g.: |
| 1944 # class Derived |
| 1945 # : public Base { |
| 1946 end_class_head = class_info.linenum |
| 1947 for i in range(class_info.linenum, linenum): |
| 1948 if Search(r'\{\s*$', clean_lines.lines[i]): |
| 1949 end_class_head = i |
| 1950 break |
| 1951 if end_class_head < linenum - 1: |
| 1952 error(filename, linenum, 'whitespace/blank_line', 3, |
| 1953 '"%s:" should be preceded by a blank line' % matched.group(1)) |
| 1954 |
| 1955 |
1865 def GetPreviousNonBlankLine(clean_lines, linenum): | 1956 def GetPreviousNonBlankLine(clean_lines, linenum): |
1866 """Return the most recent non-blank line and its line number. | 1957 """Return the most recent non-blank line and its line number. |
1867 | 1958 |
1868 Args: | 1959 Args: |
1869 clean_lines: A CleansedLines instance containing the file contents. | 1960 clean_lines: A CleansedLines instance containing the file contents. |
1870 linenum: The number of the line to check. | 1961 linenum: The number of the line to check. |
1871 | 1962 |
1872 Returns: | 1963 Returns: |
1873 A tuple with two elements. The first element is the contents of the last | 1964 A tuple with two elements. The first element is the contents of the last |
1874 non-blank line before the current line, or the empty string if this is the | 1965 non-blank line before the current line, or the empty string if this is the |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2032 | 2123 |
2033 Args: | 2124 Args: |
2034 line: A string, which may be a Unicode string. | 2125 line: A string, which may be a Unicode string. |
2035 | 2126 |
2036 Returns: | 2127 Returns: |
2037 The width of the line in column positions, accounting for Unicode | 2128 The width of the line in column positions, accounting for Unicode |
2038 combining characters and wide characters. | 2129 combining characters and wide characters. |
2039 """ | 2130 """ |
2040 if isinstance(line, unicode): | 2131 if isinstance(line, unicode): |
2041 width = 0 | 2132 width = 0 |
2042 for c in unicodedata.normalize('NFC', line): | 2133 for uc in unicodedata.normalize('NFC', line): |
2043 if unicodedata.east_asian_width(c) in ('W', 'F'): | 2134 if unicodedata.east_asian_width(uc) in ('W', 'F'): |
2044 width += 2 | 2135 width += 2 |
2045 elif not unicodedata.combining(c): | 2136 elif not unicodedata.combining(uc): |
2046 width += 1 | 2137 width += 1 |
2047 return width | 2138 return width |
2048 else: | 2139 else: |
2049 return len(line) | 2140 return len(line) |
2050 | 2141 |
2051 | 2142 |
2052 def CheckStyle(filename, clean_lines, linenum, file_extension, error): | 2143 def CheckStyle(filename, clean_lines, linenum, file_extension, class_state, |
| 2144 error): |
2053 """Checks rules from the 'C++ style rules' section of cppguide.html. | 2145 """Checks rules from the 'C++ style rules' section of cppguide.html. |
2054 | 2146 |
2055 Most of these rules are hard to test (naming, comment style), but we | 2147 Most of these rules are hard to test (naming, comment style), but we |
2056 do what we can. In particular we check for 2-space indents, line lengths, | 2148 do what we can. In particular we check for 2-space indents, line lengths, |
2057 tab usage, spaces inside code, etc. | 2149 tab usage, spaces inside code, etc. |
2058 | 2150 |
2059 Args: | 2151 Args: |
2060 filename: The name of the current file. | 2152 filename: The name of the current file. |
2061 clean_lines: A CleansedLines instance containing the file. | 2153 clean_lines: A CleansedLines instance containing the file. |
2062 linenum: The number of the line to check. | 2154 linenum: The number of the line to check. |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2112 cppvar = GetHeaderGuardCPPVariable(filename) | 2204 cppvar = GetHeaderGuardCPPVariable(filename) |
2113 if (line.startswith('#ifndef %s' % cppvar) or | 2205 if (line.startswith('#ifndef %s' % cppvar) or |
2114 line.startswith('#define %s' % cppvar) or | 2206 line.startswith('#define %s' % cppvar) or |
2115 line.startswith('#endif // %s' % cppvar)): | 2207 line.startswith('#endif // %s' % cppvar)): |
2116 is_header_guard = True | 2208 is_header_guard = True |
2117 # #include lines and header guards can be long, since there's no clean way to | 2209 # #include lines and header guards can be long, since there's no clean way to |
2118 # split them. | 2210 # split them. |
2119 # | 2211 # |
2120 # URLs can be long too. It's possible to split these, but it makes them | 2212 # URLs can be long too. It's possible to split these, but it makes them |
2121 # harder to cut&paste. | 2213 # harder to cut&paste. |
| 2214 # |
| 2215 # The "$Id:...$" comment may also get very long without it being the |
| 2216 # developers fault. |
2122 if (not line.startswith('#include') and not is_header_guard and | 2217 if (not line.startswith('#include') and not is_header_guard and |
2123 not Match(r'^\s*//.*http(s?)://\S*$', line)): | 2218 not Match(r'^\s*//.*http(s?)://\S*$', line) and |
| 2219 not Match(r'^// \$Id:.*#[0-9]+ \$$', line)): |
2124 line_width = GetLineWidth(line) | 2220 line_width = GetLineWidth(line) |
2125 if line_width > 100: | 2221 if line_width > 100: |
2126 error(filename, linenum, 'whitespace/line_length', 4, | 2222 error(filename, linenum, 'whitespace/line_length', 4, |
2127 'Lines should very rarely be longer than 100 characters') | 2223 'Lines should very rarely be longer than 100 characters') |
2128 elif line_width > 80: | 2224 elif line_width > 80: |
2129 error(filename, linenum, 'whitespace/line_length', 2, | 2225 error(filename, linenum, 'whitespace/line_length', 2, |
2130 'Lines should be <= 80 characters long') | 2226 'Lines should be <= 80 characters long') |
2131 | 2227 |
2132 if (cleansed_line.count(';') > 1 and | 2228 if (cleansed_line.count(';') > 1 and |
2133 # for loops are allowed two ;'s (and may run over two lines). | 2229 # for loops are allowed two ;'s (and may run over two lines). |
2134 cleansed_line.find('for') == -1 and | 2230 cleansed_line.find('for') == -1 and |
2135 (GetPreviousNonBlankLine(clean_lines, linenum)[0].find('for') == -1 or | 2231 (GetPreviousNonBlankLine(clean_lines, linenum)[0].find('for') == -1 or |
2136 GetPreviousNonBlankLine(clean_lines, linenum)[0].find(';') != -1) and | 2232 GetPreviousNonBlankLine(clean_lines, linenum)[0].find(';') != -1) and |
2137 # It's ok to have many commands in a switch case that fits in 1 line | 2233 # It's ok to have many commands in a switch case that fits in 1 line |
2138 not ((cleansed_line.find('case ') != -1 or | 2234 not ((cleansed_line.find('case ') != -1 or |
2139 cleansed_line.find('default:') != -1) and | 2235 cleansed_line.find('default:') != -1) and |
2140 cleansed_line.find('break;') != -1)): | 2236 cleansed_line.find('break;') != -1)): |
2141 error(filename, linenum, 'whitespace/newline', 4, | 2237 error(filename, linenum, 'whitespace/newline', 4, |
2142 'More than one command on the same line') | 2238 'More than one command on the same line') |
2143 | 2239 |
2144 # Some more style checks | 2240 # Some more style checks |
2145 CheckBraces(filename, clean_lines, linenum, error) | 2241 CheckBraces(filename, clean_lines, linenum, error) |
2146 CheckSpacing(filename, clean_lines, linenum, error) | 2242 CheckSpacing(filename, clean_lines, linenum, error) |
2147 CheckCheck(filename, clean_lines, linenum, error) | 2243 CheckCheck(filename, clean_lines, linenum, error) |
| 2244 if class_state and class_state.classinfo_stack: |
| 2245 CheckSectionSpacing(filename, clean_lines, |
| 2246 class_state.classinfo_stack[-1], linenum, error) |
2148 | 2247 |
2149 | 2248 |
2150 _RE_PATTERN_INCLUDE_NEW_STYLE = re.compile(r'#include +"[^/]+\.h"') | 2249 _RE_PATTERN_INCLUDE_NEW_STYLE = re.compile(r'#include +"[^/]+\.h"') |
2151 _RE_PATTERN_INCLUDE = re.compile(r'^\s*#\s*include\s*([<"])([^>"]*)[>"].*$') | 2250 _RE_PATTERN_INCLUDE = re.compile(r'^\s*#\s*include\s*([<"])([^>"]*)[>"].*$') |
2152 # Matches the first component of a filename delimited by -s and _s. That is: | 2251 # Matches the first component of a filename delimited by -s and _s. That is: |
2153 # _RE_FIRST_COMPONENT.match('foo').group(0) == 'foo' | 2252 # _RE_FIRST_COMPONENT.match('foo').group(0) == 'foo' |
2154 # _RE_FIRST_COMPONENT.match('foo.cc').group(0) == 'foo' | 2253 # _RE_FIRST_COMPONENT.match('foo.cc').group(0) == 'foo' |
2155 # _RE_FIRST_COMPONENT.match('foo-bar_baz.cc').group(0) == 'foo' | 2254 # _RE_FIRST_COMPONENT.match('foo-bar_baz.cc').group(0) == 'foo' |
2156 # _RE_FIRST_COMPONENT.match('foo_bar-baz.cc').group(0) == 'foo' | 2255 # _RE_FIRST_COMPONENT.match('foo_bar-baz.cc').group(0) == 'foo' |
2157 _RE_FIRST_COMPONENT = re.compile(r'^[^-_.]+') | 2256 _RE_FIRST_COMPONENT = re.compile(r'^[^-_.]+') |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2323 # Look for any of the stream classes that are part of standard C++. | 2422 # Look for any of the stream classes that are part of standard C++. |
2324 match = _RE_PATTERN_INCLUDE.match(line) | 2423 match = _RE_PATTERN_INCLUDE.match(line) |
2325 if match: | 2424 if match: |
2326 include = match.group(2) | 2425 include = match.group(2) |
2327 if Match(r'(f|ind|io|i|o|parse|pf|stdio|str|)?stream$', include): | 2426 if Match(r'(f|ind|io|i|o|parse|pf|stdio|str|)?stream$', include): |
2328 # Many unit tests use cout, so we exempt them. | 2427 # Many unit tests use cout, so we exempt them. |
2329 if not _IsTestFilename(filename): | 2428 if not _IsTestFilename(filename): |
2330 error(filename, linenum, 'readability/streams', 3, | 2429 error(filename, linenum, 'readability/streams', 3, |
2331 'Streams are highly discouraged.') | 2430 'Streams are highly discouraged.') |
2332 | 2431 |
| 2432 |
| 2433 def _GetTextInside(text, start_pattern): |
| 2434 """Retrieves all the text between matching open and close parentheses. |
| 2435 |
| 2436 Given a string of lines and a regular expression string, retrieve all the text |
| 2437 following the expression and between opening punctuation symbols like |
| 2438 (, [, or {, and the matching close-punctuation symbol. This properly nested |
| 2439 occurrences of the punctuations, so for the text like |
| 2440 printf(a(), b(c())); |
| 2441 a call to _GetTextInside(text, r'printf\(') will return 'a(), b(c())'. |
| 2442 start_pattern must match string having an open punctuation symbol at the end. |
| 2443 |
| 2444 Args: |
| 2445 text: The lines to extract text. Its comments and strings must be elided. |
| 2446 It can be single line and can span multiple lines. |
| 2447 start_pattern: The regexp string indicating where to start extracting |
| 2448 the text. |
| 2449 Returns: |
| 2450 The extracted text. |
| 2451 None if either the opening string or ending punctuation could not be found. |
| 2452 """ |
| 2453 # TODO(sugawarayu): Audit cpplint.py to see what places could be profitably |
| 2454 # rewritten to use _GetTextInside (and use inferior regexp matching today). |
| 2455 |
| 2456 # Give opening punctuations to get the matching close-punctuations. |
| 2457 matching_punctuation = {'(': ')', '{': '}', '[': ']'} |
| 2458 closing_punctuation = set(matching_punctuation.itervalues()) |
| 2459 |
| 2460 # Find the position to start extracting text. |
| 2461 match = re.search(start_pattern, text, re.M) |
| 2462 if not match: # start_pattern not found in text. |
| 2463 return None |
| 2464 start_position = match.end(0) |
| 2465 |
| 2466 assert start_position > 0, ( |
| 2467 'start_pattern must ends with an opening punctuation.') |
| 2468 assert text[start_position - 1] in matching_punctuation, ( |
| 2469 'start_pattern must ends with an opening punctuation.') |
| 2470 # Stack of closing punctuations we expect to have in text after position. |
| 2471 punctuation_stack = [matching_punctuation[text[start_position - 1]]] |
| 2472 position = start_position |
| 2473 while punctuation_stack and position < len(text): |
| 2474 if text[position] == punctuation_stack[-1]: |
| 2475 punctuation_stack.pop() |
| 2476 elif text[position] in closing_punctuation: |
| 2477 # A closing punctuation without matching opening punctuations. |
| 2478 return None |
| 2479 elif text[position] in matching_punctuation: |
| 2480 punctuation_stack.append(matching_punctuation[text[position]]) |
| 2481 position += 1 |
| 2482 if punctuation_stack: |
| 2483 # Opening punctuations left without matching close-punctuations. |
| 2484 return None |
| 2485 # punctuations match. |
| 2486 return text[start_position:position - 1] |
| 2487 |
| 2488 |
2333 def CheckLanguage(filename, clean_lines, linenum, file_extension, include_state, | 2489 def CheckLanguage(filename, clean_lines, linenum, file_extension, include_state, |
2334 error): | 2490 error): |
2335 """Checks rules from the 'C++ language rules' section of cppguide.html. | 2491 """Checks rules from the 'C++ language rules' section of cppguide.html. |
2336 | 2492 |
2337 Some of these rules are hard to test (function overloading, using | 2493 Some of these rules are hard to test (function overloading, using |
2338 uint32 inappropriately), but we do the best we can. | 2494 uint32 inappropriately), but we do the best we can. |
2339 | 2495 |
2340 Args: | 2496 Args: |
2341 filename: The name of the current file. | 2497 filename: The name of the current file. |
2342 clean_lines: A CleansedLines instance containing the file. | 2498 clean_lines: A CleansedLines instance containing the file. |
(...skipping 25 matching lines...) Expand all Loading... |
2368 fullname = os.path.abspath(filename).replace('\\', '/') | 2524 fullname = os.path.abspath(filename).replace('\\', '/') |
2369 | 2525 |
2370 # TODO(unknown): figure out if they're using default arguments in fn proto. | 2526 # TODO(unknown): figure out if they're using default arguments in fn proto. |
2371 | 2527 |
2372 # Check for non-const references in functions. This is tricky because & | 2528 # Check for non-const references in functions. This is tricky because & |
2373 # is also used to take the address of something. We allow <> for templates, | 2529 # is also used to take the address of something. We allow <> for templates, |
2374 # (ignoring whatever is between the braces) and : for classes. | 2530 # (ignoring whatever is between the braces) and : for classes. |
2375 # These are complicated re's. They try to capture the following: | 2531 # These are complicated re's. They try to capture the following: |
2376 # paren (for fn-prototype start), typename, &, varname. For the const | 2532 # paren (for fn-prototype start), typename, &, varname. For the const |
2377 # version, we're willing for const to be before typename or after | 2533 # version, we're willing for const to be before typename or after |
2378 # Don't check the implemention on same line. | 2534 # Don't check the implementation on same line. |
2379 fnline = line.split('{', 1)[0] | 2535 fnline = line.split('{', 1)[0] |
2380 if (len(re.findall(r'\([^()]*\b(?:[\w:]|<[^()]*>)+(\s?&|&\s?)\w+', fnline)) > | 2536 if (len(re.findall(r'\([^()]*\b(?:[\w:]|<[^()]*>)+(\s?&|&\s?)\w+', fnline)) > |
2381 len(re.findall(r'\([^()]*\bconst\s+(?:typename\s+)?(?:struct\s+)?' | 2537 len(re.findall(r'\([^()]*\bconst\s+(?:typename\s+)?(?:struct\s+)?' |
2382 r'(?:[\w:]|<[^()]*>)+(\s?&|&\s?)\w+', fnline)) + | 2538 r'(?:[\w:]|<[^()]*>)+(\s?&|&\s?)\w+', fnline)) + |
2383 len(re.findall(r'\([^()]*\b(?:[\w:]|<[^()]*>)+\s+const(\s?&|&\s?)[\w]+', | 2539 len(re.findall(r'\([^()]*\b(?:[\w:]|<[^()]*>)+\s+const(\s?&|&\s?)[\w]+', |
2384 fnline))): | 2540 fnline))): |
2385 | 2541 |
2386 # We allow non-const references in a few standard places, like functions | 2542 # We allow non-const references in a few standard places, like functions |
2387 # called "swap()" or iostream operators like "<<" or ">>". | 2543 # called "swap()" or iostream operators like "<<" or ">>". |
2388 if not Search( | 2544 if not Search( |
2389 r'(swap|Swap|operator[<>][<>])\s*\(\s*(?:[\w:]|<.*>)+\s*&', | 2545 r'(swap|Swap|operator[<>][<>])\s*\(\s*(?:[\w:]|<.*>)+\s*&', |
2390 fnline): | 2546 fnline): |
2391 error(filename, linenum, 'runtime/references', 2, | 2547 error(filename, linenum, 'runtime/references', 2, |
2392 'Is this a non-const reference? ' | 2548 'Is this a non-const reference? ' |
2393 'If so, make const or use a pointer.') | 2549 'If so, make const or use a pointer.') |
2394 | 2550 |
2395 # Check to see if they're using an conversion function cast. | 2551 # Check to see if they're using an conversion function cast. |
2396 # I just try to capture the most common basic types, though there are more. | 2552 # I just try to capture the most common basic types, though there are more. |
2397 # Parameterless conversion functions, such as bool(), are allowed as they are | 2553 # Parameterless conversion functions, such as bool(), are allowed as they are |
2398 # probably a member operator declaration or default constructor. | 2554 # probably a member operator declaration or default constructor. |
2399 match = Search( | 2555 match = Search( |
2400 r'(\bnew\s+)?\b' # Grab 'new' operator, if it's there | 2556 r'(\bnew\s+)?\b' # Grab 'new' operator, if it's there |
2401 r'(int|float|double|bool|char|int32|uint32|int64|uint64)\([^)]', line) | 2557 r'(int|float|double|bool|char|int32|uint32|int64|uint64)\([^)]', line) |
2402 if match: | 2558 if match: |
2403 # gMock methods are defined using some variant of MOCK_METHODx(name, type) | 2559 # gMock methods are defined using some variant of MOCK_METHODx(name, type) |
2404 # where type may be float(), int(string), etc. Without context they are | 2560 # where type may be float(), int(string), etc. Without context they are |
2405 # virtually indistinguishable from int(x) casts. | 2561 # virtually indistinguishable from int(x) casts. Likewise, gMock's |
| 2562 # MockCallback takes a template parameter of the form return_type(arg_type), |
| 2563 # which looks much like the cast we're trying to detect. |
2406 if (match.group(1) is None and # If new operator, then this isn't a cast | 2564 if (match.group(1) is None and # If new operator, then this isn't a cast |
2407 not Match(r'^\s*MOCK_(CONST_)?METHOD\d+(_T)?\(', line)): | 2565 not (Match(r'^\s*MOCK_(CONST_)?METHOD\d+(_T)?\(', line) or |
| 2566 Match(r'^\s*MockCallback<.*>', line))): |
2408 error(filename, linenum, 'readability/casting', 4, | 2567 error(filename, linenum, 'readability/casting', 4, |
2409 'Using deprecated casting style. ' | 2568 'Using deprecated casting style. ' |
2410 'Use static_cast<%s>(...) instead' % | 2569 'Use static_cast<%s>(...) instead' % |
2411 match.group(2)) | 2570 match.group(2)) |
2412 | 2571 |
2413 CheckCStyleCast(filename, linenum, line, clean_lines.raw_lines[linenum], | 2572 CheckCStyleCast(filename, linenum, line, clean_lines.raw_lines[linenum], |
2414 'static_cast', | 2573 'static_cast', |
2415 r'\((int|float|double|bool|char|u?int(16|32|64))\)', | 2574 r'\((int|float|double|bool|char|u?int(16|32|64))\)', error) |
2416 error) | 2575 |
2417 # This doesn't catch all cases. Consider (const char * const)"hello". | 2576 # This doesn't catch all cases. Consider (const char * const)"hello". |
2418 CheckCStyleCast(filename, linenum, line, clean_lines.raw_lines[linenum], | 2577 # |
2419 'reinterpret_cast', r'\((\w+\s?\*+\s?)\)', error) | 2578 # (char *) "foo" should always be a const_cast (reinterpret_cast won't |
| 2579 # compile). |
| 2580 if CheckCStyleCast(filename, linenum, line, clean_lines.raw_lines[linenum], |
| 2581 'const_cast', r'\((char\s?\*+\s?)\)\s*"', error): |
| 2582 pass |
| 2583 else: |
| 2584 # Check pointer casts for other than string constants |
| 2585 CheckCStyleCast(filename, linenum, line, clean_lines.raw_lines[linenum], |
| 2586 'reinterpret_cast', r'\((\w+\s?\*+\s?)\)', error) |
2420 | 2587 |
2421 # In addition, we look for people taking the address of a cast. This | 2588 # In addition, we look for people taking the address of a cast. This |
2422 # is dangerous -- casts can assign to temporaries, so the pointer doesn't | 2589 # is dangerous -- casts can assign to temporaries, so the pointer doesn't |
2423 # point where you think. | 2590 # point where you think. |
2424 if Search( | 2591 if Search( |
2425 r'(&\([^)]+\)[\w(])|(&(static|dynamic|reinterpret)_cast\b)', line): | 2592 r'(&\([^)]+\)[\w(])|(&(static|dynamic|reinterpret)_cast\b)', line): |
2426 error(filename, linenum, 'runtime/casting', 4, | 2593 error(filename, linenum, 'runtime/casting', 4, |
2427 ('Are you taking an address of a cast? ' | 2594 ('Are you taking an address of a cast? ' |
2428 'This is dangerous: could be a temp var. ' | 2595 'This is dangerous: could be a temp var. ' |
2429 'Take the address before doing the cast, rather than after')) | 2596 'Take the address before doing the cast, rather than after')) |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2508 | 2675 |
2509 # Check for suspicious usage of "if" like | 2676 # Check for suspicious usage of "if" like |
2510 # } if (a == b) { | 2677 # } if (a == b) { |
2511 if Search(r'\}\s*if\s*\(', line): | 2678 if Search(r'\}\s*if\s*\(', line): |
2512 error(filename, linenum, 'readability/braces', 4, | 2679 error(filename, linenum, 'readability/braces', 4, |
2513 'Did you mean "else if"? If not, start a new line for "if".') | 2680 'Did you mean "else if"? If not, start a new line for "if".') |
2514 | 2681 |
2515 # Check for potential format string bugs like printf(foo). | 2682 # Check for potential format string bugs like printf(foo). |
2516 # We constrain the pattern not to pick things like DocidForPrintf(foo). | 2683 # We constrain the pattern not to pick things like DocidForPrintf(foo). |
2517 # Not perfect but it can catch printf(foo.c_str()) and printf(foo->c_str()) | 2684 # Not perfect but it can catch printf(foo.c_str()) and printf(foo->c_str()) |
2518 match = re.search(r'\b((?:string)?printf)\s*\(([\w.\->()]+)\)', line, re.I) | 2685 # TODO(sugawarayu): Catch the following case. Need to change the calling |
2519 if match: | 2686 # convention of the whole function to process multiple line to handle it. |
2520 error(filename, linenum, 'runtime/printf', 4, | 2687 # printf( |
2521 'Potential format string bug. Do %s("%%s", %s) instead.' | 2688 # boy_this_is_a_really_long_variable_that_cannot_fit_on_the_prev_line); |
2522 % (match.group(1), match.group(2))) | 2689 printf_args = _GetTextInside(line, r'(?i)\b(string)?printf\s*\(') |
| 2690 if printf_args: |
| 2691 match = Match(r'([\w.\->()]+)$', printf_args) |
| 2692 if match: |
| 2693 function_name = re.search(r'\b((?:string)?printf)\s*\(', |
| 2694 line, re.I).group(1) |
| 2695 error(filename, linenum, 'runtime/printf', 4, |
| 2696 'Potential format string bug. Do %s("%%s", %s) instead.' |
| 2697 % (function_name, match.group(1))) |
2523 | 2698 |
2524 # Check for potential memset bugs like memset(buf, sizeof(buf), 0). | 2699 # Check for potential memset bugs like memset(buf, sizeof(buf), 0). |
2525 match = Search(r'memset\s*\(([^,]*),\s*([^,]*),\s*0\s*\)', line) | 2700 match = Search(r'memset\s*\(([^,]*),\s*([^,]*),\s*0\s*\)', line) |
2526 if match and not Match(r"^''|-?[0-9]+|0x[0-9A-Fa-f]$", match.group(2)): | 2701 if match and not Match(r"^''|-?[0-9]+|0x[0-9A-Fa-f]$", match.group(2)): |
2527 error(filename, linenum, 'runtime/memset', 4, | 2702 error(filename, linenum, 'runtime/memset', 4, |
2528 'Did you mean "memset(%s, 0, %s)"?' | 2703 'Did you mean "memset(%s, 0, %s)"?' |
2529 % (match.group(1), match.group(2))) | 2704 % (match.group(1), match.group(2))) |
2530 | 2705 |
2531 if Search(r'\busing namespace\b', line): | 2706 if Search(r'\busing namespace\b', line): |
2532 error(filename, linenum, 'build/namespaces', 5, | 2707 error(filename, linenum, 'build/namespaces', 5, |
(...skipping 21 matching lines...) Expand all Loading... |
2554 tok = tok.lstrip('(') | 2729 tok = tok.lstrip('(') |
2555 tok = tok.rstrip(')') | 2730 tok = tok.rstrip(')') |
2556 if not tok: continue | 2731 if not tok: continue |
2557 if Match(r'\d+', tok): continue | 2732 if Match(r'\d+', tok): continue |
2558 if Match(r'0[xX][0-9a-fA-F]+', tok): continue | 2733 if Match(r'0[xX][0-9a-fA-F]+', tok): continue |
2559 if Match(r'k[A-Z0-9]\w*', tok): continue | 2734 if Match(r'k[A-Z0-9]\w*', tok): continue |
2560 if Match(r'(.+::)?k[A-Z0-9]\w*', tok): continue | 2735 if Match(r'(.+::)?k[A-Z0-9]\w*', tok): continue |
2561 if Match(r'(.+::)?[A-Z][A-Z0-9_]*', tok): continue | 2736 if Match(r'(.+::)?[A-Z][A-Z0-9_]*', tok): continue |
2562 # A catch all for tricky sizeof cases, including 'sizeof expression', | 2737 # A catch all for tricky sizeof cases, including 'sizeof expression', |
2563 # 'sizeof(*type)', 'sizeof(const type)', 'sizeof(struct StructName)' | 2738 # 'sizeof(*type)', 'sizeof(const type)', 'sizeof(struct StructName)' |
2564 # requires skipping the next token becasue we split on ' ' and '*'. | 2739 # requires skipping the next token because we split on ' ' and '*'. |
2565 if tok.startswith('sizeof'): | 2740 if tok.startswith('sizeof'): |
2566 skip_next = True | 2741 skip_next = True |
2567 continue | 2742 continue |
2568 is_const = False | 2743 is_const = False |
2569 break | 2744 break |
2570 if not is_const: | 2745 if not is_const: |
2571 error(filename, linenum, 'runtime/arrays', 1, | 2746 error(filename, linenum, 'runtime/arrays', 1, |
2572 'Do not use variable-length arrays. Use an appropriately named ' | 2747 'Do not use variable-length arrays. Use an appropriately named ' |
2573 "('k' followed by CamelCase) compile-time constant for the size.") | 2748 "('k' followed by CamelCase) compile-time constant for the size.") |
2574 | 2749 |
2575 # If DISALLOW_EVIL_CONSTRUCTORS, DISALLOW_COPY_AND_ASSIGN, or | 2750 # If DISALLOW_EVIL_CONSTRUCTORS, DISALLOW_COPY_AND_ASSIGN, or |
2576 # DISALLOW_IMPLICIT_CONSTRUCTORS is present, then it should be the last thing | 2751 # DISALLOW_IMPLICIT_CONSTRUCTORS is present, then it should be the last thing |
2577 # in the class declaration. | 2752 # in the class declaration. |
2578 match = Match( | 2753 match = Match( |
2579 (r'\s*' | 2754 (r'\s*' |
2580 r'(DISALLOW_(EVIL_CONSTRUCTORS|COPY_AND_ASSIGN|IMPLICIT_CONSTRUCTORS))' | 2755 r'(DISALLOW_(EVIL_CONSTRUCTORS|COPY_AND_ASSIGN|IMPLICIT_CONSTRUCTORS))' |
2581 r'\(.*\);$'), | 2756 r'\(.*\);$'), |
2582 line) | 2757 line) |
2583 if match and linenum + 1 < clean_lines.NumLines(): | 2758 if match and linenum + 1 < clean_lines.NumLines(): |
2584 next_line = clean_lines.elided[linenum + 1] | 2759 next_line = clean_lines.elided[linenum + 1] |
2585 if not Search(r'^\s*};', next_line): | 2760 # We allow some, but not all, declarations of variables to be present |
| 2761 # in the statement that defines the class. The [\w\*,\s]* fragment of |
| 2762 # the regular expression below allows users to declare instances of |
| 2763 # the class or pointers to instances, but not less common types such |
| 2764 # as function pointers or arrays. It's a tradeoff between allowing |
| 2765 # reasonable code and avoiding trying to parse more C++ using regexps. |
| 2766 if not Search(r'^\s*}[\w\*,\s]*;', next_line): |
2586 error(filename, linenum, 'readability/constructors', 3, | 2767 error(filename, linenum, 'readability/constructors', 3, |
2587 match.group(1) + ' should be the last thing in the class') | 2768 match.group(1) + ' should be the last thing in the class') |
2588 | 2769 |
2589 # Check for use of unnamed namespaces in header files. Registration | 2770 # Check for use of unnamed namespaces in header files. Registration |
2590 # macros are typically OK, so we allow use of "namespace {" on lines | 2771 # macros are typically OK, so we allow use of "namespace {" on lines |
2591 # that end with backslashes. | 2772 # that end with backslashes. |
2592 if (file_extension == 'h' | 2773 if (file_extension == 'h' |
2593 and Search(r'\bnamespace\s*{', line) | 2774 and Search(r'\bnamespace\s*{', line) |
2594 and line[-1] != '\\'): | 2775 and line[-1] != '\\'): |
2595 error(filename, linenum, 'build/namespaces', 4, | 2776 error(filename, linenum, 'build/namespaces', 4, |
2596 'Do not use unnamed namespaces in header files. See ' | 2777 'Do not use unnamed namespaces in header files. See ' |
2597 'http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Namesp
aces' | 2778 'http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Namesp
aces' |
2598 ' for more information.') | 2779 ' for more information.') |
2599 | 2780 |
2600 | 2781 |
2601 def CheckCStyleCast(filename, linenum, line, raw_line, cast_type, pattern, | 2782 def CheckCStyleCast(filename, linenum, line, raw_line, cast_type, pattern, |
2602 error): | 2783 error): |
2603 """Checks for a C-style cast by looking for the pattern. | 2784 """Checks for a C-style cast by looking for the pattern. |
2604 | 2785 |
2605 This also handles sizeof(type) warnings, due to similarity of content. | 2786 This also handles sizeof(type) warnings, due to similarity of content. |
2606 | 2787 |
2607 Args: | 2788 Args: |
2608 filename: The name of the current file. | 2789 filename: The name of the current file. |
2609 linenum: The number of the line to check. | 2790 linenum: The number of the line to check. |
2610 line: The line of code to check. | 2791 line: The line of code to check. |
2611 raw_line: The raw line of code to check, with comments. | 2792 raw_line: The raw line of code to check, with comments. |
2612 cast_type: The string for the C++ cast to recommend. This is either | 2793 cast_type: The string for the C++ cast to recommend. This is either |
2613 reinterpret_cast or static_cast, depending. | 2794 reinterpret_cast, static_cast, or const_cast, depending. |
2614 pattern: The regular expression used to find C-style casts. | 2795 pattern: The regular expression used to find C-style casts. |
2615 error: The function to call with any errors found. | 2796 error: The function to call with any errors found. |
| 2797 |
| 2798 Returns: |
| 2799 True if an error was emitted. |
| 2800 False otherwise. |
2616 """ | 2801 """ |
2617 match = Search(pattern, line) | 2802 match = Search(pattern, line) |
2618 if not match: | 2803 if not match: |
2619 return | 2804 return False |
2620 | 2805 |
2621 # e.g., sizeof(int) | 2806 # e.g., sizeof(int) |
2622 sizeof_match = Match(r'.*sizeof\s*$', line[0:match.start(1) - 1]) | 2807 sizeof_match = Match(r'.*sizeof\s*$', line[0:match.start(1) - 1]) |
2623 if sizeof_match: | 2808 if sizeof_match: |
2624 error(filename, linenum, 'runtime/sizeof', 1, | 2809 error(filename, linenum, 'runtime/sizeof', 1, |
2625 'Using sizeof(type). Use sizeof(varname) instead if possible') | 2810 'Using sizeof(type). Use sizeof(varname) instead if possible') |
2626 return | 2811 return True |
2627 | 2812 |
2628 remainder = line[match.end(0):] | 2813 remainder = line[match.end(0):] |
2629 | 2814 |
2630 # The close paren is for function pointers as arguments to a function. | 2815 # The close paren is for function pointers as arguments to a function. |
2631 # eg, void foo(void (*bar)(int)); | 2816 # eg, void foo(void (*bar)(int)); |
2632 # The semicolon check is a more basic function check; also possibly a | 2817 # The semicolon check is a more basic function check; also possibly a |
2633 # function pointer typedef. | 2818 # function pointer typedef. |
2634 # eg, void foo(int); or void foo(int) const; | 2819 # eg, void foo(int); or void foo(int) const; |
2635 # The equals check is for function pointer assignment. | 2820 # The equals check is for function pointer assignment. |
2636 # eg, void *(*foo)(int) = ... | 2821 # eg, void *(*foo)(int) = ... |
| 2822 # The > is for MockCallback<...> ... |
2637 # | 2823 # |
2638 # Right now, this will only catch cases where there's a single argument, and | 2824 # Right now, this will only catch cases where there's a single argument, and |
2639 # it's unnamed. It should probably be expanded to check for multiple | 2825 # it's unnamed. It should probably be expanded to check for multiple |
2640 # arguments with some unnamed. | 2826 # arguments with some unnamed. |
2641 function_match = Match(r'\s*(\)|=|(const)?\s*(;|\{|throw\(\)))', remainder) | 2827 function_match = Match(r'\s*(\)|=|(const)?\s*(;|\{|throw\(\)|>))', remainder) |
2642 if function_match: | 2828 if function_match: |
2643 if (not function_match.group(3) or | 2829 if (not function_match.group(3) or |
2644 function_match.group(3) == ';' or | 2830 function_match.group(3) == ';' or |
2645 raw_line.find('/*') < 0): | 2831 ('MockCallback<' not in raw_line and |
| 2832 '/*' not in raw_line)): |
2646 error(filename, linenum, 'readability/function', 3, | 2833 error(filename, linenum, 'readability/function', 3, |
2647 'All parameters should be named in a function') | 2834 'All parameters should be named in a function') |
2648 return | 2835 return True |
2649 | 2836 |
2650 # At this point, all that should be left is actual casts. | 2837 # At this point, all that should be left is actual casts. |
2651 error(filename, linenum, 'readability/casting', 4, | 2838 error(filename, linenum, 'readability/casting', 4, |
2652 'Using C-style cast. Use %s<%s>(...) instead' % | 2839 'Using C-style cast. Use %s<%s>(...) instead' % |
2653 (cast_type, match.group(1))) | 2840 (cast_type, match.group(1))) |
2654 | 2841 |
| 2842 return True |
| 2843 |
2655 | 2844 |
2656 _HEADERS_CONTAINING_TEMPLATES = ( | 2845 _HEADERS_CONTAINING_TEMPLATES = ( |
2657 ('<deque>', ('deque',)), | 2846 ('<deque>', ('deque',)), |
2658 ('<functional>', ('unary_function', 'binary_function', | 2847 ('<functional>', ('unary_function', 'binary_function', |
2659 'plus', 'minus', 'multiplies', 'divides', 'modulus', | 2848 'plus', 'minus', 'multiplies', 'divides', 'modulus', |
2660 'negate', | 2849 'negate', |
2661 'equal_to', 'not_equal_to', 'greater', 'less', | 2850 'equal_to', 'not_equal_to', 'greater', 'less', |
2662 'greater_equal', 'less_equal', | 2851 'greater_equal', 'less_equal', |
2663 'logical_and', 'logical_or', 'logical_not', | 2852 'logical_and', 'logical_or', 'logical_not', |
2664 'unary_negate', 'not1', 'binary_negate', 'not2', | 2853 'unary_negate', 'not1', 'binary_negate', 'not2', |
(...skipping 18 matching lines...) Expand all Loading... |
2683 ('<utility>', ('pair',)), | 2872 ('<utility>', ('pair',)), |
2684 ('<vector>', ('vector',)), | 2873 ('<vector>', ('vector',)), |
2685 | 2874 |
2686 # gcc extensions. | 2875 # gcc extensions. |
2687 # Note: std::hash is their hash, ::hash is our hash | 2876 # Note: std::hash is their hash, ::hash is our hash |
2688 ('<hash_map>', ('hash_map', 'hash_multimap',)), | 2877 ('<hash_map>', ('hash_map', 'hash_multimap',)), |
2689 ('<hash_set>', ('hash_set', 'hash_multiset',)), | 2878 ('<hash_set>', ('hash_set', 'hash_multiset',)), |
2690 ('<slist>', ('slist',)), | 2879 ('<slist>', ('slist',)), |
2691 ) | 2880 ) |
2692 | 2881 |
2693 _HEADERS_ACCEPTED_BUT_NOT_PROMOTED = { | |
2694 # We can trust with reasonable confidence that map gives us pair<>, too. | |
2695 'pair<>': ('map', 'multimap', 'hash_map', 'hash_multimap') | |
2696 } | |
2697 | |
2698 _RE_PATTERN_STRING = re.compile(r'\bstring\b') | 2882 _RE_PATTERN_STRING = re.compile(r'\bstring\b') |
2699 | 2883 |
2700 _re_pattern_algorithm_header = [] | 2884 _re_pattern_algorithm_header = [] |
2701 for _template in ('copy', 'max', 'min', 'min_element', 'sort', 'swap', | 2885 for _template in ('copy', 'max', 'min', 'min_element', 'sort', 'swap', |
2702 'transform'): | 2886 'transform'): |
2703 # Match max<type>(..., ...), max(..., ...), but not foo->max, foo.max or | 2887 # Match max<type>(..., ...), max(..., ...), but not foo->max, foo.max or |
2704 # type::max(). | 2888 # type::max(). |
2705 _re_pattern_algorithm_header.append( | 2889 _re_pattern_algorithm_header.append( |
2706 (re.compile(r'[^>.]\b' + _template + r'(<.*?>)?\([^\)]'), | 2890 (re.compile(r'[^>.]\b' + _template + r'(<.*?>)?\([^\)]'), |
2707 _template, | 2891 _template, |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2820 """ | 3004 """ |
2821 required = {} # A map of header name to linenumber and the template entity. | 3005 required = {} # A map of header name to linenumber and the template entity. |
2822 # Example of required: { '<functional>': (1219, 'less<>') } | 3006 # Example of required: { '<functional>': (1219, 'less<>') } |
2823 | 3007 |
2824 for linenum in xrange(clean_lines.NumLines()): | 3008 for linenum in xrange(clean_lines.NumLines()): |
2825 line = clean_lines.elided[linenum] | 3009 line = clean_lines.elided[linenum] |
2826 if not line or line[0] == '#': | 3010 if not line or line[0] == '#': |
2827 continue | 3011 continue |
2828 | 3012 |
2829 # String is special -- it is a non-templatized type in STL. | 3013 # String is special -- it is a non-templatized type in STL. |
2830 m = _RE_PATTERN_STRING.search(line) | 3014 matched = _RE_PATTERN_STRING.search(line) |
2831 if m: | 3015 if matched: |
2832 # Don't warn about strings in non-STL namespaces: | 3016 # Don't warn about strings in non-STL namespaces: |
2833 # (We check only the first match per line; good enough.) | 3017 # (We check only the first match per line; good enough.) |
2834 prefix = line[:m.start()] | 3018 prefix = line[:matched.start()] |
2835 if prefix.endswith('std::') or not prefix.endswith('::'): | 3019 if prefix.endswith('std::') or not prefix.endswith('::'): |
2836 required['<string>'] = (linenum, 'string') | 3020 required['<string>'] = (linenum, 'string') |
2837 | 3021 |
2838 for pattern, template, header in _re_pattern_algorithm_header: | 3022 for pattern, template, header in _re_pattern_algorithm_header: |
2839 if pattern.search(line): | 3023 if pattern.search(line): |
2840 required[header] = (linenum, template) | 3024 required[header] = (linenum, template) |
2841 | 3025 |
2842 # The following function is just a speed up, no semantics are changed. | 3026 # The following function is just a speed up, no semantics are changed. |
2843 if not '<' in line: # Reduces the cpu time usage by skipping lines. | 3027 if not '<' in line: # Reduces the cpu time usage by skipping lines. |
2844 continue | 3028 continue |
(...skipping 17 matching lines...) Expand all Loading... |
2862 # If cpplint is invoked from Emacs's flymake, a temporary file is generated | 3046 # If cpplint is invoked from Emacs's flymake, a temporary file is generated |
2863 # by flymake and that file name might end with '_flymake.cc'. In that case, | 3047 # by flymake and that file name might end with '_flymake.cc'. In that case, |
2864 # restore original file name here so that the corresponding header file can be | 3048 # restore original file name here so that the corresponding header file can be |
2865 # found. | 3049 # found. |
2866 # e.g. If the file name is 'foo_flymake.cc', we should search for 'foo.h' | 3050 # e.g. If the file name is 'foo_flymake.cc', we should search for 'foo.h' |
2867 # instead of 'foo_flymake.h' | 3051 # instead of 'foo_flymake.h' |
2868 abs_filename = re.sub(r'_flymake\.cc$', '.cc', abs_filename) | 3052 abs_filename = re.sub(r'_flymake\.cc$', '.cc', abs_filename) |
2869 | 3053 |
2870 # include_state is modified during iteration, so we iterate over a copy of | 3054 # include_state is modified during iteration, so we iterate over a copy of |
2871 # the keys. | 3055 # the keys. |
2872 for header in include_state.keys(): #NOLINT | 3056 header_keys = include_state.keys() |
| 3057 for header in header_keys: |
2873 (same_module, common_path) = FilesBelongToSameModule(abs_filename, header) | 3058 (same_module, common_path) = FilesBelongToSameModule(abs_filename, header) |
2874 fullpath = common_path + header | 3059 fullpath = common_path + header |
2875 if same_module and UpdateIncludeState(fullpath, include_state, io): | 3060 if same_module and UpdateIncludeState(fullpath, include_state, io): |
2876 header_found = True | 3061 header_found = True |
2877 | 3062 |
2878 # If we can't find the header file for a .cc, assume it's because we don't | 3063 # If we can't find the header file for a .cc, assume it's because we don't |
2879 # know where to look. In that case we'll give up as we're not sure they | 3064 # know where to look. In that case we'll give up as we're not sure they |
2880 # didn't include it in the .h file. | 3065 # didn't include it in the .h file. |
2881 # TODO(unknown): Do a better job of finding .h files so we are confident that | 3066 # TODO(unknown): Do a better job of finding .h files so we are confident that |
2882 # not having the .h file means there isn't one. | 3067 # not having the .h file means there isn't one. |
2883 if filename.endswith('.cc') and not header_found: | 3068 if filename.endswith('.cc') and not header_found: |
2884 return | 3069 return |
2885 | 3070 |
2886 # All the lines have been processed, report the errors found. | 3071 # All the lines have been processed, report the errors found. |
2887 for required_header_unstripped in required: | 3072 for required_header_unstripped in required: |
2888 template = required[required_header_unstripped][1] | 3073 template = required[required_header_unstripped][1] |
2889 if template in _HEADERS_ACCEPTED_BUT_NOT_PROMOTED: | |
2890 headers = _HEADERS_ACCEPTED_BUT_NOT_PROMOTED[template] | |
2891 if [True for header in headers if header in include_state]: | |
2892 continue | |
2893 if required_header_unstripped.strip('<>"') not in include_state: | 3074 if required_header_unstripped.strip('<>"') not in include_state: |
2894 error(filename, required[required_header_unstripped][0], | 3075 error(filename, required[required_header_unstripped][0], |
2895 'build/include_what_you_use', 4, | 3076 'build/include_what_you_use', 4, |
2896 'Add #include ' + required_header_unstripped + ' for ' + template) | 3077 'Add #include ' + required_header_unstripped + ' for ' + template) |
2897 | 3078 |
2898 | 3079 |
| 3080 _RE_PATTERN_EXPLICIT_MAKEPAIR = re.compile(r'\bmake_pair\s*<') |
| 3081 |
| 3082 |
| 3083 def CheckMakePairUsesDeduction(filename, clean_lines, linenum, error): |
| 3084 """Check that make_pair's template arguments are deduced. |
| 3085 |
| 3086 G++ 4.6 in C++0x mode fails badly if make_pair's template arguments are |
| 3087 specified explicitly, and such use isn't intended in any case. |
| 3088 |
| 3089 Args: |
| 3090 filename: The name of the current file. |
| 3091 clean_lines: A CleansedLines instance containing the file. |
| 3092 linenum: The number of the line to check. |
| 3093 error: The function to call with any errors found. |
| 3094 """ |
| 3095 raw = clean_lines.raw_lines |
| 3096 line = raw[linenum] |
| 3097 match = _RE_PATTERN_EXPLICIT_MAKEPAIR.search(line) |
| 3098 if match: |
| 3099 error(filename, linenum, 'build/explicit_make_pair', |
| 3100 4, # 4 = high confidence |
| 3101 'Omit template arguments from make_pair OR use pair directly OR' |
| 3102 ' if appropriate, construct a pair directly') |
| 3103 |
| 3104 |
2899 def ProcessLine(filename, file_extension, | 3105 def ProcessLine(filename, file_extension, |
2900 clean_lines, line, include_state, function_state, | 3106 clean_lines, line, include_state, function_state, |
2901 class_state, error): | 3107 class_state, error, extra_check_functions=[]): |
2902 """Processes a single line in the file. | 3108 """Processes a single line in the file. |
2903 | 3109 |
2904 Args: | 3110 Args: |
2905 filename: Filename of the file that is being processed. | 3111 filename: Filename of the file that is being processed. |
2906 file_extension: The extension (dot not included) of the file. | 3112 file_extension: The extension (dot not included) of the file. |
2907 clean_lines: An array of strings, each representing a line of the file, | 3113 clean_lines: An array of strings, each representing a line of the file, |
2908 with comments stripped. | 3114 with comments stripped. |
2909 line: Number of line being processed. | 3115 line: Number of line being processed. |
2910 include_state: An _IncludeState instance in which the headers are inserted. | 3116 include_state: An _IncludeState instance in which the headers are inserted. |
2911 function_state: A _FunctionState instance which counts function lines, etc. | 3117 function_state: A _FunctionState instance which counts function lines, etc. |
2912 class_state: A _ClassState instance which maintains information about | 3118 class_state: A _ClassState instance which maintains information about |
2913 the current stack of nested class declarations being parsed. | 3119 the current stack of nested class declarations being parsed. |
2914 error: A callable to which errors are reported, which takes 4 arguments: | 3120 error: A callable to which errors are reported, which takes 4 arguments: |
2915 filename, line number, error level, and message | 3121 filename, line number, error level, and message |
2916 | 3122 extra_check_functions: An array of additional check functions that will be |
| 3123 run on each source line. Each function takes 4 |
| 3124 arguments: filename, clean_lines, line, error |
2917 """ | 3125 """ |
2918 raw_lines = clean_lines.raw_lines | 3126 raw_lines = clean_lines.raw_lines |
2919 ParseNolintSuppressions(filename, raw_lines[line], line, error) | 3127 ParseNolintSuppressions(filename, raw_lines[line], line, error) |
2920 CheckForFunctionLengths(filename, clean_lines, line, function_state, error) | 3128 CheckForFunctionLengths(filename, clean_lines, line, function_state, error) |
2921 CheckForMultilineCommentsAndStrings(filename, clean_lines, line, error) | 3129 CheckForMultilineCommentsAndStrings(filename, clean_lines, line, error) |
2922 CheckStyle(filename, clean_lines, line, file_extension, error) | 3130 CheckStyle(filename, clean_lines, line, file_extension, class_state, error) |
2923 CheckLanguage(filename, clean_lines, line, file_extension, include_state, | 3131 CheckLanguage(filename, clean_lines, line, file_extension, include_state, |
2924 error) | 3132 error) |
2925 CheckForNonStandardConstructs(filename, clean_lines, line, | 3133 CheckForNonStandardConstructs(filename, clean_lines, line, |
2926 class_state, error) | 3134 class_state, error) |
2927 CheckPosixThreading(filename, clean_lines, line, error) | 3135 CheckPosixThreading(filename, clean_lines, line, error) |
2928 CheckInvalidIncrement(filename, clean_lines, line, error) | 3136 CheckInvalidIncrement(filename, clean_lines, line, error) |
| 3137 CheckMakePairUsesDeduction(filename, clean_lines, line, error) |
| 3138 for check_fn in extra_check_functions: |
| 3139 check_fn(filename, clean_lines, line, error) |
2929 | 3140 |
2930 | 3141 def ProcessFileData(filename, file_extension, lines, error, |
2931 def ProcessFileData(filename, file_extension, lines, error): | 3142 extra_check_functions=[]): |
2932 """Performs lint checks and reports any errors to the given error function. | 3143 """Performs lint checks and reports any errors to the given error function. |
2933 | 3144 |
2934 Args: | 3145 Args: |
2935 filename: Filename of the file that is being processed. | 3146 filename: Filename of the file that is being processed. |
2936 file_extension: The extension (dot not included) of the file. | 3147 file_extension: The extension (dot not included) of the file. |
2937 lines: An array of strings, each representing a line of the file, with the | 3148 lines: An array of strings, each representing a line of the file, with the |
2938 last element being empty if the file is termined with a newline. | 3149 last element being empty if the file is terminated with a newline. |
2939 error: A callable to which errors are reported, which takes 4 arguments: | 3150 error: A callable to which errors are reported, which takes 4 arguments: |
| 3151 filename, line number, error level, and message |
| 3152 extra_check_functions: An array of additional check functions that will be |
| 3153 run on each source line. Each function takes 4 |
| 3154 arguments: filename, clean_lines, line, error |
2940 """ | 3155 """ |
2941 lines = (['// marker so line numbers and indices both start at 1'] + lines + | 3156 lines = (['// marker so line numbers and indices both start at 1'] + lines + |
2942 ['// marker so line numbers end in a known way']) | 3157 ['// marker so line numbers end in a known way']) |
2943 | 3158 |
2944 include_state = _IncludeState() | 3159 include_state = _IncludeState() |
2945 function_state = _FunctionState() | 3160 function_state = _FunctionState() |
2946 class_state = _ClassState() | 3161 class_state = _ClassState() |
2947 | 3162 |
2948 ResetNolintSuppressions() | 3163 ResetNolintSuppressions() |
2949 | 3164 |
2950 CheckForCopyright(filename, lines, error) | 3165 CheckForCopyright(filename, lines, error) |
2951 | 3166 |
2952 if file_extension == 'h': | 3167 if file_extension == 'h': |
2953 CheckForHeaderGuard(filename, lines, error) | 3168 CheckForHeaderGuard(filename, lines, error) |
2954 | 3169 |
2955 RemoveMultiLineComments(filename, lines, error) | 3170 RemoveMultiLineComments(filename, lines, error) |
2956 clean_lines = CleansedLines(lines) | 3171 clean_lines = CleansedLines(lines) |
2957 for line in xrange(clean_lines.NumLines()): | 3172 for line in xrange(clean_lines.NumLines()): |
2958 ProcessLine(filename, file_extension, clean_lines, line, | 3173 ProcessLine(filename, file_extension, clean_lines, line, |
2959 include_state, function_state, class_state, error) | 3174 include_state, function_state, class_state, error, |
| 3175 extra_check_functions) |
2960 class_state.CheckFinished(filename, error) | 3176 class_state.CheckFinished(filename, error) |
2961 | 3177 |
2962 CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error) | 3178 CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error) |
2963 | 3179 |
2964 # We check here rather than inside ProcessLine so that we see raw | 3180 # We check here rather than inside ProcessLine so that we see raw |
2965 # lines rather than "cleaned" lines. | 3181 # lines rather than "cleaned" lines. |
2966 CheckForUnicodeReplacementCharacters(filename, lines, error) | 3182 CheckForUnicodeReplacementCharacters(filename, lines, error) |
2967 | 3183 |
2968 CheckForNewlineAtEOF(filename, lines, error) | 3184 CheckForNewlineAtEOF(filename, lines, error) |
2969 | 3185 |
2970 def ProcessFile(filename, vlevel): | 3186 def ProcessFile(filename, vlevel, extra_check_functions=[]): |
2971 """Does google-lint on a single file. | 3187 """Does google-lint on a single file. |
2972 | 3188 |
2973 Args: | 3189 Args: |
2974 filename: The name of the file to parse. | 3190 filename: The name of the file to parse. |
2975 | 3191 |
2976 vlevel: The level of errors to report. Every error of confidence | 3192 vlevel: The level of errors to report. Every error of confidence |
2977 >= verbose_level will be reported. 0 is a good default. | 3193 >= verbose_level will be reported. 0 is a good default. |
| 3194 |
| 3195 extra_check_functions: An array of additional check functions that will be |
| 3196 run on each source line. Each function takes 4 |
| 3197 arguments: filename, clean_lines, line, error |
2978 """ | 3198 """ |
2979 | 3199 |
2980 _SetVerboseLevel(vlevel) | 3200 _SetVerboseLevel(vlevel) |
2981 | 3201 |
2982 try: | 3202 try: |
2983 # Support the UNIX convention of using "-" for stdin. Note that | 3203 # Support the UNIX convention of using "-" for stdin. Note that |
2984 # we are not opening the file with universal newline support | 3204 # we are not opening the file with universal newline support |
2985 # (which codecs doesn't support anyway), so the resulting lines do | 3205 # (which codecs doesn't support anyway), so the resulting lines do |
2986 # contain trailing '\r' characters if we are reading a file that | 3206 # contain trailing '\r' characters if we are reading a file that |
2987 # has CRLF endings. | 3207 # has CRLF endings. |
(...skipping 24 matching lines...) Expand all Loading... |
3012 | 3232 |
3013 # Note, if no dot is found, this will give the entire filename as the ext. | 3233 # Note, if no dot is found, this will give the entire filename as the ext. |
3014 file_extension = filename[filename.rfind('.') + 1:] | 3234 file_extension = filename[filename.rfind('.') + 1:] |
3015 | 3235 |
3016 # When reading from stdin, the extension is unknown, so no cpplint tests | 3236 # When reading from stdin, the extension is unknown, so no cpplint tests |
3017 # should rely on the extension. | 3237 # should rely on the extension. |
3018 if (filename != '-' and file_extension != 'cc' and file_extension != 'h' | 3238 if (filename != '-' and file_extension != 'cc' and file_extension != 'h' |
3019 and file_extension != 'cpp'): | 3239 and file_extension != 'cpp'): |
3020 sys.stderr.write('Ignoring %s; not a .cc or .h file\n' % filename) | 3240 sys.stderr.write('Ignoring %s; not a .cc or .h file\n' % filename) |
3021 else: | 3241 else: |
3022 ProcessFileData(filename, file_extension, lines, Error) | 3242 ProcessFileData(filename, file_extension, lines, Error, |
| 3243 extra_check_functions) |
3023 if carriage_return_found and os.linesep != '\r\n': | 3244 if carriage_return_found and os.linesep != '\r\n': |
3024 # Use 0 for linenum since outputing only one error for potentially | 3245 # Use 0 for linenum since outputting only one error for potentially |
3025 # several lines. | 3246 # several lines. |
3026 Error(filename, 0, 'whitespace/newline', 1, | 3247 Error(filename, 0, 'whitespace/newline', 1, |
3027 'One or more unexpected \\r (^M) found;' | 3248 'One or more unexpected \\r (^M) found;' |
3028 'better to use only a \\n') | 3249 'better to use only a \\n') |
3029 | 3250 |
3030 sys.stderr.write('Done processing %s\n' % filename) | 3251 sys.stderr.write('Done processing %s\n' % filename) |
3031 | 3252 |
3032 | 3253 |
3033 def PrintUsage(message): | 3254 def PrintUsage(message): |
3034 """Prints a brief usage string and exits, optionally with an error message. | 3255 """Prints a brief usage string and exits, optionally with an error message. |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3117 _cpplint_state.ResetErrorCounts() | 3338 _cpplint_state.ResetErrorCounts() |
3118 for filename in filenames: | 3339 for filename in filenames: |
3119 ProcessFile(filename, _cpplint_state.verbose_level) | 3340 ProcessFile(filename, _cpplint_state.verbose_level) |
3120 _cpplint_state.PrintErrorCounts() | 3341 _cpplint_state.PrintErrorCounts() |
3121 | 3342 |
3122 sys.exit(_cpplint_state.error_count > 0) | 3343 sys.exit(_cpplint_state.error_count > 0) |
3123 | 3344 |
3124 | 3345 |
3125 if __name__ == '__main__': | 3346 if __name__ == '__main__': |
3126 main() | 3347 main() |
OLD | NEW |