OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # | 2 # |
3 # Copyright (c) 2009 Google Inc. All rights reserved. | 3 # Copyright (c) 2009 Google Inc. All rights reserved. |
4 # | 4 # |
5 # Redistribution and use in source and binary forms, with or without | 5 # Redistribution and use in source and binary forms, with or without |
6 # modification, are permitted provided that the following conditions are | 6 # modification, are permitted provided that the following conditions are |
7 # met: | 7 # met: |
8 # | 8 # |
9 # * Redistributions of source code must retain the above copyright | 9 # * Redistributions of source code must retain the above copyright |
10 # notice, this list of conditions and the following disclaimer. | 10 # notice, this list of conditions and the following disclaimer. |
(...skipping 10 matching lines...) Expand all Loading... |
21 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 21 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
22 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 22 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
23 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 23 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
24 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 24 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
25 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 25 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
26 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 26 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
27 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 27 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
28 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 28 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
29 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 29 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
30 | 30 |
31 # Here are some issues that I've had people identify in my code during reviews, | |
32 # that I think are possible to flag automatically in a lint tool. If these were | |
33 # caught by lint, it would save time both for myself and that of my reviewers. | |
34 # Most likely, some of these are beyond the scope of the current lint framework, | |
35 # but I think it is valuable to retain these wish-list items even if they cannot | |
36 # be immediately implemented. | |
37 # | |
38 # Suggestions | |
39 # ----------- | |
40 # - Check for no 'explicit' for multi-arg ctor | |
41 # - Check for boolean assign RHS in parens | |
42 # - Check for ctor initializer-list colon position and spacing | |
43 # - Check that if there's a ctor, there should be a dtor | |
44 # - Check accessors that return non-pointer member variables are | |
45 # declared const | |
46 # - Check accessors that return non-const pointer member vars are | |
47 # *not* declared const | |
48 # - Check for using public includes for testing | |
49 # - Check for spaces between brackets in one-line inline method | |
50 # - Check for no assert() | |
51 # - Check for spaces surrounding operators | |
52 # - Check for 0 in pointer context (should be NULL) | |
53 # - Check for 0 in char context (should be '\0') | |
54 # - Check for camel-case method name conventions for methods | |
55 # that are not simple inline getters and setters | |
56 # - Do not indent namespace contents | |
57 # - Avoid inlining non-trivial constructors in header files | |
58 # - Check for old-school (void) cast for call-sites of functions | |
59 # ignored return value | |
60 # - Check gUnit usage of anonymous namespace | |
61 # - Check for class declaration order (typedefs, consts, enums, | |
62 # ctor(s?), dtor, friend declarations, methods, member vars) | |
63 # | |
64 | |
65 """Does google-lint on c++ files. | 31 """Does google-lint on c++ files. |
66 | 32 |
67 The goal of this script is to identify places in the code that *may* | 33 The goal of this script is to identify places in the code that *may* |
68 be in non-compliance with google style. It does not attempt to fix | 34 be in non-compliance with google style. It does not attempt to fix |
69 up these problems -- the point is to educate. It does also not | 35 up these problems -- the point is to educate. It does also not |
70 attempt to find all problems, or to ensure that everything it does | 36 attempt to find all problems, or to ensure that everything it does |
71 find is legitimately a problem. | 37 find is legitimately a problem. |
72 | 38 |
73 In particular, we can get very confused by /* and // inside strings! | 39 In particular, we can get very confused by /* and // inside strings! |
74 We do a small hack, which is to ignore //'s with "'s after them on the | 40 We do a small hack, which is to ignore //'s with "'s after them on the |
75 same line, but it is far from perfect (in either direction). | 41 same line, but it is far from perfect (in either direction). |
76 """ | 42 """ |
77 | 43 |
78 import codecs | 44 import codecs |
79 import copy | 45 import copy |
80 import getopt | 46 import getopt |
81 import math # for log | 47 import math # for log |
82 import os | 48 import os |
83 import re | 49 import re |
84 import sre_compile | 50 import sre_compile |
85 import string | 51 import string |
86 import sys | 52 import sys |
87 import unicodedata | 53 import unicodedata |
88 | 54 |
89 | 55 |
90 _USAGE = """ | 56 _USAGE = """ |
91 Syntax: cpplint.py [--verbose=#] [--output=vs7] [--filter=-x,+y,...] | 57 Syntax: cpplint.py [--verbose=#] [--output=vs7] [--filter=-x,+y,...] |
92 [--counting=total|toplevel|detailed] | 58 [--counting=total|toplevel|detailed] [--root=subdir] |
| 59 [--linelength=digits] |
93 <file> [file] ... | 60 <file> [file] ... |
94 | 61 |
95 The style guidelines this tries to follow are those in | 62 The style guidelines this tries to follow are those in |
96 http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml | 63 http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml |
97 | 64 |
98 Every problem is given a confidence score from 1-5, with 5 meaning we are | 65 Every problem is given a confidence score from 1-5, with 5 meaning we are |
99 certain of the problem, and 1 meaning it could be a legitimate construct. | 66 certain of the problem, and 1 meaning it could be a legitimate construct. |
100 This will miss some errors, and is not a substitute for a code review. | 67 This will miss some errors, and is not a substitute for a code review. |
101 | 68 |
102 To suppress false-positive errors of a certain category, add a | 69 To suppress false-positive errors of a certain category, add a |
103 'NOLINT(category)' comment to the line. NOLINT or NOLINT(*) | 70 'NOLINT(category)' comment to the line. NOLINT or NOLINT(*) |
104 suppresses errors of all categories on that line. | 71 suppresses errors of all categories on that line. |
105 | 72 |
106 The files passed in will be linted; at least one file must be provided. | 73 The files passed in will be linted; at least one file must be provided. |
107 Linted extensions are .cc, .cpp, and .h. Other file types will be ignored. | 74 Default linted extensions are .cc, .cpp, .cu, .cuh and .h. Change the |
| 75 extensions with the --extensions flag. |
108 | 76 |
109 Flags: | 77 Flags: |
110 | 78 |
111 output=vs7 | 79 output=vs7 |
112 By default, the output is formatted to ease emacs parsing. Visual Studio | 80 By default, the output is formatted to ease emacs parsing. Visual Studio |
113 compatible output (vs7) may also be used. Other formats are unsupported. | 81 compatible output (vs7) may also be used. Other formats are unsupported. |
114 | 82 |
115 verbose=# | 83 verbose=# |
116 Specify a number 0-5 to restrict errors to certain verbosity levels. | 84 Specify a number 0-5 to restrict errors to certain verbosity levels. |
117 | 85 |
(...skipping 27 matching lines...) Expand all Loading... |
145 directory. If the specified directory does not exist, this flag is | 113 directory. If the specified directory does not exist, this flag is |
146 ignored. | 114 ignored. |
147 | 115 |
148 Examples: | 116 Examples: |
149 Assuing that src/.git exists, the header guard CPP variables for | 117 Assuing that src/.git exists, the header guard CPP variables for |
150 src/chrome/browser/ui/browser.h are: | 118 src/chrome/browser/ui/browser.h are: |
151 | 119 |
152 No flag => CHROME_BROWSER_UI_BROWSER_H_ | 120 No flag => CHROME_BROWSER_UI_BROWSER_H_ |
153 --root=chrome => BROWSER_UI_BROWSER_H_ | 121 --root=chrome => BROWSER_UI_BROWSER_H_ |
154 --root=chrome/browser => UI_BROWSER_H_ | 122 --root=chrome/browser => UI_BROWSER_H_ |
| 123 |
| 124 linelength=digits |
| 125 This is the allowed line length for the project. The default value is |
| 126 80 characters. |
| 127 |
| 128 Examples: |
| 129 --linelength=120 |
| 130 |
| 131 extensions=extension,extension,... |
| 132 The allowed file extensions that cpplint will check |
| 133 |
| 134 Examples: |
| 135 --extensions=hpp,cpp |
155 """ | 136 """ |
156 | 137 |
157 # We categorize each error message we print. Here are the categories. | 138 # We categorize each error message we print. Here are the categories. |
158 # We want an explicit list so we can list them all in cpplint --filter=. | 139 # We want an explicit list so we can list them all in cpplint --filter=. |
159 # If you add a new error message with a new category, add it to the list | 140 # If you add a new error message with a new category, add it to the list |
160 # here! cpplint_unittest.py should tell you if you forget to do this. | 141 # here! cpplint_unittest.py should tell you if you forget to do this. |
161 # \ used for clearer layout -- pylint: disable-msg=C6013 | |
162 _ERROR_CATEGORIES = [ | 142 _ERROR_CATEGORIES = [ |
163 'build/class', | 143 'build/class', |
164 'build/deprecated', | 144 'build/deprecated', |
165 'build/endif_comment', | 145 'build/endif_comment', |
166 'build/explicit_make_pair', | 146 'build/explicit_make_pair', |
167 'build/forward_decl', | 147 'build/forward_decl', |
168 'build/header_guard', | 148 'build/header_guard', |
169 'build/include', | 149 'build/include', |
170 'build/include_alpha', | 150 'build/include_alpha', |
171 'build/include_order', | 151 'build/include_order', |
172 'build/include_what_you_use', | 152 'build/include_what_you_use', |
173 'build/namespaces', | 153 'build/namespaces', |
174 'build/printf_format', | 154 'build/printf_format', |
175 'build/storage_class', | 155 'build/storage_class', |
176 'legal/copyright', | 156 'legal/copyright', |
177 'readability/alt_tokens', | 157 'readability/alt_tokens', |
178 'readability/braces', | 158 'readability/braces', |
179 'readability/casting', | 159 'readability/casting', |
180 'readability/check', | 160 'readability/check', |
181 'readability/constructors', | 161 'readability/constructors', |
182 'readability/fn_size', | 162 'readability/fn_size', |
183 'readability/function', | 163 'readability/function', |
184 'readability/multiline_comment', | 164 'readability/multiline_comment', |
185 'readability/multiline_string', | 165 'readability/multiline_string', |
186 'readability/namespace', | 166 'readability/namespace', |
187 'readability/nolint', | 167 'readability/nolint', |
| 168 'readability/nul', |
188 'readability/streams', | 169 'readability/streams', |
189 'readability/todo', | 170 'readability/todo', |
190 'readability/utf8', | 171 'readability/utf8', |
191 'runtime/arrays', | 172 'runtime/arrays', |
192 'runtime/casting', | 173 'runtime/casting', |
193 'runtime/explicit', | 174 'runtime/explicit', |
194 'runtime/int', | 175 'runtime/int', |
195 'runtime/init', | 176 'runtime/init', |
196 'runtime/invalid_increment', | 177 'runtime/invalid_increment', |
197 'runtime/member_string_references', | 178 'runtime/member_string_references', |
198 'runtime/memset', | 179 'runtime/memset', |
199 'runtime/operator', | 180 'runtime/operator', |
200 'runtime/printf', | 181 'runtime/printf', |
201 'runtime/printf_format', | 182 'runtime/printf_format', |
202 'runtime/references', | 183 'runtime/references', |
203 'runtime/rtti', | |
204 'runtime/sizeof', | |
205 'runtime/string', | 184 'runtime/string', |
206 'runtime/threadsafe_fn', | 185 'runtime/threadsafe_fn', |
| 186 'runtime/vlog', |
207 'whitespace/blank_line', | 187 'whitespace/blank_line', |
208 'whitespace/braces', | 188 'whitespace/braces', |
209 'whitespace/comma', | 189 'whitespace/comma', |
210 'whitespace/comments', | 190 'whitespace/comments', |
| 191 'whitespace/empty_conditional_body', |
211 'whitespace/empty_loop_body', | 192 'whitespace/empty_loop_body', |
212 'whitespace/end_of_line', | 193 'whitespace/end_of_line', |
213 'whitespace/ending_newline', | 194 'whitespace/ending_newline', |
214 'whitespace/forcolon', | 195 'whitespace/forcolon', |
215 'whitespace/indent', | 196 'whitespace/indent', |
216 'whitespace/labels', | |
217 'whitespace/line_length', | 197 'whitespace/line_length', |
218 'whitespace/newline', | 198 'whitespace/newline', |
219 'whitespace/operators', | 199 'whitespace/operators', |
220 'whitespace/parens', | 200 'whitespace/parens', |
221 'whitespace/semicolon', | 201 'whitespace/semicolon', |
222 'whitespace/tab', | 202 'whitespace/tab', |
223 'whitespace/todo' | 203 'whitespace/todo' |
224 ] | 204 ] |
225 | 205 |
226 # The default state of the category filter. This is overrided by the --filter= | 206 # The default state of the category filter. This is overrided by the --filter= |
227 # flag. By default all errors are on, so only add here categories that should be | 207 # flag. By default all errors are on, so only add here categories that should be |
228 # off by default (i.e., categories that must be enabled by the --filter= flags). | 208 # off by default (i.e., categories that must be enabled by the --filter= flags). |
229 # All entries here should start with a '-' or '+', as in the --filter= flag. | 209 # All entries here should start with a '-' or '+', as in the --filter= flag. |
230 _DEFAULT_FILTERS = ['-build/include_alpha'] | 210 _DEFAULT_FILTERS = ['-build/include_alpha'] |
231 | 211 |
232 # We used to check for high-bit characters, but after much discussion we | 212 # We used to check for high-bit characters, but after much discussion we |
233 # decided those were OK, as long as they were in UTF-8 and didn't represent | 213 # decided those were OK, as long as they were in UTF-8 and didn't represent |
234 # hard-coded international strings, which belong in a separate i18n file. | 214 # hard-coded international strings, which belong in a separate i18n file. |
235 | 215 |
236 # Headers that we consider STL headers. | 216 |
237 _STL_HEADERS = frozenset([ | 217 # C++ headers |
238 'algobase.h', 'algorithm', 'alloc.h', 'bitset', 'deque', 'exception', | 218 _CPP_HEADERS = frozenset([ |
239 'function.h', 'functional', 'hash_map', 'hash_map.h', 'hash_set', | 219 # Legacy |
240 'hash_set.h', 'iterator', 'list', 'list.h', 'map', 'memory', 'new', | 220 'algobase.h', |
241 'pair.h', 'pthread_alloc', 'queue', 'set', 'set.h', 'sstream', 'stack', | 221 'algo.h', |
242 'stl_alloc.h', 'stl_relops.h', 'type_traits.h', | 222 'alloc.h', |
243 'utility', 'vector', 'vector.h', | 223 'builtinbuf.h', |
| 224 'bvector.h', |
| 225 'complex.h', |
| 226 'defalloc.h', |
| 227 'deque.h', |
| 228 'editbuf.h', |
| 229 'fstream.h', |
| 230 'function.h', |
| 231 'hash_map', |
| 232 'hash_map.h', |
| 233 'hash_set', |
| 234 'hash_set.h', |
| 235 'hashtable.h', |
| 236 'heap.h', |
| 237 'indstream.h', |
| 238 'iomanip.h', |
| 239 'iostream.h', |
| 240 'istream.h', |
| 241 'iterator.h', |
| 242 'list.h', |
| 243 'map.h', |
| 244 'multimap.h', |
| 245 'multiset.h', |
| 246 'ostream.h', |
| 247 'pair.h', |
| 248 'parsestream.h', |
| 249 'pfstream.h', |
| 250 'procbuf.h', |
| 251 'pthread_alloc', |
| 252 'pthread_alloc.h', |
| 253 'rope', |
| 254 'rope.h', |
| 255 'ropeimpl.h', |
| 256 'set.h', |
| 257 'slist', |
| 258 'slist.h', |
| 259 'stack.h', |
| 260 'stdiostream.h', |
| 261 'stl_alloc.h', |
| 262 'stl_relops.h', |
| 263 'streambuf.h', |
| 264 'stream.h', |
| 265 'strfile.h', |
| 266 'strstream.h', |
| 267 'tempbuf.h', |
| 268 'tree.h', |
| 269 'type_traits.h', |
| 270 'vector.h', |
| 271 # 17.6.1.2 C++ library headers |
| 272 'algorithm', |
| 273 'array', |
| 274 'atomic', |
| 275 'bitset', |
| 276 'chrono', |
| 277 'codecvt', |
| 278 'complex', |
| 279 'condition_variable', |
| 280 'deque', |
| 281 'exception', |
| 282 'forward_list', |
| 283 'fstream', |
| 284 'functional', |
| 285 'future', |
| 286 'initializer_list', |
| 287 'iomanip', |
| 288 'ios', |
| 289 'iosfwd', |
| 290 'iostream', |
| 291 'istream', |
| 292 'iterator', |
| 293 'limits', |
| 294 'list', |
| 295 'locale', |
| 296 'map', |
| 297 'memory', |
| 298 'mutex', |
| 299 'new', |
| 300 'numeric', |
| 301 'ostream', |
| 302 'queue', |
| 303 'random', |
| 304 'ratio', |
| 305 'regex', |
| 306 'set', |
| 307 'sstream', |
| 308 'stack', |
| 309 'stdexcept', |
| 310 'streambuf', |
| 311 'string', |
| 312 'strstream', |
| 313 'system_error', |
| 314 'thread', |
| 315 'tuple', |
| 316 'typeindex', |
| 317 'typeinfo', |
| 318 'type_traits', |
| 319 'unordered_map', |
| 320 'unordered_set', |
| 321 'utility', |
| 322 'valarray', |
| 323 'vector', |
| 324 # 17.6.1.2 C++ headers for C library facilities |
| 325 'cassert', |
| 326 'ccomplex', |
| 327 'cctype', |
| 328 'cerrno', |
| 329 'cfenv', |
| 330 'cfloat', |
| 331 'cinttypes', |
| 332 'ciso646', |
| 333 'climits', |
| 334 'clocale', |
| 335 'cmath', |
| 336 'csetjmp', |
| 337 'csignal', |
| 338 'cstdalign', |
| 339 'cstdarg', |
| 340 'cstdbool', |
| 341 'cstddef', |
| 342 'cstdint', |
| 343 'cstdio', |
| 344 'cstdlib', |
| 345 'cstring', |
| 346 'ctgmath', |
| 347 'ctime', |
| 348 'cuchar', |
| 349 'cwchar', |
| 350 'cwctype', |
244 ]) | 351 ]) |
245 | 352 |
246 | |
247 # Non-STL C++ system headers. | |
248 _CPP_HEADERS = frozenset([ | |
249 'algo.h', 'builtinbuf.h', 'bvector.h', 'cassert', 'cctype', | |
250 'cerrno', 'cfloat', 'ciso646', 'climits', 'clocale', 'cmath', | |
251 'complex', 'complex.h', 'csetjmp', 'csignal', 'cstdarg', 'cstddef', | |
252 'cstdio', 'cstdlib', 'cstring', 'ctime', 'cwchar', 'cwctype', | |
253 'defalloc.h', 'deque.h', 'editbuf.h', 'exception', 'fstream', | |
254 'fstream.h', 'hashtable.h', 'heap.h', 'indstream.h', 'iomanip', | |
255 'iomanip.h', 'ios', 'iosfwd', 'iostream', 'iostream.h', 'istream', | |
256 'istream.h', 'iterator.h', 'limits', 'map.h', 'multimap.h', 'multiset.h', | |
257 'numeric', 'ostream', 'ostream.h', 'parsestream.h', 'pfstream.h', | |
258 'PlotFile.h', 'procbuf.h', 'pthread_alloc.h', 'rope', 'rope.h', | |
259 'ropeimpl.h', 'SFile.h', 'slist', 'slist.h', 'stack.h', 'stdexcept', | |
260 'stdiostream.h', 'streambuf.h', 'stream.h', 'strfile.h', 'string', | |
261 'strstream', 'strstream.h', 'tempbuf.h', 'tree.h', 'typeinfo', 'valarray', | |
262 ]) | |
263 | |
264 | |
265 # Assertion macros. These are defined in base/logging.h and | 353 # Assertion macros. These are defined in base/logging.h and |
266 # testing/base/gunit.h. Note that the _M versions need to come first | 354 # testing/base/gunit.h. Note that the _M versions need to come first |
267 # for substring matching to work. | 355 # for substring matching to work. |
268 _CHECK_MACROS = [ | 356 _CHECK_MACROS = [ |
269 'DCHECK', 'CHECK', | 357 'DCHECK', 'CHECK', |
270 'EXPECT_TRUE_M', 'EXPECT_TRUE', | 358 'EXPECT_TRUE_M', 'EXPECT_TRUE', |
271 'ASSERT_TRUE_M', 'ASSERT_TRUE', | 359 'ASSERT_TRUE_M', 'ASSERT_TRUE', |
272 'EXPECT_FALSE_M', 'EXPECT_FALSE', | 360 'EXPECT_FALSE_M', 'EXPECT_FALSE', |
273 'ASSERT_FALSE_M', 'ASSERT_FALSE', | 361 'ASSERT_FALSE_M', 'ASSERT_FALSE', |
274 ] | 362 ] |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
309 'and_eq': '&=', | 397 'and_eq': '&=', |
310 'or_eq': '|=', | 398 'or_eq': '|=', |
311 'xor_eq': '^=', | 399 'xor_eq': '^=', |
312 'not': '!', | 400 'not': '!', |
313 'not_eq': '!=' | 401 'not_eq': '!=' |
314 } | 402 } |
315 | 403 |
316 # Compile regular expression that matches all the above keywords. The "[ =()]" | 404 # Compile regular expression that matches all the above keywords. The "[ =()]" |
317 # bit is meant to avoid matching these keywords outside of boolean expressions. | 405 # bit is meant to avoid matching these keywords outside of boolean expressions. |
318 # | 406 # |
319 # False positives include C-style multi-line comments (http://go/nsiut ) | 407 # False positives include C-style multi-line comments and multi-line strings |
320 # and multi-line strings (http://go/beujw ), but those have always been | 408 # but those have always been troublesome for cpplint. |
321 # troublesome for cpplint. | |
322 _ALT_TOKEN_REPLACEMENT_PATTERN = re.compile( | 409 _ALT_TOKEN_REPLACEMENT_PATTERN = re.compile( |
323 r'[ =()](' + ('|'.join(_ALT_TOKEN_REPLACEMENT.keys())) + r')(?=[ (]|$)') | 410 r'[ =()](' + ('|'.join(_ALT_TOKEN_REPLACEMENT.keys())) + r')(?=[ (]|$)') |
324 | 411 |
325 | 412 |
326 # These constants define types of headers for use with | 413 # These constants define types of headers for use with |
327 # _IncludeState.CheckNextIncludeOrder(). | 414 # _IncludeState.CheckNextIncludeOrder(). |
328 _C_SYS_HEADER = 1 | 415 _C_SYS_HEADER = 1 |
329 _CPP_SYS_HEADER = 2 | 416 _CPP_SYS_HEADER = 2 |
330 _LIKELY_MY_HEADER = 3 | 417 _LIKELY_MY_HEADER = 3 |
331 _POSSIBLE_MY_HEADER = 4 | 418 _POSSIBLE_MY_HEADER = 4 |
(...skipping 17 matching lines...) Expand all Loading... |
349 _RE_SUPPRESSION = re.compile(r'\bNOLINT\b(\([^)]*\))?') | 436 _RE_SUPPRESSION = re.compile(r'\bNOLINT\b(\([^)]*\))?') |
350 | 437 |
351 # {str, set(int)}: a map from error categories to sets of linenumbers | 438 # {str, set(int)}: a map from error categories to sets of linenumbers |
352 # on which those errors are expected and should be suppressed. | 439 # on which those errors are expected and should be suppressed. |
353 _error_suppressions = {} | 440 _error_suppressions = {} |
354 | 441 |
355 # The root directory used for deriving header guard CPP variable. | 442 # The root directory used for deriving header guard CPP variable. |
356 # This is set by --root flag. | 443 # This is set by --root flag. |
357 _root = None | 444 _root = None |
358 | 445 |
| 446 # The allowed line length of files. |
| 447 # This is set by --linelength flag. |
| 448 _line_length = 80 |
| 449 |
| 450 # The allowed extensions for file names |
| 451 # This is set by --extensions flag. |
| 452 _valid_extensions = set(['cc', 'h', 'cpp', 'cu', 'cuh']) |
| 453 |
359 def ParseNolintSuppressions(filename, raw_line, linenum, error): | 454 def ParseNolintSuppressions(filename, raw_line, linenum, error): |
360 """Updates the global list of error-suppressions. | 455 """Updates the global list of error-suppressions. |
361 | 456 |
362 Parses any NOLINT comments on the current line, updating the global | 457 Parses any NOLINT comments on the current line, updating the global |
363 error_suppressions store. Reports an error if the NOLINT comment | 458 error_suppressions store. Reports an error if the NOLINT comment |
364 was malformed. | 459 was malformed. |
365 | 460 |
366 Args: | 461 Args: |
367 filename: str, the name of the input file. | 462 filename: str, the name of the input file. |
368 raw_line: str, the line of input text, with comments. | 463 raw_line: str, the line of input text, with comments. |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
403 bool, True iff the error should be suppressed due to a NOLINT comment. | 498 bool, True iff the error should be suppressed due to a NOLINT comment. |
404 """ | 499 """ |
405 return (linenum in _error_suppressions.get(category, set()) or | 500 return (linenum in _error_suppressions.get(category, set()) or |
406 linenum in _error_suppressions.get(None, set())) | 501 linenum in _error_suppressions.get(None, set())) |
407 | 502 |
408 def Match(pattern, s): | 503 def Match(pattern, s): |
409 """Matches the string with the pattern, caching the compiled regexp.""" | 504 """Matches the string with the pattern, caching the compiled regexp.""" |
410 # The regexp compilation caching is inlined in both Match and Search for | 505 # The regexp compilation caching is inlined in both Match and Search for |
411 # performance reasons; factoring it out into a separate function turns out | 506 # performance reasons; factoring it out into a separate function turns out |
412 # to be noticeably expensive. | 507 # to be noticeably expensive. |
413 if not pattern in _regexp_compile_cache: | 508 if pattern not in _regexp_compile_cache: |
414 _regexp_compile_cache[pattern] = sre_compile.compile(pattern) | 509 _regexp_compile_cache[pattern] = sre_compile.compile(pattern) |
415 return _regexp_compile_cache[pattern].match(s) | 510 return _regexp_compile_cache[pattern].match(s) |
416 | 511 |
417 | 512 |
| 513 def ReplaceAll(pattern, rep, s): |
| 514 """Replaces instances of pattern in a string with a replacement. |
| 515 |
| 516 The compiled regex is kept in a cache shared by Match and Search. |
| 517 |
| 518 Args: |
| 519 pattern: regex pattern |
| 520 rep: replacement text |
| 521 s: search string |
| 522 |
| 523 Returns: |
| 524 string with replacements made (or original string if no replacements) |
| 525 """ |
| 526 if pattern not in _regexp_compile_cache: |
| 527 _regexp_compile_cache[pattern] = sre_compile.compile(pattern) |
| 528 return _regexp_compile_cache[pattern].sub(rep, s) |
| 529 |
| 530 |
418 def Search(pattern, s): | 531 def Search(pattern, s): |
419 """Searches the string for the pattern, caching the compiled regexp.""" | 532 """Searches the string for the pattern, caching the compiled regexp.""" |
420 if not pattern in _regexp_compile_cache: | 533 if pattern not in _regexp_compile_cache: |
421 _regexp_compile_cache[pattern] = sre_compile.compile(pattern) | 534 _regexp_compile_cache[pattern] = sre_compile.compile(pattern) |
422 return _regexp_compile_cache[pattern].search(s) | 535 return _regexp_compile_cache[pattern].search(s) |
423 | 536 |
424 | 537 |
425 class _IncludeState(dict): | 538 class _IncludeState(dict): |
426 """Tracks line numbers for includes, and the order in which includes appear. | 539 """Tracks line numbers for includes, and the order in which includes appear. |
427 | 540 |
428 As a dict, an _IncludeState object serves as a mapping between include | 541 As a dict, an _IncludeState object serves as a mapping between include |
429 filename and line number on which that file was included. | 542 filename and line number on which that file was included. |
430 | 543 |
(...skipping 20 matching lines...) Expand all Loading... |
451 _SECTION_NAMES = { | 564 _SECTION_NAMES = { |
452 _INITIAL_SECTION: "... nothing. (This can't be an error.)", | 565 _INITIAL_SECTION: "... nothing. (This can't be an error.)", |
453 _MY_H_SECTION: 'a header this file implements', | 566 _MY_H_SECTION: 'a header this file implements', |
454 _C_SECTION: 'C system header', | 567 _C_SECTION: 'C system header', |
455 _CPP_SECTION: 'C++ system header', | 568 _CPP_SECTION: 'C++ system header', |
456 _OTHER_H_SECTION: 'other header', | 569 _OTHER_H_SECTION: 'other header', |
457 } | 570 } |
458 | 571 |
459 def __init__(self): | 572 def __init__(self): |
460 dict.__init__(self) | 573 dict.__init__(self) |
| 574 self.ResetSection() |
| 575 |
| 576 def ResetSection(self): |
461 # The name of the current section. | 577 # The name of the current section. |
462 self._section = self._INITIAL_SECTION | 578 self._section = self._INITIAL_SECTION |
463 # The path of last found header. | 579 # The path of last found header. |
464 self._last_header = '' | 580 self._last_header = '' |
465 | 581 |
| 582 def SetLastHeader(self, header_path): |
| 583 self._last_header = header_path |
| 584 |
466 def CanonicalizeAlphabeticalOrder(self, header_path): | 585 def CanonicalizeAlphabeticalOrder(self, header_path): |
467 """Returns a path canonicalized for alphabetical comparison. | 586 """Returns a path canonicalized for alphabetical comparison. |
468 | 587 |
469 - replaces "-" with "_" so they both cmp the same. | 588 - replaces "-" with "_" so they both cmp the same. |
470 - removes '-inl' since we don't require them to be after the main header. | 589 - removes '-inl' since we don't require them to be after the main header. |
471 - lowercase everything, just in case. | 590 - lowercase everything, just in case. |
472 | 591 |
473 Args: | 592 Args: |
474 header_path: Path to be canonicalized. | 593 header_path: Path to be canonicalized. |
475 | 594 |
476 Returns: | 595 Returns: |
477 Canonicalized path. | 596 Canonicalized path. |
478 """ | 597 """ |
479 return header_path.replace('-inl.h', '.h').replace('-', '_').lower() | 598 return header_path.replace('-inl.h', '.h').replace('-', '_').lower() |
480 | 599 |
481 def IsInAlphabeticalOrder(self, header_path): | 600 def IsInAlphabeticalOrder(self, clean_lines, linenum, header_path): |
482 """Check if a header is in alphabetical order with the previous header. | 601 """Check if a header is in alphabetical order with the previous header. |
483 | 602 |
484 Args: | 603 Args: |
485 header_path: Header to be checked. | 604 clean_lines: A CleansedLines instance containing the file. |
| 605 linenum: The number of the line to check. |
| 606 header_path: Canonicalized header to be checked. |
486 | 607 |
487 Returns: | 608 Returns: |
488 Returns true if the header is in alphabetical order. | 609 Returns true if the header is in alphabetical order. |
489 """ | 610 """ |
490 canonical_header = self.CanonicalizeAlphabeticalOrder(header_path) | 611 # If previous section is different from current section, _last_header will |
491 if self._last_header > canonical_header: | 612 # be reset to empty string, so it's always less than current header. |
| 613 # |
| 614 # If previous line was a blank line, assume that the headers are |
| 615 # intentionally sorted the way they are. |
| 616 if (self._last_header > header_path and |
| 617 not Match(r'^\s*$', clean_lines.elided[linenum - 1])): |
492 return False | 618 return False |
493 self._last_header = canonical_header | |
494 return True | 619 return True |
495 | 620 |
496 def CheckNextIncludeOrder(self, header_type): | 621 def CheckNextIncludeOrder(self, header_type): |
497 """Returns a non-empty error message if the next header is out of order. | 622 """Returns a non-empty error message if the next header is out of order. |
498 | 623 |
499 This function also updates the internal state to be ready to check | 624 This function also updates the internal state to be ready to check |
500 the next include. | 625 the next include. |
501 | 626 |
502 Args: | 627 Args: |
503 header_type: One of the _XXX_HEADER constants defined above. | 628 header_type: One of the _XXX_HEADER constants defined above. |
(...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
876 sys.stderr.write('%s(%s): %s [%s] [%d]\n' % ( | 1001 sys.stderr.write('%s(%s): %s [%s] [%d]\n' % ( |
877 filename, linenum, message, category, confidence)) | 1002 filename, linenum, message, category, confidence)) |
878 elif _cpplint_state.output_format == 'eclipse': | 1003 elif _cpplint_state.output_format == 'eclipse': |
879 sys.stderr.write('%s:%s: warning: %s [%s] [%d]\n' % ( | 1004 sys.stderr.write('%s:%s: warning: %s [%s] [%d]\n' % ( |
880 filename, linenum, message, category, confidence)) | 1005 filename, linenum, message, category, confidence)) |
881 else: | 1006 else: |
882 sys.stderr.write('%s:%s: %s [%s] [%d]\n' % ( | 1007 sys.stderr.write('%s:%s: %s [%s] [%d]\n' % ( |
883 filename, linenum, message, category, confidence)) | 1008 filename, linenum, message, category, confidence)) |
884 | 1009 |
885 | 1010 |
886 # Matches standard C++ escape esequences per 2.13.2.3 of the C++ standard. | 1011 # Matches standard C++ escape sequences per 2.13.2.3 of the C++ standard. |
887 _RE_PATTERN_CLEANSE_LINE_ESCAPES = re.compile( | 1012 _RE_PATTERN_CLEANSE_LINE_ESCAPES = re.compile( |
888 r'\\([abfnrtv?"\\\']|\d+|x[0-9a-fA-F]+)') | 1013 r'\\([abfnrtv?"\\\']|\d+|x[0-9a-fA-F]+)') |
889 # Matches strings. Escape codes should already be removed by ESCAPES. | 1014 # Matches strings. Escape codes should already be removed by ESCAPES. |
890 _RE_PATTERN_CLEANSE_LINE_DOUBLE_QUOTES = re.compile(r'"[^"]*"') | 1015 _RE_PATTERN_CLEANSE_LINE_DOUBLE_QUOTES = re.compile(r'"[^"]*"') |
891 # Matches characters. Escape codes should already be removed by ESCAPES. | 1016 # Matches characters. Escape codes should already be removed by ESCAPES. |
892 _RE_PATTERN_CLEANSE_LINE_SINGLE_QUOTES = re.compile(r"'.'") | 1017 _RE_PATTERN_CLEANSE_LINE_SINGLE_QUOTES = re.compile(r"'.'") |
893 # Matches multi-line C++ comments. | 1018 # Matches multi-line C++ comments. |
894 # This RE is a little bit more complicated than one might expect, because we | 1019 # This RE is a little bit more complicated than one might expect, because we |
895 # have to take care of space removals tools so we can handle comments inside | 1020 # have to take care of space removals tools so we can handle comments inside |
896 # statements better. | 1021 # statements better. |
(...skipping 18 matching lines...) Expand all Loading... |
915 | 1040 |
916 Returns: | 1041 Returns: |
917 True, if next character appended to 'line' is inside a | 1042 True, if next character appended to 'line' is inside a |
918 string constant. | 1043 string constant. |
919 """ | 1044 """ |
920 | 1045 |
921 line = line.replace(r'\\', 'XX') # after this, \\" does not match to \" | 1046 line = line.replace(r'\\', 'XX') # after this, \\" does not match to \" |
922 return ((line.count('"') - line.count(r'\"') - line.count("'\"'")) & 1) == 1 | 1047 return ((line.count('"') - line.count(r'\"') - line.count("'\"'")) & 1) == 1 |
923 | 1048 |
924 | 1049 |
| 1050 def CleanseRawStrings(raw_lines): |
| 1051 """Removes C++11 raw strings from lines. |
| 1052 |
| 1053 Before: |
| 1054 static const char kData[] = R"( |
| 1055 multi-line string |
| 1056 )"; |
| 1057 |
| 1058 After: |
| 1059 static const char kData[] = "" |
| 1060 (replaced by blank line) |
| 1061 ""; |
| 1062 |
| 1063 Args: |
| 1064 raw_lines: list of raw lines. |
| 1065 |
| 1066 Returns: |
| 1067 list of lines with C++11 raw strings replaced by empty strings. |
| 1068 """ |
| 1069 |
| 1070 delimiter = None |
| 1071 lines_without_raw_strings = [] |
| 1072 for line in raw_lines: |
| 1073 if delimiter: |
| 1074 # Inside a raw string, look for the end |
| 1075 end = line.find(delimiter) |
| 1076 if end >= 0: |
| 1077 # Found the end of the string, match leading space for this |
| 1078 # line and resume copying the original lines, and also insert |
| 1079 # a "" on the last line. |
| 1080 leading_space = Match(r'^(\s*)\S', line) |
| 1081 line = leading_space.group(1) + '""' + line[end + len(delimiter):] |
| 1082 delimiter = None |
| 1083 else: |
| 1084 # Haven't found the end yet, append a blank line. |
| 1085 line = '' |
| 1086 |
| 1087 else: |
| 1088 # Look for beginning of a raw string. |
| 1089 # See 2.14.15 [lex.string] for syntax. |
| 1090 matched = Match(r'^(.*)\b(?:R|u8R|uR|UR|LR)"([^\s\\()]*)\((.*)$', line) |
| 1091 if matched: |
| 1092 delimiter = ')' + matched.group(2) + '"' |
| 1093 |
| 1094 end = matched.group(3).find(delimiter) |
| 1095 if end >= 0: |
| 1096 # Raw string ended on same line |
| 1097 line = (matched.group(1) + '""' + |
| 1098 matched.group(3)[end + len(delimiter):]) |
| 1099 delimiter = None |
| 1100 else: |
| 1101 # Start of a multi-line raw string |
| 1102 line = matched.group(1) + '""' |
| 1103 |
| 1104 lines_without_raw_strings.append(line) |
| 1105 |
| 1106 # TODO(unknown): if delimiter is not None here, we might want to |
| 1107 # emit a warning for unterminated string. |
| 1108 return lines_without_raw_strings |
| 1109 |
| 1110 |
925 def FindNextMultiLineCommentStart(lines, lineix): | 1111 def FindNextMultiLineCommentStart(lines, lineix): |
926 """Find the beginning marker for a multiline comment.""" | 1112 """Find the beginning marker for a multiline comment.""" |
927 while lineix < len(lines): | 1113 while lineix < len(lines): |
928 if lines[lineix].strip().startswith('/*'): | 1114 if lines[lineix].strip().startswith('/*'): |
929 # Only return this marker if the comment goes beyond this line | 1115 # Only return this marker if the comment goes beyond this line |
930 if lines[lineix].strip().find('*/', 2) < 0: | 1116 if lines[lineix].strip().find('*/', 2) < 0: |
931 return lineix | 1117 return lineix |
932 lineix += 1 | 1118 lineix += 1 |
933 return len(lines) | 1119 return len(lines) |
934 | 1120 |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
989 2) lines member contains lines without comments, and | 1175 2) lines member contains lines without comments, and |
990 3) raw_lines member contains all the lines without processing. | 1176 3) raw_lines member contains all the lines without processing. |
991 All these three members are of <type 'list'>, and of the same length. | 1177 All these three members are of <type 'list'>, and of the same length. |
992 """ | 1178 """ |
993 | 1179 |
994 def __init__(self, lines): | 1180 def __init__(self, lines): |
995 self.elided = [] | 1181 self.elided = [] |
996 self.lines = [] | 1182 self.lines = [] |
997 self.raw_lines = lines | 1183 self.raw_lines = lines |
998 self.num_lines = len(lines) | 1184 self.num_lines = len(lines) |
999 for linenum in range(len(lines)): | 1185 self.lines_without_raw_strings = CleanseRawStrings(lines) |
1000 self.lines.append(CleanseComments(lines[linenum])) | 1186 for linenum in range(len(self.lines_without_raw_strings)): |
1001 elided = self._CollapseStrings(lines[linenum]) | 1187 self.lines.append(CleanseComments( |
| 1188 self.lines_without_raw_strings[linenum])) |
| 1189 elided = self._CollapseStrings(self.lines_without_raw_strings[linenum]) |
1002 self.elided.append(CleanseComments(elided)) | 1190 self.elided.append(CleanseComments(elided)) |
1003 | 1191 |
1004 def NumLines(self): | 1192 def NumLines(self): |
1005 """Returns the number of lines represented.""" | 1193 """Returns the number of lines represented.""" |
1006 return self.num_lines | 1194 return self.num_lines |
1007 | 1195 |
1008 @staticmethod | 1196 @staticmethod |
1009 def _CollapseStrings(elided): | 1197 def _CollapseStrings(elided): |
1010 """Collapses strings and chars on a line to simple "" or '' blocks. | 1198 """Collapses strings and chars on a line to simple "" or '' blocks. |
1011 | 1199 |
(...skipping 19 matching lines...) Expand all Loading... |
1031 """Find the position just after the matching endchar. | 1219 """Find the position just after the matching endchar. |
1032 | 1220 |
1033 Args: | 1221 Args: |
1034 line: a CleansedLines line. | 1222 line: a CleansedLines line. |
1035 startpos: start searching at this position. | 1223 startpos: start searching at this position. |
1036 depth: nesting level at startpos. | 1224 depth: nesting level at startpos. |
1037 startchar: expression opening character. | 1225 startchar: expression opening character. |
1038 endchar: expression closing character. | 1226 endchar: expression closing character. |
1039 | 1227 |
1040 Returns: | 1228 Returns: |
1041 Index just after endchar. | 1229 On finding matching endchar: (index just after matching endchar, 0) |
| 1230 Otherwise: (-1, new depth at end of this line) |
1042 """ | 1231 """ |
1043 for i in xrange(startpos, len(line)): | 1232 for i in xrange(startpos, len(line)): |
1044 if line[i] == startchar: | 1233 if line[i] == startchar: |
1045 depth += 1 | 1234 depth += 1 |
1046 elif line[i] == endchar: | 1235 elif line[i] == endchar: |
1047 depth -= 1 | 1236 depth -= 1 |
1048 if depth == 0: | 1237 if depth == 0: |
1049 return i + 1 | 1238 return (i + 1, 0) |
1050 return -1 | 1239 return (-1, depth) |
1051 | 1240 |
1052 | 1241 |
1053 def CloseExpression(clean_lines, linenum, pos): | 1242 def CloseExpression(clean_lines, linenum, pos): |
1054 """If input points to ( or { or [, finds the position that closes it. | 1243 """If input points to ( or { or [ or <, finds the position that closes it. |
1055 | 1244 |
1056 If lines[linenum][pos] points to a '(' or '{' or '[', finds the | 1245 If lines[linenum][pos] points to a '(' or '{' or '[' or '<', finds the |
1057 linenum/pos that correspond to the closing of the expression. | 1246 linenum/pos that correspond to the closing of the expression. |
1058 | 1247 |
1059 Args: | 1248 Args: |
1060 clean_lines: A CleansedLines instance containing the file. | 1249 clean_lines: A CleansedLines instance containing the file. |
1061 linenum: The number of the line to check. | 1250 linenum: The number of the line to check. |
1062 pos: A position on the line. | 1251 pos: A position on the line. |
1063 | 1252 |
1064 Returns: | 1253 Returns: |
1065 A tuple (line, linenum, pos) pointer *past* the closing brace, or | 1254 A tuple (line, linenum, pos) pointer *past* the closing brace, or |
1066 (line, len(lines), -1) if we never find a close. Note we ignore | 1255 (line, len(lines), -1) if we never find a close. Note we ignore |
1067 strings and comments when matching; and the line we return is the | 1256 strings and comments when matching; and the line we return is the |
1068 'cleansed' line at linenum. | 1257 'cleansed' line at linenum. |
1069 """ | 1258 """ |
1070 | 1259 |
1071 line = clean_lines.elided[linenum] | 1260 line = clean_lines.elided[linenum] |
1072 startchar = line[pos] | 1261 startchar = line[pos] |
1073 if startchar not in '({[': | 1262 if startchar not in '({[<': |
1074 return (line, clean_lines.NumLines(), -1) | 1263 return (line, clean_lines.NumLines(), -1) |
1075 if startchar == '(': endchar = ')' | 1264 if startchar == '(': endchar = ')' |
1076 if startchar == '[': endchar = ']' | 1265 if startchar == '[': endchar = ']' |
1077 if startchar == '{': endchar = '}' | 1266 if startchar == '{': endchar = '}' |
| 1267 if startchar == '<': endchar = '>' |
1078 | 1268 |
1079 # Check first line | 1269 # Check first line |
1080 end_pos = FindEndOfExpressionInLine(line, pos, 0, startchar, endchar) | 1270 (end_pos, num_open) = FindEndOfExpressionInLine( |
| 1271 line, pos, 0, startchar, endchar) |
1081 if end_pos > -1: | 1272 if end_pos > -1: |
1082 return (line, linenum, end_pos) | 1273 return (line, linenum, end_pos) |
1083 tail = line[pos:] | 1274 |
1084 num_open = tail.count(startchar) - tail.count(endchar) | 1275 # Continue scanning forward |
1085 while linenum < clean_lines.NumLines() - 1: | 1276 while linenum < clean_lines.NumLines() - 1: |
1086 linenum += 1 | 1277 linenum += 1 |
1087 line = clean_lines.elided[linenum] | 1278 line = clean_lines.elided[linenum] |
1088 delta = line.count(startchar) - line.count(endchar) | 1279 (end_pos, num_open) = FindEndOfExpressionInLine( |
1089 if num_open + delta <= 0: | 1280 line, 0, num_open, startchar, endchar) |
1090 return (line, linenum, | 1281 if end_pos > -1: |
1091 FindEndOfExpressionInLine(line, 0, num_open, startchar, endchar)) | 1282 return (line, linenum, end_pos) |
1092 num_open += delta | |
1093 | 1283 |
1094 # Did not find endchar before end of file, give up | 1284 # Did not find endchar before end of file, give up |
1095 return (line, clean_lines.NumLines(), -1) | 1285 return (line, clean_lines.NumLines(), -1) |
1096 | 1286 |
| 1287 |
| 1288 def FindStartOfExpressionInLine(line, endpos, depth, startchar, endchar): |
| 1289 """Find position at the matching startchar. |
| 1290 |
| 1291 This is almost the reverse of FindEndOfExpressionInLine, but note |
| 1292 that the input position and returned position differs by 1. |
| 1293 |
| 1294 Args: |
| 1295 line: a CleansedLines line. |
| 1296 endpos: start searching at this position. |
| 1297 depth: nesting level at endpos. |
| 1298 startchar: expression opening character. |
| 1299 endchar: expression closing character. |
| 1300 |
| 1301 Returns: |
| 1302 On finding matching startchar: (index at matching startchar, 0) |
| 1303 Otherwise: (-1, new depth at beginning of this line) |
| 1304 """ |
| 1305 for i in xrange(endpos, -1, -1): |
| 1306 if line[i] == endchar: |
| 1307 depth += 1 |
| 1308 elif line[i] == startchar: |
| 1309 depth -= 1 |
| 1310 if depth == 0: |
| 1311 return (i, 0) |
| 1312 return (-1, depth) |
| 1313 |
| 1314 |
| 1315 def ReverseCloseExpression(clean_lines, linenum, pos): |
| 1316 """If input points to ) or } or ] or >, finds the position that opens it. |
| 1317 |
| 1318 If lines[linenum][pos] points to a ')' or '}' or ']' or '>', finds the |
| 1319 linenum/pos that correspond to the opening of the expression. |
| 1320 |
| 1321 Args: |
| 1322 clean_lines: A CleansedLines instance containing the file. |
| 1323 linenum: The number of the line to check. |
| 1324 pos: A position on the line. |
| 1325 |
| 1326 Returns: |
| 1327 A tuple (line, linenum, pos) pointer *at* the opening brace, or |
| 1328 (line, 0, -1) if we never find the matching opening brace. Note |
| 1329 we ignore strings and comments when matching; and the line we |
| 1330 return is the 'cleansed' line at linenum. |
| 1331 """ |
| 1332 line = clean_lines.elided[linenum] |
| 1333 endchar = line[pos] |
| 1334 if endchar not in ')}]>': |
| 1335 return (line, 0, -1) |
| 1336 if endchar == ')': startchar = '(' |
| 1337 if endchar == ']': startchar = '[' |
| 1338 if endchar == '}': startchar = '{' |
| 1339 if endchar == '>': startchar = '<' |
| 1340 |
| 1341 # Check last line |
| 1342 (start_pos, num_open) = FindStartOfExpressionInLine( |
| 1343 line, pos, 0, startchar, endchar) |
| 1344 if start_pos > -1: |
| 1345 return (line, linenum, start_pos) |
| 1346 |
| 1347 # Continue scanning backward |
| 1348 while linenum > 0: |
| 1349 linenum -= 1 |
| 1350 line = clean_lines.elided[linenum] |
| 1351 (start_pos, num_open) = FindStartOfExpressionInLine( |
| 1352 line, len(line) - 1, num_open, startchar, endchar) |
| 1353 if start_pos > -1: |
| 1354 return (line, linenum, start_pos) |
| 1355 |
| 1356 # Did not find startchar before beginning of file, give up |
| 1357 return (line, 0, -1) |
| 1358 |
| 1359 |
1097 def CheckForCopyright(filename, lines, error): | 1360 def CheckForCopyright(filename, lines, error): |
1098 """Logs an error if no Copyright message appears at the top of the file.""" | 1361 """Logs an error if no Copyright message appears at the top of the file.""" |
1099 | 1362 |
1100 # We'll say it should occur by line 10. Don't forget there's a | 1363 # We'll say it should occur by line 10. Don't forget there's a |
1101 # dummy line at the front. | 1364 # dummy line at the front. |
1102 for line in xrange(1, min(len(lines), 11)): | 1365 for line in xrange(1, min(len(lines), 11)): |
1103 if re.search(r'Copyright', lines[line], re.I): break | 1366 if re.search(r'Copyright', lines[line], re.I): break |
1104 else: # means no copyright line was found | 1367 else: # means no copyright line was found |
1105 error(filename, 0, 'legal/copyright', 5, | 1368 error(filename, 0, 'legal/copyright', 5, |
1106 'No copyright message found. ' | 1369 'No copyright message found. ' |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1199 error_level = 0 | 1462 error_level = 0 |
1200 if endif != ('#endif // %s' % (cppvar + '_')): | 1463 if endif != ('#endif // %s' % (cppvar + '_')): |
1201 error_level = 5 | 1464 error_level = 5 |
1202 | 1465 |
1203 ParseNolintSuppressions(filename, lines[endif_linenum], endif_linenum, | 1466 ParseNolintSuppressions(filename, lines[endif_linenum], endif_linenum, |
1204 error) | 1467 error) |
1205 error(filename, endif_linenum, 'build/header_guard', error_level, | 1468 error(filename, endif_linenum, 'build/header_guard', error_level, |
1206 '#endif line should be "#endif // %s"' % cppvar) | 1469 '#endif line should be "#endif // %s"' % cppvar) |
1207 | 1470 |
1208 | 1471 |
1209 def CheckForUnicodeReplacementCharacters(filename, lines, error): | 1472 def CheckForBadCharacters(filename, lines, error): |
1210 """Logs an error for each line containing Unicode replacement characters. | 1473 """Logs an error for each line containing bad characters. |
1211 | 1474 |
1212 These indicate that either the file contained invalid UTF-8 (likely) | 1475 Two kinds of bad characters: |
1213 or Unicode replacement characters (which it shouldn't). Note that | 1476 |
1214 it's possible for this to throw off line numbering if the invalid | 1477 1. Unicode replacement characters: These indicate that either the file |
1215 UTF-8 occurred adjacent to a newline. | 1478 contained invalid UTF-8 (likely) or Unicode replacement characters (which |
| 1479 it shouldn't). Note that it's possible for this to throw off line |
| 1480 numbering if the invalid UTF-8 occurred adjacent to a newline. |
| 1481 |
| 1482 2. NUL bytes. These are problematic for some tools. |
1216 | 1483 |
1217 Args: | 1484 Args: |
1218 filename: The name of the current file. | 1485 filename: The name of the current file. |
1219 lines: An array of strings, each representing a line of the file. | 1486 lines: An array of strings, each representing a line of the file. |
1220 error: The function to call with any errors found. | 1487 error: The function to call with any errors found. |
1221 """ | 1488 """ |
1222 for linenum, line in enumerate(lines): | 1489 for linenum, line in enumerate(lines): |
1223 if u'\ufffd' in line: | 1490 if u'\ufffd' in line: |
1224 error(filename, linenum, 'readability/utf8', 5, | 1491 error(filename, linenum, 'readability/utf8', 5, |
1225 'Line contains invalid UTF-8 (or Unicode replacement character).') | 1492 'Line contains invalid UTF-8 (or Unicode replacement character).') |
| 1493 if '\0' in line: |
| 1494 error(filename, linenum, 'readability/nul', 5, 'Line contains NUL byte.') |
1226 | 1495 |
1227 | 1496 |
1228 def CheckForNewlineAtEOF(filename, lines, error): | 1497 def CheckForNewlineAtEOF(filename, lines, error): |
1229 """Logs an error if there is no newline char at the end of the file. | 1498 """Logs an error if there is no newline char at the end of the file. |
1230 | 1499 |
1231 Args: | 1500 Args: |
1232 filename: The name of the current file. | 1501 filename: The name of the current file. |
1233 lines: An array of strings, each representing a line of the file. | 1502 lines: An array of strings, each representing a line of the file. |
1234 error: The function to call with any errors found. | 1503 error: The function to call with any errors found. |
1235 """ | 1504 """ |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1270 error(filename, linenum, 'readability/multiline_comment', 5, | 1539 error(filename, linenum, 'readability/multiline_comment', 5, |
1271 'Complex multi-line /*...*/-style comment found. ' | 1540 'Complex multi-line /*...*/-style comment found. ' |
1272 'Lint may give bogus warnings. ' | 1541 'Lint may give bogus warnings. ' |
1273 'Consider replacing these with //-style comments, ' | 1542 'Consider replacing these with //-style comments, ' |
1274 'with #if 0...#endif, ' | 1543 'with #if 0...#endif, ' |
1275 'or with more clearly structured multi-line comments.') | 1544 'or with more clearly structured multi-line comments.') |
1276 | 1545 |
1277 if (line.count('"') - line.count('\\"')) % 2: | 1546 if (line.count('"') - line.count('\\"')) % 2: |
1278 error(filename, linenum, 'readability/multiline_string', 5, | 1547 error(filename, linenum, 'readability/multiline_string', 5, |
1279 'Multi-line string ("...") found. This lint script doesn\'t ' | 1548 'Multi-line string ("...") found. This lint script doesn\'t ' |
1280 'do well with such strings, and may give bogus warnings. They\'re ' | 1549 'do well with such strings, and may give bogus warnings. ' |
1281 'ugly and unnecessary, and you should use concatenation instead".') | 1550 'Use C++11 raw strings or concatenation instead.') |
1282 | 1551 |
1283 | 1552 |
1284 threading_list = ( | 1553 threading_list = ( |
1285 ('asctime(', 'asctime_r('), | 1554 ('asctime(', 'asctime_r('), |
1286 ('ctime(', 'ctime_r('), | 1555 ('ctime(', 'ctime_r('), |
1287 ('getgrgid(', 'getgrgid_r('), | 1556 ('getgrgid(', 'getgrgid_r('), |
1288 ('getgrnam(', 'getgrnam_r('), | 1557 ('getgrnam(', 'getgrnam_r('), |
1289 ('getlogin(', 'getlogin_r('), | 1558 ('getlogin(', 'getlogin_r('), |
1290 ('getpwnam(', 'getpwnam_r('), | 1559 ('getpwnam(', 'getpwnam_r('), |
1291 ('getpwuid(', 'getpwuid_r('), | 1560 ('getpwuid(', 'getpwuid_r('), |
1292 ('gmtime(', 'gmtime_r('), | 1561 ('gmtime(', 'gmtime_r('), |
1293 ('localtime(', 'localtime_r('), | 1562 ('localtime(', 'localtime_r('), |
1294 ('rand(', 'rand_r('), | 1563 ('rand(', 'rand_r('), |
1295 ('readdir(', 'readdir_r('), | |
1296 ('strtok(', 'strtok_r('), | 1564 ('strtok(', 'strtok_r('), |
1297 ('ttyname(', 'ttyname_r('), | 1565 ('ttyname(', 'ttyname_r('), |
1298 ) | 1566 ) |
1299 | 1567 |
1300 | 1568 |
1301 def CheckPosixThreading(filename, clean_lines, linenum, error): | 1569 def CheckPosixThreading(filename, clean_lines, linenum, error): |
1302 """Checks for calls to thread-unsafe functions. | 1570 """Checks for calls to thread-unsafe functions. |
1303 | 1571 |
1304 Much code has been originally written without consideration of | 1572 Much code has been originally written without consideration of |
1305 multi-threading. Also, engineers are relying on their old experience; | 1573 multi-threading. Also, engineers are relying on their old experience; |
1306 they have learned posix before threading extensions were added. These | 1574 they have learned posix before threading extensions were added. These |
1307 tests guide the engineers to use thread-safe functions (when using | 1575 tests guide the engineers to use thread-safe functions (when using |
1308 posix directly). | 1576 posix directly). |
1309 | 1577 |
1310 Args: | 1578 Args: |
1311 filename: The name of the current file. | 1579 filename: The name of the current file. |
1312 clean_lines: A CleansedLines instance containing the file. | 1580 clean_lines: A CleansedLines instance containing the file. |
1313 linenum: The number of the line to check. | 1581 linenum: The number of the line to check. |
1314 error: The function to call with any errors found. | 1582 error: The function to call with any errors found. |
1315 """ | 1583 """ |
1316 line = clean_lines.elided[linenum] | 1584 line = clean_lines.elided[linenum] |
1317 for single_thread_function, multithread_safe_function in threading_list: | 1585 for single_thread_function, multithread_safe_function in threading_list: |
1318 ix = line.find(single_thread_function) | 1586 ix = line.find(single_thread_function) |
1319 # Comparisons made explicit for clarity -- pylint: disable-msg=C6403 | 1587 # Comparisons made explicit for clarity -- pylint: disable=g-explicit-bool-c
omparison |
1320 if ix >= 0 and (ix == 0 or (not line[ix - 1].isalnum() and | 1588 if ix >= 0 and (ix == 0 or (not line[ix - 1].isalnum() and |
1321 line[ix - 1] not in ('_', '.', '>'))): | 1589 line[ix - 1] not in ('_', '.', '>'))): |
1322 error(filename, linenum, 'runtime/threadsafe_fn', 2, | 1590 error(filename, linenum, 'runtime/threadsafe_fn', 2, |
1323 'Consider using ' + multithread_safe_function + | 1591 'Consider using ' + multithread_safe_function + |
1324 '...) instead of ' + single_thread_function + | 1592 '...) instead of ' + single_thread_function + |
1325 '...) for improved thread safety.') | 1593 '...) for improved thread safety.') |
1326 | 1594 |
1327 | 1595 |
| 1596 def CheckVlogArguments(filename, clean_lines, linenum, error): |
| 1597 """Checks that VLOG() is only used for defining a logging level. |
| 1598 |
| 1599 For example, VLOG(2) is correct. VLOG(INFO), VLOG(WARNING), VLOG(ERROR), and |
| 1600 VLOG(FATAL) are not. |
| 1601 |
| 1602 Args: |
| 1603 filename: The name of the current file. |
| 1604 clean_lines: A CleansedLines instance containing the file. |
| 1605 linenum: The number of the line to check. |
| 1606 error: The function to call with any errors found. |
| 1607 """ |
| 1608 line = clean_lines.elided[linenum] |
| 1609 if Search(r'\bVLOG\((INFO|ERROR|WARNING|DFATAL|FATAL)\)', line): |
| 1610 error(filename, linenum, 'runtime/vlog', 5, |
| 1611 'VLOG() should be used with numeric verbosity level. ' |
| 1612 'Use LOG() if you want symbolic severity levels.') |
| 1613 |
| 1614 |
1328 # Matches invalid increment: *count++, which moves pointer instead of | 1615 # Matches invalid increment: *count++, which moves pointer instead of |
1329 # incrementing a value. | 1616 # incrementing a value. |
1330 _RE_PATTERN_INVALID_INCREMENT = re.compile( | 1617 _RE_PATTERN_INVALID_INCREMENT = re.compile( |
1331 r'^\s*\*\w+(\+\+|--);') | 1618 r'^\s*\*\w+(\+\+|--);') |
1332 | 1619 |
1333 | 1620 |
1334 def CheckInvalidIncrement(filename, clean_lines, linenum, error): | 1621 def CheckInvalidIncrement(filename, clean_lines, linenum, error): |
1335 """Checks for invalid increment *count++. | 1622 """Checks for invalid increment *count++. |
1336 | 1623 |
1337 For example following function: | 1624 For example following function: |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1393 class _ClassInfo(_BlockInfo): | 1680 class _ClassInfo(_BlockInfo): |
1394 """Stores information about a class.""" | 1681 """Stores information about a class.""" |
1395 | 1682 |
1396 def __init__(self, name, class_or_struct, clean_lines, linenum): | 1683 def __init__(self, name, class_or_struct, clean_lines, linenum): |
1397 _BlockInfo.__init__(self, False) | 1684 _BlockInfo.__init__(self, False) |
1398 self.name = name | 1685 self.name = name |
1399 self.starting_linenum = linenum | 1686 self.starting_linenum = linenum |
1400 self.is_derived = False | 1687 self.is_derived = False |
1401 if class_or_struct == 'struct': | 1688 if class_or_struct == 'struct': |
1402 self.access = 'public' | 1689 self.access = 'public' |
| 1690 self.is_struct = True |
1403 else: | 1691 else: |
1404 self.access = 'private' | 1692 self.access = 'private' |
| 1693 self.is_struct = False |
| 1694 |
| 1695 # Remember initial indentation level for this class. Using raw_lines here |
| 1696 # instead of elided to account for leading comments. |
| 1697 initial_indent = Match(r'^( *)\S', clean_lines.raw_lines[linenum]) |
| 1698 if initial_indent: |
| 1699 self.class_indent = len(initial_indent.group(1)) |
| 1700 else: |
| 1701 self.class_indent = 0 |
1405 | 1702 |
1406 # Try to find the end of the class. This will be confused by things like: | 1703 # Try to find the end of the class. This will be confused by things like: |
1407 # class A { | 1704 # class A { |
1408 # } *x = { ... | 1705 # } *x = { ... |
1409 # | 1706 # |
1410 # But it's still good enough for CheckSectionSpacing. | 1707 # But it's still good enough for CheckSectionSpacing. |
1411 self.last_line = 0 | 1708 self.last_line = 0 |
1412 depth = 0 | 1709 depth = 0 |
1413 for i in range(linenum, clean_lines.NumLines()): | 1710 for i in range(linenum, clean_lines.NumLines()): |
1414 line = clean_lines.elided[i] | 1711 line = clean_lines.elided[i] |
1415 depth += line.count('{') - line.count('}') | 1712 depth += line.count('{') - line.count('}') |
1416 if not depth: | 1713 if not depth: |
1417 self.last_line = i | 1714 self.last_line = i |
1418 break | 1715 break |
1419 | 1716 |
1420 def CheckBegin(self, filename, clean_lines, linenum, error): | 1717 def CheckBegin(self, filename, clean_lines, linenum, error): |
1421 # Look for a bare ':' | 1718 # Look for a bare ':' |
1422 if Search('(^|[^:]):($|[^:])', clean_lines.elided[linenum]): | 1719 if Search('(^|[^:]):($|[^:])', clean_lines.elided[linenum]): |
1423 self.is_derived = True | 1720 self.is_derived = True |
1424 | 1721 |
| 1722 def CheckEnd(self, filename, clean_lines, linenum, error): |
| 1723 # Check that closing brace is aligned with beginning of the class. |
| 1724 # Only do this if the closing brace is indented by only whitespaces. |
| 1725 # This means we will not check single-line class definitions. |
| 1726 indent = Match(r'^( *)\}', clean_lines.elided[linenum]) |
| 1727 if indent and len(indent.group(1)) != self.class_indent: |
| 1728 if self.is_struct: |
| 1729 parent = 'struct ' + self.name |
| 1730 else: |
| 1731 parent = 'class ' + self.name |
| 1732 error(filename, linenum, 'whitespace/indent', 3, |
| 1733 'Closing brace should be aligned with beginning of %s' % parent) |
| 1734 |
1425 | 1735 |
1426 class _NamespaceInfo(_BlockInfo): | 1736 class _NamespaceInfo(_BlockInfo): |
1427 """Stores information about a namespace.""" | 1737 """Stores information about a namespace.""" |
1428 | 1738 |
1429 def __init__(self, name, linenum): | 1739 def __init__(self, name, linenum): |
1430 _BlockInfo.__init__(self, False) | 1740 _BlockInfo.__init__(self, False) |
1431 self.name = name or '' | 1741 self.name = name or '' |
1432 self.starting_linenum = linenum | 1742 self.starting_linenum = linenum |
1433 | 1743 |
1434 def CheckEnd(self, filename, clean_lines, linenum, error): | 1744 def CheckEnd(self, filename, clean_lines, linenum, error): |
(...skipping 12 matching lines...) Expand all Loading... |
1447 # deciding what these nontrivial things are, so this check is | 1757 # deciding what these nontrivial things are, so this check is |
1448 # triggered by namespace size only, which works most of the time. | 1758 # triggered by namespace size only, which works most of the time. |
1449 if (linenum - self.starting_linenum < 10 | 1759 if (linenum - self.starting_linenum < 10 |
1450 and not Match(r'};*\s*(//|/\*).*\bnamespace\b', line)): | 1760 and not Match(r'};*\s*(//|/\*).*\bnamespace\b', line)): |
1451 return | 1761 return |
1452 | 1762 |
1453 # Look for matching comment at end of namespace. | 1763 # Look for matching comment at end of namespace. |
1454 # | 1764 # |
1455 # Note that we accept C style "/* */" comments for terminating | 1765 # Note that we accept C style "/* */" comments for terminating |
1456 # namespaces, so that code that terminate namespaces inside | 1766 # namespaces, so that code that terminate namespaces inside |
1457 # preprocessor macros can be cpplint clean. Example: http://go/nxpiz | 1767 # preprocessor macros can be cpplint clean. |
1458 # | 1768 # |
1459 # We also accept stuff like "// end of namespace <name>." with the | 1769 # We also accept stuff like "// end of namespace <name>." with the |
1460 # period at the end. | 1770 # period at the end. |
1461 # | 1771 # |
1462 # Besides these, we don't accept anything else, otherwise we might | 1772 # Besides these, we don't accept anything else, otherwise we might |
1463 # get false negatives when existing comment is a substring of the | 1773 # get false negatives when existing comment is a substring of the |
1464 # expected namespace. Example: http://go/ldkdc, http://cl/23548205 | 1774 # expected namespace. |
1465 if self.name: | 1775 if self.name: |
1466 # Named namespace | 1776 # Named namespace |
1467 if not Match((r'};*\s*(//|/\*).*\bnamespace\s+' + re.escape(self.name) + | 1777 if not Match((r'};*\s*(//|/\*).*\bnamespace\s+' + re.escape(self.name) + |
1468 r'[\*/\.\\\s]*$'), | 1778 r'[\*/\.\\\s]*$'), |
1469 line): | 1779 line): |
1470 error(filename, linenum, 'readability/namespace', 5, | 1780 error(filename, linenum, 'readability/namespace', 5, |
1471 'Namespace should be terminated with "// namespace %s"' % | 1781 'Namespace should be terminated with "// namespace %s"' % |
1472 self.name) | 1782 self.name) |
1473 else: | 1783 else: |
1474 # Anonymous namespace | 1784 # Anonymous namespace |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1525 | 1835 |
1526 def UpdatePreprocessor(self, line): | 1836 def UpdatePreprocessor(self, line): |
1527 """Update preprocessor stack. | 1837 """Update preprocessor stack. |
1528 | 1838 |
1529 We need to handle preprocessors due to classes like this: | 1839 We need to handle preprocessors due to classes like this: |
1530 #ifdef SWIG | 1840 #ifdef SWIG |
1531 struct ResultDetailsPageElementExtensionPoint { | 1841 struct ResultDetailsPageElementExtensionPoint { |
1532 #else | 1842 #else |
1533 struct ResultDetailsPageElementExtensionPoint : public Extension { | 1843 struct ResultDetailsPageElementExtensionPoint : public Extension { |
1534 #endif | 1844 #endif |
1535 (see http://go/qwddn for original example) | |
1536 | 1845 |
1537 We make the following assumptions (good enough for most files): | 1846 We make the following assumptions (good enough for most files): |
1538 - Preprocessor condition evaluates to true from #if up to first | 1847 - Preprocessor condition evaluates to true from #if up to first |
1539 #else/#elif/#endif. | 1848 #else/#elif/#endif. |
1540 | 1849 |
1541 - Preprocessor condition evaluates to false from #else/#elif up | 1850 - Preprocessor condition evaluates to false from #else/#elif up |
1542 to #endif. We still perform lint checks on these lines, but | 1851 to #endif. We still perform lint checks on these lines, but |
1543 these do not affect nesting stack. | 1852 these do not affect nesting stack. |
1544 | 1853 |
1545 Args: | 1854 Args: |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1653 # time it saw "class Comparator", it may think that it's a new class. | 1962 # time it saw "class Comparator", it may think that it's a new class. |
1654 # Nested templates have a similar problem: | 1963 # Nested templates have a similar problem: |
1655 # template < | 1964 # template < |
1656 # typename ExportedType, | 1965 # typename ExportedType, |
1657 # typename TupleType, | 1966 # typename TupleType, |
1658 # template <typename, typename> class ImplTemplate> | 1967 # template <typename, typename> class ImplTemplate> |
1659 # | 1968 # |
1660 # To avoid these cases, we ignore classes that are followed by '=' or '>' | 1969 # To avoid these cases, we ignore classes that are followed by '=' or '>' |
1661 class_decl_match = Match( | 1970 class_decl_match = Match( |
1662 r'\s*(template\s*<[\w\s<>,:]*>\s*)?' | 1971 r'\s*(template\s*<[\w\s<>,:]*>\s*)?' |
1663 '(class|struct)\s+([A-Z_]+\s+)*(\w+(?:::\w+)*)' | 1972 r'(class|struct)\s+([A-Z_]+\s+)*(\w+(?:::\w+)*)' |
1664 '(([^=>]|<[^<>]*>)*)$', line) | 1973 r'(([^=>]|<[^<>]*>|<[^<>]*<[^<>]*>\s*>)*)$', line) |
1665 if (class_decl_match and | 1974 if (class_decl_match and |
1666 (not self.stack or self.stack[-1].open_parentheses == 0)): | 1975 (not self.stack or self.stack[-1].open_parentheses == 0)): |
1667 self.stack.append(_ClassInfo( | 1976 self.stack.append(_ClassInfo( |
1668 class_decl_match.group(4), class_decl_match.group(2), | 1977 class_decl_match.group(4), class_decl_match.group(2), |
1669 clean_lines, linenum)) | 1978 clean_lines, linenum)) |
1670 line = class_decl_match.group(5) | 1979 line = class_decl_match.group(5) |
1671 | 1980 |
1672 # If we have not yet seen the opening brace for the innermost block, | 1981 # If we have not yet seen the opening brace for the innermost block, |
1673 # run checks here. | 1982 # run checks here. |
1674 if not self.SeenOpenBrace(): | 1983 if not self.SeenOpenBrace(): |
1675 self.stack[-1].CheckBegin(filename, clean_lines, linenum, error) | 1984 self.stack[-1].CheckBegin(filename, clean_lines, linenum, error) |
1676 | 1985 |
1677 # Update access control if we are inside a class/struct | 1986 # Update access control if we are inside a class/struct |
1678 if self.stack and isinstance(self.stack[-1], _ClassInfo): | 1987 if self.stack and isinstance(self.stack[-1], _ClassInfo): |
1679 access_match = Match(r'\s*(public|private|protected)\s*:', line) | 1988 classinfo = self.stack[-1] |
| 1989 access_match = Match( |
| 1990 r'^(.*)\b(public|private|protected|signals)(\s+(?:slots\s*)?)?' |
| 1991 r':(?:[^:]|$)', |
| 1992 line) |
1680 if access_match: | 1993 if access_match: |
1681 self.stack[-1].access = access_match.group(1) | 1994 classinfo.access = access_match.group(2) |
| 1995 |
| 1996 # Check that access keywords are indented +1 space. Skip this |
| 1997 # check if the keywords are not preceded by whitespaces. |
| 1998 indent = access_match.group(1) |
| 1999 if (len(indent) != classinfo.class_indent + 1 and |
| 2000 Match(r'^\s*$', indent)): |
| 2001 if classinfo.is_struct: |
| 2002 parent = 'struct ' + classinfo.name |
| 2003 else: |
| 2004 parent = 'class ' + classinfo.name |
| 2005 slots = '' |
| 2006 if access_match.group(3): |
| 2007 slots = access_match.group(3) |
| 2008 error(filename, linenum, 'whitespace/indent', 3, |
| 2009 '%s%s: should be indented +1 space inside %s' % ( |
| 2010 access_match.group(2), slots, parent)) |
1682 | 2011 |
1683 # Consume braces or semicolons from what's left of the line | 2012 # Consume braces or semicolons from what's left of the line |
1684 while True: | 2013 while True: |
1685 # Match first brace, semicolon, or closed parenthesis. | 2014 # Match first brace, semicolon, or closed parenthesis. |
1686 matched = Match(r'^[^{;)}]*([{;)}])(.*)$', line) | 2015 matched = Match(r'^[^{;)}]*([{;)}])(.*)$', line) |
1687 if not matched: | 2016 if not matched: |
1688 break | 2017 break |
1689 | 2018 |
1690 token = matched.group(1) | 2019 token = matched.group(1) |
1691 if token == '{': | 2020 if token == '{': |
(...skipping 29 matching lines...) Expand all Loading... |
1721 | 2050 |
1722 Returns: | 2051 Returns: |
1723 A _ClassInfo object if we are inside a class, or None otherwise. | 2052 A _ClassInfo object if we are inside a class, or None otherwise. |
1724 """ | 2053 """ |
1725 for i in range(len(self.stack), 0, -1): | 2054 for i in range(len(self.stack), 0, -1): |
1726 classinfo = self.stack[i - 1] | 2055 classinfo = self.stack[i - 1] |
1727 if isinstance(classinfo, _ClassInfo): | 2056 if isinstance(classinfo, _ClassInfo): |
1728 return classinfo | 2057 return classinfo |
1729 return None | 2058 return None |
1730 | 2059 |
1731 def CheckClassFinished(self, filename, error): | 2060 def CheckCompletedBlocks(self, filename, error): |
1732 """Checks that all classes have been completely parsed. | 2061 """Checks that all classes and namespaces have been completely parsed. |
1733 | 2062 |
1734 Call this when all lines in a file have been processed. | 2063 Call this when all lines in a file have been processed. |
1735 Args: | 2064 Args: |
1736 filename: The name of the current file. | 2065 filename: The name of the current file. |
1737 error: The function to call with any errors found. | 2066 error: The function to call with any errors found. |
1738 """ | 2067 """ |
1739 # Note: This test can result in false positives if #ifdef constructs | 2068 # Note: This test can result in false positives if #ifdef constructs |
1740 # get in the way of brace matching. See the testBuildClass test in | 2069 # get in the way of brace matching. See the testBuildClass test in |
1741 # cpplint_unittest.py for an example of this. | 2070 # cpplint_unittest.py for an example of this. |
1742 for obj in self.stack: | 2071 for obj in self.stack: |
1743 if isinstance(obj, _ClassInfo): | 2072 if isinstance(obj, _ClassInfo): |
1744 error(filename, obj.starting_linenum, 'build/class', 5, | 2073 error(filename, obj.starting_linenum, 'build/class', 5, |
1745 'Failed to find complete declaration of class %s' % | 2074 'Failed to find complete declaration of class %s' % |
1746 obj.name) | 2075 obj.name) |
| 2076 elif isinstance(obj, _NamespaceInfo): |
| 2077 error(filename, obj.starting_linenum, 'build/namespaces', 5, |
| 2078 'Failed to find complete declaration of namespace %s' % |
| 2079 obj.name) |
1747 | 2080 |
1748 | 2081 |
1749 def CheckForNonStandardConstructs(filename, clean_lines, linenum, | 2082 def CheckForNonStandardConstructs(filename, clean_lines, linenum, |
1750 nesting_state, error): | 2083 nesting_state, error): |
1751 """Logs an error if we see certain non-ANSI constructs ignored by gcc-2. | 2084 r"""Logs an error if we see certain non-ANSI constructs ignored by gcc-2. |
1752 | 2085 |
1753 Complain about several constructs which gcc-2 accepts, but which are | 2086 Complain about several constructs which gcc-2 accepts, but which are |
1754 not standard C++. Warning about these in lint is one way to ease the | 2087 not standard C++. Warning about these in lint is one way to ease the |
1755 transition to new compilers. | 2088 transition to new compilers. |
1756 - put storage class first (e.g. "static const" instead of "const static"). | 2089 - put storage class first (e.g. "static const" instead of "const static"). |
1757 - "%lld" instead of %qd" in printf-type functions. | 2090 - "%lld" instead of %qd" in printf-type functions. |
1758 - "%1$d" is non-standard in printf-type functions. | 2091 - "%1$d" is non-standard in printf-type functions. |
1759 - "\%" is an undefined character escape sequence. | 2092 - "\%" is an undefined character escape sequence. |
1760 - text after #endif is not allowed. | 2093 - text after #endif is not allowed. |
1761 - invalid inner-style forward declaration. | 2094 - invalid inner-style forward declaration. |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1840 # The constructor and destructor will not have those qualifiers. | 2173 # The constructor and destructor will not have those qualifiers. |
1841 base_classname = classinfo.name.split('::')[-1] | 2174 base_classname = classinfo.name.split('::')[-1] |
1842 | 2175 |
1843 # Look for single-argument constructors that aren't marked explicit. | 2176 # Look for single-argument constructors that aren't marked explicit. |
1844 # Technically a valid construct, but against style. | 2177 # Technically a valid construct, but against style. |
1845 args = Match(r'\s+(?:inline\s+)?%s\s*\(([^,()]+)\)' | 2178 args = Match(r'\s+(?:inline\s+)?%s\s*\(([^,()]+)\)' |
1846 % re.escape(base_classname), | 2179 % re.escape(base_classname), |
1847 line) | 2180 line) |
1848 if (args and | 2181 if (args and |
1849 args.group(1) != 'void' and | 2182 args.group(1) != 'void' and |
1850 not Match(r'(const\s+)?%s\s*(?:<\w+>\s*)?&' % re.escape(base_classname), | 2183 not Match(r'(const\s+)?%s(\s+const)?\s*(?:<\w+>\s*)?&' |
1851 args.group(1).strip())): | 2184 % re.escape(base_classname), args.group(1).strip())): |
1852 error(filename, linenum, 'runtime/explicit', 5, | 2185 error(filename, linenum, 'runtime/explicit', 5, |
1853 'Single-argument constructors should be marked explicit.') | 2186 'Single-argument constructors should be marked explicit.') |
1854 | 2187 |
1855 | 2188 |
1856 def CheckSpacingForFunctionCall(filename, line, linenum, error): | 2189 def CheckSpacingForFunctionCall(filename, line, linenum, error): |
1857 """Checks for the correctness of various spacing around function calls. | 2190 """Checks for the correctness of various spacing around function calls. |
1858 | 2191 |
1859 Args: | 2192 Args: |
1860 filename: The name of the current file. | 2193 filename: The name of the current file. |
1861 line: The text of the line to check. | 2194 line: The text of the line to check. |
(...skipping 22 matching lines...) Expand all Loading... |
1884 # function argument when the char before the whitespace is legal in | 2217 # function argument when the char before the whitespace is legal in |
1885 # a function name (alnum + _) and we're not starting a macro. Also ignore | 2218 # a function name (alnum + _) and we're not starting a macro. Also ignore |
1886 # pointers and references to arrays and functions coz they're too tricky: | 2219 # pointers and references to arrays and functions coz they're too tricky: |
1887 # we use a very simple way to recognize these: | 2220 # we use a very simple way to recognize these: |
1888 # " (something)(maybe-something)" or | 2221 # " (something)(maybe-something)" or |
1889 # " (something)(maybe-something," or | 2222 # " (something)(maybe-something," or |
1890 # " (something)[something]" | 2223 # " (something)[something]" |
1891 # Note that we assume the contents of [] to be short enough that | 2224 # Note that we assume the contents of [] to be short enough that |
1892 # they'll never need to wrap. | 2225 # they'll never need to wrap. |
1893 if ( # Ignore control structures. | 2226 if ( # Ignore control structures. |
1894 not Search(r'\b(if|for|while|switch|return|delete)\b', fncall) and | 2227 not Search(r'\b(if|for|while|switch|return|new|delete|catch|sizeof)\b', |
| 2228 fncall) and |
1895 # Ignore pointers/references to functions. | 2229 # Ignore pointers/references to functions. |
1896 not Search(r' \([^)]+\)\([^)]*(\)|,$)', fncall) and | 2230 not Search(r' \([^)]+\)\([^)]*(\)|,$)', fncall) and |
1897 # Ignore pointers/references to arrays. | 2231 # Ignore pointers/references to arrays. |
1898 not Search(r' \([^)]+\)\[[^\]]+\]', fncall)): | 2232 not Search(r' \([^)]+\)\[[^\]]+\]', fncall)): |
1899 if Search(r'\w\s*\(\s(?!\s*\\$)', fncall): # a ( used for a fn call | 2233 if Search(r'\w\s*\(\s(?!\s*\\$)', fncall): # a ( used for a fn call |
1900 error(filename, linenum, 'whitespace/parens', 4, | 2234 error(filename, linenum, 'whitespace/parens', 4, |
1901 'Extra space after ( in function call') | 2235 'Extra space after ( in function call') |
1902 elif Search(r'\(\s+(?!(\s*\\)|\()', fncall): | 2236 elif Search(r'\(\s+(?!(\s*\\)|\()', fncall): |
1903 error(filename, linenum, 'whitespace/parens', 2, | 2237 error(filename, linenum, 'whitespace/parens', 2, |
1904 'Extra space after (') | 2238 'Extra space after (') |
1905 if (Search(r'\w\s+\(', fncall) and | 2239 if (Search(r'\w\s+\(', fncall) and |
1906 not Search(r'#\s*define|typedef', fncall) and | 2240 not Search(r'#\s*define|typedef', fncall) and |
1907 not Search(r'\w\s+\((\w+::)?\*\w+\)\(', fncall)): | 2241 not Search(r'\w\s+\((\w+::)*\*\w+\)\(', fncall)): |
1908 error(filename, linenum, 'whitespace/parens', 4, | 2242 error(filename, linenum, 'whitespace/parens', 4, |
1909 'Extra space before ( in function call') | 2243 'Extra space before ( in function call') |
1910 # If the ) is followed only by a newline or a { + newline, assume it's | 2244 # If the ) is followed only by a newline or a { + newline, assume it's |
1911 # part of a control statement (if/while/etc), and don't complain | 2245 # part of a control statement (if/while/etc), and don't complain |
1912 if Search(r'[^)]\s+\)\s*[^{\s]', fncall): | 2246 if Search(r'[^)]\s+\)\s*[^{\s]', fncall): |
1913 # If the closing parenthesis is preceded by only whitespaces, | 2247 # If the closing parenthesis is preceded by only whitespaces, |
1914 # try to give a more descriptive error message. | 2248 # try to give a more descriptive error message. |
1915 if Search(r'^\s+\)', fncall): | 2249 if Search(r'^\s+\)', fncall): |
1916 error(filename, linenum, 'whitespace/parens', 2, | 2250 error(filename, linenum, 'whitespace/parens', 2, |
1917 'Closing ) should be moved to the previous line') | 2251 'Closing ) should be moved to the previous line') |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2025 error(filename, linenum, 'whitespace/todo', 2, | 2359 error(filename, linenum, 'whitespace/todo', 2, |
2026 'Too many spaces before TODO') | 2360 'Too many spaces before TODO') |
2027 | 2361 |
2028 username = match.group(2) | 2362 username = match.group(2) |
2029 if not username: | 2363 if not username: |
2030 error(filename, linenum, 'readability/todo', 2, | 2364 error(filename, linenum, 'readability/todo', 2, |
2031 'Missing username in TODO; it should look like ' | 2365 'Missing username in TODO; it should look like ' |
2032 '"// TODO(my_username): Stuff."') | 2366 '"// TODO(my_username): Stuff."') |
2033 | 2367 |
2034 middle_whitespace = match.group(3) | 2368 middle_whitespace = match.group(3) |
2035 # Comparisons made explicit for correctness -- pylint: disable-msg=C6403 | 2369 # Comparisons made explicit for correctness -- pylint: disable=g-explicit-bo
ol-comparison |
2036 if middle_whitespace != ' ' and middle_whitespace != '': | 2370 if middle_whitespace != ' ' and middle_whitespace != '': |
2037 error(filename, linenum, 'whitespace/todo', 2, | 2371 error(filename, linenum, 'whitespace/todo', 2, |
2038 'TODO(my_username) should be followed by a space') | 2372 'TODO(my_username) should be followed by a space') |
2039 | 2373 |
2040 def CheckAccess(filename, clean_lines, linenum, nesting_state, error): | 2374 def CheckAccess(filename, clean_lines, linenum, nesting_state, error): |
2041 """Checks for improper use of DISALLOW* macros. | 2375 """Checks for improper use of DISALLOW* macros. |
2042 | 2376 |
2043 Args: | 2377 Args: |
2044 filename: The name of the current file. | 2378 filename: The name of the current file. |
2045 clean_lines: A CleansedLines instance containing the file. | 2379 clean_lines: A CleansedLines instance containing the file. |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2082 line = init_suffix | 2416 line = init_suffix |
2083 nesting_stack = ['<'] | 2417 nesting_stack = ['<'] |
2084 while True: | 2418 while True: |
2085 # Find the next operator that can tell us whether < is used as an | 2419 # Find the next operator that can tell us whether < is used as an |
2086 # opening bracket or as a less-than operator. We only want to | 2420 # opening bracket or as a less-than operator. We only want to |
2087 # warn on the latter case. | 2421 # warn on the latter case. |
2088 # | 2422 # |
2089 # We could also check all other operators and terminate the search | 2423 # We could also check all other operators and terminate the search |
2090 # early, e.g. if we got something like this "a<b+c", the "<" is | 2424 # early, e.g. if we got something like this "a<b+c", the "<" is |
2091 # most likely a less-than operator, but then we will get false | 2425 # most likely a less-than operator, but then we will get false |
2092 # positives for default arguments (e.g. http://go/prccd) and | 2426 # positives for default arguments and other template expressions. |
2093 # other template expressions (e.g. http://go/oxcjq). | |
2094 match = Search(r'^[^<>(),;\[\]]*([<>(),;\[\]])(.*)$', line) | 2427 match = Search(r'^[^<>(),;\[\]]*([<>(),;\[\]])(.*)$', line) |
2095 if match: | 2428 if match: |
2096 # Found an operator, update nesting stack | 2429 # Found an operator, update nesting stack |
2097 operator = match.group(1) | 2430 operator = match.group(1) |
2098 line = match.group(2) | 2431 line = match.group(2) |
2099 | 2432 |
2100 if nesting_stack[-1] == '<': | 2433 if nesting_stack[-1] == '<': |
2101 # Expecting closing angle bracket | 2434 # Expecting closing angle bracket |
2102 if operator in ('<', '(', '['): | 2435 if operator in ('<', '(', '['): |
2103 nesting_stack.append(operator) | 2436 nesting_stack.append(operator) |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2206 | 2539 |
2207 Args: | 2540 Args: |
2208 filename: The name of the current file. | 2541 filename: The name of the current file. |
2209 clean_lines: A CleansedLines instance containing the file. | 2542 clean_lines: A CleansedLines instance containing the file. |
2210 linenum: The number of the line to check. | 2543 linenum: The number of the line to check. |
2211 nesting_state: A _NestingState instance which maintains information about | 2544 nesting_state: A _NestingState instance which maintains information about |
2212 the current stack of nested blocks being parsed. | 2545 the current stack of nested blocks being parsed. |
2213 error: The function to call with any errors found. | 2546 error: The function to call with any errors found. |
2214 """ | 2547 """ |
2215 | 2548 |
2216 raw = clean_lines.raw_lines | 2549 # Don't use "elided" lines here, otherwise we can't check commented lines. |
| 2550 # Don't want to use "raw" either, because we don't want to check inside C++11 |
| 2551 # raw strings, |
| 2552 raw = clean_lines.lines_without_raw_strings |
2217 line = raw[linenum] | 2553 line = raw[linenum] |
2218 | 2554 |
2219 # Before nixing comments, check if the line is blank for no good | 2555 # Before nixing comments, check if the line is blank for no good |
2220 # reason. This includes the first line after a block is opened, and | 2556 # reason. This includes the first line after a block is opened, and |
2221 # blank lines at the end of a function (ie, right before a line like '}' | 2557 # blank lines at the end of a function (ie, right before a line like '}' |
2222 # | 2558 # |
2223 # Skip all the blank line checks if we are immediately inside a | 2559 # Skip all the blank line checks if we are immediately inside a |
2224 # namespace body. In other words, don't issue blank line warnings | 2560 # namespace body. In other words, don't issue blank line warnings |
2225 # for this block: | 2561 # for this block: |
2226 # namespace { | 2562 # namespace { |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2260 # closing paren, without the opening paren, followed by an opening brace | 2596 # closing paren, without the opening paren, followed by an opening brace |
2261 # or colon (for initializer lists) we assume that it is the last line of | 2597 # or colon (for initializer lists) we assume that it is the last line of |
2262 # a function header. If we have a colon indented 4 spaces, it is an | 2598 # a function header. If we have a colon indented 4 spaces, it is an |
2263 # initializer list. | 2599 # initializer list. |
2264 exception = (Match(r' {4}\w[^\(]*\)\s*(const\s*)?(\{\s*$|:)', | 2600 exception = (Match(r' {4}\w[^\(]*\)\s*(const\s*)?(\{\s*$|:)', |
2265 prev_line) | 2601 prev_line) |
2266 or Match(r' {4}:', prev_line)) | 2602 or Match(r' {4}:', prev_line)) |
2267 | 2603 |
2268 if not exception: | 2604 if not exception: |
2269 error(filename, linenum, 'whitespace/blank_line', 2, | 2605 error(filename, linenum, 'whitespace/blank_line', 2, |
2270 'Blank line at the start of a code block. Is this needed?') | 2606 'Redundant blank line at the start of a code block ' |
| 2607 'should be deleted.') |
2271 # Ignore blank lines at the end of a block in a long if-else | 2608 # Ignore blank lines at the end of a block in a long if-else |
2272 # chain, like this: | 2609 # chain, like this: |
2273 # if (condition1) { | 2610 # if (condition1) { |
2274 # // Something followed by a blank line | 2611 # // Something followed by a blank line |
2275 # | 2612 # |
2276 # } else if (condition2) { | 2613 # } else if (condition2) { |
2277 # // Something else | 2614 # // Something else |
2278 # } | 2615 # } |
2279 if linenum + 1 < clean_lines.NumLines(): | 2616 if linenum + 1 < clean_lines.NumLines(): |
2280 next_line = raw[linenum + 1] | 2617 next_line = raw[linenum + 1] |
2281 if (next_line | 2618 if (next_line |
2282 and Match(r'\s*}', next_line) | 2619 and Match(r'\s*}', next_line) |
2283 and next_line.find('} else ') == -1): | 2620 and next_line.find('} else ') == -1): |
2284 error(filename, linenum, 'whitespace/blank_line', 3, | 2621 error(filename, linenum, 'whitespace/blank_line', 3, |
2285 'Blank line at the end of a code block. Is this needed?') | 2622 'Redundant blank line at the end of a code block ' |
| 2623 'should be deleted.') |
2286 | 2624 |
2287 matched = Match(r'\s*(public|protected|private):', prev_line) | 2625 matched = Match(r'\s*(public|protected|private):', prev_line) |
2288 if matched: | 2626 if matched: |
2289 error(filename, linenum, 'whitespace/blank_line', 3, | 2627 error(filename, linenum, 'whitespace/blank_line', 3, |
2290 'Do not leave a blank line after "%s:"' % matched.group(1)) | 2628 'Do not leave a blank line after "%s:"' % matched.group(1)) |
2291 | 2629 |
2292 # Next, we complain if there's a comment too near the text | 2630 # Next, we complain if there's a comment too near the text |
2293 commentpos = line.find('//') | 2631 commentpos = line.find('//') |
2294 if commentpos != -1: | 2632 if commentpos != -1: |
2295 # Check if the // may be in quotes. If so, ignore it | 2633 # Check if the // may be in quotes. If so, ignore it |
2296 # Comparisons made explicit for clarity -- pylint: disable-msg=C6403 | 2634 # Comparisons made explicit for clarity -- pylint: disable=g-explicit-bool-c
omparison |
2297 if (line.count('"', 0, commentpos) - | 2635 if (line.count('"', 0, commentpos) - |
2298 line.count('\\"', 0, commentpos)) % 2 == 0: # not in quotes | 2636 line.count('\\"', 0, commentpos)) % 2 == 0: # not in quotes |
2299 # Allow one space for new scopes, two spaces otherwise: | 2637 # Allow one space for new scopes, two spaces otherwise: |
2300 if (not Match(r'^\s*{ //', line) and | 2638 if (not Match(r'^\s*{ //', line) and |
2301 ((commentpos >= 1 and | 2639 ((commentpos >= 1 and |
2302 line[commentpos-1] not in string.whitespace) or | 2640 line[commentpos-1] not in string.whitespace) or |
2303 (commentpos >= 2 and | 2641 (commentpos >= 2 and |
2304 line[commentpos-2] not in string.whitespace))): | 2642 line[commentpos-2] not in string.whitespace))): |
2305 error(filename, linenum, 'whitespace/comments', 2, | 2643 error(filename, linenum, 'whitespace/comments', 2, |
2306 'At least two spaces is best between code and comments') | 2644 'At least two spaces is best between code and comments') |
2307 # There should always be a space between the // and the comment | 2645 # There should always be a space between the // and the comment |
2308 commentend = commentpos + 2 | 2646 commentend = commentpos + 2 |
2309 if commentend < len(line) and not line[commentend] == ' ': | 2647 if commentend < len(line) and not line[commentend] == ' ': |
2310 # but some lines are exceptions -- e.g. if they're big | 2648 # but some lines are exceptions -- e.g. if they're big |
2311 # comment delimiters like: | 2649 # comment delimiters like: |
2312 # //---------------------------------------------------------- | 2650 # //---------------------------------------------------------- |
2313 # or are an empty C++ style Doxygen comment, like: | 2651 # or are an empty C++ style Doxygen comment, like: |
2314 # /// | 2652 # /// |
| 2653 # or C++ style Doxygen comments placed after the variable: |
| 2654 # ///< Header comment |
| 2655 # //!< Header comment |
2315 # or they begin with multiple slashes followed by a space: | 2656 # or they begin with multiple slashes followed by a space: |
2316 # //////// Header comment | 2657 # //////// Header comment |
2317 match = (Search(r'[=/-]{4,}\s*$', line[commentend:]) or | 2658 match = (Search(r'[=/-]{4,}\s*$', line[commentend:]) or |
2318 Search(r'^/$', line[commentend:]) or | 2659 Search(r'^/$', line[commentend:]) or |
| 2660 Search(r'^!< ', line[commentend:]) or |
| 2661 Search(r'^/< ', line[commentend:]) or |
2319 Search(r'^/+ ', line[commentend:])) | 2662 Search(r'^/+ ', line[commentend:])) |
2320 if not match: | 2663 if not match: |
2321 error(filename, linenum, 'whitespace/comments', 4, | 2664 error(filename, linenum, 'whitespace/comments', 4, |
2322 'Should have a space between // and comment') | 2665 'Should have a space between // and comment') |
2323 CheckComment(line[commentpos:], filename, linenum, error) | 2666 CheckComment(line[commentpos:], filename, linenum, error) |
2324 | 2667 |
2325 line = clean_lines.elided[linenum] # get rid of comments and strings | 2668 line = clean_lines.elided[linenum] # get rid of comments and strings |
2326 | 2669 |
2327 # Don't try to do spacing checks for operator methods | 2670 # Don't try to do spacing checks for operator methods |
2328 line = re.sub(r'operator(==|!=|<|<<|<=|>=|>>|>)\(', 'operator\(', line) | 2671 line = re.sub(r'operator(==|!=|<|<<|<=|>=|>>|>)\(', 'operator\(', line) |
(...skipping 13 matching lines...) Expand all Loading... |
2342 # You should always have whitespace around binary operators. | 2685 # You should always have whitespace around binary operators. |
2343 # | 2686 # |
2344 # Check <= and >= first to avoid false positives with < and >, then | 2687 # Check <= and >= first to avoid false positives with < and >, then |
2345 # check non-include lines for spacing around < and >. | 2688 # check non-include lines for spacing around < and >. |
2346 match = Search(r'[^<>=!\s](==|!=|<=|>=)[^<>=!\s]', line) | 2689 match = Search(r'[^<>=!\s](==|!=|<=|>=)[^<>=!\s]', line) |
2347 if match: | 2690 if match: |
2348 error(filename, linenum, 'whitespace/operators', 3, | 2691 error(filename, linenum, 'whitespace/operators', 3, |
2349 'Missing spaces around %s' % match.group(1)) | 2692 'Missing spaces around %s' % match.group(1)) |
2350 # We allow no-spaces around << when used like this: 10<<20, but | 2693 # We allow no-spaces around << when used like this: 10<<20, but |
2351 # not otherwise (particularly, not when used as streams) | 2694 # not otherwise (particularly, not when used as streams) |
2352 match = Search(r'(\S)(?:L|UL|ULL|l|ul|ull)?<<(\S)', line) | 2695 # Also ignore using ns::operator<<; |
2353 if match and not (match.group(1).isdigit() and match.group(2).isdigit()): | 2696 match = Search(r'(operator|\S)(?:L|UL|ULL|l|ul|ull)?<<(\S)', line) |
| 2697 if (match and |
| 2698 not (match.group(1).isdigit() and match.group(2).isdigit()) and |
| 2699 not (match.group(1) == 'operator' and match.group(2) == ';')): |
2354 error(filename, linenum, 'whitespace/operators', 3, | 2700 error(filename, linenum, 'whitespace/operators', 3, |
2355 'Missing spaces around <<') | 2701 'Missing spaces around <<') |
2356 elif not Match(r'#.*include', line): | 2702 elif not Match(r'#.*include', line): |
2357 # Avoid false positives on -> | 2703 # Avoid false positives on -> |
2358 reduced_line = line.replace('->', '') | 2704 reduced_line = line.replace('->', '') |
2359 | 2705 |
2360 # Look for < that is not surrounded by spaces. This is only | 2706 # Look for < that is not surrounded by spaces. This is only |
2361 # triggered if both sides are missing spaces, even though | 2707 # triggered if both sides are missing spaces, even though |
2362 # technically should should flag if at least one side is missing a | 2708 # technically should should flag if at least one side is missing a |
2363 # space. This is done to avoid some false positives with shifts. | 2709 # space. This is done to avoid some false positives with shifts. |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2414 match = Search(r'\b(if|for|while|switch)\s*' | 2760 match = Search(r'\b(if|for|while|switch)\s*' |
2415 r'\(([ ]*)(.).*[^ ]+([ ]*)\)\s*{\s*$', | 2761 r'\(([ ]*)(.).*[^ ]+([ ]*)\)\s*{\s*$', |
2416 line) | 2762 line) |
2417 if match: | 2763 if match: |
2418 if len(match.group(2)) != len(match.group(4)): | 2764 if len(match.group(2)) != len(match.group(4)): |
2419 if not (match.group(3) == ';' and | 2765 if not (match.group(3) == ';' and |
2420 len(match.group(2)) == 1 + len(match.group(4)) or | 2766 len(match.group(2)) == 1 + len(match.group(4)) or |
2421 not match.group(2) and Search(r'\bfor\s*\(.*; \)', line)): | 2767 not match.group(2) and Search(r'\bfor\s*\(.*; \)', line)): |
2422 error(filename, linenum, 'whitespace/parens', 5, | 2768 error(filename, linenum, 'whitespace/parens', 5, |
2423 'Mismatching spaces inside () in %s' % match.group(1)) | 2769 'Mismatching spaces inside () in %s' % match.group(1)) |
2424 if not len(match.group(2)) in [0, 1]: | 2770 if len(match.group(2)) not in [0, 1]: |
2425 error(filename, linenum, 'whitespace/parens', 5, | 2771 error(filename, linenum, 'whitespace/parens', 5, |
2426 'Should have zero or one spaces inside ( and ) in %s' % | 2772 'Should have zero or one spaces inside ( and ) in %s' % |
2427 match.group(1)) | 2773 match.group(1)) |
2428 | 2774 |
2429 # You should always have a space after a comma (either as fn arg or operator) | 2775 # You should always have a space after a comma (either as fn arg or operator) |
2430 if Search(r',[^\s]', line): | 2776 # |
| 2777 # This does not apply when the non-space character following the |
| 2778 # comma is another comma, since the only time when that happens is |
| 2779 # for empty macro arguments. |
| 2780 # |
| 2781 # We run this check in two passes: first pass on elided lines to |
| 2782 # verify that lines contain missing whitespaces, second pass on raw |
| 2783 # lines to confirm that those missing whitespaces are not due to |
| 2784 # elided comments. |
| 2785 if Search(r',[^,\s]', line) and Search(r',[^,\s]', raw[linenum]): |
2431 error(filename, linenum, 'whitespace/comma', 3, | 2786 error(filename, linenum, 'whitespace/comma', 3, |
2432 'Missing space after ,') | 2787 'Missing space after ,') |
2433 | 2788 |
2434 # You should always have a space after a semicolon | 2789 # You should always have a space after a semicolon |
2435 # except for few corner cases | 2790 # except for few corner cases |
2436 # TODO(unknown): clarify if 'if (1) { return 1;}' is requires one more | 2791 # TODO(unknown): clarify if 'if (1) { return 1;}' is requires one more |
2437 # space after ; | 2792 # space after ; |
2438 if Search(r';[^\s};\\)/]', line): | 2793 if Search(r';[^\s};\\)/]', line): |
2439 error(filename, linenum, 'whitespace/semicolon', 3, | 2794 error(filename, linenum, 'whitespace/semicolon', 3, |
2440 'Missing space after ;') | 2795 'Missing space after ;') |
2441 | 2796 |
2442 # Next we will look for issues with function calls. | 2797 # Next we will look for issues with function calls. |
2443 CheckSpacingForFunctionCall(filename, line, linenum, error) | 2798 CheckSpacingForFunctionCall(filename, line, linenum, error) |
2444 | 2799 |
2445 # Except after an opening paren, or after another opening brace (in case of | 2800 # Except after an opening paren, or after another opening brace (in case of |
2446 # an initializer list, for instance), you should have spaces before your | 2801 # an initializer list, for instance), you should have spaces before your |
2447 # braces. And since you should never have braces at the beginning of a line, | 2802 # braces. And since you should never have braces at the beginning of a line, |
2448 # this is an easy test. | 2803 # this is an easy test. |
2449 if Search(r'[^ ({]{', line): | 2804 match = Match(r'^(.*[^ ({]){', line) |
2450 error(filename, linenum, 'whitespace/braces', 5, | 2805 if match: |
2451 'Missing space before {') | 2806 # Try a bit harder to check for brace initialization. This |
| 2807 # happens in one of the following forms: |
| 2808 # Constructor() : initializer_list_{} { ... } |
| 2809 # Constructor{}.MemberFunction() |
| 2810 # Type variable{}; |
| 2811 # FunctionCall(type{}, ...); |
| 2812 # LastArgument(..., type{}); |
| 2813 # LOG(INFO) << type{} << " ..."; |
| 2814 # map_of_type[{...}] = ...; |
| 2815 # |
| 2816 # We check for the character following the closing brace, and |
| 2817 # silence the warning if it's one of those listed above, i.e. |
| 2818 # "{.;,)<]". |
| 2819 # |
| 2820 # To account for nested initializer list, we allow any number of |
| 2821 # closing braces up to "{;,)<". We can't simply silence the |
| 2822 # warning on first sight of closing brace, because that would |
| 2823 # cause false negatives for things that are not initializer lists. |
| 2824 # Silence this: But not this: |
| 2825 # Outer{ if (...) { |
| 2826 # Inner{...} if (...){ // Missing space before { |
| 2827 # }; } |
| 2828 # |
| 2829 # There is a false negative with this approach if people inserted |
| 2830 # spurious semicolons, e.g. "if (cond){};", but we will catch the |
| 2831 # spurious semicolon with a separate check. |
| 2832 (endline, endlinenum, endpos) = CloseExpression( |
| 2833 clean_lines, linenum, len(match.group(1))) |
| 2834 trailing_text = '' |
| 2835 if endpos > -1: |
| 2836 trailing_text = endline[endpos:] |
| 2837 for offset in xrange(endlinenum + 1, |
| 2838 min(endlinenum + 3, clean_lines.NumLines() - 1)): |
| 2839 trailing_text += clean_lines.elided[offset] |
| 2840 if not Match(r'^[\s}]*[{.;,)<\]]', trailing_text): |
| 2841 error(filename, linenum, 'whitespace/braces', 5, |
| 2842 'Missing space before {') |
2452 | 2843 |
2453 # Make sure '} else {' has spaces. | 2844 # Make sure '} else {' has spaces. |
2454 if Search(r'}else', line): | 2845 if Search(r'}else', line): |
2455 error(filename, linenum, 'whitespace/braces', 5, | 2846 error(filename, linenum, 'whitespace/braces', 5, |
2456 'Missing space before else') | 2847 'Missing space before else') |
2457 | 2848 |
2458 # You shouldn't have spaces before your brackets, except maybe after | 2849 # You shouldn't have spaces before your brackets, except maybe after |
2459 # 'delete []' or 'new char * []'. | 2850 # 'delete []' or 'new char * []'. |
2460 if Search(r'\w\s+\[', line) and not Search(r'delete\s+\[', line): | 2851 if Search(r'\w\s+\[', line) and not Search(r'delete\s+\[', line): |
2461 error(filename, linenum, 'whitespace/braces', 5, | 2852 error(filename, linenum, 'whitespace/braces', 5, |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2569 Args: | 2960 Args: |
2570 filename: The name of the current file. | 2961 filename: The name of the current file. |
2571 clean_lines: A CleansedLines instance containing the file. | 2962 clean_lines: A CleansedLines instance containing the file. |
2572 linenum: The number of the line to check. | 2963 linenum: The number of the line to check. |
2573 error: The function to call with any errors found. | 2964 error: The function to call with any errors found. |
2574 """ | 2965 """ |
2575 | 2966 |
2576 line = clean_lines.elided[linenum] # get rid of comments and strings | 2967 line = clean_lines.elided[linenum] # get rid of comments and strings |
2577 | 2968 |
2578 if Match(r'\s*{\s*$', line): | 2969 if Match(r'\s*{\s*$', line): |
2579 # We allow an open brace to start a line in the case where someone | 2970 # We allow an open brace to start a line in the case where someone is using |
2580 # is using braces in a block to explicitly create a new scope, | 2971 # braces in a block to explicitly create a new scope, which is commonly used |
2581 # which is commonly used to control the lifetime of | 2972 # to control the lifetime of stack-allocated variables. Braces are also |
2582 # stack-allocated variables. We don't detect this perfectly: we | 2973 # used for brace initializers inside function calls. We don't detect this |
2583 # just don't complain if the last non-whitespace character on the | 2974 # perfectly: we just don't complain if the last non-whitespace character on |
2584 # previous non-blank line is ';', ':', '{', or '}', or if the previous | 2975 # the previous non-blank line is ',', ';', ':', '(', '{', or '}', or if the |
2585 # line starts a preprocessor block. | 2976 # previous line starts a preprocessor block. |
2586 prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0] | 2977 prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0] |
2587 if (not Search(r'[;:}{]\s*$', prevline) and | 2978 if (not Search(r'[,;:}{(]\s*$', prevline) and |
2588 not Match(r'\s*#', prevline)): | 2979 not Match(r'\s*#', prevline)): |
2589 error(filename, linenum, 'whitespace/braces', 4, | 2980 error(filename, linenum, 'whitespace/braces', 4, |
2590 '{ should almost always be at the end of the previous line') | 2981 '{ should almost always be at the end of the previous line') |
2591 | 2982 |
2592 # An else clause should be on the same line as the preceding closing brace. | 2983 # An else clause should be on the same line as the preceding closing brace. |
2593 if Match(r'\s*else\s*', line): | 2984 if Match(r'\s*else\s*', line): |
2594 prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0] | 2985 prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0] |
2595 if Match(r'\s*}\s*$', prevline): | 2986 if Match(r'\s*}\s*$', prevline): |
2596 error(filename, linenum, 'whitespace/newline', 4, | 2987 error(filename, linenum, 'whitespace/newline', 4, |
2597 'An else should appear on the same line as the preceding }') | 2988 'An else should appear on the same line as the preceding }') |
(...skipping 17 matching lines...) Expand all Loading... |
2615 # Likewise, an else should never have the else clause on the same line | 3006 # Likewise, an else should never have the else clause on the same line |
2616 if Search(r'\belse [^\s{]', line) and not Search(r'\belse if\b', line): | 3007 if Search(r'\belse [^\s{]', line) and not Search(r'\belse if\b', line): |
2617 error(filename, linenum, 'whitespace/newline', 4, | 3008 error(filename, linenum, 'whitespace/newline', 4, |
2618 'Else clause should never be on same line as else (use 2 lines)') | 3009 'Else clause should never be on same line as else (use 2 lines)') |
2619 | 3010 |
2620 # In the same way, a do/while should never be on one line | 3011 # In the same way, a do/while should never be on one line |
2621 if Match(r'\s*do [^\s{]', line): | 3012 if Match(r'\s*do [^\s{]', line): |
2622 error(filename, linenum, 'whitespace/newline', 4, | 3013 error(filename, linenum, 'whitespace/newline', 4, |
2623 'do/while clauses should not be on a single line') | 3014 'do/while clauses should not be on a single line') |
2624 | 3015 |
2625 # Braces shouldn't be followed by a ; unless they're defining a struct | 3016 # Block bodies should not be followed by a semicolon. Due to C++11 |
2626 # or initializing an array. | 3017 # brace initialization, there are more places where semicolons are |
2627 # We can't tell in general, but we can for some common cases. | 3018 # required than not, so we use a whitelist approach to check these |
2628 prevlinenum = linenum | 3019 # rather than a blacklist. These are the places where "};" should |
2629 while True: | 3020 # be replaced by just "}": |
2630 (prevline, prevlinenum) = GetPreviousNonBlankLine(clean_lines, prevlinenum) | 3021 # 1. Some flavor of block following closing parenthesis: |
2631 if Match(r'\s+{.*}\s*;', line) and not prevline.count(';'): | 3022 # for (;;) {}; |
2632 line = prevline + line | 3023 # while (...) {}; |
2633 else: | 3024 # switch (...) {}; |
2634 break | 3025 # Function(...) {}; |
2635 if (Search(r'{.*}\s*;', line) and | 3026 # if (...) {}; |
2636 line.count('{') == line.count('}') and | 3027 # if (...) else if (...) {}; |
2637 not Search(r'struct|class|enum|\s*=\s*{', line)): | 3028 # |
2638 error(filename, linenum, 'readability/braces', 4, | 3029 # 2. else block: |
2639 "You don't need a ; after a }") | 3030 # if (...) else {}; |
| 3031 # |
| 3032 # 3. const member function: |
| 3033 # Function(...) const {}; |
| 3034 # |
| 3035 # 4. Block following some statement: |
| 3036 # x = 42; |
| 3037 # {}; |
| 3038 # |
| 3039 # 5. Block at the beginning of a function: |
| 3040 # Function(...) { |
| 3041 # {}; |
| 3042 # } |
| 3043 # |
| 3044 # Note that naively checking for the preceding "{" will also match |
| 3045 # braces inside multi-dimensional arrays, but this is fine since |
| 3046 # that expression will not contain semicolons. |
| 3047 # |
| 3048 # 6. Block following another block: |
| 3049 # while (true) {} |
| 3050 # {}; |
| 3051 # |
| 3052 # 7. End of namespaces: |
| 3053 # namespace {}; |
| 3054 # |
| 3055 # These semicolons seems far more common than other kinds of |
| 3056 # redundant semicolons, possibly due to people converting classes |
| 3057 # to namespaces. For now we do not warn for this case. |
| 3058 # |
| 3059 # Try matching case 1 first. |
| 3060 match = Match(r'^(.*\)\s*)\{', line) |
| 3061 if match: |
| 3062 # Matched closing parenthesis (case 1). Check the token before the |
| 3063 # matching opening parenthesis, and don't warn if it looks like a |
| 3064 # macro. This avoids these false positives: |
| 3065 # - macro that defines a base class |
| 3066 # - multi-line macro that defines a base class |
| 3067 # - macro that defines the whole class-head |
| 3068 # |
| 3069 # But we still issue warnings for macros that we know are safe to |
| 3070 # warn, specifically: |
| 3071 # - TEST, TEST_F, TEST_P, MATCHER, MATCHER_P |
| 3072 # - TYPED_TEST |
| 3073 # - INTERFACE_DEF |
| 3074 # - EXCLUSIVE_LOCKS_REQUIRED, SHARED_LOCKS_REQUIRED, LOCKS_EXCLUDED: |
| 3075 # |
| 3076 # We implement a whitelist of safe macros instead of a blacklist of |
| 3077 # unsafe macros, even though the latter appears less frequently in |
| 3078 # google code and would have been easier to implement. This is because |
| 3079 # the downside for getting the whitelist wrong means some extra |
| 3080 # semicolons, while the downside for getting the blacklist wrong |
| 3081 # would result in compile errors. |
| 3082 # |
| 3083 # In addition to macros, we also don't want to warn on compound |
| 3084 # literals. |
| 3085 closing_brace_pos = match.group(1).rfind(')') |
| 3086 opening_parenthesis = ReverseCloseExpression( |
| 3087 clean_lines, linenum, closing_brace_pos) |
| 3088 if opening_parenthesis[2] > -1: |
| 3089 line_prefix = opening_parenthesis[0][0:opening_parenthesis[2]] |
| 3090 macro = Search(r'\b([A-Z_]+)\s*$', line_prefix) |
| 3091 if ((macro and |
| 3092 macro.group(1) not in ( |
| 3093 'TEST', 'TEST_F', 'MATCHER', 'MATCHER_P', 'TYPED_TEST', |
| 3094 'EXCLUSIVE_LOCKS_REQUIRED', 'SHARED_LOCKS_REQUIRED', |
| 3095 'LOCKS_EXCLUDED', 'INTERFACE_DEF')) or |
| 3096 Search(r'\s+=\s*$', line_prefix)): |
| 3097 match = None |
| 3098 |
| 3099 else: |
| 3100 # Try matching cases 2-3. |
| 3101 match = Match(r'^(.*(?:else|\)\s*const)\s*)\{', line) |
| 3102 if not match: |
| 3103 # Try matching cases 4-6. These are always matched on separate lines. |
| 3104 # |
| 3105 # Note that we can't simply concatenate the previous line to the |
| 3106 # current line and do a single match, otherwise we may output |
| 3107 # duplicate warnings for the blank line case: |
| 3108 # if (cond) { |
| 3109 # // blank line |
| 3110 # } |
| 3111 prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0] |
| 3112 if prevline and Search(r'[;{}]\s*$', prevline): |
| 3113 match = Match(r'^(\s*)\{', line) |
| 3114 |
| 3115 # Check matching closing brace |
| 3116 if match: |
| 3117 (endline, endlinenum, endpos) = CloseExpression( |
| 3118 clean_lines, linenum, len(match.group(1))) |
| 3119 if endpos > -1 and Match(r'^\s*;', endline[endpos:]): |
| 3120 # Current {} pair is eligible for semicolon check, and we have found |
| 3121 # the redundant semicolon, output warning here. |
| 3122 # |
| 3123 # Note: because we are scanning forward for opening braces, and |
| 3124 # outputting warnings for the matching closing brace, if there are |
| 3125 # nested blocks with trailing semicolons, we will get the error |
| 3126 # messages in reversed order. |
| 3127 error(filename, endlinenum, 'readability/braces', 4, |
| 3128 "You don't need a ; after a }") |
2640 | 3129 |
2641 | 3130 |
2642 def CheckEmptyLoopBody(filename, clean_lines, linenum, error): | 3131 def CheckEmptyBlockBody(filename, clean_lines, linenum, error): |
2643 """Loop for empty loop body with only a single semicolon. | 3132 """Look for empty loop/conditional body with only a single semicolon. |
2644 | 3133 |
2645 Args: | 3134 Args: |
2646 filename: The name of the current file. | 3135 filename: The name of the current file. |
2647 clean_lines: A CleansedLines instance containing the file. | 3136 clean_lines: A CleansedLines instance containing the file. |
2648 linenum: The number of the line to check. | 3137 linenum: The number of the line to check. |
2649 error: The function to call with any errors found. | 3138 error: The function to call with any errors found. |
2650 """ | 3139 """ |
2651 | 3140 |
2652 # Search for loop keywords at the beginning of the line. Because only | 3141 # Search for loop keywords at the beginning of the line. Because only |
2653 # whitespaces are allowed before the keywords, this will also ignore most | 3142 # whitespaces are allowed before the keywords, this will also ignore most |
2654 # do-while-loops, since those lines should start with closing brace. | 3143 # do-while-loops, since those lines should start with closing brace. |
| 3144 # |
| 3145 # We also check "if" blocks here, since an empty conditional block |
| 3146 # is likely an error. |
2655 line = clean_lines.elided[linenum] | 3147 line = clean_lines.elided[linenum] |
2656 if Match(r'\s*(for|while)\s*\(', line): | 3148 matched = Match(r'\s*(for|while|if)\s*\(', line) |
| 3149 if matched: |
2657 # Find the end of the conditional expression | 3150 # Find the end of the conditional expression |
2658 (end_line, end_linenum, end_pos) = CloseExpression( | 3151 (end_line, end_linenum, end_pos) = CloseExpression( |
2659 clean_lines, linenum, line.find('(')) | 3152 clean_lines, linenum, line.find('(')) |
2660 | 3153 |
2661 # Output warning if what follows the condition expression is a semicolon. | 3154 # Output warning if what follows the condition expression is a semicolon. |
2662 # No warning for all other cases, including whitespace or newline, since we | 3155 # No warning for all other cases, including whitespace or newline, since we |
2663 # have a separate check for semicolons preceded by whitespace. | 3156 # have a separate check for semicolons preceded by whitespace. |
2664 if end_pos >= 0 and Match(r';', end_line[end_pos:]): | 3157 if end_pos >= 0 and Match(r';', end_line[end_pos:]): |
2665 error(filename, end_linenum, 'whitespace/empty_loop_body', 5, | 3158 if matched.group(1) == 'if': |
2666 'Empty loop bodies should use {} or continue') | 3159 error(filename, end_linenum, 'whitespace/empty_conditional_body', 5, |
2667 | 3160 'Empty conditional bodies should use {}') |
2668 | 3161 else: |
2669 def ReplaceableCheck(operator, macro, line): | 3162 error(filename, end_linenum, 'whitespace/empty_loop_body', 5, |
2670 """Determine whether a basic CHECK can be replaced with a more specific one. | 3163 'Empty loop bodies should use {} or continue') |
2671 | |
2672 For example suggest using CHECK_EQ instead of CHECK(a == b) and | |
2673 similarly for CHECK_GE, CHECK_GT, CHECK_LE, CHECK_LT, CHECK_NE. | |
2674 | |
2675 Args: | |
2676 operator: The C++ operator used in the CHECK. | |
2677 macro: The CHECK or EXPECT macro being called. | |
2678 line: The current source line. | |
2679 | |
2680 Returns: | |
2681 True if the CHECK can be replaced with a more specific one. | |
2682 """ | |
2683 | |
2684 # This matches decimal and hex integers, strings, and chars (in that order). | |
2685 match_constant = r'([-+]?(\d+|0[xX][0-9a-fA-F]+)[lLuU]{0,3}|".*"|\'.*\')' | |
2686 | |
2687 # Expression to match two sides of the operator with something that | |
2688 # looks like a literal, since CHECK(x == iterator) won't compile. | |
2689 # This means we can't catch all the cases where a more specific | |
2690 # CHECK is possible, but it's less annoying than dealing with | |
2691 # extraneous warnings. | |
2692 match_this = (r'\s*' + macro + r'\((\s*' + | |
2693 match_constant + r'\s*' + operator + r'[^<>].*|' | |
2694 r'.*[^<>]' + operator + r'\s*' + match_constant + | |
2695 r'\s*\))') | |
2696 | |
2697 # Don't complain about CHECK(x == NULL) or similar because | |
2698 # CHECK_EQ(x, NULL) won't compile (requires a cast). | |
2699 # Also, don't complain about more complex boolean expressions | |
2700 # involving && or || such as CHECK(a == b || c == d). | |
2701 return Match(match_this, line) and not Search(r'NULL|&&|\|\|', line) | |
2702 | 3164 |
2703 | 3165 |
2704 def CheckCheck(filename, clean_lines, linenum, error): | 3166 def CheckCheck(filename, clean_lines, linenum, error): |
2705 """Checks the use of CHECK and EXPECT macros. | 3167 """Checks the use of CHECK and EXPECT macros. |
2706 | 3168 |
2707 Args: | 3169 Args: |
2708 filename: The name of the current file. | 3170 filename: The name of the current file. |
2709 clean_lines: A CleansedLines instance containing the file. | 3171 clean_lines: A CleansedLines instance containing the file. |
2710 linenum: The number of the line to check. | 3172 linenum: The number of the line to check. |
2711 error: The function to call with any errors found. | 3173 error: The function to call with any errors found. |
2712 """ | 3174 """ |
2713 | 3175 |
2714 # Decide the set of replacement macros that should be suggested | 3176 # Decide the set of replacement macros that should be suggested |
2715 raw_lines = clean_lines.raw_lines | 3177 lines = clean_lines.elided |
2716 current_macro = '' | 3178 check_macro = None |
| 3179 start_pos = -1 |
2717 for macro in _CHECK_MACROS: | 3180 for macro in _CHECK_MACROS: |
2718 if raw_lines[linenum].find(macro) >= 0: | 3181 i = lines[linenum].find(macro) |
2719 current_macro = macro | 3182 if i >= 0: |
| 3183 check_macro = macro |
| 3184 |
| 3185 # Find opening parenthesis. Do a regular expression match here |
| 3186 # to make sure that we are matching the expected CHECK macro, as |
| 3187 # opposed to some other macro that happens to contain the CHECK |
| 3188 # substring. |
| 3189 matched = Match(r'^(.*\b' + check_macro + r'\s*)\(', lines[linenum]) |
| 3190 if not matched: |
| 3191 continue |
| 3192 start_pos = len(matched.group(1)) |
2720 break | 3193 break |
2721 if not current_macro: | 3194 if not check_macro or start_pos < 0: |
2722 # Don't waste time here if line doesn't contain 'CHECK' or 'EXPECT' | 3195 # Don't waste time here if line doesn't contain 'CHECK' or 'EXPECT' |
2723 return | 3196 return |
2724 | 3197 |
2725 line = clean_lines.elided[linenum] # get rid of comments and strings | 3198 # Find end of the boolean expression by matching parentheses |
| 3199 (last_line, end_line, end_pos) = CloseExpression( |
| 3200 clean_lines, linenum, start_pos) |
| 3201 if end_pos < 0: |
| 3202 return |
| 3203 if linenum == end_line: |
| 3204 expression = lines[linenum][start_pos + 1:end_pos - 1] |
| 3205 else: |
| 3206 expression = lines[linenum][start_pos + 1:] |
| 3207 for i in xrange(linenum + 1, end_line): |
| 3208 expression += lines[i] |
| 3209 expression += last_line[0:end_pos - 1] |
2726 | 3210 |
2727 # Encourage replacing plain CHECKs with CHECK_EQ/CHECK_NE/etc. | 3211 # Parse expression so that we can take parentheses into account. |
2728 for operator in ['==', '!=', '>=', '>', '<=', '<']: | 3212 # This avoids false positives for inputs like "CHECK((a < 4) == b)", |
2729 if ReplaceableCheck(operator, current_macro, line): | 3213 # which is not replaceable by CHECK_LE. |
2730 error(filename, linenum, 'readability/check', 2, | 3214 lhs = '' |
2731 'Consider using %s instead of %s(a %s b)' % ( | 3215 rhs = '' |
2732 _CHECK_REPLACEMENT[current_macro][operator], | 3216 operator = None |
2733 current_macro, operator)) | 3217 while expression: |
2734 break | 3218 matched = Match(r'^\s*(<<|<<=|>>|>>=|->\*|->|&&|\|\||' |
| 3219 r'==|!=|>=|>|<=|<|\()(.*)$', expression) |
| 3220 if matched: |
| 3221 token = matched.group(1) |
| 3222 if token == '(': |
| 3223 # Parenthesized operand |
| 3224 expression = matched.group(2) |
| 3225 (end, _) = FindEndOfExpressionInLine(expression, 0, 1, '(', ')') |
| 3226 if end < 0: |
| 3227 return # Unmatched parenthesis |
| 3228 lhs += '(' + expression[0:end] |
| 3229 expression = expression[end:] |
| 3230 elif token in ('&&', '||'): |
| 3231 # Logical and/or operators. This means the expression |
| 3232 # contains more than one term, for example: |
| 3233 # CHECK(42 < a && a < b); |
| 3234 # |
| 3235 # These are not replaceable with CHECK_LE, so bail out early. |
| 3236 return |
| 3237 elif token in ('<<', '<<=', '>>', '>>=', '->*', '->'): |
| 3238 # Non-relational operator |
| 3239 lhs += token |
| 3240 expression = matched.group(2) |
| 3241 else: |
| 3242 # Relational operator |
| 3243 operator = token |
| 3244 rhs = matched.group(2) |
| 3245 break |
| 3246 else: |
| 3247 # Unparenthesized operand. Instead of appending to lhs one character |
| 3248 # at a time, we do another regular expression match to consume several |
| 3249 # characters at once if possible. Trivial benchmark shows that this |
| 3250 # is more efficient when the operands are longer than a single |
| 3251 # character, which is generally the case. |
| 3252 matched = Match(r'^([^-=!<>()&|]+)(.*)$', expression) |
| 3253 if not matched: |
| 3254 matched = Match(r'^(\s*\S)(.*)$', expression) |
| 3255 if not matched: |
| 3256 break |
| 3257 lhs += matched.group(1) |
| 3258 expression = matched.group(2) |
| 3259 |
| 3260 # Only apply checks if we got all parts of the boolean expression |
| 3261 if not (lhs and operator and rhs): |
| 3262 return |
| 3263 |
| 3264 # Check that rhs do not contain logical operators. We already know |
| 3265 # that lhs is fine since the loop above parses out && and ||. |
| 3266 if rhs.find('&&') > -1 or rhs.find('||') > -1: |
| 3267 return |
| 3268 |
| 3269 # At least one of the operands must be a constant literal. This is |
| 3270 # to avoid suggesting replacements for unprintable things like |
| 3271 # CHECK(variable != iterator) |
| 3272 # |
| 3273 # The following pattern matches decimal, hex integers, strings, and |
| 3274 # characters (in that order). |
| 3275 lhs = lhs.strip() |
| 3276 rhs = rhs.strip() |
| 3277 match_constant = r'^([-+]?(\d+|0[xX][0-9a-fA-F]+)[lLuU]{0,3}|".*"|\'.*\')$' |
| 3278 if Match(match_constant, lhs) or Match(match_constant, rhs): |
| 3279 # Note: since we know both lhs and rhs, we can provide a more |
| 3280 # descriptive error message like: |
| 3281 # Consider using CHECK_EQ(x, 42) instead of CHECK(x == 42) |
| 3282 # Instead of: |
| 3283 # Consider using CHECK_EQ instead of CHECK(a == b) |
| 3284 # |
| 3285 # We are still keeping the less descriptive message because if lhs |
| 3286 # or rhs gets long, the error message might become unreadable. |
| 3287 error(filename, linenum, 'readability/check', 2, |
| 3288 'Consider using %s instead of %s(a %s b)' % ( |
| 3289 _CHECK_REPLACEMENT[check_macro][operator], |
| 3290 check_macro, operator)) |
2735 | 3291 |
2736 | 3292 |
2737 def CheckAltTokens(filename, clean_lines, linenum, error): | 3293 def CheckAltTokens(filename, clean_lines, linenum, error): |
2738 """Check alternative keywords being used in boolean expressions. | 3294 """Check alternative keywords being used in boolean expressions. |
2739 | 3295 |
2740 Args: | 3296 Args: |
2741 filename: The name of the current file. | 3297 filename: The name of the current file. |
2742 clean_lines: A CleansedLines instance containing the file. | 3298 clean_lines: A CleansedLines instance containing the file. |
2743 linenum: The number of the line to check. | 3299 linenum: The number of the line to check. |
2744 error: The function to call with any errors found. | 3300 error: The function to call with any errors found. |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2799 Args: | 3355 Args: |
2800 filename: The name of the current file. | 3356 filename: The name of the current file. |
2801 clean_lines: A CleansedLines instance containing the file. | 3357 clean_lines: A CleansedLines instance containing the file. |
2802 linenum: The number of the line to check. | 3358 linenum: The number of the line to check. |
2803 file_extension: The extension (without the dot) of the filename. | 3359 file_extension: The extension (without the dot) of the filename. |
2804 nesting_state: A _NestingState instance which maintains information about | 3360 nesting_state: A _NestingState instance which maintains information about |
2805 the current stack of nested blocks being parsed. | 3361 the current stack of nested blocks being parsed. |
2806 error: The function to call with any errors found. | 3362 error: The function to call with any errors found. |
2807 """ | 3363 """ |
2808 | 3364 |
2809 raw_lines = clean_lines.raw_lines | 3365 # Don't use "elided" lines here, otherwise we can't check commented lines. |
| 3366 # Don't want to use "raw" either, because we don't want to check inside C++11 |
| 3367 # raw strings, |
| 3368 raw_lines = clean_lines.lines_without_raw_strings |
2810 line = raw_lines[linenum] | 3369 line = raw_lines[linenum] |
2811 | 3370 |
2812 if line.find('\t') != -1: | 3371 if line.find('\t') != -1: |
2813 error(filename, linenum, 'whitespace/tab', 1, | 3372 error(filename, linenum, 'whitespace/tab', 1, |
2814 'Tab found; better to use spaces') | 3373 'Tab found; better to use spaces') |
2815 | 3374 |
2816 # One or three blank spaces at the beginning of the line is weird; it's | 3375 # One or three blank spaces at the beginning of the line is weird; it's |
2817 # hard to reconcile that with 2-space indents. | 3376 # hard to reconcile that with 2-space indents. |
2818 # NOTE: here are the conditions rob pike used for his tests. Mine aren't | 3377 # NOTE: here are the conditions rob pike used for his tests. Mine aren't |
2819 # as sophisticated, but it may be worth becoming so: RLENGTH==initial_spaces | 3378 # as sophisticated, but it may be worth becoming so: RLENGTH==initial_spaces |
2820 # if(RLENGTH > 20) complain = 0; | 3379 # if(RLENGTH > 20) complain = 0; |
2821 # if(match($0, " +(error|private|public|protected):")) complain = 0; | 3380 # if(match($0, " +(error|private|public|protected):")) complain = 0; |
2822 # if(match(prev, "&& *$")) complain = 0; | 3381 # if(match(prev, "&& *$")) complain = 0; |
2823 # if(match(prev, "\\|\\| *$")) complain = 0; | 3382 # if(match(prev, "\\|\\| *$")) complain = 0; |
2824 # if(match(prev, "[\",=><] *$")) complain = 0; | 3383 # if(match(prev, "[\",=><] *$")) complain = 0; |
2825 # if(match($0, " <<")) complain = 0; | 3384 # if(match($0, " <<")) complain = 0; |
2826 # if(match(prev, " +for \\(")) complain = 0; | 3385 # if(match(prev, " +for \\(")) complain = 0; |
2827 # if(prevodd && match(prevprev, " +for \\(")) complain = 0; | 3386 # if(prevodd && match(prevprev, " +for \\(")) complain = 0; |
2828 initial_spaces = 0 | 3387 initial_spaces = 0 |
2829 cleansed_line = clean_lines.elided[linenum] | 3388 cleansed_line = clean_lines.elided[linenum] |
2830 while initial_spaces < len(line) and line[initial_spaces] == ' ': | 3389 while initial_spaces < len(line) and line[initial_spaces] == ' ': |
2831 initial_spaces += 1 | 3390 initial_spaces += 1 |
2832 if line and line[-1].isspace(): | 3391 if line and line[-1].isspace(): |
2833 error(filename, linenum, 'whitespace/end_of_line', 4, | 3392 error(filename, linenum, 'whitespace/end_of_line', 4, |
2834 'Line ends in whitespace. Consider deleting these extra spaces.') | 3393 'Line ends in whitespace. Consider deleting these extra spaces.') |
2835 # There are certain situations we allow one space, notably for labels | 3394 # There are certain situations we allow one space, notably for section labels |
2836 elif ((initial_spaces == 1 or initial_spaces == 3) and | 3395 elif ((initial_spaces == 1 or initial_spaces == 3) and |
2837 not Match(r'\s*\w+\s*:\s*$', cleansed_line)): | 3396 not Match(r'\s*\w+\s*:\s*$', cleansed_line)): |
2838 error(filename, linenum, 'whitespace/indent', 3, | 3397 error(filename, linenum, 'whitespace/indent', 3, |
2839 'Weird number of spaces at line-start. ' | 3398 'Weird number of spaces at line-start. ' |
2840 'Are you using a 2-space indent?') | 3399 'Are you using a 2-space indent?') |
2841 # Labels should always be indented at least one space. | |
2842 elif not initial_spaces and line[:2] != '//' and Search(r'[^:]:\s*$', | |
2843 line): | |
2844 error(filename, linenum, 'whitespace/labels', 4, | |
2845 'Labels should always be indented at least one space. ' | |
2846 'If this is a member-initializer list in a constructor or ' | |
2847 'the base class list in a class definition, the colon should ' | |
2848 'be on the following line.') | |
2849 | |
2850 | 3400 |
2851 # Check if the line is a header guard. | 3401 # Check if the line is a header guard. |
2852 is_header_guard = False | 3402 is_header_guard = False |
2853 if file_extension == 'h': | 3403 if file_extension == 'h': |
2854 cppvar = GetHeaderGuardCPPVariable(filename) | 3404 cppvar = GetHeaderGuardCPPVariable(filename) |
2855 if (line.startswith('#ifndef %s' % cppvar) or | 3405 if (line.startswith('#ifndef %s' % cppvar) or |
2856 line.startswith('#define %s' % cppvar) or | 3406 line.startswith('#define %s' % cppvar) or |
2857 line.startswith('#endif // %s' % cppvar)): | 3407 line.startswith('#endif // %s' % cppvar)): |
2858 is_header_guard = True | 3408 is_header_guard = True |
2859 # #include lines and header guards can be long, since there's no clean way to | 3409 # #include lines and header guards can be long, since there's no clean way to |
2860 # split them. | 3410 # split them. |
2861 # | 3411 # |
2862 # URLs can be long too. It's possible to split these, but it makes them | 3412 # URLs can be long too. It's possible to split these, but it makes them |
2863 # harder to cut&paste. | 3413 # harder to cut&paste. |
2864 # | 3414 # |
2865 # The "$Id:...$" comment may also get very long without it being the | 3415 # The "$Id:...$" comment may also get very long without it being the |
2866 # developers fault. | 3416 # developers fault. |
2867 if (not line.startswith('#include') and not is_header_guard and | 3417 if (not line.startswith('#include') and not is_header_guard and |
2868 not Match(r'^\s*//.*http(s?)://\S*$', line) and | 3418 not Match(r'^\s*//.*http(s?)://\S*$', line) and |
2869 not Match(r'^// \$Id:.*#[0-9]+ \$$', line)): | 3419 not Match(r'^// \$Id:.*#[0-9]+ \$$', line)): |
2870 line_width = GetLineWidth(line) | 3420 line_width = GetLineWidth(line) |
2871 if line_width > 100: | 3421 extended_length = int((_line_length * 1.25)) |
| 3422 if line_width > extended_length: |
2872 error(filename, linenum, 'whitespace/line_length', 4, | 3423 error(filename, linenum, 'whitespace/line_length', 4, |
2873 'Lines should very rarely be longer than 100 characters') | 3424 'Lines should very rarely be longer than %i characters' % |
2874 elif line_width > 80: | 3425 extended_length) |
| 3426 elif line_width > _line_length: |
2875 error(filename, linenum, 'whitespace/line_length', 2, | 3427 error(filename, linenum, 'whitespace/line_length', 2, |
2876 'Lines should be <= 80 characters long') | 3428 'Lines should be <= %i characters long' % _line_length) |
2877 | 3429 |
2878 if (cleansed_line.count(';') > 1 and | 3430 if (cleansed_line.count(';') > 1 and |
2879 # for loops are allowed two ;'s (and may run over two lines). | 3431 # for loops are allowed two ;'s (and may run over two lines). |
2880 cleansed_line.find('for') == -1 and | 3432 cleansed_line.find('for') == -1 and |
2881 (GetPreviousNonBlankLine(clean_lines, linenum)[0].find('for') == -1 or | 3433 (GetPreviousNonBlankLine(clean_lines, linenum)[0].find('for') == -1 or |
2882 GetPreviousNonBlankLine(clean_lines, linenum)[0].find(';') != -1) and | 3434 GetPreviousNonBlankLine(clean_lines, linenum)[0].find(';') != -1) and |
2883 # It's ok to have many commands in a switch case that fits in 1 line | 3435 # It's ok to have many commands in a switch case that fits in 1 line |
2884 not ((cleansed_line.find('case ') != -1 or | 3436 not ((cleansed_line.find('case ') != -1 or |
2885 cleansed_line.find('default:') != -1) and | 3437 cleansed_line.find('default:') != -1) and |
2886 cleansed_line.find('break;') != -1)): | 3438 cleansed_line.find('break;') != -1)): |
2887 error(filename, linenum, 'whitespace/newline', 0, | 3439 error(filename, linenum, 'whitespace/newline', 0, |
2888 'More than one command on the same line') | 3440 'More than one command on the same line') |
2889 | 3441 |
2890 # Some more style checks | 3442 # Some more style checks |
2891 CheckBraces(filename, clean_lines, linenum, error) | 3443 CheckBraces(filename, clean_lines, linenum, error) |
2892 CheckEmptyLoopBody(filename, clean_lines, linenum, error) | 3444 CheckEmptyBlockBody(filename, clean_lines, linenum, error) |
2893 CheckAccess(filename, clean_lines, linenum, nesting_state, error) | 3445 CheckAccess(filename, clean_lines, linenum, nesting_state, error) |
2894 CheckSpacing(filename, clean_lines, linenum, nesting_state, error) | 3446 CheckSpacing(filename, clean_lines, linenum, nesting_state, error) |
2895 CheckCheck(filename, clean_lines, linenum, error) | 3447 CheckCheck(filename, clean_lines, linenum, error) |
2896 CheckAltTokens(filename, clean_lines, linenum, error) | 3448 CheckAltTokens(filename, clean_lines, linenum, error) |
2897 classinfo = nesting_state.InnermostClass() | 3449 classinfo = nesting_state.InnermostClass() |
2898 if classinfo: | 3450 if classinfo: |
2899 CheckSectionSpacing(filename, clean_lines, classinfo, linenum, error) | 3451 CheckSectionSpacing(filename, clean_lines, classinfo, linenum, error) |
2900 | 3452 |
2901 | 3453 |
2902 _RE_PATTERN_INCLUDE_NEW_STYLE = re.compile(r'#include +"[^/]+\.h"') | 3454 _RE_PATTERN_INCLUDE_NEW_STYLE = re.compile(r'#include +"[^/]+\.h"') |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2972 >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'foo/foo.h', False) | 3524 >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'foo/foo.h', False) |
2973 _LIKELY_MY_HEADER | 3525 _LIKELY_MY_HEADER |
2974 >>> _ClassifyInclude(FileInfo('foo/foo_unknown_extension.cc'), | 3526 >>> _ClassifyInclude(FileInfo('foo/foo_unknown_extension.cc'), |
2975 ... 'bar/foo_other_ext.h', False) | 3527 ... 'bar/foo_other_ext.h', False) |
2976 _POSSIBLE_MY_HEADER | 3528 _POSSIBLE_MY_HEADER |
2977 >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'foo/bar.h', False) | 3529 >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'foo/bar.h', False) |
2978 _OTHER_HEADER | 3530 _OTHER_HEADER |
2979 """ | 3531 """ |
2980 # This is a list of all standard c++ header files, except | 3532 # This is a list of all standard c++ header files, except |
2981 # those already checked for above. | 3533 # those already checked for above. |
2982 is_stl_h = include in _STL_HEADERS | 3534 is_cpp_h = include in _CPP_HEADERS |
2983 is_cpp_h = is_stl_h or include in _CPP_HEADERS | |
2984 | 3535 |
2985 if is_system: | 3536 if is_system: |
2986 if is_cpp_h: | 3537 if is_cpp_h: |
2987 return _CPP_SYS_HEADER | 3538 return _CPP_SYS_HEADER |
2988 else: | 3539 else: |
2989 return _C_SYS_HEADER | 3540 return _C_SYS_HEADER |
2990 | 3541 |
2991 # If the target file and the include we're checking share a | 3542 # If the target file and the include we're checking share a |
2992 # basename when we drop common extensions, and the include | 3543 # basename when we drop common extensions, and the include |
2993 # lives in . , then it's likely to be owned by the target file. | 3544 # lives in . , then it's likely to be owned by the target file. |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3061 # We classify each include statement as one of those 5 types | 3612 # We classify each include statement as one of those 5 types |
3062 # using a number of techniques. The include_state object keeps | 3613 # using a number of techniques. The include_state object keeps |
3063 # track of the highest type seen, and complains if we see a | 3614 # track of the highest type seen, and complains if we see a |
3064 # lower type after that. | 3615 # lower type after that. |
3065 error_message = include_state.CheckNextIncludeOrder( | 3616 error_message = include_state.CheckNextIncludeOrder( |
3066 _ClassifyInclude(fileinfo, include, is_system)) | 3617 _ClassifyInclude(fileinfo, include, is_system)) |
3067 if error_message: | 3618 if error_message: |
3068 error(filename, linenum, 'build/include_order', 4, | 3619 error(filename, linenum, 'build/include_order', 4, |
3069 '%s. Should be: %s.h, c system, c++ system, other.' % | 3620 '%s. Should be: %s.h, c system, c++ system, other.' % |
3070 (error_message, fileinfo.BaseName())) | 3621 (error_message, fileinfo.BaseName())) |
3071 if not include_state.IsInAlphabeticalOrder(include): | 3622 canonical_include = include_state.CanonicalizeAlphabeticalOrder(include) |
| 3623 if not include_state.IsInAlphabeticalOrder( |
| 3624 clean_lines, linenum, canonical_include): |
3072 error(filename, linenum, 'build/include_alpha', 4, | 3625 error(filename, linenum, 'build/include_alpha', 4, |
3073 'Include "%s" not in alphabetical order' % include) | 3626 'Include "%s" not in alphabetical order' % include) |
| 3627 include_state.SetLastHeader(canonical_include) |
3074 | 3628 |
3075 # Look for any of the stream classes that are part of standard C++. | 3629 # Look for any of the stream classes that are part of standard C++. |
3076 match = _RE_PATTERN_INCLUDE.match(line) | 3630 match = _RE_PATTERN_INCLUDE.match(line) |
3077 if match: | 3631 if match: |
3078 include = match.group(2) | 3632 include = match.group(2) |
3079 if Match(r'(f|ind|io|i|o|parse|pf|stdio|str|)?stream$', include): | 3633 if Match(r'(f|ind|io|i|o|parse|pf|stdio|str|)?stream$', include): |
3080 # Many unit tests use cout, so we exempt them. | 3634 # Many unit tests use cout, so we exempt them. |
3081 if not _IsTestFilename(filename): | 3635 if not _IsTestFilename(filename): |
3082 error(filename, linenum, 'readability/streams', 3, | 3636 error(filename, linenum, 'readability/streams', 3, |
3083 'Streams are highly discouraged.') | 3637 'Streams are highly discouraged.') |
3084 | 3638 |
3085 | 3639 |
3086 def _GetTextInside(text, start_pattern): | 3640 def _GetTextInside(text, start_pattern): |
3087 """Retrieves all the text between matching open and close parentheses. | 3641 r"""Retrieves all the text between matching open and close parentheses. |
3088 | 3642 |
3089 Given a string of lines and a regular expression string, retrieve all the text | 3643 Given a string of lines and a regular expression string, retrieve all the text |
3090 following the expression and between opening punctuation symbols like | 3644 following the expression and between opening punctuation symbols like |
3091 (, [, or {, and the matching close-punctuation symbol. This properly nested | 3645 (, [, or {, and the matching close-punctuation symbol. This properly nested |
3092 occurrences of the punctuations, so for the text like | 3646 occurrences of the punctuations, so for the text like |
3093 printf(a(), b(c())); | 3647 printf(a(), b(c())); |
3094 a call to _GetTextInside(text, r'printf\(') will return 'a(), b(c())'. | 3648 a call to _GetTextInside(text, r'printf\(') will return 'a(), b(c())'. |
3095 start_pattern must match string having an open punctuation symbol at the end. | 3649 start_pattern must match string having an open punctuation symbol at the end. |
3096 | 3650 |
3097 Args: | 3651 Args: |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3132 elif text[position] in matching_punctuation: | 3686 elif text[position] in matching_punctuation: |
3133 punctuation_stack.append(matching_punctuation[text[position]]) | 3687 punctuation_stack.append(matching_punctuation[text[position]]) |
3134 position += 1 | 3688 position += 1 |
3135 if punctuation_stack: | 3689 if punctuation_stack: |
3136 # Opening punctuations left without matching close-punctuations. | 3690 # Opening punctuations left without matching close-punctuations. |
3137 return None | 3691 return None |
3138 # punctuations match. | 3692 # punctuations match. |
3139 return text[start_position:position - 1] | 3693 return text[start_position:position - 1] |
3140 | 3694 |
3141 | 3695 |
3142 def CheckLanguage(filename, clean_lines, linenum, file_extension, include_state, | 3696 # Patterns for matching call-by-reference parameters. |
3143 error): | 3697 # |
| 3698 # Supports nested templates up to 2 levels deep using this messy pattern: |
| 3699 # < (?: < (?: < [^<>]* |
| 3700 # > |
| 3701 # | [^<>] )* |
| 3702 # > |
| 3703 # | [^<>] )* |
| 3704 # > |
| 3705 _RE_PATTERN_IDENT = r'[_a-zA-Z]\w*' # =~ [[:alpha:]][[:alnum:]]* |
| 3706 _RE_PATTERN_TYPE = ( |
| 3707 r'(?:const\s+)?(?:typename\s+|class\s+|struct\s+|union\s+|enum\s+)?' |
| 3708 r'(?:\w|' |
| 3709 r'\s*<(?:<(?:<[^<>]*>|[^<>])*>|[^<>])*>|' |
| 3710 r'::)+') |
| 3711 # A call-by-reference parameter ends with '& identifier'. |
| 3712 _RE_PATTERN_REF_PARAM = re.compile( |
| 3713 r'(' + _RE_PATTERN_TYPE + r'(?:\s*(?:\bconst\b|[*]))*\s*' |
| 3714 r'&\s*' + _RE_PATTERN_IDENT + r')\s*(?:=[^,()]+)?[,)]') |
| 3715 # A call-by-const-reference parameter either ends with 'const& identifier' |
| 3716 # or looks like 'const type& identifier' when 'type' is atomic. |
| 3717 _RE_PATTERN_CONST_REF_PARAM = ( |
| 3718 r'(?:.*\s*\bconst\s*&\s*' + _RE_PATTERN_IDENT + |
| 3719 r'|const\s+' + _RE_PATTERN_TYPE + r'\s*&\s*' + _RE_PATTERN_IDENT + r')') |
| 3720 |
| 3721 |
| 3722 def CheckLanguage(filename, clean_lines, linenum, file_extension, |
| 3723 include_state, nesting_state, error): |
3144 """Checks rules from the 'C++ language rules' section of cppguide.html. | 3724 """Checks rules from the 'C++ language rules' section of cppguide.html. |
3145 | 3725 |
3146 Some of these rules are hard to test (function overloading, using | 3726 Some of these rules are hard to test (function overloading, using |
3147 uint32 inappropriately), but we do the best we can. | 3727 uint32 inappropriately), but we do the best we can. |
3148 | 3728 |
3149 Args: | 3729 Args: |
3150 filename: The name of the current file. | 3730 filename: The name of the current file. |
3151 clean_lines: A CleansedLines instance containing the file. | 3731 clean_lines: A CleansedLines instance containing the file. |
3152 linenum: The number of the line to check. | 3732 linenum: The number of the line to check. |
3153 file_extension: The extension (without the dot) of the filename. | 3733 file_extension: The extension (without the dot) of the filename. |
3154 include_state: An _IncludeState instance in which the headers are inserted. | 3734 include_state: An _IncludeState instance in which the headers are inserted. |
| 3735 nesting_state: A _NestingState instance which maintains information about |
| 3736 the current stack of nested blocks being parsed. |
3155 error: The function to call with any errors found. | 3737 error: The function to call with any errors found. |
3156 """ | 3738 """ |
3157 # If the line is empty or consists of entirely a comment, no need to | 3739 # If the line is empty or consists of entirely a comment, no need to |
3158 # check it. | 3740 # check it. |
3159 line = clean_lines.elided[linenum] | 3741 line = clean_lines.elided[linenum] |
3160 if not line: | 3742 if not line: |
3161 return | 3743 return |
3162 | 3744 |
3163 match = _RE_PATTERN_INCLUDE.search(line) | 3745 match = _RE_PATTERN_INCLUDE.search(line) |
3164 if match: | 3746 if match: |
3165 CheckIncludeLine(filename, clean_lines, linenum, include_state, error) | 3747 CheckIncludeLine(filename, clean_lines, linenum, include_state, error) |
3166 return | 3748 return |
3167 | 3749 |
3168 # Create an extended_line, which is the concatenation of the current and | 3750 # Reset include state across preprocessor directives. This is meant |
3169 # next lines, for more effective checking of code that may span more than one | 3751 # to silence warnings for conditional includes. |
3170 # line. | 3752 if Match(r'^\s*#\s*(?:ifdef|elif|else|endif)\b', line): |
3171 if linenum + 1 < clean_lines.NumLines(): | 3753 include_state.ResetSection() |
3172 extended_line = line + clean_lines.elided[linenum + 1] | |
3173 else: | |
3174 extended_line = line | |
3175 | 3754 |
3176 # Make Windows paths like Unix. | 3755 # Make Windows paths like Unix. |
3177 fullname = os.path.abspath(filename).replace('\\', '/') | 3756 fullname = os.path.abspath(filename).replace('\\', '/') |
3178 | 3757 |
3179 # TODO(unknown): figure out if they're using default arguments in fn proto. | 3758 # TODO(unknown): figure out if they're using default arguments in fn proto. |
3180 | 3759 |
3181 # Check for non-const references in functions. This is tricky because & | |
3182 # is also used to take the address of something. We allow <> for templates, | |
3183 # (ignoring whatever is between the braces) and : for classes. | |
3184 # These are complicated re's. They try to capture the following: | |
3185 # paren (for fn-prototype start), typename, &, varname. For the const | |
3186 # version, we're willing for const to be before typename or after | |
3187 # Don't check the implementation on same line. | |
3188 fnline = line.split('{', 1)[0] | |
3189 if (len(re.findall(r'\([^()]*\b(?:[\w:]|<[^()]*>)+(\s?&|&\s?)\w+', fnline)) > | |
3190 len(re.findall(r'\([^()]*\bconst\s+(?:typename\s+)?(?:struct\s+)?' | |
3191 r'(?:[\w:]|<[^()]*>)+(\s?&|&\s?)\w+', fnline)) + | |
3192 len(re.findall(r'\([^()]*\b(?:[\w:]|<[^()]*>)+\s+const(\s?&|&\s?)[\w]+', | |
3193 fnline))): | |
3194 | |
3195 # We allow non-const references in a few standard places, like functions | |
3196 # called "swap()" or iostream operators like "<<" or ">>". We also filter | |
3197 # out for loops, which lint otherwise mistakenly thinks are functions. | |
3198 if not Search( | |
3199 r'(for|swap|Swap|operator[<>][<>])\s*\(\s*' | |
3200 r'(?:(?:typename\s*)?[\w:]|<.*>)+\s*&', | |
3201 fnline): | |
3202 error(filename, linenum, 'runtime/references', 2, | |
3203 'Is this a non-const reference? ' | |
3204 'If so, make const or use a pointer.') | |
3205 | |
3206 # Check to see if they're using an conversion function cast. | 3760 # Check to see if they're using an conversion function cast. |
3207 # I just try to capture the most common basic types, though there are more. | 3761 # I just try to capture the most common basic types, though there are more. |
3208 # Parameterless conversion functions, such as bool(), are allowed as they are | 3762 # Parameterless conversion functions, such as bool(), are allowed as they are |
3209 # probably a member operator declaration or default constructor. | 3763 # probably a member operator declaration or default constructor. |
3210 match = Search( | 3764 match = Search( |
3211 r'(\bnew\s+)?\b' # Grab 'new' operator, if it's there | 3765 r'(\bnew\s+)?\b' # Grab 'new' operator, if it's there |
3212 r'(int|float|double|bool|char|int32|uint32|int64|uint64)\([^)]', line) | 3766 r'(int|float|double|bool|char|int32|uint32|int64|uint64)' |
| 3767 r'(\([^)].*)', line) |
3213 if match: | 3768 if match: |
| 3769 matched_new = match.group(1) |
| 3770 matched_type = match.group(2) |
| 3771 matched_funcptr = match.group(3) |
| 3772 |
3214 # gMock methods are defined using some variant of MOCK_METHODx(name, type) | 3773 # gMock methods are defined using some variant of MOCK_METHODx(name, type) |
3215 # where type may be float(), int(string), etc. Without context they are | 3774 # where type may be float(), int(string), etc. Without context they are |
3216 # virtually indistinguishable from int(x) casts. Likewise, gMock's | 3775 # virtually indistinguishable from int(x) casts. Likewise, gMock's |
3217 # MockCallback takes a template parameter of the form return_type(arg_type), | 3776 # MockCallback takes a template parameter of the form return_type(arg_type), |
3218 # which looks much like the cast we're trying to detect. | 3777 # which looks much like the cast we're trying to detect. |
3219 if (match.group(1) is None and # If new operator, then this isn't a cast | 3778 # |
| 3779 # std::function<> wrapper has a similar problem. |
| 3780 # |
| 3781 # Return types for function pointers also look like casts if they |
| 3782 # don't have an extra space. |
| 3783 if (matched_new is None and # If new operator, then this isn't a cast |
3220 not (Match(r'^\s*MOCK_(CONST_)?METHOD\d+(_T)?\(', line) or | 3784 not (Match(r'^\s*MOCK_(CONST_)?METHOD\d+(_T)?\(', line) or |
3221 Match(r'^\s*MockCallback<.*>', line))): | 3785 Search(r'\bMockCallback<.*>', line) or |
| 3786 Search(r'\bstd::function<.*>', line)) and |
| 3787 not (matched_funcptr and |
| 3788 Match(r'\((?:[^() ]+::\s*\*\s*)?[^() ]+\)\s*\(', |
| 3789 matched_funcptr))): |
3222 # Try a bit harder to catch gmock lines: the only place where | 3790 # Try a bit harder to catch gmock lines: the only place where |
3223 # something looks like an old-style cast is where we declare the | 3791 # something looks like an old-style cast is where we declare the |
3224 # return type of the mocked method, and the only time when we | 3792 # return type of the mocked method, and the only time when we |
3225 # are missing context is if MOCK_METHOD was split across | 3793 # are missing context is if MOCK_METHOD was split across |
3226 # multiple lines (for example http://go/hrfhr ), so we only need | 3794 # multiple lines. The missing MOCK_METHOD is usually one or two |
3227 # to check the previous line for MOCK_METHOD. | 3795 # lines back, so scan back one or two lines. |
3228 if (linenum == 0 or | 3796 # |
3229 not Match(r'^\s*MOCK_(CONST_)?METHOD\d+(_T)?\(\S+,\s*$', | 3797 # It's not possible for gmock macros to appear in the first 2 |
3230 clean_lines.elided[linenum - 1])): | 3798 # lines, since the class head + section name takes up 2 lines. |
| 3799 if (linenum < 2 or |
| 3800 not (Match(r'^\s*MOCK_(?:CONST_)?METHOD\d+(?:_T)?\((?:\S+,)?\s*$', |
| 3801 clean_lines.elided[linenum - 1]) or |
| 3802 Match(r'^\s*MOCK_(?:CONST_)?METHOD\d+(?:_T)?\(\s*$', |
| 3803 clean_lines.elided[linenum - 2]))): |
3231 error(filename, linenum, 'readability/casting', 4, | 3804 error(filename, linenum, 'readability/casting', 4, |
3232 'Using deprecated casting style. ' | 3805 'Using deprecated casting style. ' |
3233 'Use static_cast<%s>(...) instead' % | 3806 'Use static_cast<%s>(...) instead' % |
3234 match.group(2)) | 3807 matched_type) |
3235 | 3808 |
3236 CheckCStyleCast(filename, linenum, line, clean_lines.raw_lines[linenum], | 3809 CheckCStyleCast(filename, linenum, line, clean_lines.raw_lines[linenum], |
3237 'static_cast', | 3810 'static_cast', |
3238 r'\((int|float|double|bool|char|u?int(16|32|64))\)', error) | 3811 r'\((int|float|double|bool|char|u?int(16|32|64))\)', error) |
3239 | 3812 |
3240 # This doesn't catch all cases. Consider (const char * const)"hello". | 3813 # This doesn't catch all cases. Consider (const char * const)"hello". |
3241 # | 3814 # |
3242 # (char *) "foo" should always be a const_cast (reinterpret_cast won't | 3815 # (char *) "foo" should always be a const_cast (reinterpret_cast won't |
3243 # compile). | 3816 # compile). |
3244 if CheckCStyleCast(filename, linenum, line, clean_lines.raw_lines[linenum], | 3817 if CheckCStyleCast(filename, linenum, line, clean_lines.raw_lines[linenum], |
3245 'const_cast', r'\((char\s?\*+\s?)\)\s*"', error): | 3818 'const_cast', r'\((char\s?\*+\s?)\)\s*"', error): |
3246 pass | 3819 pass |
3247 else: | 3820 else: |
3248 # Check pointer casts for other than string constants | 3821 # Check pointer casts for other than string constants |
3249 CheckCStyleCast(filename, linenum, line, clean_lines.raw_lines[linenum], | 3822 CheckCStyleCast(filename, linenum, line, clean_lines.raw_lines[linenum], |
3250 'reinterpret_cast', r'\((\w+\s?\*+\s?)\)', error) | 3823 'reinterpret_cast', r'\((\w+\s?\*+\s?)\)', error) |
3251 | 3824 |
3252 # In addition, we look for people taking the address of a cast. This | 3825 # In addition, we look for people taking the address of a cast. This |
3253 # is dangerous -- casts can assign to temporaries, so the pointer doesn't | 3826 # is dangerous -- casts can assign to temporaries, so the pointer doesn't |
3254 # point where you think. | 3827 # point where you think. |
3255 if Search( | 3828 match = Search( |
3256 r'(&\([^)]+\)[\w(])|(&(static|dynamic|reinterpret)_cast\b)', line): | 3829 r'(?:&\(([^)]+)\)[\w(])|' |
| 3830 r'(?:&(static|dynamic|down|reinterpret)_cast\b)', line) |
| 3831 if match and match.group(1) != '*': |
3257 error(filename, linenum, 'runtime/casting', 4, | 3832 error(filename, linenum, 'runtime/casting', 4, |
3258 ('Are you taking an address of a cast? ' | 3833 ('Are you taking an address of a cast? ' |
3259 'This is dangerous: could be a temp var. ' | 3834 'This is dangerous: could be a temp var. ' |
3260 'Take the address before doing the cast, rather than after')) | 3835 'Take the address before doing the cast, rather than after')) |
3261 | 3836 |
| 3837 # Create an extended_line, which is the concatenation of the current and |
| 3838 # next lines, for more effective checking of code that may span more than one |
| 3839 # line. |
| 3840 if linenum + 1 < clean_lines.NumLines(): |
| 3841 extended_line = line + clean_lines.elided[linenum + 1] |
| 3842 else: |
| 3843 extended_line = line |
| 3844 |
3262 # Check for people declaring static/global STL strings at the top level. | 3845 # Check for people declaring static/global STL strings at the top level. |
3263 # This is dangerous because the C++ language does not guarantee that | 3846 # This is dangerous because the C++ language does not guarantee that |
3264 # globals with constructors are initialized before the first access. | 3847 # globals with constructors are initialized before the first access. |
3265 match = Match( | 3848 match = Match( |
3266 r'((?:|static +)(?:|const +))string +([a-zA-Z0-9_:]+)\b(.*)', | 3849 r'((?:|static +)(?:|const +))string +([a-zA-Z0-9_:]+)\b(.*)', |
3267 line) | 3850 line) |
3268 # Make sure it's not a function. | 3851 # Make sure it's not a function. |
3269 # Function template specialization looks like: "string foo<Type>(...". | 3852 # Function template specialization looks like: "string foo<Type>(...". |
3270 # Class template definitions look like: "string Foo<Type>::Method(...". | 3853 # Class template definitions look like: "string Foo<Type>::Method(...". |
3271 if match and not Match(r'\s*(<.*>)?(::[a-zA-Z0-9_]+)?\s*\(([^"]|$)', | 3854 # |
3272 match.group(3)): | 3855 # Also ignore things that look like operators. These are matched separately |
| 3856 # because operator names cross non-word boundaries. If we change the pattern |
| 3857 # above, we would decrease the accuracy of matching identifiers. |
| 3858 if (match and |
| 3859 not Search(r'\boperator\W', line) and |
| 3860 not Match(r'\s*(<.*>)?(::[a-zA-Z0-9_]+)?\s*\(([^"]|$)', match.group(3))): |
3273 error(filename, linenum, 'runtime/string', 4, | 3861 error(filename, linenum, 'runtime/string', 4, |
3274 'For a static/global string constant, use a C style string instead: ' | 3862 'For a static/global string constant, use a C style string instead: ' |
3275 '"%schar %s[]".' % | 3863 '"%schar %s[]".' % |
3276 (match.group(1), match.group(2))) | 3864 (match.group(1), match.group(2))) |
3277 | 3865 |
3278 # Check that we're not using RTTI outside of testing code. | |
3279 if Search(r'\bdynamic_cast<', line) and not _IsTestFilename(filename): | |
3280 error(filename, linenum, 'runtime/rtti', 5, | |
3281 'Do not use dynamic_cast<>. If you need to cast within a class ' | |
3282 "hierarchy, use static_cast<> to upcast. Google doesn't support " | |
3283 'RTTI.') | |
3284 | |
3285 if Search(r'\b([A-Za-z0-9_]*_)\(\1\)', line): | 3866 if Search(r'\b([A-Za-z0-9_]*_)\(\1\)', line): |
3286 error(filename, linenum, 'runtime/init', 4, | 3867 error(filename, linenum, 'runtime/init', 4, |
3287 'You seem to be initializing a member variable with itself.') | 3868 'You seem to be initializing a member variable with itself.') |
3288 | 3869 |
3289 if file_extension == 'h': | 3870 if file_extension == 'h': |
3290 # TODO(unknown): check that 1-arg constructors are explicit. | 3871 # TODO(unknown): check that 1-arg constructors are explicit. |
3291 # How to tell it's a constructor? | 3872 # How to tell it's a constructor? |
3292 # (handled in CheckForNonStandardConstructs for now) | 3873 # (handled in CheckForNonStandardConstructs for now) |
3293 # TODO(unknown): check that classes have DISALLOW_EVIL_CONSTRUCTORS | 3874 # TODO(unknown): check that classes have DISALLOW_EVIL_CONSTRUCTORS |
3294 # (level 1 error) | 3875 # (level 1 error) |
(...skipping 21 matching lines...) Expand all Loading... |
3316 | 3897 |
3317 # Check if some verboten C functions are being used. | 3898 # Check if some verboten C functions are being used. |
3318 if Search(r'\bsprintf\b', line): | 3899 if Search(r'\bsprintf\b', line): |
3319 error(filename, linenum, 'runtime/printf', 5, | 3900 error(filename, linenum, 'runtime/printf', 5, |
3320 'Never use sprintf. Use snprintf instead.') | 3901 'Never use sprintf. Use snprintf instead.') |
3321 match = Search(r'\b(strcpy|strcat)\b', line) | 3902 match = Search(r'\b(strcpy|strcat)\b', line) |
3322 if match: | 3903 if match: |
3323 error(filename, linenum, 'runtime/printf', 4, | 3904 error(filename, linenum, 'runtime/printf', 4, |
3324 'Almost always, snprintf is better than %s' % match.group(1)) | 3905 'Almost always, snprintf is better than %s' % match.group(1)) |
3325 | 3906 |
3326 if Search(r'\bsscanf\b', line): | |
3327 error(filename, linenum, 'runtime/printf', 1, | |
3328 'sscanf can be ok, but is slow and can overflow buffers.') | |
3329 | |
3330 # Check if some verboten operator overloading is going on | 3907 # Check if some verboten operator overloading is going on |
3331 # TODO(unknown): catch out-of-line unary operator&: | 3908 # TODO(unknown): catch out-of-line unary operator&: |
3332 # class X {}; | 3909 # class X {}; |
3333 # int operator&(const X& x) { return 42; } // unary operator& | 3910 # int operator&(const X& x) { return 42; } // unary operator& |
3334 # The trick is it's hard to tell apart from binary operator&: | 3911 # The trick is it's hard to tell apart from binary operator&: |
3335 # class Y { int operator&(const Y& x) { return 23; } }; // binary operator& | 3912 # class Y { int operator&(const Y& x) { return 23; } }; // binary operator& |
3336 if Search(r'\boperator\s*&\s*\(\s*\)', line): | 3913 if Search(r'\boperator\s*&\s*\(\s*\)', line): |
3337 error(filename, linenum, 'runtime/operator', 4, | 3914 error(filename, linenum, 'runtime/operator', 4, |
3338 'Unary operator& is dangerous. Do not use it.') | 3915 'Unary operator& is dangerous. Do not use it.') |
3339 | 3916 |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3435 # macros are typically OK, so we allow use of "namespace {" on lines | 4012 # macros are typically OK, so we allow use of "namespace {" on lines |
3436 # that end with backslashes. | 4013 # that end with backslashes. |
3437 if (file_extension == 'h' | 4014 if (file_extension == 'h' |
3438 and Search(r'\bnamespace\s*{', line) | 4015 and Search(r'\bnamespace\s*{', line) |
3439 and line[-1] != '\\'): | 4016 and line[-1] != '\\'): |
3440 error(filename, linenum, 'build/namespaces', 4, | 4017 error(filename, linenum, 'build/namespaces', 4, |
3441 'Do not use unnamed namespaces in header files. See ' | 4018 'Do not use unnamed namespaces in header files. See ' |
3442 'http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Namesp
aces' | 4019 'http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Namesp
aces' |
3443 ' for more information.') | 4020 ' for more information.') |
3444 | 4021 |
| 4022 def CheckForNonConstReference(filename, clean_lines, linenum, |
| 4023 nesting_state, error): |
| 4024 """Check for non-const references. |
| 4025 |
| 4026 Separate from CheckLanguage since it scans backwards from current |
| 4027 line, instead of scanning forward. |
| 4028 |
| 4029 Args: |
| 4030 filename: The name of the current file. |
| 4031 clean_lines: A CleansedLines instance containing the file. |
| 4032 linenum: The number of the line to check. |
| 4033 nesting_state: A _NestingState instance which maintains information about |
| 4034 the current stack of nested blocks being parsed. |
| 4035 error: The function to call with any errors found. |
| 4036 """ |
| 4037 # Do nothing if there is no '&' on current line. |
| 4038 line = clean_lines.elided[linenum] |
| 4039 if '&' not in line: |
| 4040 return |
| 4041 |
| 4042 # Long type names may be broken across multiple lines, usually in one |
| 4043 # of these forms: |
| 4044 # LongType |
| 4045 # ::LongTypeContinued &identifier |
| 4046 # LongType:: |
| 4047 # LongTypeContinued &identifier |
| 4048 # LongType< |
| 4049 # ...>::LongTypeContinued &identifier |
| 4050 # |
| 4051 # If we detected a type split across two lines, join the previous |
| 4052 # line to current line so that we can match const references |
| 4053 # accordingly. |
| 4054 # |
| 4055 # Note that this only scans back one line, since scanning back |
| 4056 # arbitrary number of lines would be expensive. If you have a type |
| 4057 # that spans more than 2 lines, please use a typedef. |
| 4058 if linenum > 1: |
| 4059 previous = None |
| 4060 if Match(r'\s*::(?:[\w<>]|::)+\s*&\s*\S', line): |
| 4061 # previous_line\n + ::current_line |
| 4062 previous = Search(r'\b((?:const\s*)?(?:[\w<>]|::)+[\w<>])\s*$', |
| 4063 clean_lines.elided[linenum - 1]) |
| 4064 elif Match(r'\s*[a-zA-Z_]([\w<>]|::)+\s*&\s*\S', line): |
| 4065 # previous_line::\n + current_line |
| 4066 previous = Search(r'\b((?:const\s*)?(?:[\w<>]|::)+::)\s*$', |
| 4067 clean_lines.elided[linenum - 1]) |
| 4068 if previous: |
| 4069 line = previous.group(1) + line.lstrip() |
| 4070 else: |
| 4071 # Check for templated parameter that is split across multiple lines |
| 4072 endpos = line.rfind('>') |
| 4073 if endpos > -1: |
| 4074 (_, startline, startpos) = ReverseCloseExpression( |
| 4075 clean_lines, linenum, endpos) |
| 4076 if startpos > -1 and startline < linenum: |
| 4077 # Found the matching < on an earlier line, collect all |
| 4078 # pieces up to current line. |
| 4079 line = '' |
| 4080 for i in xrange(startline, linenum + 1): |
| 4081 line += clean_lines.elided[i].strip() |
| 4082 |
| 4083 # Check for non-const references in function parameters. A single '&' may |
| 4084 # found in the following places: |
| 4085 # inside expression: binary & for bitwise AND |
| 4086 # inside expression: unary & for taking the address of something |
| 4087 # inside declarators: reference parameter |
| 4088 # We will exclude the first two cases by checking that we are not inside a |
| 4089 # function body, including one that was just introduced by a trailing '{'. |
| 4090 # TODO(unknwon): Doesn't account for preprocessor directives. |
| 4091 # TODO(unknown): Doesn't account for 'catch(Exception& e)' [rare]. |
| 4092 check_params = False |
| 4093 if not nesting_state.stack: |
| 4094 check_params = True # top level |
| 4095 elif (isinstance(nesting_state.stack[-1], _ClassInfo) or |
| 4096 isinstance(nesting_state.stack[-1], _NamespaceInfo)): |
| 4097 check_params = True # within class or namespace |
| 4098 elif Match(r'.*{\s*$', line): |
| 4099 if (len(nesting_state.stack) == 1 or |
| 4100 isinstance(nesting_state.stack[-2], _ClassInfo) or |
| 4101 isinstance(nesting_state.stack[-2], _NamespaceInfo)): |
| 4102 check_params = True # just opened global/class/namespace block |
| 4103 # We allow non-const references in a few standard places, like functions |
| 4104 # called "swap()" or iostream operators like "<<" or ">>". Do not check |
| 4105 # those function parameters. |
| 4106 # |
| 4107 # We also accept & in static_assert, which looks like a function but |
| 4108 # it's actually a declaration expression. |
| 4109 whitelisted_functions = (r'(?:[sS]wap(?:<\w:+>)?|' |
| 4110 r'operator\s*[<>][<>]|' |
| 4111 r'static_assert|COMPILE_ASSERT' |
| 4112 r')\s*\(') |
| 4113 if Search(whitelisted_functions, line): |
| 4114 check_params = False |
| 4115 elif not Search(r'\S+\([^)]*$', line): |
| 4116 # Don't see a whitelisted function on this line. Actually we |
| 4117 # didn't see any function name on this line, so this is likely a |
| 4118 # multi-line parameter list. Try a bit harder to catch this case. |
| 4119 for i in xrange(2): |
| 4120 if (linenum > i and |
| 4121 Search(whitelisted_functions, clean_lines.elided[linenum - i - 1])): |
| 4122 check_params = False |
| 4123 break |
| 4124 |
| 4125 if check_params: |
| 4126 decls = ReplaceAll(r'{[^}]*}', ' ', line) # exclude function body |
| 4127 for parameter in re.findall(_RE_PATTERN_REF_PARAM, decls): |
| 4128 if not Match(_RE_PATTERN_CONST_REF_PARAM, parameter): |
| 4129 error(filename, linenum, 'runtime/references', 2, |
| 4130 'Is this a non-const reference? ' |
| 4131 'If so, make const or use a pointer: ' + |
| 4132 ReplaceAll(' *<', '<', parameter)) |
| 4133 |
3445 | 4134 |
3446 def CheckCStyleCast(filename, linenum, line, raw_line, cast_type, pattern, | 4135 def CheckCStyleCast(filename, linenum, line, raw_line, cast_type, pattern, |
3447 error): | 4136 error): |
3448 """Checks for a C-style cast by looking for the pattern. | 4137 """Checks for a C-style cast by looking for the pattern. |
3449 | 4138 |
3450 This also handles sizeof(type) warnings, due to similarity of content. | |
3451 | |
3452 Args: | 4139 Args: |
3453 filename: The name of the current file. | 4140 filename: The name of the current file. |
3454 linenum: The number of the line to check. | 4141 linenum: The number of the line to check. |
3455 line: The line of code to check. | 4142 line: The line of code to check. |
3456 raw_line: The raw line of code to check, with comments. | 4143 raw_line: The raw line of code to check, with comments. |
3457 cast_type: The string for the C++ cast to recommend. This is either | 4144 cast_type: The string for the C++ cast to recommend. This is either |
3458 reinterpret_cast, static_cast, or const_cast, depending. | 4145 reinterpret_cast, static_cast, or const_cast, depending. |
3459 pattern: The regular expression used to find C-style casts. | 4146 pattern: The regular expression used to find C-style casts. |
3460 error: The function to call with any errors found. | 4147 error: The function to call with any errors found. |
3461 | 4148 |
3462 Returns: | 4149 Returns: |
3463 True if an error was emitted. | 4150 True if an error was emitted. |
3464 False otherwise. | 4151 False otherwise. |
3465 """ | 4152 """ |
3466 match = Search(pattern, line) | 4153 match = Search(pattern, line) |
3467 if not match: | 4154 if not match: |
3468 return False | 4155 return False |
3469 | 4156 |
3470 # e.g., sizeof(int) | 4157 # Exclude lines with sizeof, since sizeof looks like a cast. |
3471 sizeof_match = Match(r'.*sizeof\s*$', line[0:match.start(1) - 1]) | 4158 sizeof_match = Match(r'.*sizeof\s*$', line[0:match.start(1) - 1]) |
3472 if sizeof_match: | 4159 if sizeof_match: |
3473 error(filename, linenum, 'runtime/sizeof', 1, | 4160 return False |
3474 'Using sizeof(type). Use sizeof(varname) instead if possible') | |
3475 return True | |
3476 | 4161 |
3477 # operator++(int) and operator--(int) | 4162 # operator++(int) and operator--(int) |
3478 if (line[0:match.start(1) - 1].endswith(' operator++') or | 4163 if (line[0:match.start(1) - 1].endswith(' operator++') or |
3479 line[0:match.start(1) - 1].endswith(' operator--')): | 4164 line[0:match.start(1) - 1].endswith(' operator--')): |
3480 return False | 4165 return False |
3481 | 4166 |
| 4167 # A single unnamed argument for a function tends to look like old |
| 4168 # style cast. If we see those, don't issue warnings for deprecated |
| 4169 # casts, instead issue warnings for unnamed arguments where |
| 4170 # appropriate. |
| 4171 # |
| 4172 # These are things that we want warnings for, since the style guide |
| 4173 # explicitly require all parameters to be named: |
| 4174 # Function(int); |
| 4175 # Function(int) { |
| 4176 # ConstMember(int) const; |
| 4177 # ConstMember(int) const { |
| 4178 # ExceptionMember(int) throw (...); |
| 4179 # ExceptionMember(int) throw (...) { |
| 4180 # PureVirtual(int) = 0; |
| 4181 # |
| 4182 # These are functions of some sort, where the compiler would be fine |
| 4183 # if they had named parameters, but people often omit those |
| 4184 # identifiers to reduce clutter: |
| 4185 # (FunctionPointer)(int); |
| 4186 # (FunctionPointer)(int) = value; |
| 4187 # Function((function_pointer_arg)(int)) |
| 4188 # <TemplateArgument(int)>; |
| 4189 # <(FunctionPointerTemplateArgument)(int)>; |
3482 remainder = line[match.end(0):] | 4190 remainder = line[match.end(0):] |
| 4191 if Match(r'^\s*(?:;|const\b|throw\b|=|>|\{|\))', remainder): |
| 4192 # Looks like an unnamed parameter. |
3483 | 4193 |
3484 # The close paren is for function pointers as arguments to a function. | 4194 # Don't warn on any kind of template arguments. |
3485 # eg, void foo(void (*bar)(int)); | 4195 if Match(r'^\s*>', remainder): |
3486 # The semicolon check is a more basic function check; also possibly a | 4196 return False |
3487 # function pointer typedef. | 4197 |
3488 # eg, void foo(int); or void foo(int) const; | 4198 # Don't warn on assignments to function pointers, but keep warnings for |
3489 # The equals check is for function pointer assignment. | 4199 # unnamed parameters to pure virtual functions. Note that this pattern |
3490 # eg, void *(*foo)(int) = ... | 4200 # will also pass on assignments of "0" to function pointers, but the |
3491 # The > is for MockCallback<...> ... | 4201 # preferred values for those would be "nullptr" or "NULL". |
3492 # | 4202 matched_zero = Match(r'^\s=\s*(\S+)\s*;', remainder) |
3493 # Right now, this will only catch cases where there's a single argument, and | 4203 if matched_zero and matched_zero.group(1) != '0': |
3494 # it's unnamed. It should probably be expanded to check for multiple | 4204 return False |
3495 # arguments with some unnamed. | 4205 |
3496 function_match = Match(r'\s*(\)|=|(const)?\s*(;|\{|throw\(\)|>))', remainder) | 4206 # Don't warn on function pointer declarations. For this we need |
3497 if function_match: | 4207 # to check what came before the "(type)" string. |
3498 if (not function_match.group(3) or | 4208 if Match(r'.*\)\s*$', line[0:match.start(0)]): |
3499 function_match.group(3) == ';' or | 4209 return False |
3500 ('MockCallback<' not in raw_line and | 4210 |
3501 '/*' not in raw_line)): | 4211 # Don't warn if the parameter is named with block comments, e.g.: |
3502 error(filename, linenum, 'readability/function', 3, | 4212 # Function(int /*unused_param*/); |
3503 'All parameters should be named in a function') | 4213 if '/*' in raw_line: |
| 4214 return False |
| 4215 |
| 4216 # Passed all filters, issue warning here. |
| 4217 error(filename, linenum, 'readability/function', 3, |
| 4218 'All parameters should be named in a function') |
3504 return True | 4219 return True |
3505 | 4220 |
3506 # At this point, all that should be left is actual casts. | 4221 # At this point, all that should be left is actual casts. |
3507 error(filename, linenum, 'readability/casting', 4, | 4222 error(filename, linenum, 'readability/casting', 4, |
3508 'Using C-style cast. Use %s<%s>(...) instead' % | 4223 'Using C-style cast. Use %s<%s>(...) instead' % |
3509 (cast_type, match.group(1))) | 4224 (cast_type, match.group(1))) |
3510 | 4225 |
3511 return True | 4226 return True |
3512 | 4227 |
3513 | 4228 |
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3754 | 4469 |
3755 G++ 4.6 in C++0x mode fails badly if make_pair's template arguments are | 4470 G++ 4.6 in C++0x mode fails badly if make_pair's template arguments are |
3756 specified explicitly, and such use isn't intended in any case. | 4471 specified explicitly, and such use isn't intended in any case. |
3757 | 4472 |
3758 Args: | 4473 Args: |
3759 filename: The name of the current file. | 4474 filename: The name of the current file. |
3760 clean_lines: A CleansedLines instance containing the file. | 4475 clean_lines: A CleansedLines instance containing the file. |
3761 linenum: The number of the line to check. | 4476 linenum: The number of the line to check. |
3762 error: The function to call with any errors found. | 4477 error: The function to call with any errors found. |
3763 """ | 4478 """ |
3764 raw = clean_lines.raw_lines | 4479 line = clean_lines.elided[linenum] |
3765 line = raw[linenum] | |
3766 match = _RE_PATTERN_EXPLICIT_MAKEPAIR.search(line) | 4480 match = _RE_PATTERN_EXPLICIT_MAKEPAIR.search(line) |
3767 if match: | 4481 if match: |
3768 error(filename, linenum, 'build/explicit_make_pair', | 4482 error(filename, linenum, 'build/explicit_make_pair', |
3769 4, # 4 = high confidence | 4483 4, # 4 = high confidence |
3770 'For C++11-compatibility, omit template arguments from make_pair' | 4484 'For C++11-compatibility, omit template arguments from make_pair' |
3771 ' OR use pair directly OR if appropriate, construct a pair directly') | 4485 ' OR use pair directly OR if appropriate, construct a pair directly') |
3772 | 4486 |
3773 | 4487 |
3774 def ProcessLine(filename, file_extension, clean_lines, line, | 4488 def ProcessLine(filename, file_extension, clean_lines, line, |
3775 include_state, function_state, nesting_state, error, | 4489 include_state, function_state, nesting_state, error, |
(...skipping 18 matching lines...) Expand all Loading... |
3794 """ | 4508 """ |
3795 raw_lines = clean_lines.raw_lines | 4509 raw_lines = clean_lines.raw_lines |
3796 ParseNolintSuppressions(filename, raw_lines[line], line, error) | 4510 ParseNolintSuppressions(filename, raw_lines[line], line, error) |
3797 nesting_state.Update(filename, clean_lines, line, error) | 4511 nesting_state.Update(filename, clean_lines, line, error) |
3798 if nesting_state.stack and nesting_state.stack[-1].inline_asm != _NO_ASM: | 4512 if nesting_state.stack and nesting_state.stack[-1].inline_asm != _NO_ASM: |
3799 return | 4513 return |
3800 CheckForFunctionLengths(filename, clean_lines, line, function_state, error) | 4514 CheckForFunctionLengths(filename, clean_lines, line, function_state, error) |
3801 CheckForMultilineCommentsAndStrings(filename, clean_lines, line, error) | 4515 CheckForMultilineCommentsAndStrings(filename, clean_lines, line, error) |
3802 CheckStyle(filename, clean_lines, line, file_extension, nesting_state, error) | 4516 CheckStyle(filename, clean_lines, line, file_extension, nesting_state, error) |
3803 CheckLanguage(filename, clean_lines, line, file_extension, include_state, | 4517 CheckLanguage(filename, clean_lines, line, file_extension, include_state, |
3804 error) | 4518 nesting_state, error) |
| 4519 CheckForNonConstReference(filename, clean_lines, line, nesting_state, error) |
3805 CheckForNonStandardConstructs(filename, clean_lines, line, | 4520 CheckForNonStandardConstructs(filename, clean_lines, line, |
3806 nesting_state, error) | 4521 nesting_state, error) |
| 4522 CheckVlogArguments(filename, clean_lines, line, error) |
3807 CheckPosixThreading(filename, clean_lines, line, error) | 4523 CheckPosixThreading(filename, clean_lines, line, error) |
3808 CheckInvalidIncrement(filename, clean_lines, line, error) | 4524 CheckInvalidIncrement(filename, clean_lines, line, error) |
3809 CheckMakePairUsesDeduction(filename, clean_lines, line, error) | 4525 CheckMakePairUsesDeduction(filename, clean_lines, line, error) |
3810 for check_fn in extra_check_functions: | 4526 for check_fn in extra_check_functions: |
3811 check_fn(filename, clean_lines, line, error) | 4527 check_fn(filename, clean_lines, line, error) |
3812 | 4528 |
3813 def ProcessFileData(filename, file_extension, lines, error, | 4529 def ProcessFileData(filename, file_extension, lines, error, |
3814 extra_check_functions=[]): | 4530 extra_check_functions=[]): |
3815 """Performs lint checks and reports any errors to the given error function. | 4531 """Performs lint checks and reports any errors to the given error function. |
3816 | 4532 |
(...skipping 21 matching lines...) Expand all Loading... |
3838 | 4554 |
3839 if file_extension == 'h': | 4555 if file_extension == 'h': |
3840 CheckForHeaderGuard(filename, lines, error) | 4556 CheckForHeaderGuard(filename, lines, error) |
3841 | 4557 |
3842 RemoveMultiLineComments(filename, lines, error) | 4558 RemoveMultiLineComments(filename, lines, error) |
3843 clean_lines = CleansedLines(lines) | 4559 clean_lines = CleansedLines(lines) |
3844 for line in xrange(clean_lines.NumLines()): | 4560 for line in xrange(clean_lines.NumLines()): |
3845 ProcessLine(filename, file_extension, clean_lines, line, | 4561 ProcessLine(filename, file_extension, clean_lines, line, |
3846 include_state, function_state, nesting_state, error, | 4562 include_state, function_state, nesting_state, error, |
3847 extra_check_functions) | 4563 extra_check_functions) |
3848 nesting_state.CheckClassFinished(filename, error) | 4564 nesting_state.CheckCompletedBlocks(filename, error) |
3849 | 4565 |
3850 CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error) | 4566 CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error) |
3851 | 4567 |
3852 # We check here rather than inside ProcessLine so that we see raw | 4568 # We check here rather than inside ProcessLine so that we see raw |
3853 # lines rather than "cleaned" lines. | 4569 # lines rather than "cleaned" lines. |
3854 CheckForUnicodeReplacementCharacters(filename, lines, error) | 4570 CheckForBadCharacters(filename, lines, error) |
3855 | 4571 |
3856 CheckForNewlineAtEOF(filename, lines, error) | 4572 CheckForNewlineAtEOF(filename, lines, error) |
3857 | 4573 |
3858 def ProcessFile(filename, vlevel, extra_check_functions=[]): | 4574 def ProcessFile(filename, vlevel, extra_check_functions=[]): |
3859 """Does google-lint on a single file. | 4575 """Does google-lint on a single file. |
3860 | 4576 |
3861 Args: | 4577 Args: |
3862 filename: The name of the file to parse. | 4578 filename: The name of the file to parse. |
3863 | 4579 |
3864 vlevel: The level of errors to report. Every error of confidence | 4580 vlevel: The level of errors to report. Every error of confidence |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3900 except IOError: | 4616 except IOError: |
3901 sys.stderr.write( | 4617 sys.stderr.write( |
3902 "Skipping input '%s': Can't open for reading\n" % filename) | 4618 "Skipping input '%s': Can't open for reading\n" % filename) |
3903 return | 4619 return |
3904 | 4620 |
3905 # Note, if no dot is found, this will give the entire filename as the ext. | 4621 # Note, if no dot is found, this will give the entire filename as the ext. |
3906 file_extension = filename[filename.rfind('.') + 1:] | 4622 file_extension = filename[filename.rfind('.') + 1:] |
3907 | 4623 |
3908 # When reading from stdin, the extension is unknown, so no cpplint tests | 4624 # When reading from stdin, the extension is unknown, so no cpplint tests |
3909 # should rely on the extension. | 4625 # should rely on the extension. |
3910 if (filename != '-' and file_extension != 'cc' and file_extension != 'h' | 4626 if filename != '-' and file_extension not in _valid_extensions: |
3911 and file_extension != 'cpp'): | 4627 sys.stderr.write('Ignoring %s; not a valid file name ' |
3912 sys.stderr.write('Ignoring %s; not a .cc or .h file\n' % filename) | 4628 '(%s)\n' % (filename, ', '.join(_valid_extensions))) |
3913 else: | 4629 else: |
3914 ProcessFileData(filename, file_extension, lines, Error, | 4630 ProcessFileData(filename, file_extension, lines, Error, |
3915 extra_check_functions) | 4631 extra_check_functions) |
3916 if carriage_return_found and os.linesep != '\r\n': | 4632 if carriage_return_found and os.linesep != '\r\n': |
3917 # Use 0 for linenum since outputting only one error for potentially | 4633 # Use 0 for linenum since outputting only one error for potentially |
3918 # several lines. | 4634 # several lines. |
3919 Error(filename, 0, 'whitespace/newline', 1, | 4635 Error(filename, 0, 'whitespace/newline', 1, |
3920 'One or more unexpected \\r (^M) found;' | 4636 'One or more unexpected \\r (^M) found;' |
3921 'better to use only a \\n') | 4637 'better to use only a \\n') |
3922 | 4638 |
(...skipping 30 matching lines...) Expand all Loading... |
3953 Args: | 4669 Args: |
3954 args: The command line arguments: | 4670 args: The command line arguments: |
3955 | 4671 |
3956 Returns: | 4672 Returns: |
3957 The list of filenames to lint. | 4673 The list of filenames to lint. |
3958 """ | 4674 """ |
3959 try: | 4675 try: |
3960 (opts, filenames) = getopt.getopt(args, '', ['help', 'output=', 'verbose=', | 4676 (opts, filenames) = getopt.getopt(args, '', ['help', 'output=', 'verbose=', |
3961 'counting=', | 4677 'counting=', |
3962 'filter=', | 4678 'filter=', |
3963 'root=']) | 4679 'root=', |
| 4680 'linelength=', |
| 4681 'extensions=']) |
3964 except getopt.GetoptError: | 4682 except getopt.GetoptError: |
3965 PrintUsage('Invalid arguments.') | 4683 PrintUsage('Invalid arguments.') |
3966 | 4684 |
3967 verbosity = _VerboseLevel() | 4685 verbosity = _VerboseLevel() |
3968 output_format = _OutputFormat() | 4686 output_format = _OutputFormat() |
3969 filters = '' | 4687 filters = '' |
3970 counting_style = '' | 4688 counting_style = '' |
3971 | 4689 |
3972 for (opt, val) in opts: | 4690 for (opt, val) in opts: |
3973 if opt == '--help': | 4691 if opt == '--help': |
3974 PrintUsage(None) | 4692 PrintUsage(None) |
3975 elif opt == '--output': | 4693 elif opt == '--output': |
3976 if not val in ('emacs', 'vs7', 'eclipse'): | 4694 if val not in ('emacs', 'vs7', 'eclipse'): |
3977 PrintUsage('The only allowed output formats are emacs, vs7 and eclipse.'
) | 4695 PrintUsage('The only allowed output formats are emacs, vs7 and eclipse.'
) |
3978 output_format = val | 4696 output_format = val |
3979 elif opt == '--verbose': | 4697 elif opt == '--verbose': |
3980 verbosity = int(val) | 4698 verbosity = int(val) |
3981 elif opt == '--filter': | 4699 elif opt == '--filter': |
3982 filters = val | 4700 filters = val |
3983 if not filters: | 4701 if not filters: |
3984 PrintCategories() | 4702 PrintCategories() |
3985 elif opt == '--counting': | 4703 elif opt == '--counting': |
3986 if val not in ('total', 'toplevel', 'detailed'): | 4704 if val not in ('total', 'toplevel', 'detailed'): |
3987 PrintUsage('Valid counting options are total, toplevel, and detailed') | 4705 PrintUsage('Valid counting options are total, toplevel, and detailed') |
3988 counting_style = val | 4706 counting_style = val |
3989 elif opt == '--root': | 4707 elif opt == '--root': |
3990 global _root | 4708 global _root |
3991 _root = val | 4709 _root = val |
| 4710 elif opt == '--linelength': |
| 4711 global _line_length |
| 4712 try: |
| 4713 _line_length = int(val) |
| 4714 except ValueError: |
| 4715 PrintUsage('Line length must be digits.') |
| 4716 elif opt == '--extensions': |
| 4717 global _valid_extensions |
| 4718 try: |
| 4719 _valid_extensions = set(val.split(',')) |
| 4720 except ValueError: |
| 4721 PrintUsage('Extensions must be comma seperated list.') |
3992 | 4722 |
3993 if not filenames: | 4723 if not filenames: |
3994 PrintUsage('No files were specified.') | 4724 PrintUsage('No files were specified.') |
3995 | 4725 |
3996 _SetOutputFormat(output_format) | 4726 _SetOutputFormat(output_format) |
3997 _SetVerboseLevel(verbosity) | 4727 _SetVerboseLevel(verbosity) |
3998 _SetFilters(filters) | 4728 _SetFilters(filters) |
3999 _SetCountingStyle(counting_style) | 4729 _SetCountingStyle(counting_style) |
4000 | 4730 |
4001 return filenames | 4731 return filenames |
(...skipping 12 matching lines...) Expand all Loading... |
4014 _cpplint_state.ResetErrorCounts() | 4744 _cpplint_state.ResetErrorCounts() |
4015 for filename in filenames: | 4745 for filename in filenames: |
4016 ProcessFile(filename, _cpplint_state.verbose_level) | 4746 ProcessFile(filename, _cpplint_state.verbose_level) |
4017 _cpplint_state.PrintErrorCounts() | 4747 _cpplint_state.PrintErrorCounts() |
4018 | 4748 |
4019 sys.exit(_cpplint_state.error_count > 0) | 4749 sys.exit(_cpplint_state.error_count > 0) |
4020 | 4750 |
4021 | 4751 |
4022 if __name__ == '__main__': | 4752 if __name__ == '__main__': |
4023 main() | 4753 main() |
OLD | NEW |