Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(246)

Side by Side Diff: Tools/Scripts/webkitpy/style/checkers/cpp.py

Issue 24406002: Add code style check error for using static_cast instead of toFoo function. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Corrected base_dir to Source to avoid searching header file in LayoutTests Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | Tools/Scripts/webkitpy/style/checkers/cpp_unittest.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 29 matching lines...) Expand all
40 import math # for log 40 import math # for log
41 import os 41 import os
42 import os.path 42 import os.path
43 import re 43 import re
44 import sre_compile 44 import sre_compile
45 import string 45 import string
46 import sys 46 import sys
47 import unicodedata 47 import unicodedata
48 48
49 from webkitpy.common.memoized import memoized 49 from webkitpy.common.memoized import memoized
50 from webkitpy.common.system.filesystem import FileSystem
50 51
51 # The key to use to provide a class to fake loading a header file. 52 # The key to use to provide a class to fake loading a header file.
52 INCLUDE_IO_INJECTION_KEY = 'include_header_io' 53 INCLUDE_IO_INJECTION_KEY = 'include_header_io'
53 54
54 # Headers that we consider STL headers. 55 # Headers that we consider STL headers.
55 _STL_HEADERS = frozenset([ 56 _STL_HEADERS = frozenset([
56 'algobase.h', 'algorithm', 'alloc.h', 'bitset', 'deque', 'exception', 57 'algobase.h', 'algorithm', 'alloc.h', 'bitset', 'deque', 'exception',
57 'function.h', 'functional', 'hash_map', 'hash_map.h', 'hash_set', 58 'function.h', 'functional', 'hash_map', 'hash_map.h', 'hash_set',
58 'hash_set.h', 'iterator', 'list', 'list.h', 'map', 'memory', 'pair.h', 59 'hash_set.h', 'iterator', 'list', 'list.h', 'map', 'memory', 'pair.h',
59 'pthread_alloc', 'queue', 'set', 'set.h', 'sstream', 'stack', 60 'pthread_alloc', 'queue', 'set', 'set.h', 'sstream', 'stack',
(...skipping 3217 matching lines...) Expand 10 before | Expand all | Expand 10 after
3277 error(line_number, 'runtime/bitfields', 5, 3278 error(line_number, 'runtime/bitfields', 5,
3278 'Please declare integral type bitfields with either signed or unsi gned.') 3279 'Please declare integral type bitfields with either signed or unsi gned.')
3279 3280
3280 check_identifier_name_in_declaration(filename, line_number, line, file_state , error) 3281 check_identifier_name_in_declaration(filename, line_number, line, file_state , error)
3281 3282
3282 # Check for unsigned int (should be just 'unsigned') 3283 # Check for unsigned int (should be just 'unsigned')
3283 if search(r'\bunsigned int\b', line): 3284 if search(r'\bunsigned int\b', line):
3284 error(line_number, 'runtime/unsigned', 1, 3285 error(line_number, 'runtime/unsigned', 1,
3285 'Omit int when using unsigned') 3286 'Omit int when using unsigned')
3286 3287
3287 # Check that we're not using static_cast<Text*>. 3288 # Check for usage of static_cast<Classname*>.
3288 if search(r'\bstatic_cast<Text\*>', line): 3289 check_for_object_static_cast(filename, line_number, line, error)
3289 error(line_number, 'readability/check', 4, 3290
3290 'Consider using toText helper function in WebCore/dom/Text.h '
3291 'instead of static_cast<Text*>')
3292 3291
3293 def check_identifier_name_in_declaration(filename, line_number, line, file_state , error): 3292 def check_identifier_name_in_declaration(filename, line_number, line, file_state , error):
3294 """Checks if identifier names contain any underscores. 3293 """Checks if identifier names contain any underscores.
3295 3294
3296 As identifiers in libraries we are using have a bunch of 3295 As identifiers in libraries we are using have a bunch of
3297 underscores, we only warn about the declarations of identifiers 3296 underscores, we only warn about the declarations of identifiers
3298 and don't check use of identifiers. 3297 and don't check use of identifiers.
3299 3298
3300 Args: 3299 Args:
3301 filename: The name of the current file. 3300 filename: The name of the current file.
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
3414 return 3413 return
3415 # We should continue checking if this is a function 3414 # We should continue checking if this is a function
3416 # declaration because we need to check its arguments. 3415 # declaration because we need to check its arguments.
3417 # Also, we need to check multiple declarations. 3416 # Also, we need to check multiple declarations.
3418 if character_after_identifier != '(' and character_after_identifier != ' ,': 3417 if character_after_identifier != '(' and character_after_identifier != ' ,':
3419 return 3418 return
3420 3419
3421 number_of_identifiers += 1 3420 number_of_identifiers += 1
3422 line = line[matched.end():] 3421 line = line[matched.end():]
3423 3422
3423
3424 def check_for_toFoo_definition(filename, pattern, error):
3425 """ Reports for using static_cast instead of toFoo convenience function.
3426
3427 This function will output warnings to make sure you are actually using
3428 the added toFoo conversion functions rather than directly hard coding
3429 the static_cast<Classname*> call. For example, you should toHTMLELement(Node *)
3430 to convert Node* to HTMLElement*, instead of static_cast<HTMLElement*>(Node* )
3431
3432 Args:
3433 filename: The name of the header file in which to check for toFoo definiti on.
3434 pattern: The conversion function pattern to grep for.
3435 error: The function to call with any errors found.
3436 """
3437 def get_abs_filepath(filename):
3438 fileSystem = FileSystem()
3439 base_dir = fileSystem.path_to_module(FileSystem.__module__).split('WebKi t', 1)[0]
3440 base_dir = ''.join((base_dir, 'WebKit/Source'))
3441 for root, dirs, names in os.walk(base_dir):
3442 if filename in names:
3443 return os.path.join(root, filename)
3444 return None
3445
3446 def grep(lines, pattern, error):
3447 matches = []
3448 function_state = None
3449 for line_number in xrange(lines.num_lines()):
3450 line = (lines.elided[line_number]).rstrip()
3451 try:
3452 if pattern in line:
3453 if not function_state:
3454 function_state = _FunctionState(1)
3455 detect_functions(lines, line_number, function_state, error)
3456 # Exclude the match of dummy conversion function. Dummy func tion is just to
3457 # catch invalid conversions and shouldn't be part of possibl e alternatives.
3458 result = re.search(r'%s(\s+)%s' % ("void", pattern), line)
3459 if not result:
3460 matches.append([line, function_state.body_start_position .row, function_state.end_position.row + 1])
3461 function_state = None
3462 except UnicodeDecodeError:
3463 # There would be no non-ascii characters in the codebase ever. T he only exception
3464 # would be comments/copyright text which might have non-ascii ch aracters. Hence,
3465 # it is prefectly safe to catch the UnicodeDecodeError and just pass the line.
3466 pass
3467
3468 return matches
3469
3470 def check_in_mock_header(filename, matches=None, io=codecs):
3471 if not filename == 'Foo.h':
3472 return False
3473
3474 io = _unit_test_config.get(INCLUDE_IO_INJECTION_KEY, codecs)
3475 header_file = None
3476 try:
3477 header_file = io.open(filename, 'r', 'utf8', 'replace')
3478 except IOError:
3479 return False
3480 line_number = 0
3481 for line in header_file:
3482 line_number += 1
3483 matched = re.search(r'\btoFoo\b', line)
3484 if matched:
3485 matches.append(['toFoo', line_number, line_number + 3])
3486 return True
3487
3488 # For unit testing only, avoid header search and lookup locally.
3489 matches = []
3490 mock_def_found = check_in_mock_header(filename, matches)
3491 if mock_def_found:
3492 return matches
3493
3494 # Regular style check flow. Search for actual header file & defs.
3495 file_path = get_abs_filepath(filename)
3496 if not file_path:
3497 return None
3498 try:
3499 f = open(file_path)
3500 clean_lines = CleansedLines(f.readlines())
3501 finally:
3502 f.close()
3503
3504 # Make a list of all genuine alternatives to static_cast.
3505 matches = grep(clean_lines, pattern, error)
3506 return matches
3507
3508
3509 def check_for_object_static_cast(processing_file, line_number, line, error):
3510 """Checks for a Cpp-style static cast on objects by looking for the pattern.
3511
3512 Args:
3513 processing_file: The name of the processing file.
3514 line_number: The number of the line to check.
3515 line: The line of code to check.
3516 error: The function to call with any errors found.
3517 """
3518 matched = search(r'\bstatic_cast<(\s*\w*:?:?\w+\s*\*+\s*)>', line)
3519 if not matched:
3520 return
3521
3522 class_name = re.sub('[\*]', '', matched.group(1))
3523 class_name = class_name.strip()
3524 # Ignore (for now) when the casting is to void*,
3525 if class_name == 'void':
3526 return
3527
3528 namespace_pos = class_name.find(':')
3529 if not namespace_pos == -1:
3530 class_name = class_name[namespace_pos + 2:]
3531
3532 header_file = ''.join((class_name, '.h'))
3533 matches = check_for_toFoo_definition(header_file, ''.join(('to', class_name) ), error)
3534 # Ignore (for now) if not able to find the header where toFoo might be defin ed.
3535 # TODO: Handle cases where Classname might be defined in some other header o r cpp file.
3536 if matches is None:
3537 return
3538
3539 report_error = True
3540 # Ensure found static_cast instance is not from within toFoo definition itse lf.
3541 if (os.path.basename(processing_file) == header_file):
3542 for item in matches:
3543 if line_number in range(item[1], item[2]):
3544 report_error = False
3545 break
3546
3547 if report_error:
3548 if len(matches):
3549 # toFoo is defined - enforce using it.
3550 # TODO: Suggest an appropriate toFoo from the alternatives present i n matches.
3551 error(line_number, 'runtime/casting', 4,
3552 'static_cast of class objects is not allowed. Use to%s defined in %s.' %
3553 (class_name, header_file))
3554 else:
3555 # No toFoo defined - enforce definition & usage.
3556 # TODO: Automate the generation of toFoo() to avoid any slippages ev er.
3557 error(line_number, 'runtime/casting', 4,
3558 'static_cast of class objects is not allowed. Add to%s in %s a nd use it instead.' %
3559 (class_name, header_file))
3560
3561
3424 def check_c_style_cast(line_number, line, raw_line, cast_type, pattern, 3562 def check_c_style_cast(line_number, line, raw_line, cast_type, pattern,
3425 error): 3563 error):
3426 """Checks for a C-style cast by looking for the pattern. 3564 """Checks for a C-style cast by looking for the pattern.
3427 3565
3428 This also handles sizeof(type) warnings, due to similarity of content. 3566 This also handles sizeof(type) warnings, due to similarity of content.
3429 3567
3430 Args: 3568 Args:
3431 line_number: The number of the line to check. 3569 line_number: The number of the line to check.
3432 line: The line of code to check. 3570 line: The line of code to check.
3433 raw_line: The raw line of code to check, with comments. 3571 raw_line: The raw line of code to check, with comments.
(...skipping 479 matching lines...) Expand 10 before | Expand all | Expand 10 after
3913 self.handle_style_error, self.min_confidence) 4051 self.handle_style_error, self.min_confidence)
3914 4052
3915 4053
3916 # FIXME: Remove this function (requires refactoring unit tests). 4054 # FIXME: Remove this function (requires refactoring unit tests).
3917 def process_file_data(filename, file_extension, lines, error, min_confidence, un it_test_config): 4055 def process_file_data(filename, file_extension, lines, error, min_confidence, un it_test_config):
3918 global _unit_test_config 4056 global _unit_test_config
3919 _unit_test_config = unit_test_config 4057 _unit_test_config = unit_test_config
3920 checker = CppChecker(filename, file_extension, error, min_confidence) 4058 checker = CppChecker(filename, file_extension, error, min_confidence)
3921 checker.check(lines) 4059 checker.check(lines)
3922 _unit_test_config = {} 4060 _unit_test_config = {}
OLDNEW
« no previous file with comments | « no previous file | Tools/Scripts/webkitpy/style/checkers/cpp_unittest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698