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 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
271 Args: | 271 Args: |
272 s: a string which is a substring of line after '(' | 272 s: a string which is a substring of line after '(' |
273 (e.g., "a == (b + c))"). | 273 (e.g., "a == (b + c))"). |
274 | 274 |
275 Returns: | 275 Returns: |
276 A pair of strings (prefix before first unmatched ')', | 276 A pair of strings (prefix before first unmatched ')', |
277 remainder of s after first unmatched ')'), e.g., | 277 remainder of s after first unmatched ')'), e.g., |
278 up_to_unmatched_closing_paren("a == (b + c)) { ") | 278 up_to_unmatched_closing_paren("a == (b + c)) { ") |
279 returns "a == (b + c)", " {". | 279 returns "a == (b + c)", " {". |
280 Returns None, None if there is no unmatched ')' | 280 Returns None, None if there is no unmatched ')' |
281 | |
282 """ | 281 """ |
283 i = 1 | 282 i = 1 |
284 for pos, c in enumerate(s): | 283 for pos, c in enumerate(s): |
285 if c == '(': | 284 if c == '(': |
286 i += 1 | 285 i += 1 |
287 elif c == ')': | 286 elif c == ')': |
288 i -= 1 | 287 i -= 1 |
289 if i == 0: | 288 if i == 0: |
290 return s[:pos], s[pos + 1:] | 289 return s[:pos], s[pos + 1:] |
291 return None, None | 290 return None, None |
292 | 291 |
293 | 292 |
294 class _IncludeState(dict): | 293 class _IncludeState(dict): |
295 """Tracks line numbers for includes, and the order in which includes appear. | 294 """Tracks line numbers for includes, and the order in which includes appear. |
296 | 295 |
297 As a dict, an _IncludeState object serves as a mapping between include | 296 As a dict, an _IncludeState object serves as a mapping between include |
298 filename and line number on which that file was included. | 297 filename and line number on which that file was included. |
299 | 298 |
300 Call check_next_include_order() once for each header in the file, passing | 299 Call check_next_include_order() once for each header in the file, passing |
301 in the type constants defined above. Calls in an illegal order will | 300 in the type constants defined above. Calls in an illegal order will |
302 raise an _IncludeError with an appropriate error message. | 301 raise an _IncludeError with an appropriate error message. |
303 | |
304 """ | 302 """ |
305 # self._section will move monotonically through this set. If it ever | 303 # self._section will move monotonically through this set. If it ever |
306 # needs to move backwards, check_next_include_order will raise an error. | 304 # needs to move backwards, check_next_include_order will raise an error. |
307 _INITIAL_SECTION = 0 | 305 _INITIAL_SECTION = 0 |
308 _PRIMARY_SECTION = 1 | 306 _PRIMARY_SECTION = 1 |
309 _OTHER_SECTION = 2 | 307 _OTHER_SECTION = 2 |
310 | 308 |
311 _TYPE_NAMES = { | 309 _TYPE_NAMES = { |
312 _PRIMARY_HEADER: 'header this file implements', | 310 _PRIMARY_HEADER: 'header this file implements', |
313 _OTHER_HEADER: 'other header', | 311 _OTHER_HEADER: 'other header', |
(...skipping 20 matching lines...) Expand all Loading... |
334 This function also updates the internal state to be ready to check | 332 This function also updates the internal state to be ready to check |
335 the next include. | 333 the next include. |
336 | 334 |
337 Args: | 335 Args: |
338 header_type: One of the _XXX_HEADER constants defined above. | 336 header_type: One of the _XXX_HEADER constants defined above. |
339 file_is_header: Whether the file that owns this _IncludeState is itsel
f a header | 337 file_is_header: Whether the file that owns this _IncludeState is itsel
f a header |
340 | 338 |
341 Returns: | 339 Returns: |
342 The empty string if the header is in the right order, or an | 340 The empty string if the header is in the right order, or an |
343 error message describing what's wrong. | 341 error message describing what's wrong. |
344 | |
345 """ | 342 """ |
346 if header_type == _PRIMARY_HEADER and file_is_header: | 343 if header_type == _PRIMARY_HEADER and file_is_header: |
347 return 'Header file should not contain itself.' | 344 return 'Header file should not contain itself.' |
348 if header_type == _MOC_HEADER: | 345 if header_type == _MOC_HEADER: |
349 return '' | 346 return '' |
350 | 347 |
351 error_message = '' | 348 error_message = '' |
352 if self._section != self._OTHER_SECTION: | 349 if self._section != self._OTHER_SECTION: |
353 before_error_message = ('Found %s before %s' % | 350 before_error_message = ('Found %s before %s' % |
354 (self._TYPE_NAMES[header_type], | 351 (self._TYPE_NAMES[header_type], |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
396 self.row = row | 393 self.row = row |
397 | 394 |
398 @memoized | 395 @memoized |
399 def lower_with_underscores_name(self): | 396 def lower_with_underscores_name(self): |
400 """Returns the parameter name in the lower with underscores format.""" | 397 """Returns the parameter name in the lower with underscores format.""" |
401 return _convert_to_lower_with_underscores(self.name) | 398 return _convert_to_lower_with_underscores(self.name) |
402 | 399 |
403 | 400 |
404 class SingleLineView(object): | 401 class SingleLineView(object): |
405 """Converts multiple lines into a single line (with line breaks replaced by
a | 402 """Converts multiple lines into a single line (with line breaks replaced by
a |
406 space) to allow for easier searching.""" | 403 space) to allow for easier searching. |
| 404 """ |
407 | 405 |
408 def __init__(self, lines, start_position, end_position): | 406 def __init__(self, lines, start_position, end_position): |
409 """Create a SingleLineView instance. | 407 """Create a SingleLineView instance. |
410 | 408 |
411 Args: | 409 Args: |
412 lines: a list of multiple lines to combine into a single line. | 410 lines: a list of multiple lines to combine into a single line. |
413 start_position: offset within lines of where to start the single line. | 411 start_position: offset within lines of where to start the single line. |
414 end_position: just after where to end (like a slice operation). | 412 end_position: just after where to end (like a slice operation). |
415 """ | 413 """ |
416 # Get the rows of interest. | 414 # Get the rows of interest. |
(...skipping 15 matching lines...) Expand all Loading... |
432 self._row_lengths = [len(line) + 1 for line in trimmed_lines] | 430 self._row_lengths = [len(line) + 1 for line in trimmed_lines] |
433 self._starting_row = start_position.row | 431 self._starting_row = start_position.row |
434 | 432 |
435 def convert_column_to_row(self, single_line_column_number): | 433 def convert_column_to_row(self, single_line_column_number): |
436 """Convert the column number from the single line into the original | 434 """Convert the column number from the single line into the original |
437 line number. | 435 line number. |
438 | 436 |
439 Special cases: | 437 Special cases: |
440 * Columns in the added spaces are considered part of the previous line. | 438 * Columns in the added spaces are considered part of the previous line. |
441 * Columns beyond the end of the line are consider part the last line | 439 * Columns beyond the end of the line are consider part the last line |
442 in the view.""" | 440 in the view. |
| 441 """ |
443 total_columns = 0 | 442 total_columns = 0 |
444 row_offset = 0 | 443 row_offset = 0 |
445 while row_offset < len(self._row_lengths) - 1 and single_line_column_num
ber >= total_columns + self._row_lengths[row_offset]: | 444 while row_offset < len(self._row_lengths) - 1 and single_line_column_num
ber >= total_columns + self._row_lengths[row_offset]: |
446 total_columns += self._row_lengths[row_offset] | 445 total_columns += self._row_lengths[row_offset] |
447 row_offset += 1 | 446 row_offset += 1 |
448 return self._starting_row + row_offset | 447 return self._starting_row + row_offset |
449 | 448 |
450 | 449 |
451 def create_skeleton_parameters(all_parameters): | 450 def create_skeleton_parameters(all_parameters): |
452 """Converts a parameter list to a skeleton version. | 451 """Converts a parameter list to a skeleton version. |
453 | 452 |
454 The skeleton only has one word for the parameter name, one word for the type
, | 453 The skeleton only has one word for the parameter name, one word for the type
, |
455 and commas after each parameter and only there. Everything in the skeleton | 454 and commas after each parameter and only there. Everything in the skeleton |
456 remains in the same columns as the original.""" | 455 remains in the same columns as the original. |
| 456 """ |
457 all_simplifications = ( | 457 all_simplifications = ( |
458 # Remove template parameters, function declaration parameters, etc. | 458 # Remove template parameters, function declaration parameters, etc. |
459 r'(<[^<>]*?>)|(\([^\(\)]*?\))|(\{[^\{\}]*?\})', | 459 r'(<[^<>]*?>)|(\([^\(\)]*?\))|(\{[^\{\}]*?\})', |
460 # Remove all initializers. | 460 # Remove all initializers. |
461 r'=[^,]*', | 461 r'=[^,]*', |
462 # Remove :: and everything before it. | 462 # Remove :: and everything before it. |
463 r'[^,]*::', | 463 r'[^,]*::', |
464 # Remove modifiers like &, *. | 464 # Remove modifiers like &, *. |
465 r'[&*]', | 465 r'[&*]', |
466 # Remove const modifiers. | 466 # Remove const modifiers. |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
512 name_offset = find_parameter_name_index(skeleton_parameter) | 512 name_offset = find_parameter_name_index(skeleton_parameter) |
513 parameter = single_line_view.single_line[start_index:end_index] | 513 parameter = single_line_view.single_line[start_index:end_index] |
514 yield Parameter(parameter, name_offset, row) | 514 yield Parameter(parameter, name_offset, row) |
515 | 515 |
516 | 516 |
517 class _FunctionState(object): | 517 class _FunctionState(object): |
518 """Tracks current function name and the number of lines in its body. | 518 """Tracks current function name and the number of lines in its body. |
519 | 519 |
520 Attributes: | 520 Attributes: |
521 min_confidence: The minimum confidence level to use while checking style. | 521 min_confidence: The minimum confidence level to use while checking style. |
522 | |
523 """ | 522 """ |
524 | 523 |
525 _NORMAL_TRIGGER = 250 # for --v=0, 500 for --v=1, etc. | 524 _NORMAL_TRIGGER = 250 # for --v=0, 500 for --v=1, etc. |
526 _TEST_TRIGGER = 400 # about 50% more than _NORMAL_TRIGGER. | 525 _TEST_TRIGGER = 400 # about 50% more than _NORMAL_TRIGGER. |
527 | 526 |
528 def __init__(self, min_confidence): | 527 def __init__(self, min_confidence): |
529 self.min_confidence = min_confidence | 528 self.min_confidence = min_confidence |
530 self.current_function = '' | 529 self.current_function = '' |
531 self.in_a_function = False | 530 self.in_a_function = False |
532 self.lines_in_function = 0 | 531 self.lines_in_function = 0 |
(...skipping 395 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
928 # simultaneously. | 927 # simultaneously. |
929 def get_legacy_header_guard_cpp_variable(filename): | 928 def get_legacy_header_guard_cpp_variable(filename): |
930 """Returns the CPP variable that should be used as a header guard. | 929 """Returns the CPP variable that should be used as a header guard. |
931 | 930 |
932 Args: | 931 Args: |
933 filename: The name of a C++ header file. | 932 filename: The name of a C++ header file. |
934 | 933 |
935 Returns: | 934 Returns: |
936 The CPP variable that should be used as a header guard in the | 935 The CPP variable that should be used as a header guard in the |
937 named file. | 936 named file. |
938 | |
939 """ | 937 """ |
940 | 938 |
941 # Restores original filename in case that style checker is invoked from Emac
s's | 939 # Restores original filename in case that style checker is invoked from Emac
s's |
942 # flymake. | 940 # flymake. |
943 filename = re.sub(r'_flymake\.h$', '.h', filename) | 941 filename = re.sub(r'_flymake\.h$', '.h', filename) |
944 | 942 |
945 standard_name = sub(r'[-.\s]', '_', os.path.basename(filename)) | 943 standard_name = sub(r'[-.\s]', '_', os.path.basename(filename)) |
946 | 944 |
947 # Files under WTF typically have header guards that start with WTF_. | 945 # Files under WTF typically have header guards that start with WTF_. |
948 if '/wtf/' in filename: | 946 if '/wtf/' in filename: |
949 special_name = "WTF_" + standard_name | 947 special_name = "WTF_" + standard_name |
950 else: | 948 else: |
951 special_name = standard_name | 949 special_name = standard_name |
952 return (special_name, standard_name) | 950 return (special_name, standard_name) |
953 | 951 |
954 | 952 |
955 def get_header_guard_cpp_variable(filename): | 953 def get_header_guard_cpp_variable(filename): |
956 """Returns the CPP variable that should be used as a header guard in Chromiu
m-style. | 954 """Returns the CPP variable that should be used as a header guard in Chromiu
m-style. |
957 | 955 |
958 Args: | 956 Args: |
959 filename: The name of a C++ header file. | 957 filename: The name of a C++ header file. |
960 | 958 |
961 Returns: | 959 Returns: |
962 The CPP variable that should be used as a header guard in the | 960 The CPP variable that should be used as a header guard in the |
963 named file in Chromium-style. | 961 named file in Chromium-style. |
964 | |
965 """ | 962 """ |
966 | 963 |
967 # Restores original filename in case that style checker is invoked from Emac
s's | 964 # Restores original filename in case that style checker is invoked from Emac
s's |
968 # flymake. | 965 # flymake. |
969 filename = re.sub(r'_flymake\.h$', '.h', filename) | 966 filename = re.sub(r'_flymake\.h$', '.h', filename) |
970 | 967 |
971 # If it's a full path and starts with Source/, replace Source with blink | 968 # If it's a full path and starts with Source/, replace Source with blink |
972 # since that will be the new style directory. | 969 # since that will be the new style directory. |
973 filename = sub(r'^Source\/', 'blink/', filename) | 970 filename = sub(r'^Source\/', 'blink/', filename) |
974 | 971 |
(...skipping 2569 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3544 # declaration because we need to check its arguments. | 3541 # declaration because we need to check its arguments. |
3545 # Also, we need to check multiple declarations. | 3542 # Also, we need to check multiple declarations. |
3546 if character_after_identifier != '(' and character_after_identifier != '
,': | 3543 if character_after_identifier != '(' and character_after_identifier != '
,': |
3547 return | 3544 return |
3548 | 3545 |
3549 number_of_identifiers += 1 | 3546 number_of_identifiers += 1 |
3550 line = line[matched.end():] | 3547 line = line[matched.end():] |
3551 | 3548 |
3552 | 3549 |
3553 def check_for_toFoo_definition(filename, pattern, error): | 3550 def check_for_toFoo_definition(filename, pattern, error): |
3554 """ Reports for using static_cast instead of toFoo convenience function. | 3551 """Reports for using static_cast instead of toFoo convenience function. |
3555 | 3552 |
3556 This function will output warnings to make sure you are actually using | 3553 This function will output warnings to make sure you are actually using |
3557 the added toFoo conversion functions rather than directly hard coding | 3554 the added toFoo conversion functions rather than directly hard coding |
3558 the static_cast<Classname*> call. For example, you should toHTMLELement(Node
*) | 3555 the static_cast<Classname*> call. For example, you should toHTMLELement(Node
*) |
3559 to convert Node* to HTMLElement*, instead of static_cast<HTMLElement*>(Node*
) | 3556 to convert Node* to HTMLElement*, instead of static_cast<HTMLElement*>(Node*
) |
3560 | 3557 |
3561 Args: | 3558 Args: |
3562 filename: The name of the header file in which to check for toFoo definiti
on. | 3559 filename: The name of the header file in which to check for toFoo definiti
on. |
3563 pattern: The conversion function pattern to grep for. | 3560 pattern: The conversion function pattern to grep for. |
3564 error: The function to call with any errors found. | 3561 error: The function to call with any errors found. |
(...skipping 425 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3990 include_state: An _IncludeState instance in which the headers are inserted
. | 3987 include_state: An _IncludeState instance in which the headers are inserted
. |
3991 function_state: A _FunctionState instance which counts function lines, etc
. | 3988 function_state: A _FunctionState instance which counts function lines, etc
. |
3992 class_state: A _ClassState instance which maintains information about | 3989 class_state: A _ClassState instance which maintains information about |
3993 the current stack of nested class declarations being parsed. | 3990 the current stack of nested class declarations being parsed. |
3994 file_state: A _FileState instance which maintains information about | 3991 file_state: A _FileState instance which maintains information about |
3995 the state of things in the file. | 3992 the state of things in the file. |
3996 enum_state: A _EnumState instance which maintains an enum declaration | 3993 enum_state: A _EnumState instance which maintains an enum declaration |
3997 state. | 3994 state. |
3998 error: A callable to which errors are reported, which takes arguments: | 3995 error: A callable to which errors are reported, which takes arguments: |
3999 line number, error level, and message | 3996 line number, error level, and message |
4000 | |
4001 """ | 3997 """ |
4002 raw_lines = clean_lines.raw_lines | 3998 raw_lines = clean_lines.raw_lines |
4003 detect_functions(clean_lines, line, function_state, error) | 3999 detect_functions(clean_lines, line, function_state, error) |
4004 check_for_function_lengths(clean_lines, line, function_state, error) | 4000 check_for_function_lengths(clean_lines, line, function_state, error) |
4005 if search(r'\bNOLINT\b', raw_lines[line]): # ignore nolint lines | 4001 if search(r'\bNOLINT\b', raw_lines[line]): # ignore nolint lines |
4006 return | 4002 return |
4007 if match(r'\s*\b__asm\b', raw_lines[line]): # Ignore asm lines as they form
at differently. | 4003 if match(r'\s*\b__asm\b', raw_lines[line]): # Ignore asm lines as they form
at differently. |
4008 return | 4004 return |
4009 check_function_definition(filename, file_extension, clean_lines, line, funct
ion_state, error) | 4005 check_function_definition(filename, file_extension, clean_lines, line, funct
ion_state, error) |
4010 check_pass_ptr_usage(clean_lines, line, function_state, error) | 4006 check_pass_ptr_usage(clean_lines, line, function_state, error) |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4147 | 4143 |
4148 fs = None | 4144 fs = None |
4149 | 4145 |
4150 def __init__(self, file_path, file_extension, handle_style_error, | 4146 def __init__(self, file_path, file_extension, handle_style_error, |
4151 min_confidence, fs=None): | 4147 min_confidence, fs=None): |
4152 """Create a CppChecker instance. | 4148 """Create a CppChecker instance. |
4153 | 4149 |
4154 Args: | 4150 Args: |
4155 file_extension: A string that is the file extension, without | 4151 file_extension: A string that is the file extension, without |
4156 the leading dot. | 4152 the leading dot. |
4157 | |
4158 """ | 4153 """ |
4159 self.file_extension = file_extension | 4154 self.file_extension = file_extension |
4160 self.file_path = file_path | 4155 self.file_path = file_path |
4161 self.handle_style_error = handle_style_error | 4156 self.handle_style_error = handle_style_error |
4162 self.min_confidence = min_confidence | 4157 self.min_confidence = min_confidence |
4163 CppChecker.fs = fs or FileSystem() | 4158 CppChecker.fs = fs or FileSystem() |
4164 | 4159 |
4165 # Useful for unit testing. | 4160 # Useful for unit testing. |
4166 def __eq__(self, other): | 4161 def __eq__(self, other): |
4167 """Return whether this CppChecker instance is equal to another.""" | 4162 """Return whether this CppChecker instance is equal to another.""" |
(...skipping 15 matching lines...) Expand all Loading... |
4183 | 4178 |
4184 def check(self, lines): | 4179 def check(self, lines): |
4185 _process_lines(self.file_path, self.file_extension, lines, | 4180 _process_lines(self.file_path, self.file_extension, lines, |
4186 self.handle_style_error, self.min_confidence) | 4181 self.handle_style_error, self.min_confidence) |
4187 | 4182 |
4188 | 4183 |
4189 # FIXME: Remove this function (requires refactoring unit tests). | 4184 # FIXME: Remove this function (requires refactoring unit tests). |
4190 def process_file_data(filename, file_extension, lines, error, min_confidence, fs
=None): | 4185 def process_file_data(filename, file_extension, lines, error, min_confidence, fs
=None): |
4191 checker = CppChecker(filename, file_extension, error, min_confidence, fs) | 4186 checker = CppChecker(filename, file_extension, error, min_confidence, fs) |
4192 checker.check(lines) | 4187 checker.check(lines) |
OLD | NEW |