Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(89)

Side by Side Diff: cpplint.py

Issue 7834045: Add lint check against "Foo *bar" and "Foo &bar" declarations. (Closed) Base URL: http://src.chromium.org/svn/trunk/tools/depot_tools/
Patch Set: '' Created 9 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | cpplint_chromium.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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()
OLDNEW
« no previous file with comments | « no previous file | cpplint_chromium.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698