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

Side by Side Diff: depot_tools/cpplint.py

Issue 92087: Create the Next Generation of depot_tools. Eh. (Closed) Base URL: svn://chrome-svn.corp.google.com/chrome/trunk/tools/
Patch Set: Created 11 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « depot_tools/chrome-update-create-task.bat ('k') | depot_tools/gcl » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Property Changes:
Added: svn:executable
+ *
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 #!/usr/bin/python2.4
2 #
3 # cpplint.py is Copyright (C) 2009 Google Inc.
4 #
5 # It is free software; you can redistribute it and/or modify it under the
6 # terms of either:
7 #
8 # a) the GNU General Public License as published by the Free Software
9 # Foundation; either version 1, or (at your option) any later version, or
10 #
11 # b) the "Artistic License".
12
13 # Here are some issues that I've had people identify in my code during reviews,
14 # that I think are possible to flag automatically in a lint tool. If these were
15 # caught by lint, it would save time both for myself and that of my reviewers.
16 # Most likely, some of these are beyond the scope of the current lint framework,
17 # but I think it is valuable to retain these wish-list items even if they cannot
18 # be immediately implemented.
19 #
20 # Suggestions
21 # -----------
22 # - Check for no 'explicit' for multi-arg ctor
23 # - Check for boolean assign RHS in parens
24 # - Check for ctor initializer-list colon position and spacing
25 # - Check that if there's a ctor, there should be a dtor
26 # - Check accessors that return non-pointer member variables are
27 # declared const
28 # - Check accessors that return non-const pointer member vars are
29 # *not* declared const
30 # - Check for using public includes for testing
31 # - Check for spaces between brackets in one-line inline method
32 # - Check for no assert()
33 # - Check for spaces surrounding operators
34 # - Check for 0 in pointer context (should be NULL)
35 # - Check for 0 in char context (should be '\0')
36 # - Check for camel-case method name conventions for methods
37 # that are not simple inline getters and setters
38 # - Check that base classes have virtual destructors
39 # put " // namespace" after } that closes a namespace, with
40 # namespace's name after 'namespace' if it is named.
41 # - Do not indent namespace contents
42 # - Avoid inlining non-trivial constructors in header files
43 # include base/basictypes.h if DISALLOW_EVIL_CONSTRUCTORS is used
44 # - Check for old-school (void) cast for call-sites of functions
45 # ignored return value
46 # - Check gUnit usage of anonymous namespace
47 # - Check for class declaration order (typedefs, consts, enums,
48 # ctor(s?), dtor, friend declarations, methods, member vars)
49 #
50
51 """Does google-lint on c++ files.
52
53 The goal of this script is to identify places in the code that *may*
54 be in non-compliance with google style. It does not attempt to fix
55 up these problems -- the point is to educate. It does also not
56 attempt to find all problems, or to ensure that everything it does
57 find is legitimately a problem.
58
59 In particular, we can get very confused by /* and // inside strings!
60 We do a small hack, which is to ignore //'s with "'s after them on the
61 same line, but it is far from perfect (in either direction).
62 """
63
64 import codecs
65 import getopt
66 import math # for log
67 import os
68 import re
69 import sre_compile
70 import string
71 import sys
72 import unicodedata
73
74
75 _USAGE = """
76 Syntax: cpplint.py [--verbose=#] [--output=vs7] [--filter=-x,+y,...]
77 <file> [file] ...
78
79 The style guidelines this tries to follow are those in
80 http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml
81
82 Every problem is given a confidence score from 1-5, with 5 meaning we are
83 certain of the problem, and 1 meaning it could be a legitimate construct.
84 This will miss some errors, and is not a substitute for a code review.
85
86 To prevent specific lines from being linted, add a '// NOLINT' comment to the
87 end of the line.
88
89 The files passed in will be linted; at least one file must be provided.
90 Linted extensions are .cc, .cpp, and .h. Other file types will be ignored.
91
92 Flags:
93
94 output=vs7
95 By default, the output is formatted to ease emacs parsing. Visual Studio
96 compatible output (vs7) may also be used. Other formats are unsupported.
97
98 verbose=#
99 Specify a number 0-5 to restrict errors to certain verbosity levels.
100
101 filter=-x,+y,...
102 Specify a comma-separated list of category-filters to apply: only
103 error messages whose category names pass the filters will be printed.
104 (Category names are printed with the message and look like
105 "[whitespace/indent]".) Filters are evaluated left to right.
106 "-FOO" and "FOO" means "do not print categories that start with FOO".
107 "+FOO" means "do print categories that start with FOO".
108
109 Examples: --filter=-whitespace,+whitespace/braces
110 --filter=whitespace,runtime/printf,+runtime/printf_format
111 --filter=-,+build/include_what_you_use
112
113 To see a list of all the categories used in cpplint, pass no arg:
114 --filter=
115 """
116
117 # We categorize each error message we print. Here are the categories.
118 # We want an explicit list so we can list them all in cpplint --filter=.
119 # If you add a new error message with a new category, add it to the list
120 # here! cpplint_unittest.py should tell you if you forget to do this.
121 _ERROR_CATEGORIES = """\
122 build/class
123 build/deprecated
124 build/endif_comment
125 build/forward_decl
126 build/header_guard
127 build/include
128 build/include_order
129 build/include_what_you_use
130 build/namespaces
131 build/printf_format
132 build/storage_class
133 legal/copyright
134 readability/braces
135 readability/casting
136 readability/check
137 readability/constructors
138 readability/fn_size
139 readability/function
140 readability/multiline_comment
141 readability/multiline_string
142 readability/streams
143 readability/todo
144 readability/utf8
145 runtime/arrays
146 runtime/casting
147 runtime/explicit
148 runtime/int
149 runtime/init
150 runtime/memset
151 runtime/printf
152 runtime/printf_format
153 runtime/references
154 runtime/rtti
155 runtime/sizeof
156 runtime/string
157 runtime/threadsafe_fn
158 runtime/virtual
159 whitespace/blank_line
160 whitespace/braces
161 whitespace/comma
162 whitespace/comments
163 whitespace/end_of_line
164 whitespace/ending_newline
165 whitespace/indent
166 whitespace/labels
167 whitespace/line_length
168 whitespace/newline
169 whitespace/operators
170 whitespace/parens
171 whitespace/semicolon
172 whitespace/tab
173 whitespace/todo
174 """
175
176 # We used to check for high-bit characters, but after much discussion we
177 # decided those were OK, as long as they were in UTF-8 and didn't represent
178 # hard-coded international strings, which belong in a seperate i18n file.
179
180 # Headers that we consider STL headers.
181 _STL_HEADERS = frozenset([
182 'algobase.h', 'algorithm', 'alloc.h', 'bitset', 'deque', 'exception',
183 'function.h', 'functional', 'hash_map', 'hash_map.h', 'hash_set',
184 'hash_set.h', 'iterator', 'list', 'list.h', 'map', 'memory', 'pair.h',
185 'pthread_alloc', 'queue', 'set', 'set.h', 'sstream', 'stack',
186 'stl_alloc.h', 'stl_relops.h', 'type_traits.h',
187 'utility', 'vector', 'vector.h',
188 ])
189
190
191 # Non-STL C++ system headers.
192 _CPP_HEADERS = frozenset([
193 'algo.h', 'builtinbuf.h', 'bvector.h', 'cassert', 'cctype',
194 'cerrno', 'cfloat', 'ciso646', 'climits', 'clocale', 'cmath',
195 'complex', 'complex.h', 'csetjmp', 'csignal', 'cstdarg', 'cstddef',
196 'cstdio', 'cstdlib', 'cstring', 'ctime', 'cwchar', 'cwctype',
197 'defalloc.h', 'deque.h', 'editbuf.h', 'exception', 'fstream',
198 'fstream.h', 'hashtable.h', 'heap.h', 'indstream.h', 'iomanip',
199 'iomanip.h', 'ios', 'iosfwd', 'iostream', 'iostream.h', 'istream.h',
200 'iterator.h', 'limits', 'map.h', 'multimap.h', 'multiset.h',
201 'numeric', 'ostream.h', 'parsestream.h', 'pfstream.h', 'PlotFile.h',
202 'procbuf.h', 'pthread_alloc.h', 'rope', 'rope.h', 'ropeimpl.h',
203 'SFile.h', 'slist', 'slist.h', 'stack.h', 'stdexcept',
204 'stdiostream.h', 'streambuf.h', 'stream.h', 'strfile.h', 'string',
205 'strstream', 'strstream.h', 'tempbuf.h', 'tree.h', 'typeinfo', 'valarray',
206 ])
207
208
209 # Assertion macros. These are defined in base/logging.h and
210 # testing/base/gunit.h. Note that the _M versions need to come first
211 # for substring matching to work.
212 _CHECK_MACROS = [
213 'CHECK',
214 'EXPECT_TRUE_M', 'EXPECT_TRUE',
215 'ASSERT_TRUE_M', 'ASSERT_TRUE',
216 'EXPECT_FALSE_M', 'EXPECT_FALSE',
217 'ASSERT_FALSE_M', 'ASSERT_FALSE',
218 ]
219
220 # Replacement macros for CHECK/EXPECT_TRUE/EXPECT_FALSE
221 _CHECK_REPLACEMENT = dict([(m, {}) for m in _CHECK_MACROS])
222
223 for op, replacement in [('==', 'EQ'), ('!=', 'NE'),
224 ('>=', 'GE'), ('>', 'GT'),
225 ('<=', 'LE'), ('<', 'LT')]:
226 _CHECK_REPLACEMENT['CHECK'][op] = 'CHECK_%s' % replacement
227 _CHECK_REPLACEMENT['EXPECT_TRUE'][op] = 'EXPECT_%s' % replacement
228 _CHECK_REPLACEMENT['ASSERT_TRUE'][op] = 'ASSERT_%s' % replacement
229 _CHECK_REPLACEMENT['EXPECT_TRUE_M'][op] = 'EXPECT_%s_M' % replacement
230 _CHECK_REPLACEMENT['ASSERT_TRUE_M'][op] = 'ASSERT_%s_M' % replacement
231
232 for op, inv_replacement in [('==', 'NE'), ('!=', 'EQ'),
233 ('>=', 'LT'), ('>', 'LE'),
234 ('<=', 'GT'), ('<', 'GE')]:
235 _CHECK_REPLACEMENT['EXPECT_FALSE'][op] = 'EXPECT_%s' % inv_replacement
236 _CHECK_REPLACEMENT['ASSERT_FALSE'][op] = 'ASSERT_%s' % inv_replacement
237 _CHECK_REPLACEMENT['EXPECT_FALSE_M'][op] = 'EXPECT_%s_M' % inv_replacement
238 _CHECK_REPLACEMENT['ASSERT_FALSE_M'][op] = 'ASSERT_%s_M' % inv_replacement
239
240
241 # These constants define types of headers for use with
242 # _IncludeState.CheckNextIncludeOrder().
243 _C_SYS_HEADER = 1
244 _CPP_SYS_HEADER = 2
245 _LIKELY_MY_HEADER = 3
246 _POSSIBLE_MY_HEADER = 4
247 _OTHER_HEADER = 5
248
249
250 _regexp_compile_cache = {}
251
252
253 def Match(pattern, s):
254 """Matches the string with the pattern, caching the compiled regexp."""
255 # The regexp compilation caching is inlined in both Match and Search for
256 # performance reasons; factoring it out into a separate function turns out
257 # to be noticeably expensive.
258 if not pattern in _regexp_compile_cache:
259 _regexp_compile_cache[pattern] = sre_compile.compile(pattern)
260 return _regexp_compile_cache[pattern].match(s)
261
262
263 def Search(pattern, s):
264 """Searches the string for the pattern, caching the compiled regexp."""
265 if not pattern in _regexp_compile_cache:
266 _regexp_compile_cache[pattern] = sre_compile.compile(pattern)
267 return _regexp_compile_cache[pattern].search(s)
268
269
270 class _IncludeState(dict):
271 """Tracks line numbers for includes, and the order in which includes appear.
272
273 As a dict, an _IncludeState object serves as a mapping between include
274 filename and line number on which that file was included.
275
276 Call CheckNextIncludeOrder() once for each header in the file, passing
277 in the type constants defined above. Calls in an illegal order will
278 raise an _IncludeError with an appropriate error message.
279
280 """
281 # self._section will move monotonically through this set. If it ever
282 # needs to move backwards, CheckNextIncludeOrder will raise an error.
283 _INITIAL_SECTION = 0
284 _MY_H_SECTION = 1
285 _C_SECTION = 2
286 _CPP_SECTION = 3
287 _OTHER_H_SECTION = 4
288
289 _TYPE_NAMES = {
290 _C_SYS_HEADER: 'C system header',
291 _CPP_SYS_HEADER: 'C++ system header',
292 _LIKELY_MY_HEADER: 'header this file implements',
293 _POSSIBLE_MY_HEADER: 'header this file may implement',
294 _OTHER_HEADER: 'other header',
295 }
296 _SECTION_NAMES = {
297 _INITIAL_SECTION: "... nothing. (This can't be an error.)",
298 _MY_H_SECTION: 'a header this file implements',
299 _C_SECTION: 'C system header',
300 _CPP_SECTION: 'C++ system header',
301 _OTHER_H_SECTION: 'other header',
302 }
303
304 def __init__(self):
305 dict.__init__(self)
306 self._section = self._INITIAL_SECTION
307
308 def CheckNextIncludeOrder(self, header_type):
309 """Returns a non-empty error message if the next header is out of order.
310
311 This function also updates the internal state to be ready to check
312 the next include.
313
314 Args:
315 header_type: One of the _XXX_HEADER constants defined above.
316
317 Returns:
318 The empty string if the header is in the right order, or an
319 error message describing what's wrong.
320
321 """
322 error_message = ('Found %s after %s' %
323 (self._TYPE_NAMES[header_type],
324 self._SECTION_NAMES[self._section]))
325
326 if header_type == _C_SYS_HEADER:
327 if self._section <= self._C_SECTION:
328 self._section = self._C_SECTION
329 else:
330 return error_message
331 elif header_type == _CPP_SYS_HEADER:
332 if self._section <= self._CPP_SECTION:
333 self._section = self._CPP_SECTION
334 else:
335 return error_message
336 elif header_type == _LIKELY_MY_HEADER:
337 if self._section <= self._MY_H_SECTION:
338 self._section = self._MY_H_SECTION
339 else:
340 self._section = self._OTHER_H_SECTION
341 elif header_type == _POSSIBLE_MY_HEADER:
342 if self._section <= self._MY_H_SECTION:
343 self._section = self._MY_H_SECTION
344 else:
345 # This will always be the fallback because we're not sure
346 # enough that the header is associated with this file.
347 self._section = self._OTHER_H_SECTION
348 else:
349 assert header_type == _OTHER_HEADER
350 self._section = self._OTHER_H_SECTION
351
352 return ''
353
354
355 class _CppLintState(object):
356 """Maintains module-wide state.."""
357
358 def __init__(self):
359 self.verbose_level = 1 # global setting.
360 self.error_count = 0 # global count of reported errors
361 self.filters = [] # filters to apply when emitting error messages
362
363 # output format:
364 # "emacs" - format that emacs can parse (default)
365 # "vs7" - format that Microsoft Visual Studio 7 can parse
366 self.output_format = 'emacs'
367
368 def SetOutputFormat(self, output_format):
369 """Sets the output format for errors."""
370 self.output_format = output_format
371
372 def SetVerboseLevel(self, level):
373 """Sets the module's verbosity, and returns the previous setting."""
374 last_verbose_level = self.verbose_level
375 self.verbose_level = level
376 return last_verbose_level
377
378 def SetFilters(self, filters):
379 """Sets the error-message filters.
380
381 These filters are applied when deciding whether to emit a given
382 error message.
383
384 Args:
385 filters: A string of comma-separated filters (eg "+whitespace/indent").
386 Each filter should start with + or -; else we die.
387 """
388 if not filters:
389 self.filters = []
390 else:
391 self.filters = filters.split(',')
392 for filt in self.filters:
393 if not (filt.startswith('+') or filt.startswith('-')):
394 raise ValueError('Every filter in --filters must start with + or -'
395 ' (%s does not)' % filt)
396
397 def ResetErrorCount(self):
398 """Sets the module's error statistic back to zero."""
399 self.error_count = 0
400
401 def IncrementErrorCount(self):
402 """Bumps the module's error statistic."""
403 self.error_count += 1
404
405
406 _cpplint_state = _CppLintState()
407
408
409 def _OutputFormat():
410 """Gets the module's output format."""
411 return _cpplint_state.output_format
412
413
414 def _SetOutputFormat(output_format):
415 """Sets the module's output format."""
416 _cpplint_state.SetOutputFormat(output_format)
417
418
419 def _VerboseLevel():
420 """Returns the module's verbosity setting."""
421 return _cpplint_state.verbose_level
422
423
424 def _SetVerboseLevel(level):
425 """Sets the module's verbosity, and returns the previous setting."""
426 return _cpplint_state.SetVerboseLevel(level)
427
428
429 def _Filters():
430 """Returns the module's list of output filters, as a list."""
431 return _cpplint_state.filters
432
433
434 def _SetFilters(filters):
435 """Sets the module's error-message filters.
436
437 These filters are applied when deciding whether to emit a given
438 error message.
439
440 Args:
441 filters: A string of comma-separated filters (eg "whitespace/indent").
442 Each filter should start with + or -; else we die.
443 """
444 _cpplint_state.SetFilters(filters)
445
446
447 class _FunctionState(object):
448 """Tracks current function name and the number of lines in its body."""
449
450 _NORMAL_TRIGGER = 250 # for --v=0, 500 for --v=1, etc.
451 _TEST_TRIGGER = 400 # about 50% more than _NORMAL_TRIGGER.
452
453 def __init__(self):
454 self.in_a_function = False
455 self.lines_in_function = 0
456 self.current_function = ''
457
458 def Begin(self, function_name):
459 """Start analyzing function body.
460
461 Args:
462 function_name: The name of the function being tracked.
463 """
464 self.in_a_function = True
465 self.lines_in_function = 0
466 self.current_function = function_name
467
468 def Count(self):
469 """Count line in current function body."""
470 if self.in_a_function:
471 self.lines_in_function += 1
472
473 def Check(self, error, filename, linenum):
474 """Report if too many lines in function body.
475
476 Args:
477 error: The function to call with any errors found.
478 filename: The name of the current file.
479 linenum: The number of the line to check.
480 """
481 if Match(r'T(EST|est)', self.current_function):
482 base_trigger = self._TEST_TRIGGER
483 else:
484 base_trigger = self._NORMAL_TRIGGER
485 trigger = base_trigger * 2**_VerboseLevel()
486
487 if self.lines_in_function > trigger:
488 error_level = int(math.log(self.lines_in_function / base_trigger, 2))
489 # 50 => 0, 100 => 1, 200 => 2, 400 => 3, 800 => 4, 1600 => 5, ...
490 if error_level > 5:
491 error_level = 5
492 error(filename, linenum, 'readability/fn_size', error_level,
493 'Small and focused functions are preferred:'
494 ' %s has %d non-comment lines'
495 ' (error triggered by exceeding %d lines).' % (
496 self.current_function, self.lines_in_function, trigger))
497
498 def End(self):
499 """Stop analizing function body."""
500 self.in_a_function = False
501
502
503 class _IncludeError(Exception):
504 """Indicates a problem with the include order in a file."""
505 pass
506
507
508 class FileInfo:
509 """Provides utility functions for filenames.
510
511 FileInfo provides easy access to the components of a file's path
512 relative to the project root.
513 """
514
515 def __init__(self, filename):
516 self._filename = filename
517
518 def FullName(self):
519 """Make Windows paths like Unix."""
520 return os.path.abspath(self._filename).replace('\\', '/')
521
522 def RepositoryName(self):
523 """FullName after removing the local path to the repository.
524
525 If we have a real absolute path name here we can try to do something smart:
526 detecting the root of the checkout and truncating /path/to/checkout from
527 the name so that we get header guards that don't include things like
528 "C:\Documents and Settings\..." or "/home/username/..." in them and thus
529 people on different computers who have checked the source out to different
530 locations won't see bogus errors.
531 """
532 fullname = self.FullName()
533
534 if os.path.exists(fullname):
535 project_dir = os.path.dirname(fullname)
536
537 if os.path.exists(os.path.join(project_dir, ".svn")):
538 # If there's a .svn file in the current directory, we recursively look
539 # up the directory tree for the top of the SVN checkout
540 root_dir = project_dir
541 one_up_dir = os.path.dirname(root_dir)
542 while os.path.exists(os.path.join(one_up_dir, ".svn")):
543 root_dir = os.path.dirname(root_dir)
544 one_up_dir = os.path.dirname(one_up_dir)
545
546 prefix = os.path.commonprefix([root_dir, project_dir])
547 return fullname[len(prefix) + 1:]
548
549 # Not SVN? Try to find a git top level directory by searching up from the
550 # current path.
551 root_dir = os.path.dirname(fullname)
552 while (root_dir != os.path.dirname(root_dir) and
553 not os.path.exists(os.path.join(root_dir, ".git"))):
554 root_dir = os.path.dirname(root_dir)
555 if os.path.exists(os.path.join(root_dir, ".git")):
556 prefix = os.path.commonprefix([root_dir, project_dir])
557 return fullname[len(prefix) + 1:]
558
559 # Don't know what to do; header guard warnings may be wrong...
560 return fullname
561
562 def Split(self):
563 """Splits the file into the directory, basename, and extension.
564
565 For 'chrome/browser/browser.cc', Split() would
566 return ('chrome/browser', 'browser', '.cc')
567
568 Returns:
569 A tuple of (directory, basename, extension).
570 """
571
572 googlename = self.RepositoryName()
573 project, rest = os.path.split(googlename)
574 return (project,) + os.path.splitext(rest)
575
576 def BaseName(self):
577 """File base name - text after the final slash, before the final period."""
578 return self.Split()[1]
579
580 def Extension(self):
581 """File extension - text following the final period."""
582 return self.Split()[2]
583
584 def NoExtension(self):
585 """File has no source file extension."""
586 return '/'.join(self.Split()[0:2])
587
588 def IsSource(self):
589 """File has a source file extension."""
590 return self.Extension()[1:] in ('c', 'cc', 'cpp', 'cxx')
591
592
593 def _ShouldPrintError(category, confidence):
594 """Returns true iff confidence >= verbose, and category passes filter."""
595 # There are two ways we might decide not to print an error message:
596 # the verbosity level isn't high enough, or the filters filter it out.
597 if confidence < _cpplint_state.verbose_level:
598 return False
599
600 is_filtered = False
601 for one_filter in _Filters():
602 if one_filter.startswith('-'):
603 if category.startswith(one_filter[1:]):
604 is_filtered = True
605 elif one_filter.startswith('+'):
606 if category.startswith(one_filter[1:]):
607 is_filtered = False
608 else:
609 assert False # should have been checked for in SetFilter.
610 if is_filtered:
611 return False
612
613 return True
614
615
616 def Error(filename, linenum, category, confidence, message):
617 """Logs the fact we've found a lint error.
618
619 We log where the error was found, and also our confidence in the error,
620 that is, how certain we are this is a legitimate style regression, and
621 not a misidentification or a use that's sometimes justified.
622
623 Args:
624 filename: The name of the file containing the error.
625 linenum: The number of the line containing the error.
626 category: A string used to describe the "category" this bug
627 falls under: "whitespace", say, or "runtime". Categories
628 may have a hierarchy separated by slashes: "whitespace/indent".
629 confidence: A number from 1-5 representing a confidence score for
630 the error, with 5 meaning that we are certain of the problem,
631 and 1 meaning that it could be a legitimate construct.
632 message: The error message.
633 """
634 # There are two ways we might decide not to print an error message:
635 # the verbosity level isn't high enough, or the filters filter it out.
636 if _ShouldPrintError(category, confidence):
637 _cpplint_state.IncrementErrorCount()
638 if _cpplint_state.output_format == 'vs7':
639 sys.stderr.write('%s(%s): %s [%s] [%d]\n' % (
640 filename, linenum, message, category, confidence))
641 else:
642 sys.stderr.write('%s:%s: %s [%s] [%d]\n' % (
643 filename, linenum, message, category, confidence))
644
645
646 # Matches standard C++ escape esequences per 2.13.2.3 of the C++ standard.
647 _RE_PATTERN_CLEANSE_LINE_ESCAPES = re.compile(
648 r'\\([abfnrtv?"\\\']|\d+|x[0-9a-fA-F]+)')
649 # Matches strings. Escape codes should already be removed by ESCAPES.
650 _RE_PATTERN_CLEANSE_LINE_DOUBLE_QUOTES = re.compile(r'"[^"]*"')
651 # Matches characters. Escape codes should already be removed by ESCAPES.
652 _RE_PATTERN_CLEANSE_LINE_SINGLE_QUOTES = re.compile(r"'.'")
653 # Matches multi-line C++ comments.
654 # This RE is a little bit more complicated than one might expect, because we
655 # have to take care of space removals tools so we can handle comments inside
656 # statements better.
657 # The current rule is: We only clear spaces from both sides when we're at the
658 # end of the line. Otherwise, we try to remove spaces from the right side,
659 # if this doesn't work we try on left side but only if there's a non-character
660 # on the right.
661 _RE_PATTERN_CLEANSE_LINE_C_COMMENTS = re.compile(
662 r"""(\s*/\*.*\*/\s*$|
663 /\*.*\*/\s+|
664 \s+/\*.*\*/(?=\W)|
665 /\*.*\*/)""", re.VERBOSE)
666
667
668 def IsCppString(line):
669 """Does line terminate so, that the next symbol is in string constant.
670
671 This function does not consider single-line nor multi-line comments.
672
673 Args:
674 line: is a partial line of code starting from the 0..n.
675
676 Returns:
677 True, if next character appended to 'line' is inside a
678 string constant.
679 """
680
681 line = line.replace(r'\\', 'XX') # after this, \\" does not match to \"
682 return ((line.count('"') - line.count(r'\"') - line.count("'\"'")) & 1) == 1
683
684
685 def FindNextMultiLineCommentStart(lines, lineix):
686 """Find the beginning marker for a multiline comment."""
687 while lineix < len(lines):
688 if lines[lineix].strip().startswith('/*'):
689 # Only return this marker if the comment goes beyond this line
690 if lines[lineix].strip().find('*/', 2) < 0:
691 return lineix
692 lineix += 1
693 return len(lines)
694
695
696 def FindNextMultiLineCommentEnd(lines, lineix):
697 """We are inside a comment, find the end marker."""
698 while lineix < len(lines):
699 if lines[lineix].strip().endswith('*/'):
700 return lineix
701 lineix += 1
702 return len(lines)
703
704
705 def RemoveMultiLineCommentsFromRange(lines, begin, end):
706 """Clears a range of lines for multi-line comments."""
707 # Having // dummy comments makes the lines non-empty, so we will not get
708 # unnecessary blank line warnings later in the code.
709 for i in range(begin, end):
710 lines[i] = '// dummy'
711
712
713 def RemoveMultiLineComments(filename, lines, error):
714 """Removes multiline (c-style) comments from lines."""
715 lineix = 0
716 while lineix < len(lines):
717 lineix_begin = FindNextMultiLineCommentStart(lines, lineix)
718 if lineix_begin >= len(lines):
719 return
720 lineix_end = FindNextMultiLineCommentEnd(lines, lineix_begin)
721 if lineix_end >= len(lines):
722 error(filename, lineix_begin + 1, 'readability/multiline_comment', 5,
723 'Could not find end of multi-line comment')
724 return
725 RemoveMultiLineCommentsFromRange(lines, lineix_begin, lineix_end + 1)
726 lineix = lineix_end + 1
727
728
729 def CleanseComments(line):
730 """Removes //-comments and single-line C-style /* */ comments.
731
732 Args:
733 line: A line of C++ source.
734
735 Returns:
736 The line with single-line comments removed.
737 """
738 commentpos = line.find('//')
739 if commentpos != -1 and not IsCppString(line[:commentpos]):
740 line = line[:commentpos]
741 # get rid of /* ... */
742 return _RE_PATTERN_CLEANSE_LINE_C_COMMENTS.sub('', line)
743
744
745 class CleansedLines:
746 """Holds 3 copies of all lines with different preprocessing applied to them.
747
748 1) elided member contains lines without strings and comments,
749 2) lines member contains lines without comments, and
750 3) raw member contains all the lines without processing.
751 All these three members are of <type 'list'>, and of the same length.
752 """
753
754 def __init__(self, lines):
755 self.elided = []
756 self.lines = []
757 self.raw_lines = lines
758 self.num_lines = len(lines)
759 for linenum in range(len(lines)):
760 self.lines.append(CleanseComments(lines[linenum]))
761 elided = self._CollapseStrings(lines[linenum])
762 self.elided.append(CleanseComments(elided))
763
764 def NumLines(self):
765 """Returns the number of lines represented."""
766 return self.num_lines
767
768 @staticmethod
769 def _CollapseStrings(elided):
770 """Collapses strings and chars on a line to simple "" or '' blocks.
771
772 We nix strings first so we're not fooled by text like '"http://"'
773
774 Args:
775 elided: The line being processed.
776
777 Returns:
778 The line with collapsed strings.
779 """
780 if not _RE_PATTERN_INCLUDE.match(elided):
781 # Remove escaped characters first to make quote/single quote collapsing
782 # basic. Things that look like escaped characters shouldn't occur
783 # outside of strings and chars.
784 elided = _RE_PATTERN_CLEANSE_LINE_ESCAPES.sub('', elided)
785 elided = _RE_PATTERN_CLEANSE_LINE_SINGLE_QUOTES.sub("''", elided)
786 elided = _RE_PATTERN_CLEANSE_LINE_DOUBLE_QUOTES.sub('""', elided)
787 return elided
788
789
790 def CloseExpression(clean_lines, linenum, pos):
791 """If input points to ( or { or [, finds the position that closes it.
792
793 If lines[linenum][pos] points to a '(' or '{' or '[', finds the the
794 linenum/pos that correspond to the closing of the expression.
795
796 Args:
797 clean_lines: A CleansedLines instance containing the file.
798 linenum: The number of the line to check.
799 pos: A position on the line.
800
801 Returns:
802 A tuple (line, linenum, pos) pointer *past* the closing brace, or
803 (line, len(lines), -1) if we never find a close. Note we ignore
804 strings and comments when matching; and the line we return is the
805 'cleansed' line at linenum.
806 """
807
808 line = clean_lines.elided[linenum]
809 startchar = line[pos]
810 if startchar not in '({[':
811 return (line, clean_lines.NumLines(), -1)
812 if startchar == '(': endchar = ')'
813 if startchar == '[': endchar = ']'
814 if startchar == '{': endchar = '}'
815
816 num_open = line.count(startchar) - line.count(endchar)
817 while linenum < clean_lines.NumLines() and num_open > 0:
818 linenum += 1
819 line = clean_lines.elided[linenum]
820 num_open += line.count(startchar) - line.count(endchar)
821 # OK, now find the endchar that actually got us back to even
822 endpos = len(line)
823 while num_open >= 0:
824 endpos = line.rfind(')', 0, endpos)
825 num_open -= 1 # chopped off another )
826 return (line, linenum, endpos + 1)
827
828
829 def CheckForCopyright(filename, lines, error):
830 """Logs an error if no Copyright message appears at the top of the file."""
831
832 # We'll say it should occur by line 10. Don't forget there's a
833 # dummy line at the front.
834 for line in xrange(1, min(len(lines), 11)):
835 if re.search(r'Copyright', lines[line], re.I): break
836 else: # means no copyright line was found
837 error(filename, 0, 'legal/copyright', 5,
838 'No copyright message found. '
839 'You should have a line: "Copyright [year] <Copyright Owner>"')
840
841
842 def GetHeaderGuardCPPVariable(filename):
843 """Returns the CPP variable that should be used as a header guard.
844
845 Args:
846 filename: The name of a C++ header file.
847
848 Returns:
849 The CPP variable that should be used as a header guard in the
850 named file.
851
852 """
853
854 fileinfo = FileInfo(filename)
855 return re.sub(r'[-./\s]', '_', fileinfo.RepositoryName()).upper() + '_'
856
857
858 def CheckForHeaderGuard(filename, lines, error):
859 """Checks that the file contains a header guard.
860
861 Logs an error if no #ifndef header guard is present. For google3
862 headers, checks that the full pathname is used.
863
864 Args:
865 filename: The name of the C++ header file.
866 lines: An array of strings, each representing a line of the file.
867 error: The function to call with any errors found.
868 """
869
870 cppvar = GetHeaderGuardCPPVariable(filename)
871
872 ifndef = None
873 ifndef_linenum = 0
874 define = None
875 endif = None
876 endif_linenum = 0
877 for linenum, line in enumerate(lines):
878 linesplit = line.split()
879 if len(linesplit) >= 2:
880 # find the first occurrence of #ifndef and #define, save arg
881 if not ifndef and linesplit[0] == '#ifndef':
882 # set ifndef to the header guard presented on the #ifndef line.
883 ifndef = linesplit[1]
884 ifndef_linenum = linenum
885 if not define and linesplit[0] == '#define':
886 define = linesplit[1]
887 # find the last occurrence of #endif, save entire line
888 if line.startswith('#endif'):
889 endif = line
890 endif_linenum = linenum
891
892 if not ifndef or not define or ifndef != define:
893 error(filename, 0, 'build/header_guard', 5,
894 'No #ifndef header guard found, suggested CPP variable is: %s' %
895 cppvar)
896 return
897
898 # The guard should be PATH_FILE_H_, but we also allow PATH_FILE_H__
899 # for backward compatibility.
900 if ifndef != cppvar:
901 error_level = 0
902 if ifndef != cppvar + '_':
903 error_level = 5
904
905 error(filename, ifndef_linenum, 'build/header_guard', error_level,
906 '#ifndef header guard has wrong style, please use: %s' % cppvar)
907
908 if endif != ('#endif // %s' % cppvar):
909 error_level = 0
910 if endif != ('#endif // %s' % (cppvar + '_')):
911 error_level = 5
912
913 error(filename, endif_linenum, 'build/header_guard', error_level,
914 '#endif line should be "#endif // %s"' % cppvar)
915
916
917 def CheckForUnicodeReplacementCharacters(filename, lines, error):
918 """Logs an error for each line containing Unicode replacement characters.
919
920 These indicate that either the file contained invalid UTF-8 (likely)
921 or Unicode replacement characters (which it shouldn't). Note that
922 it's possible for this to throw off line numbering if the invalid
923 UTF-8 occurred adjacent to a newline.
924
925 Args:
926 filename: The name of the current file.
927 lines: An array of strings, each representing a line of the file.
928 error: The function to call with any errors found.
929 """
930 for linenum, line in enumerate(lines):
931 if u'\ufffd' in line:
932 error(filename, linenum, 'readability/utf8', 5,
933 'Line contains invalid UTF-8 (or Unicode replacement character).')
934
935
936 def CheckForNewlineAtEOF(filename, lines, error):
937 """Logs an error if there is no newline char at the end of the file.
938
939 Args:
940 filename: The name of the current file.
941 lines: An array of strings, each representing a line of the file.
942 error: The function to call with any errors found.
943 """
944
945 # The array lines() was created by adding two newlines to the
946 # original file (go figure), then splitting on \n.
947 # To verify that the file ends in \n, we just have to make sure the
948 # last-but-two element of lines() exists and is empty.
949 if len(lines) < 3 or lines[-2]:
950 error(filename, len(lines) - 2, 'whitespace/ending_newline', 5,
951 'Could not find a newline character at the end of the file.')
952
953
954 def CheckForMultilineCommentsAndStrings(filename, clean_lines, linenum, error):
955 """Logs an error if we see /* ... */ or "..." that extend past one line.
956
957 /* ... */ comments are legit inside macros, for one line.
958 Otherwise, we prefer // comments, so it's ok to warn about the
959 other. Likewise, it's ok for strings to extend across multiple
960 lines, as long as a line continuation character (backslash)
961 terminates each line. Although not currently prohibited by the C++
962 style guide, it's ugly and unnecessary. We don't do well with either
963 in this lint program, so we warn about both.
964
965 Args:
966 filename: The name of the current file.
967 clean_lines: A CleansedLines instance containing the file.
968 linenum: The number of the line to check.
969 error: The function to call with any errors found.
970 """
971 line = clean_lines.elided[linenum]
972
973 # Remove all \\ (escaped backslashes) from the line. They are OK, and the
974 # second (escaped) slash may trigger later \" detection erroneously.
975 line = line.replace('\\\\', '')
976
977 if line.count('/*') > line.count('*/'):
978 error(filename, linenum, 'readability/multiline_comment', 5,
979 'Complex multi-line /*...*/-style comment found. '
980 'Lint may give bogus warnings. '
981 'Consider replacing these with //-style comments, '
982 'with #if 0...#endif, '
983 'or with more clearly structured multi-line comments.')
984
985 if (line.count('"') - line.count('\\"')) % 2:
986 error(filename, linenum, 'readability/multiline_string', 5,
987 'Multi-line string ("...") found. This lint script doesn\'t '
988 'do well with such strings, and may give bogus warnings. They\'re '
989 'ugly and unnecessary, and you should use concatenation instead".')
990
991
992 threading_list = (
993 ('asctime(', 'asctime_r('),
994 ('ctime(', 'ctime_r('),
995 ('getgrgid(', 'getgrgid_r('),
996 ('getgrnam(', 'getgrnam_r('),
997 ('getlogin(', 'getlogin_r('),
998 ('getpwnam(', 'getpwnam_r('),
999 ('getpwuid(', 'getpwuid_r('),
1000 ('gmtime(', 'gmtime_r('),
1001 ('localtime(', 'localtime_r('),
1002 ('rand(', 'rand_r('),
1003 ('readdir(', 'readdir_r('),
1004 ('strtok(', 'strtok_r('),
1005 ('ttyname(', 'ttyname_r('),
1006 )
1007
1008
1009 def CheckPosixThreading(filename, clean_lines, linenum, error):
1010 """Checks for calls to thread-unsafe functions.
1011
1012 Much code has been originally written without consideration of
1013 multi-threading. Also, engineers are relying on their old experience;
1014 they have learned posix before threading extensions were added. These
1015 tests guide the engineers to use thread-safe functions (when using
1016 posix directly).
1017
1018 Args:
1019 filename: The name of the current file.
1020 clean_lines: A CleansedLines instance containing the file.
1021 linenum: The number of the line to check.
1022 error: The function to call with any errors found.
1023 """
1024 line = clean_lines.elided[linenum]
1025 for single_thread_function, multithread_safe_function in threading_list:
1026 ix = line.find(single_thread_function)
1027 if ix >= 0 and (ix == 0 or (not line[ix - 1].isalnum() and
1028 line[ix - 1] not in ('_', '.', '>'))):
1029 error(filename, linenum, 'runtime/threadsafe_fn', 2,
1030 'Consider using ' + multithread_safe_function +
1031 '...) instead of ' + single_thread_function +
1032 '...) for improved thread safety.')
1033
1034
1035 class _ClassInfo(object):
1036 """Stores information about a class."""
1037
1038 def __init__(self, name, linenum):
1039 self.name = name
1040 self.linenum = linenum
1041 self.seen_open_brace = False
1042 self.is_derived = False
1043 self.virtual_method_linenumber = None
1044 self.has_virtual_destructor = False
1045 self.brace_depth = 0
1046
1047
1048 class _ClassState(object):
1049 """Holds the current state of the parse relating to class declarations.
1050
1051 It maintains a stack of _ClassInfos representing the parser's guess
1052 as to the current nesting of class declarations. The innermost class
1053 is at the top (back) of the stack. Typically, the stack will either
1054 be empty or have exactly one entry.
1055 """
1056
1057 def __init__(self):
1058 self.classinfo_stack = []
1059
1060 def CheckFinished(self, filename, error):
1061 """Checks that all classes have been completely parsed.
1062
1063 Call this when all lines in a file have been processed.
1064 Args:
1065 filename: The name of the current file.
1066 error: The function to call with any errors found.
1067 """
1068 if self.classinfo_stack:
1069 # Note: This test can result in false positives if #ifdef constructs
1070 # get in the way of brace matching. See the testBuildClass test in
1071 # cpplint_unittest.py for an example of this.
1072 error(filename, self.classinfo_stack[0].linenum, 'build/class', 5,
1073 'Failed to find complete declaration of class %s' %
1074 self.classinfo_stack[0].name)
1075
1076
1077 def CheckForNonStandardConstructs(filename, clean_lines, linenum,
1078 class_state, error):
1079 """Logs an error if we see certain non-ANSI constructs ignored by gcc-2.
1080
1081 Complain about several constructs which gcc-2 accepts, but which are
1082 not standard C++. Warning about these in lint is one way to ease the
1083 transition to new compilers.
1084 - put storage class first (e.g. "static const" instead of "const static").
1085 - "%lld" instead of %qd" in printf-type functions.
1086 - "%1$d" is non-standard in printf-type functions.
1087 - "\%" is an undefined character escape sequence.
1088 - text after #endif is not allowed.
1089 - invalid inner-style forward declaration.
1090 - >? and <? operators, and their >?= and <?= cousins.
1091 - classes with virtual methods need virtual destructors (compiler warning
1092 available, but not turned on yet.)
1093
1094 Additionally, check for constructor/destructor style violations as it
1095 is very convenient to do so while checking for gcc-2 compliance.
1096
1097 Args:
1098 filename: The name of the current file.
1099 clean_lines: A CleansedLines instance containing the file.
1100 linenum: The number of the line to check.
1101 class_state: A _ClassState instance which maintains information about
1102 the current stack of nested class declarations being parsed.
1103 error: A callable to which errors are reported, which takes 4 arguments:
1104 filename, line number, error level, and message
1105 """
1106
1107 # Remove comments from the line, but leave in strings for now.
1108 line = clean_lines.lines[linenum]
1109
1110 if Search(r'printf\s*\(.*".*%[-+ ]?\d*q', line):
1111 error(filename, linenum, 'runtime/printf_format', 3,
1112 '%q in format strings is deprecated. Use %ll instead.')
1113
1114 if Search(r'printf\s*\(.*".*%\d+\$', line):
1115 error(filename, linenum, 'runtime/printf_format', 2,
1116 '%N$ formats are unconventional. Try rewriting to avoid them.')
1117
1118 # Remove escaped backslashes before looking for undefined escapes.
1119 line = line.replace('\\\\', '')
1120
1121 if Search(r'("|\').*\\(%|\[|\(|{)', line):
1122 error(filename, linenum, 'build/printf_format', 3,
1123 '%, [, (, and { are undefined character escapes. Unescape them.')
1124
1125 # For the rest, work with both comments and strings removed.
1126 line = clean_lines.elided[linenum]
1127
1128 if Search(r'\b(const|volatile|void|char|short|int|long'
1129 r'|float|double|signed|unsigned'
1130 r'|schar|u?int8|u?int16|u?int32|u?int64)'
1131 r'\s+(auto|register|static|extern|typedef)\b',
1132 line):
1133 error(filename, linenum, 'build/storage_class', 5,
1134 'Storage class (static, extern, typedef, etc) should be first.')
1135
1136 if Match(r'\s*#\s*endif\s*[^/\s]+', line):
1137 error(filename, linenum, 'build/endif_comment', 5,
1138 'Uncommented text after #endif is non-standard. Use a comment.')
1139
1140 if Match(r'\s*class\s+(\w+\s*::\s*)+\w+\s*;', line):
1141 error(filename, linenum, 'build/forward_decl', 5,
1142 'Inner-style forward declarations are invalid. Remove this line.')
1143
1144 if Search(r'(\w+|[+-]?\d+(\.\d*)?)\s*(<|>)\?=?\s*(\w+|[+-]?\d+)(\.\d*)?',
1145 line):
1146 error(filename, linenum, 'build/deprecated', 3,
1147 '>? and <? (max and min) operators are non-standard and deprecated.')
1148
1149 # Track class entry and exit, and attempt to find cases within the
1150 # class declaration that don't meet the C++ style
1151 # guidelines. Tracking is very dependent on the code matching Google
1152 # style guidelines, but it seems to perform well enough in testing
1153 # to be a worthwhile addition to the checks.
1154 classinfo_stack = class_state.classinfo_stack
1155 # Look for a class declaration
1156 class_decl_match = Match(
1157 r'\s*(template\s*<[\w\s<>,:]*>\s*)?(class|struct)\s+(\w+(::\w+)*)', line)
1158 if class_decl_match:
1159 classinfo_stack.append(_ClassInfo(class_decl_match.group(3), linenum))
1160
1161 # Everything else in this function uses the top of the stack if it's
1162 # not empty.
1163 if not classinfo_stack:
1164 return
1165
1166 classinfo = classinfo_stack[-1]
1167
1168 # If the opening brace hasn't been seen look for it and also
1169 # parent class declarations.
1170 if not classinfo.seen_open_brace:
1171 # If the line has a ';' in it, assume it's a forward declaration or
1172 # a single-line class declaration, which we won't process.
1173 if line.find(';') != -1:
1174 classinfo_stack.pop()
1175 return
1176 classinfo.seen_open_brace = (line.find('{') != -1)
1177 # Look for a bare ':'
1178 if Search('(^|[^:]):($|[^:])', line):
1179 classinfo.is_derived = True
1180 if not classinfo.seen_open_brace:
1181 return # Everything else in this function is for after open brace
1182
1183 # The class may have been declared with namespace or classname qualifiers.
1184 # The constructor and destructor will not have those qualifiers.
1185 base_classname = classinfo.name.split('::')[-1]
1186
1187 # Look for single-argument constructors that aren't marked explicit.
1188 # Technically a valid construct, but against style.
1189 args = Match(r'(?<!explicit)\s+%s\s*\(([^,()]+)\)'
1190 % re.escape(base_classname),
1191 line)
1192 if (args and
1193 args.group(1) != 'void' and
1194 not Match(r'(const\s+)?%s\s*&' % re.escape(base_classname),
1195 args.group(1).strip())):
1196 error(filename, linenum, 'runtime/explicit', 5,
1197 'Single-argument constructors should be marked explicit.')
1198
1199 # Look for methods declared virtual.
1200 if Search(r'\bvirtual\b', line):
1201 classinfo.virtual_method_linenumber = linenum
1202 # Only look for a destructor declaration on the same line. It would
1203 # be extremely unlikely for the destructor declaration to occupy
1204 # more than one line.
1205 if Search(r'~%s\s*\(' % base_classname, line):
1206 classinfo.has_virtual_destructor = True
1207
1208 # Look for class end.
1209 brace_depth = classinfo.brace_depth
1210 brace_depth = brace_depth + line.count('{') - line.count('}')
1211 if brace_depth <= 0:
1212 classinfo = classinfo_stack.pop()
1213 # Try to detect missing virtual destructor declarations.
1214 # For now, only warn if a non-derived class with virtual methods lacks
1215 # a virtual destructor. This is to make it less likely that people will
1216 # declare derived virtual destructors without declaring the base
1217 # destructor virtual.
1218 if ((classinfo.virtual_method_linenumber is not None) and
1219 (not classinfo.has_virtual_destructor) and
1220 (not classinfo.is_derived)): # Only warn for base classes
1221 error(filename, classinfo.linenum, 'runtime/virtual', 4,
1222 'The class %s probably needs a virtual destructor due to '
1223 'having virtual method(s), one declared at line %d.'
1224 % (classinfo.name, classinfo.virtual_method_linenumber))
1225 else:
1226 classinfo.brace_depth = brace_depth
1227
1228
1229 def CheckSpacingForFunctionCall(filename, line, linenum, error):
1230 """Checks for the correctness of various spacing around function calls.
1231
1232 Args:
1233 filename: The name of the current file.
1234 line: The text of the line to check.
1235 linenum: The number of the line to check.
1236 error: The function to call with any errors found.
1237 """
1238
1239 # Since function calls often occur inside if/for/while/switch
1240 # expressions - which have their own, more liberal conventions - we
1241 # first see if we should be looking inside such an expression for a
1242 # function call, to which we can apply more strict standards.
1243 fncall = line # if there's no control flow construct, look at whole line
1244 for pattern in (r'\bif\s*\((.*)\)\s*{',
1245 r'\bfor\s*\((.*)\)\s*{',
1246 r'\bwhile\s*\((.*)\)\s*[{;]',
1247 r'\bswitch\s*\((.*)\)\s*{'):
1248 match = Search(pattern, line)
1249 if match:
1250 fncall = match.group(1) # look inside the parens for function calls
1251 break
1252
1253 # Except in if/for/while/switch, there should never be space
1254 # immediately inside parens (eg "f( 3, 4 )"). We make an exception
1255 # for nested parens ( (a+b) + c ). Likewise, there should never be
1256 # a space before a ( when it's a function argument. I assume it's a
1257 # function argument when the char before the whitespace is legal in
1258 # a function name (alnum + _) and we're not starting a macro. Also ignore
1259 # pointers and references to arrays and functions coz they're too tricky:
1260 # we use a very simple way to recognize these:
1261 # " (something)(maybe-something)" or
1262 # " (something)(maybe-something," or
1263 # " (something)[something]"
1264 # Note that we assume the contents of [] to be short enough that
1265 # they'll never need to wrap.
1266 if ( # Ignore control structures.
1267 not Search(r'\b(if|for|while|switch|return|delete)\b', fncall) and
1268 # Ignore pointers/references to functions.
1269 not Search(r' \([^)]+\)\([^)]*(\)|,$)', fncall) and
1270 # Ignore pointers/references to arrays.
1271 not Search(r' \([^)]+\)\[[^\]]+\]', fncall)):
1272 if Search(r'\w\s*\(\s', fncall): # a ( used for a fn call
1273 error(filename, linenum, 'whitespace/parens', 4,
1274 'Extra space after ( in function call')
1275 elif Search(r'\(\s+[^(]', fncall):
1276 error(filename, linenum, 'whitespace/parens', 2,
1277 'Extra space after (')
1278 if (Search(r'\w\s+\(', fncall) and
1279 not Search(r'#\s*define|typedef', fncall)):
1280 error(filename, linenum, 'whitespace/parens', 4,
1281 'Extra space before ( in function call')
1282 # If the ) is followed only by a newline or a { + newline, assume it's
1283 # part of a control statement (if/while/etc), and don't complain
1284 if Search(r'[^)]\s+\)\s*[^{\s]', fncall):
1285 error(filename, linenum, 'whitespace/parens', 2,
1286 'Extra space before )')
1287
1288
1289 def IsBlankLine(line):
1290 """Returns true if the given line is blank.
1291
1292 We consider a line to be blank if the line is empty or consists of
1293 only white spaces.
1294
1295 Args:
1296 line: A line of a string.
1297
1298 Returns:
1299 True, if the given line is blank.
1300 """
1301 return not line or line.isspace()
1302
1303
1304 def CheckForFunctionLengths(filename, clean_lines, linenum,
1305 function_state, error):
1306 """Reports for long function bodies.
1307
1308 For an overview why this is done, see:
1309 http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Write_Short_Fun ctions
1310
1311 Uses a simplistic algorithm assuming other style guidelines
1312 (especially spacing) are followed.
1313 Only checks unindented functions, so class members are unchecked.
1314 Trivial bodies are unchecked, so constructors with huge initializer lists
1315 may be missed.
1316 Blank/comment lines are not counted so as to avoid encouraging the removal
1317 of vertical space and commments just to get through a lint check.
1318 NOLINT *on the last line of a function* disables this check.
1319
1320 Args:
1321 filename: The name of the current file.
1322 clean_lines: A CleansedLines instance containing the file.
1323 linenum: The number of the line to check.
1324 function_state: Current function name and lines in body so far.
1325 error: The function to call with any errors found.
1326 """
1327 lines = clean_lines.lines
1328 line = lines[linenum]
1329 raw = clean_lines.raw_lines
1330 raw_line = raw[linenum]
1331 joined_line = ''
1332
1333 starting_func = False
1334 regexp = r'(\w(\w|::|\*|\&|\s)*)\(' # decls * & space::name( ...
1335 match_result = Match(regexp, line)
1336 if match_result:
1337 # If the name is all caps and underscores, figure it's a macro and
1338 # ignore it, unless it's TEST or TEST_F.
1339 function_name = match_result.group(1).split()[-1]
1340 if function_name == 'TEST' or function_name == 'TEST_F' or (
1341 not Match(r'[A-Z_]+$', function_name)):
1342 starting_func = True
1343
1344 if starting_func:
1345 body_found = False
1346 # Don't look too far for the function body. Lint might be mistaken about
1347 # whether it's a function definition.
1348 for start_linenum in xrange(linenum,
1349 min(linenum+100, clean_lines.NumLines())):
1350 start_line = lines[start_linenum]
1351 joined_line += ' ' + start_line.lstrip()
1352 if Search(r'(;|})', start_line): # Declarations and trivial functions
1353 body_found = True
1354 break # ... ignore
1355 elif Search(r'{', start_line):
1356 body_found = True
1357 function = Search(r'((\w|:)*)\(', line).group(1)
1358 if Match(r'TEST', function): # Handle TEST... macros
1359 parameter_regexp = Search(r'(\(.*\))', joined_line)
1360 if parameter_regexp: # Ignore bad syntax
1361 function += parameter_regexp.group(1)
1362 else:
1363 function += '()'
1364 function_state.Begin(function)
1365 break
1366 if not body_found:
1367 # 50 lines after finding a line deemed to start a function
1368 # definition, no body for the function was found. A macro
1369 # invocation with no terminating semicolon could trigger this.
1370 error(filename, linenum, 'readability/fn_size', 5,
1371 'Lint failed to find start of function body.')
1372 elif Match(r'^\}\s*$', line): # function end
1373 if not Search(r'\bNOLINT\b', raw_line):
1374 function_state.Check(error, filename, linenum)
1375 function_state.End()
1376 elif not Match(r'^\s*$', line):
1377 function_state.Count() # Count non-blank/non-comment lines.
1378
1379
1380 _RE_PATTERN_TODO = re.compile(r'^//(\s*)TODO(\(.+?\))?:?(\s|$)?')
1381
1382
1383 def CheckComment(comment, filename, linenum, error):
1384 """Checks for common mistakes in TODO comments.
1385
1386 Args:
1387 comment: The text of the comment from the line in question.
1388 filename: The name of the current file.
1389 linenum: The number of the line to check.
1390 error: The function to call with any errors found.
1391 """
1392 match = _RE_PATTERN_TODO.match(comment)
1393 if match:
1394 # One whitespace is correct; zero whitespace is handled elsewhere.
1395 leading_whitespace = match.group(1)
1396 if len(leading_whitespace) > 1:
1397 error(filename, linenum, 'whitespace/todo', 2,
1398 'Too many spaces before TODO')
1399
1400 username = match.group(2)
1401 if not username:
1402 error(filename, linenum, 'readability/todo', 2,
1403 'Missing username in TODO; it should look like '
1404 '"// TODO(my_username): Stuff."')
1405
1406 middle_whitespace = match.group(3)
1407 if middle_whitespace != ' ' and middle_whitespace != '':
1408 error(filename, linenum, 'whitespace/todo', 2,
1409 'TODO(my_username) should be followed by a space')
1410
1411
1412 def CheckSpacing(filename, clean_lines, linenum, error):
1413 """Checks for the correctness of various spacing issues in the code.
1414
1415 Things we check for: spaces around operators, spaces after
1416 if/for/while/switch, no spaces around parens in function calls, two
1417 spaces between code and comment, don't start a block with a blank
1418 line, don't end a function with a blank line, don't have too many
1419 blank lines in a row.
1420
1421 Args:
1422 filename: The name of the current file.
1423 clean_lines: A CleansedLines instance containing the file.
1424 linenum: The number of the line to check.
1425 error: The function to call with any errors found.
1426 """
1427
1428 raw = clean_lines.raw_lines
1429 line = raw[linenum]
1430
1431 # Before nixing comments, check if the line is blank for no good
1432 # reason. This includes the first line after a block is opened, and
1433 # blank lines at the end of a function (ie, right before a line like '}'
1434 if IsBlankLine(line):
1435 elided = clean_lines.elided
1436 prev_line = elided[linenum - 1]
1437 prevbrace = prev_line.rfind('{')
1438 # TODO(unknown): Don't complain if line before blank line, and line after,
1439 # both start with alnums and are indented the same amount.
1440 # This ignores whitespace at the start of a namespace block
1441 # because those are not usually indented.
1442 if (prevbrace != -1 and prev_line[prevbrace:].find('}') == -1
1443 and prev_line[:prevbrace].find('namespace') == -1):
1444 # OK, we have a blank line at the start of a code block. Before we
1445 # complain, we check if it is an exception to the rule: The previous
1446 # non-empty line has the paramters of a function header that are indented
1447 # 4 spaces (because they did not fit in a 80 column line when placed on
1448 # the same line as the function name). We also check for the case where
1449 # the previous line is indented 6 spaces, which may happen when the
1450 # initializers of a constructor do not fit into a 80 column line.
1451 exception = False
1452 if Match(r' {6}\w', prev_line): # Initializer list?
1453 # We are looking for the opening column of initializer list, which
1454 # should be indented 4 spaces to cause 6 space indentation afterwards.
1455 search_position = linenum-2
1456 while (search_position >= 0
1457 and Match(r' {6}\w', elided[search_position])):
1458 search_position -= 1
1459 exception = (search_position >= 0
1460 and elided[search_position][:5] == ' :')
1461 else:
1462 # Search for the function arguments or an initializer list. We use a
1463 # simple heuristic here: If the line is indented 4 spaces; and we have a
1464 # closing paren, without the opening paren, followed by an opening brace
1465 # or colon (for initializer lists) we assume that it is the last line of
1466 # a function header. If we have a colon indented 4 spaces, it is an
1467 # initializer list.
1468 exception = (Match(r' {4}\w[^\(]*\)\s*(const\s*)?(\{\s*$|:)',
1469 prev_line)
1470 or Match(r' {4}:', prev_line))
1471
1472 if not exception:
1473 error(filename, linenum, 'whitespace/blank_line', 2,
1474 'Blank line at the start of a code block. Is this needed?')
1475 # This doesn't ignore whitespace at the end of a namespace block
1476 # because that is too hard without pairing open/close braces;
1477 # however, a special exception is made for namespace closing
1478 # brackets which have a comment containing "namespace".
1479 #
1480 # Also, ignore blank lines at the end of a block in a long if-else
1481 # chain, like this:
1482 # if (condition1) {
1483 # // Something followed by a blank line
1484 #
1485 # } else if (condition2) {
1486 # // Something else
1487 # }
1488 if linenum + 1 < clean_lines.NumLines():
1489 next_line = raw[linenum + 1]
1490 if (next_line
1491 and Match(r'\s*}', next_line)
1492 and next_line.find('namespace') == -1
1493 and next_line.find('} else ') == -1):
1494 error(filename, linenum, 'whitespace/blank_line', 3,
1495 'Blank line at the end of a code block. Is this needed?')
1496
1497 # Next, we complain if there's a comment too near the text
1498 commentpos = line.find('//')
1499 if commentpos != -1:
1500 # Check if the // may be in quotes. If so, ignore it
1501 if (line.count('"', 0, commentpos) -
1502 line.count('\\"', 0, commentpos)) % 2 == 0: # not in quotes
1503 # Allow one space for new scopes, two spaces otherwise:
1504 if (not Match(r'^\s*{ //', line) and
1505 ((commentpos >= 1 and
1506 line[commentpos-1] not in string.whitespace) or
1507 (commentpos >= 2 and
1508 line[commentpos-2] not in string.whitespace))):
1509 error(filename, linenum, 'whitespace/comments', 2,
1510 'At least two spaces is best between code and comments')
1511 # There should always be a space between the // and the comment
1512 commentend = commentpos + 2
1513 if commentend < len(line) and not line[commentend] == ' ':
1514 # but some lines are exceptions -- e.g. if they're big
1515 # comment delimiters like:
1516 # //----------------------------------------------------------
1517 match = Search(r'[=/-]{4,}\s*$', line[commentend:])
1518 if not match:
1519 error(filename, linenum, 'whitespace/comments', 4,
1520 'Should have a space between // and comment')
1521 CheckComment(line[commentpos:], filename, linenum, error)
1522
1523 line = clean_lines.elided[linenum] # get rid of comments and strings
1524
1525 # Don't try to do spacing checks for operator methods
1526 line = re.sub(r'operator(==|!=|<|<<|<=|>=|>>|>)\(', 'operator\(', line)
1527
1528 # We allow no-spaces around = within an if: "if ( (a=Foo()) == 0 )".
1529 # Otherwise not. Note we only check for non-spaces on *both* sides;
1530 # sometimes people put non-spaces on one side when aligning ='s among
1531 # many lines (not that this is behavior that I approve of...)
1532 if Search(r'[\w.]=[\w.]', line) and not Search(r'\b(if|while) ', line):
1533 error(filename, linenum, 'whitespace/operators', 4,
1534 'Missing spaces around =')
1535
1536 # It's ok not to have spaces around binary operators like + - * /, but if
1537 # there's too little whitespace, we get concerned. It's hard to tell,
1538 # though, so we punt on this one for now. TODO.
1539
1540 # You should always have whitespace around binary operators.
1541 # Alas, we can't test < or > because they're legitimately used sans spaces
1542 # (a->b, vector<int> a). The only time we can tell is a < with no >, and
1543 # only if it's not template params list spilling into the next line.
1544 match = Search(r'[^<>=!\s](==|!=|<=|>=)[^<>=!\s]', line)
1545 if not match:
1546 # Note that while it seems that the '<[^<]*' term in the following
1547 # regexp could be simplified to '<.*', which would indeed match
1548 # the same class of strings, the [^<] means that searching for the
1549 # regexp takes linear rather than quadratic time.
1550 if not Search(r'<[^<]*,\s*$', line): # template params spill
1551 match = Search(r'[^<>=!\s](<)[^<>=!\s]([^>]|->)*$', line)
1552 if match:
1553 error(filename, linenum, 'whitespace/operators', 3,
1554 'Missing spaces around %s' % match.group(1))
1555 # We allow no-spaces around << and >> when used like this: 10<<20, but
1556 # not otherwise (particularly, not when used as streams)
1557 match = Search(r'[^0-9\s](<<|>>)[^0-9\s]', line)
1558 if match:
1559 error(filename, linenum, 'whitespace/operators', 3,
1560 'Missing spaces around %s' % match.group(1))
1561
1562 # There shouldn't be space around unary operators
1563 match = Search(r'(!\s|~\s|[\s]--[\s;]|[\s]\+\+[\s;])', line)
1564 if match:
1565 error(filename, linenum, 'whitespace/operators', 4,
1566 'Extra space for operator %s' % match.group(1))
1567
1568 # A pet peeve of mine: no spaces after an if, while, switch, or for
1569 match = Search(r' (if\(|for\(|while\(|switch\()', line)
1570 if match:
1571 error(filename, linenum, 'whitespace/parens', 5,
1572 'Missing space before ( in %s' % match.group(1))
1573
1574 # For if/for/while/switch, the left and right parens should be
1575 # consistent about how many spaces are inside the parens, and
1576 # there should either be zero or one spaces inside the parens.
1577 # We don't want: "if ( foo)" or "if ( foo )".
1578 # Exception: "for ( ; foo; bar)" is allowed.
1579 match = Search(r'\b(if|for|while|switch)\s*'
1580 r'\(([ ]*)(.).*[^ ]+([ ]*)\)\s*{\s*$',
1581 line)
1582 if match:
1583 if len(match.group(2)) != len(match.group(4)):
1584 if not (match.group(3) == ';' and
1585 len(match.group(2)) == 1 + len(match.group(4))):
1586 error(filename, linenum, 'whitespace/parens', 5,
1587 'Mismatching spaces inside () in %s' % match.group(1))
1588 if not len(match.group(2)) in [0, 1]:
1589 error(filename, linenum, 'whitespace/parens', 5,
1590 'Should have zero or one spaces inside ( and ) in %s' %
1591 match.group(1))
1592
1593 # You should always have a space after a comma (either as fn arg or operator)
1594 if Search(r',[^\s]', line):
1595 error(filename, linenum, 'whitespace/comma', 3,
1596 'Missing space after ,')
1597
1598 # Next we will look for issues with function calls.
1599 CheckSpacingForFunctionCall(filename, line, linenum, error)
1600
1601 # Except after an opening paren, you should have spaces before your braces.
1602 # And since you should never have braces at the beginning of a line, this is
1603 # an easy test.
1604 if Search(r'[^ (]{', line):
1605 error(filename, linenum, 'whitespace/braces', 5,
1606 'Missing space before {')
1607
1608 # Make sure '} else {' has spaces.
1609 if Search(r'}else', line):
1610 error(filename, linenum, 'whitespace/braces', 5,
1611 'Missing space before else')
1612
1613 # You shouldn't have spaces before your brackets, except maybe after
1614 # 'delete []' or 'new char * []'.
1615 if Search(r'\w\s+\[', line) and not Search(r'delete\s+\[', line):
1616 error(filename, linenum, 'whitespace/braces', 5,
1617 'Extra space before [')
1618
1619 # You shouldn't have a space before a semicolon at the end of the line.
1620 # There's a special case for "for" since the style guide allows space before
1621 # the semicolon there.
1622 if Search(r':\s*;\s*$', line):
1623 error(filename, linenum, 'whitespace/semicolon', 5,
1624 'Semicolon defining empty statement. Use { } instead.')
1625 elif Search(r'^\s*;\s*$', line):
1626 error(filename, linenum, 'whitespace/semicolon', 5,
1627 'Line contains only semicolon. If this should be an empty statement, '
1628 'use { } instead.')
1629 elif (Search(r'\s+;\s*$', line) and
1630 not Search(r'\bfor\b', line)):
1631 error(filename, linenum, 'whitespace/semicolon', 5,
1632 'Extra space before last semicolon. If this should be an empty '
1633 'statement, use { } instead.')
1634
1635
1636 def GetPreviousNonBlankLine(clean_lines, linenum):
1637 """Return the most recent non-blank line and its line number.
1638
1639 Args:
1640 clean_lines: A CleansedLines instance containing the file contents.
1641 linenum: The number of the line to check.
1642
1643 Returns:
1644 A tuple with two elements. The first element is the contents of the last
1645 non-blank line before the current line, or the empty string if this is the
1646 first non-blank line. The second is the line number of that line, or -1
1647 if this is the first non-blank line.
1648 """
1649
1650 prevlinenum = linenum - 1
1651 while prevlinenum >= 0:
1652 prevline = clean_lines.elided[prevlinenum]
1653 if not IsBlankLine(prevline): # if not a blank line...
1654 return (prevline, prevlinenum)
1655 prevlinenum -= 1
1656 return ('', -1)
1657
1658
1659 def CheckBraces(filename, clean_lines, linenum, error):
1660 """Looks for misplaced braces (e.g. at the end of line).
1661
1662 Args:
1663 filename: The name of the current file.
1664 clean_lines: A CleansedLines instance containing the file.
1665 linenum: The number of the line to check.
1666 error: The function to call with any errors found.
1667 """
1668
1669 line = clean_lines.elided[linenum] # get rid of comments and strings
1670
1671 if Match(r'\s*{\s*$', line):
1672 # We allow an open brace to start a line in the case where someone
1673 # is using braces in a block to explicitly create a new scope,
1674 # which is commonly used to control the lifetime of
1675 # stack-allocated variables. We don't detect this perfectly: we
1676 # just don't complain if the last non-whitespace character on the
1677 # previous non-blank line is ';', ':', '{', or '}'.
1678 prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0]
1679 if not Search(r'[;:}{]\s*$', prevline):
1680 error(filename, linenum, 'whitespace/braces', 4,
1681 '{ should almost always be at the end of the previous line')
1682
1683 # An else clause should be on the same line as the preceding closing brace.
1684 if Match(r'\s*else\s*', line):
1685 prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0]
1686 if Match(r'\s*}\s*$', prevline):
1687 error(filename, linenum, 'whitespace/newline', 4,
1688 'An else should appear on the same line as the preceding }')
1689
1690 # If braces come on one side of an else, they should be on both.
1691 # However, we have to worry about "else if" that spans multiple lines!
1692 if Search(r'}\s*else[^{]*$', line) or Match(r'[^}]*else\s*{', line):
1693 if Search(r'}\s*else if([^{]*)$', line): # could be multi-line if
1694 # find the ( after the if
1695 pos = line.find('else if')
1696 pos = line.find('(', pos)
1697 if pos > 0:
1698 (endline, _, endpos) = CloseExpression(clean_lines, linenum, pos)
1699 if endline[endpos:].find('{') == -1: # must be brace after if
1700 error(filename, linenum, 'readability/braces', 5,
1701 'If an else has a brace on one side, it should have it on both')
1702 else: # common case: else not followed by a multi-line if
1703 error(filename, linenum, 'readability/braces', 5,
1704 'If an else has a brace on one side, it should have it on both')
1705
1706 # Likewise, an else should never have the else clause on the same line
1707 if Search(r'\belse [^\s{]', line) and not Search(r'\belse if\b', line):
1708 error(filename, linenum, 'whitespace/newline', 4,
1709 'Else clause should never be on same line as else (use 2 lines)')
1710
1711 # In the same way, a do/while should never be on one line
1712 if Match(r'\s*do [^\s{]', line):
1713 error(filename, linenum, 'whitespace/newline', 4,
1714 'do/while clauses should not be on a single line')
1715
1716 # Braces shouldn't be followed by a ; unless they're defining a struct
1717 # or initializing an array.
1718 # We can't tell in general, but we can for some common cases.
1719 prevlinenum = linenum
1720 while True:
1721 (prevline, prevlinenum) = GetPreviousNonBlankLine(clean_lines, prevlinenum)
1722 if Match(r'\s+{.*}\s*;', line) and not prevline.count(';'):
1723 line = prevline + line
1724 else:
1725 break
1726 if (Search(r'{.*}\s*;', line) and
1727 line.count('{') == line.count('}') and
1728 not Search(r'struct|class|enum|\s*=\s*{', line)):
1729 error(filename, linenum, 'readability/braces', 4,
1730 "You don't need a ; after a }")
1731
1732
1733 def ReplaceableCheck(operator, macro, line):
1734 """Determine whether a basic CHECK can be replaced with a more specific one.
1735
1736 For example suggest using CHECK_EQ instead of CHECK(a == b) and
1737 similarly for CHECK_GE, CHECK_GT, CHECK_LE, CHECK_LT, CHECK_NE.
1738
1739 Args:
1740 operator: The C++ operator used in the CHECK.
1741 macro: The CHECK or EXPECT macro being called.
1742 line: The current source line.
1743
1744 Returns:
1745 True if the CHECK can be replaced with a more specific one.
1746 """
1747
1748 # This matches decimal and hex integers, strings, and chars (in that order).
1749 match_constant = r'([-+]?(\d+|0[xX][0-9a-fA-F]+)[lLuU]{0,3}|".*"|\'.*\')'
1750
1751 # Expression to match two sides of the operator with something that
1752 # looks like a literal, since CHECK(x == iterator) won't compile.
1753 # This means we can't catch all the cases where a more specific
1754 # CHECK is possible, but it's less annoying than dealing with
1755 # extraneous warnings.
1756 match_this = (r'\s*' + macro + r'\((\s*' +
1757 match_constant + r'\s*' + operator + r'[^<>].*|'
1758 r'.*[^<>]' + operator + r'\s*' + match_constant +
1759 r'\s*\))')
1760
1761 # Don't complain about CHECK(x == NULL) or similar because
1762 # CHECK_EQ(x, NULL) won't compile (requires a cast).
1763 # Also, don't complain about more complex boolean expressions
1764 # involving && or || such as CHECK(a == b || c == d).
1765 return Match(match_this, line) and not Search(r'NULL|&&|\|\|', line)
1766
1767
1768 def CheckCheck(filename, clean_lines, linenum, error):
1769 """Checks the use of CHECK and EXPECT macros.
1770
1771 Args:
1772 filename: The name of the current file.
1773 clean_lines: A CleansedLines instance containing the file.
1774 linenum: The number of the line to check.
1775 error: The function to call with any errors found.
1776 """
1777
1778 # Decide the set of replacement macros that should be suggested
1779 raw_lines = clean_lines.raw_lines
1780 current_macro = ''
1781 for macro in _CHECK_MACROS:
1782 if raw_lines[linenum].find(macro) >= 0:
1783 current_macro = macro
1784 break
1785 if not current_macro:
1786 # Don't waste time here if line doesn't contain 'CHECK' or 'EXPECT'
1787 return
1788
1789 line = clean_lines.elided[linenum] # get rid of comments and strings
1790
1791 # Encourage replacing plain CHECKs with CHECK_EQ/CHECK_NE/etc.
1792 for operator in ['==', '!=', '>=', '>', '<=', '<']:
1793 if ReplaceableCheck(operator, current_macro, line):
1794 error(filename, linenum, 'readability/check', 2,
1795 'Consider using %s instead of %s(a %s b)' % (
1796 _CHECK_REPLACEMENT[current_macro][operator],
1797 current_macro, operator))
1798 break
1799
1800
1801 def GetLineWidth(line):
1802 """Determines the width of the line in column positions.
1803
1804 Args:
1805 line: A string, which may be a Unicode string.
1806
1807 Returns:
1808 The width of the line in column positions, accounting for Unicode
1809 combining characters and wide characters.
1810 """
1811 if isinstance(line, unicode):
1812 width = 0
1813 for c in unicodedata.normalize('NFC', line):
1814 if unicodedata.east_asian_width(c) in ('W', 'F'):
1815 width += 2
1816 elif not unicodedata.combining(c):
1817 width += 1
1818 return width
1819 else:
1820 return len(line)
1821
1822
1823 def CheckStyle(filename, clean_lines, linenum, file_extension, error):
1824 """Checks rules from the 'C++ style rules' section of cppguide.html.
1825
1826 Most of these rules are hard to test (naming, comment style), but we
1827 do what we can. In particular we check for 2-space indents, line lengths,
1828 tab usage, spaces inside code, etc.
1829
1830 Args:
1831 filename: The name of the current file.
1832 clean_lines: A CleansedLines instance containing the file.
1833 linenum: The number of the line to check.
1834 file_extension: The extension (without the dot) of the filename.
1835 error: The function to call with any errors found.
1836 """
1837
1838 raw_lines = clean_lines.raw_lines
1839 line = raw_lines[linenum]
1840
1841 if line.find('\t') != -1:
1842 error(filename, linenum, 'whitespace/tab', 1,
1843 'Tab found; better to use spaces')
1844
1845 # One or three blank spaces at the beginning of the line is weird; it's
1846 # hard to reconcile that with 2-space indents.
1847 # NOTE: here are the conditions rob pike used for his tests. Mine aren't
1848 # as sophisticated, but it may be worth becoming so: RLENGTH==initial_spaces
1849 # if(RLENGTH > 20) complain = 0;
1850 # if(match($0, " +(error|private|public|protected):")) complain = 0;
1851 # if(match(prev, "&& *$")) complain = 0;
1852 # if(match(prev, "\\|\\| *$")) complain = 0;
1853 # if(match(prev, "[\",=><] *$")) complain = 0;
1854 # if(match($0, " <<")) complain = 0;
1855 # if(match(prev, " +for \\(")) complain = 0;
1856 # if(prevodd && match(prevprev, " +for \\(")) complain = 0;
1857 initial_spaces = 0
1858 cleansed_line = clean_lines.elided[linenum]
1859 while initial_spaces < len(line) and line[initial_spaces] == ' ':
1860 initial_spaces += 1
1861 if line and line[-1].isspace():
1862 error(filename, linenum, 'whitespace/end_of_line', 4,
1863 'Line ends in whitespace. Consider deleting these extra spaces.')
1864 # There are certain situations we allow one space, notably for labels
1865 elif ((initial_spaces == 1 or initial_spaces == 3) and
1866 not Match(r'\s*\w+\s*:\s*$', cleansed_line)):
1867 error(filename, linenum, 'whitespace/indent', 3,
1868 'Weird number of spaces at line-start. '
1869 'Are you using a 2-space indent?')
1870 # Labels should always be indented at least one space.
1871 elif not initial_spaces and line[:2] != '//' and Search(r'[^:]:\s*$',
1872 line):
1873 error(filename, linenum, 'whitespace/labels', 4,
1874 'Labels should always be indented at least one space. '
1875 'If this is a member-initializer list in a constructor, '
1876 'the colon should be on the line after the definition header.')
1877
1878 # Check if the line is a header guard.
1879 is_header_guard = False
1880 if file_extension == 'h':
1881 cppvar = GetHeaderGuardCPPVariable(filename)
1882 if (line.startswith('#ifndef %s' % cppvar) or
1883 line.startswith('#define %s' % cppvar) or
1884 line.startswith('#endif // %s' % cppvar)):
1885 is_header_guard = True
1886 # #include lines and header guards can be long, since there's no clean way to
1887 # split them.
1888 if not line.startswith('#include') and not is_header_guard:
1889 line_width = GetLineWidth(line)
1890 if line_width > 100:
1891 error(filename, linenum, 'whitespace/line_length', 4,
1892 'Lines should very rarely be longer than 100 characters')
1893 elif line_width > 80:
1894 error(filename, linenum, 'whitespace/line_length', 2,
1895 'Lines should be <= 80 characters long')
1896
1897 if (cleansed_line.count(';') > 1 and
1898 # for loops are allowed two ;'s (and may run over two lines).
1899 cleansed_line.find('for') == -1 and
1900 (GetPreviousNonBlankLine(clean_lines, linenum)[0].find('for') == -1 or
1901 GetPreviousNonBlankLine(clean_lines, linenum)[0].find(';') != -1) and
1902 # It's ok to have many commands in a switch case that fits in 1 line
1903 not ((cleansed_line.find('case ') != -1 or
1904 cleansed_line.find('default:') != -1) and
1905 cleansed_line.find('break;') != -1)):
1906 error(filename, linenum, 'whitespace/newline', 4,
1907 'More than one command on the same line')
1908
1909 # Some more style checks
1910 CheckBraces(filename, clean_lines, linenum, error)
1911 CheckSpacing(filename, clean_lines, linenum, error)
1912 CheckCheck(filename, clean_lines, linenum, error)
1913
1914
1915 _RE_PATTERN_INCLUDE_NEW_STYLE = re.compile(r'#include +"[^/]+\.h"')
1916 _RE_PATTERN_INCLUDE = re.compile(r'^\s*#\s*include\s*([<"])([^>"]*)[>"].*$')
1917 # Matches the first component of a filename delimited by -s and _s. That is:
1918 # _RE_FIRST_COMPONENT.match('foo').group(0) == 'foo'
1919 # _RE_FIRST_COMPONENT.match('foo.cc').group(0) == 'foo'
1920 # _RE_FIRST_COMPONENT.match('foo-bar_baz.cc').group(0) == 'foo'
1921 # _RE_FIRST_COMPONENT.match('foo_bar-baz.cc').group(0) == 'foo'
1922 _RE_FIRST_COMPONENT = re.compile(r'^[^-_.]+')
1923
1924
1925 def _DropCommonSuffixes(filename):
1926 """Drops common suffixes like _test.cc or -inl.h from filename.
1927
1928 For example:
1929 >>> _DropCommonSuffixes('foo/foo-inl.h')
1930 'foo/foo'
1931 >>> _DropCommonSuffixes('foo/bar/foo.cc')
1932 'foo/bar/foo'
1933 >>> _DropCommonSuffixes('foo/foo_internal.h')
1934 'foo/foo'
1935 >>> _DropCommonSuffixes('foo/foo_unusualinternal.h')
1936 'foo/foo_unusualinternal'
1937
1938 Args:
1939 filename: The input filename.
1940
1941 Returns:
1942 The filename with the common suffix removed.
1943 """
1944 for suffix in ('test.cc', 'regtest.cc', 'unittest.cc',
1945 'inl.h', 'impl.h', 'internal.h'):
1946 if (filename.endswith(suffix) and len(filename) > len(suffix) and
1947 filename[-len(suffix) - 1] in ('-', '_')):
1948 return filename[:-len(suffix) - 1]
1949 return os.path.splitext(filename)[0]
1950
1951
1952 def _IsTestFilename(filename):
1953 """Determines if the given filename has a suffix that identifies it as a test.
1954
1955 Args:
1956 filename: The input filename.
1957
1958 Returns:
1959 True if 'filename' looks like a test, False otherwise.
1960 """
1961 if (filename.endswith('_test.cc') or
1962 filename.endswith('_unittest.cc') or
1963 filename.endswith('_regtest.cc')):
1964 return True
1965 else:
1966 return False
1967
1968
1969 def _ClassifyInclude(fileinfo, include, is_system):
1970 """Figures out what kind of header 'include' is.
1971
1972 Args:
1973 fileinfo: The current file cpplint is running over. A FileInfo instance.
1974 include: The path to a #included file.
1975 is_system: True if the #include used <> rather than "".
1976
1977 Returns:
1978 One of the _XXX_HEADER constants.
1979
1980 For example:
1981 >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'stdio.h', True)
1982 _C_SYS_HEADER
1983 >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'string', True)
1984 _CPP_SYS_HEADER
1985 >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'foo/foo.h', False)
1986 _LIKELY_MY_HEADER
1987 >>> _ClassifyInclude(FileInfo('foo/foo_unknown_extension.cc'),
1988 ... 'bar/foo_other_ext.h', False)
1989 _POSSIBLE_MY_HEADER
1990 >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'foo/bar.h', False)
1991 _OTHER_HEADER
1992 """
1993 # This is a list of all standard c++ header files, except
1994 # those already checked for above.
1995 is_stl_h = include in _STL_HEADERS
1996 is_cpp_h = is_stl_h or include in _CPP_HEADERS
1997
1998 if is_system:
1999 if is_cpp_h:
2000 return _CPP_SYS_HEADER
2001 else:
2002 return _C_SYS_HEADER
2003
2004 # If the target file and the include we're checking share a
2005 # basename when we drop common extensions, and the include
2006 # lives in . , then it's likely to be owned by the target file.
2007 target_dir, target_base = (
2008 os.path.split(_DropCommonSuffixes(fileinfo.RepositoryName())))
2009 include_dir, include_base = os.path.split(_DropCommonSuffixes(include))
2010 if target_base == include_base and (
2011 include_dir == target_dir or
2012 include_dir == os.path.normpath(target_dir + '/../public')):
2013 return _LIKELY_MY_HEADER
2014
2015 # If the target and include share some initial basename
2016 # component, it's possible the target is implementing the
2017 # include, so it's allowed to be first, but we'll never
2018 # complain if it's not there.
2019 target_first_component = _RE_FIRST_COMPONENT.match(target_base)
2020 include_first_component = _RE_FIRST_COMPONENT.match(include_base)
2021 if (target_first_component and include_first_component and
2022 target_first_component.group(0) ==
2023 include_first_component.group(0)):
2024 return _POSSIBLE_MY_HEADER
2025
2026 return _OTHER_HEADER
2027
2028
2029 def CheckLanguage(filename, clean_lines, linenum, file_extension, include_state,
2030 error):
2031 """Checks rules from the 'C++ language rules' section of cppguide.html.
2032
2033 Some of these rules are hard to test (function overloading, using
2034 uint32 inappropriately), but we do the best we can.
2035
2036 Args:
2037 filename: The name of the current file.
2038 clean_lines: A CleansedLines instance containing the file.
2039 linenum: The number of the line to check.
2040 file_extension: The extension (without the dot) of the filename.
2041 include_state: An _IncludeState instance in which the headers are inserted.
2042 error: The function to call with any errors found.
2043 """
2044 fileinfo = FileInfo(filename)
2045
2046 # get rid of comments
2047 comment_elided_line = clean_lines.lines[linenum]
2048
2049 # "include" should use the new style "foo/bar.h" instead of just "bar.h"
2050 if _RE_PATTERN_INCLUDE_NEW_STYLE.search(comment_elided_line):
2051 error(filename, linenum, 'build/include', 4,
2052 'Include the directory when naming .h files')
2053
2054 # we shouldn't include a file more than once. actually, there are a
2055 # handful of instances where doing so is okay, but in general it's
2056 # not.
2057 match = _RE_PATTERN_INCLUDE.search(comment_elided_line)
2058 if match:
2059 include = match.group(2)
2060 is_system = (match.group(1) == '<')
2061 if include in include_state:
2062 error(filename, linenum, 'build/include', 4,
2063 '"%s" already included at %s:%s' %
2064 (include, filename, include_state[include]))
2065 else:
2066 include_state[include] = linenum
2067
2068 # We want to ensure that headers appear in the right order:
2069 # 1) for foo.cc, foo.h (preferred location)
2070 # 2) c system files
2071 # 3) cpp system files
2072 # 4) for foo.cc, foo.h (deprecated location)
2073 # 5) other google headers
2074 #
2075 # We classify each include statement as one of those 5 types
2076 # using a number of techniques. The include_state object keeps
2077 # track of the highest type seen, and complains if we see a
2078 # lower type after that.
2079 error_message = include_state.CheckNextIncludeOrder(
2080 _ClassifyInclude(fileinfo, include, is_system))
2081 if error_message:
2082 error(filename, linenum, 'build/include_order', 4,
2083 '%s. Should be: %s.h, c system, c++ system, other.' %
2084 (error_message, fileinfo.BaseName()))
2085
2086 # If the line is empty or consists of entirely a comment, no need to
2087 # check it.
2088 line = clean_lines.elided[linenum]
2089 if not line:
2090 return
2091
2092 # Create an extended_line, which is the concatenation of the current and
2093 # next lines, for more effective checking of code that may span more than one
2094 # line.
2095 if linenum + 1 < clean_lines.NumLines():
2096 extended_line = line + clean_lines.elided[linenum + 1]
2097 else:
2098 extended_line = line
2099
2100 # Make Windows paths like Unix.
2101 fullname = os.path.abspath(filename).replace('\\', '/')
2102
2103 # TODO(unknown): figure out if they're using default arguments in fn proto.
2104
2105 # Look for any of the stream classes that are part of standard C++.
2106 match = _RE_PATTERN_INCLUDE.match(line)
2107 if match:
2108 include = match.group(2)
2109 if Match(r'(f|ind|io|i|o|parse|pf|stdio|str|)?stream$', include):
2110 # Many unit tests use cout, so we exempt them.
2111 if not _IsTestFilename(filename):
2112 error(filename, linenum, 'readability/streams', 3,
2113 'Streams are highly discouraged.')
2114
2115 # Check for non-const references in functions. This is tricky because &
2116 # is also used to take the address of something. We allow <> for templates,
2117 # (ignoring whatever is between the braces) and : for classes.
2118 # These are complicated re's. They try to capture the following:
2119 # paren (for fn-prototype start), typename, &, varname. For the const
2120 # version, we're willing for const to be before typename or after
2121 # Don't check the implemention on same line.
2122 fnline = line.split('{', 1)[0]
2123 if (len(re.findall(r'\([^()]*\b(?:[\w:]|<[^()]*>)+(\s?&|&\s?)\w+', fnline)) >
2124 len(re.findall(r'\([^()]*\bconst\s+(?:typename\s+)?(?:struct\s+)?'
2125 r'(?:[\w:]|<[^()]*>)+(\s?&|&\s?)\w+', fnline)) +
2126 len(re.findall(r'\([^()]*\b(?:[\w:]|<[^()]*>)+\s+const(\s?&|&\s?)[\w]+',
2127 fnline))):
2128
2129 # We allow non-const references in a few standard places, like functions
2130 # called "swap()" or iostream operators like "<<" or ">>".
2131 if not Search(
2132 r'(swap|Swap|operator[<>][<>])\s*\(\s*(?:[\w:]|<.*>)+\s*&',
2133 fnline):
2134 error(filename, linenum, 'runtime/references', 2,
2135 'Is this a non-const reference? '
2136 'If so, make const or use a pointer.')
2137
2138 # Check to see if they're using an conversion function cast.
2139 # I just try to capture the most common basic types, though there are more.
2140 # Parameterless conversion functions, such as bool(), are allowed as they are
2141 # probably a member operator declaration or default constructor.
2142 match = Search(
2143 r'\b(int|float|double|bool|char|int32|uint32|int64|uint64)\([^)]', line)
2144 if match:
2145 # gMock methods are defined using some variant of MOCK_METHODx(name, type)
2146 # where type may be float(), int(string), etc. Without context they are
2147 # virtually indistinguishable from int(x) casts.
2148 if not Match(r'^\s*MOCK_(CONST_)?METHOD\d+(_T)?\(', line):
2149 error(filename, linenum, 'readability/casting', 4,
2150 'Using deprecated casting style. '
2151 'Use static_cast<%s>(...) instead' %
2152 match.group(1))
2153
2154 CheckCStyleCast(filename, linenum, line, clean_lines.raw_lines[linenum],
2155 'static_cast',
2156 r'\((int|float|double|bool|char|u?int(16|32|64))\)',
2157 error)
2158 # This doesn't catch all cases. Consider (const char * const)"hello".
2159 CheckCStyleCast(filename, linenum, line, clean_lines.raw_lines[linenum],
2160 'reinterpret_cast', r'\((\w+\s?\*+\s?)\)', error)
2161
2162 # In addition, we look for people taking the address of a cast. This
2163 # is dangerous -- casts can assign to temporaries, so the pointer doesn't
2164 # point where you think.
2165 if Search(
2166 r'(&\([^)]+\)[\w(])|(&(static|dynamic|reinterpret)_cast\b)', line):
2167 error(filename, linenum, 'runtime/casting', 4,
2168 ('Are you taking an address of a cast? '
2169 'This is dangerous: could be a temp var. '
2170 'Take the address before doing the cast, rather than after'))
2171
2172 # Check for people declaring static/global STL strings at the top level.
2173 # This is dangerous because the C++ language does not guarantee that
2174 # globals with constructors are initialized before the first access.
2175 match = Match(
2176 r'((?:|static +)(?:|const +))string +([a-zA-Z0-9_:]+)\b(.*)',
2177 line)
2178 # Make sure it's not a function.
2179 # Function template specialization looks like: "string foo<Type>(...".
2180 # Class template definitions look like: "string Foo<Type>::Method(...".
2181 if match and not Match(r'\s*(<.*>)?(::[a-zA-Z0-9_]+)?\s*\(([^"]|$)',
2182 match.group(3)):
2183 error(filename, linenum, 'runtime/string', 4,
2184 'For a static/global string constant, use a C style string instead: '
2185 '"%schar %s[]".' %
2186 (match.group(1), match.group(2)))
2187
2188 # Check that we're not using RTTI outside of testing code.
2189 if Search(r'\bdynamic_cast<', line) and not _IsTestFilename(filename):
2190 error(filename, linenum, 'runtime/rtti', 5,
2191 'Do not use dynamic_cast<>. If you need to cast within a class '
2192 "hierarchy, use static_cast<> to upcast. Google doesn't support "
2193 'RTTI.')
2194
2195 if Search(r'\b([A-Za-z0-9_]*_)\(\1\)', line):
2196 error(filename, linenum, 'runtime/init', 4,
2197 'You seem to be initializing a member variable with itself.')
2198
2199 if file_extension == 'h':
2200 # TODO(unknown): check that 1-arg constructors are explicit.
2201 # How to tell it's a constructor?
2202 # (handled in CheckForNonStandardConstructs for now)
2203 # TODO(unknown): check that classes have DISALLOW_EVIL_CONSTRUCTORS
2204 # (level 1 error)
2205 pass
2206
2207 # Check if people are using the verboten C basic types. The only exception
2208 # we regularly allow is "unsigned short port" for port.
2209 if Search(r'\bshort port\b', line):
2210 if not Search(r'\bunsigned short port\b', line):
2211 error(filename, linenum, 'runtime/int', 4,
2212 'Use "unsigned short" for ports, not "short"')
2213 else:
2214 match = Search(r'\b(short|long(?! +double)|long long)\b', line)
2215 if match:
2216 error(filename, linenum, 'runtime/int', 4,
2217 'Use int16/int64/etc, rather than the C type %s' % match.group(1))
2218
2219 # When snprintf is used, the second argument shouldn't be a literal.
2220 match = Search(r'snprintf\s*\(([^,]*),\s*([0-9]*)\s*,', line)
2221 if match:
2222 error(filename, linenum, 'runtime/printf', 3,
2223 'If you can, use sizeof(%s) instead of %s as the 2nd arg '
2224 'to snprintf.' % (match.group(1), match.group(2)))
2225
2226 # Check if some verboten C functions are being used.
2227 if Search(r'\bsprintf\b', line):
2228 error(filename, linenum, 'runtime/printf', 5,
2229 'Never use sprintf. Use snprintf instead.')
2230 match = Search(r'\b(strcpy|strcat)\b', line)
2231 if match:
2232 error(filename, linenum, 'runtime/printf', 4,
2233 'Almost always, snprintf is better than %s' % match.group(1))
2234
2235 if Search(r'\bsscanf\b', line):
2236 error(filename, linenum, 'runtime/printf', 1,
2237 'sscanf can be ok, but is slow and can overflow buffers.')
2238
2239 # Check for suspicious usage of "if" like
2240 # } if (a == b) {
2241 if Search(r'\}\s*if\s*\(', line):
2242 error(filename, linenum, 'readability/braces', 4,
2243 'Did you mean "else if"? If not, start a new line for "if".')
2244
2245 # Check for potential format string bugs like printf(foo).
2246 # We constrain the pattern not to pick things like DocidForPrintf(foo).
2247 # Not perfect but it can catch printf(foo.c_str()) and printf(foo->c_str())
2248 match = re.search(r'\b((?:string)?printf)\s*\(([\w.\->()]+)\)', line, re.I)
2249 if match:
2250 error(filename, linenum, 'runtime/printf', 4,
2251 'Potential format string bug. Do %s("%%s", %s) instead.'
2252 % (match.group(1), match.group(2)))
2253
2254 # Check for potential memset bugs like memset(buf, sizeof(buf), 0).
2255 match = Search(r'memset\s*\(([^,]*),\s*([^,]*),\s*0\s*\)', line)
2256 if match and not Match(r"^''|-?[0-9]+|0x[0-9A-Fa-f]$", match.group(2)):
2257 error(filename, linenum, 'runtime/memset', 4,
2258 'Did you mean "memset(%s, 0, %s)"?'
2259 % (match.group(1), match.group(2)))
2260
2261 if Search(r'\busing namespace\b', line):
2262 error(filename, linenum, 'build/namespaces', 5,
2263 'Do not use namespace using-directives. '
2264 'Use using-declarations instead.')
2265
2266 # Detect variable-length arrays.
2267 match = Match(r'\s*(.+::)?(\w+) [a-z]\w*\[(.+)];', line)
2268 if (match and match.group(2) != 'return' and match.group(2) != 'delete' and
2269 match.group(3).find(']') == -1):
2270 # Split the size using space and arithmetic operators as delimiters.
2271 # If any of the resulting tokens are not compile time constants then
2272 # report the error.
2273 tokens = re.split(r'\s|\+|\-|\*|\/|<<|>>]', match.group(3))
2274 is_const = True
2275 skip_next = False
2276 for tok in tokens:
2277 if skip_next:
2278 skip_next = False
2279 continue
2280
2281 if Search(r'sizeof\(.+\)', tok): continue
2282 if Search(r'arraysize\(\w+\)', tok): continue
2283
2284 tok = tok.lstrip('(')
2285 tok = tok.rstrip(')')
2286 if not tok: continue
2287 if Match(r'\d+', tok): continue
2288 if Match(r'0[xX][0-9a-fA-F]+', tok): continue
2289 if Match(r'k[A-Z0-9]\w*', tok): continue
2290 if Match(r'(.+::)?k[A-Z0-9]\w*', tok): continue
2291 if Match(r'(.+::)?[A-Z][A-Z0-9_]*', tok): continue
2292 # A catch all for tricky sizeof cases, including 'sizeof expression',
2293 # 'sizeof(*type)', 'sizeof(const type)', 'sizeof(struct StructName)'
2294 # requires skipping the next token becasue we split on ' ' and '*'.
2295 if tok.startswith('sizeof'):
2296 skip_next = True
2297 continue
2298 is_const = False
2299 break
2300 if not is_const:
2301 error(filename, linenum, 'runtime/arrays', 1,
2302 'Do not use variable-length arrays. Use an appropriately named '
2303 "('k' followed by CamelCase) compile-time constant for the size.")
2304
2305 # If DISALLOW_EVIL_CONSTRUCTORS, DISALLOW_COPY_AND_ASSIGN, or
2306 # DISALLOW_IMPLICIT_CONSTRUCTORS is present, then it should be the last thing
2307 # in the class declaration.
2308 match = Match(
2309 (r'\s*'
2310 r'(DISALLOW_(EVIL_CONSTRUCTORS|COPY_AND_ASSIGN|IMPLICIT_CONSTRUCTORS))'
2311 r'\(.*\);$'),
2312 line)
2313 if match and linenum + 1 < clean_lines.NumLines():
2314 next_line = clean_lines.elided[linenum + 1]
2315 if not Search(r'^\s*};', next_line):
2316 error(filename, linenum, 'readability/constructors', 3,
2317 match.group(1) + ' should be the last thing in the class')
2318
2319 # Check for use of unnamed namespaces in header files. Registration
2320 # macros are typically OK, so we allow use of "namespace {" on lines
2321 # that end with backslashes.
2322 if (file_extension == 'h'
2323 and Search(r'\bnamespace\s*{', line)
2324 and line[-1] != '\\'):
2325 error(filename, linenum, 'build/namespaces', 4,
2326 'Do not use unnamed namespaces in header files. See '
2327 'http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Namesp aces'
2328 ' for more information.')
2329
2330
2331 def CheckCStyleCast(filename, linenum, line, raw_line, cast_type, pattern,
2332 error):
2333 """Checks for a C-style cast by looking for the pattern.
2334
2335 This also handles sizeof(type) warnings, due to similarity of content.
2336
2337 Args:
2338 filename: The name of the current file.
2339 linenum: The number of the line to check.
2340 line: The line of code to check.
2341 raw_line: The raw line of code to check, with comments.
2342 cast_type: The string for the C++ cast to recommend. This is either
2343 reinterpret_cast or static_cast, depending.
2344 pattern: The regular expression used to find C-style casts.
2345 error: The function to call with any errors found.
2346 """
2347 match = Search(pattern, line)
2348 if not match:
2349 return
2350
2351 # e.g., sizeof(int)
2352 sizeof_match = Match(r'.*sizeof\s*$', line[0:match.start(1) - 1])
2353 if sizeof_match:
2354 error(filename, linenum, 'runtime/sizeof', 1,
2355 'Using sizeof(type). Use sizeof(varname) instead if possible')
2356 return
2357
2358 remainder = line[match.end(0):]
2359
2360 # The close paren is for function pointers as arguments to a function.
2361 # eg, void foo(void (*bar)(int));
2362 # The semicolon check is a more basic function check; also possibly a
2363 # function pointer typedef.
2364 # eg, void foo(int); or void foo(int) const;
2365 # The equals check is for function pointer assignment.
2366 # eg, void *(*foo)(int) = ...
2367 #
2368 # Right now, this will only catch cases where there's a single argument, and
2369 # it's unnamed. It should probably be expanded to check for multiple
2370 # arguments with some unnamed.
2371 function_match = Match(r'\s*(\)|=|(const)?\s*(;|\{|throw\(\)))', remainder)
2372 if function_match:
2373 if (not function_match.group(3) or
2374 function_match.group(3) == ';' or
2375 raw_line.find('/*') < 0):
2376 error(filename, linenum, 'readability/function', 3,
2377 'All parameters should be named in a function')
2378 return
2379
2380 # At this point, all that should be left is actual casts.
2381 error(filename, linenum, 'readability/casting', 4,
2382 'Using C-style cast. Use %s<%s>(...) instead' %
2383 (cast_type, match.group(1)))
2384
2385
2386 _HEADERS_CONTAINING_TEMPLATES = (
2387 ('<deque>', ('deque',)),
2388 ('<functional>', ('unary_function', 'binary_function',
2389 'plus', 'minus', 'multiplies', 'divides', 'modulus',
2390 'negate',
2391 'equal_to', 'not_equal_to', 'greater', 'less',
2392 'greater_equal', 'less_equal',
2393 'logical_and', 'logical_or', 'logical_not',
2394 'unary_negate', 'not1', 'binary_negate', 'not2',
2395 'bind1st', 'bind2nd',
2396 'pointer_to_unary_function',
2397 'pointer_to_binary_function',
2398 'ptr_fun',
2399 'mem_fun_t', 'mem_fun', 'mem_fun1_t', 'mem_fun1_ref_t',
2400 'mem_fun_ref_t',
2401 'const_mem_fun_t', 'const_mem_fun1_t',
2402 'const_mem_fun_ref_t', 'const_mem_fun1_ref_t',
2403 'mem_fun_ref',
2404 )),
2405 ('<limits>', ('numeric_limits',)),
2406 ('<list>', ('list',)),
2407 ('<map>', ('map', 'multimap',)),
2408 ('<memory>', ('allocator',)),
2409 ('<queue>', ('queue', 'priority_queue',)),
2410 ('<set>', ('set', 'multiset',)),
2411 ('<stack>', ('stack',)),
2412 ('<string>', ('char_traits', 'basic_string',)),
2413 ('<utility>', ('pair',)),
2414 ('<vector>', ('vector',)),
2415
2416 # gcc extensions.
2417 # Note: std::hash is their hash, ::hash is our hash
2418 ('<hash_map>', ('hash_map', 'hash_multimap',)),
2419 ('<hash_set>', ('hash_set', 'hash_multiset',)),
2420 ('<slist>', ('slist',)),
2421 )
2422
2423 _HEADERS_ACCEPTED_BUT_NOT_PROMOTED = {
2424 # We can trust with reasonable confidence that map gives us pair<>, too.
2425 'pair<>': ('map', 'multimap', 'hash_map', 'hash_multimap')
2426 }
2427
2428 _RE_PATTERN_STRING = re.compile(r'\bstring\b')
2429
2430 _re_pattern_algorithm_header = []
2431 for _template in ('copy', 'max', 'min', 'sort', 'swap'):
2432 # Match max<type>(..., ...), max(..., ...), but not foo->max, foo.max or
2433 # type::max().
2434 _re_pattern_algorithm_header.append(
2435 (re.compile(r'[^>.]\b' + _template + r'(<.*?>)?\([^\)]'),
2436 _template,
2437 '<algorithm>'))
2438
2439 _re_pattern_templates = []
2440 for _header, _templates in _HEADERS_CONTAINING_TEMPLATES:
2441 for _template in _templates:
2442 _re_pattern_templates.append(
2443 (re.compile(r'(\<|\b)' + _template + r'\s*\<'),
2444 _template + '<>',
2445 _header))
2446
2447
2448 def CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error):
2449 """Reports for missing stl includes.
2450
2451 This function will output warnings to make sure you are including the headers
2452 necessary for the stl containers and functions that you use. We only give one
2453 reason to include a header. For example, if you use both equal_to<> and
2454 less<> in a .h file, only one (the latter in the file) of these will be
2455 reported as a reason to include the <functional>.
2456
2457 We only check headers. We do not check inside cc-files. .cc files should be
2458 able to depend on their respective header files for includes. However, there
2459 is no simple way of producing this logic here.
2460
2461 Args:
2462 filename: The name of the current file.
2463 clean_lines: A CleansedLines instance containing the file.
2464 include_state: An _IncludeState instance.
2465 error: The function to call with any errors found.
2466 """
2467 if filename.endswith('.cc'):
2468 return
2469
2470 required = {} # A map of header name to linenumber and the template entity.
2471 # Example of required: { '<functional>': (1219, 'less<>') }
2472
2473 for linenum in xrange(clean_lines.NumLines()):
2474 line = clean_lines.elided[linenum]
2475 if not line or line[0] == '#':
2476 continue
2477
2478 # String is special -- it is a non-templatized type in STL.
2479 if _RE_PATTERN_STRING.search(line):
2480 required['<string>'] = (linenum, 'string')
2481
2482 for pattern, template, header in _re_pattern_algorithm_header:
2483 if pattern.search(line):
2484 required[header] = (linenum, template)
2485
2486 # The following function is just a speed up, no semantics are changed.
2487 if not '<' in line: # Reduces the cpu time usage by skipping lines.
2488 continue
2489
2490 for pattern, template, header in _re_pattern_templates:
2491 if pattern.search(line):
2492 required[header] = (linenum, template)
2493
2494 # All the lines have been processed, report the errors found.
2495 for required_header_unstripped in required:
2496 template = required[required_header_unstripped][1]
2497 if template in _HEADERS_ACCEPTED_BUT_NOT_PROMOTED:
2498 headers = _HEADERS_ACCEPTED_BUT_NOT_PROMOTED[template]
2499 if [True for header in headers if header in include_state]:
2500 continue
2501 if required_header_unstripped.strip('<>"') not in include_state:
2502 error(filename, required[required_header_unstripped][0],
2503 'build/include_what_you_use', 4,
2504 'Add #include ' + required_header_unstripped + ' for ' + template)
2505
2506
2507 def ProcessLine(filename, file_extension,
2508 clean_lines, line, include_state, function_state,
2509 class_state, error):
2510 """Processes a single line in the file.
2511
2512 Args:
2513 filename: Filename of the file that is being processed.
2514 file_extension: The extension (dot not included) of the file.
2515 clean_lines: An array of strings, each representing a line of the file,
2516 with comments stripped.
2517 line: Number of line being processed.
2518 include_state: An _IncludeState instance in which the headers are inserted.
2519 function_state: A _FunctionState instance which counts function lines, etc.
2520 class_state: A _ClassState instance which maintains information about
2521 the current stack of nested class declarations being parsed.
2522 error: A callable to which errors are reported, which takes 4 arguments:
2523 filename, line number, error level, and message
2524
2525 """
2526 raw_lines = clean_lines.raw_lines
2527 CheckForFunctionLengths(filename, clean_lines, line, function_state, error)
2528 if Search(r'\bNOLINT\b', raw_lines[line]): # ignore nolint lines
2529 return
2530 CheckForMultilineCommentsAndStrings(filename, clean_lines, line, error)
2531 CheckStyle(filename, clean_lines, line, file_extension, error)
2532 CheckLanguage(filename, clean_lines, line, file_extension, include_state,
2533 error)
2534 CheckForNonStandardConstructs(filename, clean_lines, line,
2535 class_state, error)
2536 CheckPosixThreading(filename, clean_lines, line, error)
2537
2538
2539 def ProcessFileData(filename, file_extension, lines, error):
2540 """Performs lint checks and reports any errors to the given error function.
2541
2542 Args:
2543 filename: Filename of the file that is being processed.
2544 file_extension: The extension (dot not included) of the file.
2545 lines: An array of strings, each representing a line of the file, with the
2546 last element being empty if the file is termined with a newline.
2547 error: A callable to which errors are reported, which takes 4 arguments:
2548 """
2549 lines = (['// marker so line numbers and indices both start at 1'] + lines +
2550 ['// marker so line numbers end in a known way'])
2551
2552 include_state = _IncludeState()
2553 function_state = _FunctionState()
2554 class_state = _ClassState()
2555
2556 CheckForCopyright(filename, lines, error)
2557
2558 if file_extension == 'h':
2559 CheckForHeaderGuard(filename, lines, error)
2560
2561 RemoveMultiLineComments(filename, lines, error)
2562 clean_lines = CleansedLines(lines)
2563 for line in xrange(clean_lines.NumLines()):
2564 ProcessLine(filename, file_extension, clean_lines, line,
2565 include_state, function_state, class_state, error)
2566 class_state.CheckFinished(filename, error)
2567
2568 CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error)
2569
2570 # We check here rather than inside ProcessLine so that we see raw
2571 # lines rather than "cleaned" lines.
2572 CheckForUnicodeReplacementCharacters(filename, lines, error)
2573
2574 CheckForNewlineAtEOF(filename, lines, error)
2575
2576
2577 def ProcessFile(filename, vlevel):
2578 """Does google-lint on a single file.
2579
2580 Args:
2581 filename: The name of the file to parse.
2582
2583 vlevel: The level of errors to report. Every error of confidence
2584 >= verbose_level will be reported. 0 is a good default.
2585 """
2586
2587 _SetVerboseLevel(vlevel)
2588
2589 try:
2590 # Support the UNIX convention of using "-" for stdin. Note that
2591 # we are not opening the file with universal newline support
2592 # (which codecs doesn't support anyway), so the resulting lines do
2593 # contain trailing '\r' characters if we are reading a file that
2594 # has CRLF endings.
2595 # If after the split a trailing '\r' is present, it is removed
2596 # below. If it is not expected to be present (i.e. os.linesep !=
2597 # '\r\n' as in Windows), a warning is issued below if this file
2598 # is processed.
2599
2600 if filename == '-':
2601 lines = codecs.StreamReaderWriter(sys.stdin,
2602 codecs.getreader('utf8'),
2603 codecs.getwriter('utf8'),
2604 'replace').read().split('\n')
2605 else:
2606 lines = codecs.open(filename, 'r', 'utf8', 'replace').read().split('\n')
2607
2608 carriage_return_found = False
2609 # Remove trailing '\r'.
2610 for linenum in range(len(lines)):
2611 if lines[linenum].endswith('\r'):
2612 lines[linenum] = lines[linenum].rstrip('\r')
2613 carriage_return_found = True
2614
2615 except IOError:
2616 sys.stderr.write(
2617 "Skipping input '%s': Can't open for reading\n" % filename)
2618 return
2619
2620 # Note, if no dot is found, this will give the entire filename as the ext.
2621 file_extension = filename[filename.rfind('.') + 1:]
2622
2623 # When reading from stdin, the extension is unknown, so no cpplint tests
2624 # should rely on the extension.
2625 if (filename != '-' and file_extension != 'cc' and file_extension != 'h'
2626 and file_extension != 'cpp'):
2627 sys.stderr.write('Ignoring %s; not a .cc or .h file\n' % filename)
2628 else:
2629 ProcessFileData(filename, file_extension, lines, Error)
2630 if carriage_return_found and os.linesep != '\r\n':
2631 # Use 0 for linenum since outputing only one error for potentially
2632 # several lines.
2633 Error(filename, 0, 'whitespace/newline', 1,
2634 'One or more unexpected \\r (^M) found;'
2635 'better to use only a \\n')
2636
2637 sys.stderr.write('Done processing %s\n' % filename)
2638
2639
2640 def PrintUsage(message):
2641 """Prints a brief usage string and exits, optionally with an error message.
2642
2643 Args:
2644 message: The optional error message.
2645 """
2646 sys.stderr.write(_USAGE)
2647 if message:
2648 sys.exit('\nFATAL ERROR: ' + message)
2649 else:
2650 sys.exit(1)
2651
2652
2653 def PrintCategories():
2654 """Prints a list of all the error-categories used by error messages.
2655
2656 These are the categories used to filter messages via --filter.
2657 """
2658 sys.stderr.write(_ERROR_CATEGORIES)
2659 sys.exit(0)
2660
2661
2662 def ParseArguments(args):
2663 """Parses the command line arguments.
2664
2665 This may set the output format and verbosity level as side-effects.
2666
2667 Args:
2668 args: The command line arguments:
2669
2670 Returns:
2671 The list of filenames to lint.
2672 """
2673 try:
2674 (opts, filenames) = getopt.getopt(args, '', ['help', 'output=', 'verbose=',
2675 'filter='])
2676 except getopt.GetoptError:
2677 PrintUsage('Invalid arguments.')
2678
2679 verbosity = _VerboseLevel()
2680 output_format = _OutputFormat()
2681 filters = ''
2682
2683 for (opt, val) in opts:
2684 if opt == '--help':
2685 PrintUsage(None)
2686 elif opt == '--output':
2687 if not val in ('emacs', 'vs7'):
2688 PrintUsage('The only allowed output formats are emacs and vs7.')
2689 output_format = val
2690 elif opt == '--verbose':
2691 verbosity = int(val)
2692 elif opt == '--filter':
2693 filters = val
2694 if filters == '':
2695 PrintCategories()
2696
2697 if not filenames:
2698 PrintUsage('No files were specified.')
2699
2700 _SetOutputFormat(output_format)
2701 _SetVerboseLevel(verbosity)
2702 _SetFilters(filters)
2703
2704 return filenames
2705
2706
2707 def main():
2708 filenames = ParseArguments(sys.argv[1:])
2709
2710 # Change stderr to write with replacement characters so we don't die
2711 # if we try to print something containing non-ASCII characters.
2712 sys.stderr = codecs.StreamReaderWriter(sys.stderr,
2713 codecs.getreader('utf8'),
2714 codecs.getwriter('utf8'),
2715 'replace')
2716
2717 _cpplint_state.ResetErrorCount()
2718 for filename in filenames:
2719 ProcessFile(filename, _cpplint_state.verbose_level)
2720 sys.stderr.write('Total errors found: %d\n' % _cpplint_state.error_count)
2721 sys.exit(_cpplint_state.error_count > 0)
2722
2723
2724 if __name__ == '__main__':
2725 main()
OLDNEW
« no previous file with comments | « depot_tools/chrome-update-create-task.bat ('k') | depot_tools/gcl » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698