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

Side by Side Diff: tools/checkdeps/cpp_checker.py

Issue 10805042: Implement ability to specify temporarily-allowed dependencies in DEPS (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Respond to review comments. Created 8 years, 5 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 | Annotate | Revision Log
OLDNEW
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 """Checks C++ and Objective-C files for illegal includes.""" 5 """Checks C++ and Objective-C files for illegal includes."""
6 6
7 import codecs 7 import codecs
8 import re 8 import re
9 9
10 from rules import Rule
11
10 12
11 class CppChecker(object): 13 class CppChecker(object):
12 14
13 EXTENSIONS = [ 15 EXTENSIONS = [
14 '.h', 16 '.h',
15 '.cc', 17 '.cc',
16 '.m', 18 '.m',
17 '.mm', 19 '.mm',
18 ] 20 ]
19 21
20 # The maximum number of non-include lines we can see before giving up. 22 # The maximum number of non-include lines we can see before giving up.
21 _MAX_UNINTERESTING_LINES = 50 23 _MAX_UNINTERESTING_LINES = 50
22 24
23 # The maximum line length, this is to be efficient in the case of very long 25 # The maximum line length, this is to be efficient in the case of very long
24 # lines (which can't be #includes). 26 # lines (which can't be #includes).
25 _MAX_LINE_LENGTH = 128 27 _MAX_LINE_LENGTH = 128
26 28
27 # This regular expression will be used to extract filenames from include 29 # This regular expression will be used to extract filenames from include
28 # statements. 30 # statements.
29 _EXTRACT_INCLUDE_PATH = re.compile( 31 _EXTRACT_INCLUDE_PATH = re.compile(
30 '[ \t]*#[ \t]*(?:include|import)[ \t]+"(.*)"') 32 '[ \t]*#[ \t]*(?:include|import)[ \t]+"(.*)"')
31 33
32 def __init__(self, verbose): 34 def __init__(self, verbose):
33 self._verbose = verbose 35 self._verbose = verbose
34 36
35 def _CheckLine(self, rules, line): 37 def CheckLine(self, rules, line, fail_on_temp_allow=False):
36 """Checks the given file with the given rule set. 38 """Checks the given line with the given rule set.
37 Returns a tuple (is_include, illegal_description). 39 Returns a triplet (is_include, illegal_description. rule_type).
M-A Ruel 2012/07/26 13:50:51 illegal_description, rule_type
Jói 2012/07/26 17:05:52 Done.
40
38 If the line is an #include directive the first value will be True. 41 If the line is an #include directive the first value will be True.
39 If it is also an illegal include, the second value will be a string 42 If it is also an illegal include, the second value will be a
40 describing the error. Otherwise, it will be None.""" 43 string describing the error. Otherwise, it will be None. If
44 fail_on_temp_allow is False, only Rule.DISALLOW rules will cause a
45 problem to be reported. If it is true, both Rule.DISALLOW and
46 Rule.TEMP_ALLOW will cause an error.
47
48 The last item in the triplet returns the type of rule that
49 applied, one of Rule.ALLOW (which implies the second item is
50 None), Rule.DISALLOW (which implies that the second item is not
51 None) and Rule.TEMP_ALLOW (in which case the second item will be
52 None only if fail_on_temp_allow is False).
53 """
41 found_item = self._EXTRACT_INCLUDE_PATH.match(line) 54 found_item = self._EXTRACT_INCLUDE_PATH.match(line)
42 if not found_item: 55 if not found_item:
43 return False, None # Not a match 56 return False, None, Rule.ALLOW # Not a match
44 57
45 include_path = found_item.group(1) 58 include_path = found_item.group(1)
46 59
47 if '\\' in include_path: 60 if '\\' in include_path:
48 return True, 'Include paths may not include backslashes' 61 return True, 'Include paths may not include backslashes', Rule.DISALLOW
49 62
50 if '/' not in include_path: 63 if '/' not in include_path:
51 # Don't fail when no directory is specified. We may want to be more 64 # Don't fail when no directory is specified. We may want to be more
52 # strict about this in the future. 65 # strict about this in the future.
53 if self._verbose: 66 if self._verbose:
54 print ' WARNING: directory specified with no path: ' + include_path 67 print ' WARNING: directory specified with no path: ' + include_path
55 return True, None 68 return True, None, Rule.ALLOW
56 69
57 (allowed, why_failed) = rules.DirAllowed(include_path) 70 (allowed, why_failed) = rules.DirAllowed(include_path)
58 if not allowed: 71 if (allowed == Rule.DISALLOW or
72 (fail_on_temp_allow and allowed == Rule.TEMP_ALLOW)):
59 if self._verbose: 73 if self._verbose:
60 retval = '\nFor %s' % rules 74 retval = '\nFor %s' % rules
61 else: 75 else:
62 retval = '' 76 retval = ''
63 return True, retval + ('Illegal include: "%s"\n Because of %s' % 77 return True, retval + ('Illegal include: "%s"\n Because of %s' %
64 (include_path, why_failed)) 78 (include_path, why_failed)), allowed
65 79
66 return True, None 80 return True, None, allowed
67 81
68 def CheckFile(self, rules, filepath): 82 def CheckFile(self, rules, filepath):
69 if self._verbose: 83 if self._verbose:
70 print 'Checking: ' + filepath 84 print 'Checking: ' + filepath
71 85
72 ret_val = '' # We'll collect the error messages in here 86 ret_val = '' # We'll collect the error messages in here
73 last_include = 0 87 last_include = 0
74 with codecs.open(filepath, encoding='utf-8') as f: 88 with codecs.open(filepath, encoding='utf-8') as f:
75 in_if0 = 0 89 in_if0 = 0
76 for line_num, line in enumerate(f): 90 for line_num, line in enumerate(f):
77 if line_num - last_include > self._MAX_UNINTERESTING_LINES: 91 if line_num - last_include > self._MAX_UNINTERESTING_LINES:
78 break 92 break
79 93
80 line = line.strip() 94 line = line.strip()
81 95
82 # Check to see if we're at / inside a #if 0 block 96 # Check to see if we're at / inside a #if 0 block
83 if line.startswith('#if 0'): 97 if line.startswith('#if 0'):
84 in_if0 += 1 98 in_if0 += 1
85 continue 99 continue
86 if in_if0 > 0: 100 if in_if0 > 0:
87 if line.startswith('#if'): 101 if line.startswith('#if'):
88 in_if0 += 1 102 in_if0 += 1
89 elif line.startswith('#endif'): 103 elif line.startswith('#endif'):
90 in_if0 -= 1 104 in_if0 -= 1
91 continue 105 continue
92 106
93 is_include, line_status = self._CheckLine(rules, line) 107 is_include, line_status, rule_type = self.CheckLine(rules, line)
94 if is_include: 108 if is_include:
95 last_include = line_num 109 last_include = line_num
96 if line_status is not None: 110 if line_status is not None:
97 if len(line_status) > 0: # Add newline to separate messages. 111 if len(line_status) > 0: # Add newline to separate messages.
98 line_status += '\n' 112 line_status += '\n'
99 ret_val += line_status 113 ret_val += line_status
100 114
101 return ret_val 115 return ret_val
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698