67 """Does google-lint on c++ files.
69 The goal of this script is to identify places in the code that *may*
70 be in non-compliance with google style. It does not attempt to fix
71 up these problems -- the point is to educate. It does also not
72 attempt to find all problems, or to ensure that everything it does
73 find is legitimately a problem.
75 In particular, we can get very confused by /* and // inside strings!
76 We do a small hack, which is to ignore //'s with "'s after them on the
77 same line, but it is far from perfect (in either direction).
93 Syntax: cpplint.py [--verbose=#] [--output=vs7] [--filter=-x,+y,...]
94 [--counting=total|toplevel|detailed]
97 The style guidelines this tries to follow are those in
98 http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml
100 Every problem is given a confidence score from 1-5, with 5 meaning we are
101 certain of the problem, and 1 meaning it could be a legitimate construct.
102 This will miss some errors, and is not a substitute for a code review.
104 To suppress false-positive errors of a certain category, add a
105 'NOLINT(category)' comment to the line. NOLINT or NOLINT(*)
106 suppresses errors of all categories on that line.
108 The files passed in will be linted; at least one file must be provided.
109 Linted extensions are .cc, .cpp, and .h. Other file types will be ignored.
114 By default, the output is formatted to ease emacs parsing. Visual Studio
115 compatible output (vs7) may also be used. Other formats are unsupported.
118 Specify a number 0-5 to restrict errors to certain verbosity levels.
121 Specify a comma-separated list of category-filters to apply: only
122 error messages whose category names pass the filters will be printed.
123 (Category names are printed with the message and look like
124 "[whitespace/indent]".) Filters are evaluated left to right.
125 "-FOO" and "FOO" means "do not print categories that start with FOO".
126 "+FOO" means "do print categories that start with FOO".
128 Examples: --filter=-whitespace,+whitespace/braces
129 --filter=whitespace,runtime/printf,+runtime/printf_format
130 --filter=-,+build/include_what_you_use
132 To see a list of all the categories used in cpplint, pass no arg:
135 counting=total|toplevel|detailed
136 The total number of errors found is always printed. If
137 'toplevel' is provided, then the count of errors in each of
138 the top-level categories like 'build' and 'whitespace' will
139 also be printed. If 'detailed' is provided, then a count
140 is provided for each category like 'build/class'.
143 The root directory used for deriving header guard CPP variable.
144 By default, the header guard CPP variable is calculated as the relative
145 path to the directory that contains .git, .hg, or .svn. When this flag
146 is specified, the relative path is calculated from the specified
147 directory. If the specified directory does not exist, this flag is
151 Assuing that src/.git exists, the header guard CPP variables for
152 src/chrome/browser/ui/browser.h are:
154 No flag => CHROME_BROWSER_UI_BROWSER_H_
155 --root=chrome => BROWSER_UI_BROWSER_H_
156 --root=chrome/browser => UI_BROWSER_H_
164 _ERROR_CATEGORIES = [
167 'build/endif_comment',
168 'build/explicit_make_pair',
169 'build/forward_decl',
170 'build/header_guard',
172 'build/include_alpha',
173 'build/include_order',
174 'build/include_what_you_use',
176 'build/printf_format',
177 'build/storage_class',
179 'readability/alt_tokens',
180 'readability/braces',
181 'readability/casting',
183 'readability/constructors',
184 'readability/fn_size',
185 'readability/function',
186 'readability/multiline_comment',
187 'readability/multiline_string',
188 'readability/namespace',
189 'readability/nolint',
190 'readability/streams',
198 'runtime/invalid_increment',
199 'runtime/member_string_references',
203 'runtime/printf_format',
204 'runtime/references',
208 'runtime/threadsafe_fn',
209 'whitespace/blank_line',
212 'whitespace/comments',
213 'whitespace/empty_loop_body',
214 'whitespace/end_of_line',
215 'whitespace/ending_newline',
216 'whitespace/forcolon',
219 'whitespace/line_length',
220 'whitespace/newline',
221 'whitespace/operators',
223 'whitespace/semicolon',
232 _DEFAULT_FILTERS = [
'-build/include_alpha']
239 _STL_HEADERS = frozenset([
240 'algobase.h',
'algorithm',
'alloc.h',
'bitset',
'deque',
'exception',
241 'function.h',
'functional',
'hash_map',
'hash_map.h',
'hash_set',
242 'hash_set.h',
'iterator',
'list',
'list.h',
'map',
'memory',
'new',
243 'pair.h',
'pthread_alloc',
'queue',
'set',
'set.h',
'sstream',
'stack',
244 'stl_alloc.h',
'stl_relops.h',
'type_traits.h',
245 'utility',
'vector',
'vector.h',
250 _CPP_HEADERS = frozenset([
251 'algo.h',
'builtinbuf.h',
'bvector.h',
'cassert',
'cctype',
252 'cerrno',
'cfloat',
'ciso646',
'climits',
'clocale',
'cmath',
253 'complex',
'complex.h',
'csetjmp',
'csignal',
'cstdarg',
'cstddef',
254 'cstdio',
'cstdlib',
'cstring',
'ctime',
'cwchar',
'cwctype',
255 'defalloc.h',
'deque.h',
'editbuf.h',
'exception',
'fstream',
256 'fstream.h',
'hashtable.h',
'heap.h',
'indstream.h',
'iomanip',
257 'iomanip.h',
'ios',
'iosfwd',
'iostream',
'iostream.h',
'istream',
258 'istream.h',
'iterator.h',
'limits',
'map.h',
'multimap.h',
'multiset.h',
259 'numeric',
'ostream',
'ostream.h',
'parsestream.h',
'pfstream.h',
260 'PlotFile.h',
'procbuf.h',
'pthread_alloc.h',
'rope',
'rope.h',
261 'ropeimpl.h',
'SFile.h',
'slist',
'slist.h',
'stack.h',
'stdexcept',
262 'stdiostream.h',
'streambuf',
'streambuf.h',
'stream.h',
'strfile.h',
263 'string',
'strstream',
'strstream.h',
'tempbuf.h',
'tree.h',
'typeinfo',
273 'EXPECT_TRUE_M',
'EXPECT_TRUE',
274 'ASSERT_TRUE_M',
'ASSERT_TRUE',
275 'EXPECT_FALSE_M',
'EXPECT_FALSE',
276 'ASSERT_FALSE_M',
'ASSERT_FALSE',
280 _CHECK_REPLACEMENT = dict([(m, {})
for m
in _CHECK_MACROS])
282 for op, replacement
in [(
'==',
'EQ'), (
'!=',
'NE'),
283 (
'>=',
'GE'), (
'>',
'GT'),
284 (
'<=',
'LE'), (
'<',
'LT')]:
285 _CHECK_REPLACEMENT[
'DCHECK'][op] =
'DCHECK_%s' % replacement
286 _CHECK_REPLACEMENT[
'CHECK'][op] =
'CHECK_%s' % replacement
287 _CHECK_REPLACEMENT[
'EXPECT_TRUE'][op] =
'EXPECT_%s' % replacement
288 _CHECK_REPLACEMENT[
'ASSERT_TRUE'][op] =
'ASSERT_%s' % replacement
289 _CHECK_REPLACEMENT[
'EXPECT_TRUE_M'][op] =
'EXPECT_%s_M' % replacement
290 _CHECK_REPLACEMENT[
'ASSERT_TRUE_M'][op] =
'ASSERT_%s_M' % replacement
292 for op, inv_replacement
in [(
'==',
'NE'), (
'!=',
'EQ'),
293 (
'>=',
'LT'), (
'>',
'LE'),
294 (
'<=',
'GT'), (
'<',
'GE')]:
295 _CHECK_REPLACEMENT[
'EXPECT_FALSE'][op] =
'EXPECT_%s' % inv_replacement
296 _CHECK_REPLACEMENT[
'ASSERT_FALSE'][op] =
'ASSERT_%s' % inv_replacement
297 _CHECK_REPLACEMENT[
'EXPECT_FALSE_M'][op] =
'EXPECT_%s_M' % inv_replacement
298 _CHECK_REPLACEMENT[
'ASSERT_FALSE_M'][op] =
'ASSERT_%s_M' % inv_replacement
305 _ALT_TOKEN_REPLACEMENT = {
325 _ALT_TOKEN_REPLACEMENT_PATTERN = re.compile(
326 r'[ =()](' + (
'|'.join(_ALT_TOKEN_REPLACEMENT.keys())) +
r')(?=[ (]|$)')
333 _LIKELY_MY_HEADER = 3
334 _POSSIBLE_MY_HEADER = 4
344 _MATCH_ASM = re.compile(
r'^\s*(?:asm|_asm|__asm|__asm__)'
345 r'(?:\s+(volatile|__volatile__))?'
349 _regexp_compile_cache = {}
352 _RE_SUPPRESSION = re.compile(
r'\bNOLINT\b(\([^)]*\))?')
356 _error_suppressions = {}
362 def ParseNolintSuppressions(filename, raw_line, linenum, error):
363 """Updates the global list of error-suppressions.
365 Parses any NOLINT comments on the current line, updating the global
366 error_suppressions store. Reports an error if the NOLINT comment
370 filename: str, the name of the input file.
371 raw_line: str, the line of input text, with comments.
372 linenum: int, the number of the current line.
373 error: function, an error handler.
376 matched = _RE_SUPPRESSION.search(raw_line)
378 category = matched.group(1)
379 if category
in (
None,
'(*)'):
380 _error_suppressions.setdefault(
None, set()).
add(linenum)
382 if category.startswith(
'(')
and category.endswith(
')'):
383 category = category[1:-1]
384 if category
in _ERROR_CATEGORIES:
385 _error_suppressions.setdefault(category, set()).
add(linenum)
387 error(filename, linenum,
'readability/nolint', 5,
388 'Unknown NOLINT error category: %s' % category)
391 def ResetNolintSuppressions():
392 "Resets the set of NOLINT suppressions to empty."
393 _error_suppressions.clear()
396 def IsErrorSuppressedByNolint(category, linenum):
397 """Returns true if the specified error category is suppressed on this line.
399 Consults the global error_suppressions map populated by
400 ParseNolintSuppressions/ResetNolintSuppressions.
403 category: str, the category of the error.
404 linenum: int, the current line number.
406 bool, True iff the error should be suppressed due to a NOLINT comment.
408 return (linenum
in _error_suppressions.get(category, set())
or
409 linenum
in _error_suppressions.get(
None, set()))
411 def Match(pattern, s):
412 """Matches the string with the pattern, caching the compiled regexp."""
416 if not pattern
in _regexp_compile_cache:
417 _regexp_compile_cache[pattern] = sre_compile.compile(pattern)
418 return _regexp_compile_cache[pattern].match(s)
421 def Search(pattern, s):
422 """Searches the string for the pattern, caching the compiled regexp."""
423 if not pattern
in _regexp_compile_cache:
424 _regexp_compile_cache[pattern] = sre_compile.compile(pattern)
425 return _regexp_compile_cache[pattern].search(s)
428 class _IncludeState(dict):
429 """Tracks line numbers for includes, and the order in which includes appear.
431 As a dict, an _IncludeState object serves as a mapping between include
432 filename and line number on which that file was included.
434 Call CheckNextIncludeOrder() once for each header in the file, passing
435 in the type constants defined above. Calls in an illegal order will
436 raise an _IncludeError with an appropriate error message.
448 _C_SYS_HEADER:
'C system header',
449 _CPP_SYS_HEADER:
'C++ system header',
450 _LIKELY_MY_HEADER:
'header this file implements',
451 _POSSIBLE_MY_HEADER:
'header this file may implement',
452 _OTHER_HEADER:
'other header',
455 _INITIAL_SECTION:
"... nothing. (This can't be an error.)",
456 _MY_H_SECTION:
'a header this file implements',
457 _C_SECTION:
'C system header',
458 _CPP_SECTION:
'C++ system header',
459 _OTHER_H_SECTION:
'other header',
465 self._section = self._INITIAL_SECTION
467 self._last_header =
''
469 def CanonicalizeAlphabeticalOrder(self, header_path):
470 """Returns a path canonicalized for alphabetical comparison.
472 - replaces "-" with "_" so they both cmp the same.
473 - removes '-inl' since we don't require them to be after the main header.
474 - lowercase everything, just in case.
477 header_path: Path to be canonicalized.
482 return header_path.replace(
'-inl.h',
'.h').replace(
'-',
'_').lower()
484 def IsInAlphabeticalOrder(self, header_path):
485 """Check if a header is in alphabetical order with the previous header.
488 header_path: Header to be checked.
491 Returns true if the header is in alphabetical order.
493 canonical_header = self.CanonicalizeAlphabeticalOrder(header_path)
494 if self._last_header > canonical_header:
496 self._last_header = canonical_header
499 def CheckNextIncludeOrder(self, header_type):
500 """Returns a non-empty error message if the next header is out of order.
502 This function also updates the internal state to be ready to check
506 header_type: One of the _XXX_HEADER constants defined above.
509 The empty string if the header is in the right order, or an
510 error message describing what's wrong.
513 error_message = (
'Found %s after %s' %
514 (self._TYPE_NAMES[header_type],
515 self._SECTION_NAMES[self._section]))
517 last_section = self._section
519 if header_type == _C_SYS_HEADER:
520 if self._section <= self._C_SECTION:
521 self._section = self._C_SECTION
523 self._last_header =
''
525 elif header_type == _CPP_SYS_HEADER:
526 if self._section <= self._CPP_SECTION:
527 self._section = self._CPP_SECTION
529 self._last_header =
''
531 elif header_type == _LIKELY_MY_HEADER:
532 if self._section <= self._MY_H_SECTION:
533 self._section = self._MY_H_SECTION
535 self._section = self._OTHER_H_SECTION
536 elif header_type == _POSSIBLE_MY_HEADER:
537 if self._section <= self._MY_H_SECTION:
538 self._section = self._MY_H_SECTION
542 self._section = self._OTHER_H_SECTION
544 assert header_type == _OTHER_HEADER
545 self._section = self._OTHER_H_SECTION
547 if last_section != self._section:
548 self._last_header =
''
553 class _CppLintState(object):
554 """Maintains module-wide state.."""
557 self.verbose_level = 1
560 self.filters = _DEFAULT_FILTERS[:]
561 self.counting =
'total'
562 self.errors_by_category = {}
567 self.output_format =
'emacs'
569 def SetOutputFormat(self, output_format):
570 """Sets the output format for errors."""
571 self.output_format = output_format
573 def SetVerboseLevel(self, level):
574 """Sets the module's verbosity, and returns the previous setting."""
575 last_verbose_level = self.verbose_level
576 self.verbose_level = level
577 return last_verbose_level
579 def SetCountingStyle(self, counting_style):
580 """Sets the module's counting options."""
581 self.counting = counting_style
583 def SetFilters(self, filters):
584 """Sets the error-message filters.
586 These filters are applied when deciding whether to emit a given
590 filters: A string of comma-separated filters (eg "+whitespace/indent").
591 Each filter should start with + or -; else we die.
594 ValueError: The comma-separated filters did not all start with '+' or '-'.
595 E.g. "-,+whitespace,-whitespace/indent,whitespace/badfilter"
598 self.filters = _DEFAULT_FILTERS[:]
599 for filt
in filters.split(
','):
600 clean_filt = filt.strip()
602 self.filters.append(clean_filt)
603 for filt
in self.filters:
604 if not (filt.startswith(
'+')
or filt.startswith(
'-')):
605 raise ValueError(
'Every filter in --filters must start with + or -'
606 ' (%s does not)' % filt)
608 def ResetErrorCounts(self):
609 """Sets the module's error statistic back to zero."""
611 self.errors_by_category = {}
613 def IncrementErrorCount(self, category):
614 """Bumps the module's error statistic."""
615 self.error_count += 1
616 if self.counting
in (
'toplevel',
'detailed'):
617 if self.counting !=
'detailed':
618 category = category.split(
'/')[0]
619 if category
not in self.errors_by_category:
620 self.errors_by_category[category] = 0
621 self.errors_by_category[category] += 1
623 def PrintErrorCounts(self):
624 """Print a summary of errors by category, and the total."""
625 for category, count
in self.errors_by_category.iteritems():
626 sys.stderr.write(
'Category \'%s\' errors found: %d\n' %
628 sys.stderr.write(
'Total errors found: %d\n' % self.error_count)
630 _cpplint_state = _CppLintState()
634 """Gets the module's output format."""
635 return _cpplint_state.output_format
638 def _SetOutputFormat(output_format):
639 """Sets the module's output format."""
640 _cpplint_state.SetOutputFormat(output_format)
644 """Returns the module's verbosity setting."""
645 return _cpplint_state.verbose_level
648 def _SetVerboseLevel(level):
649 """Sets the module's verbosity, and returns the previous setting."""
650 return _cpplint_state.SetVerboseLevel(level)
653 def _SetCountingStyle(level):
654 """Sets the module's counting options."""
655 _cpplint_state.SetCountingStyle(level)
659 """Returns the module's list of output filters, as a list."""
660 return _cpplint_state.filters
663 def _SetFilters(filters):
664 """Sets the module's error-message filters.
666 These filters are applied when deciding whether to emit a given
670 filters: A string of comma-separated filters (eg "whitespace/indent").
671 Each filter should start with + or -; else we die.
673 _cpplint_state.SetFilters(filters)
676 class _FunctionState(object):
677 """Tracks current function name and the number of lines in its body."""
679 _NORMAL_TRIGGER = 250
683 self.in_a_function =
False
684 self.lines_in_function = 0
685 self.current_function =
''
687 def Begin(self, function_name):
688 """Start analyzing function body.
691 function_name: The name of the function being tracked.
693 self.in_a_function =
True
694 self.lines_in_function = 0
695 self.current_function = function_name
698 """Count line in current function body."""
699 if self.in_a_function:
700 self.lines_in_function += 1
702 def Check(self, error, filename, linenum):
703 """Report if too many lines in function body.
706 error: The function to call with any errors found.
707 filename: The name of the current file.
708 linenum: The number of the line to check.
710 if Match(
r'T(EST|est)', self.current_function):
711 base_trigger = self._TEST_TRIGGER
713 base_trigger = self._NORMAL_TRIGGER
714 trigger = base_trigger * 2**_VerboseLevel()
716 if self.lines_in_function > trigger:
717 error_level = int(math.log(self.lines_in_function / base_trigger, 2))
721 error(filename, linenum,
'readability/fn_size', error_level,
722 'Small and focused functions are preferred:'
723 ' %s has %d non-comment lines'
724 ' (error triggered by exceeding %d lines).' % (
725 self.current_function, self.lines_in_function, trigger))
728 """Stop analyzing function body."""
729 self.in_a_function =
False
732 class _IncludeError(Exception):
733 """Indicates a problem with the include order in a file."""
738 """Provides utility functions for filenames.
740 FileInfo provides easy access to the components of a file's path
741 relative to the project root.
744 def __init__(self, filename):
745 self._filename = filename
748 """Make Windows paths like Unix."""
749 return os.path.abspath(self._filename).replace(
'\\',
'/')
751 def RepositoryName(self):
752 """FullName after removing the local path to the repository.
754 If we have a real absolute path name here we can try to do something smart:
755 detecting the root of the checkout and truncating /path/to/checkout from
756 the name so that we get header guards that don't include things like
757 "C:\Documents and Settings\..." or "/home/username/..." in them and thus
758 people on different computers who have checked the source out to different
759 locations won't see bogus errors.
761 fullname = self.FullName()
763 if os.path.exists(fullname):
764 project_dir = os.path.dirname(fullname)
766 if os.path.exists(os.path.join(project_dir,
".svn")):
769 root_dir = project_dir
770 one_up_dir = os.path.dirname(root_dir)
771 while os.path.exists(os.path.join(one_up_dir,
".svn")):
772 root_dir = os.path.dirname(root_dir)
773 one_up_dir = os.path.dirname(one_up_dir)
775 prefix = os.path.commonprefix([root_dir, project_dir])
776 return fullname[len(prefix) + 1:]
780 root_dir = os.path.dirname(fullname)
781 while (root_dir != os.path.dirname(root_dir)
and
782 not os.path.exists(os.path.join(root_dir,
".git"))
and
783 not os.path.exists(os.path.join(root_dir,
".hg"))
and
784 not os.path.exists(os.path.join(root_dir,
".svn"))):
785 root_dir = os.path.dirname(root_dir)
787 if (os.path.exists(os.path.join(root_dir,
".git"))
or
788 os.path.exists(os.path.join(root_dir,
".hg"))
or
789 os.path.exists(os.path.join(root_dir,
".svn"))):
790 prefix = os.path.commonprefix([root_dir, project_dir])
791 return fullname[len(prefix) + 1:]
797 """Splits the file into the directory, basename, and extension.
799 For 'chrome/browser/browser.cc', Split() would
800 return ('chrome/browser', 'browser', '.cc')
803 A tuple of (directory, basename, extension).
806 googlename = self.RepositoryName()
807 project, rest = os.path.split(googlename)
808 return (project,) + os.path.splitext(rest)
811 """File base name - text after the final slash, before the final period."""
812 return self.Split()[1]
815 """File extension - text following the final period."""
816 return self.Split()[2]
818 def NoExtension(self):
819 """File has no source file extension."""
820 return '/'.join(self.Split()[0:2])
823 """File has a source file extension."""
824 return self.Extension()[1:]
in (
'c',
'cc',
'cpp',
'cxx')
827 def _ShouldPrintError(category, confidence, linenum):
828 """If confidence >= verbose, category passes filter and is not suppressed."""
833 if IsErrorSuppressedByNolint(category, linenum):
835 if confidence < _cpplint_state.verbose_level:
839 for one_filter
in _Filters():
840 if one_filter.startswith(
'-'):
841 if category.startswith(one_filter[1:]):
843 elif one_filter.startswith(
'+'):
844 if category.startswith(one_filter[1:]):
854 def Error(filename, linenum, category, confidence, message):
855 """Logs the fact we've found a lint error.
857 We log where the error was found, and also our confidence in the error,
858 that is, how certain we are this is a legitimate style regression, and
859 not a misidentification or a use that's sometimes justified.
861 False positives can be suppressed by the use of
862 "cpplint(category)" comments on the offending line. These are
863 parsed into _error_suppressions.
866 filename: The name of the file containing the error.
867 linenum: The number of the line containing the error.
868 category: A string used to describe the "category" this bug
869 falls under: "whitespace", say, or "runtime". Categories
870 may have a hierarchy separated by slashes: "whitespace/indent".
871 confidence: A number from 1-5 representing a confidence score for
872 the error, with 5 meaning that we are certain of the problem,
873 and 1 meaning that it could be a legitimate construct.
874 message: The error message.
876 if _ShouldPrintError(category, confidence, linenum):
877 _cpplint_state.IncrementErrorCount(category)
878 if _cpplint_state.output_format ==
'vs7':
879 sys.stderr.write(
'%s(%s): %s [%s] [%d]\n' % (
880 filename, linenum, message, category, confidence))
881 elif _cpplint_state.output_format ==
'eclipse':
882 sys.stderr.write(
'%s:%s: warning: %s [%s] [%d]\n' % (
883 filename, linenum, message, category, confidence))
885 sys.stderr.write(
'%s:%s: %s [%s] [%d]\n' % (
886 filename, linenum, message, category, confidence))
890 _RE_PATTERN_CLEANSE_LINE_ESCAPES = re.compile(
891 r'\\([abfnrtv?"\\\']|\d+|x[0-9a-fA-F]+)')
893 _RE_PATTERN_CLEANSE_LINE_DOUBLE_QUOTES = re.compile(
r'"[^"]*"')
895 _RE_PATTERN_CLEANSE_LINE_SINGLE_QUOTES = re.compile(
r"'.'")
904 _RE_PATTERN_CLEANSE_LINE_C_COMMENTS = re.compile(
905 r"""(\s*/\*.*\*/\s*$|
908 /\*.*\*/)""", re.VERBOSE)
911 def IsCppString(line):
912 """Does line terminate so, that the next symbol is in string constant.
914 This function does not consider single-line nor multi-line comments.
917 line: is a partial line of code starting from the 0..n.
920 True, if next character appended to 'line' is inside a
924 line = line.replace(
r'\\',
'XX')
925 return ((line.count(
'"') - line.count(
r'\"') - line.count(
"'\"'")) & 1) == 1
929 """Find the beginning marker for a multiline comment."""
930 while lineix < len(lines):
931 if lines[lineix].strip().startswith(
'/*'):
933 if lines[lineix].strip().find(
'*/', 2) < 0:
940 """We are inside a comment, find the end marker."""
941 while lineix < len(lines):
942 if lines[lineix].strip().endswith(
'*/'):
949 """Clears a range of lines for multi-line comments."""
952 for i
in range(begin, end):
953 lines[i] =
'// dummy'
957 """Removes multiline (c-style) comments from lines."""
959 while lineix < len(lines):
961 if lineix_begin >= len(lines):
964 if lineix_end >= len(lines):
965 error(filename, lineix_begin + 1,
'readability/multiline_comment', 5,
966 'Could not find end of multi-line comment')
969 lineix = lineix_end + 1
973 """Removes //-comments and single-line C-style /* */ comments.
976 line: A line of C++ source.
979 The line with single-line comments removed.
981 commentpos = line.find(
'//')
982 if commentpos != -1
and not IsCppString(line[:commentpos]):
983 line = line[:commentpos].rstrip()
985 return _RE_PATTERN_CLEANSE_LINE_C_COMMENTS.sub(
'', line)
989 """Holds 3 copies of all lines with different preprocessing applied to them.
991 1) elided member contains lines without strings and comments,
992 2) lines member contains lines without comments, and
993 3) raw_lines member contains all the lines without processing.
994 All these three members are of <type 'list'>, and of the same length.
1002 for linenum
in range(len(lines)):
1008 """Returns the number of lines represented."""
1013 """Collapses strings and chars on a line to simple "" or '' blocks.
1015 We nix strings first so we're not fooled by text like '"http://"'
1018 elided: The line being processed.
1021 The line with collapsed strings.
1023 if not _RE_PATTERN_INCLUDE.match(elided):
1027 elided = _RE_PATTERN_CLEANSE_LINE_ESCAPES.sub(
'', elided)
1028 elided = _RE_PATTERN_CLEANSE_LINE_SINGLE_QUOTES.sub(
"''", elided)
1029 elided = _RE_PATTERN_CLEANSE_LINE_DOUBLE_QUOTES.sub(
'""', elided)
1034 """Find the position just after the matching endchar.
1037 line: a CleansedLines line.
1038 startpos: start searching at this position.
1039 depth: nesting level at startpos.
1040 startchar: expression opening character.
1041 endchar: expression closing character.
1044 Index just after endchar.
1046 for i
in xrange(startpos, len(line)):
1047 if line[i] == startchar:
1049 elif line[i] == endchar:
1057 """If input points to ( or { or [, finds the position that closes it.
1059 If lines[linenum][pos] points to a '(' or '{' or '[', finds the
1060 linenum/pos that correspond to the closing of the expression.
1063 clean_lines: A CleansedLines instance containing the file.
1064 linenum: The number of the line to check.
1065 pos: A position on the line.
1068 A tuple (line, linenum, pos) pointer *past* the closing brace, or
1069 (line, len(lines), -1) if we never find a close. Note we ignore
1070 strings and comments when matching; and the line we return is the
1071 'cleansed' line at linenum.
1074 line = clean_lines.elided[linenum]
1075 startchar = line[pos]
1076 if startchar
not in '({[':
1077 return (line, clean_lines.NumLines(), -1)
1078 if startchar ==
'(': endchar =
')'
1079 if startchar ==
'[': endchar =
']'
1080 if startchar ==
'{': endchar =
'}'
1085 return (line, linenum, end_pos)
1087 num_open = tail.count(startchar) - tail.count(endchar)
1088 while linenum < clean_lines.NumLines() - 1:
1090 line = clean_lines.elided[linenum]
1091 delta = line.count(startchar) - line.count(endchar)
1092 if num_open + delta <= 0:
1093 return (line, linenum,
1098 return (line, clean_lines.NumLines(), -1)
1101 """Logs an error if no Copyright message appears at the top of the file."""
1105 for line
in xrange(1,
min(len(lines), 11)):
1106 if re.search(
r'Copyright', lines[line], re.I):
break
1108 error(filename, 0,
'legal/copyright', 5,
1109 'No copyright message found. '
1110 'You should have a line: "Copyright [year] <Copyright Owner>"')
1114 """Returns the CPP variable that should be used as a header guard.
1117 filename: The name of a C++ header file.
1120 The CPP variable that should be used as a header guard in the
1127 filename = re.sub(
r'_flymake\.h$',
'.h', filename)
1128 filename = re.sub(
r'/\.flymake/([^/]*)$',
r'/\1', filename)
1130 fileinfo = FileInfo(filename)
1131 file_path_from_root = fileinfo.RepositoryName()
1133 file_path_from_root = re.sub(
'^' + _root + os.sep,
'', file_path_from_root)
1134 return re.sub(
r'[-./\s]',
'_', file_path_from_root).upper() +
'_'
1138 """Checks that the file contains a header guard.
1140 Logs an error if no #ifndef header guard is present. For other
1141 headers, checks that the full pathname is used.
1144 filename: The name of the C++ header file.
1145 lines: An array of strings, each representing a line of the file.
1146 error: The function to call with any errors found.
1156 for linenum, line
in enumerate(lines):
1157 linesplit = line.split()
1158 if len(linesplit) >= 2:
1160 if not ifndef
and linesplit[0] ==
'#ifndef':
1162 ifndef = linesplit[1]
1163 ifndef_linenum = linenum
1164 if not define
and linesplit[0] ==
'#define':
1165 define = linesplit[1]
1167 if line.startswith(
'#endif'):
1169 endif_linenum = linenum
1172 error(filename, 0,
'build/header_guard', 5,
1173 'No #ifndef header guard found, suggested CPP variable is: %s' %
1178 error(filename, 0,
'build/header_guard', 5,
1179 'No #define header guard found, suggested CPP variable is: %s' %
1185 if ifndef != cppvar:
1187 if ifndef != cppvar +
'_':
1190 ParseNolintSuppressions(filename, lines[ifndef_linenum], ifndef_linenum,
1192 error(filename, ifndef_linenum,
'build/header_guard', error_level,
1193 '#ifndef header guard has wrong style, please use: %s' % cppvar)
1195 if define != ifndef:
1196 error(filename, 0,
'build/header_guard', 5,
1197 '#ifndef and #define don\'t match, suggested CPP variable is: %s' %
1201 if endif != (
'#endif // %s' % cppvar):
1203 if endif != (
'#endif // %s' % (cppvar +
'_')):
1206 ParseNolintSuppressions(filename, lines[endif_linenum], endif_linenum,
1208 error(filename, endif_linenum,
'build/header_guard', error_level,
1209 '#endif line should be "#endif // %s"' % cppvar)
1213 """Logs an error for each line containing Unicode replacement characters.
1215 These indicate that either the file contained invalid UTF-8 (likely)
1216 or Unicode replacement characters (which it shouldn't). Note that
1217 it's possible for this to throw off line numbering if the invalid
1218 UTF-8 occurred adjacent to a newline.
1221 filename: The name of the current file.
1222 lines: An array of strings, each representing a line of the file.
1223 error: The function to call with any errors found.
1225 for linenum, line
in enumerate(lines):
1226 if u'\ufffd' in line:
1227 error(filename, linenum,
'readability/utf8', 5,
1228 'Line contains invalid UTF-8 (or Unicode replacement character).')
1232 """Logs an error if there is no newline char at the end of the file.
1235 filename: The name of the current file.
1236 lines: An array of strings, each representing a line of the file.
1237 error: The function to call with any errors found.
1244 if len(lines) < 3
or lines[-2]:
1245 error(filename, len(lines) - 2,
'whitespace/ending_newline', 5,
1246 'Could not find a newline character at the end of the file.')
1250 """Logs an error if we see /* ... */ or "..." that extend past one line.
1252 /* ... */ comments are legit inside macros, for one line.
1253 Otherwise, we prefer // comments, so it's ok to warn about the
1254 other. Likewise, it's ok for strings to extend across multiple
1255 lines, as long as a line continuation character (backslash)
1256 terminates each line. Although not currently prohibited by the C++
1257 style guide, it's ugly and unnecessary. We don't do well with either
1258 in this lint program, so we warn about both.
1261 filename: The name of the current file.
1262 clean_lines: A CleansedLines instance containing the file.
1263 linenum: The number of the line to check.
1264 error: The function to call with any errors found.
1266 line = clean_lines.elided[linenum]
1270 line = line.replace(
'\\\\',
'')
1272 if line.count(
'/*') > line.count(
'*/'):
1273 error(filename, linenum,
'readability/multiline_comment', 5,
1274 'Complex multi-line /*...*/-style comment found. '
1275 'Lint may give bogus warnings. '
1276 'Consider replacing these with //-style comments, '
1277 'with #if 0...#endif, '
1278 'or with more clearly structured multi-line comments.')
1280 if (line.count(
'"') - line.count(
'\\"')) % 2:
1281 error(filename, linenum,
'readability/multiline_string', 5,
1282 'Multi-line string ("...") found. This lint script doesn\'t '
1283 'do well with such strings, and may give bogus warnings. They\'re '
1284 'ugly and unnecessary, and you should use concatenation instead".')
1288 (
'asctime(',
'asctime_r('),
1289 (
'ctime(',
'ctime_r('),
1290 (
'getgrgid(',
'getgrgid_r('),
1291 (
'getgrnam(',
'getgrnam_r('),
1292 (
'getlogin(',
'getlogin_r('),
1293 (
'getpwnam(',
'getpwnam_r('),
1294 (
'getpwuid(',
'getpwuid_r('),
1295 (
'gmtime(',
'gmtime_r('),
1296 (
'localtime(',
'localtime_r('),
1297 (
'rand(',
'rand_r('),
1298 (
'readdir(',
'readdir_r('),
1299 (
'strtok(',
'strtok_r('),
1300 (
'ttyname(',
'ttyname_r('),
1304 def CheckPosixThreading(filename, clean_lines, linenum, error):
1305 """Checks for calls to thread-unsafe functions.
1307 Much code has been originally written without consideration of
1308 multi-threading. Also, engineers are relying on their old experience;
1309 they have learned posix before threading extensions were added. These
1310 tests guide the engineers to use thread-safe functions (when using
1314 filename: The name of the current file.
1315 clean_lines: A CleansedLines instance containing the file.
1316 linenum: The number of the line to check.
1317 error: The function to call with any errors found.
1319 line = clean_lines.elided[linenum]
1320 for single_thread_function, multithread_safe_function
in threading_list:
1321 ix = line.find(single_thread_function)
1323 if ix >= 0
and (ix == 0
or (
not line[ix - 1].isalnum()
and
1324 line[ix - 1]
not in (
'_',
'.',
'>'))):
1325 error(filename, linenum,
'runtime/threadsafe_fn', 2,
1326 'Consider using ' + multithread_safe_function +
1327 '...) instead of ' + single_thread_function +
1328 '...) for improved thread safety.')
1333 _RE_PATTERN_INVALID_INCREMENT = re.compile(
1334 r'^\s*\*\w+(\+\+|--);')
1337 def CheckInvalidIncrement(filename, clean_lines, linenum, error):
1338 """Checks for invalid increment *count++.
1340 For example following function:
1341 void increment_counter(int* count) {
1344 is invalid, because it effectively does count++, moving pointer, and should
1345 be replaced with ++*count, (*count)++ or *count += 1.
1348 filename: The name of the current file.
1349 clean_lines: A CleansedLines instance containing the file.
1350 linenum: The number of the line to check.
1351 error: The function to call with any errors found.
1353 line = clean_lines.elided[linenum]
1354 if _RE_PATTERN_INVALID_INCREMENT.match(line):
1355 error(filename, linenum,
'runtime/invalid_increment', 5,
1356 'Changing pointer instead of value (or unused value of operator*).')
1359 class _BlockInfo(object):
1360 """Stores information about a generic block of code."""
1362 def __init__(self, seen_open_brace):
1363 self.seen_open_brace = seen_open_brace
1364 self.open_parentheses = 0
1365 self.inline_asm = _NO_ASM
1367 def CheckBegin(self, filename, clean_lines, linenum, error):
1368 """Run checks that applies to text up to the opening brace.
1370 This is mostly for checking the text after the class identifier
1371 and the "{", usually where the base class is specified. For other
1372 blocks, there isn't much to check, so we always pass.
1375 filename: The name of the current file.
1376 clean_lines: A CleansedLines instance containing the file.
1377 linenum: The number of the line to check.
1378 error: The function to call with any errors found.
1382 def CheckEnd(self, filename, clean_lines, linenum, error):
1383 """Run checks that applies to text after the closing brace.
1385 This is mostly used for checking end of namespace comments.
1388 filename: The name of the current file.
1389 clean_lines: A CleansedLines instance containing the file.
1390 linenum: The number of the line to check.
1391 error: The function to call with any errors found.
1396 class _ClassInfo(_BlockInfo):
1397 """Stores information about a class."""
1399 def __init__(self, name, class_or_struct, clean_lines, linenum):
1400 _BlockInfo.__init__(self,
False)
1402 self.starting_linenum = linenum
1403 self.is_derived =
False
1404 if class_or_struct ==
'struct':
1405 self.access =
'public'
1407 self.access =
'private'
1416 for i
in range(linenum, clean_lines.NumLines()):
1417 line = clean_lines.elided[i]
1418 depth += line.count(
'{') - line.count(
'}')
1423 def CheckBegin(self, filename, clean_lines, linenum, error):
1425 if Search(
'(^|[^:]):($|[^:])', clean_lines.elided[linenum]):
1426 self.is_derived =
True
1429 class _NamespaceInfo(_BlockInfo):
1430 """Stores information about a namespace."""
1432 def __init__(self, name, linenum):
1433 _BlockInfo.__init__(self,
False)
1434 self.name = name
or ''
1435 self.starting_linenum = linenum
1437 def CheckEnd(self, filename, clean_lines, linenum, error):
1438 """Check end of namespace comments."""
1439 line = clean_lines.raw_lines[linenum]
1452 if (linenum - self.starting_linenum < 10
1453 and not Match(
r'};*\s*(//|/\*).*\bnamespace\b', line)):
1470 if not Match((
r'};*\s*(//|/\*).*\bnamespace\s+' + re.escape(self.name) +
1473 error(filename, linenum,
'readability/namespace', 5,
1474 'Namespace should be terminated with "// namespace %s"' %
1478 if not Match(
r'};*\s*(//|/\*).*\bnamespace[\*/\.\\\s]*$', line):
1479 error(filename, linenum,
'readability/namespace', 5,
1480 'Namespace should be terminated with "// namespace"')
1483 class _PreprocessorInfo(object):
1484 """Stores checkpoints of nesting stacks when #if/#else is seen."""
1486 def __init__(self, stack_before_if):
1488 self.stack_before_if = stack_before_if
1491 self.stack_before_else = []
1494 self.seen_else =
False
1497 class _NestingState(object):
1498 """Holds states related to parsing braces."""
1512 def SeenOpenBrace(self):
1513 """Check if we have seen the opening brace for the innermost block.
1516 True if we have seen the opening brace, False if the innermost
1517 block is still expecting an opening brace.
1519 return (
not self.stack)
or self.stack[-1].seen_open_brace
1521 def InNamespaceBody(self):
1522 """Check if we are currently one level inside a namespace body.
1525 True if top of the stack is a namespace block, False otherwise.
1527 return self.stack
and isinstance(self.stack[-1], _NamespaceInfo)
1529 def UpdatePreprocessor(self, line):
1530 """Update preprocessor stack.
1532 We need to handle preprocessors due to classes like this:
1534 struct ResultDetailsPageElementExtensionPoint {
1536 struct ResultDetailsPageElementExtensionPoint : public Extension {
1538 (see http://go/qwddn for original example)
1540 We make the following assumptions (good enough for most files):
1541 - Preprocessor condition evaluates to true from #if up to first
1544 - Preprocessor condition evaluates to false from #else/#elif up
1545 to #endif. We still perform lint checks on these lines, but
1546 these do not affect nesting stack.
1549 line: current line to check.
1551 if Match(
r'^\s*#\s*(if|ifdef|ifndef)\b', line):
1554 self.pp_stack.append(_PreprocessorInfo(copy.deepcopy(self.stack)))
1555 elif Match(
r'^\s*#\s*(else|elif)\b', line):
1558 if not self.pp_stack[-1].seen_else:
1562 self.pp_stack[-1].seen_else =
True
1563 self.pp_stack[-1].stack_before_else = copy.deepcopy(self.stack)
1566 self.stack = copy.deepcopy(self.pp_stack[-1].stack_before_if)
1570 elif Match(
r'^\s*#\s*endif\b', line):
1576 if self.pp_stack[-1].seen_else:
1579 self.stack = self.pp_stack[-1].stack_before_else
1586 def Update(self, filename, clean_lines, linenum, error):
1587 """Update nesting state with current line.
1590 filename: The name of the current file.
1591 clean_lines: A CleansedLines instance containing the file.
1592 linenum: The number of the line to check.
1593 error: The function to call with any errors found.
1595 line = clean_lines.elided[linenum]
1598 self.UpdatePreprocessor(line)
1603 inner_block = self.stack[-1]
1604 depth_change = line.count(
'(') - line.count(
')')
1605 inner_block.open_parentheses += depth_change
1608 if inner_block.inline_asm
in (_NO_ASM, _END_ASM):
1609 if (depth_change != 0
and
1610 inner_block.open_parentheses == 1
and
1611 _MATCH_ASM.match(line)):
1613 inner_block.inline_asm = _INSIDE_ASM
1617 inner_block.inline_asm = _NO_ASM
1618 elif (inner_block.inline_asm == _INSIDE_ASM
and
1619 inner_block.open_parentheses == 0):
1621 inner_block.inline_asm = _END_ASM
1631 namespace_decl_match = Match(
r'^\s*namespace\b\s*([:\w]+)?(.*)$', line)
1632 if not namespace_decl_match:
1635 new_namespace = _NamespaceInfo(namespace_decl_match.group(1), linenum)
1636 self.stack.append(new_namespace)
1638 line = namespace_decl_match.group(2)
1639 if line.find(
'{') != -1:
1640 new_namespace.seen_open_brace =
True
1641 line = line[line.find(
'{') + 1:]
1664 class_decl_match = Match(
1665 r'\s*(template\s*<[\w\s<>,:]*>\s*)?'
1666 '(class|struct)\s+([A-Z_]+\s+)*(\w+(?:::\w+)*)'
1667 '(([^=>]|<[^<>]*>)*)$', line)
1668 if (class_decl_match
and
1669 (
not self.stack
or self.stack[-1].open_parentheses == 0)):
1670 self.stack.append(_ClassInfo(
1671 class_decl_match.group(4), class_decl_match.group(2),
1672 clean_lines, linenum))
1673 line = class_decl_match.group(5)
1677 if not self.SeenOpenBrace():
1678 self.stack[-1].CheckBegin(filename, clean_lines, linenum, error)
1681 if self.stack
and isinstance(self.stack[-1], _ClassInfo):
1682 access_match = Match(
r'\s*(public|private|protected)\s*:', line)
1684 self.stack[-1].access = access_match.group(1)
1689 matched = Match(
r'^[^{;)}]*([{;)}])(.*)$', line)
1693 token = matched.group(1)
1698 if not self.SeenOpenBrace():
1699 self.stack[-1].seen_open_brace =
True
1701 self.stack.append(_BlockInfo(
True))
1702 if _MATCH_ASM.match(line):
1703 self.stack[-1].inline_asm = _BLOCK_ASM
1704 elif token ==
';' or token ==
')':
1713 if not self.SeenOpenBrace():
1718 self.stack[-1].CheckEnd(filename, clean_lines, linenum, error)
1720 line = matched.group(2)
1722 def InnermostClass(self):
1723 """Get class info on the top of the stack.
1726 A _ClassInfo object if we are inside a class, or None otherwise.
1728 for i
in range(len(self.stack), 0, -1):
1729 classinfo = self.stack[i - 1]
1730 if isinstance(classinfo, _ClassInfo):
1734 def CheckClassFinished(self, filename, error):
1735 """Checks that all classes have been completely parsed.
1737 Call this when all lines in a file have been processed.
1739 filename: The name of the current file.
1740 error: The function to call with any errors found.
1745 for obj
in self.stack:
1746 if isinstance(obj, _ClassInfo):
1747 error(filename, obj.starting_linenum,
'build/class', 5,
1748 'Failed to find complete declaration of class %s' %
1752 def CheckForNonStandardConstructs(filename, clean_lines, linenum,
1753 nesting_state, error):
1754 """Logs an error if we see certain non-ANSI constructs ignored by gcc-2.
1756 Complain about several constructs which gcc-2 accepts, but which are
1757 not standard C++. Warning about these in lint is one way to ease the
1758 transition to new compilers.
1759 - put storage class first (e.g. "static const" instead of "const static").
1760 - "%lld" instead of %qd" in printf-type functions.
1761 - "%1$d" is non-standard in printf-type functions.
1762 - "\%" is an undefined character escape sequence.
1763 - text after #endif is not allowed.
1764 - invalid inner-style forward declaration.
1765 - >? and <? operators, and their >?= and <?= cousins.
1767 Additionally, check for constructor/destructor style violations and reference
1768 members, as it is very convenient to do so while checking for
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 nesting_state: A _NestingState instance which maintains information about
1776 the current stack of nested blocks being parsed.
1777 error: A callable to which errors are reported, which takes 4 arguments:
1778 filename, line number, error level, and message
1782 line = clean_lines.lines[linenum]
1784 if Search(
r'printf\s*\(.*".*%[-+ ]?\d*q', line):
1785 error(filename, linenum,
'runtime/printf_format', 3,
1786 '%q in format strings is deprecated. Use %ll instead.')
1788 if Search(
r'printf\s*\(.*".*%\d+\$', line):
1789 error(filename, linenum,
'runtime/printf_format', 2,
1790 '%N$ formats are unconventional. Try rewriting to avoid them.')
1793 line = line.replace(
'\\\\',
'')
1795 if Search(
r'("|\').*\\(%|\[|\(|{)', line):
1796 error(filename, linenum,
'build/printf_format', 3,
1797 '%, [, (, and { are undefined character escapes. Unescape them.')
1800 line = clean_lines.elided[linenum]
1802 if Search(
r'\b(const|volatile|void|char|short|int|long'
1803 r'|float|double|signed|unsigned'
1804 r'|schar|u?int8|u?int16|u?int32|u?int64)'
1805 r'\s+(register|static|extern|typedef)\b',
1807 error(filename, linenum,
'build/storage_class', 5,
1808 'Storage class (static, extern, typedef, etc) should be first.')
1810 if Match(
r'\s*#\s*endif\s*[^/\s]+', line):
1811 error(filename, linenum,
'build/endif_comment', 5,
1812 'Uncommented text after #endif is non-standard. Use a comment.')
1814 if Match(
r'\s*class\s+(\w+\s*::\s*)+\w+\s*;', line):
1815 error(filename, linenum,
'build/forward_decl', 5,
1816 'Inner-style forward declarations are invalid. Remove this line.')
1818 if Search(
r'(\w+|[+-]?\d+(\.\d*)?)\s*(<|>)\?=?\s*(\w+|[+-]?\d+)(\.\d*)?',
1820 error(filename, linenum,
'build/deprecated', 3,
1821 '>? and <? (max and min) operators are non-standard and deprecated.')
1823 if Search(
r'^\s*const\s*string\s*&\s*\w+\s*;', line):
1831 error(filename, linenum,
'runtime/member_string_references', 2,
1832 'const string& members are dangerous. It is much better to use '
1833 'alternatives, such as pointers or simple constants.')
1838 classinfo = nesting_state.InnermostClass()
1839 if not classinfo
or not classinfo.seen_open_brace:
1844 base_classname = classinfo.name.split(
'::')[-1]
1848 args = Match(
r'\s+(?:inline\s+)?%s\s*\(([^,()]+)\)'
1849 % re.escape(base_classname),
1852 args.group(1) !=
'void' and
1853 not Match(
r'(const\s+)?%s\s*(?:<\w+>\s*)?&' % re.escape(base_classname),
1854 args.group(1).strip())):
1855 error(filename, linenum,
'runtime/explicit', 5,
1856 'Single-argument constructors should be marked explicit.')
1859 def CheckSpacingForFunctionCall(filename, line, linenum, error):
1860 """Checks for the correctness of various spacing around function calls.
1863 filename: The name of the current file.
1864 line: The text of the line to check.
1865 linenum: The number of the line to check.
1866 error: The function to call with any errors found.
1874 for pattern
in (
r'\bif\s*\((.*)\)\s*{',
1875 r'\bfor\s*\((.*)\)\s*{',
1876 r'\bwhile\s*\((.*)\)\s*[{;]',
1877 r'\bswitch\s*\((.*)\)\s*{'):
1878 match = Search(pattern, line)
1880 fncall = match.group(1)
1897 not Search(
r'\b(if|for|while|switch|return|delete)\b', fncall)
and
1899 not Search(
r' \([^)]+\)\([^)]*(\)|,$)', fncall)
and
1901 not Search(
r' \([^)]+\)\[[^\]]+\]', fncall)):
1902 if Search(
r'\w\s*\(\s(?!\s*\\$)', fncall):
1903 error(filename, linenum,
'whitespace/parens', 4,
1904 'Extra space after ( in function call')
1905 elif Search(
r'\(\s+(?!(\s*\\)|\()', fncall):
1906 error(filename, linenum,
'whitespace/parens', 2,
1907 'Extra space after (')
1908 if (Search(
r'\w\s+\(', fncall)
and
1909 not Search(
r'#\s*define|typedef', fncall)
and
1910 not Search(
r'\w\s+\((\w+::)?\*\w+\)\(', fncall)):
1911 error(filename, linenum,
'whitespace/parens', 4,
1912 'Extra space before ( in function call')
1915 if Search(
r'[^)]\s+\)\s*[^{\s]', fncall):
1918 if Search(
r'^\s+\)', fncall):
1919 error(filename, linenum,
'whitespace/parens', 2,
1920 'Closing ) should be moved to the previous line')
1922 error(filename, linenum,
'whitespace/parens', 2,
1923 'Extra space before )')
1926 def IsBlankLine(line):
1927 """Returns true if the given line is blank.
1929 We consider a line to be blank if the line is empty or consists of
1933 line: A line of a string.
1936 True, if the given line is blank.
1938 return not line
or line.isspace()
1941 def CheckForFunctionLengths(filename, clean_lines, linenum,
1942 function_state, error):
1943 """Reports for long function bodies.
1945 For an overview why this is done, see:
1946 http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Write_Short_Functions
1948 Uses a simplistic algorithm assuming other style guidelines
1949 (especially spacing) are followed.
1950 Only checks unindented functions, so class members are unchecked.
1951 Trivial bodies are unchecked, so constructors with huge initializer lists
1953 Blank/comment lines are not counted so as to avoid encouraging the removal
1954 of vertical space and comments just to get through a lint check.
1955 NOLINT *on the last line of a function* disables this check.
1958 filename: The name of the current file.
1959 clean_lines: A CleansedLines instance containing the file.
1960 linenum: The number of the line to check.
1961 function_state: Current function name and lines in body so far.
1962 error: The function to call with any errors found.
1964 lines = clean_lines.lines
1965 line = lines[linenum]
1966 raw = clean_lines.raw_lines
1967 raw_line = raw[linenum]
1970 starting_func =
False
1971 regexp =
r'(\w(\w|::|\*|\&|\s)*)\('
1972 match_result = Match(regexp, line)
1976 function_name = match_result.group(1).split()[-1]
1977 if function_name ==
'TEST' or function_name ==
'TEST_F' or (
1978 not Match(
r'[A-Z_]+$', function_name)):
1979 starting_func =
True
1983 for start_linenum
in xrange(linenum, clean_lines.NumLines()):
1984 start_line = lines[start_linenum]
1985 joined_line +=
' ' + start_line.lstrip()
1986 if Search(
r'(;|})', start_line):
1989 elif Search(
r'{', start_line):
1991 function = Search(
r'((\w|:)*)\(', line).group(1)
1992 if Match(
r'TEST', function):
1993 parameter_regexp = Search(
r'(\(.*\))', joined_line)
1994 if parameter_regexp:
1995 function += parameter_regexp.group(1)
1998 function_state.Begin(function)
2002 error(filename, linenum,
'readability/fn_size', 5,
2003 'Lint failed to find start of function body.')
2004 elif Match(
r'^\}\s*$', line):
2005 function_state.Check(error, filename, linenum)
2006 function_state.End()
2007 elif not Match(
r'^\s*$', line):
2008 function_state.Count()
2011 _RE_PATTERN_TODO = re.compile(
r'^//(\s*)TODO(\(.+?\))?:?(\s|$)?')
2014 def CheckComment(comment, filename, linenum, error):
2015 """Checks for common mistakes in TODO comments.
2018 comment: The text of the comment from the line in question.
2019 filename: The name of the current file.
2020 linenum: The number of the line to check.
2021 error: The function to call with any errors found.
2023 match = _RE_PATTERN_TODO.match(comment)
2026 leading_whitespace = match.group(1)
2027 if len(leading_whitespace) > 1:
2028 error(filename, linenum,
'whitespace/todo', 2,
2029 'Too many spaces before TODO')
2031 username = match.group(2)
2033 error(filename, linenum,
'readability/todo', 2,
2034 'Missing username in TODO; it should look like '
2035 '"// TODO(my_username): Stuff."')
2037 middle_whitespace = match.group(3)
2039 if middle_whitespace !=
' ' and middle_whitespace !=
'':
2040 error(filename, linenum,
'whitespace/todo', 2,
2041 'TODO(my_username) should be followed by a space')
2043 def CheckAccess(filename, clean_lines, linenum, nesting_state, error):
2044 """Checks for improper use of DISALLOW* macros.
2047 filename: The name of the current file.
2048 clean_lines: A CleansedLines instance containing the file.
2049 linenum: The number of the line to check.
2050 nesting_state: A _NestingState instance which maintains information about
2051 the current stack of nested blocks being parsed.
2052 error: The function to call with any errors found.
2054 line = clean_lines.elided[linenum]
2056 matched = Match((
r'\s*(DISALLOW_COPY_AND_ASSIGN|'
2057 r'DISALLOW_EVIL_CONSTRUCTORS|'
2058 r'DISALLOW_IMPLICIT_CONSTRUCTORS)'), line)
2061 if nesting_state.stack
and isinstance(nesting_state.stack[-1], _ClassInfo):
2062 if nesting_state.stack[-1].access !=
'private':
2063 error(filename, linenum,
'readability/constructors', 3,
2064 '%s must be in the private: section' % matched.group(1))
2074 def FindNextMatchingAngleBracket(clean_lines, linenum, init_suffix):
2075 """Find the corresponding > to close a template.
2078 clean_lines: A CleansedLines instance containing the file.
2079 linenum: Current line number.
2080 init_suffix: Remainder of the current line after the initial <.
2083 True if a matching bracket exists.
2086 nesting_stack = [
'<']
2097 match = Search(
r'^[^<>(),;\[\]]*([<>(),;\[\]])(.*)$', line)
2100 operator = match.group(1)
2101 line = match.group(2)
2103 if nesting_stack[-1] ==
'<':
2105 if operator
in (
'<',
'(',
'['):
2106 nesting_stack.append(operator)
2107 elif operator ==
'>':
2109 if not nesting_stack:
2112 elif operator ==
',':
2124 if operator
in (
'<',
'(',
'['):
2125 nesting_stack.append(operator)
2126 elif operator
in (
')',
']'):
2134 if linenum >= len(clean_lines.elided):
2136 line = clean_lines.elided[linenum]
2144 def FindPreviousMatchingAngleBracket(clean_lines, linenum, init_prefix):
2145 """Find the corresponding < that started a template.
2148 clean_lines: A CleansedLines instance containing the file.
2149 linenum: Current line number.
2150 init_prefix: Part of the current line before the initial >.
2153 True if a matching bracket exists.
2156 nesting_stack = [
'>']
2159 match = Search(
r'^(.*)([<>(),;\[\]])[^<>(),;\[\]]*$', line)
2162 operator = match.group(2)
2163 line = match.group(1)
2165 if nesting_stack[-1] ==
'>':
2167 if operator
in (
'>',
')',
']'):
2168 nesting_stack.append(operator)
2169 elif operator ==
'<':
2171 if not nesting_stack:
2174 elif operator ==
',':
2185 if operator
in (
'>',
')',
']'):
2186 nesting_stack.append(operator)
2187 elif operator
in (
'(',
'['):
2195 line = clean_lines.elided[linenum]
2201 def CheckSpacing(filename, clean_lines, linenum, nesting_state, error):
2202 """Checks for the correctness of various spacing issues in the code.
2204 Things we check for: spaces around operators, spaces after
2205 if/for/while/switch, no spaces around parens in function calls, two
2206 spaces between code and comment, don't start a block with a blank
2207 line, don't end a function with a blank line, don't add a blank line
2208 after public/protected/private, don't have too many blank lines in a row.
2211 filename: The name of the current file.
2212 clean_lines: A CleansedLines instance containing the file.
2213 linenum: The number of the line to check.
2214 nesting_state: A _NestingState instance which maintains information about
2215 the current stack of nested blocks being parsed.
2216 error: The function to call with any errors found.
2219 raw = clean_lines.raw_lines
2234 if IsBlankLine(line)
and not nesting_state.InNamespaceBody():
2235 elided = clean_lines.elided
2236 prev_line = elided[linenum - 1]
2237 prevbrace = prev_line.rfind(
'{')
2242 if prevbrace != -1
and prev_line[prevbrace:].find(
'}') == -1:
2251 if Match(
r' {6}\w', prev_line):
2254 search_position = linenum-2
2255 while (search_position >= 0
2256 and Match(
r' {6}\w', elided[search_position])):
2257 search_position -= 1
2258 exception = (search_position >= 0
2259 and elided[search_position][:5] ==
' :')
2267 exception = (Match(
r' {4}\w[^\(]*\)\s*(const\s*)?(\{\s*$|:)',
2269 or Match(
r' {4}:', prev_line))
2272 error(filename, linenum,
'whitespace/blank_line', 2,
2273 'Blank line at the start of a code block. Is this needed?')
2282 if linenum + 1 < clean_lines.NumLines():
2283 next_line = raw[linenum + 1]
2285 and Match(
r'\s*}', next_line)
2286 and next_line.find(
'} else ') == -1):
2287 error(filename, linenum,
'whitespace/blank_line', 3,
2288 'Blank line at the end of a code block. Is this needed?')
2290 matched = Match(
r'\s*(public|protected|private):', prev_line)
2292 error(filename, linenum,
'whitespace/blank_line', 3,
2293 'Do not leave a blank line after "%s:"' % matched.group(1))
2296 commentpos = line.find(
'//')
2297 if commentpos != -1:
2300 if (line.count(
'"', 0, commentpos) -
2301 line.count(
'\\"', 0, commentpos)) % 2 == 0:
2303 if (
not Match(
r'^\s*{ //', line)
and
2304 ((commentpos >= 1
and
2305 line[commentpos-1]
not in string.whitespace)
or
2306 (commentpos >= 2
and
2307 line[commentpos-2]
not in string.whitespace))):
2308 error(filename, linenum,
'whitespace/comments', 2,
2309 'At least two spaces is best between code and comments')
2311 commentend = commentpos + 2
2312 if commentend < len(line)
and not line[commentend] ==
' ':
2320 match = (Search(
r'[=/-]{4,}\s*$', line[commentend:])
or
2321 Search(
r'^/$', line[commentend:])
or
2322 Search(
r'^/+ ', line[commentend:]))
2324 error(filename, linenum,
'whitespace/comments', 4,
2325 'Should have a space between // and comment')
2326 CheckComment(line[commentpos:], filename, linenum, error)
2328 line = clean_lines.elided[linenum]
2331 line = re.sub(
r'operator(==|!=|<|<<|<=|>=|>>|>)\(',
'operator\(', line)
2337 if Search(
r'[\w.]=[\w.]', line)
and not Search(
r'\b(if|while) ', line):
2338 error(filename, linenum,
'whitespace/operators', 4,
2339 'Missing spaces around =')
2349 match = Search(
r'[^<>=!\s](==|!=|<=|>=)[^<>=!\s]', line)
2351 error(filename, linenum,
'whitespace/operators', 3,
2352 'Missing spaces around %s' % match.group(1))
2355 match = Search(
r'(\S)(?:L|UL|ULL|l|ul|ull)?<<(\S)', line)
2356 if match
and not (match.group(1).isdigit()
and match.group(2).isdigit()):
2357 error(filename, linenum,
'whitespace/operators', 3,
2358 'Missing spaces around <<')
2359 elif not Match(
r'#.*include', line):
2361 reduced_line = line.replace(
'->',
'')
2367 match = Search(
r'[^\s<]<([^\s=<].*)', reduced_line)
2369 not FindNextMatchingAngleBracket(clean_lines, linenum, match.group(1))):
2370 error(filename, linenum,
'whitespace/operators', 3,
2371 'Missing spaces around <')
2376 match = Search(
r'^(.*[^\s>])>[^\s=>]', reduced_line)
2378 not FindPreviousMatchingAngleBracket(clean_lines, linenum,
2380 error(filename, linenum,
'whitespace/operators', 3,
2381 'Missing spaces around >')
2395 match = Search(
r'>>[a-zA-Z_]', line)
2397 error(filename, linenum,
'whitespace/operators', 3,
2398 'Missing spaces around >>')
2401 match = Search(
r'(!\s|~\s|[\s]--[\s;]|[\s]\+\+[\s;])', line)
2403 error(filename, linenum,
'whitespace/operators', 4,
2404 'Extra space for operator %s' % match.group(1))
2407 match = Search(
r' (if\(|for\(|while\(|switch\()', line)
2409 error(filename, linenum,
'whitespace/parens', 5,
2410 'Missing space before ( in %s' % match.group(1))
2417 match = Search(
r'\b(if|for|while|switch)\s*'
2418 r'\(([ ]*)(.).*[^ ]+([ ]*)\)\s*{\s*$',
2421 if len(match.group(2)) != len(match.group(4)):
2422 if not (match.group(3) ==
';' and
2423 len(match.group(2)) == 1 + len(match.group(4))
or
2424 not match.group(2)
and Search(
r'\bfor\s*\(.*; \)', line)):
2425 error(filename, linenum,
'whitespace/parens', 5,
2426 'Mismatching spaces inside () in %s' % match.group(1))
2427 if not len(match.group(2))
in [0, 1]:
2428 error(filename, linenum,
'whitespace/parens', 5,
2429 'Should have zero or one spaces inside ( and ) in %s' %
2433 if Search(
r',[^\s]', line):
2434 error(filename, linenum,
'whitespace/comma', 3,
2435 'Missing space after ,')
2441 if Search(
r';[^\s};\\)/]', line):
2442 error(filename, linenum,
'whitespace/semicolon', 3,
2443 'Missing space after ;')
2446 CheckSpacingForFunctionCall(filename, line, linenum, error)
2452 if Search(
r'[^ ({]{', line):
2453 error(filename, linenum,
'whitespace/braces', 5,
2454 'Missing space before {')
2457 if Search(
r'}else', line):
2458 error(filename, linenum,
'whitespace/braces', 5,
2459 'Missing space before else')
2463 if Search(
r'\w\s+\[', line)
and not Search(
r'delete\s+\[', line):
2464 error(filename, linenum,
'whitespace/braces', 5,
2465 'Extra space before [')
2470 if Search(
r':\s*;\s*$', line):
2471 error(filename, linenum,
'whitespace/semicolon', 5,
2472 'Semicolon defining empty statement. Use {} instead.')
2473 elif Search(
r'^\s*;\s*$', line):
2474 error(filename, linenum,
'whitespace/semicolon', 5,
2475 'Line contains only semicolon. If this should be an empty statement, '
2477 elif (Search(
r'\s+;\s*$', line)
and
2478 not Search(
r'\bfor\b', line)):
2479 error(filename, linenum,
'whitespace/semicolon', 5,
2480 'Extra space before last semicolon. If this should be an empty '
2481 'statement, use {} instead.')
2485 if (Search(
'for *\(.*[^:]:[^: ]', line)
or
2486 Search(
'for *\(.*[^: ]:[^:]', line)):
2487 error(filename, linenum,
'whitespace/forcolon', 2,
2488 'Missing space around colon in range-based for loop')
2491 def CheckSectionSpacing(filename, clean_lines, class_info, linenum, error):
2492 """Checks for additional blank line issues related to sections.
2494 Currently the only thing checked here is blank line before protected/private.
2497 filename: The name of the current file.
2498 clean_lines: A CleansedLines instance containing the file.
2499 class_info: A _ClassInfo objects.
2500 linenum: The number of the line to check.
2501 error: The function to call with any errors found.
2514 if (class_info.last_line - class_info.starting_linenum <= 24
or
2515 linenum <= class_info.starting_linenum):
2518 matched = Match(
r'\s*(public|protected|private):', clean_lines.lines[linenum])
2528 prev_line = clean_lines.lines[linenum - 1]
2529 if (
not IsBlankLine(prev_line)
and
2530 not Search(
r'\b(class|struct)\b', prev_line)
and
2531 not Search(
r'\\$', prev_line)):
2536 end_class_head = class_info.starting_linenum
2537 for i
in range(class_info.starting_linenum, linenum):
2538 if Search(
r'\{\s*$', clean_lines.lines[i]):
2541 if end_class_head < linenum - 1:
2542 error(filename, linenum,
'whitespace/blank_line', 3,
2543 '"%s:" should be preceded by a blank line' % matched.group(1))
2546 def GetPreviousNonBlankLine(clean_lines, linenum):
2547 """Return the most recent non-blank line and its line number.
2550 clean_lines: A CleansedLines instance containing the file contents.
2551 linenum: The number of the line to check.
2554 A tuple with two elements. The first element is the contents of the last
2555 non-blank line before the current line, or the empty string if this is the
2556 first non-blank line. The second is the line number of that line, or -1
2557 if this is the first non-blank line.
2560 prevlinenum = linenum - 1
2561 while prevlinenum >= 0:
2562 prevline = clean_lines.elided[prevlinenum]
2563 if not IsBlankLine(prevline):
2564 return (prevline, prevlinenum)
2569 def CheckBraces(filename, clean_lines, linenum, error):
2570 """Looks for misplaced braces (e.g. at the end of line).
2573 filename: The name of the current file.
2574 clean_lines: A CleansedLines instance containing the file.
2575 linenum: The number of the line to check.
2576 error: The function to call with any errors found.
2579 line = clean_lines.elided[linenum]
2581 if Match(
r'\s*{\s*$', line):
2589 prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0]
2590 if (
not Search(
r'[;:}{]\s*$', prevline)
and
2591 not Match(
r'\s*#', prevline)):
2592 error(filename, linenum,
'whitespace/braces', 4,
2593 '{ should almost always be at the end of the previous line')
2596 if Match(
r'\s*else\s*', line):
2597 prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0]
2598 if Match(
r'\s*}\s*$', prevline):
2599 error(filename, linenum,
'whitespace/newline', 4,
2600 'An else should appear on the same line as the preceding }')
2604 if Search(
r'}\s*else[^{]*$', line)
or Match(
r'[^}]*else\s*{', line):
2605 if Search(
r'}\s*else if([^{]*)$', line):
2607 pos = line.find(
'else if')
2608 pos = line.find(
'(', pos)
2611 if endline[endpos:].find(
'{') == -1:
2612 error(filename, linenum,
'readability/braces', 5,
2613 'If an else has a brace on one side, it should have it on both')
2615 error(filename, linenum,
'readability/braces', 5,
2616 'If an else has a brace on one side, it should have it on both')
2619 if Search(
r'\belse [^\s{]', line)
and not Search(
r'\belse if\b', line):
2620 error(filename, linenum,
'whitespace/newline', 4,
2621 'Else clause should never be on same line as else (use 2 lines)')
2624 if Match(
r'\s*do [^\s{]', line):
2625 error(filename, linenum,
'whitespace/newline', 4,
2626 'do/while clauses should not be on a single line')
2631 prevlinenum = linenum
2633 (prevline, prevlinenum) = GetPreviousNonBlankLine(clean_lines, prevlinenum)
2634 if Match(
r'\s+{.*}\s*;', line)
and not prevline.count(
';'):
2635 line = prevline + line
2638 if (Search(
r'{.*}\s*;', line)
and
2639 line.count(
'{') == line.count(
'}')
and
2640 not Search(
r'struct|class|enum|\s*=\s*{', line)):
2641 error(filename, linenum,
'readability/braces', 4,
2642 "You don't need a ; after a }")
2645 def CheckEmptyLoopBody(filename, clean_lines, linenum, error):
2646 """Loop for empty loop body with only a single semicolon.
2649 filename: The name of the current file.
2650 clean_lines: A CleansedLines instance containing the file.
2651 linenum: The number of the line to check.
2652 error: The function to call with any errors found.
2658 line = clean_lines.elided[linenum]
2659 if Match(
r'\s*(for|while)\s*\(', line):
2662 clean_lines, linenum, line.find(
'('))
2667 if end_pos >= 0
and Match(
r';', end_line[end_pos:]):
2668 error(filename, end_linenum,
'whitespace/empty_loop_body', 5,
2669 'Empty loop bodies should use {} or continue')
2672 def ReplaceableCheck(operator, macro, line):
2673 """Determine whether a basic CHECK can be replaced with a more specific one.
2675 For example suggest using CHECK_EQ instead of CHECK(a == b) and
2676 similarly for CHECK_GE, CHECK_GT, CHECK_LE, CHECK_LT, CHECK_NE.
2679 operator: The C++ operator used in the CHECK.
2680 macro: The CHECK or EXPECT macro being called.
2681 line: The current source line.
2684 True if the CHECK can be replaced with a more specific one.
2688 match_constant =
r'([-+]?(\d+|0[xX][0-9a-fA-F]+)[lLuU]{0,3}|".*"|\'.*\')'
2695 match_this = (
r'\s*' + macro +
r'\((\s*' +
2696 match_constant +
r'\s*' + operator +
r'[^<>].*|'
2697 r'.*[^<>]' + operator +
r'\s*' + match_constant +
2704 return Match(match_this, line)
and not Search(
r'NULL|&&|\|\|', line)
2707 def CheckCheck(filename, clean_lines, linenum, error):
2708 """Checks the use of CHECK and EXPECT macros.
2711 filename: The name of the current file.
2712 clean_lines: A CleansedLines instance containing the file.
2713 linenum: The number of the line to check.
2714 error: The function to call with any errors found.
2718 raw_lines = clean_lines.raw_lines
2720 for macro
in _CHECK_MACROS:
2721 if raw_lines[linenum].find(macro) >= 0:
2722 current_macro = macro
2724 if not current_macro:
2728 line = clean_lines.elided[linenum]
2731 for operator
in [
'==',
'!=',
'>=',
'>',
'<=',
'<']:
2732 if ReplaceableCheck(operator, current_macro, line):
2733 error(filename, linenum,
'readability/check', 2,
2734 'Consider using %s instead of %s(a %s b)' % (
2735 _CHECK_REPLACEMENT[current_macro][operator],
2736 current_macro, operator))
2740 def CheckAltTokens(filename, clean_lines, linenum, error):
2741 """Check alternative keywords being used in boolean expressions.
2744 filename: The name of the current file.
2745 clean_lines: A CleansedLines instance containing the file.
2746 linenum: The number of the line to check.
2747 error: The function to call with any errors found.
2749 line = clean_lines.elided[linenum]
2752 if Match(
r'^\s*#', line):
2763 if line.find(
'/*') >= 0
or line.find(
'*/') >= 0:
2766 for match
in _ALT_TOKEN_REPLACEMENT_PATTERN.finditer(line):
2767 error(filename, linenum,
'readability/alt_tokens', 2,
2768 'Use operator %s instead of %s' % (
2769 _ALT_TOKEN_REPLACEMENT[match.group(1)], match.group(1)))
2772 def GetLineWidth(line):
2773 """Determines the width of the line in column positions.
2776 line: A string, which may be a Unicode string.
2779 The width of the line in column positions, accounting for Unicode
2780 combining characters and wide characters.
2782 if isinstance(line, unicode):
2784 for uc
in unicodedata.normalize(
'NFC', line):
2785 if unicodedata.east_asian_width(uc)
in (
'W',
'F'):
2787 elif not unicodedata.combining(uc):
2794 def CheckStyle(filename, clean_lines, linenum, file_extension, nesting_state,
2796 """Checks rules from the 'C++ style rules' section of cppguide.html.
2798 Most of these rules are hard to test (naming, comment style), but we
2799 do what we can. In particular we check for 2-space indents, line lengths,
2800 tab usage, spaces inside code, etc.
2803 filename: The name of the current file.
2804 clean_lines: A CleansedLines instance containing the file.
2805 linenum: The number of the line to check.
2806 file_extension: The extension (without the dot) of the filename.
2807 nesting_state: A _NestingState instance which maintains information about
2808 the current stack of nested blocks being parsed.
2809 error: The function to call with any errors found.
2812 raw_lines = clean_lines.raw_lines
2813 line = raw_lines[linenum]
2815 if line.find(
'\t') != -1:
2816 error(filename, linenum,
'whitespace/tab', 1,
2817 'Tab found; better to use spaces')
2832 cleansed_line = clean_lines.elided[linenum]
2833 while initial_spaces < len(line)
and line[initial_spaces] ==
' ':
2835 if line
and line[-1].isspace():
2836 error(filename, linenum,
'whitespace/end_of_line', 4,
2837 'Line ends in whitespace. Consider deleting these extra spaces.')
2839 elif ((initial_spaces == 1
or initial_spaces == 3)
and
2840 not Match(
r'\s*\w+\s*:\s*$', cleansed_line)):
2841 error(filename, linenum,
'whitespace/indent', 3,
2842 'Weird number of spaces at line-start. '
2843 'Are you using a 2-space indent?')
2845 elif not initial_spaces
and line[:2] !=
'//' and Search(
r'[^:]:\s*$',
2847 error(filename, linenum,
'whitespace/labels', 4,
2848 'Labels should always be indented at least one space. '
2849 'If this is a member-initializer list in a constructor or '
2850 'the base class list in a class definition, the colon should '
2851 'be on the following line.')
2855 is_header_guard =
False
2856 if file_extension ==
'h':
2858 if (line.startswith(
'#ifndef %s' % cppvar)
or
2859 line.startswith(
'#define %s' % cppvar)
or
2860 line.startswith(
'#endif // %s' % cppvar)):
2861 is_header_guard =
True
2870 if (
not line.startswith(
'#include')
and not is_header_guard
and
2871 not Match(
r'^\s*//.*http(s?)://\S*$', line)
and
2872 not Match(
r'^// \$Id:.*#[0-9]+ \$$', line)):
2873 line_width = GetLineWidth(line)
2874 if line_width > 100:
2875 error(filename, linenum,
'whitespace/line_length', 4,
2876 'Lines should very rarely be longer than 100 characters')
2877 elif line_width > 80:
2878 error(filename, linenum,
'whitespace/line_length', 2,
2879 'Lines should be <= 80 characters long')
2881 if (cleansed_line.count(
';') > 1
and
2883 cleansed_line.find(
'for') == -1
and
2884 (GetPreviousNonBlankLine(clean_lines, linenum)[0].find(
'for') == -1
or
2885 GetPreviousNonBlankLine(clean_lines, linenum)[0].find(
';') != -1)
and
2887 not ((cleansed_line.find(
'case ') != -1
or
2888 cleansed_line.find(
'default:') != -1)
and
2889 cleansed_line.find(
'break;') != -1)):
2890 error(filename, linenum,
'whitespace/newline', 0,
2891 'More than one command on the same line')
2894 CheckBraces(filename, clean_lines, linenum, error)
2895 CheckEmptyLoopBody(filename, clean_lines, linenum, error)
2896 CheckAccess(filename, clean_lines, linenum, nesting_state, error)
2897 CheckSpacing(filename, clean_lines, linenum, nesting_state, error)
2898 CheckCheck(filename, clean_lines, linenum, error)
2899 CheckAltTokens(filename, clean_lines, linenum, error)
2900 classinfo = nesting_state.InnermostClass()
2902 CheckSectionSpacing(filename, clean_lines, classinfo, linenum, error)
2905 _RE_PATTERN_INCLUDE_NEW_STYLE = re.compile(
r'#include +"[^/]+\.h"')
2906 _RE_PATTERN_INCLUDE = re.compile(
r'^\s*#\s*include\s*([<"])([^>"]*)[>"].*$')
2912 _RE_FIRST_COMPONENT = re.compile(
r'^[^-_.]+')
2915 def _DropCommonSuffixes(filename):
2916 """Drops common suffixes like _test.cc or -inl.h from filename.
2919 >>> _DropCommonSuffixes('foo/foo-inl.h')
2921 >>> _DropCommonSuffixes('foo/bar/foo.cc')
2923 >>> _DropCommonSuffixes('foo/foo_internal.h')
2925 >>> _DropCommonSuffixes('foo/foo_unusualinternal.h')
2926 'foo/foo_unusualinternal'
2929 filename: The input filename.
2932 The filename with the common suffix removed.
2934 for suffix
in (
'test.cc',
'regtest.cc',
'unittest.cc',
2935 'inl.h',
'impl.h',
'internal.h'):
2936 if (filename.endswith(suffix)
and len(filename) > len(suffix)
and
2937 filename[-len(suffix) - 1]
in (
'-',
'_')):
2938 return filename[:-len(suffix) - 1]
2939 return os.path.splitext(filename)[0]
2942 def _IsTestFilename(filename):
2943 """Determines if the given filename has a suffix that identifies it as a test.
2946 filename: The input filename.
2949 True if 'filename' looks like a test, False otherwise.
2951 if (filename.endswith(
'_test.cc')
or
2952 filename.endswith(
'_unittest.cc')
or
2953 filename.endswith(
'_regtest.cc')):
2959 def _ClassifyInclude(fileinfo, include, is_system):
2960 """Figures out what kind of header 'include' is.
2963 fileinfo: The current file cpplint is running over. A FileInfo instance.
2964 include: The path to a #included file.
2965 is_system: True if the #include used <> rather than "".
2968 One of the _XXX_HEADER constants.
2971 >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'stdio.h', True)
2973 >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'string', True)
2975 >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'foo/foo.h', False)
2977 >>> _ClassifyInclude(FileInfo('foo/foo_unknown_extension.cc'),
2978 ... 'bar/foo_other_ext.h', False)
2980 >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'foo/bar.h', False)
2985 is_stl_h = include
in _STL_HEADERS
2986 is_cpp_h = is_stl_h
or include
in _CPP_HEADERS
2990 return _CPP_SYS_HEADER
2992 return _C_SYS_HEADER
2997 target_dir, target_base = (
2998 os.path.split(_DropCommonSuffixes(fileinfo.RepositoryName())))
2999 include_dir, include_base = os.path.split(_DropCommonSuffixes(include))
3000 if target_base == include_base
and (
3001 include_dir == target_dir
or
3002 include_dir == os.path.normpath(target_dir +
'/../public')):
3003 return _LIKELY_MY_HEADER
3009 target_first_component = _RE_FIRST_COMPONENT.match(target_base)
3010 include_first_component = _RE_FIRST_COMPONENT.match(include_base)
3011 if (target_first_component
and include_first_component
and
3012 target_first_component.group(0) ==
3013 include_first_component.group(0)):
3014 return _POSSIBLE_MY_HEADER
3016 return _OTHER_HEADER
3020 def CheckIncludeLine(filename, clean_lines, linenum, include_state, error):
3021 """Check rules that are applicable to #include lines.
3023 Strings on #include lines are NOT removed from elided line, to make
3024 certain tasks easier. However, to prevent false positives, checks
3025 applicable to #include lines in CheckLanguage must be put here.
3028 filename: The name of the current file.
3029 clean_lines: A CleansedLines instance containing the file.
3030 linenum: The number of the line to check.
3031 include_state: An _IncludeState instance in which the headers are inserted.
3032 error: The function to call with any errors found.
3034 fileinfo = FileInfo(filename)
3036 line = clean_lines.lines[linenum]
3039 if _RE_PATTERN_INCLUDE_NEW_STYLE.search(line):
3040 error(filename, linenum,
'build/include', 4,
3041 'Include the directory when naming .h files')
3046 match = _RE_PATTERN_INCLUDE.search(line)
3048 include = match.group(2)
3049 is_system = (match.group(1) ==
'<')
3050 if include
in include_state:
3051 error(filename, linenum,
'build/include', 4,
3052 '"%s" already included at %s:%s' %
3053 (include, filename, include_state[include]))
3055 include_state[include] = linenum
3068 error_message = include_state.CheckNextIncludeOrder(
3069 _ClassifyInclude(fileinfo, include, is_system))
3071 error(filename, linenum,
'build/include_order', 4,
3072 '%s. Should be: %s.h, c system, c++ system, other.' %
3073 (error_message, fileinfo.BaseName()))
3074 if not include_state.IsInAlphabeticalOrder(include):
3075 error(filename, linenum,
'build/include_alpha', 4,
3076 'Include "%s" not in alphabetical order' % include)
3079 match = _RE_PATTERN_INCLUDE.match(line)
3081 include = match.group(2)
3082 if Match(
r'(f|ind|io|i|o|parse|pf|stdio|str|)?stream$', include):
3084 if not _IsTestFilename(filename):
3085 error(filename, linenum,
'readability/streams', 3,
3086 'Streams are highly discouraged.')
3089 def _GetTextInside(text, start_pattern):
3090 """Retrieves all the text between matching open and close parentheses.
3092 Given a string of lines and a regular expression string, retrieve all the text
3093 following the expression and between opening punctuation symbols like
3094 (, [, or {, and the matching close-punctuation symbol. This properly nested
3095 occurrences of the punctuations, so for the text like
3096 printf(a(), b(c()));
3097 a call to _GetTextInside(text, r'printf\(') will return 'a(), b(c())'.
3098 start_pattern must match string having an open punctuation symbol at the end.
3101 text: The lines to extract text. Its comments and strings must be elided.
3102 It can be single line and can span multiple lines.
3103 start_pattern: The regexp string indicating where to start extracting
3107 None if either the opening string or ending punctuation could not be found.
3113 matching_punctuation = {
'(':
')',
'{':
'}',
'[':
']'}
3114 closing_punctuation = set(matching_punctuation.itervalues())
3117 match = re.search(start_pattern, text, re.M)
3120 start_position = match.end(0)
3122 assert start_position > 0, (
3123 'start_pattern must ends with an opening punctuation.')
3124 assert text[start_position - 1]
in matching_punctuation, (
3125 'start_pattern must ends with an opening punctuation.')
3127 punctuation_stack = [matching_punctuation[text[start_position - 1]]]
3128 position = start_position
3129 while punctuation_stack
and position < len(text):
3130 if text[position] == punctuation_stack[-1]:
3131 punctuation_stack.pop()
3132 elif text[position]
in closing_punctuation:
3135 elif text[position]
in matching_punctuation:
3136 punctuation_stack.append(matching_punctuation[text[position]])
3138 if punctuation_stack:
3142 return text[start_position:position - 1]
3145 def CheckLanguage(filename, clean_lines, linenum, file_extension, include_state,
3147 """Checks rules from the 'C++ language rules' section of cppguide.html.
3149 Some of these rules are hard to test (function overloading, using
3150 uint32 inappropriately), but we do the best we can.
3153 filename: The name of the current file.
3154 clean_lines: A CleansedLines instance containing the file.
3155 linenum: The number of the line to check.
3156 file_extension: The extension (without the dot) of the filename.
3157 include_state: An _IncludeState instance in which the headers are inserted.
3158 error: The function to call with any errors found.
3162 line = clean_lines.elided[linenum]
3166 match = _RE_PATTERN_INCLUDE.search(line)
3168 CheckIncludeLine(filename, clean_lines, linenum, include_state, error)
3174 if linenum + 1 < clean_lines.NumLines():
3175 extended_line = line + clean_lines.elided[linenum + 1]
3177 extended_line = line
3180 fullname = os.path.abspath(filename).replace(
'\\',
'/')
3191 fnline = line.split(
'{', 1)[0]
3192 if (len(re.findall(
r'\([^()]*\b(?:[\w:]|<[^()]*>)+(\s?&|&\s?)\w+', fnline)) >
3193 len(re.findall(
r'\([^()]*\bconst\s+(?:typename\s+)?(?:struct\s+)?'
3194 r'(?:[\w:]|<[^()]*>)+(\s?&|&\s?)\w+', fnline)) +
3195 len(re.findall(
r'\([^()]*\b(?:[\w:]|<[^()]*>)+\s+const(\s?&|&\s?)[\w]+',
3202 r'(for|swap|Swap|operator[<>][<>])\s*\(\s*'
3203 r'(?:(?:typename\s*)?[\w:]|<.*>)+\s*&',
3205 error(filename, linenum,
'runtime/references', 2,
3206 'Is this a non-const reference? '
3207 'If so, make const or use a pointer.')
3215 r'(int|float|double|bool|char|int32|uint32|int64|uint64)\([^)]', line)
3222 if (match.group(1)
is None and
3223 not (Match(
r'^\s*MOCK_(CONST_)?METHOD\d+(_T)?\(', line)
or
3224 Match(
r'^\s*MockCallback<.*>', line))):
3232 not Match(
r'^\s*MOCK_(CONST_)?METHOD\d+(_T)?\(\S+,\s*$',
3233 clean_lines.elided[linenum - 1])):
3234 error(filename, linenum,
'readability/casting', 4,
3235 'Using deprecated casting style. '
3236 'Use static_cast<%s>(...) instead' %
3239 CheckCStyleCast(filename, linenum, line, clean_lines.raw_lines[linenum],
3241 r'\((int|float|double|bool|char|u?int(16|32|64))\)', error)
3247 if CheckCStyleCast(filename, linenum, line, clean_lines.raw_lines[linenum],
3248 'const_cast',
r'\((char\s?\*+\s?)\)\s*"', error):
3252 CheckCStyleCast(filename, linenum, line, clean_lines.raw_lines[linenum],
3253 'reinterpret_cast',
r'\((\w+\s?\*+\s?)\)', error)
3259 r'(&\([^)]+\)[\w(])|(&(static|dynamic|reinterpret)_cast\b)', line):
3260 error(filename, linenum,
'runtime/casting', 4,
3261 (
'Are you taking an address of a cast? '
3262 'This is dangerous: could be a temp var. '
3263 'Take the address before doing the cast, rather than after'))
3269 r'((?:|static +)(?:|const +))string +([a-zA-Z0-9_:]+)\b(.*)',
3274 if match
and not Match(
r'\s*(<.*>)?(::[a-zA-Z0-9_]+)?\s*\(([^"]|$)',
3276 error(filename, linenum,
'runtime/string', 4,
3277 'For a static/global string constant, use a C style string instead: '
3279 (match.group(1), match.group(2)))
3282 if Search(
r'\bdynamic_cast<', line)
and not _IsTestFilename(filename):
3283 error(filename, linenum,
'runtime/rtti', 5,
3284 'Do not use dynamic_cast<>. If you need to cast within a class '
3285 "hierarchy, use static_cast<> to upcast. Google doesn't support "
3288 if Search(
r'\b([A-Za-z0-9_]*_)\(\1\)', line):
3289 error(filename, linenum,
'runtime/init', 4,
3290 'You seem to be initializing a member variable with itself.')
3292 if file_extension ==
'h':
3302 if Search(
r'\bshort port\b', line):
3303 if not Search(
r'\bunsigned short port\b', line):
3304 error(filename, linenum,
'runtime/int', 4,
3305 'Use "unsigned short" for ports, not "short"')
3307 match = Search(
r'\b(short|long(?! +double)|long long)\b', line)
3309 error(filename, linenum,
'runtime/int', 4,
3310 'Use int16/int64/etc, rather than the C type %s' % match.group(1))
3313 match = Search(
r'snprintf\s*\(([^,]*),\s*([0-9]*)\s*,', line)
3314 if match
and match.group(2) !=
'0':
3316 error(filename, linenum,
'runtime/printf', 3,
3317 'If you can, use sizeof(%s) instead of %s as the 2nd arg '
3318 'to snprintf.' % (match.group(1), match.group(2)))
3321 if Search(
r'\bsprintf\b', line):
3322 error(filename, linenum,
'runtime/printf', 5,
3323 'Never use sprintf. Use snprintf instead.')
3324 match = Search(
r'\b(strcpy|strcat)\b', line)
3326 error(filename, linenum,
'runtime/printf', 4,
3327 'Almost always, snprintf is better than %s' % match.group(1))
3329 if Search(
r'\bsscanf\b', line):
3330 error(filename, linenum,
'runtime/printf', 1,
3331 'sscanf can be ok, but is slow and can overflow buffers.')
3339 if Search(
r'\boperator\s*&\s*\(\s*\)', line):
3340 error(filename, linenum,
'runtime/operator', 4,
3341 'Unary operator& is dangerous. Do not use it.')
3345 if Search(
r'\}\s*if\s*\(', line):
3346 error(filename, linenum,
'readability/braces', 4,
3347 'Did you mean "else if"? If not, start a new line for "if".')
3356 printf_args = _GetTextInside(line,
r'(?i)\b(string)?printf\s*\(')
3358 match = Match(
r'([\w.\->()]+)$', printf_args)
3359 if match
and match.group(1) !=
'__VA_ARGS__':
3360 function_name = re.search(
r'\b((?:string)?printf)\s*\(',
3361 line, re.I).group(1)
3362 error(filename, linenum,
'runtime/printf', 4,
3363 'Potential format string bug. Do %s("%%s", %s) instead.'
3364 % (function_name, match.group(1)))
3367 match = Search(
r'memset\s*\(([^,]*),\s*([^,]*),\s*0\s*\)', line)
3368 if match
and not Match(
r"^''|-?[0-9]+|0x[0-9A-Fa-f]$", match.group(2)):
3369 error(filename, linenum,
'runtime/memset', 4,
3370 'Did you mean "memset(%s, 0, %s)"?'
3371 % (match.group(1), match.group(2)))
3373 if Search(
r'\busing namespace\b', line):
3374 error(filename, linenum,
'build/namespaces', 5,
3375 'Do not use namespace using-directives. '
3376 'Use using-declarations instead.')
3379 match = Match(
r'\s*(.+::)?(\w+) [a-z]\w*\[(.+)];', line)
3380 if (match
and match.group(2) !=
'return' and match.group(2) !=
'delete' and
3381 match.group(3).find(
']') == -1):
3385 tokens = re.split(
r'\s|\+|\-|\*|\/|<<|>>]', match.group(3))
3393 if Search(
r'sizeof\(.+\)', tok):
continue
3394 if Search(
r'arraysize\(\w+\)', tok):
continue
3396 tok = tok.lstrip(
'(')
3397 tok = tok.rstrip(
')')
3398 if not tok:
continue
3399 if Match(
r'\d+', tok):
continue
3400 if Match(
r'0[xX][0-9a-fA-F]+', tok):
continue
3401 if Match(
r'k[A-Z0-9]\w*', tok):
continue
3402 if Match(
r'(.+::)?k[A-Z0-9]\w*', tok):
continue
3403 if Match(
r'(.+::)?[A-Z][A-Z0-9_]*', tok):
continue
3407 if tok.startswith(
'sizeof'):
3413 error(filename, linenum,
'runtime/arrays', 1,
3414 'Do not use variable-length arrays. Use an appropriately named '
3415 "('k' followed by CamelCase) compile-time constant for the size.")
3422 r'(DISALLOW_(EVIL_CONSTRUCTORS|COPY_AND_ASSIGN|IMPLICIT_CONSTRUCTORS))'
3425 if match
and linenum + 1 < clean_lines.NumLines():
3426 next_line = clean_lines.elided[linenum + 1]
3433 if not Search(
r'^\s*}[\w\*,\s]*;', next_line):
3434 error(filename, linenum,
'readability/constructors', 3,
3435 match.group(1) +
' should be the last thing in the class')
3440 if (file_extension ==
'h'
3441 and Search(
r'\bnamespace\s*{', line)
3442 and line[-1] !=
'\\'):
3443 error(filename, linenum,
'build/namespaces', 4,
3444 'Do not use unnamed namespaces in header files. See '
3445 'http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Namespaces'
3446 ' for more information.')
3449 def CheckCStyleCast(filename, linenum, line, raw_line, cast_type, pattern,
3451 """Checks for a C-style cast by looking for the pattern.
3453 This also handles sizeof(type) warnings, due to similarity of content.
3456 filename: The name of the current file.
3457 linenum: The number of the line to check.
3458 line: The line of code to check.
3459 raw_line: The raw line of code to check, with comments.
3460 cast_type: The string for the C++ cast to recommend. This is either
3461 reinterpret_cast, static_cast, or const_cast, depending.
3462 pattern: The regular expression used to find C-style casts.
3463 error: The function to call with any errors found.
3466 True if an error was emitted.
3469 match = Search(pattern, line)
3474 sizeof_match = Match(
r'.*sizeof\s*$', line[0:match.start(1) - 1])
3476 error(filename, linenum,
'runtime/sizeof', 1,
3477 'Using sizeof(type). Use sizeof(varname) instead if possible')
3481 if (line[0:match.start(1) - 1].endswith(
' operator++')
or
3482 line[0:match.start(1) - 1].endswith(
' operator--')):
3485 remainder = line[match.end(0):]
3499 function_match = Match(
r'\s*(\)|=|(const)?\s*(;|\{|throw\(\)|>))', remainder)
3501 if (
not function_match.group(3)
or
3502 function_match.group(3) ==
';' or
3503 (
'MockCallback<' not in raw_line
and
3504 '/*' not in raw_line)):
3505 error(filename, linenum,
'readability/function', 3,
3506 'All parameters should be named in a function')
3510 error(filename, linenum,
'readability/casting', 4,
3511 'Using C-style cast. Use %s<%s>(...) instead' %
3512 (cast_type, match.group(1)))
3517 _HEADERS_CONTAINING_TEMPLATES = (
3518 (
'<deque>', (
'deque',)),
3519 (
'<functional>', (
'unary_function',
'binary_function',
3520 'plus',
'minus',
'multiplies',
'divides',
'modulus',
3522 'equal_to',
'not_equal_to',
'greater',
'less',
3523 'greater_equal',
'less_equal',
3524 'logical_and',
'logical_or',
'logical_not',
3525 'unary_negate',
'not1',
'binary_negate',
'not2',
3526 'bind1st',
'bind2nd',
3527 'pointer_to_unary_function',
3528 'pointer_to_binary_function',
3530 'mem_fun_t',
'mem_fun',
'mem_fun1_t',
'mem_fun1_ref_t',
3532 'const_mem_fun_t',
'const_mem_fun1_t',
3533 'const_mem_fun_ref_t',
'const_mem_fun1_ref_t',
3536 (
'<limits>', (
'numeric_limits',)),
3537 (
'<list>', (
'list',)),
3538 (
'<map>', (
'map',
'multimap',)),
3539 (
'<memory>', (
'allocator',)),
3540 (
'<queue>', (
'queue',
'priority_queue',)),
3541 (
'<set>', (
'set',
'multiset',)),
3542 (
'<stack>', (
'stack',)),
3543 (
'<string>', (
'char_traits',
'basic_string',)),
3544 (
'<utility>', (
'pair',)),
3545 (
'<vector>', (
'vector',)),
3549 (
'<hash_map>', (
'hash_map',
'hash_multimap',)),
3550 (
'<hash_set>', (
'hash_set',
'hash_multiset',)),
3551 (
'<slist>', (
'slist',)),
3554 _RE_PATTERN_STRING = re.compile(
r'\bstring\b')
3556 _re_pattern_algorithm_header = []
3557 for _template
in (
'copy',
'max',
'min',
'min_element',
'sort',
'swap',
3561 _re_pattern_algorithm_header.append(
3562 (re.compile(
r'[^>.]\b' + _template +
r'(<.*?>)?\([^\)]'),
3566 _re_pattern_templates = []
3567 for _header, _templates
in _HEADERS_CONTAINING_TEMPLATES:
3568 for _template
in _templates:
3569 _re_pattern_templates.append(
3570 (re.compile(
r'(<|\b)' + _template +
r'\s*<'),
3575 def FilesBelongToSameModule(filename_cc, filename_h):
3576 """Check if these two filenames belong to the same module.
3578 The concept of a 'module' here is a as follows:
3579 foo.h, foo-inl.h, foo.cc, foo_test.cc and foo_unittest.cc belong to the
3580 same 'module' if they are in the same directory.
3581 some/path/public/xyzzy and some/path/internal/xyzzy are also considered
3582 to belong to the same module here.
3584 If the filename_cc contains a longer path than the filename_h, for example,
3585 '/absolute/path/to/base/sysinfo.cc', and this file would include
3586 'base/sysinfo.h', this function also produces the prefix needed to open the
3587 header. This is used by the caller of this function to more robustly open the
3588 header file. We don't have access to the real include paths in this context,
3589 so we need this guesswork here.
3591 Known bugs: tools/base/bar.cc and base/bar.h belong to the same module
3592 according to this implementation. Because of this, this function gives
3593 some false positives. This should be sufficiently rare in practice.
3596 filename_cc: is the path for the .cc file
3597 filename_h: is the path for the header path
3600 Tuple with a bool and a string:
3601 bool: True if filename_cc and filename_h belong to the same module.
3602 string: the additional prefix needed to open the header file.
3605 if not filename_cc.endswith(
'.cc'):
3607 filename_cc = filename_cc[:-len(
'.cc')]
3608 if filename_cc.endswith(
'_unittest'):
3609 filename_cc = filename_cc[:-len(
'_unittest')]
3610 elif filename_cc.endswith(
'_test'):
3611 filename_cc = filename_cc[:-len(
'_test')]
3612 filename_cc = filename_cc.replace(
'/public/',
'/')
3613 filename_cc = filename_cc.replace(
'/internal/',
'/')
3615 if not filename_h.endswith(
'.h'):
3617 filename_h = filename_h[:-len(
'.h')]
3618 if filename_h.endswith(
'-inl'):
3619 filename_h = filename_h[:-len(
'-inl')]
3620 filename_h = filename_h.replace(
'/public/',
'/')
3621 filename_h = filename_h.replace(
'/internal/',
'/')
3623 files_belong_to_same_module = filename_cc.endswith(filename_h)
3625 if files_belong_to_same_module:
3626 common_path = filename_cc[:-len(filename_h)]
3627 return files_belong_to_same_module, common_path
3630 def UpdateIncludeState(filename, include_state, io=codecs):
3631 """Fill up the include_state with new includes found from the file.
3634 filename: the name of the header to read.
3635 include_state: an _IncludeState instance in which the headers are inserted.
3636 io: The io factory to use to read the file. Provided for testability.
3639 True if a header was succesfully added. False otherwise.
3643 headerfile = io.open(filename,
'r', 'utf8', 'replace')
3647 for line
in headerfile:
3650 match = _RE_PATTERN_INCLUDE.search(clean_line)
3652 include = match.group(2)
3655 include_state.setdefault(include,
'%s:%d' % (filename, linenum))
3659 def CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error,
3661 """Reports for missing stl includes.
3663 This function will output warnings to make sure you are including the headers
3664 necessary for the stl containers and functions that you use. We only give one
3665 reason to include a header. For example, if you use both equal_to<> and
3666 less<> in a .h file, only one (the latter in the file) of these will be
3667 reported as a reason to include the <functional>.
3670 filename: The name of the current file.
3671 clean_lines: A CleansedLines instance containing the file.
3672 include_state: An _IncludeState instance.
3673 error: The function to call with any errors found.
3674 io: The IO factory to use to read the header file. Provided for unittest
3680 for linenum
in xrange(clean_lines.NumLines()):
3681 line = clean_lines.elided[linenum]
3682 if not line
or line[0] ==
'#':
3686 matched = _RE_PATTERN_STRING.search(line)
3690 prefix = line[:matched.start()]
3691 if prefix.endswith(
'std::')
or not prefix.endswith(
'::'):
3692 required[
'<string>'] = (linenum,
'string')
3694 for pattern, template, header
in _re_pattern_algorithm_header:
3695 if pattern.search(line):
3696 required[header] = (linenum, template)
3702 for pattern, template, header
in _re_pattern_templates:
3703 if pattern.search(line):
3704 required[header] = (linenum, template)
3709 include_state = include_state.copy()
3712 header_found =
False
3715 abs_filename = FileInfo(filename).FullName()
3724 abs_filename = re.sub(
r'_flymake\.cc$',
'.cc', abs_filename)
3728 header_keys = include_state.keys()
3729 for header
in header_keys:
3730 (same_module, common_path) = FilesBelongToSameModule(abs_filename, header)
3731 fullpath = common_path + header
3732 if same_module
and UpdateIncludeState(fullpath, include_state, io):
3740 if filename.endswith(
'.cc')
and not header_found:
3744 for required_header_unstripped
in required:
3745 template = required[required_header_unstripped][1]
3746 if required_header_unstripped.strip(
'<>"')
not in include_state:
3747 error(filename, required[required_header_unstripped][0],
3748 'build/include_what_you_use', 4,
3749 'Add #include ' + required_header_unstripped +
' for ' + template)
3752 _RE_PATTERN_EXPLICIT_MAKEPAIR = re.compile(
r'\bmake_pair\s*<')
3755 def CheckMakePairUsesDeduction(filename, clean_lines, linenum, error):
3756 """Check that make_pair's template arguments are deduced.
3758 G++ 4.6 in C++0x mode fails badly if make_pair's template arguments are
3759 specified explicitly, and such use isn't intended in any case.
3762 filename: The name of the current file.
3763 clean_lines: A CleansedLines instance containing the file.
3764 linenum: The number of the line to check.
3765 error: The function to call with any errors found.
3767 raw = clean_lines.raw_lines
3769 match = _RE_PATTERN_EXPLICIT_MAKEPAIR.search(line)
3771 error(filename, linenum,
'build/explicit_make_pair',
3773 'For C++11-compatibility, omit template arguments from make_pair'
3774 ' OR use pair directly OR if appropriate, construct a pair directly')
3777 def ProcessLine(filename, file_extension, clean_lines, line,
3778 include_state, function_state, nesting_state, error,
3779 extra_check_functions=[]):
3780 """Processes a single line in the file.
3783 filename: Filename of the file that is being processed.
3784 file_extension: The extension (dot not included) of the file.
3785 clean_lines: An array of strings, each representing a line of the file,
3786 with comments stripped.
3787 line: Number of line being processed.
3788 include_state: An _IncludeState instance in which the headers are inserted.
3789 function_state: A _FunctionState instance which counts function lines, etc.
3790 nesting_state: A _NestingState instance which maintains information about
3791 the current stack of nested blocks being parsed.
3792 error: A callable to which errors are reported, which takes 4 arguments:
3793 filename, line number, error level, and message
3794 extra_check_functions: An array of additional check functions that will be
3795 run on each source line. Each function takes 4
3796 arguments: filename, clean_lines, line, error
3798 raw_lines = clean_lines.raw_lines
3799 ParseNolintSuppressions(filename, raw_lines[line], line, error)
3800 nesting_state.Update(filename, clean_lines, line, error)
3801 if nesting_state.stack
and nesting_state.stack[-1].inline_asm != _NO_ASM:
3803 CheckForFunctionLengths(filename, clean_lines, line, function_state, error)
3805 CheckStyle(filename, clean_lines, line, file_extension, nesting_state, error)
3806 CheckLanguage(filename, clean_lines, line, file_extension, include_state,
3808 CheckForNonStandardConstructs(filename, clean_lines, line,
3809 nesting_state, error)
3810 CheckPosixThreading(filename, clean_lines, line, error)
3811 CheckInvalidIncrement(filename, clean_lines, line, error)
3812 CheckMakePairUsesDeduction(filename, clean_lines, line, error)
3813 for check_fn
in extra_check_functions:
3814 check_fn(filename, clean_lines, line, error)
3816 def ProcessFileData(filename, file_extension, lines, error,
3817 extra_check_functions=[]):
3818 """Performs lint checks and reports any errors to the given error function.
3821 filename: Filename of the file that is being processed.
3822 file_extension: The extension (dot not included) of the file.
3823 lines: An array of strings, each representing a line of the file, with the
3824 last element being empty if the file is terminated with a newline.
3825 error: A callable to which errors are reported, which takes 4 arguments:
3826 filename, line number, error level, and message
3827 extra_check_functions: An array of additional check functions that will be
3828 run on each source line. Each function takes 4
3829 arguments: filename, clean_lines, line, error
3831 lines = ([
'// marker so line numbers and indices both start at 1'] + lines +
3832 [
'// marker so line numbers end in a known way'])
3834 include_state = _IncludeState()
3835 function_state = _FunctionState()
3836 nesting_state = _NestingState()
3838 ResetNolintSuppressions()
3842 if file_extension ==
'h':
3846 clean_lines = CleansedLines(lines)
3847 for line
in xrange(clean_lines.NumLines()):
3848 ProcessLine(filename, file_extension, clean_lines, line,
3849 include_state, function_state, nesting_state, error,
3850 extra_check_functions)
3851 nesting_state.CheckClassFinished(filename, error)
3853 CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error)
3861 def ProcessFile(filename, vlevel, extra_check_functions=[]):
3862 """Does google-lint on a single file.
3865 filename: The name of the file to parse.
3867 vlevel: The level of errors to report. Every error of confidence
3868 >= verbose_level will be reported. 0 is a good default.
3870 extra_check_functions: An array of additional check functions that will be
3871 run on each source line. Each function takes 4
3872 arguments: filename, clean_lines, line, error
3875 _SetVerboseLevel(vlevel)
3889 lines = codecs.StreamReaderWriter(sys.stdin,
3890 codecs.getreader(
'utf8'),
3891 codecs.getwriter(
'utf8'),
3892 'replace').
read().split(
'\n')
3894 lines = codecs.open(filename,
'r', 'utf8', 'replace').read().split('\n')
3896 carriage_return_found =
False
3898 for linenum
in range(len(lines)):
3899 if lines[linenum].endswith(
'\r'):
3900 lines[linenum] = lines[linenum].rstrip(
'\r')
3901 carriage_return_found =
True
3905 "Skipping input '%s': Can't open for reading\n" % filename)
3909 file_extension = filename[filename.rfind(
'.') + 1:]
3913 if (filename !=
'-' and file_extension !=
'cc' and file_extension !=
'h'
3914 and file_extension !=
'cpp' and file_extension !=
'cxx'):
3915 sys.stderr.write(
'Ignoring %s; not a .cpp, .cxx, .cc or .h file\n'
3918 ProcessFileData(filename, file_extension, lines, Error,
3919 extra_check_functions)
3920 if carriage_return_found
and os.linesep !=
'\r\n':
3923 Error(filename, 0,
'whitespace/newline', 1,
3924 'One or more unexpected \\r (^M) found;'
3925 'better to use only a \\n')
3927 sys.stderr.write(
'Done processing %s\n' % filename)
3930 def PrintUsage(message):
3931 """Prints a brief usage string and exits, optionally with an error message.
3934 message: The optional error message.
3936 sys.stderr.write(_USAGE)
3938 sys.exit(
'\nFATAL ERROR: ' + message)
3943 def PrintCategories():
3944 """Prints a list of all the error-categories used by error messages.
3946 These are the categories used to filter messages via --filter.
3948 sys.stderr.write(
''.join(
' %s\n' % cat
for cat
in _ERROR_CATEGORIES))
3953 """Parses the command line arguments.
3955 This may set the output format and verbosity level as side-effects.
3958 args: The command line arguments:
3961 The list of filenames to lint.
3964 (opts, filenames) = getopt.getopt(args,
'', [
'help',
'output=',
'verbose=',
3968 except getopt.GetoptError:
3969 PrintUsage(
'Invalid arguments.')
3971 verbosity = _VerboseLevel()
3972 output_format = _OutputFormat()
3976 for (opt, val)
in opts:
3979 elif opt ==
'--output':
3980 if not val
in (
'emacs',
'vs7',
'eclipse'):
3981 PrintUsage(
'The only allowed output formats are emacs, vs7 and eclipse.')
3983 elif opt ==
'--verbose':
3984 verbosity = int(val)
3985 elif opt ==
'--filter':
3989 elif opt ==
'--counting':
3990 if val
not in (
'total',
'toplevel',
'detailed'):
3991 PrintUsage(
'Valid counting options are total, toplevel, and detailed')
3992 counting_style = val
3993 elif opt ==
'--root':
3998 PrintUsage(
'No files were specified.')
4000 _SetOutputFormat(output_format)
4001 _SetVerboseLevel(verbosity)
4002 _SetFilters(filters)
4003 _SetCountingStyle(counting_style)
4013 sys.stderr = codecs.StreamReaderWriter(sys.stderr,
4014 codecs.getreader(
'utf8'),
4015 codecs.getwriter(
'utf8'),
4018 _cpplint_state.ResetErrorCounts()
4019 for filename
in filenames:
4020 ProcessFile(filename, _cpplint_state.verbose_level)
4021 _cpplint_state.PrintErrorCounts()
4023 sys.exit(_cpplint_state.error_count > 0)
4026 if __name__ ==
'__main__':