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

Side by Side Diff: cpplint.py

Issue 147119: Copy a newer release of cpplint.py from google-styleguide. (Closed) Base URL: svn://chrome-svn/chrome/trunk/tools/depot_tools/
Patch Set: Created 11 years, 5 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 | « README ('k') | no next file » | 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 # cpplint.py is Copyright (C) 2009 Google Inc. 3 # cpplint.py is Copyright (C) 2009 Google Inc.
4 # 4 #
5 # It is free software; you can redistribute it and/or modify it under the 5 # It is free software; you can redistribute it and/or modify it under the
6 # terms of either: 6 # terms of either:
7 # 7 #
8 # a) the GNU General Public License as published by the Free Software 8 # a) the GNU General Public License as published by the Free Software
9 # Foundation; either version 1, or (at your option) any later version, or 9 # Foundation; either version 1, or (at your option) any later version, or
10 # 10 #
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
111 --filter=-,+build/include_what_you_use 111 --filter=-,+build/include_what_you_use
112 112
113 To see a list of all the categories used in cpplint, pass no arg: 113 To see a list of all the categories used in cpplint, pass no arg:
114 --filter= 114 --filter=
115 """ 115 """
116 116
117 # We categorize each error message we print. Here are the categories. 117 # We categorize each error message we print. Here are the categories.
118 # We want an explicit list so we can list them all in cpplint --filter=. 118 # We want an explicit list so we can list them all in cpplint --filter=.
119 # If you add a new error message with a new category, add it to the list 119 # If you add a new error message with a new category, add it to the list
120 # here! cpplint_unittest.py should tell you if you forget to do this. 120 # here! cpplint_unittest.py should tell you if you forget to do this.
121 _ERROR_CATEGORIES = """\ 121 # \ used for clearer layout -- pylint: disable-msg=C6013
122 _ERROR_CATEGORIES = '''\
122 build/class 123 build/class
123 build/deprecated 124 build/deprecated
124 build/endif_comment 125 build/endif_comment
125 build/forward_decl 126 build/forward_decl
126 build/header_guard 127 build/header_guard
127 build/include 128 build/include
128 build/include_order 129 build/include_order
129 build/include_what_you_use 130 build/include_what_you_use
130 build/namespaces 131 build/namespaces
131 build/printf_format 132 build/printf_format
132 build/storage_class 133 build/storage_class
133 legal/copyright 134 legal/copyright
134 readability/braces 135 readability/braces
135 readability/casting 136 readability/casting
136 readability/check 137 readability/check
137 readability/constructors 138 readability/constructors
138 readability/fn_size 139 readability/fn_size
139 readability/function 140 readability/function
140 readability/multiline_comment 141 readability/multiline_comment
141 readability/multiline_string 142 readability/multiline_string
142 readability/streams 143 readability/streams
143 readability/todo 144 readability/todo
144 readability/utf8 145 readability/utf8
145 runtime/arrays 146 runtime/arrays
146 runtime/casting 147 runtime/casting
147 runtime/explicit 148 runtime/explicit
148 runtime/int 149 runtime/int
149 runtime/init 150 runtime/init
151 runtime/invalid_increment
150 runtime/memset 152 runtime/memset
151 runtime/printf 153 runtime/printf
152 runtime/printf_format 154 runtime/printf_format
153 runtime/references 155 runtime/references
154 runtime/rtti 156 runtime/rtti
155 runtime/sizeof 157 runtime/sizeof
156 runtime/string 158 runtime/string
157 runtime/threadsafe_fn 159 runtime/threadsafe_fn
158 runtime/virtual 160 runtime/virtual
159 whitespace/blank_line 161 whitespace/blank_line
160 whitespace/braces 162 whitespace/braces
161 whitespace/comma 163 whitespace/comma
162 whitespace/comments 164 whitespace/comments
163 whitespace/end_of_line 165 whitespace/end_of_line
164 whitespace/ending_newline 166 whitespace/ending_newline
165 whitespace/indent 167 whitespace/indent
166 whitespace/labels 168 whitespace/labels
167 whitespace/line_length 169 whitespace/line_length
168 whitespace/newline 170 whitespace/newline
169 whitespace/operators 171 whitespace/operators
170 whitespace/parens 172 whitespace/parens
171 whitespace/semicolon 173 whitespace/semicolon
172 whitespace/tab 174 whitespace/tab
173 whitespace/todo 175 whitespace/todo
174 """ 176 '''
177
178 # The default state of the category filter. This is overrided by the --filter=
179 # flag. By default all errors are on, so only add here categories that should be
180 # off by default (i.e., categories that must be enabled by the --filter= flags).
181 # All entries here should start with a '-' or '+', as in the --filter= flag.
182 _DEFAULT_FILTERS = []
175 183
176 # We used to check for high-bit characters, but after much discussion we 184 # We used to check for high-bit characters, but after much discussion we
177 # decided those were OK, as long as they were in UTF-8 and didn't represent 185 # decided those were OK, as long as they were in UTF-8 and didn't represent
178 # hard-coded international strings, which belong in a seperate i18n file. 186 # hard-coded international strings, which belong in a seperate i18n file.
179 187
180 # Headers that we consider STL headers. 188 # Headers that we consider STL headers.
181 _STL_HEADERS = frozenset([ 189 _STL_HEADERS = frozenset([
182 'algobase.h', 'algorithm', 'alloc.h', 'bitset', 'deque', 'exception', 190 'algobase.h', 'algorithm', 'alloc.h', 'bitset', 'deque', 'exception',
183 'function.h', 'functional', 'hash_map', 'hash_map.h', 'hash_set', 191 'function.h', 'functional', 'hash_map', 'hash_map.h', 'hash_set',
184 'hash_set.h', 'iterator', 'list', 'list.h', 'map', 'memory', 'pair.h', 192 'hash_set.h', 'iterator', 'list', 'list.h', 'map', 'memory', 'pair.h',
(...skipping 18 matching lines...) Expand all
203 'SFile.h', 'slist', 'slist.h', 'stack.h', 'stdexcept', 211 'SFile.h', 'slist', 'slist.h', 'stack.h', 'stdexcept',
204 'stdiostream.h', 'streambuf.h', 'stream.h', 'strfile.h', 'string', 212 'stdiostream.h', 'streambuf.h', 'stream.h', 'strfile.h', 'string',
205 'strstream', 'strstream.h', 'tempbuf.h', 'tree.h', 'typeinfo', 'valarray', 213 'strstream', 'strstream.h', 'tempbuf.h', 'tree.h', 'typeinfo', 'valarray',
206 ]) 214 ])
207 215
208 216
209 # Assertion macros. These are defined in base/logging.h and 217 # Assertion macros. These are defined in base/logging.h and
210 # testing/base/gunit.h. Note that the _M versions need to come first 218 # testing/base/gunit.h. Note that the _M versions need to come first
211 # for substring matching to work. 219 # for substring matching to work.
212 _CHECK_MACROS = [ 220 _CHECK_MACROS = [
213 'CHECK', 221 'DCHECK', 'CHECK',
214 'EXPECT_TRUE_M', 'EXPECT_TRUE', 222 'EXPECT_TRUE_M', 'EXPECT_TRUE',
215 'ASSERT_TRUE_M', 'ASSERT_TRUE', 223 'ASSERT_TRUE_M', 'ASSERT_TRUE',
216 'EXPECT_FALSE_M', 'EXPECT_FALSE', 224 'EXPECT_FALSE_M', 'EXPECT_FALSE',
217 'ASSERT_FALSE_M', 'ASSERT_FALSE', 225 'ASSERT_FALSE_M', 'ASSERT_FALSE',
218 ] 226 ]
219 227
220 # Replacement macros for CHECK/EXPECT_TRUE/EXPECT_FALSE 228 # Replacement macros for CHECK/DCHECK/EXPECT_TRUE/EXPECT_FALSE
221 _CHECK_REPLACEMENT = dict([(m, {}) for m in _CHECK_MACROS]) 229 _CHECK_REPLACEMENT = dict([(m, {}) for m in _CHECK_MACROS])
222 230
223 for op, replacement in [('==', 'EQ'), ('!=', 'NE'), 231 for op, replacement in [('==', 'EQ'), ('!=', 'NE'),
224 ('>=', 'GE'), ('>', 'GT'), 232 ('>=', 'GE'), ('>', 'GT'),
225 ('<=', 'LE'), ('<', 'LT')]: 233 ('<=', 'LE'), ('<', 'LT')]:
234 _CHECK_REPLACEMENT['DCHECK'][op] = 'DCHECK_%s' % replacement
226 _CHECK_REPLACEMENT['CHECK'][op] = 'CHECK_%s' % replacement 235 _CHECK_REPLACEMENT['CHECK'][op] = 'CHECK_%s' % replacement
227 _CHECK_REPLACEMENT['EXPECT_TRUE'][op] = 'EXPECT_%s' % replacement 236 _CHECK_REPLACEMENT['EXPECT_TRUE'][op] = 'EXPECT_%s' % replacement
228 _CHECK_REPLACEMENT['ASSERT_TRUE'][op] = 'ASSERT_%s' % replacement 237 _CHECK_REPLACEMENT['ASSERT_TRUE'][op] = 'ASSERT_%s' % replacement
229 _CHECK_REPLACEMENT['EXPECT_TRUE_M'][op] = 'EXPECT_%s_M' % replacement 238 _CHECK_REPLACEMENT['EXPECT_TRUE_M'][op] = 'EXPECT_%s_M' % replacement
230 _CHECK_REPLACEMENT['ASSERT_TRUE_M'][op] = 'ASSERT_%s_M' % replacement 239 _CHECK_REPLACEMENT['ASSERT_TRUE_M'][op] = 'ASSERT_%s_M' % replacement
231 240
232 for op, inv_replacement in [('==', 'NE'), ('!=', 'EQ'), 241 for op, inv_replacement in [('==', 'NE'), ('!=', 'EQ'),
233 ('>=', 'LT'), ('>', 'LE'), 242 ('>=', 'LT'), ('>', 'LE'),
234 ('<=', 'GT'), ('<', 'GE')]: 243 ('<=', 'GT'), ('<', 'GE')]:
235 _CHECK_REPLACEMENT['EXPECT_FALSE'][op] = 'EXPECT_%s' % inv_replacement 244 _CHECK_REPLACEMENT['EXPECT_FALSE'][op] = 'EXPECT_%s' % inv_replacement
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
351 360
352 return '' 361 return ''
353 362
354 363
355 class _CppLintState(object): 364 class _CppLintState(object):
356 """Maintains module-wide state..""" 365 """Maintains module-wide state.."""
357 366
358 def __init__(self): 367 def __init__(self):
359 self.verbose_level = 1 # global setting. 368 self.verbose_level = 1 # global setting.
360 self.error_count = 0 # global count of reported errors 369 self.error_count = 0 # global count of reported errors
361 self.filters = [] # filters to apply when emitting error messages 370 # filters to apply when emitting error messages
371 self.filters = _DEFAULT_FILTERS[:]
362 372
363 # output format: 373 # output format:
364 # "emacs" - format that emacs can parse (default) 374 # "emacs" - format that emacs can parse (default)
365 # "vs7" - format that Microsoft Visual Studio 7 can parse 375 # "vs7" - format that Microsoft Visual Studio 7 can parse
366 self.output_format = 'emacs' 376 self.output_format = 'emacs'
367 377
368 def SetOutputFormat(self, output_format): 378 def SetOutputFormat(self, output_format):
369 """Sets the output format for errors.""" 379 """Sets the output format for errors."""
370 self.output_format = output_format 380 self.output_format = output_format
371 381
372 def SetVerboseLevel(self, level): 382 def SetVerboseLevel(self, level):
373 """Sets the module's verbosity, and returns the previous setting.""" 383 """Sets the module's verbosity, and returns the previous setting."""
374 last_verbose_level = self.verbose_level 384 last_verbose_level = self.verbose_level
375 self.verbose_level = level 385 self.verbose_level = level
376 return last_verbose_level 386 return last_verbose_level
377 387
378 def SetFilters(self, filters): 388 def SetFilters(self, filters):
379 """Sets the error-message filters. 389 """Sets the error-message filters.
380 390
381 These filters are applied when deciding whether to emit a given 391 These filters are applied when deciding whether to emit a given
382 error message. 392 error message.
383 393
384 Args: 394 Args:
385 filters: A string of comma-separated filters (eg "+whitespace/indent"). 395 filters: A string of comma-separated filters (eg "+whitespace/indent").
386 Each filter should start with + or -; else we die. 396 Each filter should start with + or -; else we die.
397
398 Raises:
399 ValueError: The comma-separated filters did not all start with '+' or '-'.
400 E.g. "-,+whitespace,-whitespace/indent,whitespace/badfilter"
387 """ 401 """
388 if not filters: 402 # Default filters always have less priority than the flag ones.
389 self.filters = [] 403 self.filters = _DEFAULT_FILTERS[:]
390 else: 404 for filt in filters.split(','):
391 self.filters = filters.split(',') 405 clean_filt = filt.strip()
406 if clean_filt:
407 self.filters.append(clean_filt)
392 for filt in self.filters: 408 for filt in self.filters:
393 if not (filt.startswith('+') or filt.startswith('-')): 409 if not (filt.startswith('+') or filt.startswith('-')):
394 raise ValueError('Every filter in --filters must start with + or -' 410 raise ValueError('Every filter in --filters must start with + or -'
395 ' (%s does not)' % filt) 411 ' (%s does not)' % filt)
396 412
397 def ResetErrorCount(self): 413 def ResetErrorCount(self):
398 """Sets the module's error statistic back to zero.""" 414 """Sets the module's error statistic back to zero."""
399 self.error_count = 0 415 self.error_count = 0
400 416
401 def IncrementErrorCount(self): 417 def IncrementErrorCount(self):
(...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after
735 Returns: 751 Returns:
736 The line with single-line comments removed. 752 The line with single-line comments removed.
737 """ 753 """
738 commentpos = line.find('//') 754 commentpos = line.find('//')
739 if commentpos != -1 and not IsCppString(line[:commentpos]): 755 if commentpos != -1 and not IsCppString(line[:commentpos]):
740 line = line[:commentpos] 756 line = line[:commentpos]
741 # get rid of /* ... */ 757 # get rid of /* ... */
742 return _RE_PATTERN_CLEANSE_LINE_C_COMMENTS.sub('', line) 758 return _RE_PATTERN_CLEANSE_LINE_C_COMMENTS.sub('', line)
743 759
744 760
745 class CleansedLines: 761 class CleansedLines(object):
746 """Holds 3 copies of all lines with different preprocessing applied to them. 762 """Holds 3 copies of all lines with different preprocessing applied to them.
747 763
748 1) elided member contains lines without strings and comments, 764 1) elided member contains lines without strings and comments,
749 2) lines member contains lines without comments, and 765 2) lines member contains lines without comments, and
750 3) raw member contains all the lines without processing. 766 3) raw member contains all the lines without processing.
751 All these three members are of <type 'list'>, and of the same length. 767 All these three members are of <type 'list'>, and of the same length.
752 """ 768 """
753 769
754 def __init__(self, lines): 770 def __init__(self, lines):
755 self.elided = [] 771 self.elided = []
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
851 867
852 """ 868 """
853 869
854 fileinfo = FileInfo(filename) 870 fileinfo = FileInfo(filename)
855 return re.sub(r'[-./\s]', '_', fileinfo.RepositoryName()).upper() + '_' 871 return re.sub(r'[-./\s]', '_', fileinfo.RepositoryName()).upper() + '_'
856 872
857 873
858 def CheckForHeaderGuard(filename, lines, error): 874 def CheckForHeaderGuard(filename, lines, error):
859 """Checks that the file contains a header guard. 875 """Checks that the file contains a header guard.
860 876
861 Logs an error if no #ifndef header guard is present. For google3 877 Logs an error if no #ifndef header guard is present. For other
862 headers, checks that the full pathname is used. 878 headers, checks that the full pathname is used.
863 879
864 Args: 880 Args:
865 filename: The name of the C++ header file. 881 filename: The name of the C++ header file.
866 lines: An array of strings, each representing a line of the file. 882 lines: An array of strings, each representing a line of the file.
867 error: The function to call with any errors found. 883 error: The function to call with any errors found.
868 """ 884 """
869 885
870 cppvar = GetHeaderGuardCPPVariable(filename) 886 cppvar = GetHeaderGuardCPPVariable(filename)
871 887
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
1017 1033
1018 Args: 1034 Args:
1019 filename: The name of the current file. 1035 filename: The name of the current file.
1020 clean_lines: A CleansedLines instance containing the file. 1036 clean_lines: A CleansedLines instance containing the file.
1021 linenum: The number of the line to check. 1037 linenum: The number of the line to check.
1022 error: The function to call with any errors found. 1038 error: The function to call with any errors found.
1023 """ 1039 """
1024 line = clean_lines.elided[linenum] 1040 line = clean_lines.elided[linenum]
1025 for single_thread_function, multithread_safe_function in threading_list: 1041 for single_thread_function, multithread_safe_function in threading_list:
1026 ix = line.find(single_thread_function) 1042 ix = line.find(single_thread_function)
1043 # Comparisons made explicit for clarity -- pylint: disable-msg=C6403
1027 if ix >= 0 and (ix == 0 or (not line[ix - 1].isalnum() and 1044 if ix >= 0 and (ix == 0 or (not line[ix - 1].isalnum() and
1028 line[ix - 1] not in ('_', '.', '>'))): 1045 line[ix - 1] not in ('_', '.', '>'))):
1029 error(filename, linenum, 'runtime/threadsafe_fn', 2, 1046 error(filename, linenum, 'runtime/threadsafe_fn', 2,
1030 'Consider using ' + multithread_safe_function + 1047 'Consider using ' + multithread_safe_function +
1031 '...) instead of ' + single_thread_function + 1048 '...) instead of ' + single_thread_function +
1032 '...) for improved thread safety.') 1049 '...) for improved thread safety.')
1033 1050
1034 1051
1052 # Matches invalid increment: *count++, which moves pointer insead of
1053 # incrementing a value.
1054 _RE_PATTERN_IVALID_INCREMENT = re.compile(
1055 r'^\s*\*\w+(\+\+|--);')
1056
1057
1058 def CheckInvalidIncrement(filename, clean_lines, linenum, error):
1059 """Checks for invalud increment *count++.
1060
1061 For example following function:
1062 void increment_counter(int* count) {
1063 *count++;
1064 }
1065 is invalid, because it effectively does count++, moving pointer, and should
1066 be replaced with ++*count, (*count)++ or *count += 1.
1067
1068 Args:
1069 filename: The name of the current file.
1070 clean_lines: A CleansedLines instance containing the file.
1071 linenum: The number of the line to check.
1072 error: The function to call with any errors found.
1073 """
1074 line = clean_lines.elided[linenum]
1075 if _RE_PATTERN_IVALID_INCREMENT.match(line):
1076 error(filename, linenum, 'runtime/invalid_increment', 5,
1077 'Changing pointer instead of value (or unused value of operator*).')
1078
1079
1035 class _ClassInfo(object): 1080 class _ClassInfo(object):
1036 """Stores information about a class.""" 1081 """Stores information about a class."""
1037 1082
1038 def __init__(self, name, linenum): 1083 def __init__(self, name, linenum):
1039 self.name = name 1084 self.name = name
1040 self.linenum = linenum 1085 self.linenum = linenum
1041 self.seen_open_brace = False 1086 self.seen_open_brace = False
1042 self.is_derived = False 1087 self.is_derived = False
1043 self.virtual_method_linenumber = None 1088 self.virtual_method_linenumber = None
1044 self.has_virtual_destructor = False 1089 self.has_virtual_destructor = False
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after
1262 # " (something)(maybe-something," or 1307 # " (something)(maybe-something," or
1263 # " (something)[something]" 1308 # " (something)[something]"
1264 # Note that we assume the contents of [] to be short enough that 1309 # Note that we assume the contents of [] to be short enough that
1265 # they'll never need to wrap. 1310 # they'll never need to wrap.
1266 if ( # Ignore control structures. 1311 if ( # Ignore control structures.
1267 not Search(r'\b(if|for|while|switch|return|delete)\b', fncall) and 1312 not Search(r'\b(if|for|while|switch|return|delete)\b', fncall) and
1268 # Ignore pointers/references to functions. 1313 # Ignore pointers/references to functions.
1269 not Search(r' \([^)]+\)\([^)]*(\)|,$)', fncall) and 1314 not Search(r' \([^)]+\)\([^)]*(\)|,$)', fncall) and
1270 # Ignore pointers/references to arrays. 1315 # Ignore pointers/references to arrays.
1271 not Search(r' \([^)]+\)\[[^\]]+\]', fncall)): 1316 not Search(r' \([^)]+\)\[[^\]]+\]', fncall)):
1272 if Search(r'\w\s*\(\s', fncall): # a ( used for a fn call 1317 if Search(r'\w\s*\(\s(?!\s*\\$)', fncall): # a ( used for a fn call
1273 error(filename, linenum, 'whitespace/parens', 4, 1318 error(filename, linenum, 'whitespace/parens', 4,
1274 'Extra space after ( in function call') 1319 'Extra space after ( in function call')
1275 elif Search(r'\(\s+[^(]', fncall): 1320 elif Search(r'\(\s+(?!(\s*\\)|\()', fncall):
1276 error(filename, linenum, 'whitespace/parens', 2, 1321 error(filename, linenum, 'whitespace/parens', 2,
1277 'Extra space after (') 1322 'Extra space after (')
1278 if (Search(r'\w\s+\(', fncall) and 1323 if (Search(r'\w\s+\(', fncall) and
1279 not Search(r'#\s*define|typedef', fncall)): 1324 not Search(r'#\s*define|typedef', fncall)):
1280 error(filename, linenum, 'whitespace/parens', 4, 1325 error(filename, linenum, 'whitespace/parens', 4,
1281 'Extra space before ( in function call') 1326 'Extra space before ( in function call')
1282 # If the ) is followed only by a newline or a { + newline, assume it's 1327 # If the ) is followed only by a newline or a { + newline, assume it's
1283 # part of a control statement (if/while/etc), and don't complain 1328 # part of a control statement (if/while/etc), and don't complain
1284 if Search(r'[^)]\s+\)\s*[^{\s]', fncall): 1329 if Search(r'[^)]\s+\)\s*[^{\s]', fncall):
1285 error(filename, linenum, 'whitespace/parens', 2, 1330 error(filename, linenum, 'whitespace/parens', 2,
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1324 function_state: Current function name and lines in body so far. 1369 function_state: Current function name and lines in body so far.
1325 error: The function to call with any errors found. 1370 error: The function to call with any errors found.
1326 """ 1371 """
1327 lines = clean_lines.lines 1372 lines = clean_lines.lines
1328 line = lines[linenum] 1373 line = lines[linenum]
1329 raw = clean_lines.raw_lines 1374 raw = clean_lines.raw_lines
1330 raw_line = raw[linenum] 1375 raw_line = raw[linenum]
1331 joined_line = '' 1376 joined_line = ''
1332 1377
1333 starting_func = False 1378 starting_func = False
1334 regexp = r'(\w(\w|::|\*|\&|\s)*)\(' # decls * & space::name( ... 1379 regexp = r'(\w(\w|::|\*|\&|\s)*)\(' # decls * & space::name( ...
1335 match_result = Match(regexp, line) 1380 match_result = Match(regexp, line)
1336 if match_result: 1381 if match_result:
1337 # If the name is all caps and underscores, figure it's a macro and 1382 # If the name is all caps and underscores, figure it's a macro and
1338 # ignore it, unless it's TEST or TEST_F. 1383 # ignore it, unless it's TEST or TEST_F.
1339 function_name = match_result.group(1).split()[-1] 1384 function_name = match_result.group(1).split()[-1]
1340 if function_name == 'TEST' or function_name == 'TEST_F' or ( 1385 if function_name == 'TEST' or function_name == 'TEST_F' or (
1341 not Match(r'[A-Z_]+$', function_name)): 1386 not Match(r'[A-Z_]+$', function_name)):
1342 starting_func = True 1387 starting_func = True
1343 1388
1344 if starting_func: 1389 if starting_func:
1345 body_found = False 1390 body_found = False
1346 # Don't look too far for the function body. Lint might be mistaken about 1391 for start_linenum in xrange(linenum, clean_lines.NumLines()):
1347 # whether it's a function definition.
1348 for start_linenum in xrange(linenum,
1349 min(linenum+100, clean_lines.NumLines())):
1350 start_line = lines[start_linenum] 1392 start_line = lines[start_linenum]
1351 joined_line += ' ' + start_line.lstrip() 1393 joined_line += ' ' + start_line.lstrip()
1352 if Search(r'(;|})', start_line): # Declarations and trivial functions 1394 if Search(r'(;|})', start_line): # Declarations and trivial functions
1353 body_found = True 1395 body_found = True
1354 break # ... ignore 1396 break # ... ignore
1355 elif Search(r'{', start_line): 1397 elif Search(r'{', start_line):
1356 body_found = True 1398 body_found = True
1357 function = Search(r'((\w|:)*)\(', line).group(1) 1399 function = Search(r'((\w|:)*)\(', line).group(1)
1358 if Match(r'TEST', function): # Handle TEST... macros 1400 if Match(r'TEST', function): # Handle TEST... macros
1359 parameter_regexp = Search(r'(\(.*\))', joined_line) 1401 parameter_regexp = Search(r'(\(.*\))', joined_line)
1360 if parameter_regexp: # Ignore bad syntax 1402 if parameter_regexp: # Ignore bad syntax
1361 function += parameter_regexp.group(1) 1403 function += parameter_regexp.group(1)
1362 else: 1404 else:
1363 function += '()' 1405 function += '()'
1364 function_state.Begin(function) 1406 function_state.Begin(function)
1365 break 1407 break
1366 if not body_found: 1408 if not body_found:
1367 # 50 lines after finding a line deemed to start a function 1409 # No body for the function (or evidence of a non-function) was found.
1368 # definition, no body for the function was found. A macro
1369 # invocation with no terminating semicolon could trigger this.
1370 error(filename, linenum, 'readability/fn_size', 5, 1410 error(filename, linenum, 'readability/fn_size', 5,
1371 'Lint failed to find start of function body.') 1411 'Lint failed to find start of function body.')
1372 elif Match(r'^\}\s*$', line): # function end 1412 elif Match(r'^\}\s*$', line): # function end
1373 if not Search(r'\bNOLINT\b', raw_line): 1413 if not Search(r'\bNOLINT\b', raw_line):
1374 function_state.Check(error, filename, linenum) 1414 function_state.Check(error, filename, linenum)
1375 function_state.End() 1415 function_state.End()
1376 elif not Match(r'^\s*$', line): 1416 elif not Match(r'^\s*$', line):
1377 function_state.Count() # Count non-blank/non-comment lines. 1417 function_state.Count() # Count non-blank/non-comment lines.
1378 1418
1379 1419
(...skipping 17 matching lines...) Expand all
1397 error(filename, linenum, 'whitespace/todo', 2, 1437 error(filename, linenum, 'whitespace/todo', 2,
1398 'Too many spaces before TODO') 1438 'Too many spaces before TODO')
1399 1439
1400 username = match.group(2) 1440 username = match.group(2)
1401 if not username: 1441 if not username:
1402 error(filename, linenum, 'readability/todo', 2, 1442 error(filename, linenum, 'readability/todo', 2,
1403 'Missing username in TODO; it should look like ' 1443 'Missing username in TODO; it should look like '
1404 '"// TODO(my_username): Stuff."') 1444 '"// TODO(my_username): Stuff."')
1405 1445
1406 middle_whitespace = match.group(3) 1446 middle_whitespace = match.group(3)
1447 # Comparisons made explicit for correctness -- pylint: disable-msg=C6403
1407 if middle_whitespace != ' ' and middle_whitespace != '': 1448 if middle_whitespace != ' ' and middle_whitespace != '':
1408 error(filename, linenum, 'whitespace/todo', 2, 1449 error(filename, linenum, 'whitespace/todo', 2,
1409 'TODO(my_username) should be followed by a space') 1450 'TODO(my_username) should be followed by a space')
1410 1451
1411 1452
1412 def CheckSpacing(filename, clean_lines, linenum, error): 1453 def CheckSpacing(filename, clean_lines, linenum, error):
1413 """Checks for the correctness of various spacing issues in the code. 1454 """Checks for the correctness of various spacing issues in the code.
1414 1455
1415 Things we check for: spaces around operators, spaces after 1456 Things we check for: spaces around operators, spaces after
1416 if/for/while/switch, no spaces around parens in function calls, two 1457 if/for/while/switch, no spaces around parens in function calls, two
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
1491 and Match(r'\s*}', next_line) 1532 and Match(r'\s*}', next_line)
1492 and next_line.find('namespace') == -1 1533 and next_line.find('namespace') == -1
1493 and next_line.find('} else ') == -1): 1534 and next_line.find('} else ') == -1):
1494 error(filename, linenum, 'whitespace/blank_line', 3, 1535 error(filename, linenum, 'whitespace/blank_line', 3,
1495 'Blank line at the end of a code block. Is this needed?') 1536 'Blank line at the end of a code block. Is this needed?')
1496 1537
1497 # Next, we complain if there's a comment too near the text 1538 # Next, we complain if there's a comment too near the text
1498 commentpos = line.find('//') 1539 commentpos = line.find('//')
1499 if commentpos != -1: 1540 if commentpos != -1:
1500 # Check if the // may be in quotes. If so, ignore it 1541 # Check if the // may be in quotes. If so, ignore it
1542 # Comparisons made explicit for clarity -- pylint: disable-msg=C6403
1501 if (line.count('"', 0, commentpos) - 1543 if (line.count('"', 0, commentpos) -
1502 line.count('\\"', 0, commentpos)) % 2 == 0: # not in quotes 1544 line.count('\\"', 0, commentpos)) % 2 == 0: # not in quotes
1503 # Allow one space for new scopes, two spaces otherwise: 1545 # Allow one space for new scopes, two spaces otherwise:
1504 if (not Match(r'^\s*{ //', line) and 1546 if (not Match(r'^\s*{ //', line) and
1505 ((commentpos >= 1 and 1547 ((commentpos >= 1 and
1506 line[commentpos-1] not in string.whitespace) or 1548 line[commentpos-1] not in string.whitespace) or
1507 (commentpos >= 2 and 1549 (commentpos >= 2 and
1508 line[commentpos-2] not in string.whitespace))): 1550 line[commentpos-2] not in string.whitespace))):
1509 error(filename, linenum, 'whitespace/comments', 2, 1551 error(filename, linenum, 'whitespace/comments', 2,
1510 'At least two spaces is best between code and comments') 1552 'At least two spaces is best between code and comments')
1511 # There should always be a space between the // and the comment 1553 # There should always be a space between the // and the comment
1512 commentend = commentpos + 2 1554 commentend = commentpos + 2
1513 if commentend < len(line) and not line[commentend] == ' ': 1555 if commentend < len(line) and not line[commentend] == ' ':
1514 # but some lines are exceptions -- e.g. if they're big 1556 # but some lines are exceptions -- e.g. if they're big
1515 # comment delimiters like: 1557 # comment delimiters like:
1516 # //---------------------------------------------------------- 1558 # //----------------------------------------------------------
1517 match = Search(r'[=/-]{4,}\s*$', line[commentend:]) 1559 # or they begin with multiple slashes followed by a space:
1560 # //////// Header comment
1561 match = (Search(r'[=/-]{4,}\s*$', line[commentend:]) or
1562 Search(r'^/+ ', line[commentend:]))
1518 if not match: 1563 if not match:
1519 error(filename, linenum, 'whitespace/comments', 4, 1564 error(filename, linenum, 'whitespace/comments', 4,
1520 'Should have a space between // and comment') 1565 'Should have a space between // and comment')
1521 CheckComment(line[commentpos:], filename, linenum, error) 1566 CheckComment(line[commentpos:], filename, linenum, error)
1522 1567
1523 line = clean_lines.elided[linenum] # get rid of comments and strings 1568 line = clean_lines.elided[linenum] # get rid of comments and strings
1524 1569
1525 # Don't try to do spacing checks for operator methods 1570 # Don't try to do spacing checks for operator methods
1526 line = re.sub(r'operator(==|!=|<|<<|<=|>=|>>|>)\(', 'operator\(', line) 1571 line = re.sub(r'operator(==|!=|<|<<|<=|>=|>>|>)\(', 'operator\(', line)
1527 1572
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1568 # A pet peeve of mine: no spaces after an if, while, switch, or for 1613 # A pet peeve of mine: no spaces after an if, while, switch, or for
1569 match = Search(r' (if\(|for\(|while\(|switch\()', line) 1614 match = Search(r' (if\(|for\(|while\(|switch\()', line)
1570 if match: 1615 if match:
1571 error(filename, linenum, 'whitespace/parens', 5, 1616 error(filename, linenum, 'whitespace/parens', 5,
1572 'Missing space before ( in %s' % match.group(1)) 1617 'Missing space before ( in %s' % match.group(1))
1573 1618
1574 # For if/for/while/switch, the left and right parens should be 1619 # For if/for/while/switch, the left and right parens should be
1575 # consistent about how many spaces are inside the parens, and 1620 # consistent about how many spaces are inside the parens, and
1576 # there should either be zero or one spaces inside the parens. 1621 # there should either be zero or one spaces inside the parens.
1577 # We don't want: "if ( foo)" or "if ( foo )". 1622 # We don't want: "if ( foo)" or "if ( foo )".
1578 # Exception: "for ( ; foo; bar)" is allowed. 1623 # Exception: "for ( ; foo; bar)" and "for (foo; bar; )" are allowed.
1579 match = Search(r'\b(if|for|while|switch)\s*' 1624 match = Search(r'\b(if|for|while|switch)\s*'
1580 r'\(([ ]*)(.).*[^ ]+([ ]*)\)\s*{\s*$', 1625 r'\(([ ]*)(.).*[^ ]+([ ]*)\)\s*{\s*$',
1581 line) 1626 line)
1582 if match: 1627 if match:
1583 if len(match.group(2)) != len(match.group(4)): 1628 if len(match.group(2)) != len(match.group(4)):
1584 if not (match.group(3) == ';' and 1629 if not (match.group(3) == ';' and
1585 len(match.group(2)) == 1 + len(match.group(4))): 1630 len(match.group(2)) == 1 + len(match.group(4)) or
1631 not match.group(2) and Search(r'\bfor\s*\(.*; \)', line)):
1586 error(filename, linenum, 'whitespace/parens', 5, 1632 error(filename, linenum, 'whitespace/parens', 5,
1587 'Mismatching spaces inside () in %s' % match.group(1)) 1633 'Mismatching spaces inside () in %s' % match.group(1))
1588 if not len(match.group(2)) in [0, 1]: 1634 if not len(match.group(2)) in [0, 1]:
1589 error(filename, linenum, 'whitespace/parens', 5, 1635 error(filename, linenum, 'whitespace/parens', 5,
1590 'Should have zero or one spaces inside ( and ) in %s' % 1636 'Should have zero or one spaces inside ( and ) in %s' %
1591 match.group(1)) 1637 match.group(1))
1592 1638
1593 # You should always have a space after a comma (either as fn arg or operator) 1639 # You should always have a space after a comma (either as fn arg or operator)
1594 if Search(r',[^\s]', line): 1640 if Search(r',[^\s]', line):
1595 error(filename, linenum, 'whitespace/comma', 3, 1641 error(filename, linenum, 'whitespace/comma', 3,
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after
1878 # Check if the line is a header guard. 1924 # Check if the line is a header guard.
1879 is_header_guard = False 1925 is_header_guard = False
1880 if file_extension == 'h': 1926 if file_extension == 'h':
1881 cppvar = GetHeaderGuardCPPVariable(filename) 1927 cppvar = GetHeaderGuardCPPVariable(filename)
1882 if (line.startswith('#ifndef %s' % cppvar) or 1928 if (line.startswith('#ifndef %s' % cppvar) or
1883 line.startswith('#define %s' % cppvar) or 1929 line.startswith('#define %s' % cppvar) or
1884 line.startswith('#endif // %s' % cppvar)): 1930 line.startswith('#endif // %s' % cppvar)):
1885 is_header_guard = True 1931 is_header_guard = True
1886 # #include lines and header guards can be long, since there's no clean way to 1932 # #include lines and header guards can be long, since there's no clean way to
1887 # split them. 1933 # split them.
1888 if not line.startswith('#include') and not is_header_guard: 1934 #
1935 # URLs can be long too. It's possible to split these, but it makes them
1936 # harder to cut&paste.
1937 if (not line.startswith('#include') and not is_header_guard and
1938 not Match(r'^\s*//.*http(s?)://\S*$', line)):
1889 line_width = GetLineWidth(line) 1939 line_width = GetLineWidth(line)
1890 if line_width > 100: 1940 if line_width > 100:
1891 error(filename, linenum, 'whitespace/line_length', 4, 1941 error(filename, linenum, 'whitespace/line_length', 4,
1892 'Lines should very rarely be longer than 100 characters') 1942 'Lines should very rarely be longer than 100 characters')
1893 elif line_width > 80: 1943 elif line_width > 80:
1894 error(filename, linenum, 'whitespace/line_length', 2, 1944 error(filename, linenum, 'whitespace/line_length', 2,
1895 'Lines should be <= 80 characters long') 1945 'Lines should be <= 80 characters long')
1896 1946
1897 if (cleansed_line.count(';') > 1 and 1947 if (cleansed_line.count(';') > 1 and
1898 # for loops are allowed two ;'s (and may run over two lines). 1948 # for loops are allowed two ;'s (and may run over two lines).
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
2019 target_first_component = _RE_FIRST_COMPONENT.match(target_base) 2069 target_first_component = _RE_FIRST_COMPONENT.match(target_base)
2020 include_first_component = _RE_FIRST_COMPONENT.match(include_base) 2070 include_first_component = _RE_FIRST_COMPONENT.match(include_base)
2021 if (target_first_component and include_first_component and 2071 if (target_first_component and include_first_component and
2022 target_first_component.group(0) == 2072 target_first_component.group(0) ==
2023 include_first_component.group(0)): 2073 include_first_component.group(0)):
2024 return _POSSIBLE_MY_HEADER 2074 return _POSSIBLE_MY_HEADER
2025 2075
2026 return _OTHER_HEADER 2076 return _OTHER_HEADER
2027 2077
2028 2078
2029 def CheckLanguage(filename, clean_lines, linenum, file_extension, include_state,
2030 error):
2031 """Checks rules from the 'C++ language rules' section of cppguide.html.
2032 2079
2033 Some of these rules are hard to test (function overloading, using 2080 def CheckIncludeLine(filename, clean_lines, linenum, include_state, error):
2034 uint32 inappropriately), but we do the best we can. 2081 """Check rules that are applicable to #include lines.
2082
2083 Strings on #include lines are NOT removed from elided line, to make
2084 certain tasks easier. However, to prevent false positives, checks
2085 applicable to #include lines in CheckLanguage must be put here.
2035 2086
2036 Args: 2087 Args:
2037 filename: The name of the current file. 2088 filename: The name of the current file.
2038 clean_lines: A CleansedLines instance containing the file. 2089 clean_lines: A CleansedLines instance containing the file.
2039 linenum: The number of the line to check. 2090 linenum: The number of the line to check.
2040 file_extension: The extension (without the dot) of the filename.
2041 include_state: An _IncludeState instance in which the headers are inserted. 2091 include_state: An _IncludeState instance in which the headers are inserted.
2042 error: The function to call with any errors found. 2092 error: The function to call with any errors found.
2043 """ 2093 """
2044 fileinfo = FileInfo(filename) 2094 fileinfo = FileInfo(filename)
2045 2095
2046 # get rid of comments 2096 line = clean_lines.lines[linenum]
2047 comment_elided_line = clean_lines.lines[linenum]
2048 2097
2049 # "include" should use the new style "foo/bar.h" instead of just "bar.h" 2098 # "include" should use the new style "foo/bar.h" instead of just "bar.h"
2050 if _RE_PATTERN_INCLUDE_NEW_STYLE.search(comment_elided_line): 2099 if _RE_PATTERN_INCLUDE_NEW_STYLE.search(line):
2051 error(filename, linenum, 'build/include', 4, 2100 error(filename, linenum, 'build/include', 4,
2052 'Include the directory when naming .h files') 2101 'Include the directory when naming .h files')
2053 2102
2054 # we shouldn't include a file more than once. actually, there are a 2103 # we shouldn't include a file more than once. actually, there are a
2055 # handful of instances where doing so is okay, but in general it's 2104 # handful of instances where doing so is okay, but in general it's
2056 # not. 2105 # not.
2057 match = _RE_PATTERN_INCLUDE.search(comment_elided_line) 2106 match = _RE_PATTERN_INCLUDE.search(line)
2058 if match: 2107 if match:
2059 include = match.group(2) 2108 include = match.group(2)
2060 is_system = (match.group(1) == '<') 2109 is_system = (match.group(1) == '<')
2061 if include in include_state: 2110 if include in include_state:
2062 error(filename, linenum, 'build/include', 4, 2111 error(filename, linenum, 'build/include', 4,
2063 '"%s" already included at %s:%s' % 2112 '"%s" already included at %s:%s' %
2064 (include, filename, include_state[include])) 2113 (include, filename, include_state[include]))
2065 else: 2114 else:
2066 include_state[include] = linenum 2115 include_state[include] = linenum
2067 2116
2068 # We want to ensure that headers appear in the right order: 2117 # We want to ensure that headers appear in the right order:
2069 # 1) for foo.cc, foo.h (preferred location) 2118 # 1) for foo.cc, foo.h (preferred location)
2070 # 2) c system files 2119 # 2) c system files
2071 # 3) cpp system files 2120 # 3) cpp system files
2072 # 4) for foo.cc, foo.h (deprecated location) 2121 # 4) for foo.cc, foo.h (deprecated location)
2073 # 5) other google headers 2122 # 5) other google headers
2074 # 2123 #
2075 # We classify each include statement as one of those 5 types 2124 # We classify each include statement as one of those 5 types
2076 # using a number of techniques. The include_state object keeps 2125 # using a number of techniques. The include_state object keeps
2077 # track of the highest type seen, and complains if we see a 2126 # track of the highest type seen, and complains if we see a
2078 # lower type after that. 2127 # lower type after that.
2079 error_message = include_state.CheckNextIncludeOrder( 2128 error_message = include_state.CheckNextIncludeOrder(
2080 _ClassifyInclude(fileinfo, include, is_system)) 2129 _ClassifyInclude(fileinfo, include, is_system))
2081 if error_message: 2130 if error_message:
2082 error(filename, linenum, 'build/include_order', 4, 2131 error(filename, linenum, 'build/include_order', 4,
2083 '%s. Should be: %s.h, c system, c++ system, other.' % 2132 '%s. Should be: %s.h, c system, c++ system, other.' %
2084 (error_message, fileinfo.BaseName())) 2133 (error_message, fileinfo.BaseName()))
2085 2134
2135 # Look for any of the stream classes that are part of standard C++.
2136 match = _RE_PATTERN_INCLUDE.match(line)
2137 if match:
2138 include = match.group(2)
2139 if Match(r'(f|ind|io|i|o|parse|pf|stdio|str|)?stream$', include):
2140 # Many unit tests use cout, so we exempt them.
2141 if not _IsTestFilename(filename):
2142 error(filename, linenum, 'readability/streams', 3,
2143 'Streams are highly discouraged.')
2144
2145 def CheckLanguage(filename, clean_lines, linenum, file_extension, include_state,
2146 error):
2147 """Checks rules from the 'C++ language rules' section of cppguide.html.
2148
2149 Some of these rules are hard to test (function overloading, using
2150 uint32 inappropriately), but we do the best we can.
2151
2152 Args:
2153 filename: The name of the current file.
2154 clean_lines: A CleansedLines instance containing the file.
2155 linenum: The number of the line to check.
2156 file_extension: The extension (without the dot) of the filename.
2157 include_state: An _IncludeState instance in which the headers are inserted.
2158 error: The function to call with any errors found.
2159 """
2086 # If the line is empty or consists of entirely a comment, no need to 2160 # If the line is empty or consists of entirely a comment, no need to
2087 # check it. 2161 # check it.
2088 line = clean_lines.elided[linenum] 2162 line = clean_lines.elided[linenum]
2089 if not line: 2163 if not line:
2090 return 2164 return
2091 2165
2166 match = _RE_PATTERN_INCLUDE.search(line)
2167 if match:
2168 CheckIncludeLine(filename, clean_lines, linenum, include_state, error)
2169 return
2170
2092 # Create an extended_line, which is the concatenation of the current and 2171 # Create an extended_line, which is the concatenation of the current and
2093 # next lines, for more effective checking of code that may span more than one 2172 # next lines, for more effective checking of code that may span more than one
2094 # line. 2173 # line.
2095 if linenum + 1 < clean_lines.NumLines(): 2174 if linenum + 1 < clean_lines.NumLines():
2096 extended_line = line + clean_lines.elided[linenum + 1] 2175 extended_line = line + clean_lines.elided[linenum + 1]
2097 else: 2176 else:
2098 extended_line = line 2177 extended_line = line
2099 2178
2100 # Make Windows paths like Unix. 2179 # Make Windows paths like Unix.
2101 fullname = os.path.abspath(filename).replace('\\', '/') 2180 fullname = os.path.abspath(filename).replace('\\', '/')
2102 2181
2103 # TODO(unknown): figure out if they're using default arguments in fn proto. 2182 # TODO(unknown): figure out if they're using default arguments in fn proto.
2104 2183
2105 # Look for any of the stream classes that are part of standard C++.
2106 match = _RE_PATTERN_INCLUDE.match(line)
2107 if match:
2108 include = match.group(2)
2109 if Match(r'(f|ind|io|i|o|parse|pf|stdio|str|)?stream$', include):
2110 # Many unit tests use cout, so we exempt them.
2111 if not _IsTestFilename(filename):
2112 error(filename, linenum, 'readability/streams', 3,
2113 'Streams are highly discouraged.')
2114
2115 # Check for non-const references in functions. This is tricky because & 2184 # Check for non-const references in functions. This is tricky because &
2116 # is also used to take the address of something. We allow <> for templates, 2185 # is also used to take the address of something. We allow <> for templates,
2117 # (ignoring whatever is between the braces) and : for classes. 2186 # (ignoring whatever is between the braces) and : for classes.
2118 # These are complicated re's. They try to capture the following: 2187 # These are complicated re's. They try to capture the following:
2119 # paren (for fn-prototype start), typename, &, varname. For the const 2188 # paren (for fn-prototype start), typename, &, varname. For the const
2120 # version, we're willing for const to be before typename or after 2189 # version, we're willing for const to be before typename or after
2121 # Don't check the implemention on same line. 2190 # Don't check the implemention on same line.
2122 fnline = line.split('{', 1)[0] 2191 fnline = line.split('{', 1)[0]
2123 if (len(re.findall(r'\([^()]*\b(?:[\w:]|<[^()]*>)+(\s?&|&\s?)\w+', fnline)) > 2192 if (len(re.findall(r'\([^()]*\b(?:[\w:]|<[^()]*>)+(\s?&|&\s?)\w+', fnline)) >
2124 len(re.findall(r'\([^()]*\bconst\s+(?:typename\s+)?(?:struct\s+)?' 2193 len(re.findall(r'\([^()]*\bconst\s+(?:typename\s+)?(?:struct\s+)?'
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after
2421 ) 2490 )
2422 2491
2423 _HEADERS_ACCEPTED_BUT_NOT_PROMOTED = { 2492 _HEADERS_ACCEPTED_BUT_NOT_PROMOTED = {
2424 # We can trust with reasonable confidence that map gives us pair<>, too. 2493 # We can trust with reasonable confidence that map gives us pair<>, too.
2425 'pair<>': ('map', 'multimap', 'hash_map', 'hash_multimap') 2494 'pair<>': ('map', 'multimap', 'hash_map', 'hash_multimap')
2426 } 2495 }
2427 2496
2428 _RE_PATTERN_STRING = re.compile(r'\bstring\b') 2497 _RE_PATTERN_STRING = re.compile(r'\bstring\b')
2429 2498
2430 _re_pattern_algorithm_header = [] 2499 _re_pattern_algorithm_header = []
2431 for _template in ('copy', 'max', 'min', 'sort', 'swap'): 2500 for _template in ('copy', 'max', 'min', 'min_element', 'sort', 'swap',
2501 'transform'):
2432 # Match max<type>(..., ...), max(..., ...), but not foo->max, foo.max or 2502 # Match max<type>(..., ...), max(..., ...), but not foo->max, foo.max or
2433 # type::max(). 2503 # type::max().
2434 _re_pattern_algorithm_header.append( 2504 _re_pattern_algorithm_header.append(
2435 (re.compile(r'[^>.]\b' + _template + r'(<.*?>)?\([^\)]'), 2505 (re.compile(r'[^>.]\b' + _template + r'(<.*?>)?\([^\)]'),
2436 _template, 2506 _template,
2437 '<algorithm>')) 2507 '<algorithm>'))
2438 2508
2439 _re_pattern_templates = [] 2509 _re_pattern_templates = []
2440 for _header, _templates in _HEADERS_CONTAINING_TEMPLATES: 2510 for _header, _templates in _HEADERS_CONTAINING_TEMPLATES:
2441 for _template in _templates: 2511 for _template in _templates:
2442 _re_pattern_templates.append( 2512 _re_pattern_templates.append(
2443 (re.compile(r'(\<|\b)' + _template + r'\s*\<'), 2513 (re.compile(r'(\<|\b)' + _template + r'\s*\<'),
2444 _template + '<>', 2514 _template + '<>',
2445 _header)) 2515 _header))
2446 2516
2447 2517
2448 def CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error): 2518 def FilesBelongToSameModule(filename_cc, filename_h):
2519 """Check if these two filenames belong to the same module.
2520
2521 The concept of a 'module' here is a as follows:
2522 foo.h, foo-inl.h, foo.cc, foo_test.cc and foo_unittest.cc belong to the
2523 same 'module' if they are in the same directory.
2524 some/path/public/xyzzy and some/path/internal/xyzzy are also considered
2525 to belong to the same module here.
2526
2527 If the filename_cc contains a longer path than the filename_h, for example,
2528 '/absolute/path/to/base/sysinfo.cc', and this file would include
2529 'base/sysinfo.h', this function also produces the prefix needed to open the
2530 header. This is used by the caller of this function to more robustly open the
2531 header file. We don't have access to the real include paths in this context,
2532 so we need this guesswork here.
2533
2534 Known bugs: tools/base/bar.cc and base/bar.h belong to the same module
2535 according to this implementation. Because of this, this function gives
2536 some false positives. This should be sufficiently rare in practice.
2537
2538 Args:
2539 filename_cc: is the path for the .cc file
2540 filename_h: is the path for the header path
2541
2542 Returns:
2543 Tuple with a bool and a string:
2544 bool: True if filename_cc and filename_h belong to the same module.
2545 string: the additional prefix needed to open the header file.
2546 """
2547
2548 if not filename_cc.endswith('.cc'):
2549 return (False, '')
2550 filename_cc = filename_cc[:-len('.cc')]
2551 if filename_cc.endswith('_unittest'):
2552 filename_cc = filename_cc[:-len('_unittest')]
2553 elif filename_cc.endswith('_test'):
2554 filename_cc = filename_cc[:-len('_test')]
2555 filename_cc = filename_cc.replace('/public/', '/')
2556 filename_cc = filename_cc.replace('/internal/', '/')
2557
2558 if not filename_h.endswith('.h'):
2559 return (False, '')
2560 filename_h = filename_h[:-len('.h')]
2561 if filename_h.endswith('-inl'):
2562 filename_h = filename_h[:-len('-inl')]
2563 filename_h = filename_h.replace('/public/', '/')
2564 filename_h = filename_h.replace('/internal/', '/')
2565
2566 files_belong_to_same_module = filename_cc.endswith(filename_h)
2567 common_path = ''
2568 if files_belong_to_same_module:
2569 common_path = filename_cc[:-len(filename_h)]
2570 return files_belong_to_same_module, common_path
2571
2572
2573 def UpdateIncludeState(filename, include_state, io=codecs):
2574 """Fill up the include_state with new includes found from the file.
2575
2576 Args:
2577 filename: the name of the header to read.
2578 include_state: an _IncludeState instance in which the headers are inserted.
2579 io: The io factory to use to read the file. Provided for testability.
2580
2581 Returns:
2582 True if a header was succesfully added. False otherwise.
2583 """
2584 headerfile = None
2585 try:
2586 headerfile = io.open(filename, 'r', 'utf8', 'replace')
2587 except IOError:
2588 return False
2589 linenum = 0
2590 for line in headerfile:
2591 linenum += 1
2592 clean_line = CleanseComments(line)
2593 match = _RE_PATTERN_INCLUDE.search(clean_line)
2594 if match:
2595 include = match.group(2)
2596 # The value formatting is cute, but not really used right now.
2597 # What matters here is that the key is in include_state.
2598 include_state.setdefault(include, '%s:%d' % (filename, linenum))
2599 return True
2600
2601
2602 def CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error,
2603 io=codecs):
2449 """Reports for missing stl includes. 2604 """Reports for missing stl includes.
2450 2605
2451 This function will output warnings to make sure you are including the headers 2606 This function will output warnings to make sure you are including the headers
2452 necessary for the stl containers and functions that you use. We only give one 2607 necessary for the stl containers and functions that you use. We only give one
2453 reason to include a header. For example, if you use both equal_to<> and 2608 reason to include a header. For example, if you use both equal_to<> and
2454 less<> in a .h file, only one (the latter in the file) of these will be 2609 less<> in a .h file, only one (the latter in the file) of these will be
2455 reported as a reason to include the <functional>. 2610 reported as a reason to include the <functional>.
2456 2611
2457 We only check headers. We do not check inside cc-files. .cc files should be
2458 able to depend on their respective header files for includes. However, there
2459 is no simple way of producing this logic here.
2460
2461 Args: 2612 Args:
2462 filename: The name of the current file. 2613 filename: The name of the current file.
2463 clean_lines: A CleansedLines instance containing the file. 2614 clean_lines: A CleansedLines instance containing the file.
2464 include_state: An _IncludeState instance. 2615 include_state: An _IncludeState instance.
2465 error: The function to call with any errors found. 2616 error: The function to call with any errors found.
2617 io: The IO factory to use to read the header file. Provided for unittest
2618 injection.
2466 """ 2619 """
2467 if filename.endswith('.cc'):
2468 return
2469
2470 required = {} # A map of header name to linenumber and the template entity. 2620 required = {} # A map of header name to linenumber and the template entity.
2471 # Example of required: { '<functional>': (1219, 'less<>') } 2621 # Example of required: { '<functional>': (1219, 'less<>') }
2472 2622
2473 for linenum in xrange(clean_lines.NumLines()): 2623 for linenum in xrange(clean_lines.NumLines()):
2474 line = clean_lines.elided[linenum] 2624 line = clean_lines.elided[linenum]
2475 if not line or line[0] == '#': 2625 if not line or line[0] == '#':
2476 continue 2626 continue
2477 2627
2478 # String is special -- it is a non-templatized type in STL. 2628 # String is special -- it is a non-templatized type in STL.
2479 if _RE_PATTERN_STRING.search(line): 2629 if _RE_PATTERN_STRING.search(line):
2480 required['<string>'] = (linenum, 'string') 2630 required['<string>'] = (linenum, 'string')
2481 2631
2482 for pattern, template, header in _re_pattern_algorithm_header: 2632 for pattern, template, header in _re_pattern_algorithm_header:
2483 if pattern.search(line): 2633 if pattern.search(line):
2484 required[header] = (linenum, template) 2634 required[header] = (linenum, template)
2485 2635
2486 # The following function is just a speed up, no semantics are changed. 2636 # The following function is just a speed up, no semantics are changed.
2487 if not '<' in line: # Reduces the cpu time usage by skipping lines. 2637 if not '<' in line: # Reduces the cpu time usage by skipping lines.
2488 continue 2638 continue
2489 2639
2490 for pattern, template, header in _re_pattern_templates: 2640 for pattern, template, header in _re_pattern_templates:
2491 if pattern.search(line): 2641 if pattern.search(line):
2492 required[header] = (linenum, template) 2642 required[header] = (linenum, template)
2493 2643
2644 # The policy is that if you #include something in foo.h you don't need to
2645 # include it again in foo.cc. Here, we will look at possible includes.
2646 # Let's copy the include_state so it is only messed up within this function.
2647 include_state = include_state.copy()
2648
2649 # Did we find the header for this file (if any) and succesfully load it?
2650 header_found = False
2651
2652 # Use the absolute path so that matching works properly.
2653 abs_filename = os.path.abspath(filename)
2654
2655 # For Emacs's flymake.
2656 # If cpplint is invoked from Emacs's flymake, a temporary file is generated
2657 # by flymake and that file name might end with '_flymake.cc'. In that case,
2658 # restore original file name here so that the corresponding header file can be
2659 # found.
2660 # e.g. If the file name is 'foo_flymake.cc', we should search for 'foo.h'
2661 # instead of 'foo_flymake.h'
2662 emacs_flymake_suffix = '_flymake.cc'
2663 if abs_filename.endswith(emacs_flymake_suffix):
2664 abs_filename = abs_filename[:-len(emacs_flymake_suffix)] + '.cc'
2665
2666 # include_state is modified during iteration, so we iterate over a copy of
2667 # the keys.
2668 for header in include_state.keys(): #NOLINT
2669 (same_module, common_path) = FilesBelongToSameModule(abs_filename, header)
2670 fullpath = common_path + header
2671 if same_module and UpdateIncludeState(fullpath, include_state, io):
2672 header_found = True
2673
2674 # If we can't find the header file for a .cc, assume it's because we don't
2675 # know where to look. In that case we'll give up as we're not sure they
2676 # didn't include it in the .h file.
2677 # TODO(unknown): Do a better job of finding .h files so we are confident that
2678 # not having the .h file means there isn't one.
2679 if filename.endswith('.cc') and not header_found:
2680 return
2681
2494 # All the lines have been processed, report the errors found. 2682 # All the lines have been processed, report the errors found.
2495 for required_header_unstripped in required: 2683 for required_header_unstripped in required:
2496 template = required[required_header_unstripped][1] 2684 template = required[required_header_unstripped][1]
2497 if template in _HEADERS_ACCEPTED_BUT_NOT_PROMOTED: 2685 if template in _HEADERS_ACCEPTED_BUT_NOT_PROMOTED:
2498 headers = _HEADERS_ACCEPTED_BUT_NOT_PROMOTED[template] 2686 headers = _HEADERS_ACCEPTED_BUT_NOT_PROMOTED[template]
2499 if [True for header in headers if header in include_state]: 2687 if [True for header in headers if header in include_state]:
2500 continue 2688 continue
2501 if required_header_unstripped.strip('<>"') not in include_state: 2689 if required_header_unstripped.strip('<>"') not in include_state:
2502 error(filename, required[required_header_unstripped][0], 2690 error(filename, required[required_header_unstripped][0],
2503 'build/include_what_you_use', 4, 2691 'build/include_what_you_use', 4,
(...skipping 23 matching lines...) Expand all
2527 CheckForFunctionLengths(filename, clean_lines, line, function_state, error) 2715 CheckForFunctionLengths(filename, clean_lines, line, function_state, error)
2528 if Search(r'\bNOLINT\b', raw_lines[line]): # ignore nolint lines 2716 if Search(r'\bNOLINT\b', raw_lines[line]): # ignore nolint lines
2529 return 2717 return
2530 CheckForMultilineCommentsAndStrings(filename, clean_lines, line, error) 2718 CheckForMultilineCommentsAndStrings(filename, clean_lines, line, error)
2531 CheckStyle(filename, clean_lines, line, file_extension, error) 2719 CheckStyle(filename, clean_lines, line, file_extension, error)
2532 CheckLanguage(filename, clean_lines, line, file_extension, include_state, 2720 CheckLanguage(filename, clean_lines, line, file_extension, include_state,
2533 error) 2721 error)
2534 CheckForNonStandardConstructs(filename, clean_lines, line, 2722 CheckForNonStandardConstructs(filename, clean_lines, line,
2535 class_state, error) 2723 class_state, error)
2536 CheckPosixThreading(filename, clean_lines, line, error) 2724 CheckPosixThreading(filename, clean_lines, line, error)
2725 CheckInvalidIncrement(filename, clean_lines, line, error)
2537 2726
2538 2727
2539 def ProcessFileData(filename, file_extension, lines, error): 2728 def ProcessFileData(filename, file_extension, lines, error):
2540 """Performs lint checks and reports any errors to the given error function. 2729 """Performs lint checks and reports any errors to the given error function.
2541 2730
2542 Args: 2731 Args:
2543 filename: Filename of the file that is being processed. 2732 filename: Filename of the file that is being processed.
2544 file_extension: The extension (dot not included) of the file. 2733 file_extension: The extension (dot not included) of the file.
2545 lines: An array of strings, each representing a line of the file, with the 2734 lines: An array of strings, each representing a line of the file, with the
2546 last element being empty if the file is termined with a newline. 2735 last element being empty if the file is termined with a newline.
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
2684 if opt == '--help': 2873 if opt == '--help':
2685 PrintUsage(None) 2874 PrintUsage(None)
2686 elif opt == '--output': 2875 elif opt == '--output':
2687 if not val in ('emacs', 'vs7'): 2876 if not val in ('emacs', 'vs7'):
2688 PrintUsage('The only allowed output formats are emacs and vs7.') 2877 PrintUsage('The only allowed output formats are emacs and vs7.')
2689 output_format = val 2878 output_format = val
2690 elif opt == '--verbose': 2879 elif opt == '--verbose':
2691 verbosity = int(val) 2880 verbosity = int(val)
2692 elif opt == '--filter': 2881 elif opt == '--filter':
2693 filters = val 2882 filters = val
2694 if filters == '': 2883 if not filters:
2695 PrintCategories() 2884 PrintCategories()
2696 2885
2697 if not filenames: 2886 if not filenames:
2698 PrintUsage('No files were specified.') 2887 PrintUsage('No files were specified.')
2699 2888
2700 _SetOutputFormat(output_format) 2889 _SetOutputFormat(output_format)
2701 _SetVerboseLevel(verbosity) 2890 _SetVerboseLevel(verbosity)
2702 _SetFilters(filters) 2891 _SetFilters(filters)
2703 2892
2704 return filenames 2893 return filenames
(...skipping 11 matching lines...) Expand all
2716 2905
2717 _cpplint_state.ResetErrorCount() 2906 _cpplint_state.ResetErrorCount()
2718 for filename in filenames: 2907 for filename in filenames:
2719 ProcessFile(filename, _cpplint_state.verbose_level) 2908 ProcessFile(filename, _cpplint_state.verbose_level)
2720 sys.stderr.write('Total errors found: %d\n' % _cpplint_state.error_count) 2909 sys.stderr.write('Total errors found: %d\n' % _cpplint_state.error_count)
2721 sys.exit(_cpplint_state.error_count > 0) 2910 sys.exit(_cpplint_state.error_count > 0)
2722 2911
2723 2912
2724 if __name__ == '__main__': 2913 if __name__ == '__main__':
2725 main() 2914 main()
OLDNEW
« no previous file with comments | « README ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698