OLD | NEW |
1 # -*- coding: utf-8 -*- | 1 # -*- coding: utf-8 -*- |
2 # | 2 # |
3 # Copyright (C) 2009, 2010, 2012 Google Inc. All rights reserved. | 3 # Copyright (C) 2009, 2010, 2012 Google Inc. All rights reserved. |
4 # Copyright (C) 2009 Torch Mobile Inc. | 4 # Copyright (C) 2009 Torch Mobile Inc. |
5 # Copyright (C) 2009 Apple Inc. All rights reserved. | 5 # Copyright (C) 2009 Apple Inc. All rights reserved. |
6 # Copyright (C) 2010 Chris Jerdonek (cjerdonek@webkit.org) | 6 # Copyright (C) 2010 Chris Jerdonek (cjerdonek@webkit.org) |
7 # | 7 # |
8 # Redistribution and use in source and binary forms, with or without | 8 # Redistribution and use in source and binary forms, with or without |
9 # modification, are permitted provided that the following conditions are | 9 # modification, are permitted provided that the following conditions are |
10 # met: | 10 # met: |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
49 from webkitpy.common.system.filesystem import FileSystem | 49 from webkitpy.common.system.filesystem import FileSystem |
50 | 50 |
51 # Headers that we consider STL headers. | 51 # Headers that we consider STL headers. |
52 _STL_HEADERS = frozenset([ | 52 _STL_HEADERS = frozenset([ |
53 'algobase.h', 'algorithm', 'alloc.h', 'bitset', 'deque', 'exception', | 53 'algobase.h', 'algorithm', 'alloc.h', 'bitset', 'deque', 'exception', |
54 'function.h', 'functional', 'hash_map', 'hash_map.h', 'hash_set', | 54 'function.h', 'functional', 'hash_map', 'hash_map.h', 'hash_set', |
55 'hash_set.h', 'iterator', 'list', 'list.h', 'map', 'memory', 'pair.h', | 55 'hash_set.h', 'iterator', 'list', 'list.h', 'map', 'memory', 'pair.h', |
56 'pthread_alloc', 'queue', 'set', 'set.h', 'sstream', 'stack', | 56 'pthread_alloc', 'queue', 'set', 'set.h', 'sstream', 'stack', |
57 'stl_alloc.h', 'stl_relops.h', 'type_traits.h', | 57 'stl_alloc.h', 'stl_relops.h', 'type_traits.h', |
58 'utility', 'vector', 'vector.h', | 58 'utility', 'vector', 'vector.h', |
59 ]) | 59 ]) |
60 | 60 |
61 | 61 |
62 # Non-STL C++ system headers. | 62 # Non-STL C++ system headers. |
63 _CPP_HEADERS = frozenset([ | 63 _CPP_HEADERS = frozenset([ |
64 'algo.h', 'builtinbuf.h', 'bvector.h', 'cassert', 'cctype', | 64 'algo.h', 'builtinbuf.h', 'bvector.h', 'cassert', 'cctype', |
65 'cerrno', 'cfloat', 'ciso646', 'climits', 'clocale', 'cmath', | 65 'cerrno', 'cfloat', 'ciso646', 'climits', 'clocale', 'cmath', |
66 'complex', 'complex.h', 'csetjmp', 'csignal', 'cstdarg', 'cstddef', | 66 'complex', 'complex.h', 'csetjmp', 'csignal', 'cstdarg', 'cstddef', |
67 'cstdio', 'cstdlib', 'cstring', 'ctime', 'cwchar', 'cwctype', | 67 'cstdio', 'cstdlib', 'cstring', 'ctime', 'cwchar', 'cwctype', |
68 'defalloc.h', 'deque.h', 'editbuf.h', 'exception', 'fstream', | 68 'defalloc.h', 'deque.h', 'editbuf.h', 'exception', 'fstream', |
69 'fstream.h', 'hashtable.h', 'heap.h', 'indstream.h', 'iomanip', | 69 'fstream.h', 'hashtable.h', 'heap.h', 'indstream.h', 'iomanip', |
70 'iomanip.h', 'ios', 'iosfwd', 'iostream', 'iostream.h', 'istream.h', | 70 'iomanip.h', 'ios', 'iosfwd', 'iostream', 'iostream.h', 'istream.h', |
71 'iterator.h', 'limits', 'map.h', 'multimap.h', 'multiset.h', | 71 'iterator.h', 'limits', 'map.h', 'multimap.h', 'multiset.h', |
72 'numeric', 'ostream.h', 'parsestream.h', 'pfstream.h', 'PlotFile.h', | 72 'numeric', 'ostream.h', 'parsestream.h', 'pfstream.h', 'PlotFile.h', |
73 'procbuf.h', 'pthread_alloc.h', 'rope', 'rope.h', 'ropeimpl.h', | 73 'procbuf.h', 'pthread_alloc.h', 'rope', 'rope.h', 'ropeimpl.h', |
74 'SFile.h', 'slist', 'slist.h', 'stack.h', 'stdexcept', | 74 'SFile.h', 'slist', 'slist.h', 'stack.h', 'stdexcept', |
75 'stdiostream.h', 'streambuf.h', 'stream.h', 'strfile.h', 'string', | 75 'stdiostream.h', 'streambuf.h', 'stream.h', 'strfile.h', 'string', |
76 'strstream', 'strstream.h', 'tempbuf.h', 'tree.h', 'typeinfo', 'valarray', | 76 'strstream', 'strstream.h', 'tempbuf.h', 'tree.h', 'typeinfo', 'valarray', |
77 ]) | 77 ]) |
78 | 78 |
79 | 79 |
80 # Assertion macros. These are defined in base/logging.h and | 80 # Assertion macros. These are defined in base/logging.h and |
81 # testing/base/gunit.h. Note that the _M versions need to come first | 81 # testing/base/gunit.h. Note that the _M versions need to come first |
82 # for substring matching to work. | 82 # for substring matching to work. |
83 _CHECK_MACROS = [ | 83 _CHECK_MACROS = [ |
84 'DCHECK', 'CHECK', | 84 'DCHECK', 'CHECK', |
85 'EXPECT_TRUE_M', 'EXPECT_TRUE', | 85 'EXPECT_TRUE_M', 'EXPECT_TRUE', |
86 'ASSERT_TRUE_M', 'ASSERT_TRUE', | 86 'ASSERT_TRUE_M', 'ASSERT_TRUE', |
87 'EXPECT_FALSE_M', 'EXPECT_FALSE', | 87 'EXPECT_FALSE_M', 'EXPECT_FALSE', |
88 'ASSERT_FALSE_M', 'ASSERT_FALSE', | 88 'ASSERT_FALSE_M', 'ASSERT_FALSE', |
89 ] | 89 ] |
90 | 90 |
91 # Replacement macros for CHECK/DCHECK/EXPECT_TRUE/EXPECT_FALSE | 91 # Replacement macros for CHECK/DCHECK/EXPECT_TRUE/EXPECT_FALSE |
92 _CHECK_REPLACEMENT = dict([(m, {}) for m in _CHECK_MACROS]) | 92 _CHECK_REPLACEMENT = dict([(m, {}) for m in _CHECK_MACROS]) |
93 | 93 |
94 for op, replacement in [('==', 'EQ'), ('!=', 'NE'), | 94 for op, replacement in [('==', 'EQ'), ('!=', 'NE'), |
95 ('>=', 'GE'), ('>', 'GT'), | 95 ('>=', 'GE'), ('>', 'GT'), |
96 ('<=', 'LE'), ('<', 'LT')]: | 96 ('<=', 'LE'), ('<', 'LT')]: |
97 _CHECK_REPLACEMENT['DCHECK'][op] = 'DCHECK_%s' % replacement | 97 _CHECK_REPLACEMENT['DCHECK'][op] = 'DCHECK_%s' % replacement |
98 _CHECK_REPLACEMENT['CHECK'][op] = 'CHECK_%s' % replacement | 98 _CHECK_REPLACEMENT['CHECK'][op] = 'CHECK_%s' % replacement |
99 _CHECK_REPLACEMENT['EXPECT_TRUE'][op] = 'EXPECT_%s' % replacement | 99 _CHECK_REPLACEMENT['EXPECT_TRUE'][op] = 'EXPECT_%s' % replacement |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
199 if found_match: | 199 if found_match: |
200 return Position(current_row, starting_offset + found_match.start()) | 200 return Position(current_row, starting_offset + found_match.start()) |
201 | 201 |
202 # A match was not found so continue forward. | 202 # A match was not found so continue forward. |
203 current_row += 1 | 203 current_row += 1 |
204 starting_offset = 0 | 204 starting_offset = 0 |
205 if current_row >= len(lines): | 205 if current_row >= len(lines): |
206 return not_found_position | 206 return not_found_position |
207 current_line = lines[current_row] | 207 current_line = lines[current_row] |
208 | 208 |
| 209 |
209 def _rfind_in_lines(regex, lines, start_position, not_found_position): | 210 def _rfind_in_lines(regex, lines, start_position, not_found_position): |
210 """Does a reverse find starting at start position and going backwards until | 211 """Does a reverse find starting at start position and going backwards until |
211 a match is found. | 212 a match is found. |
212 | 213 |
213 Returns the position where the regex ended. | 214 Returns the position where the regex ended. |
214 """ | 215 """ |
215 # Put the regex in a group and proceed it with a greedy expression that | 216 # Put the regex in a group and proceed it with a greedy expression that |
216 # matches anything to ensure that we get the last possible match in a line. | 217 # matches anything to ensure that we get the last possible match in a line. |
217 last_in_line_regex = r'.*(' + regex + ')' | 218 last_in_line_regex = r'.*(' + regex + ')' |
218 current_row = start_position.row | 219 current_row = start_position.row |
(...skipping 25 matching lines...) Expand all Loading... |
244 # (This puts an underscore before A in isA but not A in CBA). | 245 # (This puts an underscore before A in isA but not A in CBA). |
245 text = sub(r'(?<=[a-z0-9])([A-Z])(?=\b)', r'_\1', text) | 246 text = sub(r'(?<=[a-z0-9])([A-Z])(?=\b)', r'_\1', text) |
246 | 247 |
247 # Next add underscores when you have a captial letter which is followed by a
capital letter | 248 # Next add underscores when you have a captial letter which is followed by a
capital letter |
248 # but is not proceeded by one. (This puts an underscore before A in 'WordADa
y'). | 249 # but is not proceeded by one. (This puts an underscore before A in 'WordADa
y'). |
249 text = sub(r'(?<=[a-z0-9])([A-Z][A-Z_])', r'_\1', text) | 250 text = sub(r'(?<=[a-z0-9])([A-Z][A-Z_])', r'_\1', text) |
250 | 251 |
251 return text.lower() | 252 return text.lower() |
252 | 253 |
253 | 254 |
254 | |
255 def _create_acronym(text): | 255 def _create_acronym(text): |
256 """Creates an acronym for the given text.""" | 256 """Creates an acronym for the given text.""" |
257 # Removes all lower case letters except those starting words. | 257 # Removes all lower case letters except those starting words. |
258 text = sub(r'(?<!\b)[a-z]', '', text) | 258 text = sub(r'(?<!\b)[a-z]', '', text) |
259 return text.upper() | 259 return text.upper() |
260 | 260 |
261 | 261 |
262 def up_to_unmatched_closing_paren(s): | 262 def up_to_unmatched_closing_paren(s): |
263 """Splits a string into two parts up to first unmatched ')'. | 263 """Splits a string into two parts up to first unmatched ')'. |
264 | 264 |
265 Args: | 265 Args: |
266 s: a string which is a substring of line after '(' | 266 s: a string which is a substring of line after '(' |
267 (e.g., "a == (b + c))"). | 267 (e.g., "a == (b + c))"). |
268 | 268 |
269 Returns: | 269 Returns: |
270 A pair of strings (prefix before first unmatched ')', | 270 A pair of strings (prefix before first unmatched ')', |
271 remainder of s after first unmatched ')'), e.g., | 271 remainder of s after first unmatched ')'), e.g., |
272 up_to_unmatched_closing_paren("a == (b + c)) { ") | 272 up_to_unmatched_closing_paren("a == (b + c)) { ") |
273 returns "a == (b + c)", " {". | 273 returns "a == (b + c)", " {". |
274 Returns None, None if there is no unmatched ')' | 274 Returns None, None if there is no unmatched ')' |
275 | 275 |
276 """ | 276 """ |
277 i = 1 | 277 i = 1 |
278 for pos, c in enumerate(s): | 278 for pos, c in enumerate(s): |
279 if c == '(': | 279 if c == '(': |
280 i += 1 | 280 i += 1 |
281 elif c == ')': | 281 elif c == ')': |
282 i -= 1 | 282 i -= 1 |
283 if i == 0: | 283 if i == 0: |
284 return s[:pos], s[pos + 1:] | 284 return s[:pos], s[pos + 1:] |
285 return None, None | 285 return None, None |
286 | 286 |
| 287 |
287 class _IncludeState(dict): | 288 class _IncludeState(dict): |
288 """Tracks line numbers for includes, and the order in which includes appear. | 289 """Tracks line numbers for includes, and the order in which includes appear. |
289 | 290 |
290 As a dict, an _IncludeState object serves as a mapping between include | 291 As a dict, an _IncludeState object serves as a mapping between include |
291 filename and line number on which that file was included. | 292 filename and line number on which that file was included. |
292 | 293 |
293 Call check_next_include_order() once for each header in the file, passing | 294 Call check_next_include_order() once for each header in the file, passing |
294 in the type constants defined above. Calls in an illegal order will | 295 in the type constants defined above. Calls in an illegal order will |
295 raise an _IncludeError with an appropriate error message. | 296 raise an _IncludeError with an appropriate error message. |
296 | 297 |
297 """ | 298 """ |
298 # self._section will move monotonically through this set. If it ever | 299 # self._section will move monotonically through this set. If it ever |
299 # needs to move backwards, check_next_include_order will raise an error. | 300 # needs to move backwards, check_next_include_order will raise an error. |
300 _INITIAL_SECTION = 0 | 301 _INITIAL_SECTION = 0 |
301 _PRIMARY_SECTION = 1 | 302 _PRIMARY_SECTION = 1 |
302 _OTHER_SECTION = 2 | 303 _OTHER_SECTION = 2 |
303 | 304 |
304 _TYPE_NAMES = { | 305 _TYPE_NAMES = { |
305 _PRIMARY_HEADER: 'header this file implements', | 306 _PRIMARY_HEADER: 'header this file implements', |
306 _OTHER_HEADER: 'other header', | 307 _OTHER_HEADER: 'other header', |
307 _MOC_HEADER: 'moc file', | 308 _MOC_HEADER: 'moc file', |
308 } | 309 } |
309 _SECTION_NAMES = { | 310 _SECTION_NAMES = { |
310 _INITIAL_SECTION: "... nothing.", | 311 _INITIAL_SECTION: "... nothing.", |
311 _PRIMARY_SECTION: 'a header this file implements.', | 312 _PRIMARY_SECTION: 'a header this file implements.', |
312 _OTHER_SECTION: 'other header.', | 313 _OTHER_SECTION: 'other header.', |
313 } | 314 } |
314 | 315 |
315 def __init__(self): | 316 def __init__(self): |
316 dict.__init__(self) | 317 dict.__init__(self) |
317 self._section = self._INITIAL_SECTION | 318 self._section = self._INITIAL_SECTION |
318 self._visited_primary_section = False | 319 self._visited_primary_section = False |
319 self.header_types = dict(); | 320 self.header_types = dict() |
320 | 321 |
321 def visited_primary_section(self): | 322 def visited_primary_section(self): |
322 return self._visited_primary_section | 323 return self._visited_primary_section |
323 | 324 |
324 def check_next_include_order(self, header_type, file_is_header, primary_head
er_exists): | 325 def check_next_include_order(self, header_type, file_is_header, primary_head
er_exists): |
325 """Returns a non-empty error message if the next header is out of order. | 326 """Returns a non-empty error message if the next header is out of order. |
326 | 327 |
327 This function also updates the internal state to be ready to check | 328 This function also updates the internal state to be ready to check |
328 the next include. | 329 the next include. |
329 | 330 |
(...skipping 10 matching lines...) Expand all Loading... |
340 return 'Header file should not contain itself.' | 341 return 'Header file should not contain itself.' |
341 if header_type == _MOC_HEADER: | 342 if header_type == _MOC_HEADER: |
342 return '' | 343 return '' |
343 | 344 |
344 error_message = '' | 345 error_message = '' |
345 if self._section != self._OTHER_SECTION: | 346 if self._section != self._OTHER_SECTION: |
346 before_error_message = ('Found %s before %s' % | 347 before_error_message = ('Found %s before %s' % |
347 (self._TYPE_NAMES[header_type], | 348 (self._TYPE_NAMES[header_type], |
348 self._SECTION_NAMES[self._section + 1])) | 349 self._SECTION_NAMES[self._section + 1])) |
349 after_error_message = ('Found %s after %s' % | 350 after_error_message = ('Found %s after %s' % |
350 (self._TYPE_NAMES[header_type], | 351 (self._TYPE_NAMES[header_type], |
351 self._SECTION_NAMES[self._section])) | 352 self._SECTION_NAMES[self._section])) |
352 | 353 |
353 if header_type == _PRIMARY_HEADER: | 354 if header_type == _PRIMARY_HEADER: |
354 if self._section >= self._PRIMARY_SECTION: | 355 if self._section >= self._PRIMARY_SECTION: |
355 error_message = after_error_message | 356 error_message = after_error_message |
356 self._section = self._PRIMARY_SECTION | 357 self._section = self._PRIMARY_SECTION |
357 self._visited_primary_section = True | 358 self._visited_primary_section = True |
358 else: | 359 else: |
359 assert header_type == _OTHER_HEADER | 360 assert header_type == _OTHER_HEADER |
360 if not file_is_header and self._section < self._PRIMARY_SECTION: | 361 if not file_is_header and self._section < self._PRIMARY_SECTION: |
361 if primary_header_exists: | 362 if primary_header_exists: |
362 error_message = before_error_message | 363 error_message = before_error_message |
363 self._section = self._OTHER_SECTION | 364 self._section = self._OTHER_SECTION |
364 | 365 |
365 return error_message | 366 return error_message |
366 | 367 |
367 | 368 |
368 class Position(object): | 369 class Position(object): |
369 """Holds the position of something.""" | 370 """Holds the position of something.""" |
| 371 |
370 def __init__(self, row, column): | 372 def __init__(self, row, column): |
371 self.row = row | 373 self.row = row |
372 self.column = column | 374 self.column = column |
373 | 375 |
374 def __str__(self): | 376 def __str__(self): |
375 return '(%s, %s)' % (self.row, self.column) | 377 return '(%s, %s)' % (self.row, self.column) |
376 | 378 |
377 def __cmp__(self, other): | 379 def __cmp__(self, other): |
378 return self.row.__cmp__(other.row) or self.column.__cmp__(other.column) | 380 return self.row.__cmp__(other.row) or self.column.__cmp__(other.column) |
379 | 381 |
380 | 382 |
381 class Parameter(object): | 383 class Parameter(object): |
382 """Information about one function parameter.""" | 384 """Information about one function parameter.""" |
| 385 |
383 def __init__(self, parameter, parameter_name_index, row): | 386 def __init__(self, parameter, parameter_name_index, row): |
384 self.type = parameter[:parameter_name_index].strip() | 387 self.type = parameter[:parameter_name_index].strip() |
385 # Remove any initializers from the parameter name (e.g. int i = 5). | 388 # Remove any initializers from the parameter name (e.g. int i = 5). |
386 self.name = sub(r'=.*', '', parameter[parameter_name_index:]).strip() | 389 self.name = sub(r'=.*', '', parameter[parameter_name_index:]).strip() |
387 self.row = row | 390 self.row = row |
388 | 391 |
389 @memoized | 392 @memoized |
390 def lower_with_underscores_name(self): | 393 def lower_with_underscores_name(self): |
391 """Returns the parameter name in the lower with underscores format.""" | 394 """Returns the parameter name in the lower with underscores format.""" |
392 return _convert_to_lower_with_underscores(self.name) | 395 return _convert_to_lower_with_underscores(self.name) |
393 | 396 |
394 | 397 |
395 class SingleLineView(object): | 398 class SingleLineView(object): |
396 """Converts multiple lines into a single line (with line breaks replaced by
a | 399 """Converts multiple lines into a single line (with line breaks replaced by
a |
397 space) to allow for easier searching.""" | 400 space) to allow for easier searching.""" |
| 401 |
398 def __init__(self, lines, start_position, end_position): | 402 def __init__(self, lines, start_position, end_position): |
399 """Create a SingleLineView instance. | 403 """Create a SingleLineView instance. |
400 | 404 |
401 Args: | 405 Args: |
402 lines: a list of multiple lines to combine into a single line. | 406 lines: a list of multiple lines to combine into a single line. |
403 start_position: offset within lines of where to start the single line. | 407 start_position: offset within lines of where to start the single line. |
404 end_position: just after where to end (like a slice operation). | 408 end_position: just after where to end (like a slice operation). |
405 """ | 409 """ |
406 # Get the rows of interest. | 410 # Get the rows of interest. |
407 trimmed_lines = lines[start_position.row:end_position.row + 1] | 411 trimmed_lines = lines[start_position.row:end_position.row + 1] |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
542 self.lines_in_function = -1 # Don't count the open brace line. | 546 self.lines_in_function = -1 # Don't count the open brace line. |
543 self.current_function = function_name | 547 self.current_function = function_name |
544 self.function_name_start_position = function_name_start_position | 548 self.function_name_start_position = function_name_start_position |
545 self.body_start_position = body_start_position | 549 self.body_start_position = body_start_position |
546 self.end_position = end_position | 550 self.end_position = end_position |
547 self.is_declaration = clean_lines.elided[body_start_position.row][body_s
tart_position.column] == ';' | 551 self.is_declaration = clean_lines.elided[body_start_position.row][body_s
tart_position.column] == ';' |
548 self.parameter_start_position = parameter_start_position | 552 self.parameter_start_position = parameter_start_position |
549 self.parameter_end_position = parameter_end_position | 553 self.parameter_end_position = parameter_end_position |
550 self.is_pure = False | 554 self.is_pure = False |
551 if self.is_declaration: | 555 if self.is_declaration: |
552 characters_after_parameters = SingleLineView(clean_lines.elided, par
ameter_end_position, body_start_position).single_line | 556 characters_after_parameters = SingleLineView( |
| 557 clean_lines.elided, parameter_end_position, body_start_position)
.single_line |
553 self.is_pure = bool(match(r'\s*=\s*0\s*', characters_after_parameter
s)) | 558 self.is_pure = bool(match(r'\s*=\s*0\s*', characters_after_parameter
s)) |
554 self._clean_lines = clean_lines | 559 self._clean_lines = clean_lines |
555 self._parameter_list = None | 560 self._parameter_list = None |
556 | 561 |
557 def modifiers_and_return_type(self): | 562 def modifiers_and_return_type(self): |
558 """Returns the modifiers and the return type.""" | 563 """Returns the modifiers and the return type.""" |
559 # Go backwards from where the function name is until we encounter one of
several things: | 564 # Go backwards from where the function name is until we encounter one of
several things: |
560 # ';' or '{' or '}' or 'private:', etc. or '#' or return Position(0, 0
) | 565 # ';' or '{' or '}' or 'private:', etc. or '#' or return Position(0, 0
) |
561 elided = self._clean_lines.elided | 566 elided = self._clean_lines.elided |
562 start_modifiers = _rfind_in_lines(r';|\{|\}|((private|public|protected):
)|(#.*)', | 567 start_modifiers = _rfind_in_lines(r';|\{|\}|((private|public|protected):
)|(#.*)', |
563 elided, self.parameter_start_position,
Position(0, 0)) | 568 elided, self.parameter_start_position,
Position(0, 0)) |
564 return SingleLineView(elided, start_modifiers, self.function_name_start_
position).single_line.strip() | 569 return SingleLineView(elided, start_modifiers, self.function_name_start_
position).single_line.strip() |
565 | 570 |
566 def parameter_list(self): | 571 def parameter_list(self): |
567 if not self._parameter_list: | 572 if not self._parameter_list: |
568 # Store the final result as a tuple since that is immutable. | 573 # Store the final result as a tuple since that is immutable. |
569 self._parameter_list = tuple(parameter_list(self._clean_lines.elided
, self.parameter_start_position, self.parameter_end_position)) | 574 self._parameter_list = tuple(parameter_list(self._clean_lines.elided
, |
| 575 self.parameter_start_pos
ition, self.parameter_end_position)) |
570 | 576 |
571 return self._parameter_list | 577 return self._parameter_list |
572 | 578 |
573 def count(self, line_number): | 579 def count(self, line_number): |
574 """Count line in current function body.""" | 580 """Count line in current function body.""" |
575 if self.in_a_function and line_number >= self.body_start_position.row: | 581 if self.in_a_function and line_number >= self.body_start_position.row: |
576 self.lines_in_function += 1 | 582 self.lines_in_function += 1 |
577 | 583 |
578 def check(self, error, line_number): | 584 def check(self, error, line_number): |
579 """Report if too many lines in function body. | 585 """Report if too many lines in function body. |
580 | 586 |
581 Args: | 587 Args: |
582 error: The function to call with any errors found. | 588 error: The function to call with any errors found. |
583 line_number: The number of the line to check. | 589 line_number: The number of the line to check. |
584 """ | 590 """ |
585 if match(r'T(EST|est)', self.current_function): | 591 if match(r'T(EST|est)', self.current_function): |
586 base_trigger = self._TEST_TRIGGER | 592 base_trigger = self._TEST_TRIGGER |
587 else: | 593 else: |
588 base_trigger = self._NORMAL_TRIGGER | 594 base_trigger = self._NORMAL_TRIGGER |
589 trigger = base_trigger * 2 ** self.min_confidence | 595 trigger = base_trigger * 2 ** self.min_confidence |
590 | 596 |
591 if self.lines_in_function > trigger: | 597 if self.lines_in_function > trigger: |
592 error_level = int(math.log(self.lines_in_function / base_trigger, 2)
) | 598 error_level = int(math.log(self.lines_in_function / base_trigger, 2)
) |
593 # 50 => 0, 100 => 1, 200 => 2, 400 => 3, 800 => 4, 1600 => 5, ... | 599 # 50 => 0, 100 => 1, 200 => 2, 400 => 3, 800 => 4, 1600 => 5, ... |
594 if error_level > 5: | 600 if error_level > 5: |
595 error_level = 5 | 601 error_level = 5 |
596 error(line_number, 'readability/fn_size', error_level, | 602 error(line_number, 'readability/fn_size', error_level, |
597 'Small and focused functions are preferred:' | 603 'Small and focused functions are preferred:' |
598 ' %s has %d non-comment lines' | 604 ' %s has %d non-comment lines' |
599 ' (error triggered by exceeding %d lines).' % ( | 605 ' (error triggered by exceeding %d lines).' % ( |
600 self.current_function, self.lines_in_function, trigger)) | 606 self.current_function, self.lines_in_function, trigger)) |
601 | 607 |
602 def end(self): | 608 def end(self): |
603 """Stop analyzing function body.""" | 609 """Stop analyzing function body.""" |
604 self.in_a_function = False | 610 self.in_a_function = False |
605 | 611 |
606 | 612 |
607 class _IncludeError(Exception): | 613 class _IncludeError(Exception): |
608 """Indicates a problem with the include order in a file.""" | 614 """Indicates a problem with the include order in a file.""" |
609 pass | 615 pass |
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
889 if not net_open: | 895 if not net_open: |
890 return Position(line_number, current_column) | 896 return Position(line_number, current_column) |
891 | 897 |
892 # Proceed to the next line. | 898 # Proceed to the next line. |
893 line_number += 1 | 899 line_number += 1 |
894 current_column = 0 | 900 current_column = 0 |
895 | 901 |
896 # The given item was not closed. | 902 # The given item was not closed. |
897 return Position(len(elided), -1) | 903 return Position(len(elided), -1) |
898 | 904 |
| 905 |
899 def check_for_copyright(lines, error): | 906 def check_for_copyright(lines, error): |
900 """Logs an error if no Copyright message appears at the top of the file.""" | 907 """Logs an error if no Copyright message appears at the top of the file.""" |
901 | 908 |
902 # We'll say it should occur by line 10. Don't forget there's a | 909 # We'll say it should occur by line 10. Don't forget there's a |
903 # dummy line at the front. | 910 # dummy line at the front. |
904 for line in xrange(1, min(len(lines), 11)): | 911 for line in xrange(1, min(len(lines), 11)): |
905 if re.search(r'Copyright', lines[line], re.I): | 912 if re.search(r'Copyright', lines[line], re.I): |
906 break | 913 break |
907 else: # means no copyright line was found | 914 else: # means no copyright line was found |
908 error(0, 'legal/copyright', 5, | 915 error(0, 'legal/copyright', 5, |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1087 ('getgrnam(', 'getgrnam_r('), | 1094 ('getgrnam(', 'getgrnam_r('), |
1088 ('getlogin(', 'getlogin_r('), | 1095 ('getlogin(', 'getlogin_r('), |
1089 ('getpwnam(', 'getpwnam_r('), | 1096 ('getpwnam(', 'getpwnam_r('), |
1090 ('getpwuid(', 'getpwuid_r('), | 1097 ('getpwuid(', 'getpwuid_r('), |
1091 ('gmtime(', 'gmtime_r('), | 1098 ('gmtime(', 'gmtime_r('), |
1092 ('localtime(', 'localtime_r('), | 1099 ('localtime(', 'localtime_r('), |
1093 ('rand(', 'rand_r('), | 1100 ('rand(', 'rand_r('), |
1094 ('readdir(', 'readdir_r('), | 1101 ('readdir(', 'readdir_r('), |
1095 ('strtok(', 'strtok_r('), | 1102 ('strtok(', 'strtok_r('), |
1096 ('ttyname(', 'ttyname_r('), | 1103 ('ttyname(', 'ttyname_r('), |
1097 ) | 1104 ) |
1098 | 1105 |
1099 | 1106 |
1100 def check_posix_threading(clean_lines, line_number, error): | 1107 def check_posix_threading(clean_lines, line_number, error): |
1101 """Checks for calls to thread-unsafe functions. | 1108 """Checks for calls to thread-unsafe functions. |
1102 | 1109 |
1103 Much code has been originally written without consideration of | 1110 Much code has been originally written without consideration of |
1104 multi-threading. Also, engineers are relying on their old experience; | 1111 multi-threading. Also, engineers are relying on their old experience; |
1105 they have learned posix before threading extensions were added. These | 1112 they have learned posix before threading extensions were added. These |
1106 tests guide the engineers to use thread-safe functions (when using | 1113 tests guide the engineers to use thread-safe functions (when using |
1107 posix directly). | 1114 posix directly). |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1187 if self.classinfo_stack: | 1194 if self.classinfo_stack: |
1188 # Note: This test can result in false positives if #ifdef constructs | 1195 # Note: This test can result in false positives if #ifdef constructs |
1189 # get in the way of brace matching. See the testBuildClass test in | 1196 # get in the way of brace matching. See the testBuildClass test in |
1190 # cpp_style_unittest.py for an example of this. | 1197 # cpp_style_unittest.py for an example of this. |
1191 error(self.classinfo_stack[0].line_number, 'build/class', 5, | 1198 error(self.classinfo_stack[0].line_number, 'build/class', 5, |
1192 'Failed to find complete declaration of class %s' % | 1199 'Failed to find complete declaration of class %s' % |
1193 self.classinfo_stack[0].name) | 1200 self.classinfo_stack[0].name) |
1194 | 1201 |
1195 | 1202 |
1196 class _FileState(object): | 1203 class _FileState(object): |
| 1204 |
1197 def __init__(self, clean_lines, file_extension): | 1205 def __init__(self, clean_lines, file_extension): |
1198 self._did_inside_namespace_indent_warning = False | 1206 self._did_inside_namespace_indent_warning = False |
1199 self._clean_lines = clean_lines | 1207 self._clean_lines = clean_lines |
1200 if file_extension in ['m', 'mm']: | 1208 if file_extension in ['m', 'mm']: |
1201 self._is_objective_c = True | 1209 self._is_objective_c = True |
1202 self._is_c = False | 1210 self._is_c = False |
1203 elif file_extension == 'h': | 1211 elif file_extension == 'h': |
1204 # In the case of header files, it is unknown if the file | 1212 # In the case of header files, it is unknown if the file |
1205 # is c / objective c or not, so set this value to None and then | 1213 # is c / objective c or not, so set this value to None and then |
1206 # if it is requested, use heuristics to guess the value. | 1214 # if it is requested, use heuristics to guess the value. |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1286 if match(expr_all_uppercase, member): | 1294 if match(expr_all_uppercase, member): |
1287 found_invalid_member = not self.is_webidl_enum | 1295 found_invalid_member = not self.is_webidl_enum |
1288 if match(expr_starts_lowercase, member): | 1296 if match(expr_starts_lowercase, member): |
1289 found_invalid_member = True | 1297 found_invalid_member = True |
1290 if found_invalid_member: | 1298 if found_invalid_member: |
1291 self.is_webidl_enum = False | 1299 self.is_webidl_enum = False |
1292 return False | 1300 return False |
1293 return True | 1301 return True |
1294 return True | 1302 return True |
1295 | 1303 |
| 1304 |
1296 def check_for_non_standard_constructs(clean_lines, line_number, | 1305 def check_for_non_standard_constructs(clean_lines, line_number, |
1297 class_state, error): | 1306 class_state, error): |
1298 """Logs an error if we see certain non-ANSI constructs ignored by gcc-2. | 1307 """Logs an error if we see certain non-ANSI constructs ignored by gcc-2. |
1299 | 1308 |
1300 Complain about several constructs which gcc-2 accepts, but which are | 1309 Complain about several constructs which gcc-2 accepts, but which are |
1301 not standard C++. Warning about these in lint is one way to ease the | 1310 not standard C++. Warning about these in lint is one way to ease the |
1302 transition to new compilers. | 1311 transition to new compilers. |
1303 - put storage class first (e.g. "static const" instead of "const static"). | 1312 - put storage class first (e.g. "static const" instead of "const static"). |
1304 - "%lld" instead of %qd" in printf-type functions. | 1313 - "%lld" instead of %qd" in printf-type functions. |
1305 - "%1$d" is non-standard in printf-type functions. | 1314 - "%1$d" is non-standard in printf-type functions. |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1453 unsigned_list = ', '.join(classinfo.unsigned_bitfields) | 1462 unsigned_list = ', '.join(classinfo.unsigned_bitfields) |
1454 error(classinfo.line_number, 'runtime/bitfields', 5, | 1463 error(classinfo.line_number, 'runtime/bitfields', 5, |
1455 'The class %s contains mixed unsigned and bool bitfields, ' | 1464 'The class %s contains mixed unsigned and bool bitfields, ' |
1456 'which will pack into separate words on the MSVC compiler.\n' | 1465 'which will pack into separate words on the MSVC compiler.\n' |
1457 'Bool bitfields are [%s].\nUnsigned bitfields are [%s].\n' | 1466 'Bool bitfields are [%s].\nUnsigned bitfields are [%s].\n' |
1458 'Consider converting bool bitfields to unsigned.' | 1467 'Consider converting bool bitfields to unsigned.' |
1459 % (classinfo.name, bool_list, unsigned_list)) | 1468 % (classinfo.name, bool_list, unsigned_list)) |
1460 else: | 1469 else: |
1461 classinfo.brace_depth = brace_depth | 1470 classinfo.brace_depth = brace_depth |
1462 | 1471 |
1463 well_typed_bitfield = False; | 1472 well_typed_bitfield = False |
1464 # Look for bool <name> : 1 declarations. | 1473 # Look for bool <name> : 1 declarations. |
1465 args = search(r'\bbool\s+(\S*)\s*:\s*\d+\s*;', line) | 1474 args = search(r'\bbool\s+(\S*)\s*:\s*\d+\s*;', line) |
1466 if args: | 1475 if args: |
1467 classinfo.bool_bitfields.append('%d: %s' % (line_number, args.group(1))) | 1476 classinfo.bool_bitfields.append('%d: %s' % (line_number, args.group(1))) |
1468 well_typed_bitfield = True; | 1477 well_typed_bitfield = True |
1469 | 1478 |
1470 # Look for unsigned <name> : n declarations. | 1479 # Look for unsigned <name> : n declarations. |
1471 args = search(r'\bunsigned\s+(?:int\s+)?(\S+)\s*:\s*\d+\s*;', line) | 1480 args = search(r'\bunsigned\s+(?:int\s+)?(\S+)\s*:\s*\d+\s*;', line) |
1472 if args: | 1481 if args: |
1473 classinfo.unsigned_bitfields.append('%d: %s' % (line_number, args.group(
1))) | 1482 classinfo.unsigned_bitfields.append('%d: %s' % (line_number, args.group(
1))) |
1474 well_typed_bitfield = True; | 1483 well_typed_bitfield = True |
1475 | 1484 |
1476 # Look for other bitfield declarations. We don't care about those in | 1485 # Look for other bitfield declarations. We don't care about those in |
1477 # size-matching structs. | 1486 # size-matching structs. |
1478 if not (well_typed_bitfield or classinfo.name.startswith('SameSizeAs') or | 1487 if not (well_typed_bitfield or classinfo.name.startswith('SameSizeAs') or |
1479 classinfo.name.startswith('Expected')): | 1488 classinfo.name.startswith('Expected')): |
1480 args = match(r'\s*(\S+)\s+(\S+)\s*:\s*\d+\s*;', line) | 1489 args = match(r'\s*(\S+)\s+(\S+)\s*:\s*\d+\s*;', line) |
1481 if args: | 1490 if args: |
1482 error(line_number, 'runtime/bitfields', 4, | 1491 error(line_number, 'runtime/bitfields', 4, |
1483 'Member %s of class %s defined as a bitfield of type %s. ' | 1492 'Member %s of class %s defined as a bitfield of type %s. ' |
1484 'Please declare all bitfields as unsigned.' | 1493 'Please declare all bitfields as unsigned.' |
1485 % (args.group(2), classinfo.name, args.group(1))) | 1494 % (args.group(2), classinfo.name, args.group(1))) |
1486 | 1495 |
| 1496 |
1487 def check_spacing_for_function_call(line, line_number, error): | 1497 def check_spacing_for_function_call(line, line_number, error): |
1488 """Checks for the correctness of various spacing around function calls. | 1498 """Checks for the correctness of various spacing around function calls. |
1489 | 1499 |
1490 Args: | 1500 Args: |
1491 line: The text of the line to check. | 1501 line: The text of the line to check. |
1492 line_number: The number of the line to check. | 1502 line_number: The number of the line to check. |
1493 error: The function to call with any errors found. | 1503 error: The function to call with any errors found. |
1494 """ | 1504 """ |
1495 | 1505 |
1496 # Since function calls often occur inside if/for/foreach/while/switch | 1506 # Since function calls often occur inside if/for/foreach/while/switch |
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1751 elif not file_extension == "h": | 1761 elif not file_extension == "h": |
1752 error(function_state.function_name_start_position.row, 'readability/
webkit_export', 5, | 1762 error(function_state.function_name_start_position.row, 'readability/
webkit_export', 5, |
1753 'WEBKIT_EXPORT should only be used in header files.') | 1763 'WEBKIT_EXPORT should only be used in header files.') |
1754 elif not function_state.is_declaration or search(r'\binline\b', modifier
s_and_return_type): | 1764 elif not function_state.is_declaration or search(r'\binline\b', modifier
s_and_return_type): |
1755 error(function_state.function_name_start_position.row, 'readability/
webkit_export', 5, | 1765 error(function_state.function_name_start_position.row, 'readability/
webkit_export', 5, |
1756 'WEBKIT_EXPORT should not be used on a function with a body.') | 1766 'WEBKIT_EXPORT should not be used on a function with a body.') |
1757 elif function_state.is_pure: | 1767 elif function_state.is_pure: |
1758 error(function_state.function_name_start_position.row, 'readability/
webkit_export', 5, | 1768 error(function_state.function_name_start_position.row, 'readability/
webkit_export', 5, |
1759 'WEBKIT_EXPORT should not be used with a pure virtual function
.') | 1769 'WEBKIT_EXPORT should not be used with a pure virtual function
.') |
1760 | 1770 |
1761 check_function_definition_and_pass_ptr(modifiers_and_return_type, function_s
tate.function_name_start_position.row, 'return', error) | 1771 check_function_definition_and_pass_ptr( |
| 1772 modifiers_and_return_type, function_state.function_name_start_position.r
ow, 'return', error) |
1762 | 1773 |
1763 parameter_list = function_state.parameter_list() | 1774 parameter_list = function_state.parameter_list() |
1764 for parameter in parameter_list: | 1775 for parameter in parameter_list: |
1765 check_function_definition_and_pass_ptr(parameter.type, parameter.row, 'p
arameter', error) | 1776 check_function_definition_and_pass_ptr(parameter.type, parameter.row, 'p
arameter', error) |
1766 | 1777 |
1767 # Do checks specific to function declarations and parameter names. | 1778 # Do checks specific to function declarations and parameter names. |
1768 if not function_state.is_declaration or not parameter.name: | 1779 if not function_state.is_declaration or not parameter.name: |
1769 continue | 1780 continue |
1770 | 1781 |
1771 # Check the parameter name against the function name for single paramete
r set functions. | 1782 # Check the parameter name against the function name for single paramete
r set functions. |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1917 | 1928 |
1918 # Next, we check for proper spacing with respect to comments. | 1929 # Next, we check for proper spacing with respect to comments. |
1919 comment_position = line.find('//') | 1930 comment_position = line.find('//') |
1920 if comment_position != -1: | 1931 if comment_position != -1: |
1921 # Check if the // may be in quotes. If so, ignore it | 1932 # Check if the // may be in quotes. If so, ignore it |
1922 # Comparisons made explicit for clarity | 1933 # Comparisons made explicit for clarity |
1923 if (line.count('"', 0, comment_position) - line.count('\\"', 0, comment_
position)) % 2 == 0: # not in quotes | 1934 if (line.count('"', 0, comment_position) - line.count('\\"', 0, comment_
position)) % 2 == 0: # not in quotes |
1924 # Allow one space before end of line comment. | 1935 # Allow one space before end of line comment. |
1925 if (not match(r'^\s*$', line[:comment_position]) | 1936 if (not match(r'^\s*$', line[:comment_position]) |
1926 and (comment_position >= 1 | 1937 and (comment_position >= 1 |
1927 and ((line[comment_position - 1] not in string.whitespace) | 1938 and ((line[comment_position - 1] not in string.whitespace) |
1928 or (comment_position >= 2 | 1939 or (comment_position >= 2 |
1929 and line[comment_position - 2] in string.whitespace))))
: | 1940 and line[comment_position - 2] in string.whitespac
e)))): |
1930 error(line_number, 'whitespace/comments', 5, | 1941 error(line_number, 'whitespace/comments', 5, |
1931 'One space before end of line comments') | 1942 'One space before end of line comments') |
1932 # There should always be a space between the // and the comment | 1943 # There should always be a space between the // and the comment |
1933 commentend = comment_position + 2 | 1944 commentend = comment_position + 2 |
1934 if commentend < len(line) and not line[commentend] == ' ': | 1945 if commentend < len(line) and not line[commentend] == ' ': |
1935 # but some lines are exceptions -- e.g. if they're big | 1946 # but some lines are exceptions -- e.g. if they're big |
1936 # comment delimiters like: | 1947 # comment delimiters like: |
1937 # //---------------------------------------------------------- | 1948 # //---------------------------------------------------------- |
1938 # or they begin with multiple slashes followed by a space: | 1949 # or they begin with multiple slashes followed by a space: |
1939 # //////// Header comment | 1950 # //////// Header comment |
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2124 | 2135 |
2125 Args: | 2136 Args: |
2126 clean_lines: A CleansedLines instance containing the file. | 2137 clean_lines: A CleansedLines instance containing the file. |
2127 line_number: The number of the line to check. | 2138 line_number: The number of the line to check. |
2128 file_extension: The extension (dot not included) of the file. | 2139 file_extension: The extension (dot not included) of the file. |
2129 file_state: A _FileState instance which maintains information about | 2140 file_state: A _FileState instance which maintains information about |
2130 the state of things in the file. | 2141 the state of things in the file. |
2131 error: The function to call with any errors found. | 2142 error: The function to call with any errors found. |
2132 """ | 2143 """ |
2133 | 2144 |
2134 line = clean_lines.elided[line_number] # Get rid of comments and strings. | 2145 line = clean_lines.elided[line_number] # Get rid of comments and strings. |
2135 | 2146 |
2136 namespace_match = match(r'(?P<namespace_indentation>\s*)namespace\s+\S+\s*{\
s*$', line) | 2147 namespace_match = match(r'(?P<namespace_indentation>\s*)namespace\s+\S+\s*{\
s*$', line) |
2137 if not namespace_match: | 2148 if not namespace_match: |
2138 return | 2149 return |
2139 | 2150 |
2140 current_indentation_level = len(namespace_match.group('namespace_indentation
')) | 2151 current_indentation_level = len(namespace_match.group('namespace_indentation
')) |
2141 if current_indentation_level > 0: | 2152 if current_indentation_level > 0: |
2142 # Don't warn about an indented namespace if we already warned about inde
nted code. | 2153 # Don't warn about an indented namespace if we already warned about inde
nted code. |
2143 if not file_state.did_inside_namespace_indent_warning(): | 2154 if not file_state.did_inside_namespace_indent_warning(): |
2144 error(line_number, 'whitespace/indent', 4, | 2155 error(line_number, 'whitespace/indent', 4, |
2145 'namespace should never be indented.') | 2156 'namespace should never be indented.') |
2146 return | 2157 return |
2147 looking_for_semicolon = False; | 2158 looking_for_semicolon = False |
2148 line_offset = 0 | 2159 line_offset = 0 |
2149 in_preprocessor_directive = False; | 2160 in_preprocessor_directive = False |
2150 for current_line in clean_lines.elided[line_number + 1:]: | 2161 for current_line in clean_lines.elided[line_number + 1:]: |
2151 line_offset += 1 | 2162 line_offset += 1 |
2152 if not current_line.strip(): | 2163 if not current_line.strip(): |
2153 continue | 2164 continue |
2154 if not current_indentation_level: | 2165 if not current_indentation_level: |
2155 if not (in_preprocessor_directive or looking_for_semicolon): | 2166 if not (in_preprocessor_directive or looking_for_semicolon): |
2156 if not match(r'\S', current_line) and not file_state.did_inside_
namespace_indent_warning(): | 2167 if not match(r'\S', current_line) and not file_state.did_inside_
namespace_indent_warning(): |
2157 file_state.set_did_inside_namespace_indent_warning() | 2168 file_state.set_did_inside_namespace_indent_warning() |
2158 error(line_number + line_offset, 'whitespace/indent', 4, | 2169 error(line_number + line_offset, 'whitespace/indent', 4, |
2159 'Code inside a namespace should not be indented.') | 2170 'Code inside a namespace should not be indented.') |
2160 if in_preprocessor_directive or (current_line.strip()[0] == '#'): #
This takes care of preprocessor directive syntax. | 2171 if in_preprocessor_directive or (current_line.strip()[0] == '#'): #
This takes care of preprocessor directive syntax. |
2161 in_preprocessor_directive = current_line[-1] == '\\' | 2172 in_preprocessor_directive = current_line[-1] == '\\' |
2162 else: | 2173 else: |
2163 looking_for_semicolon = ((current_line.find(';') == -1) and (cur
rent_line.strip()[-1] != '}')) or (current_line[-1] == '\\') | 2174 looking_for_semicolon = ((current_line.find(';') == -1) and (cur
rent_line.strip() |
| 2175 [-1
] != '}')) or (current_line[-1] == '\\') |
2164 else: | 2176 else: |
2165 looking_for_semicolon = False; # If we have a brace we may not need
a semicolon. | 2177 looking_for_semicolon = False # If we have a brace we may not need
a semicolon. |
2166 current_indentation_level += current_line.count('{') - current_line.coun
t('}') | 2178 current_indentation_level += current_line.count('{') - current_line.coun
t('}') |
2167 if current_indentation_level < 0: | 2179 if current_indentation_level < 0: |
2168 break; | 2180 break |
2169 | 2181 |
2170 | 2182 |
2171 def check_enum_casing(clean_lines, line_number, enum_state, error): | 2183 def check_enum_casing(clean_lines, line_number, enum_state, error): |
2172 """Looks for incorrectly named enum values. | 2184 """Looks for incorrectly named enum values. |
2173 | 2185 |
2174 Args: | 2186 Args: |
2175 clean_lines: A CleansedLines instance containing the file. | 2187 clean_lines: A CleansedLines instance containing the file. |
2176 line_number: The number of the line to check. | 2188 line_number: The number of the line to check. |
2177 enum_state: A _EnumState instance which maintains enum declaration state. | 2189 enum_state: A _EnumState instance which maintains enum declaration state. |
2178 error: The function to call with any errors found. | 2190 error: The function to call with any errors found. |
2179 """ | 2191 """ |
2180 | 2192 |
2181 enum_state.is_webidl_enum |= bool(match(r'\s*// Web(?:Kit)?IDL enum\s*$', cl
ean_lines.raw_lines[line_number])) | 2193 enum_state.is_webidl_enum |= bool(match(r'\s*// Web(?:Kit)?IDL enum\s*$', cl
ean_lines.raw_lines[line_number])) |
2182 | 2194 |
2183 line = clean_lines.elided[line_number] # Get rid of comments and strings. | 2195 line = clean_lines.elided[line_number] # Get rid of comments and strings. |
2184 if not enum_state.process_clean_line(line): | 2196 if not enum_state.process_clean_line(line): |
2185 error(line_number, 'readability/enum_casing', 4, | 2197 error(line_number, 'readability/enum_casing', 4, |
2186 'enum members should use InterCaps with an initial capital letter.
') | 2198 'enum members should use InterCaps with an initial capital letter.
') |
2187 | 2199 |
| 2200 |
2188 def check_directive_indentation(clean_lines, line_number, file_state, error): | 2201 def check_directive_indentation(clean_lines, line_number, file_state, error): |
2189 """Looks for indentation of preprocessor directives. | 2202 """Looks for indentation of preprocessor directives. |
2190 | 2203 |
2191 Args: | 2204 Args: |
2192 clean_lines: A CleansedLines instance containing the file. | 2205 clean_lines: A CleansedLines instance containing the file. |
2193 line_number: The number of the line to check. | 2206 line_number: The number of the line to check. |
2194 file_state: A _FileState instance which maintains information about | 2207 file_state: A _FileState instance which maintains information about |
2195 the state of things in the file. | 2208 the state of things in the file. |
2196 error: The function to call with any errors found. | 2209 error: The function to call with any errors found. |
2197 """ | 2210 """ |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2238 line_number: The number of the line to check. | 2251 line_number: The number of the line to check. |
2239 file_state: A _FileState instance which maintains information about | 2252 file_state: A _FileState instance which maintains information about |
2240 the state of things in the file. | 2253 the state of things in the file. |
2241 error: The function to call with any errors found. | 2254 error: The function to call with any errors found. |
2242 """ | 2255 """ |
2243 | 2256 |
2244 # This check doesn't apply to C or Objective-C implementation files. | 2257 # This check doesn't apply to C or Objective-C implementation files. |
2245 if file_state.is_c_or_objective_c(): | 2258 if file_state.is_c_or_objective_c(): |
2246 return | 2259 return |
2247 | 2260 |
2248 line = clean_lines.elided[line_number] # Get rid of comments and strings. | 2261 line = clean_lines.elided[line_number] # Get rid of comments and strings. |
2249 | 2262 |
2250 using_std_match = match(r'\s*using\s+std::(?P<method_name>\S+)\s*;\s*$', lin
e) | 2263 using_std_match = match(r'\s*using\s+std::(?P<method_name>\S+)\s*;\s*$', lin
e) |
2251 if not using_std_match: | 2264 if not using_std_match: |
2252 return | 2265 return |
2253 | 2266 |
2254 method_name = using_std_match.group('method_name') | 2267 method_name = using_std_match.group('method_name') |
2255 # Exception for the established idiom for swapping objects in generic code. | 2268 # Exception for the established idiom for swapping objects in generic code. |
2256 if method_name == 'swap': | 2269 if method_name == 'swap': |
2257 return | 2270 return |
2258 error(line_number, 'build/using_std', 4, | 2271 error(line_number, 'build/using_std', 4, |
2259 "Use 'using namespace std;' instead of 'using std::%s;'." % method_nam
e) | 2272 "Use 'using namespace std;' instead of 'using std::%s;'." % method_nam
e) |
2260 | 2273 |
2261 | 2274 |
2262 def check_max_min_macros(clean_lines, line_number, file_state, error): | 2275 def check_max_min_macros(clean_lines, line_number, file_state, error): |
2263 """Looks use of MAX() and MIN() macros that should be replaced with std::max
() and std::min(). | 2276 """Looks use of MAX() and MIN() macros that should be replaced with std::max
() and std::min(). |
2264 | 2277 |
2265 Args: | 2278 Args: |
2266 clean_lines: A CleansedLines instance containing the file. | 2279 clean_lines: A CleansedLines instance containing the file. |
2267 line_number: The number of the line to check. | 2280 line_number: The number of the line to check. |
2268 file_state: A _FileState instance which maintains information about | 2281 file_state: A _FileState instance which maintains information about |
2269 the state of things in the file. | 2282 the state of things in the file. |
2270 error: The function to call with any errors found. | 2283 error: The function to call with any errors found. |
2271 """ | 2284 """ |
2272 | 2285 |
2273 # This check doesn't apply to C or Objective-C implementation files. | 2286 # This check doesn't apply to C or Objective-C implementation files. |
2274 if file_state.is_c_or_objective_c(): | 2287 if file_state.is_c_or_objective_c(): |
2275 return | 2288 return |
2276 | 2289 |
2277 line = clean_lines.elided[line_number] # Get rid of comments and strings. | 2290 line = clean_lines.elided[line_number] # Get rid of comments and strings. |
2278 | 2291 |
2279 max_min_macros_search = search(r'\b(?P<max_min_macro>(MAX|MIN))\s*\(', line) | 2292 max_min_macros_search = search(r'\b(?P<max_min_macro>(MAX|MIN))\s*\(', line) |
2280 if not max_min_macros_search: | 2293 if not max_min_macros_search: |
2281 return | 2294 return |
2282 | 2295 |
2283 max_min_macro = max_min_macros_search.group('max_min_macro') | 2296 max_min_macro = max_min_macros_search.group('max_min_macro') |
2284 max_min_macro_lower = max_min_macro.lower() | 2297 max_min_macro_lower = max_min_macro.lower() |
2285 error(line_number, 'runtime/max_min_macros', 4, | 2298 error(line_number, 'runtime/max_min_macros', 4, |
2286 'Use std::%s() or std::%s<type>() instead of the %s() macro.' | 2299 'Use std::%s() or std::%s<type>() instead of the %s() macro.' |
2287 % (max_min_macro_lower, max_min_macro_lower, max_min_macro)) | 2300 % (max_min_macro_lower, max_min_macro_lower, max_min_macro)) |
2288 | 2301 |
2289 | 2302 |
2290 def check_ctype_functions(clean_lines, line_number, file_state, error): | 2303 def check_ctype_functions(clean_lines, line_number, file_state, error): |
2291 """Looks for use of the standard functions in ctype.h and suggest they be re
placed | 2304 """Looks for use of the standard functions in ctype.h and suggest they be re
placed |
2292 by use of equivilent ones in <wtf/ASCIICType.h>?. | 2305 by use of equivilent ones in <wtf/ASCIICType.h>?. |
2293 | 2306 |
2294 Args: | 2307 Args: |
2295 clean_lines: A CleansedLines instance containing the file. | 2308 clean_lines: A CleansedLines instance containing the file. |
2296 line_number: The number of the line to check. | 2309 line_number: The number of the line to check. |
2297 file_state: A _FileState instance which maintains information about | 2310 file_state: A _FileState instance which maintains information about |
2298 the state of things in the file. | 2311 the state of things in the file. |
2299 error: The function to call with any errors found. | 2312 error: The function to call with any errors found. |
2300 """ | 2313 """ |
2301 | 2314 |
2302 line = clean_lines.elided[line_number] # Get rid of comments and strings. | 2315 line = clean_lines.elided[line_number] # Get rid of comments and strings. |
2303 | 2316 |
2304 ctype_function_search = search(r'\b(?P<ctype_function>(isalnum|isalpha|isasc
ii|isblank|iscntrl|isdigit|isgraph|islower|isprint|ispunct|isspace|isupper|isxdi
git|toascii|tolower|toupper))\s*\(', line) | 2317 ctype_function_search = search( |
| 2318 r'\b(?P<ctype_function>(isalnum|isalpha|isascii|isblank|iscntrl|isdigit|
isgraph|islower|isprint|ispunct|isspace|isupper|isxdigit|toascii|tolower|toupper
))\s*\(', line) |
2305 if not ctype_function_search: | 2319 if not ctype_function_search: |
2306 return | 2320 return |
2307 | 2321 |
2308 ctype_function = ctype_function_search.group('ctype_function') | 2322 ctype_function = ctype_function_search.group('ctype_function') |
2309 error(line_number, 'runtime/ctype_function', 4, | 2323 error(line_number, 'runtime/ctype_function', 4, |
2310 'Use equivelent function in <wtf/ASCIICType.h> instead of the %s() fun
ction.' | 2324 'Use equivelent function in <wtf/ASCIICType.h> instead of the %s() fun
ction.' |
2311 % (ctype_function)) | 2325 % (ctype_function)) |
2312 | 2326 |
| 2327 |
2313 def check_switch_indentation(clean_lines, line_number, error): | 2328 def check_switch_indentation(clean_lines, line_number, error): |
2314 """Looks for indentation errors inside of switch statements. | 2329 """Looks for indentation errors inside of switch statements. |
2315 | 2330 |
2316 Args: | 2331 Args: |
2317 clean_lines: A CleansedLines instance containing the file. | 2332 clean_lines: A CleansedLines instance containing the file. |
2318 line_number: The number of the line to check. | 2333 line_number: The number of the line to check. |
2319 error: The function to call with any errors found. | 2334 error: The function to call with any errors found. |
2320 """ | 2335 """ |
2321 | 2336 |
2322 line = clean_lines.elided[line_number] # Get rid of comments and strings. | 2337 line = clean_lines.elided[line_number] # Get rid of comments and strings. |
2323 | 2338 |
2324 switch_match = match(r'(?P<switch_indentation>\s*)switch\s*\(.+\)\s*{\s*$',
line) | 2339 switch_match = match(r'(?P<switch_indentation>\s*)switch\s*\(.+\)\s*{\s*$',
line) |
2325 if not switch_match: | 2340 if not switch_match: |
2326 return | 2341 return |
2327 | 2342 |
2328 switch_indentation = switch_match.group('switch_indentation') | 2343 switch_indentation = switch_match.group('switch_indentation') |
2329 inner_indentation = switch_indentation + ' ' * 4 | 2344 inner_indentation = switch_indentation + ' ' * 4 |
2330 line_offset = 0 | 2345 line_offset = 0 |
2331 encountered_nested_switch = False | 2346 encountered_nested_switch = False |
2332 | 2347 |
2333 for current_line in clean_lines.elided[line_number + 1:]: | 2348 for current_line in clean_lines.elided[line_number + 1:]: |
2334 line_offset += 1 | 2349 line_offset += 1 |
2335 | 2350 |
2336 # Skip not only empty lines but also those with preprocessor directives. | 2351 # Skip not only empty lines but also those with preprocessor directives. |
2337 if current_line.strip() == '' or current_line.startswith('#'): | 2352 if current_line.strip() == '' or current_line.startswith('#'): |
2338 continue | 2353 continue |
2339 | 2354 |
2340 if match(r'\s*switch\s*\(.+\)\s*{\s*$', current_line): | 2355 if match(r'\s*switch\s*\(.+\)\s*{\s*$', current_line): |
2341 # Complexity alarm - another switch statement nested inside the one | 2356 # Complexity alarm - another switch statement nested inside the one |
2342 # that we're currently testing. We'll need to track the extent of | 2357 # that we're currently testing. We'll need to track the extent of |
2343 # that inner switch if the upcoming label tests are still supposed | 2358 # that inner switch if the upcoming label tests are still supposed |
2344 # to work correctly. Let's not do that; instead, we'll finish | 2359 # to work correctly. Let's not do that; instead, we'll finish |
2345 # checking this line, and then leave it like that. Assuming the | 2360 # checking this line, and then leave it like that. Assuming the |
2346 # indentation is done consistently (even if incorrectly), this will | 2361 # indentation is done consistently (even if incorrectly), this will |
2347 # still catch all indentation issues in practice. | 2362 # still catch all indentation issues in practice. |
2348 encountered_nested_switch = True | 2363 encountered_nested_switch = True |
2349 | 2364 |
2350 current_indentation_match = match(r'(?P<indentation>\s*)(?P<remaining_li
ne>.*)$', current_line); | 2365 current_indentation_match = match(r'(?P<indentation>\s*)(?P<remaining_li
ne>.*)$', current_line) |
2351 current_indentation = current_indentation_match.group('indentation') | 2366 current_indentation = current_indentation_match.group('indentation') |
2352 remaining_line = current_indentation_match.group('remaining_line') | 2367 remaining_line = current_indentation_match.group('remaining_line') |
2353 | 2368 |
2354 # End the check at the end of the switch statement. | 2369 # End the check at the end of the switch statement. |
2355 if remaining_line.startswith('}') and current_indentation == switch_inde
ntation: | 2370 if remaining_line.startswith('}') and current_indentation == switch_inde
ntation: |
2356 break | 2371 break |
2357 # Case and default branches should not be indented. The regexp also | 2372 # Case and default branches should not be indented. The regexp also |
2358 # catches single-line cases like "default: break;" but does not trigger | 2373 # catches single-line cases like "default: break;" but does not trigger |
2359 # on stuff like "Document::Foo();". | 2374 # on stuff like "Document::Foo();". |
2360 elif match(r'(default|case\s+.*)\s*:([^:].*)?$', remaining_line): | 2375 elif match(r'(default|case\s+.*)\s*:([^:].*)?$', remaining_line): |
(...skipping 21 matching lines...) Expand all Loading... |
2382 | 2397 |
2383 def check_braces(clean_lines, line_number, error): | 2398 def check_braces(clean_lines, line_number, error): |
2384 """Looks for misplaced braces (e.g. at the end of line). | 2399 """Looks for misplaced braces (e.g. at the end of line). |
2385 | 2400 |
2386 Args: | 2401 Args: |
2387 clean_lines: A CleansedLines instance containing the file. | 2402 clean_lines: A CleansedLines instance containing the file. |
2388 line_number: The number of the line to check. | 2403 line_number: The number of the line to check. |
2389 error: The function to call with any errors found. | 2404 error: The function to call with any errors found. |
2390 """ | 2405 """ |
2391 | 2406 |
2392 line = clean_lines.elided[line_number] # Get rid of comments and strings. | 2407 line = clean_lines.elided[line_number] # Get rid of comments and strings. |
2393 | 2408 |
2394 if match(r'\s*{\s*$', line): | 2409 if match(r'\s*{\s*$', line): |
2395 # We allow an open brace to start a line in the case where someone | 2410 # We allow an open brace to start a line in the case where someone |
2396 # is using braces for function definition or in a block to | 2411 # is using braces for function definition or in a block to |
2397 # explicitly create a new scope, which is commonly used to control | 2412 # explicitly create a new scope, which is commonly used to control |
2398 # the lifetime of stack-allocated variables. We don't detect this | 2413 # the lifetime of stack-allocated variables. We don't detect this |
2399 # perfectly: we just don't complain if the last non-whitespace | 2414 # perfectly: we just don't complain if the last non-whitespace |
2400 # character on the previous non-blank line is ';', ':', '{', '}', | 2415 # character on the previous non-blank line is ';', ':', '{', '}', |
2401 # ')' or is like a function declaration, and doesn't begin with | 2416 # ')' or is like a function declaration, and doesn't begin with |
2402 # 'if|for|while|switch|else' without a beginning '{'. | 2417 # 'if|for|while|switch|else' without a beginning '{'. |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2452 """Looks for else or else-if statements that should be written as an | 2467 """Looks for else or else-if statements that should be written as an |
2453 if statement when the prior if concludes with a return, break, continue or | 2468 if statement when the prior if concludes with a return, break, continue or |
2454 goto statement. | 2469 goto statement. |
2455 | 2470 |
2456 Args: | 2471 Args: |
2457 clean_lines: A CleansedLines instance containing the file. | 2472 clean_lines: A CleansedLines instance containing the file. |
2458 line_number: The number of the line to check. | 2473 line_number: The number of the line to check. |
2459 error: The function to call with any errors found. | 2474 error: The function to call with any errors found. |
2460 """ | 2475 """ |
2461 | 2476 |
2462 line = clean_lines.elided[line_number] # Get rid of comments and strings. | 2477 line = clean_lines.elided[line_number] # Get rid of comments and strings. |
2463 | 2478 |
2464 else_match = match(r'(?P<else_indentation>\s*)(\}\s*)?else(\s+if\s*\(|(?P<el
se>\s*(\{\s*)?\Z))', line) | 2479 else_match = match(r'(?P<else_indentation>\s*)(\}\s*)?else(\s+if\s*\(|(?P<el
se>\s*(\{\s*)?\Z))', line) |
2465 if not else_match: | 2480 if not else_match: |
2466 return | 2481 return |
2467 | 2482 |
2468 else_indentation = else_match.group('else_indentation') | 2483 else_indentation = else_match.group('else_indentation') |
2469 inner_indentation = else_indentation + ' ' * 4 | 2484 inner_indentation = else_indentation + ' ' * 4 |
2470 | 2485 |
2471 previous_lines = clean_lines.elided[:line_number] | 2486 previous_lines = clean_lines.elided[:line_number] |
2472 previous_lines.reverse() | 2487 previous_lines.reverse() |
2473 line_offset = 0 | 2488 line_offset = 0 |
2474 encountered_exit_statement = False | 2489 encountered_exit_statement = False |
2475 | 2490 |
2476 for current_line in previous_lines: | 2491 for current_line in previous_lines: |
2477 line_offset -= 1 | 2492 line_offset -= 1 |
2478 | 2493 |
2479 # Skip not only empty lines but also those with preprocessor directives | 2494 # Skip not only empty lines but also those with preprocessor directives |
2480 # and goto labels. | 2495 # and goto labels. |
2481 if current_line.strip() == '' or current_line.startswith('#') or match(r
'\w+\s*:\s*$', current_line): | 2496 if current_line.strip() == '' or current_line.startswith('#') or match(r
'\w+\s*:\s*$', current_line): |
2482 continue | 2497 continue |
2483 | 2498 |
2484 # Skip lines with closing braces on the original indentation level. | 2499 # Skip lines with closing braces on the original indentation level. |
2485 # Even though the styleguide says they should be on the same line as | 2500 # Even though the styleguide says they should be on the same line as |
2486 # the "else if" statement, we also want to check for instances where | 2501 # the "else if" statement, we also want to check for instances where |
2487 # the current code does not comply with the coding style. Thus, ignore | 2502 # the current code does not comply with the coding style. Thus, ignore |
2488 # these lines and proceed to the line before that. | 2503 # these lines and proceed to the line before that. |
2489 if current_line == else_indentation + '}': | 2504 if current_line == else_indentation + '}': |
2490 continue | 2505 continue |
2491 | 2506 |
2492 current_indentation_match = match(r'(?P<indentation>\s*)(?P<remaining_li
ne>.*)$', current_line); | 2507 current_indentation_match = match(r'(?P<indentation>\s*)(?P<remaining_li
ne>.*)$', current_line) |
2493 current_indentation = current_indentation_match.group('indentation') | 2508 current_indentation = current_indentation_match.group('indentation') |
2494 remaining_line = current_indentation_match.group('remaining_line') | 2509 remaining_line = current_indentation_match.group('remaining_line') |
2495 | 2510 |
2496 # As we're going up the lines, the first real statement to encounter | 2511 # As we're going up the lines, the first real statement to encounter |
2497 # has to be an exit statement (return, break, continue or goto) - | 2512 # has to be an exit statement (return, break, continue or goto) - |
2498 # otherwise, this check doesn't apply. | 2513 # otherwise, this check doesn't apply. |
2499 if not encountered_exit_statement: | 2514 if not encountered_exit_statement: |
2500 # We only want to find exit statements if they are on exactly | 2515 # We only want to find exit statements if they are on exactly |
2501 # the same level of indentation as expected from the code inside | 2516 # the same level of indentation as expected from the code inside |
2502 # the block. If the indentation doesn't strictly match then we | 2517 # the block. If the indentation doesn't strictly match then we |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2628 return | 2643 return |
2629 | 2644 |
2630 # Don't warn about NULL usage in gst_*(). See Bug 70498. | 2645 # Don't warn about NULL usage in gst_*(). See Bug 70498. |
2631 if search(r'\bgst(_[a-z]+)+\b', line): | 2646 if search(r'\bgst(_[a-z]+)+\b', line): |
2632 return | 2647 return |
2633 | 2648 |
2634 # Don't warn about NULL usage in gdk_pixbuf_save_to_*{join,concat}(). See Bu
g 43090. | 2649 # Don't warn about NULL usage in gdk_pixbuf_save_to_*{join,concat}(). See Bu
g 43090. |
2635 if search(r'\bgdk_pixbuf_save_to\w+\b', line): | 2650 if search(r'\bgdk_pixbuf_save_to\w+\b', line): |
2636 return | 2651 return |
2637 | 2652 |
2638 # Don't warn about NULL usage in gtk_widget_style_get(), gtk_style_context_g
et_style(), or gtk_style_context_get(). See Bug 51758 | 2653 # Don't warn about NULL usage in gtk_widget_style_get(), |
| 2654 # gtk_style_context_get_style(), or gtk_style_context_get(). See Bug 51758 |
2639 if search(r'\bgtk_widget_style_get\(\w+\b', line) or search(r'\bgtk_style_co
ntext_get_style\(\w+\b', line) or search(r'\bgtk_style_context_get\(\w+\b', line
): | 2655 if search(r'\bgtk_widget_style_get\(\w+\b', line) or search(r'\bgtk_style_co
ntext_get_style\(\w+\b', line) or search(r'\bgtk_style_context_get\(\w+\b', line
): |
2640 return | 2656 return |
2641 | 2657 |
2642 # Don't warn about NULL usage in soup_server_new(). See Bug 77890. | 2658 # Don't warn about NULL usage in soup_server_new(). See Bug 77890. |
2643 if search(r'\bsoup_server_new\(\w+\b', line): | 2659 if search(r'\bsoup_server_new\(\w+\b', line): |
2644 return | 2660 return |
2645 | 2661 |
2646 if search(r'\bNULL\b', line): | 2662 if search(r'\bNULL\b', line): |
2647 error(line_number, 'readability/null', 5, 'Use 0 instead of NULL.') | 2663 error(line_number, 'readability/null', 5, 'Use 0 instead of NULL.') |
2648 return | 2664 return |
2649 | 2665 |
2650 line = clean_lines.raw_lines[line_number] | 2666 line = clean_lines.raw_lines[line_number] |
2651 # See if NULL occurs in any comments in the line. If the search for NULL usi
ng the raw line | 2667 # See if NULL occurs in any comments in the line. If the search for NULL usi
ng the raw line |
2652 # matches, then do the check with strings collapsed to avoid giving errors f
or | 2668 # matches, then do the check with strings collapsed to avoid giving errors f
or |
2653 # NULLs occurring in strings. | 2669 # NULLs occurring in strings. |
2654 if search(r'\bNULL\b', line) and search(r'\bNULL\b', CleansedLines.collapse_
strings(line)): | 2670 if search(r'\bNULL\b', line) and search(r'\bNULL\b', CleansedLines.collapse_
strings(line)): |
2655 error(line_number, 'readability/null', 4, 'Use 0 or null instead of NULL
(even in *comments*).') | 2671 error(line_number, 'readability/null', 4, 'Use 0 or null instead of NULL
(even in *comments*).') |
2656 | 2672 |
| 2673 |
2657 def get_line_width(line): | 2674 def get_line_width(line): |
2658 """Determines the width of the line in column positions. | 2675 """Determines the width of the line in column positions. |
2659 | 2676 |
2660 Args: | 2677 Args: |
2661 line: A string, which may be a Unicode string. | 2678 line: A string, which may be a Unicode string. |
2662 | 2679 |
2663 Returns: | 2680 Returns: |
2664 The width of the line in column positions, accounting for Unicode | 2681 The width of the line in column positions, accounting for Unicode |
2665 combining characters and wide characters. | 2682 combining characters and wide characters. |
2666 """ | 2683 """ |
(...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3021 """ | 3038 """ |
3022 | 3039 |
3023 # If it is a system header we know it is classified as _OTHER_HEADER. | 3040 # If it is a system header we know it is classified as _OTHER_HEADER. |
3024 if is_system and not include.startswith('public/'): | 3041 if is_system and not include.startswith('public/'): |
3025 return _OTHER_HEADER | 3042 return _OTHER_HEADER |
3026 | 3043 |
3027 # There cannot be primary includes in header files themselves. Only an | 3044 # There cannot be primary includes in header files themselves. Only an |
3028 # include exactly matches the header filename will be is flagged as | 3045 # include exactly matches the header filename will be is flagged as |
3029 # primary, so that it triggers the "don't include yourself" check. | 3046 # primary, so that it triggers the "don't include yourself" check. |
3030 if filename.endswith('.h') and filename != include: | 3047 if filename.endswith('.h') and filename != include: |
3031 return _OTHER_HEADER; | 3048 return _OTHER_HEADER |
3032 | 3049 |
3033 # Qt's moc files do not follow the naming and ordering rules, so they should
be skipped | 3050 # Qt's moc files do not follow the naming and ordering rules, so they should
be skipped |
3034 if include.startswith('moc_') and include.endswith('.cpp'): | 3051 if include.startswith('moc_') and include.endswith('.cpp'): |
3035 return _MOC_HEADER | 3052 return _MOC_HEADER |
3036 | 3053 |
3037 if include.endswith('.moc'): | 3054 if include.endswith('.moc'): |
3038 return _MOC_HEADER | 3055 return _MOC_HEADER |
3039 | 3056 |
3040 # If the target file basename starts with the include we're checking | 3057 # If the target file basename starts with the include we're checking |
3041 # then we consider it the primary header. | 3058 # then we consider it the primary header. |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3139 # 1) for implementation files: primary header, blank line, alphabetically so
rted | 3156 # 1) for implementation files: primary header, blank line, alphabetically so
rted |
3140 # 2) for header files: alphabetically sorted | 3157 # 2) for header files: alphabetically sorted |
3141 # The include_state object keeps track of the last type seen | 3158 # The include_state object keeps track of the last type seen |
3142 # and complains if the header types are out of order or missing. | 3159 # and complains if the header types are out of order or missing. |
3143 error_message = include_state.check_next_include_order(header_type, | 3160 error_message = include_state.check_next_include_order(header_type, |
3144 file_extension == "h"
, | 3161 file_extension == "h"
, |
3145 primary_header_exists
) | 3162 primary_header_exists
) |
3146 | 3163 |
3147 # Check to make sure we have a blank line after primary header. | 3164 # Check to make sure we have a blank line after primary header. |
3148 if not error_message and header_type == _PRIMARY_HEADER: | 3165 if not error_message and header_type == _PRIMARY_HEADER: |
3149 next_line = clean_lines.raw_lines[line_number + 1] | 3166 next_line = clean_lines.raw_lines[line_number + 1] |
3150 if not is_blank_line(next_line): | 3167 if not is_blank_line(next_line): |
3151 error(line_number, 'build/include_order', 4, | 3168 error(line_number, 'build/include_order', 4, |
3152 'You should add a blank line after implementation file\'s own
header.') | 3169 'You should add a blank line after implementation file\'s own
header.') |
3153 | 3170 |
3154 # Check to make sure all headers besides the primary header are | 3171 # Check to make sure all headers besides the primary header are |
3155 # alphabetically sorted. Skip Qt's moc files. | 3172 # alphabetically sorted. Skip Qt's moc files. |
3156 if not error_message and header_type == _OTHER_HEADER: | 3173 if not error_message and header_type == _OTHER_HEADER: |
3157 previous_line_number = line_number - 1; | 3174 previous_line_number = line_number - 1 |
3158 previous_line = clean_lines.lines[previous_line_number] | 3175 previous_line = clean_lines.lines[previous_line_number] |
3159 previous_match = _RE_PATTERN_INCLUDE.search(previous_line) | 3176 previous_match = _RE_PATTERN_INCLUDE.search(previous_line) |
3160 while (not previous_match and previous_line_number > 0 | 3177 while (not previous_match and previous_line_number > 0 |
3161 and not search(r'\A(#if|#ifdef|#ifndef|#else|#elif|#endif)', pre
vious_line)): | 3178 and not search(r'\A(#if|#ifdef|#ifndef|#else|#elif|#endif)', prev
ious_line)): |
3162 previous_line_number -= 1; | 3179 previous_line_number -= 1 |
3163 previous_line = clean_lines.lines[previous_line_number] | 3180 previous_line = clean_lines.lines[previous_line_number] |
3164 previous_match = _RE_PATTERN_INCLUDE.search(previous_line) | 3181 previous_match = _RE_PATTERN_INCLUDE.search(previous_line) |
3165 if previous_match: | 3182 if previous_match: |
3166 previous_header_type = include_state.header_types[previous_line_numb
er] | 3183 previous_header_type = include_state.header_types[previous_line_numb
er] |
3167 if previous_header_type == _OTHER_HEADER and previous_line.strip() >
line.strip(): | 3184 if previous_header_type == _OTHER_HEADER and previous_line.strip() >
line.strip(): |
3168 # This type of error is potentially a problem with this line or
the previous one, | 3185 # This type of error is potentially a problem with this line or
the previous one, |
3169 # so if the error is filtered for one line, report it for the ne
xt. This is so that | 3186 # so if the error is filtered for one line, report it for the ne
xt. This is so that |
3170 # we properly handle patches, for which only modified lines prod
uce errors. | 3187 # we properly handle patches, for which only modified lines prod
uce errors. |
3171 if not error(line_number - 1, 'build/include_order', 4, 'Alphabe
tical sorting problem.'): | 3188 if not error(line_number - 1, 'build/include_order', 4, 'Alphabe
tical sorting problem.'): |
3172 error(line_number, 'build/include_order', 4, 'Alphabetical s
orting problem.') | 3189 error(line_number, 'build/include_order', 4, 'Alphabetical s
orting problem.') |
3173 | 3190 |
3174 if error_message: | 3191 if error_message: |
3175 if file_extension == 'h': | 3192 if file_extension == 'h': |
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3382 and search(r'\bnamespace\s*{', line) | 3399 and search(r'\bnamespace\s*{', line) |
3383 and line[-1] != '\\'): | 3400 and line[-1] != '\\'): |
3384 error(line_number, 'build/namespaces', 4, | 3401 error(line_number, 'build/namespaces', 4, |
3385 'Do not use unnamed namespaces in header files. See ' | 3402 'Do not use unnamed namespaces in header files. See ' |
3386 'http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Na
mespaces' | 3403 'http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Na
mespaces' |
3387 ' for more information.') | 3404 ' for more information.') |
3388 | 3405 |
3389 # Check for plain bitfields declared without either "singed" or "unsigned". | 3406 # Check for plain bitfields declared without either "singed" or "unsigned". |
3390 # Most compilers treat such bitfields as signed, but there are still compile
rs like | 3407 # Most compilers treat such bitfields as signed, but there are still compile
rs like |
3391 # RVCT 4.0 that use unsigned by default. | 3408 # RVCT 4.0 that use unsigned by default. |
3392 matched = re.match(r'\s*((const|mutable)\s+)?(char|(short(\s+int)?)|int|long
(\s+(long|int))?)\s+[a-zA-Z_][a-zA-Z0-9_]*\s*:\s*\d+\s*;', line) | 3409 matched = re.match( |
| 3410 r'\s*((const|mutable)\s+)?(char|(short(\s+int)?)|int|long(\s+(long|int))
?)\s+[a-zA-Z_][a-zA-Z0-9_]*\s*:\s*\d+\s*;', line) |
3393 if matched: | 3411 if matched: |
3394 error(line_number, 'runtime/bitfields', 5, | 3412 error(line_number, 'runtime/bitfields', 5, |
3395 'Please declare integral type bitfields with either signed or unsi
gned.') | 3413 'Please declare integral type bitfields with either signed or unsi
gned.') |
3396 | 3414 |
3397 check_identifier_name_in_declaration(filename, line_number, line, file_state
, error) | 3415 check_identifier_name_in_declaration(filename, line_number, line, file_state
, error) |
3398 | 3416 |
3399 # Check for unsigned int (should be just 'unsigned') | 3417 # Check for unsigned int (should be just 'unsigned') |
3400 if search(r'\bunsigned int\b', line): | 3418 if search(r'\bunsigned int\b', line): |
3401 error(line_number, 'runtime/unsigned', 1, | 3419 error(line_number, 'runtime/unsigned', 1, |
3402 'Omit int when using unsigned') | 3420 'Omit int when using unsigned') |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3511 and not modified_identifier.startswith('Ecore_') | 3529 and not modified_identifier.startswith('Ecore_') |
3512 and not modified_identifier.startswith('Eina_') | 3530 and not modified_identifier.startswith('Eina_') |
3513 and not modified_identifier.startswith('Evas_') | 3531 and not modified_identifier.startswith('Evas_') |
3514 and not modified_identifier.startswith('Ewk_') | 3532 and not modified_identifier.startswith('Ewk_') |
3515 and not modified_identifier.startswith('cti_') | 3533 and not modified_identifier.startswith('cti_') |
3516 and not modified_identifier.find('::qt_') >= 0 | 3534 and not modified_identifier.find('::qt_') >= 0 |
3517 and not modified_identifier.find('::_q_') >= 0 | 3535 and not modified_identifier.find('::_q_') >= 0 |
3518 and not modified_identifier == "const_iterator" | 3536 and not modified_identifier == "const_iterator" |
3519 and not modified_identifier == "vm_throw" | 3537 and not modified_identifier == "vm_throw" |
3520 and not modified_identifier == "DFG_OPERATION"): | 3538 and not modified_identifier == "DFG_OPERATION"): |
3521 error(line_number, 'readability/naming/underscores', 4, identifi
er + " is incorrectly named. Don't use underscores in your identifier names.") | 3539 error(line_number, 'readability/naming/underscores', 4, identifi
er + |
| 3540 " is incorrectly named. Don't use underscores in your iden
tifier names.") |
3522 | 3541 |
3523 # Check for variables named 'l', these are too easy to confuse with '1'
in some fonts | 3542 # Check for variables named 'l', these are too easy to confuse with '1'
in some fonts |
3524 if modified_identifier == 'l': | 3543 if modified_identifier == 'l': |
3525 error(line_number, 'readability/naming', 4, identifier + " is incorr
ectly named. Don't use the single letter 'l' as an identifier name.") | 3544 error(line_number, 'readability/naming', 4, identifier + |
| 3545 " is incorrectly named. Don't use the single letter 'l' as an
identifier name.") |
3526 | 3546 |
3527 # There can be only one declaration in non-for-control statements. | 3547 # There can be only one declaration in non-for-control statements. |
3528 if control_statement: | 3548 if control_statement: |
3529 return | 3549 return |
3530 # We should continue checking if this is a function | 3550 # We should continue checking if this is a function |
3531 # declaration because we need to check its arguments. | 3551 # declaration because we need to check its arguments. |
3532 # Also, we need to check multiple declarations. | 3552 # Also, we need to check multiple declarations. |
3533 if character_after_identifier != '(' and character_after_identifier != '
,': | 3553 if character_after_identifier != '(' and character_after_identifier != '
,': |
3534 return | 3554 return |
3535 | 3555 |
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3739 'unary_negate', 'not1', 'binary_negate', 'not2', | 3759 'unary_negate', 'not1', 'binary_negate', 'not2', |
3740 'bind1st', 'bind2nd', | 3760 'bind1st', 'bind2nd', |
3741 'pointer_to_unary_function', | 3761 'pointer_to_unary_function', |
3742 'pointer_to_binary_function', | 3762 'pointer_to_binary_function', |
3743 'ptr_fun', | 3763 'ptr_fun', |
3744 'mem_fun_t', 'mem_fun', 'mem_fun1_t', 'mem_fun1_ref_t', | 3764 'mem_fun_t', 'mem_fun', 'mem_fun1_t', 'mem_fun1_ref_t', |
3745 'mem_fun_ref_t', | 3765 'mem_fun_ref_t', |
3746 'const_mem_fun_t', 'const_mem_fun1_t', | 3766 'const_mem_fun_t', 'const_mem_fun1_t', |
3747 'const_mem_fun_ref_t', 'const_mem_fun1_ref_t', | 3767 'const_mem_fun_ref_t', 'const_mem_fun1_ref_t', |
3748 'mem_fun_ref', | 3768 'mem_fun_ref', |
3749 )), | 3769 )), |
3750 ('<limits>', ('numeric_limits',)), | 3770 ('<limits>', ('numeric_limits',)), |
3751 ('<list>', ('list',)), | 3771 ('<list>', ('list',)), |
3752 ('<map>', ('map', 'multimap',)), | 3772 ('<map>', ('map', 'multimap',)), |
3753 ('<memory>', ('allocator',)), | 3773 ('<memory>', ('allocator',)), |
3754 ('<queue>', ('queue', 'priority_queue',)), | 3774 ('<queue>', ('queue', 'priority_queue',)), |
3755 ('<set>', ('set', 'multiset',)), | 3775 ('<set>', ('set', 'multiset',)), |
3756 ('<stack>', ('stack',)), | 3776 ('<stack>', ('stack',)), |
3757 ('<string>', ('char_traits', 'basic_string',)), | 3777 ('<string>', ('char_traits', 'basic_string',)), |
3758 ('<utility>', ('pair',)), | 3778 ('<utility>', ('pair',)), |
3759 ('<vector>', ('vector',)), | 3779 ('<vector>', ('vector',)), |
3760 | 3780 |
3761 # gcc extensions. | 3781 # gcc extensions. |
3762 # Note: std::hash is their hash, ::hash is our hash | 3782 # Note: std::hash is their hash, ::hash is our hash |
3763 ('<hash_map>', ('hash_map', 'hash_multimap',)), | 3783 ('<hash_map>', ('hash_map', 'hash_multimap',)), |
3764 ('<hash_set>', ('hash_set', 'hash_multiset',)), | 3784 ('<hash_set>', ('hash_set', 'hash_multiset',)), |
3765 ('<slist>', ('slist',)), | 3785 ('<slist>', ('slist',)), |
3766 ) | 3786 ) |
3767 | 3787 |
3768 _HEADERS_ACCEPTED_BUT_NOT_PROMOTED = { | 3788 _HEADERS_ACCEPTED_BUT_NOT_PROMOTED = { |
3769 # We can trust with reasonable confidence that map gives us pair<>, too. | 3789 # We can trust with reasonable confidence that map gives us pair<>, too. |
3770 'pair<>': ('map', 'multimap', 'hash_map', 'hash_multimap') | 3790 'pair<>': ('map', 'multimap', 'hash_map', 'hash_multimap') |
3771 } | 3791 } |
3772 | 3792 |
3773 _RE_PATTERN_STRING = re.compile(r'\bstring\b') | 3793 _RE_PATTERN_STRING = re.compile(r'\bstring\b') |
3774 | 3794 |
3775 _re_pattern_algorithm_header = [] | 3795 _re_pattern_algorithm_header = [] |
3776 for _template in ('copy', 'max', 'min', 'min_element', 'sort', 'swap', | 3796 for _template in ('copy', 'max', 'min', 'min_element', 'sort', 'swap', |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3884 less<> in a .h file, only one (the latter in the file) of these will be | 3904 less<> in a .h file, only one (the latter in the file) of these will be |
3885 reported as a reason to include the <functional>. | 3905 reported as a reason to include the <functional>. |
3886 | 3906 |
3887 Args: | 3907 Args: |
3888 filename: The name of the current file. | 3908 filename: The name of the current file. |
3889 clean_lines: A CleansedLines instance containing the file. | 3909 clean_lines: A CleansedLines instance containing the file. |
3890 include_state: An _IncludeState instance. | 3910 include_state: An _IncludeState instance. |
3891 error: The function to call with any errors found. | 3911 error: The function to call with any errors found. |
3892 """ | 3912 """ |
3893 required = {} # A map of header name to line_number and the template entity
. | 3913 required = {} # A map of header name to line_number and the template entity
. |
3894 # Example of required: { '<functional>': (1219, 'less<>') } | 3914 # Example of required: { '<functional>': (1219, 'less<>') } |
3895 | 3915 |
3896 for line_number in xrange(clean_lines.num_lines()): | 3916 for line_number in xrange(clean_lines.num_lines()): |
3897 line = clean_lines.elided[line_number] | 3917 line = clean_lines.elided[line_number] |
3898 if not line or line[0] == '#': | 3918 if not line or line[0] == '#': |
3899 continue | 3919 continue |
3900 | 3920 |
3901 # String is special -- it is a non-templatized type in STL. | 3921 # String is special -- it is a non-templatized type in STL. |
3902 if _RE_PATTERN_STRING.search(line): | 3922 if _RE_PATTERN_STRING.search(line): |
3903 required['<string>'] = (line_number, 'string') | 3923 required['<string>'] = (line_number, 'string') |
3904 | 3924 |
(...skipping 24 matching lines...) Expand all Loading... |
3929 # If cpp_style is invoked from Emacs's flymake, a temporary file is generate
d | 3949 # If cpp_style is invoked from Emacs's flymake, a temporary file is generate
d |
3930 # by flymake and that file name might end with '_flymake.cpp'. In that case, | 3950 # by flymake and that file name might end with '_flymake.cpp'. In that case, |
3931 # restore original file name here so that the corresponding header file can
be | 3951 # restore original file name here so that the corresponding header file can
be |
3932 # found. | 3952 # found. |
3933 # e.g. If the file name is 'foo_flymake.cpp', we should search for 'foo.h' | 3953 # e.g. If the file name is 'foo_flymake.cpp', we should search for 'foo.h' |
3934 # instead of 'foo_flymake.h' | 3954 # instead of 'foo_flymake.h' |
3935 abs_filename = re.sub(r'_flymake\.cpp$', '.cpp', abs_filename) | 3955 abs_filename = re.sub(r'_flymake\.cpp$', '.cpp', abs_filename) |
3936 | 3956 |
3937 # include_state is modified during iteration, so we iterate over a copy of | 3957 # include_state is modified during iteration, so we iterate over a copy of |
3938 # the keys. | 3958 # the keys. |
3939 for header in include_state.keys(): #NOLINT | 3959 for header in include_state.keys(): # NOLINT |
3940 (same_module, common_path) = files_belong_to_same_module(abs_filename, h
eader) | 3960 (same_module, common_path) = files_belong_to_same_module(abs_filename, h
eader) |
3941 fullpath = common_path + header | 3961 fullpath = common_path + header |
3942 if same_module and update_include_state(fullpath, include_state): | 3962 if same_module and update_include_state(fullpath, include_state): |
3943 header_found = True | 3963 header_found = True |
3944 | 3964 |
3945 # If we can't find the header file for a .cpp, assume it's because we don't | 3965 # If we can't find the header file for a .cpp, assume it's because we don't |
3946 # know where to look. In that case we'll give up as we're not sure they | 3966 # know where to look. In that case we'll give up as we're not sure they |
3947 # didn't include it in the .h file. | 3967 # didn't include it in the .h file. |
3948 # FIXME: Do a better job of finding .h files so we are confident that | 3968 # FIXME: Do a better job of finding .h files so we are confident that |
3949 # not having the .h file means there isn't one. | 3969 # not having the .h file means there isn't one. |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4000 check_style(clean_lines, line, file_extension, class_state, file_state, enum
_state, error) | 4020 check_style(clean_lines, line, file_extension, class_state, file_state, enum
_state, error) |
4001 check_language(filename, clean_lines, line, file_extension, include_state, | 4021 check_language(filename, clean_lines, line, file_extension, include_state, |
4002 file_state, error) | 4022 file_state, error) |
4003 check_for_non_standard_constructs(clean_lines, line, class_state, error) | 4023 check_for_non_standard_constructs(clean_lines, line, class_state, error) |
4004 check_posix_threading(clean_lines, line, error) | 4024 check_posix_threading(clean_lines, line, error) |
4005 check_invalid_increment(clean_lines, line, error) | 4025 check_invalid_increment(clean_lines, line, error) |
4006 check_conditional_and_loop_bodies_for_brace_violations(clean_lines, line, er
ror) | 4026 check_conditional_and_loop_bodies_for_brace_violations(clean_lines, line, er
ror) |
4007 check_redundant_virtual(clean_lines, line, error) | 4027 check_redundant_virtual(clean_lines, line, error) |
4008 check_redundant_override(clean_lines, line, error) | 4028 check_redundant_override(clean_lines, line, error) |
4009 | 4029 |
| 4030 |
4010 def _process_lines(filename, file_extension, lines, error, min_confidence): | 4031 def _process_lines(filename, file_extension, lines, error, min_confidence): |
4011 """Performs lint checks and reports any errors to the given error function. | 4032 """Performs lint checks and reports any errors to the given error function. |
4012 | 4033 |
4013 Args: | 4034 Args: |
4014 filename: Filename of the file that is being processed. | 4035 filename: Filename of the file that is being processed. |
4015 file_extension: The extension (dot not included) of the file. | 4036 file_extension: The extension (dot not included) of the file. |
4016 lines: An array of strings, each representing a line of the file, with the | 4037 lines: An array of strings, each representing a line of the file, with the |
4017 last element being empty if the file is termined with a newline. | 4038 last element being empty if the file is termined with a newline. |
4018 error: A callable to which errors are reported, which takes 4 arguments: | 4039 error: A callable to which errors are reported, which takes 4 arguments: |
4019 """ | 4040 """ |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4122 'whitespace/end_of_line', | 4143 'whitespace/end_of_line', |
4123 'whitespace/ending_newline', | 4144 'whitespace/ending_newline', |
4124 'whitespace/indent', | 4145 'whitespace/indent', |
4125 'whitespace/line_length', | 4146 'whitespace/line_length', |
4126 'whitespace/newline', | 4147 'whitespace/newline', |
4127 'whitespace/operators', | 4148 'whitespace/operators', |
4128 'whitespace/parens', | 4149 'whitespace/parens', |
4129 'whitespace/semicolon', | 4150 'whitespace/semicolon', |
4130 'whitespace/tab', | 4151 'whitespace/tab', |
4131 'whitespace/todo', | 4152 'whitespace/todo', |
4132 ]) | 4153 ]) |
4133 | 4154 |
4134 fs = None | 4155 fs = None |
4135 | 4156 |
4136 def __init__(self, file_path, file_extension, handle_style_error, | 4157 def __init__(self, file_path, file_extension, handle_style_error, |
4137 min_confidence, fs=None): | 4158 min_confidence, fs=None): |
4138 """Create a CppChecker instance. | 4159 """Create a CppChecker instance. |
4139 | 4160 |
4140 Args: | 4161 Args: |
4141 file_extension: A string that is the file extension, without | 4162 file_extension: A string that is the file extension, without |
4142 the leading dot. | 4163 the leading dot. |
(...skipping 26 matching lines...) Expand all Loading... |
4169 | 4190 |
4170 def check(self, lines): | 4191 def check(self, lines): |
4171 _process_lines(self.file_path, self.file_extension, lines, | 4192 _process_lines(self.file_path, self.file_extension, lines, |
4172 self.handle_style_error, self.min_confidence) | 4193 self.handle_style_error, self.min_confidence) |
4173 | 4194 |
4174 | 4195 |
4175 # FIXME: Remove this function (requires refactoring unit tests). | 4196 # FIXME: Remove this function (requires refactoring unit tests). |
4176 def process_file_data(filename, file_extension, lines, error, min_confidence, fs
=None): | 4197 def process_file_data(filename, file_extension, lines, error, min_confidence, fs
=None): |
4177 checker = CppChecker(filename, file_extension, error, min_confidence, fs) | 4198 checker = CppChecker(filename, file_extension, error, min_confidence, fs) |
4178 checker.check(lines) | 4199 checker.check(lines) |
OLD | NEW |