29 """Does google-lint on c++ files.
31 The goal of this script is to identify places in the code that *may*
32 be in non-compliance with google style. It does not attempt to fix
33 up these problems -- the point is to educate. It does also not
34 attempt to find all problems, or to ensure that everything it does
35 find is legitimately a problem.
37 In particular, we can get very confused by /* and // inside strings!
38 We do a small hack, which is to ignore //'s with "'s after them on the
39 same line, but it is far from perfect (in either direction).
60 sys.stderr = codecs.StreamReaderWriter(sys.stderr,
61 codecs.getreader(
'utf8'),
62 codecs.getwriter(
'utf8'),
66 Syntax: cpplint.py [--verbose=#] [--output=vs7] [--filter=-x,+y,...]
67 [--counting=total|toplevel|detailed] [--root=subdir]
68 [--linelength=digits] [--headers=x,y,...]
72 The style guidelines this tries to follow are those in
73 https://google-styleguide.googlecode.com/svn/trunk/cppguide.xml
75 Every problem is given a confidence score from 1-5, with 5 meaning we are
76 certain of the problem, and 1 meaning it could be a legitimate construct.
77 This will miss some errors, and is not a substitute for a code review.
79 To suppress false-positive errors of a certain category, add a
80 'NOLINT(category)' comment to the line. NOLINT or NOLINT(*)
81 suppresses errors of all categories on that line.
83 The files passed in will be linted; at least one file must be provided.
84 Default linted extensions are .cc, .cpp, .cu, .cuh and .h. Change the
85 extensions with the --extensions flag.
90 By default, the output is formatted to ease emacs parsing. Visual Studio
91 compatible output (vs7) may also be used. Other formats are unsupported.
94 Specify a number 0-5 to restrict errors to certain verbosity levels.
97 Don't print anything if no errors are found.
100 Specify a comma-separated list of category-filters to apply: only
101 error messages whose category names pass the filters will be printed.
102 (Category names are printed with the message and look like
103 "[whitespace/indent]".) Filters are evaluated left to right.
104 "-FOO" and "FOO" means "do not print categories that start with FOO".
105 "+FOO" means "do print categories that start with FOO".
107 Examples: --filter=-whitespace,+whitespace/braces
108 --filter=whitespace,runtime/printf,+runtime/printf_format
109 --filter=-,+build/include_what_you_use
111 To see a list of all the categories used in cpplint, pass no arg:
114 counting=total|toplevel|detailed
115 The total number of errors found is always printed. If
116 'toplevel' is provided, then the count of errors in each of
117 the top-level categories like 'build' and 'whitespace' will
118 also be printed. If 'detailed' is provided, then a count
119 is provided for each category like 'build/class'.
122 The root directory used for deriving header guard CPP variable.
123 By default, the header guard CPP variable is calculated as the relative
124 path to the directory that contains .git, .hg, or .svn. When this flag
125 is specified, the relative path is calculated from the specified
126 directory. If the specified directory does not exist, this flag is
130 Assuming that top/src/.git exists (and cwd=top/src), the header guard
131 CPP variables for top/src/chrome/browser/ui/browser.h are:
133 No flag => CHROME_BROWSER_UI_BROWSER_H_
134 --root=chrome => BROWSER_UI_BROWSER_H_
135 --root=chrome/browser => UI_BROWSER_H_
136 --root=.. => SRC_CHROME_BROWSER_UI_BROWSER_H_
139 This is the allowed line length for the project. The default value is
145 extensions=extension,extension,...
146 The allowed file extensions that cpplint will check
152 The header extensions that cpplint will treat as .h in checks. Values are
153 automatically added to --extensions list.
159 cpplint.py supports per-directory configurations specified in CPPLINT.cfg
160 files. CPPLINT.cfg file can contain a number of key=value pairs.
161 Currently the following options are supported:
164 filter=+filter1,-filter2,...
170 "set noparent" option prevents cpplint from traversing directory tree
171 upwards looking for more .cfg files in parent directories. This option
172 is usually placed in the top-level project directory.
174 The "filter" option is similar in function to --filter flag. It specifies
175 message filters in addition to the |_DEFAULT_FILTERS| and those specified
176 through --filter command-line flag.
178 "exclude_files" allows to specify a regular expression to be matched against
179 a file name. If the expression matches, the file is skipped and not run
182 "linelength" allows to specify the allowed line length for the project.
184 The "root" option is similar in function to the --root flag (see example
185 above). Paths are relative to the directory of the CPPLINT.cfg.
187 The "headers" option is similar in function to the --headers flag
190 CPPLINT.cfg has an effect on files in the same directory and all
191 sub-directories, unless overridden by a nested configuration file.
194 filter=-build/include_order,+build/include_alpha
197 The above example disables build/include_order warning and enables
198 build/include_alpha as well as excludes all .cc from being
199 processed by linter, in the current directory (where the .cfg
200 file is located) and all sub-directories.
207 _ERROR_CATEGORIES = [
213 'build/endif_comment',
214 'build/explicit_make_pair',
215 'build/forward_decl',
216 'build/header_guard',
218 'build/include_alpha',
219 'build/include_order',
220 'build/include_what_you_use',
222 'build/printf_format',
223 'build/storage_class',
225 'readability/alt_tokens',
226 'readability/braces',
227 'readability/casting',
229 'readability/constructors',
230 'readability/fn_size',
231 'readability/inheritance',
232 'readability/multiline_comment',
233 'readability/multiline_string',
234 'readability/namespace',
235 'readability/nolint',
237 'readability/strings',
245 'runtime/invalid_increment',
246 'runtime/member_string_references',
248 'runtime/indentation_namespace',
251 'runtime/printf_format',
252 'runtime/references',
254 'runtime/threadsafe_fn',
256 'whitespace/blank_line',
259 'whitespace/comments',
260 'whitespace/empty_conditional_body',
261 'whitespace/empty_if_body',
262 'whitespace/empty_loop_body',
263 'whitespace/end_of_line',
264 'whitespace/ending_newline',
265 'whitespace/forcolon',
267 'whitespace/line_length',
268 'whitespace/newline',
269 'whitespace/operators',
271 'whitespace/semicolon',
278 _LEGACY_ERROR_CATEGORIES = [
279 'readability/streams',
280 'readability/function',
287 _DEFAULT_FILTERS = [
'-build/include_alpha']
290 _DEFAULT_C_SUPPRESSED_CATEGORIES = [
291 'readability/casting',
295 _DEFAULT_KERNEL_SUPPRESSED_CATEGORIES = [
304 _CPP_HEADERS = frozenset([
365 'condition_variable',
444 r'(char(16_t|32_t)?)|wchar_t|'
445 r'bool|short|int|long|signed|unsigned|float|double|'
447 r'(ptrdiff_t|size_t|max_align_t|nullptr_t)|'
449 r'(u?int(_fast|_least)?(8|16|32|64)_t)|'
450 r'(u?int(max|ptr)_t)|'
459 _THIRD_PARTY_HEADERS_PATTERN = re.compile(
460 r'^(?:[^/]*[A-Z][^/]*\.h|lua\.h|lauxlib\.h|lualib\.h)$')
463 _TEST_FILE_SUFFIX =
r'(_test|_unittest|_regtest)$'
466 _EMPTY_CONDITIONAL_BODY_PATTERN = re.compile(
r'^\s*$', re.DOTALL)
472 'EXPECT_TRUE',
'ASSERT_TRUE',
473 'EXPECT_FALSE',
'ASSERT_FALSE',
477 _CHECK_REPLACEMENT = dict([(m, {})
for m
in _CHECK_MACROS])
479 for op, replacement
in [(
'==',
'EQ'), (
'!=',
'NE'),
480 (
'>=',
'GE'), (
'>',
'GT'),
481 (
'<=',
'LE'), (
'<',
'LT')]:
482 _CHECK_REPLACEMENT[
'DCHECK'][op] =
'DCHECK_%s' % replacement
483 _CHECK_REPLACEMENT[
'CHECK'][op] =
'CHECK_%s' % replacement
484 _CHECK_REPLACEMENT[
'EXPECT_TRUE'][op] =
'EXPECT_%s' % replacement
485 _CHECK_REPLACEMENT[
'ASSERT_TRUE'][op] =
'ASSERT_%s' % replacement
487 for op, inv_replacement
in [(
'==',
'NE'), (
'!=',
'EQ'),
488 (
'>=',
'LT'), (
'>',
'LE'),
489 (
'<=',
'GT'), (
'<',
'GE')]:
490 _CHECK_REPLACEMENT[
'EXPECT_FALSE'][op] =
'EXPECT_%s' % inv_replacement
491 _CHECK_REPLACEMENT[
'ASSERT_FALSE'][op] =
'ASSERT_%s' % inv_replacement
498 _ALT_TOKEN_REPLACEMENT = {
517 _ALT_TOKEN_REPLACEMENT_PATTERN = re.compile(
518 r'[ =()](' + (
'|'.join(_ALT_TOKEN_REPLACEMENT.keys())) +
r')(?=[ (]|$)')
525 _LIKELY_MY_HEADER = 3
526 _POSSIBLE_MY_HEADER = 4
536 _MATCH_ASM = re.compile(
r'^\s*(?:asm|_asm|__asm|__asm__)'
537 r'(?:\s+(volatile|__volatile__))?'
541 _SEARCH_C_FILE = re.compile(
r'\b(?:LINT_C_FILE|'
542 r'vim?:\s*.*(\s*|:)filetype=c(\s*|:|$))')
545 _SEARCH_KERNEL_FILE = re.compile(
r'\b(?:LINT_KERNEL_FILE)')
547 _regexp_compile_cache = {}
551 _error_suppressions = {}
564 _valid_extensions = set([
'cc',
'cpp',
'cu',
'cuh'])
568 _hpp_headers = set([
'h',
'hpp',
'hxx'])
572 _global_error_suppressions = {}
577 _hpp_headers = set(val.split(
','))
579 _valid_extensions.update(_hpp_headers)
581 PrintUsage(
'Header extensions must be comma separated list.')
584 return file_extension
in _hpp_headers
587 """Updates the global list of line error-suppressions.
589 Parses any NOLINT comments on the current line, updating the global
590 error_suppressions store. Reports an error if the NOLINT comment
594 filename: str, the name of the input file.
595 raw_line: str, the line of input text, with comments.
596 linenum: int, the number of the current line.
597 error: function, an error handler.
599 matched =
Search(
r'\bNOLINT(NEXTLINE)?\b(\([^)]+\))?', raw_line)
602 suppressed_line = linenum + 1
604 suppressed_line = linenum
605 category = matched.group(2)
606 if category
in (
None,
'(*)'):
607 _error_suppressions.setdefault(
None, set()).add(suppressed_line)
609 if category.startswith(
'(')
and category.endswith(
')'):
610 category = category[1:-1]
611 if category
in _ERROR_CATEGORIES:
612 _error_suppressions.setdefault(category, set()).add(suppressed_line)
613 elif category
not in _LEGACY_ERROR_CATEGORIES:
614 error(filename, linenum,
'readability/nolint', 5,
615 'Unknown NOLINT error category: %s' % category)
619 """Updates the list of global error suppressions.
621 Parses any lint directives in the file that have global effect.
624 lines: An array of strings, each representing a line of the file, with the
625 last element being empty if the file is terminated with a newline.
628 if _SEARCH_C_FILE.search(line):
629 for category
in _DEFAULT_C_SUPPRESSED_CATEGORIES:
630 _global_error_suppressions[category] =
True
631 if _SEARCH_KERNEL_FILE.search(line):
632 for category
in _DEFAULT_KERNEL_SUPPRESSED_CATEGORIES:
633 _global_error_suppressions[category] =
True
637 """Resets the set of NOLINT suppressions to empty."""
638 _error_suppressions.clear()
639 _global_error_suppressions.clear()
643 """Returns true if the specified error category is suppressed on this line.
645 Consults the global error_suppressions map populated by
646 ParseNolintSuppressions/ProcessGlobalSuppresions/ResetNolintSuppressions.
649 category: str, the category of the error.
650 linenum: int, the current line number.
652 bool, True iff the error should be suppressed due to a NOLINT comment or
655 return (_global_error_suppressions.get(category,
False)
or
656 linenum
in _error_suppressions.get(category, set())
or
657 linenum
in _error_suppressions.get(
None, set()))
661 """Matches the string with the pattern, caching the compiled regexp."""
665 if pattern
not in _regexp_compile_cache:
666 _regexp_compile_cache[pattern] = sre_compile.compile(pattern)
667 return _regexp_compile_cache[pattern].match(s)
671 """Replaces instances of pattern in a string with a replacement.
673 The compiled regex is kept in a cache shared by Match and Search.
676 pattern: regex pattern
677 rep: replacement text
681 string with replacements made (or original string if no replacements)
683 if pattern
not in _regexp_compile_cache:
684 _regexp_compile_cache[pattern] = sre_compile.compile(pattern)
685 return _regexp_compile_cache[pattern].sub(rep, s)
689 """Searches the string for the pattern, caching the compiled regexp."""
690 if pattern
not in _regexp_compile_cache:
691 _regexp_compile_cache[pattern] = sre_compile.compile(pattern)
692 return _regexp_compile_cache[pattern].search(s)
696 """File extension (excluding dot) matches a source file extension."""
697 return s
in (
'c',
'cc',
'cpp',
'cxx')
701 """Tracks line numbers for includes, and the order in which includes appear.
703 include_list contains list of lists of (header, line number) pairs.
704 It's a lists of lists rather than just one flat list to make it
705 easier to update across preprocessor boundaries.
707 Call CheckNextIncludeOrder() once for each header in the file, passing
708 in the type constants defined above. Calls in an illegal order will
709 raise an _IncludeError with an appropriate error message.
721 _C_SYS_HEADER:
'C system header',
722 _CPP_SYS_HEADER:
'C++ system header',
723 _LIKELY_MY_HEADER:
'header this file implements',
724 _POSSIBLE_MY_HEADER:
'header this file may implement',
725 _OTHER_HEADER:
'other header',
728 _INITIAL_SECTION:
"... nothing. (This can't be an error.)",
729 _MY_H_SECTION:
'a header this file implements',
730 _C_SECTION:
'C system header',
731 _CPP_SECTION:
'C++ system header',
732 _OTHER_H_SECTION:
'other header',
740 """Check if a header has already been included.
743 header: header to check.
745 Line number of previous occurrence, or -1 if the header has not
749 for f
in section_list:
755 """Reset section checking for preprocessor directive.
758 directive: preprocessor directive (e.g. "if", "else").
767 if directive
in (
'if',
'ifdef',
'ifndef'):
769 elif directive
in (
'else',
'elif'):
776 """Returns a path canonicalized for alphabetical comparison.
778 - replaces "-" with "_" so they both cmp the same.
779 - removes '-inl' since we don't require them to be after the main header.
780 - lowercase everything, just in case.
783 header_path: Path to be canonicalized.
788 return header_path.replace(
'-inl.h',
'.h').replace(
'-',
'_').lower()
791 """Check if a header is in alphabetical order with the previous header.
794 clean_lines: A CleansedLines instance containing the file.
795 linenum: The number of the line to check.
796 header_path: Canonicalized header to be checked.
799 Returns true if the header is in alphabetical order.
807 Match(
r'^\s*#\s*include\b', clean_lines.elided[linenum - 1])):
812 """Returns a non-empty error message if the next header is out of order.
814 This function also updates the internal state to be ready to check
818 header_type: One of the _XXX_HEADER constants defined above.
821 The empty string if the header is in the right order, or an
822 error message describing what's wrong.
825 error_message = (
'Found %s after %s' %
831 if header_type == _C_SYS_HEADER:
837 elif header_type == _CPP_SYS_HEADER:
843 elif header_type == _LIKELY_MY_HEADER:
848 elif header_type == _POSSIBLE_MY_HEADER:
856 assert header_type == _OTHER_HEADER
866 """Maintains module-wide state.."""
885 """Sets the output format for errors."""
889 """Sets the module's quiet settings, and returns the previous setting."""
890 last_quiet = self.
quiet
895 """Sets the module's verbosity, and returns the previous setting."""
898 return last_verbose_level
901 """Sets the module's counting options."""
905 """Sets the error-message filters.
907 These filters are applied when deciding whether to emit a given
911 filters: A string of comma-separated filters (eg "+whitespace/indent").
912 Each filter should start with + or -; else we die.
915 ValueError: The comma-separated filters did not all start with '+' or '-'.
916 E.g. "-,+whitespace,-whitespace/indent,whitespace/badfilter"
919 self.
filters = _DEFAULT_FILTERS[:]
923 """ Adds more filters to the existing list of error-message filters. """
924 for filt
in filters.split(
','):
925 clean_filt = filt.strip()
927 self.
filters.append(clean_filt)
929 if not (filt.startswith(
'+')
or filt.startswith(
'-')):
930 raise ValueError(
'Every filter in --filters must start with + or -'
931 ' (%s does not)' % filt)
934 """ Saves the current filter list to backup storage."""
938 """ Restores filters previously backed up."""
942 """Sets the module's error statistic back to zero."""
947 """Bumps the module's error statistic."""
949 if self.
counting in (
'toplevel',
'detailed'):
951 category = category.split(
'/')[0]
957 """Print a summary of errors by category, and the total."""
959 sys.stderr.write(
'Category \'%s\' errors found: %d\n' %
961 sys.stdout.write(
'Total errors found: %d\n' % self.
error_count)
967 """Gets the module's output format."""
968 return _cpplint_state.output_format
972 """Sets the module's output format."""
973 _cpplint_state.SetOutputFormat(output_format)
976 """Return's the module's quiet setting."""
977 return _cpplint_state.quiet
980 """Set the module's quiet status, and return previous setting."""
981 return _cpplint_state.SetQuiet(quiet)
985 """Returns the module's verbosity setting."""
986 return _cpplint_state.verbose_level
990 """Sets the module's verbosity, and returns the previous setting."""
991 return _cpplint_state.SetVerboseLevel(level)
995 """Sets the module's counting options."""
996 _cpplint_state.SetCountingStyle(level)
1000 """Returns the module's list of output filters, as a list."""
1001 return _cpplint_state.filters
1005 """Sets the module's error-message filters.
1007 These filters are applied when deciding whether to emit a given
1011 filters: A string of comma-separated filters (eg "whitespace/indent").
1012 Each filter should start with + or -; else we die.
1014 _cpplint_state.SetFilters(filters)
1017 """Adds more filter overrides.
1019 Unlike _SetFilters, this function does not reset the current list of filters
1023 filters: A string of comma-separated filters (eg "whitespace/indent").
1024 Each filter should start with + or -; else we die.
1026 _cpplint_state.AddFilters(filters)
1029 """ Saves the current filter list to backup storage."""
1030 _cpplint_state.BackupFilters()
1033 """ Restores filters previously backed up."""
1034 _cpplint_state.RestoreFilters()
1037 """Tracks current function name and the number of lines in its body."""
1039 _NORMAL_TRIGGER = 250
1048 """Start analyzing function body.
1051 function_name: The name of the function being tracked.
1058 """Count line in current function body."""
1062 def Check(self, error, filename, linenum):
1063 """Report if too many lines in function body.
1066 error: The function to call with any errors found.
1067 filename: The name of the current file.
1068 linenum: The number of the line to check.
1084 error(filename, linenum,
'readability/fn_size', error_level,
1085 'Small and focused functions are preferred:'
1086 ' %s has %d non-comment lines'
1087 ' (error triggered by exceeding %d lines).' % (
1091 """Stop analyzing function body."""
1096 """Indicates a problem with the include order in a file."""
1100 class FileInfo(object):
1101 """Provides utility functions for filenames.
1103 FileInfo provides easy access to the components of a file's path
1104 relative to the project root.
1111 """Make Windows paths like Unix."""
1112 return os.path.abspath(self.
_filename).replace(
'\\',
'/')
1115 """FullName after removing the local path to the repository.
1117 If we have a real absolute path name here we can try to do something smart:
1118 detecting the root of the checkout and truncating /path/to/checkout from
1119 the name so that we get header guards that don't include things like
1120 "C:\Documents and Settings\..." or "/home/username/..." in them and thus
1121 people on different computers who have checked the source out to different
1122 locations won't see bogus errors.
1126 if os.path.exists(fullname):
1127 project_dir = os.path.dirname(fullname)
1129 if os.path.exists(os.path.join(project_dir,
".svn")):
1132 root_dir = project_dir
1133 one_up_dir = os.path.dirname(root_dir)
1134 while os.path.exists(os.path.join(one_up_dir,
".svn")):
1135 root_dir = os.path.dirname(root_dir)
1136 one_up_dir = os.path.dirname(one_up_dir)
1138 prefix = os.path.commonprefix([root_dir, project_dir])
1139 return fullname[len(prefix) + 1:]
1143 root_dir = current_dir = os.path.dirname(fullname)
1144 while current_dir != os.path.dirname(current_dir):
1145 if (os.path.exists(os.path.join(current_dir,
".git"))
or
1146 os.path.exists(os.path.join(current_dir,
".hg"))
or
1147 os.path.exists(os.path.join(current_dir,
".svn"))):
1148 root_dir = current_dir
1149 current_dir = os.path.dirname(current_dir)
1151 if (os.path.exists(os.path.join(root_dir,
".git"))
or
1152 os.path.exists(os.path.join(root_dir,
".hg"))
or
1153 os.path.exists(os.path.join(root_dir,
".svn"))):
1154 prefix = os.path.commonprefix([root_dir, project_dir])
1155 return fullname[len(prefix) + 1:]
1161 """Splits the file into the directory, basename, and extension.
1163 For 'chrome/browser/browser.cc', Split() would
1164 return ('chrome/browser', 'browser', '.cc')
1167 A tuple of (directory, basename, extension).
1171 project, rest = os.path.split(googlename)
1172 return (project,) + os.path.splitext(rest)
1175 """File base name - text after the final slash, before the final period."""
1176 return self.
Split()[1]
1179 """File extension - text following the final period."""
1180 return self.
Split()[2]
1183 """File has no source file extension."""
1184 return '/'.join(self.
Split()[0:2])
1187 """File has a source file extension."""
1192 """If confidence >= verbose, category passes filter and is not suppressed."""
1200 if confidence < _cpplint_state.verbose_level:
1205 if one_filter.startswith(
'-'):
1206 if category.startswith(one_filter[1:]):
1208 elif one_filter.startswith(
'+'):
1209 if category.startswith(one_filter[1:]):
1219 def Error(filename, linenum, category, confidence, message):
1220 """Logs the fact we've found a lint error.
1222 We log where the error was found, and also our confidence in the error,
1223 that is, how certain we are this is a legitimate style regression, and
1224 not a misidentification or a use that's sometimes justified.
1226 False positives can be suppressed by the use of
1227 "cpplint(category)" comments on the offending line. These are
1228 parsed into _error_suppressions.
1231 filename: The name of the file containing the error.
1232 linenum: The number of the line containing the error.
1233 category: A string used to describe the "category" this bug
1234 falls under: "whitespace", say, or "runtime". Categories
1235 may have a hierarchy separated by slashes: "whitespace/indent".
1236 confidence: A number from 1-5 representing a confidence score for
1237 the error, with 5 meaning that we are certain of the problem,
1238 and 1 meaning that it could be a legitimate construct.
1239 message: The error message.
1242 _cpplint_state.IncrementErrorCount(category)
1243 if _cpplint_state.output_format ==
'vs7':
1244 sys.stderr.write(
'%s(%s): error cpplint: [%s] %s [%d]\n' % (
1245 filename, linenum, category, message, confidence))
1246 elif _cpplint_state.output_format ==
'eclipse':
1247 sys.stderr.write(
'%s:%s: warning: %s [%s] [%d]\n' % (
1248 filename, linenum, message, category, confidence))
1250 sys.stderr.write(
'%s:%s: %s [%s] [%d]\n' % (
1251 filename, linenum, message, category, confidence))
1255 _RE_PATTERN_CLEANSE_LINE_ESCAPES = re.compile(
1256 r'\\([abfnrtv?"\\\']|\d+|x[0-9a-fA-F]+)')
1258 _RE_PATTERN_C_COMMENTS =
r'/\*(?:[^*]|\*(?!/))*\*/'
1267 _RE_PATTERN_CLEANSE_LINE_C_COMMENTS = re.compile(
1268 r'(\s*' + _RE_PATTERN_C_COMMENTS +
r'\s*$|' +
1269 _RE_PATTERN_C_COMMENTS +
r'\s+|' +
1270 r'\s+' + _RE_PATTERN_C_COMMENTS +
r'(?=\W)|' +
1271 _RE_PATTERN_C_COMMENTS +
r')')
1275 """Does line terminate so, that the next symbol is in string constant.
1277 This function does not consider single-line nor multi-line comments.
1280 line: is a partial line of code starting from the 0..n.
1283 True, if next character appended to 'line' is inside a
1287 line = line.replace(
r'\\',
'XX')
1288 return ((line.count(
'"') - line.count(
r'\"') - line.count(
"'\"'")) & 1) == 1
1292 """Removes C++11 raw strings from lines.
1295 static const char kData[] = R"(
1300 static const char kData[] = ""
1301 (replaced by blank line)
1305 raw_lines: list of raw lines.
1308 list of lines with C++11 raw strings replaced by empty strings.
1312 lines_without_raw_strings = []
1313 for line
in raw_lines:
1316 end = line.find(delimiter)
1321 leading_space =
Match(
r'^(\s*)\S', line)
1322 line = leading_space.group(1) +
'""' + line[end + len(delimiter):]
1331 while delimiter
is None:
1342 matched =
Match(
r'^(.*?)\b(?:R|u8R|uR|UR|LR)"([^\s\\()]*)\((.*)$', line)
1344 not Match(
r'^([^\'"]|\'(\\.|[^\'])*\'|"(\\.|[^"])*")*//',
1346 delimiter =
')' + matched.group(2) +
'"'
1348 end = matched.group(3).find(delimiter)
1351 line = (matched.group(1) +
'""' +
1352 matched.group(3)[end + len(delimiter):])
1356 line = matched.group(1) +
'""'
1360 lines_without_raw_strings.append(line)
1364 return lines_without_raw_strings
1368 """Find the beginning marker for a multiline comment."""
1369 while lineix < len(lines):
1370 if lines[lineix].strip().startswith(
'/*'):
1372 if lines[lineix].strip().find(
'*/', 2) < 0:
1379 """We are inside a comment, find the end marker."""
1380 while lineix < len(lines):
1381 if lines[lineix].strip().endswith(
'*/'):
1388 """Clears a range of lines for multi-line comments."""
1391 for i
in range(begin, end):
1396 """Removes multiline (c-style) comments from lines."""
1398 while lineix < len(lines):
1400 if lineix_begin >= len(lines):
1403 if lineix_end >= len(lines):
1404 error(filename, lineix_begin + 1,
'readability/multiline_comment', 5,
1405 'Could not find end of multi-line comment')
1408 lineix = lineix_end + 1
1412 """Removes //-comments and single-line C-style /* */ comments.
1415 line: A line of C++ source.
1418 The line with single-line comments removed.
1420 commentpos = line.find(
'//')
1421 if commentpos != -1
and not IsCppString(line[:commentpos]):
1422 line = line[:commentpos].rstrip()
1424 return _RE_PATTERN_CLEANSE_LINE_C_COMMENTS.sub(
'', line)
1428 """Holds 4 copies of all lines with different preprocessing applied to them.
1430 1) elided member contains lines without strings and comments.
1431 2) lines member contains lines without comments.
1432 3) raw_lines member contains all the lines without processing.
1433 4) lines_without_raw_strings member is same as raw_lines, but with C++11 raw
1435 All these members are of <type 'list'>, and of the same length.
1451 """Returns the number of lines represented."""
1456 """Collapses strings and chars on a line to simple "" or '' blocks.
1458 We nix strings first so we're not fooled by text like '"http://"'
1461 elided: The line being processed.
1464 The line with collapsed strings.
1466 if _RE_PATTERN_INCLUDE.match(elided):
1472 elided = _RE_PATTERN_CLEANSE_LINE_ESCAPES.sub(
'', elided)
1480 match =
Match(
r'^([^\'"]*)([\'"])(.*)$', elided)
1484 head, quote, tail = match.groups()
1488 second_quote = tail.find(
'"')
1489 if second_quote >= 0:
1490 collapsed += head +
'""'
1491 elided = tail[second_quote + 1:]
1505 if Search(
r'\b(?:0[bBxX]?|[1-9])[0-9a-fA-F]*$', head):
1506 match_literal =
Match(
r'^((?:\'?[0-9a-zA-Z_])*)(.*)$',
"'" + tail)
1507 collapsed += head + match_literal.group(1).replace(
"'",
'')
1508 elided = match_literal.group(2)
1510 second_quote = tail.find(
'\'')
1511 if second_quote >= 0:
1512 collapsed += head +
"''"
1513 elided = tail[second_quote + 1:]
1523 """Find the position just after the end of current parenthesized expression.
1526 line: a CleansedLines line.
1527 startpos: start searching at this position.
1528 stack: nesting stack at startpos.
1531 On finding matching end: (index just after matching end, None)
1532 On finding an unclosed expression: (-1, None)
1533 Otherwise: (-1, new stack at end of this line)
1535 for i
in xrange(startpos, len(line)):
1542 if i > 0
and line[i - 1] ==
'<':
1544 if stack
and stack[-1] ==
'<':
1548 elif i > 0
and Search(
r'\boperator\s*$', line[0:i]):
1559 while stack
and stack[-1] ==
'<':
1563 if ((stack[-1] ==
'(' and char ==
')')
or
1564 (stack[-1] ==
'[' and char ==
']')
or
1565 (stack[-1] ==
'{' and char ==
'}')):
1568 return (i + 1,
None)
1577 (line[i - 1] ==
'-' or Search(
r'\boperator\s*$', line[0:i - 1]))):
1583 if stack[-1] ==
'<':
1586 return (i + 1,
None)
1591 while stack
and stack[-1] ==
'<':
1601 """If input points to ( or { or [ or <, finds the position that closes it.
1603 If lines[linenum][pos] points to a '(' or '{' or '[' or '<', finds the
1604 linenum/pos that correspond to the closing of the expression.
1606 TODO(unknown): cpplint spends a fair bit of time matching parentheses.
1607 Ideally we would want to index all opening and closing parentheses once
1608 and have CloseExpression be just a simple lookup, but due to preprocessor
1609 tricks, this is not so easy.
1612 clean_lines: A CleansedLines instance containing the file.
1613 linenum: The number of the line to check.
1614 pos: A position on the line.
1617 A tuple (line, linenum, pos) pointer *past* the closing brace, or
1618 (line, len(lines), -1) if we never find a close. Note we ignore
1619 strings and comments when matching; and the line we return is the
1620 'cleansed' line at linenum.
1623 line = clean_lines.elided[linenum]
1624 if (line[pos]
not in '({[<')
or Match(
r'<[<=]', line[pos:]):
1625 return (line, clean_lines.NumLines(), -1)
1630 return (line, linenum, end_pos)
1633 while stack
and linenum < clean_lines.NumLines() - 1:
1635 line = clean_lines.elided[linenum]
1638 return (line, linenum, end_pos)
1641 return (line, clean_lines.NumLines(), -1)
1645 """Find position at the matching start of current expression.
1647 This is almost the reverse of FindEndOfExpressionInLine, but note
1648 that the input position and returned position differs by 1.
1651 line: a CleansedLines line.
1652 endpos: start searching at this position.
1653 stack: nesting stack at endpos.
1656 On finding matching start: (index at matching start, None)
1657 On finding an unclosed expression: (-1, None)
1658 Otherwise: (-1, new stack at beginning of this line)
1671 (line[i - 1] ==
'-' or
1672 Match(
r'\s>=\s', line[i - 1:])
or
1673 Search(
r'\boperator\s*$', line[0:i]))):
1679 if i > 0
and line[i - 1] ==
'<':
1685 if stack
and stack[-1] ==
'>':
1694 while stack
and stack[-1] ==
'>':
1698 if ((char ==
'(' and stack[-1] ==
')')
or
1699 (char ==
'[' and stack[-1] ==
']')
or
1700 (char ==
'{' and stack[-1] ==
'}')):
1711 while stack
and stack[-1] ==
'>':
1722 """If input points to ) or } or ] or >, finds the position that opens it.
1724 If lines[linenum][pos] points to a ')' or '}' or ']' or '>', finds the
1725 linenum/pos that correspond to the opening of the expression.
1728 clean_lines: A CleansedLines instance containing the file.
1729 linenum: The number of the line to check.
1730 pos: A position on the line.
1733 A tuple (line, linenum, pos) pointer *at* the opening brace, or
1734 (line, 0, -1) if we never find the matching opening brace. Note
1735 we ignore strings and comments when matching; and the line we
1736 return is the 'cleansed' line at linenum.
1738 line = clean_lines.elided[linenum]
1739 if line[pos]
not in ')}]>':
1740 return (line, 0, -1)
1745 return (line, linenum, start_pos)
1748 while stack
and linenum > 0:
1750 line = clean_lines.elided[linenum]
1753 return (line, linenum, start_pos)
1756 return (line, 0, -1)
1760 """Logs an error if no Copyright message appears at the top of the file."""
1764 for line
in xrange(1, min(len(lines), 11)):
1765 if re.search(
r'Copyright', lines[line], re.I):
break
1767 error(filename, 0,
'legal/copyright', 5,
1768 'No copyright message found. '
1769 'You should have a line: "Copyright [year] <Copyright Owner>"')
1773 """Return the number of leading spaces in line.
1776 line: A string to check.
1779 An integer count of leading spaces, possibly zero.
1781 indent =
Match(
r'^( *)\S', line)
1783 return len(indent.group(1))
1788 """Returns the path split into a list by the separator.
1791 path: An absolute or relative path (e.g. '/a/b/c/' or '../a')
1794 A list of path components (e.g. ['a', 'b', 'c]).
1798 (head, tail) = os.path.split(path)
1813 """Returns the CPP variable that should be used as a header guard.
1816 filename: The name of a C++ header file.
1819 The CPP variable that should be used as a header guard in the
1826 filename = re.sub(
r'_flymake\.h$',
'.h', filename)
1827 filename = re.sub(
r'/\.flymake/([^/]*)$',
r'/\1', filename)
1829 filename = filename.replace(
'C++',
'cpp').replace(
'c++',
'cpp')
1832 file_path_from_root = fileinfo.RepositoryName()
1834 def FixupPathFromRoot():
1836 sys.stderr.write(
"\n_root fixup, _root = '%s', repository name = '%s'\n"
1837 %(_root, fileinfo.RepositoryName()))
1842 sys.stderr.write(
"_root unspecified\n")
1843 return file_path_from_root
1845 def StripListPrefix(lst, prefix):
1847 if lst[:len(prefix)] != prefix:
1850 return lst[(len(prefix)):]
1858 sys.stderr.write((
"_root lstrip (maybe_path=%s, file_path_from_root=%s," +
1859 " _root=%s)\n") %(maybe_path, file_path_from_root, _root))
1862 return os.path.join(*maybe_path)
1865 full_path = fileinfo.FullName()
1866 root_abspath = os.path.abspath(_root)
1872 sys.stderr.write((
"_root prepend (maybe_path=%s, full_path=%s, " +
1873 "root_abspath=%s)\n") %(maybe_path, full_path, root_abspath))
1876 return os.path.join(*maybe_path)
1879 sys.stderr.write(
"_root ignore, returning %s\n" %(file_path_from_root))
1882 return file_path_from_root
1884 file_path_from_root = FixupPathFromRoot()
1885 return re.sub(
r'[^a-zA-Z0-9]',
'_', file_path_from_root).upper() +
'_'
1889 """Checks that the file contains a header guard.
1891 Logs an error if no #ifndef header guard is present. For other
1892 headers, checks that the full pathname is used.
1895 filename: The name of the C++ header file.
1896 clean_lines: A CleansedLines instance containing the file.
1897 error: The function to call with any errors found.
1906 raw_lines = clean_lines.lines_without_raw_strings
1908 if Search(
r'//\s*NOLINT\(build/header_guard\)', i):
1918 for linenum, line
in enumerate(raw_lines):
1919 linesplit = line.split()
1920 if len(linesplit) >= 2:
1922 if not ifndef
and linesplit[0] ==
'#ifndef':
1924 ifndef = linesplit[1]
1925 ifndef_linenum = linenum
1926 if not define
and linesplit[0] ==
'#define':
1927 define = linesplit[1]
1929 if line.startswith(
'#endif'):
1931 endif_linenum = linenum
1933 if not ifndef
or not define
or ifndef != define:
1934 error(filename, 0,
'build/header_guard', 5,
1935 'No #ifndef header guard found, suggested CPP variable is: %s' %
1941 if ifndef != cppvar:
1943 if ifndef != cppvar +
'_':
1948 error(filename, ifndef_linenum,
'build/header_guard', error_level,
1949 '#ifndef header guard has wrong style, please use: %s' % cppvar)
1954 match =
Match(
r'#endif\s*//\s*' + cppvar +
r'(_)?\b', endif)
1956 if match.group(1) ==
'_':
1958 error(filename, endif_linenum,
'build/header_guard', 0,
1959 '#endif line should be "#endif // %s"' % cppvar)
1965 no_single_line_comments =
True
1966 for i
in xrange(1, len(raw_lines) - 1):
1968 if Match(
r'^(?:(?:\'(?:\.|[^\'])*\')|(?:"(?:\.|[^"])*")|[^\'"])*//', line):
1969 no_single_line_comments =
False
1972 if no_single_line_comments:
1973 match =
Match(
r'#endif\s*/\*\s*' + cppvar +
r'(_)?\s*\*/', endif)
1975 if match.group(1) ==
'_':
1977 error(filename, endif_linenum,
'build/header_guard', 0,
1978 '#endif line should be "#endif /* %s */"' % cppvar)
1982 error(filename, endif_linenum,
'build/header_guard', 5,
1983 '#endif line should be "#endif // %s"' % cppvar)
1987 """Logs an error if a .cc file does not include its header."""
1991 if Search(_TEST_FILE_SUFFIX, fileinfo.BaseName()):
1994 headerfile = filename[0:len(filename) - len(fileinfo.Extension())] +
'.h'
1995 if not os.path.exists(headerfile):
1997 headername =
FileInfo(headerfile).RepositoryName()
1999 for section_list
in include_state.include_list:
2000 for f
in section_list:
2001 if headername
in f[0]
or f[0]
in headername:
2003 if not first_include:
2004 first_include = f[1]
2006 error(filename, first_include,
'build/include', 5,
2007 '%s should include its header file %s' % (fileinfo.RepositoryName(),
2012 """Logs an error for each line containing bad characters.
2014 Two kinds of bad characters:
2016 1. Unicode replacement characters: These indicate that either the file
2017 contained invalid UTF-8 (likely) or Unicode replacement characters (which
2018 it shouldn't). Note that it's possible for this to throw off line
2019 numbering if the invalid UTF-8 occurred adjacent to a newline.
2021 2. NUL bytes. These are problematic for some tools.
2024 filename: The name of the current file.
2025 lines: An array of strings, each representing a line of the file.
2026 error: The function to call with any errors found.
2028 for linenum, line
in enumerate(lines):
2029 if u'\ufffd' in line:
2030 error(filename, linenum,
'readability/utf8', 5,
2031 'Line contains invalid UTF-8 (or Unicode replacement character).')
2033 error(filename, linenum,
'readability/nul', 5,
'Line contains NUL byte.')
2037 """Logs an error if there is no newline char at the end of the file.
2040 filename: The name of the current file.
2041 lines: An array of strings, each representing a line of the file.
2042 error: The function to call with any errors found.
2049 if len(lines) < 3
or lines[-2]:
2050 error(filename, len(lines) - 2,
'whitespace/ending_newline', 5,
2051 'Could not find a newline character at the end of the file.')
2055 """Logs an error if we see /* ... */ or "..." that extend past one line.
2057 /* ... */ comments are legit inside macros, for one line.
2058 Otherwise, we prefer // comments, so it's ok to warn about the
2059 other. Likewise, it's ok for strings to extend across multiple
2060 lines, as long as a line continuation character (backslash)
2061 terminates each line. Although not currently prohibited by the C++
2062 style guide, it's ugly and unnecessary. We don't do well with either
2063 in this lint program, so we warn about both.
2066 filename: The name of the current file.
2067 clean_lines: A CleansedLines instance containing the file.
2068 linenum: The number of the line to check.
2069 error: The function to call with any errors found.
2071 line = clean_lines.elided[linenum]
2075 line = line.replace(
'\\\\',
'')
2077 if line.count(
'/*') > line.count(
'*/'):
2078 error(filename, linenum,
'readability/multiline_comment', 5,
2079 'Complex multi-line /*...*/-style comment found. '
2080 'Lint may give bogus warnings. '
2081 'Consider replacing these with //-style comments, '
2082 'with #if 0...#endif, '
2083 'or with more clearly structured multi-line comments.')
2085 if (line.count(
'"') - line.count(
'\\"')) % 2:
2086 error(filename, linenum,
'readability/multiline_string', 5,
2087 'Multi-line string ("...") found. This lint script doesn\'t '
2088 'do well with such strings, and may give bogus warnings. '
2089 'Use C++11 raw strings or concatenation instead.')
2104 _UNSAFE_FUNC_PREFIX =
r'(?:[-+*/=%^&|(<]\s*|>\s+)'
2106 (
'asctime(',
'asctime_r(', _UNSAFE_FUNC_PREFIX +
r'asctime\([^)]+\)'),
2107 (
'ctime(',
'ctime_r(', _UNSAFE_FUNC_PREFIX +
r'ctime\([^)]+\)'),
2108 (
'getgrgid(',
'getgrgid_r(', _UNSAFE_FUNC_PREFIX +
r'getgrgid\([^)]+\)'),
2109 (
'getgrnam(',
'getgrnam_r(', _UNSAFE_FUNC_PREFIX +
r'getgrnam\([^)]+\)'),
2110 (
'getlogin(',
'getlogin_r(', _UNSAFE_FUNC_PREFIX +
r'getlogin\(\)'),
2111 (
'getpwnam(',
'getpwnam_r(', _UNSAFE_FUNC_PREFIX +
r'getpwnam\([^)]+\)'),
2112 (
'getpwuid(',
'getpwuid_r(', _UNSAFE_FUNC_PREFIX +
r'getpwuid\([^)]+\)'),
2113 (
'gmtime(',
'gmtime_r(', _UNSAFE_FUNC_PREFIX +
r'gmtime\([^)]+\)'),
2114 (
'localtime(',
'localtime_r(', _UNSAFE_FUNC_PREFIX +
r'localtime\([^)]+\)'),
2115 (
'rand(',
'rand_r(', _UNSAFE_FUNC_PREFIX +
r'rand\(\)'),
2116 (
'strtok(',
'strtok_r(',
2117 _UNSAFE_FUNC_PREFIX +
r'strtok\([^)]+\)'),
2118 (
'ttyname(',
'ttyname_r(', _UNSAFE_FUNC_PREFIX +
r'ttyname\([^)]+\)'),
2123 """Checks for calls to thread-unsafe functions.
2125 Much code has been originally written without consideration of
2126 multi-threading. Also, engineers are relying on their old experience;
2127 they have learned posix before threading extensions were added. These
2128 tests guide the engineers to use thread-safe functions (when using
2132 filename: The name of the current file.
2133 clean_lines: A CleansedLines instance containing the file.
2134 linenum: The number of the line to check.
2135 error: The function to call with any errors found.
2137 line = clean_lines.elided[linenum]
2138 for single_thread_func, multithread_safe_func, pattern
in _THREADING_LIST:
2141 if Search(pattern, line):
2142 error(filename, linenum,
'runtime/threadsafe_fn', 2,
2143 'Consider using ' + multithread_safe_func +
2144 '...) instead of ' + single_thread_func +
2145 '...) for improved thread safety.')
2149 """Checks that VLOG() is only used for defining a logging level.
2151 For example, VLOG(2) is correct. VLOG(INFO), VLOG(WARNING), VLOG(ERROR), and
2152 VLOG(FATAL) are not.
2155 filename: The name of the current file.
2156 clean_lines: A CleansedLines instance containing the file.
2157 linenum: The number of the line to check.
2158 error: The function to call with any errors found.
2160 line = clean_lines.elided[linenum]
2161 if Search(
r'\bVLOG\((INFO|ERROR|WARNING|DFATAL|FATAL)\)', line):
2162 error(filename, linenum,
'runtime/vlog', 5,
2163 'VLOG() should be used with numeric verbosity level. '
2164 'Use LOG() if you want symbolic severity levels.')
2168 _RE_PATTERN_INVALID_INCREMENT = re.compile(
2169 r'^\s*\*\w+(\+\+|--);')
2173 """Checks for invalid increment *count++.
2175 For example following function:
2176 void increment_counter(int* count) {
2179 is invalid, because it effectively does count++, moving pointer, and should
2180 be replaced with ++*count, (*count)++ or *count += 1.
2183 filename: The name of the current file.
2184 clean_lines: A CleansedLines instance containing the file.
2185 linenum: The number of the line to check.
2186 error: The function to call with any errors found.
2188 line = clean_lines.elided[linenum]
2189 if _RE_PATTERN_INVALID_INCREMENT.match(line):
2190 error(filename, linenum,
'runtime/invalid_increment', 5,
2191 'Changing pointer instead of value (or unused value of operator*).')
2195 if Search(
r'^#define', clean_lines[linenum]):
2198 if linenum > 0
and Search(
r'\\$', clean_lines[linenum - 1]):
2205 return Match(
r'^\s*(\btemplate\b)*.*class\s+\w+;\s*$', clean_lines[linenum])
2209 """Stores information about a generic block of code."""
2219 """Run checks that applies to text up to the opening brace.
2221 This is mostly for checking the text after the class identifier
2222 and the "{", usually where the base class is specified. For other
2223 blocks, there isn't much to check, so we always pass.
2226 filename: The name of the current file.
2227 clean_lines: A CleansedLines instance containing the file.
2228 linenum: The number of the line to check.
2229 error: The function to call with any errors found.
2233 def CheckEnd(self, filename, clean_lines, linenum, error):
2234 """Run checks that applies to text after the closing brace.
2236 This is mostly used for checking end of namespace comments.
2239 filename: The name of the current file.
2240 clean_lines: A CleansedLines instance containing the file.
2241 linenum: The number of the line to check.
2242 error: The function to call with any errors found.
2247 """Returns true if this block is a _BlockInfo.
2249 This is convenient for verifying that an object is an instance of
2250 a _BlockInfo, but not an instance of any of the derived classes.
2253 True for this class, False for derived classes.
2259 """Stores information about an 'extern "C"' block."""
2262 _BlockInfo.__init__(self, linenum,
True)
2266 """Stores information about a class."""
2268 def __init__(self, name, class_or_struct, clean_lines, linenum):
2269 _BlockInfo.__init__(self, linenum,
False)
2273 if class_or_struct ==
'struct':
2291 for i
in range(linenum, clean_lines.NumLines()):
2292 line = clean_lines.elided[i]
2293 depth += line.count(
'{') - line.count(
'}')
2300 if Search(
'(^|[^:]):($|[^:])', clean_lines.elided[linenum]):
2303 def CheckEnd(self, filename, clean_lines, linenum, error):
2306 seen_last_thing_in_class =
False
2309 r'\b(DISALLOW_COPY_AND_ASSIGN|DISALLOW_IMPLICIT_CONSTRUCTORS)\(' +
2311 clean_lines.elided[i])
2313 if seen_last_thing_in_class:
2314 error(filename, i,
'readability/constructors', 3,
2315 match.group(1) +
' should be the last thing in the class')
2318 if not Match(
r'^\s*$', clean_lines.elided[i]):
2319 seen_last_thing_in_class =
True
2324 indent =
Match(
r'^( *)\}', clean_lines.elided[linenum])
2325 if indent
and len(indent.group(1)) != self.
class_indent:
2327 parent =
'struct ' + self.
name
2329 parent =
'class ' + self.
name
2330 error(filename, linenum,
'whitespace/indent', 3,
2331 'Closing brace should be aligned with beginning of %s' % parent)
2335 """Stores information about a namespace."""
2338 _BlockInfo.__init__(self, linenum,
False)
2342 def CheckEnd(self, filename, clean_lines, linenum, error):
2343 """Check end of namespace comments."""
2344 line = clean_lines.raw_lines[linenum]
2358 and not Match(
r'^\s*};*\s*(//|/\*).*\bnamespace\b', line)):
2375 if not Match((
r'^\s*};*\s*(//|/\*).*\bnamespace\s+' +
2376 re.escape(self.
name) +
r'[\*/\.\\\s]*$'),
2378 error(filename, linenum,
'readability/namespace', 5,
2379 'Namespace should be terminated with "// namespace %s"' %
2383 if not Match(
r'^\s*};*\s*(//|/\*).*\bnamespace[\*/\.\\\s]*$', line):
2386 if Match(
r'^\s*}.*\b(namespace anonymous|anonymous namespace)\b', line):
2387 error(filename, linenum,
'readability/namespace', 5,
2388 'Anonymous namespace should be terminated with "// namespace"'
2389 ' or "// anonymous namespace"')
2391 error(filename, linenum,
'readability/namespace', 5,
2392 'Anonymous namespace should be terminated with "// namespace"')
2396 """Stores checkpoints of nesting stacks when #if/#else is seen."""
2410 """Holds states related to parsing braces."""
2436 """Check if we have seen the opening brace for the innermost block.
2439 True if we have seen the opening brace, False if the innermost
2440 block is still expecting an opening brace.
2442 return (
not self.
stack)
or self.
stack[-1].seen_open_brace
2445 """Check if we are currently one level inside a namespace body.
2448 True if top of the stack is a namespace block, False otherwise.
2450 return self.
stack and isinstance(self.
stack[-1], _NamespaceInfo)
2453 """Check if we are currently one level inside an 'extern "C"' block.
2456 True if top of the stack is an extern block, False otherwise.
2458 return self.
stack and isinstance(self.
stack[-1], _ExternCInfo)
2461 """Check if we are currently one level inside a class or struct declaration.
2464 True if top of the stack is a class/struct, False otherwise.
2466 return self.
stack and isinstance(self.
stack[-1], _ClassInfo)
2469 """Check if we are currently one level inside an inline ASM block.
2472 True if the top of the stack is a block containing inline ASM.
2474 return self.
stack and self.
stack[-1].inline_asm != _NO_ASM
2477 """Check if current position is inside template argument list.
2480 clean_lines: A CleansedLines instance containing the file.
2481 linenum: The number of the line to check.
2482 pos: position just after the suspected template argument.
2484 True if (linenum, pos) is inside template arguments.
2486 while linenum < clean_lines.NumLines():
2488 line = clean_lines.elided[linenum]
2489 match =
Match(
r'^[^{};=\[\]\.<>]*(.)', line[pos:])
2494 token = match.group(1)
2495 pos += len(match.group(0))
2500 if token
in (
'{',
'}',
';'):
return False
2507 if token
in (
'>',
'=',
'[',
']',
'.'):
return True
2513 if pos >= len(line):
2520 (_, end_line, end_pos) =
CloseExpression(clean_lines, linenum, pos - 1)
2529 """Update preprocessor stack.
2531 We need to handle preprocessors due to classes like this:
2533 struct ResultDetailsPageElementExtensionPoint {
2535 struct ResultDetailsPageElementExtensionPoint : public Extension {
2538 We make the following assumptions (good enough for most files):
2539 - Preprocessor condition evaluates to true from #if up to first
2542 - Preprocessor condition evaluates to false from #else/#elif up
2543 to #endif. We still perform lint checks on these lines, but
2544 these do not affect nesting stack.
2547 line: current line to check.
2549 if Match(
r'^\s*#\s*(if|ifdef|ifndef)\b', line):
2553 elif Match(
r'^\s*#\s*(else|elif)\b', line):
2556 if not self.
pp_stack[-1].seen_else:
2561 self.
pp_stack[-1].stack_before_else = copy.deepcopy(self.
stack)
2564 self.
stack = copy.deepcopy(self.
pp_stack[-1].stack_before_if)
2568 elif Match(
r'^\s*#\s*endif\b', line):
2585 def Update(self, filename, clean_lines, linenum, error):
2586 """Update nesting state with current line.
2589 filename: The name of the current file.
2590 clean_lines: A CleansedLines instance containing the file.
2591 linenum: The number of the line to check.
2592 error: The function to call with any errors found.
2594 line = clean_lines.elided[linenum]
2612 inner_block = self.
stack[-1]
2613 depth_change = line.count(
'(') - line.count(
')')
2614 inner_block.open_parentheses += depth_change
2617 if inner_block.inline_asm
in (_NO_ASM, _END_ASM):
2618 if (depth_change != 0
and
2619 inner_block.open_parentheses == 1
and
2620 _MATCH_ASM.match(line)):
2622 inner_block.inline_asm = _INSIDE_ASM
2626 inner_block.inline_asm = _NO_ASM
2627 elif (inner_block.inline_asm == _INSIDE_ASM
and
2628 inner_block.open_parentheses == 0):
2630 inner_block.inline_asm = _END_ASM
2640 namespace_decl_match =
Match(
r'^\s*namespace\b\s*([:\w]+)?(.*)$', line)
2641 if not namespace_decl_match:
2644 new_namespace =
_NamespaceInfo(namespace_decl_match.group(1), linenum)
2645 self.
stack.append(new_namespace)
2647 line = namespace_decl_match.group(2)
2648 if line.find(
'{') != -1:
2649 new_namespace.seen_open_brace =
True
2650 line = line[line.find(
'{') + 1:]
2657 class_decl_match =
Match(
2658 r'^(\s*(?:template\s*<[\w\s<>,:]*>\s*)?'
2659 r'(class|struct)\s+(?:[A-Z_]+\s+)*(\w+(?:::\w+)*))'
2661 if (class_decl_match
and
2662 (
not self.
stack or self.
stack[-1].open_parentheses == 0)):
2672 end_declaration = len(class_decl_match.group(1))
2675 class_decl_match.group(3), class_decl_match.group(2),
2676 clean_lines, linenum))
2677 line = class_decl_match.group(4)
2682 self.
stack[-1].CheckBegin(filename, clean_lines, linenum, error)
2685 if self.
stack and isinstance(self.
stack[-1], _ClassInfo):
2686 classinfo = self.
stack[-1]
2687 access_match =
Match(
2688 r'^(.*)\b(public|private|protected|signals)(\s+(?:slots\s*)?)?'
2692 classinfo.access = access_match.group(2)
2696 indent = access_match.group(1)
2697 if (len(indent) != classinfo.class_indent + 1
and
2698 Match(
r'^\s*$', indent)):
2699 if classinfo.is_struct:
2700 parent =
'struct ' + classinfo.name
2702 parent =
'class ' + classinfo.name
2704 if access_match.group(3):
2705 slots = access_match.group(3)
2706 error(filename, linenum,
'whitespace/indent', 3,
2707 '%s%s: should be indented +1 space inside %s' % (
2708 access_match.group(2), slots, parent))
2713 matched =
Match(
r'^[^{;)}]*([{;)}])(.*)$', line)
2717 token = matched.group(1)
2723 self.
stack[-1].seen_open_brace =
True
2724 elif Match(
r'^extern\s*"[^"]*"\s*\{', line):
2728 if _MATCH_ASM.match(line):
2729 self.
stack[-1].inline_asm = _BLOCK_ASM
2731 elif token ==
';' or token ==
')':
2745 self.
stack[-1].CheckEnd(filename, clean_lines, linenum, error)
2747 line = matched.group(2)
2750 """Get class info on the top of the stack.
2753 A _ClassInfo object if we are inside a class, or None otherwise.
2755 for i
in range(len(self.
stack), 0, -1):
2756 classinfo = self.
stack[i - 1]
2757 if isinstance(classinfo, _ClassInfo):
2762 """Checks that all classes and namespaces have been completely parsed.
2764 Call this when all lines in a file have been processed.
2766 filename: The name of the current file.
2767 error: The function to call with any errors found.
2772 for obj
in self.
stack:
2773 if isinstance(obj, _ClassInfo):
2774 error(filename, obj.starting_linenum,
'build/class', 5,
2775 'Failed to find complete declaration of class %s' %
2777 elif isinstance(obj, _NamespaceInfo):
2778 error(filename, obj.starting_linenum,
'build/namespaces', 5,
2779 'Failed to find complete declaration of namespace %s' %
2784 nesting_state, error):
2785 r"""Logs an error if we see certain non-ANSI constructs ignored by gcc-2.
2787 Complain about several constructs which gcc-2 accepts, but which are
2788 not standard C++. Warning about these in lint is one way to ease the
2789 transition to new compilers.
2790 - put storage class first (e.g. "static const" instead of "const static").
2791 - "%lld" instead of %qd" in printf-type functions.
2792 - "%1$d" is non-standard in printf-type functions.
2793 - "\%" is an undefined character escape sequence.
2794 - text after #endif is not allowed.
2795 - invalid inner-style forward declaration.
2796 - >? and <? operators, and their >?= and <?= cousins.
2798 Additionally, check for constructor/destructor style violations and reference
2799 members, as it is very convenient to do so while checking for
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 nesting_state: A NestingState instance which maintains information about
2807 the current stack of nested blocks being parsed.
2808 error: A callable to which errors are reported, which takes 4 arguments:
2809 filename, line number, error level, and message
2813 line = clean_lines.lines[linenum]
2815 if Search(
r'printf\s*\(.*".*%[-+ ]?\d*q', line):
2816 error(filename, linenum,
'runtime/printf_format', 3,
2817 '%q in format strings is deprecated. Use %ll instead.')
2819 if Search(
r'printf\s*\(.*".*%\d+\$', line):
2820 error(filename, linenum,
'runtime/printf_format', 2,
2821 '%N$ formats are unconventional. Try rewriting to avoid them.')
2824 line = line.replace(
'\\\\',
'')
2826 if Search(
r'("|\').*\\(%|\[|\(|{)', line):
2827 error(filename, linenum,
'build/printf_format', 3,
2828 '%, [, (, and { are undefined character escapes. Unescape them.')
2831 line = clean_lines.elided[linenum]
2833 if Search(
r'\b(const|volatile|void|char|short|int|long'
2834 r'|float|double|signed|unsigned'
2835 r'|schar|u?int8|u?int16|u?int32|u?int64)'
2836 r'\s+(register|static|extern|typedef)\b',
2838 error(filename, linenum,
'build/storage_class', 5,
2839 'Storage-class specifier (static, extern, typedef, etc) should be '
2840 'at the beginning of the declaration.')
2842 if Match(
r'\s*#\s*endif\s*[^/\s]+', line):
2843 error(filename, linenum,
'build/endif_comment', 5,
2844 'Uncommented text after #endif is non-standard. Use a comment.')
2846 if Match(
r'\s*class\s+(\w+\s*::\s*)+\w+\s*;', line):
2847 error(filename, linenum,
'build/forward_decl', 5,
2848 'Inner-style forward declarations are invalid. Remove this line.')
2850 if Search(
r'(\w+|[+-]?\d+(\.\d*)?)\s*(<|>)\?=?\s*(\w+|[+-]?\d+)(\.\d*)?',
2852 error(filename, linenum,
'build/deprecated', 3,
2853 '>? and <? (max and min) operators are non-standard and deprecated.')
2855 if Search(
r'^\s*const\s*string\s*&\s*\w+\s*;', line):
2863 error(filename, linenum,
'runtime/member_string_references', 2,
2864 'const string& members are dangerous. It is much better to use '
2865 'alternatives, such as pointers or simple constants.')
2870 classinfo = nesting_state.InnermostClass()
2871 if not classinfo
or not classinfo.seen_open_brace:
2876 base_classname = classinfo.name.split(
'::')[-1]
2880 explicit_constructor_match =
Match(
2881 r'\s+(?:(?:inline|constexpr)\s+)*(explicit\s+)?'
2882 r'(?:(?:inline|constexpr)\s+)*%s\s*'
2883 r'\(((?:[^()]|\([^()]*\))*)\)'
2884 % re.escape(base_classname),
2887 if explicit_constructor_match:
2888 is_marked_explicit = explicit_constructor_match.group(1)
2890 if not explicit_constructor_match.group(2):
2891 constructor_args = []
2893 constructor_args = explicit_constructor_match.group(2).split(
',')
2898 while i < len(constructor_args):
2899 constructor_arg = constructor_args[i]
2900 while (constructor_arg.count(
'<') > constructor_arg.count(
'>')
or
2901 constructor_arg.count(
'(') > constructor_arg.count(
')')):
2902 constructor_arg +=
',' + constructor_args[i + 1]
2903 del constructor_args[i + 1]
2904 constructor_args[i] = constructor_arg
2907 defaulted_args = [arg
for arg
in constructor_args
if '=' in arg]
2908 noarg_constructor = (
not constructor_args
or
2910 (len(constructor_args) == 1
and
2911 constructor_args[0].strip() ==
'void'))
2912 onearg_constructor = ((len(constructor_args) == 1
and
2913 not noarg_constructor)
or
2915 (len(constructor_args) >= 1
and
2916 not noarg_constructor
and
2917 len(defaulted_args) >= len(constructor_args) - 1))
2918 initializer_list_constructor = bool(
2919 onearg_constructor
and
2920 Search(
r'\bstd\s*::\s*initializer_list\b', constructor_args[0]))
2921 copy_constructor = bool(
2922 onearg_constructor
and
2923 Match(
r'(const\s+)?%s(\s*<[^>]*>)?(\s+const)?\s*(?:<\w+>\s*)?&'
2924 % re.escape(base_classname), constructor_args[0].strip()))
2926 if (
not is_marked_explicit
and
2927 onearg_constructor
and
2928 not initializer_list_constructor
and
2929 not copy_constructor):
2931 error(filename, linenum,
'runtime/explicit', 5,
2932 'Constructors callable with one argument '
2933 'should be marked explicit.')
2935 error(filename, linenum,
'runtime/explicit', 5,
2936 'Single-parameter constructors should be marked explicit.')
2937 elif is_marked_explicit
and not onearg_constructor:
2938 if noarg_constructor:
2939 error(filename, linenum,
'runtime/explicit', 5,
2940 'Zero-parameter constructors should not be marked explicit.')
2944 """Checks for the correctness of various spacing around function calls.
2947 filename: The name of the current file.
2948 clean_lines: A CleansedLines instance containing the file.
2949 linenum: The number of the line to check.
2950 error: The function to call with any errors found.
2952 line = clean_lines.elided[linenum]
2959 for pattern
in (
r'\bif\s*\((.*)\)\s*{',
2960 r'\bfor\s*\((.*)\)\s*{',
2961 r'\bwhile\s*\((.*)\)\s*[{;]',
2962 r'\bswitch\s*\((.*)\)\s*{'):
2963 match =
Search(pattern, line)
2965 fncall = match.group(1)
2982 not Search(
r'\b(if|for|while|switch|return|new|delete|catch|sizeof)\b',
2985 not Search(
r' \([^)]+\)\([^)]*(\)|,$)', fncall)
and
2987 not Search(
r' \([^)]+\)\[[^\]]+\]', fncall)):
2988 if Search(
r'\w\s*\(\s(?!\s*\\$)', fncall):
2989 error(filename, linenum,
'whitespace/parens', 4,
2990 'Extra space after ( in function call')
2991 elif Search(
r'\(\s+(?!(\s*\\)|\()', fncall):
2992 error(filename, linenum,
'whitespace/parens', 2,
2993 'Extra space after (')
2994 if (
Search(
r'\w\s+\(', fncall)
and
2995 not Search(
r'_{0,2}asm_{0,2}\s+_{0,2}volatile_{0,2}\s+\(', fncall)
and
2996 not Search(
r'#\s*define|typedef|using\s+\w+\s*=', fncall)
and
2997 not Search(
r'\w\s+\((\w+::)*\*\w+\)\(', fncall)
and
2998 not Search(
r'\bcase\s+\(', fncall)):
3001 if Search(
r'\boperator_*\b', line):
3002 error(filename, linenum,
'whitespace/parens', 0,
3003 'Extra space before ( in function call')
3005 error(filename, linenum,
'whitespace/parens', 4,
3006 'Extra space before ( in function call')
3009 if Search(
r'[^)]\s+\)\s*[^{\s]', fncall):
3012 if Search(
r'^\s+\)', fncall):
3013 error(filename, linenum,
'whitespace/parens', 2,
3014 'Closing ) should be moved to the previous line')
3016 error(filename, linenum,
'whitespace/parens', 2,
3017 'Extra space before )')
3021 """Returns true if the given line is blank.
3023 We consider a line to be blank if the line is empty or consists of
3027 line: A line of a string.
3030 True, if the given line is blank.
3032 return not line
or line.isspace()
3037 is_namespace_indent_item = (
3038 len(nesting_state.stack) > 1
and
3039 nesting_state.stack[-1].check_namespace_indentation
and
3040 isinstance(nesting_state.previous_stack_top, _NamespaceInfo)
and
3041 nesting_state.previous_stack_top == nesting_state.stack[-2])
3044 clean_lines.elided, line):
3050 function_state, error):
3051 """Reports for long function bodies.
3053 For an overview why this is done, see:
3054 https://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Write_Short_Functions
3056 Uses a simplistic algorithm assuming other style guidelines
3057 (especially spacing) are followed.
3058 Only checks unindented functions, so class members are unchecked.
3059 Trivial bodies are unchecked, so constructors with huge initializer lists
3061 Blank/comment lines are not counted so as to avoid encouraging the removal
3062 of vertical space and comments just to get through a lint check.
3063 NOLINT *on the last line of a function* disables this check.
3066 filename: The name of the current file.
3067 clean_lines: A CleansedLines instance containing the file.
3068 linenum: The number of the line to check.
3069 function_state: Current function name and lines in body so far.
3070 error: The function to call with any errors found.
3072 lines = clean_lines.lines
3073 line = lines[linenum]
3076 starting_func =
False
3077 regexp =
r'(\w(\w|::|\*|\&|\s)*)\('
3078 match_result =
Match(regexp, line)
3082 function_name = match_result.group(1).split()[-1]
3083 if function_name ==
'TEST' or function_name ==
'TEST_F' or (
3084 not Match(
r'[A-Z_]+$', function_name)):
3085 starting_func =
True
3089 for start_linenum
in xrange(linenum, clean_lines.NumLines()):
3090 start_line = lines[start_linenum]
3091 joined_line +=
' ' + start_line.lstrip()
3092 if Search(
r'(;|})', start_line):
3095 elif Search(
r'{', start_line):
3097 function =
Search(
r'((\w|:)*)\(', line).group(1)
3098 if Match(
r'TEST', function):
3099 parameter_regexp =
Search(
r'(\(.*\))', joined_line)
3100 if parameter_regexp:
3101 function += parameter_regexp.group(1)
3104 function_state.Begin(function)
3108 error(filename, linenum,
'readability/fn_size', 5,
3109 'Lint failed to find start of function body.')
3110 elif Match(
r'^\}\s*$', line):
3111 function_state.Check(error, filename, linenum)
3112 function_state.End()
3113 elif not Match(
r'^\s*$', line):
3114 function_state.Count()
3117 _RE_PATTERN_TODO = re.compile(
r'^//(\s*)TODO(\(.+?\))?:?(\s|$)?')
3121 """Checks for common mistakes in comments.
3124 line: The line in question.
3125 filename: The name of the current file.
3126 linenum: The number of the line to check.
3127 next_line_start: The first non-whitespace column of the next line.
3128 error: The function to call with any errors found.
3130 commentpos = line.find(
'//')
3131 if commentpos != -1:
3133 if re.sub(
r'\\.',
'', line[0:commentpos]).count(
'"') % 2 == 0:
3135 if (
not (
Match(
r'^.*{ *//', line)
and next_line_start == commentpos)
and
3136 ((commentpos >= 1
and
3137 line[commentpos-1]
not in string.whitespace)
or
3138 (commentpos >= 2
and
3139 line[commentpos-2]
not in string.whitespace))):
3140 error(filename, linenum,
'whitespace/comments', 2,
3141 'At least two spaces is best between code and comments')
3144 comment = line[commentpos:]
3145 match = _RE_PATTERN_TODO.match(comment)
3148 leading_whitespace = match.group(1)
3149 if len(leading_whitespace) > 1:
3150 error(filename, linenum,
'whitespace/todo', 2,
3151 'Too many spaces before TODO')
3153 username = match.group(2)
3155 error(filename, linenum,
'readability/todo', 2,
3156 'Missing username in TODO; it should look like '
3157 '"// TODO(my_username): Stuff."')
3159 middle_whitespace = match.group(3)
3161 if middle_whitespace !=
' ' and middle_whitespace !=
'':
3162 error(filename, linenum,
'whitespace/todo', 2,
3163 'TODO(my_username) should be followed by a space')
3168 if (
Match(
r'//[^ ]*\w', comment)
and
3169 not Match(
r'(///|//\!)(\s+|$)', comment)):
3170 error(filename, linenum,
'whitespace/comments', 4,
3171 'Should have a space between // and comment')
3175 """Checks for the correctness of various spacing issues in the code.
3177 Things we check for: spaces around operators, spaces after
3178 if/for/while/switch, no spaces around parens in function calls, two
3179 spaces between code and comment, don't start a block with a blank
3180 line, don't end a function with a blank line, don't add a blank line
3181 after public/protected/private, don't have too many blank lines in a row.
3184 filename: The name of the current file.
3185 clean_lines: A CleansedLines instance containing the file.
3186 linenum: The number of the line to check.
3187 nesting_state: A NestingState instance which maintains information about
3188 the current stack of nested blocks being parsed.
3189 error: The function to call with any errors found.
3195 raw = clean_lines.lines_without_raw_strings
3214 not nesting_state.InNamespaceBody()
and
3215 not nesting_state.InExternC()):
3216 elided = clean_lines.elided
3217 prev_line = elided[linenum - 1]
3218 prevbrace = prev_line.rfind(
'{')
3223 if prevbrace != -1
and prev_line[prevbrace:].find(
'}') == -1:
3232 if Match(
r' {6}\w', prev_line):
3235 search_position = linenum-2
3236 while (search_position >= 0
3237 and Match(
r' {6}\w', elided[search_position])):
3238 search_position -= 1
3239 exception = (search_position >= 0
3240 and elided[search_position][:5] ==
' :')
3248 exception = (
Match(
r' {4}\w[^\(]*\)\s*(const\s*)?(\{\s*$|:)',
3250 or Match(
r' {4}:', prev_line))
3253 error(filename, linenum,
'whitespace/blank_line', 2,
3254 'Redundant blank line at the start of a code block '
3255 'should be deleted.')
3264 if linenum + 1 < clean_lines.NumLines():
3265 next_line = raw[linenum + 1]
3267 and Match(
r'\s*}', next_line)
3268 and next_line.find(
'} else ') == -1):
3269 error(filename, linenum,
'whitespace/blank_line', 3,
3270 'Redundant blank line at the end of a code block '
3271 'should be deleted.')
3273 matched =
Match(
r'\s*(public|protected|private):', prev_line)
3275 error(filename, linenum,
'whitespace/blank_line', 3,
3276 'Do not leave a blank line after "%s:"' % matched.group(1))
3280 if linenum + 1 < clean_lines.NumLines():
3281 next_line = raw[linenum + 1]
3282 next_line_start = len(next_line) - len(next_line.lstrip())
3283 CheckComment(line, filename, linenum, next_line_start, error)
3286 line = clean_lines.elided[linenum]
3290 if Search(
r'\w\s+\[', line)
and not Search(
r'(?:auto&?|delete|return)\s+\[', line):
3291 error(filename, linenum,
'whitespace/braces', 5,
3292 'Extra space before [')
3296 if (
Search(
r'for *\(.*[^:]:[^: ]', line)
or
3297 Search(
r'for *\(.*[^: ]:[^:]', line)):
3298 error(filename, linenum,
'whitespace/forcolon', 2,
3299 'Missing space around colon in range-based for loop')
3303 """Checks for horizontal spacing around operators.
3306 filename: The name of the current file.
3307 clean_lines: A CleansedLines instance containing the file.
3308 linenum: The number of the line to check.
3309 error: The function to call with any errors found.
3311 line = clean_lines.elided[linenum]
3320 match =
Match(
r'^(.*\boperator\b)(\S+)(\s*\(.*)$', line)
3322 line = match.group(1) + (
'_' * len(match.group(2))) + match.group(3)
3330 if ((
Search(
r'[\w.]=', line)
or
3332 and not Search(
r'\b(if|while|for) ', line)
3334 and not Search(
r'(>=|<=|==|!=|&=|\^=|\|=|\+=|\*=|\/=|\%=)', line)
3335 and not Search(
r'operator=', line)):
3336 error(filename, linenum,
'whitespace/operators', 4,
3337 'Missing spaces around =')
3354 match =
Search(
r'[^<>=!\s](==|!=|<=|>=|\|\|)[^<>=!\s,;\)]', line)
3356 error(filename, linenum,
'whitespace/operators', 3,
3357 'Missing spaces around %s' % match.group(1))
3358 elif not Match(
r'#.*include', line):
3363 match =
Match(
r'^(.*[^\s<])<[^\s=<,]', line)
3366 clean_lines, linenum, len(match.group(1)))
3368 error(filename, linenum,
'whitespace/operators', 3,
3369 'Missing spaces around <')
3374 match =
Match(
r'^(.*[^-\s>])>[^\s=>,]', line)
3377 clean_lines, linenum, len(match.group(1)))
3379 error(filename, linenum,
'whitespace/operators', 3,
3380 'Missing spaces around >')
3387 match =
Search(
r'(operator|[^\s(<])(?:L|UL|LL|ULL|l|ul|ll|ull)?<<([^\s,=<])', line)
3388 if (match
and not (match.group(1).isdigit()
and match.group(2).isdigit())
and
3389 not (match.group(1) ==
'operator' and match.group(2) ==
';')):
3390 error(filename, linenum,
'whitespace/operators', 3,
3391 'Missing spaces around <<')
3405 match =
Search(
r'>>[a-zA-Z_]', line)
3407 error(filename, linenum,
'whitespace/operators', 3,
3408 'Missing spaces around >>')
3411 match =
Search(
r'(!\s|~\s|[\s]--[\s;]|[\s]\+\+[\s;])', line)
3413 error(filename, linenum,
'whitespace/operators', 4,
3414 'Extra space for operator %s' % match.group(1))
3418 """Checks for horizontal spacing around parentheses.
3421 filename: The name of the current file.
3422 clean_lines: A CleansedLines instance containing the file.
3423 linenum: The number of the line to check.
3424 error: The function to call with any errors found.
3426 line = clean_lines.elided[linenum]
3429 match =
Search(
r' (if\(|for\(|while\(|switch\()', line)
3431 error(filename, linenum,
'whitespace/parens', 5,
3432 'Missing space before ( in %s' % match.group(1))
3439 match =
Search(
r'\b(if|for|while|switch)\s*'
3440 r'\(([ ]*)(.).*[^ ]+([ ]*)\)\s*{\s*$',
3443 if len(match.group(2)) != len(match.group(4)):
3444 if not (match.group(3) ==
';' and
3445 len(match.group(2)) == 1 + len(match.group(4))
or
3446 not match.group(2)
and Search(
r'\bfor\s*\(.*; \)', line)):
3447 error(filename, linenum,
'whitespace/parens', 5,
3448 'Mismatching spaces inside () in %s' % match.group(1))
3449 if len(match.group(2))
not in [0, 1]:
3450 error(filename, linenum,
'whitespace/parens', 5,
3451 'Should have zero or one spaces inside ( and ) in %s' %
3456 """Checks for horizontal spacing near commas and semicolons.
3459 filename: The name of the current file.
3460 clean_lines: A CleansedLines instance containing the file.
3461 linenum: The number of the line to check.
3462 error: The function to call with any errors found.
3464 raw = clean_lines.lines_without_raw_strings
3465 line = clean_lines.elided[linenum]
3478 Search(
r',[^,\s]', raw[linenum])):
3479 error(filename, linenum,
'whitespace/comma', 3,
3480 'Missing space after ,')
3486 if Search(
r';[^\s};\\)/]', line):
3487 error(filename, linenum,
'whitespace/semicolon', 3,
3488 'Missing space after ;')
3492 """Check if expression looks like a type name, returns true if so.
3495 clean_lines: A CleansedLines instance containing the file.
3496 nesting_state: A NestingState instance which maintains information about
3497 the current stack of nested blocks being parsed.
3498 expr: The expression to check.
3500 True, if token looks like a type.
3503 last_word =
Match(
r'^.*(\b\S+)$', expr)
3505 token = last_word.group(1)
3510 if _TYPES.match(token):
3516 typename_pattern = (
r'\b(?:typename|class|struct)\s+' + re.escape(token) +
3518 block_index = len(nesting_state.stack) - 1
3519 while block_index >= 0:
3520 if isinstance(nesting_state.stack[block_index], _NamespaceInfo):
3529 last_line = nesting_state.stack[block_index].starting_linenum
3531 next_block_start = 0
3533 next_block_start = nesting_state.stack[block_index - 1].starting_linenum
3534 first_line = last_line
3535 while first_line >= next_block_start:
3536 if clean_lines.elided[first_line].find(
'template') >= 0:
3539 if first_line < next_block_start:
3546 for i
in xrange(first_line, last_line + 1, 1):
3547 if Search(typename_pattern, clean_lines.elided[i]):
3555 """Checks for horizontal spacing near commas.
3558 filename: The name of the current file.
3559 clean_lines: A CleansedLines instance containing the file.
3560 linenum: The number of the line to check.
3561 nesting_state: A NestingState instance which maintains information about
3562 the current stack of nested blocks being parsed.
3563 error: The function to call with any errors found.
3565 line = clean_lines.elided[linenum]
3573 match =
Match(
r'^(.*[^ ({>]){', line)
3604 leading_text = match.group(1)
3606 clean_lines, linenum, len(match.group(1)))
3609 trailing_text = endline[endpos:]
3610 for offset
in xrange(endlinenum + 1,
3611 min(endlinenum + 3, clean_lines.NumLines() - 1)):
3612 trailing_text += clean_lines.elided[offset]
3616 if (
not Match(
r'^[\s}]*[{.;,)<>\]:]', trailing_text)
3617 and not _IsType(clean_lines, nesting_state, leading_text)):
3618 error(filename, linenum,
'whitespace/braces', 5,
3619 'Missing space before {')
3622 if Search(
r'}else', line):
3623 error(filename, linenum,
'whitespace/braces', 5,
3624 'Missing space before else')
3629 if Search(
r':\s*;\s*$', line):
3630 error(filename, linenum,
'whitespace/semicolon', 5,
3631 'Semicolon defining empty statement. Use {} instead.')
3632 elif Search(
r'^\s*;\s*$', line):
3633 error(filename, linenum,
'whitespace/semicolon', 5,
3634 'Line contains only semicolon. If this should be an empty statement, '
3636 elif (
Search(
r'\s+;\s*$', line)
and
3637 not Search(
r'\bfor\b', line)):
3638 error(filename, linenum,
'whitespace/semicolon', 5,
3639 'Extra space before last semicolon. If this should be an empty '
3640 'statement, use {} instead.')
3644 """Check if the token ending on (linenum, column) is decltype().
3647 clean_lines: A CleansedLines instance containing the file.
3648 linenum: the number of the line to check.
3649 column: end column of the token to check.
3651 True if this token is decltype() expression, False otherwise.
3656 if Search(
r'\bdecltype\s*$', text[0:start_col]):
3662 """Checks for additional blank line issues related to sections.
3664 Currently the only thing checked here is blank line before protected/private.
3667 filename: The name of the current file.
3668 clean_lines: A CleansedLines instance containing the file.
3669 class_info: A _ClassInfo objects.
3670 linenum: The number of the line to check.
3671 error: The function to call with any errors found.
3684 if (class_info.last_line - class_info.starting_linenum <= 24
or
3685 linenum <= class_info.starting_linenum):
3688 matched =
Match(
r'\s*(public|protected|private):', clean_lines.lines[linenum])
3698 prev_line = clean_lines.lines[linenum - 1]
3700 not Search(
r'\b(class|struct)\b', prev_line)
and
3701 not Search(
r'\\$', prev_line)):
3706 end_class_head = class_info.starting_linenum
3707 for i
in range(class_info.starting_linenum, linenum):
3708 if Search(
r'\{\s*$', clean_lines.lines[i]):
3711 if end_class_head < linenum - 1:
3712 error(filename, linenum,
'whitespace/blank_line', 3,
3713 '"%s:" should be preceded by a blank line' % matched.group(1))
3717 """Return the most recent non-blank line and its line number.
3720 clean_lines: A CleansedLines instance containing the file contents.
3721 linenum: The number of the line to check.
3724 A tuple with two elements. The first element is the contents of the last
3725 non-blank line before the current line, or the empty string if this is the
3726 first non-blank line. The second is the line number of that line, or -1
3727 if this is the first non-blank line.
3730 prevlinenum = linenum - 1
3731 while prevlinenum >= 0:
3732 prevline = clean_lines.elided[prevlinenum]
3734 return (prevline, prevlinenum)
3740 """Looks for misplaced braces (e.g. at the end of line).
3743 filename: The name of the current file.
3744 clean_lines: A CleansedLines instance containing the file.
3745 linenum: The number of the line to check.
3746 error: The function to call with any errors found.
3749 line = clean_lines.elided[linenum]
3751 if Match(
r'\s*{\s*$', line):
3762 if (
not Search(
r'[,;:}{(]\s*$', prevline)
and
3763 not Match(
r'\s*#', prevline)
and
3764 not (
GetLineWidth(prevline) > _line_length - 2
and '[]' in prevline)):
3765 error(filename, linenum,
'whitespace/braces', 4,
3766 '{ should almost always be at the end of the previous line')
3769 if Match(
r'\s*else\b\s*(?:if\b|\{|$)', line):
3771 if Match(
r'\s*}\s*$', prevline):
3772 error(filename, linenum,
'whitespace/newline', 4,
3773 'An else should appear on the same line as the preceding }')
3777 if Search(
r'else if\s*\(', line):
3778 brace_on_left = bool(
Search(
r'}\s*else if\s*\(', line))
3780 pos = line.find(
'else if')
3781 pos = line.find(
'(', pos)
3784 brace_on_right = endline[endpos:].find(
'{') != -1
3785 if brace_on_left != brace_on_right:
3786 error(filename, linenum,
'readability/braces', 5,
3787 'If an else has a brace on one side, it should have it on both')
3788 elif Search(
r'}\s*else[^{]*$', line)
or Match(
r'[^}]*else\s*{', line):
3789 error(filename, linenum,
'readability/braces', 5,
3790 'If an else has a brace on one side, it should have it on both')
3793 if Search(
r'\belse [^\s{]', line)
and not Search(
r'\belse if\b', line):
3794 error(filename, linenum,
'whitespace/newline', 4,
3795 'Else clause should never be on same line as else (use 2 lines)')
3798 if Match(
r'\s*do [^\s{]', line):
3799 error(filename, linenum,
'whitespace/newline', 4,
3800 'do/while clauses should not be on a single line')
3809 if_else_match =
Search(
r'\b(if\s*\(|else\b)', line)
3810 if if_else_match
and not Match(
r'\s*#', line):
3812 endline, endlinenum, endpos = line, linenum, if_else_match.end()
3813 if_match =
Search(
r'\bif\s*\(', line)
3816 pos = if_match.end() - 1
3817 (endline, endlinenum, endpos) =
CloseExpression(clean_lines, linenum, pos)
3820 if (
not Match(
r'\s*{', endline[endpos:])
3821 and not (
Match(
r'\s*$', endline[endpos:])
3822 and endlinenum < (len(clean_lines.elided) - 1)
3823 and Match(
r'\s*{', clean_lines.elided[endlinenum + 1]))):
3824 while (endlinenum < len(clean_lines.elided)
3825 and ';' not in clean_lines.elided[endlinenum][endpos:]):
3828 if endlinenum < len(clean_lines.elided):
3829 endline = clean_lines.elided[endlinenum]
3832 endpos = endline.find(
';')
3833 if not Match(
r';[\s}]*(\\?)$', endline[endpos:]):
3837 if not Match(
r'^[^{};]*\[[^\[\]]*\][^{}]*\{[^{}]*\}\s*\)*[;,]\s*$',
3839 error(filename, linenum,
'readability/braces', 4,
3840 'If/else bodies with multiple statements require braces')
3841 elif endlinenum < len(clean_lines.elided) - 1:
3843 next_line = clean_lines.elided[endlinenum + 1]
3848 if (if_match
and Match(
r'\s*else\b', next_line)
3849 and next_indent != if_indent):
3850 error(filename, linenum,
'readability/braces', 4,
3851 'Else clause should be indented at the same level as if. '
3852 'Ambiguous nested if/else chains require braces.')
3853 elif next_indent > if_indent:
3854 error(filename, linenum,
'readability/braces', 4,
3855 'If/else bodies with multiple statements require braces')
3859 """Looks for redundant trailing semicolon.
3862 filename: The name of the current file.
3863 clean_lines: A CleansedLines instance containing the file.
3864 linenum: The number of the line to check.
3865 error: The function to call with any errors found.
3868 line = clean_lines.elided[linenum]
3914 match =
Match(
r'^(.*\)\s*)\{', line)
3942 closing_brace_pos = match.group(1).rfind(
')')
3944 clean_lines, linenum, closing_brace_pos)
3945 if opening_parenthesis[2] > -1:
3946 line_prefix = opening_parenthesis[0][0:opening_parenthesis[2]]
3947 macro =
Search(
r'\b([A-Z_][A-Z0-9_]*)\s*$', line_prefix)
3948 func =
Match(
r'^(.*\])\s*$', line_prefix)
3950 macro.group(1)
not in (
3951 'TEST',
'TEST_F',
'MATCHER',
'MATCHER_P',
'TYPED_TEST',
3952 'EXCLUSIVE_LOCKS_REQUIRED',
'SHARED_LOCKS_REQUIRED',
3953 'LOCKS_EXCLUDED',
'INTERFACE_DEF'))
or
3954 (func
and not Search(
r'\boperator\s*\[\s*\]', func.group(1)))
or
3955 Search(
r'\b(?:struct|union)\s+alignas\s*$', line_prefix)
or
3956 Search(
r'\bdecltype$', line_prefix)
or
3957 Search(
r'\s+=\s*$', line_prefix)):
3960 opening_parenthesis[1] > 1
and
3961 Search(
r'\]\s*$', clean_lines.elided[opening_parenthesis[1] - 1])):
3967 match =
Match(
r'^(.*(?:else|\)\s*const)\s*)\{', line)
3978 if prevline
and Search(
r'[;{}]\s*$', prevline):
3979 match =
Match(
r'^(\s*)\{', line)
3984 clean_lines, linenum, len(match.group(1)))
3985 if endpos > -1
and Match(
r'^\s*;', endline[endpos:]):
3995 raw_lines = clean_lines.raw_lines
4001 error(filename, endlinenum,
'readability/braces', 4,
4002 "You don't need a ; after a }")
4006 """Look for empty loop/conditional body with only a single semicolon.
4009 filename: The name of the current file.
4010 clean_lines: A CleansedLines instance containing the file.
4011 linenum: The number of the line to check.
4012 error: The function to call with any errors found.
4021 line = clean_lines.elided[linenum]
4022 matched =
Match(
r'\s*(for|while|if)\s*\(', line)
4026 clean_lines, linenum, line.find(
'('))
4031 if end_pos >= 0
and Match(
r';', end_line[end_pos:]):
4032 if matched.group(1) ==
'if':
4033 error(filename, end_linenum,
'whitespace/empty_conditional_body', 5,
4034 'Empty conditional bodies should use {}')
4036 error(filename, end_linenum,
'whitespace/empty_loop_body', 5,
4037 'Empty loop bodies should use {} or continue')
4041 if end_pos >= 0
and matched.group(1) ==
'if':
4044 opening_linenum = end_linenum
4045 opening_line_fragment = end_line[end_pos:]
4047 while not Search(
r'^\s*\{', opening_line_fragment):
4048 if Search(
r'^(?!\s*$)', opening_line_fragment):
4051 opening_linenum += 1
4052 if opening_linenum == len(clean_lines.elided):
4055 opening_line_fragment = clean_lines.elided[opening_linenum]
4057 opening_line = clean_lines.elided[opening_linenum]
4060 opening_pos = opening_line_fragment.find(
'{')
4061 if opening_linenum == end_linenum:
4063 opening_pos += end_pos
4065 clean_lines, opening_linenum, opening_pos)
4072 if (clean_lines.raw_lines[opening_linenum] !=
4076 if closing_linenum > opening_linenum:
4078 body = list(opening_line[opening_pos+1:])
4080 body.extend(clean_lines.raw_lines[opening_linenum+1:closing_linenum])
4082 body.append(clean_lines.elided[closing_linenum][:closing_pos-1])
4083 body =
'\n'.join(body)
4086 body = opening_line[opening_pos+1:closing_pos-1]
4089 if not _EMPTY_CONDITIONAL_BODY_PATTERN.search(body):
4092 current_linenum = closing_linenum
4093 current_line_fragment = closing_line[closing_pos:]
4095 while Search(
r'^\s*$|^(?=\s*else)', current_line_fragment):
4096 if Search(
r'^(?=\s*else)', current_line_fragment):
4099 current_linenum += 1
4100 if current_linenum == len(clean_lines.elided):
4102 current_line_fragment = clean_lines.elided[current_linenum]
4105 error(filename, end_linenum,
'whitespace/empty_if_body', 4,
4106 (
'If statement had no body and no else clause'))
4110 """Find a replaceable CHECK-like macro.
4113 line: line to search on.
4115 (macro name, start position), or (None, -1) if no replaceable
4118 for macro
in _CHECK_MACROS:
4119 i = line.find(macro)
4125 matched =
Match(
r'^(.*\b' + macro +
r'\s*)\(', line)
4128 return (macro, len(matched.group(1)))
4133 """Checks the use of CHECK and EXPECT macros.
4136 filename: The name of the current file.
4137 clean_lines: A CleansedLines instance containing the file.
4138 linenum: The number of the line to check.
4139 error: The function to call with any errors found.
4143 lines = clean_lines.elided
4150 clean_lines, linenum, start_pos)
4157 if not Match(
r'\s*;', last_line[end_pos:]):
4160 if linenum == end_line:
4161 expression = lines[linenum][start_pos + 1:end_pos - 1]
4163 expression = lines[linenum][start_pos + 1:]
4164 for i
in xrange(linenum + 1, end_line):
4165 expression += lines[i]
4166 expression += last_line[0:end_pos - 1]
4175 matched =
Match(
r'^\s*(<<|<<=|>>|>>=|->\*|->|&&|\|\||'
4176 r'==|!=|>=|>|<=|<|\()(.*)$', expression)
4178 token = matched.group(1)
4181 expression = matched.group(2)
4185 lhs +=
'(' + expression[0:end]
4186 expression = expression[end:]
4187 elif token
in (
'&&',
'||'):
4194 elif token
in (
'<<',
'<<=',
'>>',
'>>=',
'->*',
'->'):
4197 expression = matched.group(2)
4201 rhs = matched.group(2)
4209 matched =
Match(
r'^([^-=!<>()&|]+)(.*)$', expression)
4211 matched =
Match(
r'^(\s*\S)(.*)$', expression)
4214 lhs += matched.group(1)
4215 expression = matched.group(2)
4218 if not (lhs
and operator
and rhs):
4223 if rhs.find(
'&&') > -1
or rhs.find(
'||') > -1:
4234 match_constant =
r'^([-+]?(\d+|0[xX][0-9a-fA-F]+)[lLuU]{0,3}|".*"|\'.*\')$'
4235 if Match(match_constant, lhs)
or Match(match_constant, rhs):
4244 error(filename, linenum,
'readability/check', 2,
4245 'Consider using %s instead of %s(a %s b)' % (
4246 _CHECK_REPLACEMENT[check_macro][operator],
4247 check_macro, operator))
4251 """Check alternative keywords being used in boolean expressions.
4254 filename: The name of the current file.
4255 clean_lines: A CleansedLines instance containing the file.
4256 linenum: The number of the line to check.
4257 error: The function to call with any errors found.
4259 line = clean_lines.elided[linenum]
4262 if Match(
r'^\s*#', line):
4273 if line.find(
'/*') >= 0
or line.find(
'*/') >= 0:
4276 for match
in _ALT_TOKEN_REPLACEMENT_PATTERN.finditer(line):
4277 error(filename, linenum,
'readability/alt_tokens', 2,
4278 'Use operator %s instead of %s' % (
4279 _ALT_TOKEN_REPLACEMENT[match.group(1)], match.group(1)))
4283 """Determines the width of the line in column positions.
4286 line: A string, which may be a Unicode string.
4289 The width of the line in column positions, accounting for Unicode
4290 combining characters and wide characters.
4292 if isinstance(line, unicode):
4294 for uc
in unicodedata.normalize(
'NFC', line):
4295 if unicodedata.east_asian_width(uc)
in (
'W',
'F'):
4297 elif not unicodedata.combining(uc):
4300 if (sys.version_info.major, sys.version_info.minor) <= (3, 2):
4302 is_wide_build = sysconfig.get_config_var(
"Py_UNICODE_SIZE") >= 4
4304 is_low_surrogate = 0xDC00 <= ord(uc) <= 0xDFFF
4305 if not is_wide_build
and is_low_surrogate:
4314 def CheckStyle(filename, clean_lines, linenum, file_extension, nesting_state,
4316 """Checks rules from the 'C++ style rules' section of cppguide.html.
4318 Most of these rules are hard to test (naming, comment style), but we
4319 do what we can. In particular we check for 2-space indents, line lengths,
4320 tab usage, spaces inside code, etc.
4323 filename: The name of the current file.
4324 clean_lines: A CleansedLines instance containing the file.
4325 linenum: The number of the line to check.
4326 file_extension: The extension (without the dot) of the filename.
4327 nesting_state: A NestingState instance which maintains information about
4328 the current stack of nested blocks being parsed.
4329 error: The function to call with any errors found.
4335 raw_lines = clean_lines.lines_without_raw_strings
4336 line = raw_lines[linenum]
4337 prev = raw_lines[linenum - 1]
if linenum > 0
else ''
4339 if line.find(
'\t') != -1:
4340 error(filename, linenum,
'whitespace/tab', 1,
4341 'Tab found; better to use spaces')
4355 scope_or_label_pattern =
r'\s*\w+\s*:\s*\\?$'
4356 classinfo = nesting_state.InnermostClass()
4358 cleansed_line = clean_lines.elided[linenum]
4359 while initial_spaces < len(line)
and line[initial_spaces] ==
' ':
4366 if (
not Search(
r'[",=><] *$', prev)
and
4367 (initial_spaces == 1
or initial_spaces == 3)
and
4368 not Match(scope_or_label_pattern, cleansed_line)
and
4369 not (clean_lines.raw_lines[linenum] != line
and
4370 Match(
r'^\s*""', line))):
4371 error(filename, linenum,
'whitespace/indent', 3,
4372 'Weird number of spaces at line-start. '
4373 'Are you using a 2-space indent?')
4375 if line
and line[-1].isspace():
4376 error(filename, linenum,
'whitespace/end_of_line', 4,
4377 'Line ends in whitespace. Consider deleting these extra spaces.')
4380 is_header_guard =
False
4383 if (line.startswith(
'#ifndef %s' % cppvar)
or
4384 line.startswith(
'#define %s' % cppvar)
or
4385 line.startswith(
'#endif // %s' % cppvar)):
4386 is_header_guard =
True
4395 if (
not line.startswith(
'#include')
and not is_header_guard
and
4396 not Match(
r'^\s*//.*http(s?)://\S*$', line)
and
4397 not Match(
r'^\s*//\s*[^\s]*$', line)
and
4398 not Match(
r'^// \$Id:.*#[0-9]+ \$$', line)):
4400 if line_width > _line_length:
4401 error(filename, linenum,
'whitespace/line_length', 2,
4402 'Lines should be <= %i characters long' % _line_length)
4404 if (cleansed_line.count(
';') > 1
and
4406 cleansed_line.find(
'for') == -1
and
4410 not ((cleansed_line.find(
'case ') != -1
or
4411 cleansed_line.find(
'default:') != -1)
and
4412 cleansed_line.find(
'break;') != -1)):
4413 error(filename, linenum,
'whitespace/newline', 0,
4414 'More than one command on the same line')
4417 CheckBraces(filename, clean_lines, linenum, error)
4420 CheckSpacing(filename, clean_lines, linenum, nesting_state, error)
4426 CheckCheck(filename, clean_lines, linenum, error)
4428 classinfo = nesting_state.InnermostClass()
4433 _RE_PATTERN_INCLUDE = re.compile(
r'^\s*#\s*include\s*([<"])([^>"]*)[>"].*$')
4439 _RE_FIRST_COMPONENT = re.compile(
r'^[^-_.]+')
4443 """Drops common suffixes like _test.cc or -inl.h from filename.
4446 >>> _DropCommonSuffixes('foo/foo-inl.h')
4448 >>> _DropCommonSuffixes('foo/bar/foo.cc')
4450 >>> _DropCommonSuffixes('foo/foo_internal.h')
4452 >>> _DropCommonSuffixes('foo/foo_unusualinternal.h')
4453 'foo/foo_unusualinternal'
4456 filename: The input filename.
4459 The filename with the common suffix removed.
4461 for suffix
in (
'test.cc',
'regtest.cc',
'unittest.cc',
4462 'inl.h',
'impl.h',
'internal.h'):
4463 if (filename.endswith(suffix)
and len(filename) > len(suffix)
and
4464 filename[-len(suffix) - 1]
in (
'-',
'_')):
4465 return filename[:-len(suffix) - 1]
4466 return os.path.splitext(filename)[0]
4470 """Figures out what kind of header 'include' is.
4473 fileinfo: The current file cpplint is running over. A FileInfo instance.
4474 include: The path to a #included file.
4475 is_system: True if the #include used <> rather than "".
4478 One of the _XXX_HEADER constants.
4481 >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'stdio.h', True)
4483 >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'string', True)
4485 >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'foo/foo.h', False)
4487 >>> _ClassifyInclude(FileInfo('foo/foo_unknown_extension.cc'),
4488 ... 'bar/foo_other_ext.h', False)
4490 >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'foo/bar.h', False)
4495 is_cpp_h = include
in _CPP_HEADERS
4499 return _CPP_SYS_HEADER
4501 return _C_SYS_HEADER
4506 target_dir, target_base = (
4509 if target_base == include_base
and (
4510 include_dir == target_dir
or
4511 include_dir == os.path.normpath(target_dir +
'/../public')):
4512 return _LIKELY_MY_HEADER
4518 target_first_component = _RE_FIRST_COMPONENT.match(target_base)
4519 include_first_component = _RE_FIRST_COMPONENT.match(include_base)
4520 if (target_first_component
and include_first_component
and
4521 target_first_component.group(0) ==
4522 include_first_component.group(0)):
4523 return _POSSIBLE_MY_HEADER
4525 return _OTHER_HEADER
4530 """Check rules that are applicable to #include lines.
4532 Strings on #include lines are NOT removed from elided line, to make
4533 certain tasks easier. However, to prevent false positives, checks
4534 applicable to #include lines in CheckLanguage must be put here.
4537 filename: The name of the current file.
4538 clean_lines: A CleansedLines instance containing the file.
4539 linenum: The number of the line to check.
4540 include_state: An _IncludeState instance in which the headers are inserted.
4541 error: The function to call with any errors found.
4544 line = clean_lines.lines[linenum]
4553 match =
Match(
r'#include\s*"([^/]+\.h)"', line)
4554 if match
and not _THIRD_PARTY_HEADERS_PATTERN.match(match.group(1)):
4555 error(filename, linenum,
'build/include', 4,
4556 'Include the directory when naming .h files')
4561 match = _RE_PATTERN_INCLUDE.search(line)
4563 include = match.group(2)
4564 is_system = (match.group(1) ==
'<')
4565 duplicate_line = include_state.FindHeader(include)
4566 if duplicate_line >= 0:
4567 error(filename, linenum,
'build/include', 4,
4568 '"%s" already included at %s:%s' %
4569 (include, filename, duplicate_line))
4570 elif (include.endswith(
'.cc')
and
4571 os.path.dirname(fileinfo.RepositoryName()) != os.path.dirname(include)):
4572 error(filename, linenum,
'build/include', 4,
4573 'Do not include .cc files from other packages')
4574 elif not _THIRD_PARTY_HEADERS_PATTERN.match(include):
4575 include_state.include_list[-1].append((include, linenum))
4588 error_message = include_state.CheckNextIncludeOrder(
4591 error(filename, linenum,
'build/include_order', 4,
4592 '%s. Should be: %s.h, c system, c++ system, other.' %
4593 (error_message, fileinfo.BaseName()))
4594 canonical_include = include_state.CanonicalizeAlphabeticalOrder(include)
4595 if not include_state.IsInAlphabeticalOrder(
4596 clean_lines, linenum, canonical_include):
4597 error(filename, linenum,
'build/include_alpha', 4,
4598 'Include "%s" not in alphabetical order' % include)
4599 include_state.SetLastHeader(canonical_include)
4604 r"""Retrieves all the text between matching open and close parentheses.
4606 Given a string of lines and a regular expression string, retrieve all the text
4607 following the expression and between opening punctuation symbols like
4608 (, [, or {, and the matching close-punctuation symbol. This properly nested
4609 occurrences of the punctuations, so for the text like
4610 printf(a(), b(c()));
4611 a call to _GetTextInside(text, r'printf\(') will return 'a(), b(c())'.
4612 start_pattern must match string having an open punctuation symbol at the end.
4615 text: The lines to extract text. Its comments and strings must be elided.
4616 It can be single line and can span multiple lines.
4617 start_pattern: The regexp string indicating where to start extracting
4621 None if either the opening string or ending punctuation could not be found.
4627 matching_punctuation = {
'(':
')',
'{':
'}',
'[':
']'}
4628 closing_punctuation = set(matching_punctuation.values())
4631 match = re.search(start_pattern, text, re.M)
4634 start_position = match.end(0)
4636 assert start_position > 0, (
4637 'start_pattern must ends with an opening punctuation.')
4638 assert text[start_position - 1]
in matching_punctuation, (
4639 'start_pattern must ends with an opening punctuation.')
4641 punctuation_stack = [matching_punctuation[text[start_position - 1]]]
4642 position = start_position
4643 while punctuation_stack
and position < len(text):
4644 if text[position] == punctuation_stack[-1]:
4645 punctuation_stack.pop()
4646 elif text[position]
in closing_punctuation:
4649 elif text[position]
in matching_punctuation:
4650 punctuation_stack.append(matching_punctuation[text[position]])
4652 if punctuation_stack:
4656 return text[start_position:position - 1]
4668 _RE_PATTERN_IDENT =
r'[_a-zA-Z]\w*'
4669 _RE_PATTERN_TYPE = (
4670 r'(?:const\s+)?(?:typename\s+|class\s+|struct\s+|union\s+|enum\s+)?'
4672 r'\s*<(?:<(?:<[^<>]*>|[^<>])*>|[^<>])*>|'
4675 _RE_PATTERN_REF_PARAM = re.compile(
4676 r'(' + _RE_PATTERN_TYPE +
r'(?:\s*(?:\bconst\b|[*]))*\s*'
4677 r'&\s*' + _RE_PATTERN_IDENT +
r')\s*(?:=[^,()]+)?[,)]')
4680 _RE_PATTERN_CONST_REF_PARAM = (
4681 r'(?:.*\s*\bconst\s*&\s*' + _RE_PATTERN_IDENT +
4682 r'|const\s+' + _RE_PATTERN_TYPE +
r'\s*&\s*' + _RE_PATTERN_IDENT +
r')')
4684 _RE_PATTERN_REF_STREAM_PARAM = (
4685 r'(?:.*stream\s*&\s*' + _RE_PATTERN_IDENT +
r')')
4689 include_state, nesting_state, error):
4690 """Checks rules from the 'C++ language rules' section of cppguide.html.
4692 Some of these rules are hard to test (function overloading, using
4693 uint32 inappropriately), but we do the best we can.
4696 filename: The name of the current file.
4697 clean_lines: A CleansedLines instance containing the file.
4698 linenum: The number of the line to check.
4699 file_extension: The extension (without the dot) of the filename.
4700 include_state: An _IncludeState instance in which the headers are inserted.
4701 nesting_state: A NestingState instance which maintains information about
4702 the current stack of nested blocks being parsed.
4703 error: The function to call with any errors found.
4707 line = clean_lines.elided[linenum]
4711 match = _RE_PATTERN_INCLUDE.search(line)
4718 match =
Match(
r'^\s*#\s*(if|ifdef|ifndef|elif|else|endif)\b', line)
4720 include_state.ResetSection(match.group(1))
4723 fullname = os.path.abspath(filename).replace(
'\\',
'/')
4726 CheckCasts(filename, clean_lines, linenum, error)
4728 CheckPrintf(filename, clean_lines, linenum, error)
4740 if Search(
r'\bshort port\b', line):
4741 if not Search(
r'\bunsigned short port\b', line):
4742 error(filename, linenum,
'runtime/int', 4,
4743 'Use "unsigned short" for ports, not "short"')
4745 match =
Search(
r'\b(short|long(?! +double)|long long)\b', line)
4747 error(filename, linenum,
'runtime/int', 4,
4748 'Use int16/int64/etc, rather than the C type %s' % match.group(1))
4756 if Search(
r'\boperator\s*&\s*\(\s*\)', line):
4757 error(filename, linenum,
'runtime/operator', 4,
4758 'Unary operator& is dangerous. Do not use it.')
4762 if Search(
r'\}\s*if\s*\(', line):
4763 error(filename, linenum,
'readability/braces', 4,
4764 'Did you mean "else if"? If not, start a new line for "if".')
4773 printf_args =
_GetTextInside(line,
r'(?i)\b(string)?printf\s*\(')
4775 match =
Match(
r'([\w.\->()]+)$', printf_args)
4776 if match
and match.group(1) !=
'__VA_ARGS__':
4777 function_name = re.search(
r'\b((?:string)?printf)\s*\(',
4778 line, re.I).group(1)
4779 error(filename, linenum,
'runtime/printf', 4,
4780 'Potential format string bug. Do %s("%%s", %s) instead.'
4781 % (function_name, match.group(1)))
4784 match =
Search(
r'memset\s*\(([^,]*),\s*([^,]*),\s*0\s*\)', line)
4785 if match
and not Match(
r"^''|-?[0-9]+|0x[0-9A-Fa-f]$", match.group(2)):
4786 error(filename, linenum,
'runtime/memset', 4,
4787 'Did you mean "memset(%s, 0, %s)"?'
4788 % (match.group(1), match.group(2)))
4790 if Search(
r'\busing namespace\b', line):
4791 error(filename, linenum,
'build/namespaces', 5,
4792 'Do not use namespace using-directives. '
4793 'Use using-declarations instead.')
4796 match =
Match(
r'\s*(.+::)?(\w+) [a-z]\w*\[(.+)];', line)
4797 if (match
and match.group(2) !=
'return' and match.group(2) !=
'delete' and
4798 match.group(3).find(
']') == -1):
4802 tokens = re.split(
r'\s|\+|\-|\*|\/|<<|>>]', match.group(3))
4810 if Search(
r'sizeof\(.+\)', tok):
continue
4811 if Search(
r'arraysize\(\w+\)', tok):
continue
4813 tok = tok.lstrip(
'(')
4814 tok = tok.rstrip(
')')
4815 if not tok:
continue
4816 if Match(
r'\d+', tok):
continue
4817 if Match(
r'0[xX][0-9a-fA-F]+', tok):
continue
4818 if Match(
r'k[A-Z0-9]\w*', tok):
continue
4819 if Match(
r'(.+::)?k[A-Z0-9]\w*', tok):
continue
4820 if Match(
r'(.+::)?[A-Z][A-Z0-9_]*', tok):
continue
4824 if tok.startswith(
'sizeof'):
4830 error(filename, linenum,
'runtime/arrays', 1,
4831 'Do not use variable-length arrays. Use an appropriately named '
4832 "('k' followed by CamelCase) compile-time constant for the size.")
4838 and Search(
r'\bnamespace\s*{', line)
4839 and line[-1] !=
'\\'):
4840 error(filename, linenum,
'build/namespaces', 4,
4841 'Do not use unnamed namespaces in header files. See '
4842 'https://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Namespaces'
4843 ' for more information.')
4847 """Check for unsafe global or static objects.
4850 filename: The name of the current file.
4851 clean_lines: A CleansedLines instance containing the file.
4852 linenum: The number of the line to check.
4853 error: The function to call with any errors found.
4855 line = clean_lines.elided[linenum]
4858 if linenum + 1 < clean_lines.NumLines()
and not Search(
r'[;({]', line):
4859 line += clean_lines.elided[linenum + 1].strip()
4868 r'((?:|static +)(?:|const +))(?::*std::)?string( +const)? +'
4869 r'([a-zA-Z0-9_:]+)\b(.*)',
4889 not Search(
r'\bstring\b(\s+const)?\s*[\*\&]\s*(const\s+)?\w', line)
and
4890 not Search(
r'\boperator\W', line)
and
4891 not Match(
r'\s*(<.*>)?(::[a-zA-Z0-9_]+)*\s*\(([^"]|$)', match.group(4))):
4892 if Search(
r'\bconst\b', line):
4893 error(filename, linenum,
'runtime/string', 4,
4894 'For a static/global string constant, use a C style string '
4895 'instead: "%schar%s %s[]".' %
4896 (match.group(1), match.group(2)
or '', match.group(3)))
4898 error(filename, linenum,
'runtime/string', 4,
4899 'Static/global string variables are not permitted.')
4901 if (
Search(
r'\b([A-Za-z0-9_]*_)\(\1\)', line)
or
4902 Search(
r'\b([A-Za-z0-9_]*_)\(CHECK_NOTNULL\(\1\)\)', line)):
4903 error(filename, linenum,
'runtime/init', 4,
4904 'You seem to be initializing a member variable with itself.')
4908 """Check for printf related issues.
4911 filename: The name of the current file.
4912 clean_lines: A CleansedLines instance containing the file.
4913 linenum: The number of the line to check.
4914 error: The function to call with any errors found.
4916 line = clean_lines.elided[linenum]
4919 match =
Search(
r'snprintf\s*\(([^,]*),\s*([0-9]*)\s*,', line)
4920 if match
and match.group(2) !=
'0':
4922 error(filename, linenum,
'runtime/printf', 3,
4923 'If you can, use sizeof(%s) instead of %s as the 2nd arg '
4924 'to snprintf.' % (match.group(1), match.group(2)))
4927 if Search(
r'\bsprintf\s*\(', line):
4928 error(filename, linenum,
'runtime/printf', 5,
4929 'Never use sprintf. Use snprintf instead.')
4930 match =
Search(
r'\b(strcpy|strcat)\s*\(', line)
4932 error(filename, linenum,
'runtime/printf', 4,
4933 'Almost always, snprintf is better than %s' % match.group(1))
4937 """Check if current line contains an inherited function.
4940 clean_lines: A CleansedLines instance containing the file.
4941 linenum: The number of the line to check.
4943 True if current line contains a function with "override"
4947 for i
in xrange(linenum, max(-1, linenum - 10), -1):
4948 match =
Match(
r'^([^()]*\w+)\(', clean_lines.elided[i])
4952 clean_lines, i, len(match.group(1)))
4953 return (closing_paren >= 0
and
4954 Search(
r'\boverride\b', line[closing_paren:]))
4959 """Check if current line contains an out-of-line method definition.
4962 clean_lines: A CleansedLines instance containing the file.
4963 linenum: The number of the line to check.
4965 True if current line contains an out-of-line method definition.
4968 for i
in xrange(linenum, max(-1, linenum - 10), -1):
4969 if Match(
r'^([^()]*\w+)\(', clean_lines.elided[i]):
4970 return Match(
r'^[^()]*\w+::\w+\(', clean_lines.elided[i])
is not None
4975 """Check if current line is inside constructor initializer list.
4978 clean_lines: A CleansedLines instance containing the file.
4979 linenum: The number of the line to check.
4981 True if current line appears to be inside constructor initializer
4982 list, False otherwise.
4984 for i
in xrange(linenum, 1, -1):
4985 line = clean_lines.elided[i]
4987 remove_function_body =
Match(
r'^(.*)\{\s*$', line)
4988 if remove_function_body:
4989 line = remove_function_body.group(1)
4991 if Search(
r'\s:\s*\w+[({]', line):
4997 if Search(
r'\}\s*,\s*$', line):
5001 if Search(
r'[{};]\s*$', line):
5017 nesting_state, error):
5018 """Check for non-const references.
5020 Separate from CheckLanguage since it scans backwards from current
5021 line, instead of scanning forward.
5024 filename: The name of the current file.
5025 clean_lines: A CleansedLines instance containing the file.
5026 linenum: The number of the line to check.
5027 nesting_state: A NestingState instance which maintains information about
5028 the current stack of nested blocks being parsed.
5029 error: The function to call with any errors found.
5032 line = clean_lines.elided[linenum]
5065 if Match(
r'\s*::(?:[\w<>]|::)+\s*&\s*\S', line):
5067 previous =
Search(
r'\b((?:const\s*)?(?:[\w<>]|::)+[\w<>])\s*$',
5068 clean_lines.elided[linenum - 1])
5069 elif Match(
r'\s*[a-zA-Z_]([\w<>]|::)+\s*&\s*\S', line):
5071 previous =
Search(
r'\b((?:const\s*)?(?:[\w<>]|::)+::)\s*$',
5072 clean_lines.elided[linenum - 1])
5074 line = previous.group(1) + line.lstrip()
5077 endpos = line.rfind(
'>')
5080 clean_lines, linenum, endpos)
5081 if startpos > -1
and startline < linenum:
5085 for i
in xrange(startline, linenum + 1):
5086 line += clean_lines.elided[i].strip()
5096 if (nesting_state.previous_stack_top
and
5097 not (isinstance(nesting_state.previous_stack_top, _ClassInfo)
or
5098 isinstance(nesting_state.previous_stack_top, _NamespaceInfo))):
5109 for i
in xrange(linenum - 1, max(0, linenum - 10), -1):
5110 previous_line = clean_lines.elided[i]
5111 if not Search(
r'[),]\s*$', previous_line):
5113 if Match(
r'^\s*:\s+\S', previous_line):
5117 if Search(
r'\\\s*$', line):
5130 whitelisted_functions = (
r'(?:[sS]wap(?:<\w:+>)?|'
5131 r'operator\s*[<>][<>]|'
5132 r'static_assert|COMPILE_ASSERT'
5134 if Search(whitelisted_functions, line):
5136 elif not Search(
r'\S+\([^)]*$', line):
5142 Search(whitelisted_functions, clean_lines.elided[linenum - i - 1])):
5146 for parameter
in re.findall(_RE_PATTERN_REF_PARAM, decls):
5147 if (
not Match(_RE_PATTERN_CONST_REF_PARAM, parameter)
and
5148 not Match(_RE_PATTERN_REF_STREAM_PARAM, parameter)):
5149 error(filename, linenum,
'runtime/references', 2,
5150 'Is this a non-const reference? '
5151 'If so, make const or use a pointer: ' +
5156 """Various cast related checks.
5159 filename: The name of the current file.
5160 clean_lines: A CleansedLines instance containing the file.
5161 linenum: The number of the line to check.
5162 error: The function to call with any errors found.
5164 line = clean_lines.elided[linenum]
5171 r'(\bnew\s+(?:const\s+)?|\S<\s*(?:const\s+)?)?\b'
5172 r'(int|float|double|bool|char|int32|uint32|int64|uint64)'
5173 r'(\([^)].*)', line)
5175 if match
and not expecting_function:
5176 matched_type = match.group(2)
5190 matched_new_or_template = match.group(1)
5194 if Match(
r'\([^()]+\)\s*\[', match.group(3)):
5202 matched_funcptr = match.group(3)
5203 if (matched_new_or_template
is None and
5204 not (matched_funcptr
and
5205 (
Match(
r'\((?:[^() ]+::\s*\*\s*)?[^() ]+\)\s*\(',
5207 matched_funcptr.startswith(
'(*)')))
and
5208 not Match(
r'\s*using\s+\S+\s*=\s*' + matched_type, line)
and
5209 not Search(
r'new\(\S+\)\s*' + matched_type, line)):
5210 error(filename, linenum,
'readability/casting', 4,
5211 'Using deprecated casting style. '
5212 'Use static_cast<%s>(...) instead' %
5215 if not expecting_function:
5217 r'\((int|float|double|bool|char|u?int(16|32|64))\)', error)
5224 r'\((char\s?\*+\s?)\)\s*"', error):
5229 r'\((\w+\s?\*+\s?)\)', error)
5243 r'(?:[^\w]&\(([^)*][^)]*)\)[\w(])|'
5244 r'(?:[^\w]&(static|dynamic|down|reinterpret)_cast\b)', line)
5249 parenthesis_error =
False
5250 match =
Match(
r'^(.*&(?:static|dynamic|down|reinterpret)_cast\b)<', line)
5252 _, y1, x1 =
CloseExpression(clean_lines, linenum, len(match.group(1)))
5253 if x1 >= 0
and clean_lines.elided[y1][x1] ==
'(':
5256 extended_line = clean_lines.elided[y2][x2:]
5257 if y2 < clean_lines.NumLines() - 1:
5258 extended_line += clean_lines.elided[y2 + 1]
5259 if Match(
r'\s*(?:->|\[)', extended_line):
5260 parenthesis_error =
True
5262 if parenthesis_error:
5263 error(filename, linenum,
'readability/casting', 4,
5264 (
'Are you taking an address of something dereferenced '
5265 'from a cast? Wrapping the dereferenced expression in '
5266 'parentheses will make the binding more obvious'))
5268 error(filename, linenum,
'runtime/casting', 4,
5269 (
'Are you taking an address of a cast? '
5270 'This is dangerous: could be a temp var. '
5271 'Take the address before doing the cast, rather than after'))
5275 """Checks for a C-style cast by looking for the pattern.
5278 filename: The name of the current file.
5279 clean_lines: A CleansedLines instance containing the file.
5280 linenum: The number of the line to check.
5281 cast_type: The string for the C++ cast to recommend. This is either
5282 reinterpret_cast, static_cast, or const_cast, depending.
5283 pattern: The regular expression used to find C-style casts.
5284 error: The function to call with any errors found.
5287 True if an error was emitted.
5290 line = clean_lines.elided[linenum]
5291 match =
Search(pattern, line)
5296 context = line[0:match.start(1) - 1]
5297 if Match(
r'.*\b(?:sizeof|alignof|alignas|[_A-Z][_A-Z0-9]*)\s*$', context):
5303 for i
in xrange(linenum - 1, max(0, linenum - 5), -1):
5304 context = clean_lines.elided[i] + context
5305 if Match(
r'.*\b[_A-Z][_A-Z0-9]*\s*\((?:\([^()]*\)|[^()])*$', context):
5309 if context.endswith(
' operator++')
or context.endswith(
' operator--'):
5314 remainder = line[match.end(0):]
5315 if Match(
r'^\s*(?:;|const\b|throw\b|final\b|override\b|[=>{),]|->)',
5320 error(filename, linenum,
'readability/casting', 4,
5321 'Using C-style cast. Use %s<%s>(...) instead' %
5322 (cast_type, match.group(1)))
5328 """Checks whether where function type arguments are expected.
5331 clean_lines: A CleansedLines instance containing the file.
5332 linenum: The number of the line to check.
5335 True if the line at 'linenum' is inside something that expects arguments
5338 line = clean_lines.elided[linenum]
5339 return (
Match(
r'^\s*MOCK_(CONST_)?METHOD\d+(_T)?\(', line)
or
5341 (
Match(
r'^\s*MOCK_(?:CONST_)?METHOD\d+(?:_T)?\((?:\S+,)?\s*$',
5342 clean_lines.elided[linenum - 1])
or
5343 Match(
r'^\s*MOCK_(?:CONST_)?METHOD\d+(?:_T)?\(\s*$',
5344 clean_lines.elided[linenum - 2])
or
5345 Search(
r'\bstd::m?function\s*<\s*$',
5346 clean_lines.elided[linenum - 1]))))
5349 _HEADERS_CONTAINING_TEMPLATES = (
5350 (
'<deque>', (
'deque',)),
5351 (
'<functional>', (
'unary_function',
'binary_function',
5352 'plus',
'minus',
'multiplies',
'divides',
'modulus',
5354 'equal_to',
'not_equal_to',
'greater',
'less',
5355 'greater_equal',
'less_equal',
5356 'logical_and',
'logical_or',
'logical_not',
5357 'unary_negate',
'not1',
'binary_negate',
'not2',
5358 'bind1st',
'bind2nd',
5359 'pointer_to_unary_function',
5360 'pointer_to_binary_function',
5362 'mem_fun_t',
'mem_fun',
'mem_fun1_t',
'mem_fun1_ref_t',
5364 'const_mem_fun_t',
'const_mem_fun1_t',
5365 'const_mem_fun_ref_t',
'const_mem_fun1_ref_t',
5368 (
'<limits>', (
'numeric_limits',)),
5369 (
'<list>', (
'list',)),
5370 (
'<map>', (
'map',
'multimap',)),
5371 (
'<memory>', (
'allocator',
'make_shared',
'make_unique',
'shared_ptr',
5372 'unique_ptr',
'weak_ptr')),
5373 (
'<queue>', (
'queue',
'priority_queue',)),
5374 (
'<set>', (
'set',
'multiset',)),
5375 (
'<stack>', (
'stack',)),
5376 (
'<string>', (
'char_traits',
'basic_string',)),
5377 (
'<tuple>', (
'tuple',)),
5378 (
'<unordered_map>', (
'unordered_map',
'unordered_multimap')),
5379 (
'<unordered_set>', (
'unordered_set',
'unordered_multiset')),
5380 (
'<utility>', (
'pair',)),
5381 (
'<vector>', (
'vector',)),
5385 (
'<hash_map>', (
'hash_map',
'hash_multimap',)),
5386 (
'<hash_set>', (
'hash_set',
'hash_multiset',)),
5387 (
'<slist>', (
'slist',)),
5390 _HEADERS_MAYBE_TEMPLATES = (
5391 (
'<algorithm>', (
'copy',
'max',
'min',
'min_element',
'sort',
5394 (
'<utility>', (
'forward',
'make_pair',
'move',
'swap')),
5397 _RE_PATTERN_STRING = re.compile(
r'\bstring\b')
5399 _re_pattern_headers_maybe_templates = []
5400 for _header, _templates
in _HEADERS_MAYBE_TEMPLATES:
5401 for _template
in _templates:
5404 _re_pattern_headers_maybe_templates.append(
5405 (re.compile(
r'[^>.]\b' + _template +
r'(<.*?>)?\([^\)]'),
5410 _re_pattern_templates = []
5411 for _header, _templates
in _HEADERS_CONTAINING_TEMPLATES:
5412 for _template
in _templates:
5413 _re_pattern_templates.append(
5414 (re.compile(
r'(<|\b)' + _template +
r'\s*<'),
5420 """Check if these two filenames belong to the same module.
5422 The concept of a 'module' here is a as follows:
5423 foo.h, foo-inl.h, foo.cc, foo_test.cc and foo_unittest.cc belong to the
5424 same 'module' if they are in the same directory.
5425 some/path/public/xyzzy and some/path/internal/xyzzy are also considered
5426 to belong to the same module here.
5428 If the filename_cc contains a longer path than the filename_h, for example,
5429 '/absolute/path/to/base/sysinfo.cc', and this file would include
5430 'base/sysinfo.h', this function also produces the prefix needed to open the
5431 header. This is used by the caller of this function to more robustly open the
5432 header file. We don't have access to the real include paths in this context,
5433 so we need this guesswork here.
5435 Known bugs: tools/base/bar.cc and base/bar.h belong to the same module
5436 according to this implementation. Because of this, this function gives
5437 some false positives. This should be sufficiently rare in practice.
5440 filename_cc: is the path for the .cc file
5441 filename_h: is the path for the header path
5444 Tuple with a bool and a string:
5445 bool: True if filename_cc and filename_h belong to the same module.
5446 string: the additional prefix needed to open the header file.
5450 if not fileinfo.IsSource():
5452 filename_cc = filename_cc[:-len(fileinfo.Extension())]
5453 matched_test_suffix =
Search(_TEST_FILE_SUFFIX, fileinfo.BaseName())
5454 if matched_test_suffix:
5455 filename_cc = filename_cc[:-len(matched_test_suffix.group(1))]
5456 filename_cc = filename_cc.replace(
'/public/',
'/')
5457 filename_cc = filename_cc.replace(
'/internal/',
'/')
5459 if not filename_h.endswith(
'.h'):
5461 filename_h = filename_h[:-len(
'.h')]
5462 if filename_h.endswith(
'-inl'):
5463 filename_h = filename_h[:-len(
'-inl')]
5464 filename_h = filename_h.replace(
'/public/',
'/')
5465 filename_h = filename_h.replace(
'/internal/',
'/')
5467 files_belong_to_same_module = filename_cc.endswith(filename_h)
5469 if files_belong_to_same_module:
5470 common_path = filename_cc[:-len(filename_h)]
5471 return files_belong_to_same_module, common_path
5475 """Fill up the include_dict with new includes found from the file.
5478 filename: the name of the header to read.
5479 include_dict: a dictionary in which the headers are inserted.
5480 io: The io factory to use to read the file. Provided for testability.
5483 True if a header was successfully added. False otherwise.
5487 headerfile = io.open(filename,
'r',
'utf8',
'replace')
5491 for line
in headerfile:
5494 match = _RE_PATTERN_INCLUDE.search(clean_line)
5496 include = match.group(2)
5497 include_dict.setdefault(include, linenum)
5503 """Reports for missing stl includes.
5505 This function will output warnings to make sure you are including the headers
5506 necessary for the stl containers and functions that you use. We only give one
5507 reason to include a header. For example, if you use both equal_to<> and
5508 less<> in a .h file, only one (the latter in the file) of these will be
5509 reported as a reason to include the <functional>.
5512 filename: The name of the current file.
5513 clean_lines: A CleansedLines instance containing the file.
5514 include_state: An _IncludeState instance.
5515 error: The function to call with any errors found.
5516 io: The IO factory to use to read the header file. Provided for unittest
5522 for linenum
in xrange(clean_lines.NumLines()):
5523 line = clean_lines.elided[linenum]
5524 if not line
or line[0] ==
'#':
5528 matched = _RE_PATTERN_STRING.search(line)
5532 prefix = line[:matched.start()]
5533 if prefix.endswith(
'std::')
or not prefix.endswith(
'::'):
5534 required[
'<string>'] = (linenum,
'string')
5536 for pattern, template, header
in _re_pattern_headers_maybe_templates:
5537 if pattern.search(line):
5538 required[header] = (linenum, template)
5544 for pattern, template, header
in _re_pattern_templates:
5545 matched = pattern.search(line)
5549 prefix = line[:matched.start()]
5550 if prefix.endswith(
'std::')
or not prefix.endswith(
'::'):
5551 required[header] = (linenum, template)
5556 include_dict = dict([item
for sublist
in include_state.include_list
5557 for item
in sublist])
5560 header_found =
False
5563 abs_filename =
FileInfo(filename).FullName()
5572 abs_filename = re.sub(
r'_flymake\.cc$',
'.cc', abs_filename)
5576 header_keys = include_dict.keys()
5577 for header
in header_keys:
5579 fullpath = common_path + header
5588 if filename.endswith(
'.cc')
and not header_found:
5592 for required_header_unstripped
in required:
5593 template = required[required_header_unstripped][1]
5594 if required_header_unstripped.strip(
'<>"')
not in include_dict:
5595 error(filename, required[required_header_unstripped][0],
5596 'build/include_what_you_use', 4,
5597 'Add #include ' + required_header_unstripped +
' for ' + template)
5600 _RE_PATTERN_EXPLICIT_MAKEPAIR = re.compile(
r'\bmake_pair\s*<')
5604 """Check that make_pair's template arguments are deduced.
5606 G++ 4.6 in C++11 mode fails badly if make_pair's template arguments are
5607 specified explicitly, and such use isn't intended in any case.
5610 filename: The name of the current file.
5611 clean_lines: A CleansedLines instance containing the file.
5612 linenum: The number of the line to check.
5613 error: The function to call with any errors found.
5615 line = clean_lines.elided[linenum]
5616 match = _RE_PATTERN_EXPLICIT_MAKEPAIR.search(line)
5618 error(filename, linenum,
'build/explicit_make_pair',
5620 'For C++11-compatibility, omit template arguments from make_pair'
5621 ' OR use pair directly OR if appropriate, construct a pair directly')
5625 """Check if line contains a redundant "virtual" function-specifier.
5628 filename: The name of the current file.
5629 clean_lines: A CleansedLines instance containing the file.
5630 linenum: The number of the line to check.
5631 error: The function to call with any errors found.
5634 line = clean_lines.elided[linenum]
5635 virtual =
Match(
r'^(.*)(\bvirtual\b)(.*)$', line)
5636 if not virtual:
return
5641 if (
Search(
r'\b(public|protected|private)\s+$', virtual.group(1))
or
5642 Match(
r'^\s+(public|protected|private)\b', virtual.group(3))):
5648 if Match(
r'^.*[^:]:[^:].*$', line):
return
5657 start_col = len(virtual.group(2))
5658 for start_line
in xrange(linenum, min(linenum + 3, clean_lines.NumLines())):
5659 line = clean_lines.elided[start_line][start_col:]
5660 parameter_list =
Match(
r'^([^(]*)\(', line)
5664 clean_lines, start_line, start_col + len(parameter_list.group(1)))
5673 for i
in xrange(end_line, min(end_line + 3, clean_lines.NumLines())):
5674 line = clean_lines.elided[i][end_col:]
5675 match =
Search(
r'\b(override|final)\b', line)
5677 error(filename, linenum,
'readability/inheritance', 4,
5678 (
'"virtual" is redundant since function is '
5679 'already declared as "%s"' % match.group(1)))
5684 if Search(
r'[^\w]\s*$', line):
5689 """Check if line contains a redundant "override" or "final" virt-specifier.
5692 filename: The name of the current file.
5693 clean_lines: A CleansedLines instance containing the file.
5694 linenum: The number of the line to check.
5695 error: The function to call with any errors found.
5700 line = clean_lines.elided[linenum]
5701 declarator_end = line.rfind(
')')
5702 if declarator_end >= 0:
5703 fragment = line[declarator_end:]
5705 if linenum > 1
and clean_lines.elided[linenum - 1].rfind(
')') >= 0:
5711 if Search(
r'\boverride\b', fragment)
and Search(
r'\bfinal\b', fragment):
5712 error(filename, linenum,
'readability/inheritance', 4,
5713 (
'"override" is redundant since function is '
5714 'already declared as "final"'))
5722 """Checks that the new block is directly in a namespace.
5725 nesting_state: The _NestingState object that contains info about our state.
5726 is_forward_declaration: If the class is a forward declared class.
5728 Whether or not the new block is directly in a namespace.
5730 if is_forward_declaration:
5731 if len(nesting_state.stack) >= 1
and (
5732 isinstance(nesting_state.stack[-1], _NamespaceInfo)):
5737 return (len(nesting_state.stack) > 1
and
5738 nesting_state.stack[-1].check_namespace_indentation
and
5739 isinstance(nesting_state.stack[-2], _NamespaceInfo))
5743 raw_lines_no_comments, linenum):
5744 """This method determines if we should apply our namespace indentation check.
5747 nesting_state: The current nesting state.
5748 is_namespace_indent_item: If we just put a new class on the stack, True.
5749 If the top of the stack is not a class, or we did not recently
5750 add the class, False.
5751 raw_lines_no_comments: The lines without the comments.
5752 linenum: The current line number we are processing.
5755 True if we should apply our namespace indentation check. Currently, it
5756 only works for classes and namespaces inside of a namespace.
5762 if not (is_namespace_indent_item
or is_forward_declaration):
5777 line = raw_lines_no_comments[linenum]
5778 if Match(
r'^\s+', line):
5779 error(filename, linenum,
'runtime/indentation_namespace', 4,
5780 'Do not indent within a namespace')
5784 include_state, function_state, nesting_state, error,
5785 extra_check_functions=[]):
5786 """Processes a single line in the file.
5789 filename: Filename of the file that is being processed.
5790 file_extension: The extension (dot not included) of the file.
5791 clean_lines: An array of strings, each representing a line of the file,
5792 with comments stripped.
5793 line: Number of line being processed.
5794 include_state: An _IncludeState instance in which the headers are inserted.
5795 function_state: A _FunctionState instance which counts function lines, etc.
5796 nesting_state: A NestingState instance which maintains information about
5797 the current stack of nested blocks being parsed.
5798 error: A callable to which errors are reported, which takes 4 arguments:
5799 filename, line number, error level, and message
5800 extra_check_functions: An array of additional check functions that will be
5801 run on each source line. Each function takes 4
5802 arguments: filename, clean_lines, line, error
5804 raw_lines = clean_lines.raw_lines
5806 nesting_state.Update(filename, clean_lines, line, error)
5809 if nesting_state.InAsmBlock():
return
5812 CheckStyle(filename, clean_lines, line, file_extension, nesting_state, error)
5813 CheckLanguage(filename, clean_lines, line, file_extension, include_state,
5814 nesting_state, error)
5817 nesting_state, error)
5824 for check_fn
in extra_check_functions:
5825 check_fn(filename, clean_lines, line, error)
5828 """Flag those c++11 features that we only allow in certain places.
5831 filename: The name of the current file.
5832 clean_lines: A CleansedLines instance containing the file.
5833 linenum: The number of the line to check.
5834 error: The function to call with any errors found.
5836 line = clean_lines.elided[linenum]
5838 include =
Match(
r'\s*#\s*include\s+[<"]([^<"]+)[">]', line)
5841 if include
and include.group(1).startswith(
'tr1/'):
5842 error(filename, linenum,
'build/c++tr1', 5,
5843 (
'C++ TR1 headers such as <%s> are unapproved.') % include.group(1))
5846 if include
and include.group(1)
in (
'cfenv',
5847 'condition_variable',
5857 error(filename, linenum,
'build/c++11', 5,
5858 (
'<%s> is an unapproved C++11 header.') % include.group(1))
5862 if Match(
r'\s*#', line)
and not Match(
r'\s*#\s*define\b', line):
return
5872 if Search(
r'\bstd::%s\b' % top_name, line):
5873 error(filename, linenum,
'build/c++11', 5,
5874 (
'std::%s is an unapproved C++11 class or function. Send c-style '
5875 'an example of where it would make your code more readable, and '
5876 'they may let you use it.') % top_name)
5880 """Flag those C++14 features that we restrict.
5883 filename: The name of the current file.
5884 clean_lines: A CleansedLines instance containing the file.
5885 linenum: The number of the line to check.
5886 error: The function to call with any errors found.
5888 line = clean_lines.elided[linenum]
5890 include =
Match(
r'\s*#\s*include\s+[<"]([^<"]+)[">]', line)
5893 if include
and include.group(1)
in (
'scoped_allocator',
'shared_mutex'):
5894 error(filename, linenum,
'build/c++14', 5,
5895 (
'<%s> is an unapproved C++14 header.') % include.group(1))
5899 extra_check_functions=[]):
5900 """Performs lint checks and reports any errors to the given error function.
5903 filename: Filename of the file that is being processed.
5904 file_extension: The extension (dot not included) of the file.
5905 lines: An array of strings, each representing a line of the file, with the
5906 last element being empty if the file is terminated with a newline.
5907 error: A callable to which errors are reported, which takes 4 arguments:
5908 filename, line number, error level, and message
5909 extra_check_functions: An array of additional check functions that will be
5910 run on each source line. Each function takes 4
5911 arguments: filename, clean_lines, line, error
5913 lines = ([
'// marker so line numbers and indices both start at 1'] + lines +
5914 [
'// marker so line numbers end in a known way'])
5930 for line
in xrange(clean_lines.NumLines()):
5931 ProcessLine(filename, file_extension, clean_lines, line,
5932 include_state, function_state, nesting_state, error,
5933 extra_check_functions)
5935 nesting_state.CheckCompletedBlocks(filename, error)
5950 """ Loads the configuration files and processes the config overrides.
5953 filename: The name of the file being processed by the linter.
5956 False if the current |filename| should not be processed further.
5959 abs_filename = os.path.abspath(filename)
5963 abs_path, base_name = os.path.split(abs_filename)
5967 cfg_file = os.path.join(abs_path,
"CPPLINT.cfg")
5968 abs_filename = abs_path
5969 if not os.path.isfile(cfg_file):
5973 with open(cfg_file)
as file_handle:
5974 for line
in file_handle:
5975 line, _, _ = line.partition(
'#')
5976 if not line.strip():
5979 name, _, val = line.partition(
'=')
5982 if name ==
'set noparent':
5983 keep_looking =
False
5984 elif name ==
'filter':
5985 cfg_filters.append(val)
5986 elif name ==
'exclude_files':
5994 pattern = re.compile(val)
5995 if pattern.match(base_name):
5996 if _cpplint_state.quiet:
5999 sys.stderr.write(
'Ignoring "%s": file excluded by "%s". '
6000 'File path component "%s" matches '
6002 (filename, cfg_file, base_name, val))
6004 elif name ==
'linelength':
6007 _line_length = int(val)
6009 sys.stderr.write(
'Line length must be numeric.')
6010 elif name ==
'root':
6013 _root = os.path.join(os.path.dirname(cfg_file), val)
6014 elif name ==
'headers':
6018 'Invalid configuration option (%s) in file %s\n' %
6023 "Skipping config file '%s': Can't open for reading\n" % cfg_file)
6024 keep_looking =
False
6028 for filter
in reversed(cfg_filters):
6035 """Does google-lint on a single file.
6038 filename: The name of the file to parse.
6040 vlevel: The level of errors to report. Every error of confidence
6041 >= verbose_level will be reported. 0 is a good default.
6043 extra_check_functions: An array of additional check functions that will be
6044 run on each source line. Each function takes 4
6045 arguments: filename, clean_lines, line, error
6050 old_errors = _cpplint_state.error_count
6067 lines = codecs.StreamReaderWriter(sys.stdin,
6068 codecs.getreader(
'utf8'),
6069 codecs.getwriter(
'utf8'),
6070 'replace').read().split(
'\n')
6072 lines = codecs.open(filename,
'r',
'utf8',
'replace').read().split(
'\n')
6076 for linenum
in range(len(lines) - 1):
6077 if lines[linenum].endswith(
'\r'):
6078 lines[linenum] = lines[linenum].rstrip(
'\r')
6079 crlf_lines.append(linenum + 1)
6081 lf_lines.append(linenum + 1)
6085 "Skipping input '%s': Can't open for reading\n" % filename)
6090 file_extension = filename[filename.rfind(
'.') + 1:]
6094 if filename !=
'-' and file_extension
not in _valid_extensions:
6095 sys.stderr.write(
'Ignoring %s; not a valid file name '
6096 '(%s)\n' % (filename,
', '.join(_valid_extensions)))
6099 extra_check_functions)
6111 if lf_lines
and crlf_lines:
6115 for linenum
in crlf_lines:
6116 Error(filename, linenum,
'whitespace/newline', 1,
6117 'Unexpected \\r (^M) found; better to use only \\n')
6121 if not _cpplint_state.quiet
or old_errors != _cpplint_state.error_count:
6122 sys.stdout.write(
'Done processing %s\n' % filename)
6127 """Prints a brief usage string and exits, optionally with an error message.
6130 message: The optional error message.
6132 sys.stderr.write(_USAGE)
6134 sys.exit(
'\nFATAL ERROR: ' + message)
6140 """Prints a list of all the error-categories used by error messages.
6142 These are the categories used to filter messages via --filter.
6144 sys.stderr.write(
''.join(
' %s\n' % cat
for cat
in _ERROR_CATEGORIES))
6149 """Parses the command line arguments.
6151 This may set the output format and verbosity level as side-effects.
6154 args: The command line arguments:
6157 The list of filenames to lint.
6160 (opts, filenames) = getopt.getopt(args,
'', [
'help',
'output=',
'verbose=',
6168 except getopt.GetoptError:
6177 for (opt, val)
in opts:
6180 elif opt ==
'--output':
6181 if val
not in (
'emacs',
'vs7',
'eclipse'):
6182 PrintUsage(
'The only allowed output formats are emacs, vs7 and eclipse.')
6184 elif opt ==
'--quiet':
6186 elif opt ==
'--verbose':
6187 verbosity = int(val)
6188 elif opt ==
'--filter':
6192 elif opt ==
'--counting':
6193 if val
not in (
'total',
'toplevel',
'detailed'):
6194 PrintUsage(
'Valid counting options are total, toplevel, and detailed')
6195 counting_style = val
6196 elif opt ==
'--root':
6199 elif opt ==
'--linelength':
6202 _line_length = int(val)
6205 elif opt ==
'--extensions':
6206 global _valid_extensions
6208 _valid_extensions = set(val.split(
','))
6210 PrintUsage(
'Extensions must be comma separated list.')
6211 elif opt ==
'--headers':
6229 _cpplint_state.ResetErrorCounts()
6230 for filename
in filenames:
6231 ProcessFile(filename, _cpplint_state.verbose_level)
6233 if not _cpplint_state.quiet
or _cpplint_state.error_count > 0:
6234 _cpplint_state.PrintErrorCounts()
6236 sys.exit(_cpplint_state.error_count > 0)
6239 if __name__ ==
'__main__':