Chromium Code Reviews| 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 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 | 117 # These constants define types of headers for use with | 
| 118 # _IncludeState.check_next_include_order(). | 118 # _IncludeState.check_next_include_order(). | 
| 119 _PRIMARY_HEADER = 0 | 119 _PRIMARY_HEADER = 0 | 
| 120 _OTHER_HEADER = 1 | 120 _OTHER_HEADER = 1 | 
| 121 _MOC_HEADER = 2 | |
| 122 | 121 | 
| 123 | 122 | 
| 124 # The regexp compilation caching is inlined in all regexp functions for | 123 # The regexp compilation caching is inlined in all regexp functions for | 
| 125 # performance reasons; factoring it out into a separate function turns out | 124 # performance reasons; factoring it out into a separate function turns out | 
| 126 # to be noticeably expensive. | 125 # to be noticeably expensive. | 
| 127 _regexp_compile_cache = {} | 126 _regexp_compile_cache = {} | 
| 128 | 127 | 
| 129 | 128 | 
| 130 def match(pattern, s): | 129 def match(pattern, s): | 
| 131 """Matches the string with the pattern, caching the compiled regexp.""" | 130 """Matches the string with the pattern, caching the compiled regexp.""" | 
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 300 """ | 299 """ | 
| 301 # self._section will move monotonically through this set. If it ever | 300 # self._section will move monotonically through this set. If it ever | 
| 302 # needs to move backwards, check_next_include_order will raise an error. | 301 # needs to move backwards, check_next_include_order will raise an error. | 
| 303 _INITIAL_SECTION = 0 | 302 _INITIAL_SECTION = 0 | 
| 304 _PRIMARY_SECTION = 1 | 303 _PRIMARY_SECTION = 1 | 
| 305 _OTHER_SECTION = 2 | 304 _OTHER_SECTION = 2 | 
| 306 | 305 | 
| 307 _TYPE_NAMES = { | 306 _TYPE_NAMES = { | 
| 308 _PRIMARY_HEADER: 'header this file implements', | 307 _PRIMARY_HEADER: 'header this file implements', | 
| 309 _OTHER_HEADER: 'other header', | 308 _OTHER_HEADER: 'other header', | 
| 310 _MOC_HEADER: 'moc file', | |
| 311 } | 309 } | 
| 312 _SECTION_NAMES = { | 310 _SECTION_NAMES = { | 
| 313 _INITIAL_SECTION: "... nothing.", | 311 _INITIAL_SECTION: "... nothing.", | 
| 314 _PRIMARY_SECTION: 'a header this file implements.', | 312 _PRIMARY_SECTION: 'a header this file implements.', | 
| 315 _OTHER_SECTION: 'other header.', | 313 _OTHER_SECTION: 'other header.', | 
| 316 } | 314 } | 
| 317 | 315 | 
| 318 def __init__(self): | 316 def __init__(self): | 
| 319 dict.__init__(self) | 317 dict.__init__(self) | 
| 320 self._section = self._INITIAL_SECTION | 318 self._section = self._INITIAL_SECTION | 
| (...skipping 12 matching lines...) Expand all Loading... | |
| 333 Args: | 331 Args: | 
| 334 header_type: One of the _XXX_HEADER constants defined above. | 332 header_type: One of the _XXX_HEADER constants defined above. | 
| 335 file_is_header: Whether the file that owns this _IncludeState is itsel f a header | 333 file_is_header: Whether the file that owns this _IncludeState is itsel f a header | 
| 336 | 334 | 
| 337 Returns: | 335 Returns: | 
| 338 The empty string if the header is in the right order, or an | 336 The empty string if the header is in the right order, or an | 
| 339 error message describing what's wrong. | 337 error message describing what's wrong. | 
| 340 """ | 338 """ | 
| 341 if header_type == _PRIMARY_HEADER and file_is_header: | 339 if header_type == _PRIMARY_HEADER and file_is_header: | 
| 342 return 'Header file should not contain itself.' | 340 return 'Header file should not contain itself.' | 
| 343 if header_type == _MOC_HEADER: | |
| 344 return '' | |
| 345 | 341 | 
| 346 error_message = '' | 342 error_message = '' | 
| 347 if self._section != self._OTHER_SECTION: | 343 if self._section != self._OTHER_SECTION: | 
| 348 before_error_message = ('Found %s before %s' % | 344 before_error_message = ('Found %s before %s' % | 
| 349 (self._TYPE_NAMES[header_type], | 345 (self._TYPE_NAMES[header_type], | 
| 350 self._SECTION_NAMES[self._section + 1])) | 346 self._SECTION_NAMES[self._section + 1])) | 
| 351 after_error_message = ('Found %s after %s' % | 347 after_error_message = ('Found %s after %s' % | 
| 352 (self._TYPE_NAMES[header_type], | 348 (self._TYPE_NAMES[header_type], | 
| 353 self._SECTION_NAMES[self._section])) | 349 self._SECTION_NAMES[self._section])) | 
| 354 | 350 | 
| (...skipping 2077 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2432 check_braces(clean_lines, line_number, error) | 2428 check_braces(clean_lines, line_number, error) | 
| 2433 check_exit_statement_simplifications(clean_lines, line_number, error) | 2429 check_exit_statement_simplifications(clean_lines, line_number, error) | 
| 2434 check_spacing(file_extension, clean_lines, line_number, error) | 2430 check_spacing(file_extension, clean_lines, line_number, error) | 
| 2435 check_check(clean_lines, line_number, error) | 2431 check_check(clean_lines, line_number, error) | 
| 2436 check_deprecated_macros(clean_lines, line_number, error) | 2432 check_deprecated_macros(clean_lines, line_number, error) | 
| 2437 check_for_comparisons_to_boolean(clean_lines, line_number, error) | 2433 check_for_comparisons_to_boolean(clean_lines, line_number, error) | 
| 2438 check_for_null(clean_lines, line_number, file_state, error) | 2434 check_for_null(clean_lines, line_number, file_state, error) | 
| 2439 check_enum_casing(clean_lines, line_number, enum_state, error) | 2435 check_enum_casing(clean_lines, line_number, enum_state, error) | 
| 2440 | 2436 | 
| 2441 | 2437 | 
| 2442 _RE_PATTERN_INCLUDE_NEW_STYLE = re.compile(r'#include +"[^/]+\.h"') | |
| 2443 _RE_PATTERN_INCLUDE = re.compile(r'^\s*#\s*include\s*([<"])([^>"]*)[>"].*$') | 2438 _RE_PATTERN_INCLUDE = re.compile(r'^\s*#\s*include\s*([<"])([^>"]*)[>"].*$') | 
| 2444 # Matches the first component of a filename delimited by -s and _s. That is: | 2439 # Matches the first component of a filename delimited by -s and _s. That is: | 
| 2445 # _RE_FIRST_COMPONENT.match('foo').group(0) == 'foo' | 2440 # _RE_FIRST_COMPONENT.match('foo').group(0) == 'foo' | 
| 2446 # _RE_FIRST_COMPONENT.match('foo.cpp').group(0) == 'foo' | 2441 # _RE_FIRST_COMPONENT.match('foo.cpp').group(0) == 'foo' | 
| 2447 # _RE_FIRST_COMPONENT.match('foo-bar_baz.cpp').group(0) == 'foo' | 2442 # _RE_FIRST_COMPONENT.match('foo-bar_baz.cpp').group(0) == 'foo' | 
| 2448 # _RE_FIRST_COMPONENT.match('foo_bar-baz.cpp').group(0) == 'foo' | 2443 # _RE_FIRST_COMPONENT.match('foo_bar-baz.cpp').group(0) == 'foo' | 
| 2449 _RE_FIRST_COMPONENT = re.compile(r'^[^-_.]+') | 2444 _RE_FIRST_COMPONENT = re.compile(r'^[^-_.]+') | 
| 2450 | 2445 | 
| 2451 | 2446 | 
| 2452 def _drop_common_suffixes(filename): | 2447 def _drop_common_suffixes(filename): | 
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2498 # If it is a system header we know it is classified as _OTHER_HEADER. | 2493 # If it is a system header we know it is classified as _OTHER_HEADER. | 
| 2499 if is_system and not include.startswith('public/'): | 2494 if is_system and not include.startswith('public/'): | 
| 2500 return _OTHER_HEADER | 2495 return _OTHER_HEADER | 
| 2501 | 2496 | 
| 2502 # There cannot be primary includes in header files themselves. Only an | 2497 # There cannot be primary includes in header files themselves. Only an | 
| 2503 # include exactly matches the header filename will be is flagged as | 2498 # include exactly matches the header filename will be is flagged as | 
| 2504 # primary, so that it triggers the "don't include yourself" check. | 2499 # primary, so that it triggers the "don't include yourself" check. | 
| 2505 if filename.endswith('.h') and filename != include: | 2500 if filename.endswith('.h') and filename != include: | 
| 2506 return _OTHER_HEADER | 2501 return _OTHER_HEADER | 
| 2507 | 2502 | 
| 2508 # Qt's moc files do not follow the naming and ordering rules, so they should be skipped | |
| 2509 if include.startswith('moc_') and include.endswith('.cpp'): | |
| 2510 return _MOC_HEADER | |
| 2511 | |
| 2512 if include.endswith('.moc'): | |
| 2513 return _MOC_HEADER | |
| 2514 | |
| 2515 # If the target file basename starts with the include we're checking | 2503 # If the target file basename starts with the include we're checking | 
| 2516 # then we consider it the primary header. | 2504 # then we consider it the primary header. | 
| 2517 target_base = FileInfo(filename).base_name() | 2505 target_base = FileInfo(filename).base_name() | 
| 2518 include_base = FileInfo(include).base_name() | 2506 include_base = FileInfo(include).base_name() | 
| 2519 | 2507 | 
| 2520 # If we haven't encountered a primary header, then be lenient in checking. | 2508 # If we haven't encountered a primary header, then be lenient in checking. | 
| 2521 if not include_state.visited_primary_section(): | 2509 if not include_state.visited_primary_section(): | 
| 2522 if target_base.find(include_base) != -1: | 2510 if target_base.find(include_base) != -1: | 
| 2523 return _PRIMARY_HEADER | 2511 return _PRIMARY_HEADER | 
| 2524 # Qt private APIs use _p.h suffix. | 2512 # Qt private APIs use _p.h suffix. | 
| 
 
dcheng
2017/02/03 18:16:18
Nit: remove this as well
 
Nico
2017/02/03 18:20:38
Done.
 
 | |
| 2525 if include_base.find(target_base) != -1 and include_base.endswith('_p'): | 2513 if include_base.find(target_base) != -1 and include_base.endswith('_p'): | 
| 2526 return _PRIMARY_HEADER | 2514 return _PRIMARY_HEADER | 
| 2527 | 2515 | 
| 2528 # If we already encountered a primary header, perform a strict comparison. | 2516 # If we already encountered a primary header, perform a strict comparison. | 
| 2529 # In case the two filename bases are the same then the above lenient check | 2517 # In case the two filename bases are the same then the above lenient check | 
| 2530 # probably was a false positive. | 2518 # probably was a false positive. | 
| 2531 elif include_state.visited_primary_section() and target_base == include_base : | 2519 elif include_state.visited_primary_section() and target_base == include_base : | 
| 2532 if include == "ResourceHandleWin.h": | 2520 if include == "ResourceHandleWin.h": | 
| 
 
dcheng
2017/02/03 18:16:18
Maybe this too?
 
Nico
2017/02/03 18:20:38
sure, done
 
 | |
| 2533 # FIXME: Thus far, we've only seen one example of these, but if we | 2521 # FIXME: Thus far, we've only seen one example of these, but if we | 
| 2534 # start to see more, please consider generalizing this check | 2522 # start to see more, please consider generalizing this check | 
| 2535 # somehow. | 2523 # somehow. | 
| 2536 return _OTHER_HEADER | 2524 return _OTHER_HEADER | 
| 2537 return _PRIMARY_HEADER | 2525 return _PRIMARY_HEADER | 
| 2538 | 2526 | 
| 2539 return _OTHER_HEADER | 2527 return _OTHER_HEADER | 
| 2540 | 2528 | 
| 2541 | 2529 | 
| 2542 def _does_primary_header_exist(filename): | 2530 def _does_primary_header_exist(filename): | 
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2619 file_extension == "h" , | 2607 file_extension == "h" , | 
| 2620 primary_header_exists ) | 2608 primary_header_exists ) | 
| 2621 | 2609 | 
| 2622 # Check to make sure we have a blank line after primary header. | 2610 # Check to make sure we have a blank line after primary header. | 
| 2623 if not error_message and header_type == _PRIMARY_HEADER: | 2611 if not error_message and header_type == _PRIMARY_HEADER: | 
| 2624 next_line = clean_lines.raw_lines[line_number + 1] | 2612 next_line = clean_lines.raw_lines[line_number + 1] | 
| 2625 if not is_blank_line(next_line): | 2613 if not is_blank_line(next_line): | 
| 2626 error(line_number, 'build/include_order', 4, | 2614 error(line_number, 'build/include_order', 4, | 
| 2627 'You should add a blank line after implementation file\'s own header.') | 2615 'You should add a blank line after implementation file\'s own header.') | 
| 2628 | 2616 | 
| 2629 # Check to make sure all headers besides the primary header are | |
| 2630 # alphabetically sorted. Skip Qt's moc files. | |
| 2631 if not error_message and header_type == _OTHER_HEADER: | |
| 2632 previous_line_number = line_number - 1 | |
| 2633 previous_line = clean_lines.lines[previous_line_number] | |
| 2634 previous_match = _RE_PATTERN_INCLUDE.search(previous_line) | |
| 2635 while (not previous_match and previous_line_number > 0 | |
| 2636 and not search(r'\A(#if|#ifdef|#ifndef|#else|#elif|#endif)', prev ious_line)): | |
| 2637 previous_line_number -= 1 | |
| 2638 previous_line = clean_lines.lines[previous_line_number] | |
| 2639 previous_match = _RE_PATTERN_INCLUDE.search(previous_line) | |
| 2640 if previous_match: | |
| 2641 previous_header_type = include_state.header_types[previous_line_numb er] | |
| 2642 if previous_header_type == _OTHER_HEADER and previous_line.strip() > line.strip(): | |
| 2643 # This type of error is potentially a problem with this line or the previous one, | |
| 2644 # so if the error is filtered for one line, report it for the ne xt. This is so that | |
| 2645 # we properly handle patches, for which only modified lines prod uce errors. | |
| 2646 if not error(line_number - 1, 'build/include_order', 4, 'Alphabe tical sorting problem.'): | |
| 2647 error(line_number, 'build/include_order', 4, 'Alphabetical s orting problem.') | |
| 2648 | |
| 2649 if error_message: | 2617 if error_message: | 
| 2650 if file_extension == 'h': | 2618 if file_extension == 'h': | 
| 2651 error(line_number, 'build/include_order', 4, | 2619 error(line_number, 'build/include_order', 4, | 
| 2652 '%s Should be: alphabetically sorted.' % | 2620 '%s Should be: alphabetically sorted.' % | 
| 
 
dcheng
2017/02/03 18:16:18
What's the path for emitting this error now? I can
 
Nico
2017/02/03 18:20:38
test_check_next_include_order__no_self reaches it
 
dcheng
2017/02/03 18:53:50
Hmm. The "should be: alphabetically sorted" thing
 
 | |
| 2653 error_message) | 2621 error_message) | 
| 2654 else: | 2622 else: | 
| 2655 error(line_number, 'build/include_order', 4, | 2623 error(line_number, 'build/include_order', 4, | 
| 2656 '%s Should be: primary header, blank line, and then alphabetic ally sorted.' % | 2624 '%s Should be: primary header, blank line, and then alphabetic ally sorted.' % | 
| 2657 error_message) | 2625 error_message) | 
| 2658 | 2626 | 
| 2659 | 2627 | 
| 2660 def check_language(filename, clean_lines, line_number, file_extension, include_s tate, | 2628 def check_language(filename, clean_lines, line_number, file_extension, include_s tate, | 
| 2661 file_state, error): | 2629 file_state, error): | 
| 2662 """Checks rules from the 'C++ language rules' section of cppguide.html. | 2630 """Checks rules from the 'C++ language rules' section of cppguide.html. | 
| (...skipping 974 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3637 | 3605 | 
| 3638 def check(self, lines): | 3606 def check(self, lines): | 
| 3639 _process_lines(self.file_path, self.file_extension, lines, | 3607 _process_lines(self.file_path, self.file_extension, lines, | 
| 3640 self.handle_style_error, self.min_confidence) | 3608 self.handle_style_error, self.min_confidence) | 
| 3641 | 3609 | 
| 3642 | 3610 | 
| 3643 # FIXME: Remove this function (requires refactoring unit tests). | 3611 # FIXME: Remove this function (requires refactoring unit tests). | 
| 3644 def process_file_data(filename, file_extension, lines, error, min_confidence, fs =None): | 3612 def process_file_data(filename, file_extension, lines, error, min_confidence, fs =None): | 
| 3645 checker = CppChecker(filename, file_extension, error, min_confidence, fs) | 3613 checker = CppChecker(filename, file_extension, error, min_confidence, fs) | 
| 3646 checker.check(lines) | 3614 checker.check(lines) | 
| OLD | NEW |