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 3393 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3404 # We should continue checking if this is a function | 3404 # We should continue checking if this is a function |
3405 # declaration because we need to check its arguments. | 3405 # declaration because we need to check its arguments. |
3406 # Also, we need to check multiple declarations. | 3406 # Also, we need to check multiple declarations. |
3407 if character_after_identifier != '(' and character_after_identifier != ' ,': | 3407 if character_after_identifier != '(' and character_after_identifier != ' ,': |
3408 return | 3408 return |
3409 | 3409 |
3410 number_of_identifiers += 1 | 3410 number_of_identifiers += 1 |
3411 line = line[matched.end():] | 3411 line = line[matched.end():] |
3412 | 3412 |
3413 | 3413 |
3414 def check_for_toFoo_definition(filename, pattern, error): | 3414 def check_for_toFoo_definition(filename, search_func_name, grep_patterns, error) : |
aarya
2014/01/27 19:45:56
check_for_toFoo_definition -> check_for_cast_defin
r.kasibhatla
2014/02/03 15:29:15
Done.
| |
3415 """ Reports for using static_cast instead of toFoo convenience function. | 3415 """Checks for a Cpp-style static cast on objects by searching for the patter n. |
3416 | |
3417 This function will output warnings to make sure you are actually using | |
3418 the added toFoo conversion functions rather than directly hard coding | |
3419 the static_cast<Classname*> call. For example, you should toHTMLELement(Node *) | |
3420 to convert Node* to HTMLElement*, instead of static_cast<HTMLElement*>(Node* ) | |
3421 | 3416 |
3422 Args: | 3417 Args: |
3423 filename: The name of the header file in which to check for toFoo definiti on. | 3418 filename: The name of the header file in which to check for toFoo definiti on. |
3424 pattern: The conversion function pattern to grep for. | 3419 search_func_name: The toFoo convinience function string. |
Dirk Pranke
2014/01/27 19:38:51
Nit: "convenience".
aarya
2014/01/27 19:45:56
typo: convenience
r.kasibhatla
2014/02/03 15:29:15
Done.
r.kasibhatla
2014/02/03 15:29:15
Done.
| |
3420 grep_patterns: Array consisting the regex patterns to search for. | |
3425 error: The function to call with any errors found. | 3421 error: The function to call with any errors found. |
3426 """ | 3422 """ |
3427 def get_abs_filepath(filename): | 3423 def get_abs_filepath(filename): |
3428 fileSystem = FileSystem() | 3424 fileSystem = FileSystem() |
3429 base_dir = fileSystem.path_to_module(FileSystem.__module__).split('WebKi t', 1)[0] | 3425 base_dir = fileSystem.path_to_module(FileSystem.__module__).split('WebKi t', 1)[0] |
3430 base_dir = ''.join((base_dir, 'WebKit/Source')) | 3426 base_dir = ''.join((base_dir, 'WebKit/Source')) |
3431 for root, dirs, names in os.walk(base_dir): | 3427 for root, dirs, names in os.walk(base_dir): |
3432 if filename in names: | 3428 if filename in names: |
3433 return os.path.join(root, filename) | 3429 return os.path.join(root, filename) |
3434 return None | 3430 return None |
3435 | 3431 |
3436 def grep(lines, pattern, error): | 3432 def grep(lines, search_func_name, grep_patterns, error): |
3437 matches = [] | 3433 matches = [] |
3438 function_state = None | 3434 function_state = None |
3439 for line_number in xrange(lines.num_lines()): | 3435 for line_number in xrange(lines.num_lines()): |
3440 line = (lines.elided[line_number]).rstrip() | 3436 line = (lines.elided[line_number]).rstrip() |
3441 try: | 3437 try: |
3442 if pattern in line: | 3438 # Search for DEFINE_TYPE_CASTS pattern in the file. |
3439 if re.search(grep_patterns[0], line): | |
aarya
2014/01/27 19:45:56
grep_patterns[0], grep_patterns[1] is not a good w
r.kasibhatla
2014/02/03 15:29:15
Done.
| |
3440 matches.append([line, line_number + 1, line_number + 1]) | |
3441 # DEFINE_TYPE_CASTS pattern not found. Search for toFoo pattern instead in the file. | |
Dirk Pranke
2014/01/27 19:38:51
Nit: it's a bit odd to me to have a comment immedi
r.kasibhatla
2014/02/03 15:29:15
Done.
| |
3442 elif re.search(grep_patterns[1], line): | |
3443 if not function_state: | 3443 if not function_state: |
3444 function_state = _FunctionState(1) | 3444 function_state = _FunctionState(1) |
3445 detect_functions(lines, line_number, function_state, error) | 3445 detect_functions(lines, line_number, function_state, error) |
3446 # Exclude the match of dummy conversion function. Dummy func tion is just to | 3446 # Exclude the match of dummy conversion function. Dummy func tion is just to |
3447 # catch invalid conversions and shouldn't be part of possibl e alternatives. | 3447 # catch invalid conversions and shouldn't be part of possibl e alternatives. |
3448 result = re.search(r'%s(\s+)%s' % ("void", pattern), line) | 3448 result = re.search(r'%s(\s+)%s' % ("void", search_func_name) , line) |
3449 if not result: | 3449 if not result: |
3450 matches.append([line, function_state.body_start_position .row, function_state.end_position.row + 1]) | 3450 matches.append([line, function_state.body_start_position .row, function_state.end_position.row + 1]) |
3451 function_state = None | 3451 function_state = None |
3452 except UnicodeDecodeError: | 3452 except UnicodeDecodeError: |
3453 # There would be no non-ascii characters in the codebase ever. T he only exception | 3453 # There would be no non-ascii characters in the codebase ever. T he only exception |
3454 # would be comments/copyright text which might have non-ascii ch aracters. Hence, | 3454 # would be comments/copyright text which might have non-ascii ch aracters. Hence, |
3455 # it is prefectly safe to catch the UnicodeDecodeError and just pass the line. | 3455 # it is prefectly safe to catch the UnicodeDecodeError and just pass the line. |
3456 pass | 3456 pass |
3457 | 3457 |
3458 return matches | 3458 return matches |
(...skipping 25 matching lines...) Expand all Loading... | |
3484 file_path = get_abs_filepath(filename) | 3484 file_path = get_abs_filepath(filename) |
3485 if not file_path: | 3485 if not file_path: |
3486 return None | 3486 return None |
3487 try: | 3487 try: |
3488 f = open(file_path) | 3488 f = open(file_path) |
3489 clean_lines = CleansedLines(f.readlines()) | 3489 clean_lines = CleansedLines(f.readlines()) |
3490 finally: | 3490 finally: |
3491 f.close() | 3491 f.close() |
3492 | 3492 |
3493 # Make a list of all genuine alternatives to static_cast. | 3493 # Make a list of all genuine alternatives to static_cast. |
3494 matches = grep(clean_lines, pattern, error) | 3494 matches = grep(clean_lines, search_func_name, grep_patterns, error) |
3495 return matches | 3495 return matches |
3496 | 3496 |
3497 | 3497 |
3498 def check_for_object_static_cast(processing_file, line_number, line, error): | 3498 def check_for_object_static_cast(processing_file, line_number, line, error): |
3499 """Checks for a Cpp-style static cast on objects by looking for the pattern. | 3499 """ Reports for using static_cast instead of toFoo convenience function. |
3500 | |
3501 This function will output warnings to make sure you are actually using | |
3502 the added toFoo conversion functions rather than directly hard coding | |
3503 the static_cast<Classname*> call. For example, you should toHTMLELement(Node *) | |
3504 to convert Node* to HTMLElement*, instead of static_cast<HTMLElement*>(Node* ) | |
3500 | 3505 |
3501 Args: | 3506 Args: |
3502 processing_file: The name of the processing file. | 3507 processing_file: The name of the processing file. |
3503 line_number: The number of the line to check. | 3508 line_number: The number of the line to check. |
3504 line: The line of code to check. | 3509 line: The line of code to check. |
3505 error: The function to call with any errors found. | 3510 error: The function to call with any errors found. |
3506 """ | 3511 """ |
3512 | |
3507 matched = search(r'\bstatic_cast<(\s*\w*:?:?\w+\s*\*+\s*)>', line) | 3513 matched = search(r'\bstatic_cast<(\s*\w*:?:?\w+\s*\*+\s*)>', line) |
3508 if not matched: | 3514 if not matched: |
3509 return | 3515 return |
3510 | 3516 |
3511 class_name = re.sub('[\*]', '', matched.group(1)) | 3517 class_name = re.sub('[\*]', '', matched.group(1)) |
3512 class_name = class_name.strip() | 3518 class_name = class_name.strip() |
3513 # Ignore (for now) when the casting is to void*, | 3519 # Ignore (for now) when the casting is to void*, |
3514 if class_name == 'void': | 3520 if class_name == 'void': |
3515 return | 3521 return |
3516 | 3522 |
3517 namespace_pos = class_name.find(':') | 3523 namespace_pos = class_name.find(':') |
3518 if not namespace_pos == -1: | 3524 if not namespace_pos == -1: |
3519 class_name = class_name[namespace_pos + 2:] | 3525 class_name = class_name[namespace_pos + 2:] |
3520 | 3526 |
3521 header_file = ''.join((class_name, '.h')) | 3527 header_file = ''.join((class_name, '.h')) |
3522 matches = check_for_toFoo_definition(header_file, ''.join(('to', class_name) ), error) | 3528 toFoo_name = ''.join(('to', class_name)) |
3523 # Ignore (for now) if not able to find the header where toFoo might be defin ed. | 3529 matching_patterns = [] |
3524 # TODO: Handle cases where Classname might be defined in some other header o r cpp file. | 3530 matching_patterns.append(re.compile(r'\s*DEFINE_(\w*)TYPE_CASTS\(%s,(.+)(\); $)' % class_name)) |
3531 matching_patterns.append(re.compile(r'[ \w]*%s\*\s+%s\((.+)\)$' % (class_nam e, toFoo_name))) | |
3532 | |
3533 matches = check_for_toFoo_definition(header_file, toFoo_name, matching_patte rns, error) | |
3534 # FIXME(kphanee): Handle cases where Classname might be defined in some othe r header or cpp file. | |
Dirk Pranke
2014/01/27 19:38:51
Nit: We don't use usernames in FIXMEs.
r.kasibhatla
2014/02/03 15:29:15
Done.
| |
3535 # It would remove this hack for ignoring not finding Foo.h | |
aarya
2014/01/27 19:45:56
This line is not clear, can you rephrase this.
r.kasibhatla
2014/02/03 15:29:15
Done.
| |
3525 if matches is None: | 3536 if matches is None: |
3526 return | 3537 return |
3527 | 3538 |
3528 report_error = True | 3539 report_error = True |
3529 # Ensure found static_cast instance is not from within toFoo definition itse lf. | 3540 # Ensure found static_cast instance is not from within toFoo definition itse lf. |
3530 if (os.path.basename(processing_file) == header_file): | 3541 if (os.path.basename(processing_file) == header_file): |
3531 for item in matches: | 3542 for item in matches: |
3532 if line_number in range(item[1], item[2]): | 3543 if line_number in range(item[1], item[2]): |
3533 report_error = False | 3544 report_error = False |
3534 break | 3545 break |
3535 | 3546 |
3536 if report_error: | 3547 if report_error: |
3537 if len(matches): | 3548 if len(matches): |
3538 # toFoo is defined - enforce using it. | 3549 # toFoo is defined - enforce using it. |
3539 # TODO: Suggest an appropriate toFoo from the alternatives present i n matches. | 3550 # TODO: Suggest an appropriate toFoo from the alternatives present i n matches. |
3540 error(line_number, 'runtime/casting', 4, | 3551 error(line_number, 'security/casting', 4, |
3541 'static_cast of class objects is not allowed. Use to%s defined in %s.' % | 3552 'static_cast of class objects is not allowed. Use to%s defined in %s.' % |
3542 (class_name, header_file)) | 3553 (class_name, header_file)) |
3543 else: | 3554 else: |
3544 # No toFoo defined - enforce definition & usage. | 3555 # No toFoo defined - enforce definition & usage. |
3545 # TODO: Automate the generation of toFoo() to avoid any slippages ev er. | 3556 # TODO: Automate the generation of toFoo() to avoid any slippages ev er. |
3546 error(line_number, 'runtime/casting', 4, | 3557 error(line_number, 'runtime/casting', 4, |
3547 'static_cast of class objects is not allowed. Add to%s in %s a nd use it instead.' % | 3558 'static_cast of class objects is not allowed. Add to%s in %s a nd use it instead.' % |
3548 (class_name, header_file)) | 3559 (class_name, header_file)) |
3549 | 3560 |
3550 | 3561 |
(...skipping 426 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3977 'runtime/memset', | 3988 'runtime/memset', |
3978 'runtime/printf', | 3989 'runtime/printf', |
3979 'runtime/printf_format', | 3990 'runtime/printf_format', |
3980 'runtime/references', | 3991 'runtime/references', |
3981 'runtime/rtti', | 3992 'runtime/rtti', |
3982 'runtime/sizeof', | 3993 'runtime/sizeof', |
3983 'runtime/string', | 3994 'runtime/string', |
3984 'runtime/threadsafe_fn', | 3995 'runtime/threadsafe_fn', |
3985 'runtime/unsigned', | 3996 'runtime/unsigned', |
3986 'runtime/virtual', | 3997 'runtime/virtual', |
3998 'security/casting', | |
3987 'whitespace/blank_line', | 3999 'whitespace/blank_line', |
3988 'whitespace/braces', | 4000 'whitespace/braces', |
3989 'whitespace/comma', | 4001 'whitespace/comma', |
3990 'whitespace/comments', | 4002 'whitespace/comments', |
3991 'whitespace/declaration', | 4003 'whitespace/declaration', |
3992 'whitespace/end_of_line', | 4004 'whitespace/end_of_line', |
3993 'whitespace/ending_newline', | 4005 'whitespace/ending_newline', |
3994 'whitespace/indent', | 4006 'whitespace/indent', |
3995 'whitespace/line_length', | 4007 'whitespace/line_length', |
3996 'whitespace/newline', | 4008 'whitespace/newline', |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4039 | 4051 |
4040 def check(self, lines): | 4052 def check(self, lines): |
4041 _process_lines(self.file_path, self.file_extension, lines, | 4053 _process_lines(self.file_path, self.file_extension, lines, |
4042 self.handle_style_error, self.min_confidence) | 4054 self.handle_style_error, self.min_confidence) |
4043 | 4055 |
4044 | 4056 |
4045 # FIXME: Remove this function (requires refactoring unit tests). | 4057 # FIXME: Remove this function (requires refactoring unit tests). |
4046 def process_file_data(filename, file_extension, lines, error, min_confidence, fs =None): | 4058 def process_file_data(filename, file_extension, lines, error, min_confidence, fs =None): |
4047 checker = CppChecker(filename, file_extension, error, min_confidence, fs) | 4059 checker = CppChecker(filename, file_extension, error, min_confidence, fs) |
4048 checker.check(lines) | 4060 checker.check(lines) |
OLD | NEW |