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

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: 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 _sep = 'src/third_party/WebKit'
inferno 2013/10/01 05:29:38 This will be overkill since we have ton of layout
r.kasibhatla 2013/10/01 09:53:46 Done.
3440 base_dir = fileSystem.path_to_module(FileSystem.__module__).split(_sep, 1)[0]
3441 base_dir = ''.join((base_dir, _sep))
3442 for root, dirs, names in os.walk(base_dir):
3443 if filename in names:
3444 return os.path.join(root, filename)
3445 return None
3446
3447 def grep(lines, pattern, error):
3448 matches = []
3449 function_state = None
3450 for line_number in xrange(lines.num_lines()):
3451 line = (lines.elided[line_number]).rstrip()
3452 try:
3453 if pattern in line:
3454 if not function_state:
3455 function_state = _FunctionState(1)
3456 detect_functions(lines, line_number, function_state, error)
3457 # Exclude the match of dummy conversion function. Dummy func tion is just to
3458 # catch invalid conversions and shouldn't be part of possibl e alternatives.
3459 result = re.search(r'%s(\s+)%s' % ("void", pattern), line)
3460 if not result:
3461 matches.append([line, function_state.body_start_position .row, function_state.end_position.row + 1])
3462 function_state = None
3463 except UnicodeDecodeError:
3464 # There would be no non-ascii characters in the codebase ever. T he only exception
3465 # would be comments/copyright text which might have non-ascii ch aracters. Hence,
3466 # it is prefectly safe to catch the UnicodeDecodeError and just pass the line.
3467 pass
3468
3469 return matches
3470
3471 def check_in_mock_header(filename, matches=None, io=codecs):
3472 if not filename == 'Foo.h':
3473 return False
3474
3475 io = _unit_test_config.get(INCLUDE_IO_INJECTION_KEY, codecs)
Dirk Pranke 2013/09/26 19:01:35 Ick. Can you file a separate bug to clean up all o
r.kasibhatla 2013/09/26 19:07:44 Sorry for re-asking, but should I remove usage of
3476 header_file = None
3477 try:
3478 header_file = io.open(filename, 'r', 'utf8', 'replace')
3479 except IOError:
3480 return False
3481 line_number = 0
3482 for line in header_file:
3483 line_number += 1
3484 matched = re.search(r'\btoFoo\b', line)
3485 if matched:
3486 matches.append(['toFoo', line_number, line_number + 3])
3487 return True
3488
3489 # For unit testing only, avoid header search and lookup locally.
3490 matches = []
3491 mock_def_found = check_in_mock_header(filename, matches)
3492 if mock_def_found:
3493 return matches
3494
3495 # Regular style check flow. Search for actual header file & defs.
3496 file_path = get_abs_filepath(filename)
3497 if not file_path:
3498 return None
3499 try:
3500 f = open(file_path)
3501 clean_lines = CleansedLines(f.readlines())
3502 finally:
3503 f.close()
3504
3505 # Make a list of all genuine alternatives to static_cast.
3506 matches = grep(clean_lines, pattern, error)
3507 return matches
3508
3509
3510 def check_for_object_static_cast(processing_file, line_number, line, error):
3511 """Checks for a Cpp-style static cast on objects by looking for the pattern.
3512
3513 Args:
3514 processing_file: The name of the processing file.
3515 line_number: The number of the line to check.
3516 line: The line of code to check.
3517 error: The function to call with any errors found.
3518 """
3519 matched = search(r'\bstatic_cast<(\s*\w*:?:?\w+\s*\*+\s*)>', line)
3520 if not matched:
3521 return
3522
3523 class_name = re.sub('[\*]', '', matched.group(1))
3524 class_name = class_name.strip()
3525 # Ignore (for now) when the casting is to void*,
3526 if class_name == 'void':
3527 return
3528
3529 namespace_pos = class_name.find(':')
3530 if not namespace_pos == -1:
3531 class_name = class_name[namespace_pos + 2:]
3532
3533 header_file = ''.join((class_name, '.h'))
3534 matches = check_for_toFoo_definition(header_file, ''.join(('to', class_name) ), error)
3535 # Ignore (for now) if not able to find the header where toFoo might be defin ed.
3536 # TODO: Handle cases where Classname might be defined in some other header o r cpp file.
3537 if matches is None:
3538 return
3539
3540 report_error = True
3541 # Ensure found static_cast instance is not from within toFoo definition itse lf.
3542 if (os.path.basename(processing_file) == header_file):
3543 for item in matches:
3544 if line_number in range(item[1], item[2]):
3545 report_error = False
3546 break
3547
3548 if report_error:
3549 if len(matches):
3550 # toFoo is defined - enforce using it.
3551 # TODO: Suggest an appropriate toFoo from the alternatives present i n matches.
3552 error(line_number, 'runtime/casting', 4,
3553 'static_cast of class objects is not allowed. Use to%s defined in %s.' %
3554 (class_name, header_file))
3555 else:
3556 # No toFoo defined - enforce definition & usage.
3557 # TODO: Automate the generation of toFoo() to avoid any slippages ev er.
3558 error(line_number, 'runtime/casting', 4,
3559 'static_cast of class objects is not allowed. Add to%s in %s a nd use it instead.' %
3560 (class_name, header_file))
3561
3562
3424 def check_c_style_cast(line_number, line, raw_line, cast_type, pattern, 3563 def check_c_style_cast(line_number, line, raw_line, cast_type, pattern,
3425 error): 3564 error):
3426 """Checks for a C-style cast by looking for the pattern. 3565 """Checks for a C-style cast by looking for the pattern.
3427 3566
3428 This also handles sizeof(type) warnings, due to similarity of content. 3567 This also handles sizeof(type) warnings, due to similarity of content.
3429 3568
3430 Args: 3569 Args:
3431 line_number: The number of the line to check. 3570 line_number: The number of the line to check.
3432 line: The line of code to check. 3571 line: The line of code to check.
3433 raw_line: The raw line of code to check, with comments. 3572 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) 4052 self.handle_style_error, self.min_confidence)
3914 4053
3915 4054
3916 # FIXME: Remove this function (requires refactoring unit tests). 4055 # FIXME: Remove this function (requires refactoring unit tests).
3917 def process_file_data(filename, file_extension, lines, error, min_confidence, un it_test_config): 4056 def process_file_data(filename, file_extension, lines, error, min_confidence, un it_test_config):
3918 global _unit_test_config 4057 global _unit_test_config
3919 _unit_test_config = unit_test_config 4058 _unit_test_config = unit_test_config
3920 checker = CppChecker(filename, file_extension, error, min_confidence) 4059 checker = CppChecker(filename, file_extension, error, min_confidence)
3921 checker.check(lines) 4060 checker.check(lines)
3922 _unit_test_config = {} 4061 _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