| 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 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 107 _CHECK_REPLACEMENT['EXPECT_FALSE_M'][op] = 'EXPECT_%s_M' % inv_replacement | 107 _CHECK_REPLACEMENT['EXPECT_FALSE_M'][op] = 'EXPECT_%s_M' % inv_replacement |
| 108 _CHECK_REPLACEMENT['ASSERT_FALSE_M'][op] = 'ASSERT_%s_M' % inv_replacement | 108 _CHECK_REPLACEMENT['ASSERT_FALSE_M'][op] = 'ASSERT_%s_M' % inv_replacement |
| 109 | 109 |
| 110 _DEPRECATED_MACROS = [ | 110 _DEPRECATED_MACROS = [ |
| 111 ['ASSERT', 'DCHECK or its variants'], | 111 ['ASSERT', 'DCHECK or its variants'], |
| 112 ['ASSERT_UNUSED', 'DCHECK or its variants'], | 112 ['ASSERT_UNUSED', 'DCHECK or its variants'], |
| 113 ['ASSERT_NOT_REACHED', 'NOTREACHED'], | 113 ['ASSERT_NOT_REACHED', 'NOTREACHED'], |
| 114 ['WTF_LOG', 'DVLOG'] | 114 ['WTF_LOG', 'DVLOG'] |
| 115 ] | 115 ] |
| 116 | 116 |
| 117 # These constants define types of headers for use with | |
| 118 # _IncludeState.check_next_include_order(). | |
| 119 _PRIMARY_HEADER = 0 | |
| 120 _OTHER_HEADER = 1 | |
| 121 | |
| 122 | 117 |
| 123 # The regexp compilation caching is inlined in all regexp functions for | 118 # The regexp compilation caching is inlined in all regexp functions for |
| 124 # performance reasons; factoring it out into a separate function turns out | 119 # performance reasons; factoring it out into a separate function turns out |
| 125 # to be noticeably expensive. | 120 # to be noticeably expensive. |
| 126 _regexp_compile_cache = {} | 121 _regexp_compile_cache = {} |
| 127 | 122 |
| 128 | 123 |
| 129 def match(pattern, s): | 124 def match(pattern, s): |
| 130 """Matches the string with the pattern, caching the compiled regexp.""" | 125 """Matches the string with the pattern, caching the compiled regexp.""" |
| 131 if not pattern in _regexp_compile_cache: | 126 if not pattern in _regexp_compile_cache: |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 285 if i == 0: | 280 if i == 0: |
| 286 return s[:pos], s[pos + 1:] | 281 return s[:pos], s[pos + 1:] |
| 287 return None, None | 282 return None, None |
| 288 | 283 |
| 289 | 284 |
| 290 class _IncludeState(dict): | 285 class _IncludeState(dict): |
| 291 """Tracks line numbers for includes, and the order in which includes appear. | 286 """Tracks line numbers for includes, and the order in which includes appear. |
| 292 | 287 |
| 293 As a dict, an _IncludeState object serves as a mapping between include | 288 As a dict, an _IncludeState object serves as a mapping between include |
| 294 filename and line number on which that file was included. | 289 filename and line number on which that file was included. |
| 295 | |
| 296 Call check_next_include_order() once for each header in the file, passing | |
| 297 in the type constants defined above. Calls in an illegal order will | |
| 298 raise an _IncludeError with an appropriate error message. | |
| 299 """ | 290 """ |
| 300 # self._section will move monotonically through this set. If it ever | 291 # self._section will move monotonically through this set. If it ever |
| 301 # needs to move backwards, check_next_include_order will raise an error. | 292 # needs to move backwards, check_next_include_order will raise an error. |
| 302 _INITIAL_SECTION = 0 | 293 _INITIAL_SECTION = 0 |
| 303 _PRIMARY_SECTION = 1 | 294 _PRIMARY_SECTION = 1 |
| 304 _OTHER_SECTION = 2 | 295 _OTHER_SECTION = 2 |
| 305 | 296 |
| 306 _TYPE_NAMES = { | |
| 307 _PRIMARY_HEADER: 'header this file implements', | |
| 308 _OTHER_HEADER: 'other header', | |
| 309 } | |
| 310 _SECTION_NAMES = { | 297 _SECTION_NAMES = { |
| 311 _INITIAL_SECTION: '... nothing.', | 298 _INITIAL_SECTION: '... nothing.', |
| 312 _PRIMARY_SECTION: 'a header this file implements.', | 299 _PRIMARY_SECTION: 'a header this file implements.', |
| 313 _OTHER_SECTION: 'other header.', | 300 _OTHER_SECTION: 'other header.', |
| 314 } | 301 } |
| 315 | 302 |
| 316 def __init__(self): | 303 def __init__(self): |
| 317 dict.__init__(self) | 304 dict.__init__(self) |
| 318 self._section = self._INITIAL_SECTION | 305 self._section = self._INITIAL_SECTION |
| 319 self._visited_primary_section = False | 306 self._visited_primary_section = False |
| 320 self.header_types = dict() | 307 self.header_types = dict() |
| 321 | 308 |
| 322 def visited_primary_section(self): | 309 def visited_primary_section(self): |
| 323 return self._visited_primary_section | 310 return self._visited_primary_section |
| 324 | 311 |
| 325 def check_next_include_order(self, header_type, file_is_header, primary_head
er_exists): | |
| 326 """Returns a non-empty error message if the next header is out of order. | |
| 327 | |
| 328 This function also updates the internal state to be ready to check | |
| 329 the next include. | |
| 330 | |
| 331 Args: | |
| 332 header_type: One of the _XXX_HEADER constants defined above. | |
| 333 file_is_header: Whether the file that owns this _IncludeState is itsel
f a header | |
| 334 | |
| 335 Returns: | |
| 336 The empty string if the header is in the right order, or an | |
| 337 error message describing what's wrong. | |
| 338 """ | |
| 339 if header_type == _PRIMARY_HEADER and file_is_header: | |
| 340 return 'Header file should not contain itself.' | |
| 341 | |
| 342 error_message = '' | |
| 343 if self._section != self._OTHER_SECTION: | |
| 344 before_error_message = ('Found %s before %s' % | |
| 345 (self._TYPE_NAMES[header_type], | |
| 346 self._SECTION_NAMES[self._section + 1])) | |
| 347 after_error_message = ('Found %s after %s' % | |
| 348 (self._TYPE_NAMES[header_type], | |
| 349 self._SECTION_NAMES[self._section])) | |
| 350 | |
| 351 if header_type == _PRIMARY_HEADER: | |
| 352 if self._section >= self._PRIMARY_SECTION: | |
| 353 error_message = after_error_message | |
| 354 self._section = self._PRIMARY_SECTION | |
| 355 self._visited_primary_section = True | |
| 356 else: | |
| 357 assert header_type == _OTHER_HEADER | |
| 358 if not file_is_header and self._section < self._PRIMARY_SECTION: | |
| 359 if primary_header_exists: | |
| 360 error_message = before_error_message | |
| 361 self._section = self._OTHER_SECTION | |
| 362 | |
| 363 return error_message | |
| 364 | |
| 365 | 312 |
| 366 class Position(object): | 313 class Position(object): |
| 367 """Holds the position of something.""" | 314 """Holds the position of something.""" |
| 368 | 315 |
| 369 def __init__(self, row, column): | 316 def __init__(self, row, column): |
| 370 self.row = row | 317 self.row = row |
| 371 self.column = column | 318 self.column = column |
| 372 | 319 |
| 373 def __str__(self): | 320 def __str__(self): |
| 374 return '(%s, %s)' % (self.row, self.column) | 321 return '(%s, %s)' % (self.row, self.column) |
| (...skipping 2048 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2423 | 2370 |
| 2424 _RE_PATTERN_INCLUDE = re.compile(r'^\s*#\s*include\s*([<"])([^>"]*)[>"].*$') | 2371 _RE_PATTERN_INCLUDE = re.compile(r'^\s*#\s*include\s*([<"])([^>"]*)[>"].*$') |
| 2425 # Matches the first component of a filename delimited by -s and _s. That is: | 2372 # Matches the first component of a filename delimited by -s and _s. That is: |
| 2426 # _RE_FIRST_COMPONENT.match('foo').group(0) == 'foo' | 2373 # _RE_FIRST_COMPONENT.match('foo').group(0) == 'foo' |
| 2427 # _RE_FIRST_COMPONENT.match('foo.cpp').group(0) == 'foo' | 2374 # _RE_FIRST_COMPONENT.match('foo.cpp').group(0) == 'foo' |
| 2428 # _RE_FIRST_COMPONENT.match('foo-bar_baz.cpp').group(0) == 'foo' | 2375 # _RE_FIRST_COMPONENT.match('foo-bar_baz.cpp').group(0) == 'foo' |
| 2429 # _RE_FIRST_COMPONENT.match('foo_bar-baz.cpp').group(0) == 'foo' | 2376 # _RE_FIRST_COMPONENT.match('foo_bar-baz.cpp').group(0) == 'foo' |
| 2430 _RE_FIRST_COMPONENT = re.compile(r'^[^-_.]+') | 2377 _RE_FIRST_COMPONENT = re.compile(r'^[^-_.]+') |
| 2431 | 2378 |
| 2432 | 2379 |
| 2433 def _drop_common_suffixes(filename): | |
| 2434 """Drops common suffixes like _test.cpp or -inl.h from filename. | |
| 2435 | |
| 2436 For example: | |
| 2437 >>> _drop_common_suffixes('foo/foo-inl.h') | |
| 2438 'foo/foo' | |
| 2439 >>> _drop_common_suffixes('foo/bar/foo.cpp') | |
| 2440 'foo/bar/foo' | |
| 2441 >>> _drop_common_suffixes('foo/foo_internal.h') | |
| 2442 'foo/foo' | |
| 2443 >>> _drop_common_suffixes('foo/foo_unusualinternal.h') | |
| 2444 'foo/foo_unusualinternal' | |
| 2445 | |
| 2446 Args: | |
| 2447 filename: The input filename. | |
| 2448 | |
| 2449 Returns: | |
| 2450 The filename with the common suffix removed. | |
| 2451 """ | |
| 2452 for suffix in ('test.cpp', 'regtest.cpp', 'unittest.cpp', | |
| 2453 'inl.h', 'impl.h', 'internal.h'): | |
| 2454 if (filename.endswith(suffix) and len(filename) > len(suffix) | |
| 2455 and filename[-len(suffix) - 1] in ('-', '_')): | |
| 2456 return filename[:-len(suffix) - 1] | |
| 2457 return os.path.splitext(filename)[0] | |
| 2458 | |
| 2459 | |
| 2460 def _classify_include(filename, include, is_system, include_state): | |
| 2461 """Figures out what kind of header 'include' is. | |
| 2462 | |
| 2463 Args: | |
| 2464 filename: The current file cpp_style is running over. | |
| 2465 include: The path to a #included file. | |
| 2466 is_system: True if the #include used <> rather than "". | |
| 2467 include_state: An _IncludeState instance in which the headers are inserted
. | |
| 2468 | |
| 2469 Returns: | |
| 2470 One of the _XXX_HEADER constants. | |
| 2471 | |
| 2472 For example: | |
| 2473 >>> _classify_include('foo.cpp', 'foo.h', False) | |
| 2474 _PRIMARY_HEADER | |
| 2475 >>> _classify_include('foo.cpp', 'bar.h', False) | |
| 2476 _OTHER_HEADER | |
| 2477 """ | |
| 2478 | |
| 2479 # If it is a system header we know it is classified as _OTHER_HEADER. | |
| 2480 if is_system and not include.startswith('public/'): | |
| 2481 return _OTHER_HEADER | |
| 2482 | |
| 2483 # There cannot be primary includes in header files themselves. Only an | |
| 2484 # include exactly matches the header filename will be is flagged as | |
| 2485 # primary, so that it triggers the "don't include yourself" check. | |
| 2486 if filename.endswith('.h') and filename != include: | |
| 2487 return _OTHER_HEADER | |
| 2488 | |
| 2489 # If the target file basename starts with the include we're checking | |
| 2490 # then we consider it the primary header. | |
| 2491 target_base = FileInfo(filename).base_name() | |
| 2492 include_base = FileInfo(include).base_name() | |
| 2493 | |
| 2494 # If we haven't encountered a primary header, then be lenient in checking. | |
| 2495 if not include_state.visited_primary_section(): | |
| 2496 if target_base.find(include_base) != -1: | |
| 2497 return _PRIMARY_HEADER | |
| 2498 | |
| 2499 # If we already encountered a primary header, perform a strict comparison. | |
| 2500 # In case the two filename bases are the same then the above lenient check | |
| 2501 # probably was a false positive. | |
| 2502 elif include_state.visited_primary_section() and target_base == include_base
: | |
| 2503 return _PRIMARY_HEADER | |
| 2504 | |
| 2505 return _OTHER_HEADER | |
| 2506 | |
| 2507 | |
| 2508 def _does_primary_header_exist(filename): | |
| 2509 """Return a primary header file name for a file, or empty string | |
| 2510 if the file is not source file or primary header does not exist. | |
| 2511 """ | |
| 2512 fileinfo = FileInfo(filename) | |
| 2513 if not fileinfo.is_source(): | |
| 2514 return False | |
| 2515 primary_header = fileinfo.no_extension() + '.h' | |
| 2516 return os.path.isfile(primary_header) | |
| 2517 | |
| 2518 | |
| 2519 def check_include_line(filename, file_extension, clean_lines, line_number, inclu
de_state, error): | 2380 def check_include_line(filename, file_extension, clean_lines, line_number, inclu
de_state, error): |
| 2520 """Check rules that are applicable to #include lines. | 2381 """Check rules that are applicable to #include lines. |
| 2521 | 2382 |
| 2522 Strings on #include lines are NOT removed from elided line, to make | 2383 Strings on #include lines are NOT removed from elided line, to make |
| 2523 certain tasks easier. However, to prevent false positives, checks | 2384 certain tasks easier. However, to prevent false positives, checks |
| 2524 applicable to #include lines in CheckLanguage must be put here. | 2385 applicable to #include lines in CheckLanguage must be put here. |
| 2525 | 2386 |
| 2526 Args: | 2387 Args: |
| 2527 filename: The name of the current file. | 2388 filename: The name of the current file. |
| 2528 file_extension: The current file extension, without the leading dot. | 2389 file_extension: The current file extension, without the leading dot. |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2561 'cc includes should be "CCFoo.h" instead of "cc/CCFoo.h".') | 2422 'cc includes should be "CCFoo.h" instead of "cc/CCFoo.h".') |
| 2562 | 2423 |
| 2563 duplicate_header = include in include_state | 2424 duplicate_header = include in include_state |
| 2564 if duplicate_header: | 2425 if duplicate_header: |
| 2565 error(line_number, 'build/include', 4, | 2426 error(line_number, 'build/include', 4, |
| 2566 '"%s" already included at %s:%s' % | 2427 '"%s" already included at %s:%s' % |
| 2567 (include, filename, include_state[include])) | 2428 (include, filename, include_state[include])) |
| 2568 else: | 2429 else: |
| 2569 include_state[include] = line_number | 2430 include_state[include] = line_number |
| 2570 | 2431 |
| 2571 header_type = _classify_include(filename, include, is_system, include_state) | |
| 2572 primary_header_exists = _does_primary_header_exist(filename) | |
| 2573 include_state.header_types[line_number] = header_type | |
| 2574 | |
| 2575 # Only proceed if this isn't a duplicate header. | |
| 2576 if duplicate_header: | |
| 2577 return | |
| 2578 | |
| 2579 # We want to ensure that headers appear in the right order: | |
| 2580 # 1) for implementation files: primary header, blank line, alphabetically so
rted | |
| 2581 # 2) for header files: alphabetically sorted | |
| 2582 # The include_state object keeps track of the last type seen | |
| 2583 # and complains if the header types are out of order or missing. | |
| 2584 error_message = include_state.check_next_include_order(header_type, | |
| 2585 file_extension == 'h'
, | |
| 2586 primary_header_exists
) | |
| 2587 | |
| 2588 # Check to make sure we have a blank line after primary header. | |
| 2589 if not error_message and header_type == _PRIMARY_HEADER: | |
| 2590 next_line = clean_lines.raw_lines[line_number + 1] | |
| 2591 if not is_blank_line(next_line): | |
| 2592 error(line_number, 'build/include_order', 4, | |
| 2593 'You should add a blank line after implementation file\'s own
header.') | |
| 2594 | |
| 2595 if error_message: | |
| 2596 if file_extension == 'h': | |
| 2597 error(line_number, 'build/include_order', 4, | |
| 2598 '%s Should be: alphabetically sorted.' % | |
| 2599 error_message) | |
| 2600 else: | |
| 2601 error(line_number, 'build/include_order', 4, | |
| 2602 '%s Should be: primary header, blank line, and then alphabetic
ally sorted.' % | |
| 2603 error_message) | |
| 2604 | |
| 2605 | 2432 |
| 2606 def check_language(filename, clean_lines, line_number, file_extension, include_s
tate, | 2433 def check_language(filename, clean_lines, line_number, file_extension, include_s
tate, |
| 2607 file_state, error): | 2434 file_state, error): |
| 2608 """Checks rules from the 'C++ language rules' section of cppguide.html. | 2435 """Checks rules from the 'C++ language rules' section of cppguide.html. |
| 2609 | 2436 |
| 2610 Some of these rules are hard to test (function overloading, using | 2437 Some of these rules are hard to test (function overloading, using |
| 2611 uint32 inappropriately), but we do the best we can. | 2438 uint32 inappropriately), but we do the best we can. |
| 2612 | 2439 |
| 2613 Args: | 2440 Args: |
| 2614 filename: The name of the current file. | 2441 filename: The name of the current file. |
| (...skipping 968 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3583 | 3410 |
| 3584 def check(self, lines): | 3411 def check(self, lines): |
| 3585 _process_lines(self.file_path, self.file_extension, lines, | 3412 _process_lines(self.file_path, self.file_extension, lines, |
| 3586 self.handle_style_error, self.min_confidence) | 3413 self.handle_style_error, self.min_confidence) |
| 3587 | 3414 |
| 3588 | 3415 |
| 3589 # FIXME: Remove this function (requires refactoring unit tests). | 3416 # FIXME: Remove this function (requires refactoring unit tests). |
| 3590 def process_file_data(filename, file_extension, lines, error, min_confidence, fs
=None): | 3417 def process_file_data(filename, file_extension, lines, error, min_confidence, fs
=None): |
| 3591 checker = CppChecker(filename, file_extension, error, min_confidence, fs) | 3418 checker = CppChecker(filename, file_extension, error, min_confidence, fs) |
| 3592 checker.check(lines) | 3419 checker.check(lines) |
| OLD | NEW |