31 """Does google-lint on c++ files. 33 The goal of this script is to identify places in the code that *may* 34 be in non-compliance with google style. It does not attempt to fix 35 up these problems -- the point is to educate. It does also not 36 attempt to find all problems, or to ensure that everything it does 37 find is legitimately a problem. 39 In particular, we can get very confused by /* and // inside strings! 40 We do a small hack, which is to ignore //'s with "'s after them on the 41 same line, but it is far from perfect (in either direction). 56 import xml.etree.ElementTree
59 _header_extensions =
set([])
62 _valid_extensions =
set([])
70 if not _header_extensions:
71 return set([
'h',
'hpp',
'hxx',
'h++',
'cuh'])
72 return _header_extensions
77 if not _valid_extensions:
79 return _valid_extensions
86 Syntax: cpplint.py [--verbose=#] [--output=emacs|eclipse|vs7|junit] 88 [--counting=total|toplevel|detailed] [--repository=path] 89 [--root=subdir] [--linelength=digits] [--recursive] 92 [--extensions=hpp,cpp,...] 95 The style guidelines this tries to follow are those in 96 https://google.github.io/styleguide/cppguide.html 98 Every problem is given a confidence score from 1-5, with 5 meaning we are 99 certain of the problem, and 1 meaning it could be a legitimate construct. 100 This will miss some errors, and is not a substitute for a code review. 102 To suppress false-positive errors of a certain category, add a 103 'NOLINT(category)' comment to the line. NOLINT or NOLINT(*) 104 suppresses errors of all categories on that line. 106 The files passed in will be linted; at least one file must be provided. 107 Default linted extensions are %s. 108 Other file types will be ignored. 109 Change the extensions with the --extensions flag. 113 output=emacs|eclipse|vs7|junit 114 By default, the output is formatted to ease emacs parsing. Output 115 compatible with eclipse (eclipse), Visual Studio (vs7), and JUnit 116 XML parsers such as those used in Jenkins and Bamboo may also be 117 used. Other formats are unsupported. 120 Specify a number 0-5 to restrict errors to certain verbosity levels. 121 Errors with lower verbosity levels have lower confidence and are more 122 likely to be false positives. 125 Supress output other than linting errors, such as information about 126 which files have been processed and excluded. 129 Specify a comma-separated list of category-filters to apply: only 130 error messages whose category names pass the filters will be printed. 131 (Category names are printed with the message and look like 132 "[whitespace/indent]".) Filters are evaluated left to right. 133 "-FOO" and "FOO" means "do not print categories that start with FOO". 134 "+FOO" means "do print categories that start with FOO". 136 Examples: --filter=-whitespace,+whitespace/braces 137 --filter=whitespace,runtime/printf,+runtime/printf_format 138 --filter=-,+build/include_what_you_use 140 To see a list of all the categories used in cpplint, pass no arg: 143 counting=total|toplevel|detailed 144 The total number of errors found is always printed. If 145 'toplevel' is provided, then the count of errors in each of 146 the top-level categories like 'build' and 'whitespace' will 147 also be printed. If 'detailed' is provided, then a count 148 is provided for each category like 'build/class'. 151 The top level directory of the repository, used to derive the header 152 guard CPP variable. By default, this is determined by searching for a 153 path that contains .git, .hg, or .svn. When this flag is specified, the 154 given path is used instead. This option allows the header guard CPP 155 variable to remain consistent even if members of a team have different 156 repository root directories (such as when checking out a subdirectory 157 with SVN). In addition, users of non-mainstream version control systems 158 can use this flag to ensure readable header guard CPP variables. 161 Assuming that Alice checks out ProjectName and Bob checks out 162 ProjectName/trunk and trunk contains src/chrome/ui/browser.h, then 163 with no --repository flag, the header guard CPP variable will be: 165 Alice => TRUNK_SRC_CHROME_BROWSER_UI_BROWSER_H_ 166 Bob => SRC_CHROME_BROWSER_UI_BROWSER_H_ 168 If Alice uses the --repository=trunk flag and Bob omits the flag or 169 uses --repository=. then the header guard CPP variable will be: 171 Alice => SRC_CHROME_BROWSER_UI_BROWSER_H_ 172 Bob => SRC_CHROME_BROWSER_UI_BROWSER_H_ 175 The root directory used for deriving header guard CPP variables. This 176 directory is relative to the top level directory of the repository which 177 by default is determined by searching for a directory that contains .git, 178 .hg, or .svn but can also be controlled with the --repository flag. If 179 the specified directory does not exist, this flag is ignored. 182 Assuming that src is the top level directory of the repository, the 183 header guard CPP variables for src/chrome/browser/ui/browser.h are: 185 No flag => CHROME_BROWSER_UI_BROWSER_H_ 186 --root=chrome => BROWSER_UI_BROWSER_H_ 187 --root=chrome/browser => UI_BROWSER_H_ 190 This is the allowed line length for the project. The default value is 197 Search for files to lint recursively. Each directory given in the list 198 of files to be linted is replaced by all files that descend from that 199 directory. Files with extensions not in the valid extensions list are 203 Exclude the given path from the list of files to be linted. Relative 204 paths are evaluated relative to the current directory and shell globbing 205 is performed. This flag can be provided multiple times to exclude 211 --exclude=src/*.cc --exclude=test/*.cc 213 extensions=extension,extension,... 214 The allowed file extensions that cpplint will check 219 headers=extension,extension,... 220 The allowed header extensions that cpplint will consider to be header files 221 (by default, only files with extensions %s 222 will be assumed to be headers) 227 cpplint.py supports per-directory configurations specified in CPPLINT.cfg 228 files. CPPLINT.cfg file can contain a number of key=value pairs. 229 Currently the following options are supported: 232 filter=+filter1,-filter2,... 237 "set noparent" option prevents cpplint from traversing directory tree 238 upwards looking for more .cfg files in parent directories. This option 239 is usually placed in the top-level project directory. 241 The "filter" option is similar in function to --filter flag. It specifies 242 message filters in addition to the |_DEFAULT_FILTERS| and those specified 243 through --filter command-line flag. 245 "exclude_files" allows to specify a regular expression to be matched against 246 a file name. If the expression matches, the file is skipped and not run 249 "linelength" specifies the allowed line length for the project. 251 The "root" option is similar in function to the --root flag (see example 254 CPPLINT.cfg has an effect on files in the same directory and all 255 subdirectories, unless overridden by a nested configuration file. 258 filter=-build/include_order,+build/include_alpha 259 exclude_files=.*\\.cc 261 The above example disables build/include_order warning and enables 262 build/include_alpha as well as excludes all .cc from being 263 processed by linter, in the current directory (where the .cfg 264 file is located) and all subdirectories. 274 _ERROR_CATEGORIES = [
280 'build/endif_comment',
281 'build/explicit_make_pair',
282 'build/forward_decl',
283 'build/header_guard',
285 'build/include_subdir',
286 'build/include_alpha',
287 'build/include_order',
288 'build/include_what_you_use',
289 'build/namespaces_literals',
291 'build/printf_format',
292 'build/storage_class',
294 'readability/alt_tokens',
295 'readability/braces',
296 'readability/casting',
298 'readability/constructors',
299 'readability/fn_size',
300 'readability/inheritance',
301 'readability/multiline_comment',
302 'readability/multiline_string',
303 'readability/namespace',
304 'readability/nolint',
306 'readability/strings',
314 'runtime/invalid_increment',
315 'runtime/member_string_references',
317 'runtime/indentation_namespace',
320 'runtime/printf_format',
321 'runtime/references',
323 'runtime/threadsafe_fn',
325 'whitespace/blank_line',
328 'whitespace/comments',
329 'whitespace/empty_conditional_body',
330 'whitespace/empty_if_body',
331 'whitespace/empty_loop_body',
332 'whitespace/end_of_line',
333 'whitespace/ending_newline',
334 'whitespace/forcolon',
336 'whitespace/line_length',
337 'whitespace/newline',
338 'whitespace/operators',
340 'whitespace/semicolon',
347 _LEGACY_ERROR_CATEGORIES = [
348 'readability/streams',
349 'readability/function',
356 _DEFAULT_FILTERS = [
'-build/include_alpha']
359 _DEFAULT_C_SUPPRESSED_CATEGORIES = [
360 'readability/casting',
364 _DEFAULT_KERNEL_SUPPRESSED_CATEGORIES = [
373 _CPP_HEADERS = frozenset([
434 'condition_variable',
513 r'(char(16_t|32_t)?)|wchar_t|' 514 r'bool|short|int|long|signed|unsigned|float|double|' 516 r'(ptrdiff_t|size_t|max_align_t|nullptr_t)|' 518 r'(u?int(_fast|_least)?(8|16|32|64)_t)|' 519 r'(u?int(max|ptr)_t)|' 528 _THIRD_PARTY_HEADERS_PATTERN = re.compile(
529 r'^(?:[^/]*[A-Z][^/]*\.h|lua\.h|lauxlib\.h|lualib\.h)$')
532 _test_suffixes = [
'_test',
'_regtest',
'_unittest']
533 _TEST_FILE_SUFFIX =
'(' +
'|'.join(_test_suffixes) +
r')$' 536 _EMPTY_CONDITIONAL_BODY_PATTERN = re.compile(
r'^\s*$', re.DOTALL)
542 'EXPECT_TRUE',
'ASSERT_TRUE',
543 'EXPECT_FALSE',
'ASSERT_FALSE',
547 _CHECK_REPLACEMENT = dict([(macro_var, {})
for macro_var
in _CHECK_MACROS])
549 for op, replacement
in [(
'==',
'EQ'), (
'!=',
'NE'),
550 (
'>=',
'GE'), (
'>',
'GT'),
551 (
'<=',
'LE'), (
'<',
'LT')]:
552 _CHECK_REPLACEMENT[
'DCHECK'][op] =
'DCHECK_%s' % replacement
553 _CHECK_REPLACEMENT[
'CHECK'][op] =
'CHECK_%s' % replacement
554 _CHECK_REPLACEMENT[
'EXPECT_TRUE'][op] =
'EXPECT_%s' % replacement
555 _CHECK_REPLACEMENT[
'ASSERT_TRUE'][op] =
'ASSERT_%s' % replacement
557 for op, inv_replacement
in [(
'==',
'NE'), (
'!=',
'EQ'),
558 (
'>=',
'LT'), (
'>',
'LE'),
559 (
'<=',
'GT'), (
'<',
'GE')]:
560 _CHECK_REPLACEMENT[
'EXPECT_FALSE'][op] =
'EXPECT_%s' % inv_replacement
561 _CHECK_REPLACEMENT[
'ASSERT_FALSE'][op] =
'ASSERT_%s' % inv_replacement
568 _ALT_TOKEN_REPLACEMENT = {
587 _ALT_TOKEN_REPLACEMENT_PATTERN = re.compile(
588 r'[ =()](' + (
'|'.join(_ALT_TOKEN_REPLACEMENT.keys())) +
r')(?=[ (]|$)')
595 _LIKELY_MY_HEADER = 3
596 _POSSIBLE_MY_HEADER = 4
606 _MATCH_ASM = re.compile(
r'^\s*(?:asm|_asm|__asm|__asm__)' 607 r'(?:\s+(volatile|__volatile__))?' 611 _SEARCH_C_FILE = re.compile(
r'\b(?:LINT_C_FILE|' 612 r'vim?:\s*.*(\s*|:)filetype=c(\s*|:|$))')
615 _SEARCH_KERNEL_FILE = re.compile(
r'\b(?:LINT_KERNEL_FILE)')
617 _regexp_compile_cache = {}
621 _error_suppressions = {}
652 basestring = unicode = str
660 if sys.version_info < (3,):
663 itervalues = dict.itervalues
664 iteritems = dict.iteritems
667 itervalues = dict.values
668 iteritems = dict.items
671 if sys.version_info < (3,):
672 return codecs.unicode_escape_decode(x)[0]
678 _global_error_suppressions = {}
684 """Updates the global list of line error-suppressions. 686 Parses any NOLINT comments on the current line, updating the global 687 error_suppressions store. Reports an error if the NOLINT comment 691 filename: str, the name of the input file. 692 raw_line: str, the line of input text, with comments. 693 linenum: int, the number of the current line. 694 error: function, an error handler. 696 matched =
Search(
r'\bNOLINT(NEXTLINE)?\b(\([^)]+\))?', raw_line)
699 suppressed_line = linenum + 1
701 suppressed_line = linenum
702 category = matched.group(2)
703 if category
in (
None,
'(*)'):
704 _error_suppressions.setdefault(
None,
set()).
add(suppressed_line)
706 if category.startswith(
'(')
and category.endswith(
')'):
707 category = category[1:-1]
708 if category
in _ERROR_CATEGORIES:
709 _error_suppressions.setdefault(category,
set()).
add(suppressed_line)
710 elif category
not in _LEGACY_ERROR_CATEGORIES:
711 error(filename, linenum,
'readability/nolint', 5,
712 'Unknown NOLINT error category: %s' % category)
716 """Updates the list of global error suppressions. 718 Parses any lint directives in the file that have global effect. 721 lines: An array of strings, each representing a line of the file, with the 722 last element being empty if the file is terminated with a newline. 725 if _SEARCH_C_FILE.search(line):
726 for category
in _DEFAULT_C_SUPPRESSED_CATEGORIES:
727 _global_error_suppressions[category] =
True 728 if _SEARCH_KERNEL_FILE.search(line):
729 for category
in _DEFAULT_KERNEL_SUPPRESSED_CATEGORIES:
730 _global_error_suppressions[category] =
True 734 """Resets the set of NOLINT suppressions to empty.""" 735 _error_suppressions.clear()
736 _global_error_suppressions.clear()
740 """Returns true if the specified error category is suppressed on this line. 742 Consults the global error_suppressions map populated by 743 ParseNolintSuppressions/ProcessGlobalSuppresions/ResetNolintSuppressions. 746 category: str, the category of the error. 747 linenum: int, the current line number. 749 bool, True iff the error should be suppressed due to a NOLINT comment or 752 return (_global_error_suppressions.get(category,
False)
or 753 linenum
in _error_suppressions.get(category,
set())
or 754 linenum
in _error_suppressions.get(
None,
set()))
757 def Match(pattern, s):
758 """Matches the string with the pattern, caching the compiled regexp.""" 762 if pattern
not in _regexp_compile_cache:
763 _regexp_compile_cache[pattern] = sre_compile.compile(pattern)
764 return _regexp_compile_cache[pattern].match(s)
768 """Replaces instances of pattern in a string with a replacement. 770 The compiled regex is kept in a cache shared by Match and Search. 773 pattern: regex pattern 774 rep: replacement text 778 string with replacements made (or original string if no replacements) 780 if pattern
not in _regexp_compile_cache:
781 _regexp_compile_cache[pattern] = sre_compile.compile(pattern)
782 return _regexp_compile_cache[pattern].sub(rep, s)
786 """Searches the string for the pattern, caching the compiled regexp.""" 787 if pattern
not in _regexp_compile_cache:
788 _regexp_compile_cache[pattern] = sre_compile.compile(pattern)
789 return _regexp_compile_cache[pattern].
search(s)
793 """File extension (excluding dot) matches a source file extension.""" 797 class _IncludeState(object):
798 """Tracks line numbers for includes, and the order in which includes appear. 800 include_list contains list of lists of (header, line number) pairs. 801 It's a lists of lists rather than just one flat list to make it 802 easier to update across preprocessor boundaries. 804 Call CheckNextIncludeOrder() once for each header in the file, passing 805 in the type constants defined above. Calls in an illegal order will 806 raise an _IncludeError with an appropriate error message. 818 _C_SYS_HEADER:
'C system header',
819 _CPP_SYS_HEADER:
'C++ system header',
820 _LIKELY_MY_HEADER:
'header this file implements',
821 _POSSIBLE_MY_HEADER:
'header this file may implement',
822 _OTHER_HEADER:
'other header',
825 _INITIAL_SECTION:
"... nothing. (This can't be an error.)",
826 _MY_H_SECTION:
'a header this file implements',
827 _C_SECTION:
'C system header',
828 _CPP_SECTION:
'C++ system header',
829 _OTHER_H_SECTION:
'other header',
839 """Check if a header has already been included. 842 header: header to check. 844 Line number of previous occurrence, or -1 if the header has not 848 for f
in section_list:
854 """Reset section checking for preprocessor directive. 857 directive: preprocessor directive (e.g. "if", "else"). 866 if directive
in (
'if',
'ifdef',
'ifndef'):
868 elif directive
in (
'else',
'elif'):
875 """Returns a path canonicalized for alphabetical comparison. 877 - replaces "-" with "_" so they both cmp the same. 878 - removes '-inl' since we don't require them to be after the main header. 879 - lowercase everything, just in case. 882 header_path: Path to be canonicalized. 887 return header_path.replace(
'-inl.h',
'.h').replace(
'-',
'_').lower()
890 """Check if a header is in alphabetical order with the previous header. 893 clean_lines: A CleansedLines instance containing the file. 894 linenum: The number of the line to check. 895 header_path: Canonicalized header to be checked. 898 Returns true if the header is in alphabetical order. 906 Match(
r'^\s*#\s*include\b', clean_lines.elided[linenum - 1])):
911 """Returns a non-empty error message if the next header is out of order. 913 This function also updates the internal state to be ready to check 917 header_type: One of the _XXX_HEADER constants defined above. 920 The empty string if the header is in the right order, or an 921 error message describing what's wrong. 924 error_message = (
'Found %s after %s' %
930 if header_type == _C_SYS_HEADER:
936 elif header_type == _CPP_SYS_HEADER:
942 elif header_type == _LIKELY_MY_HEADER:
947 elif header_type == _POSSIBLE_MY_HEADER:
955 assert header_type == _OTHER_HEADER
965 """Maintains module-wide state..""" 971 self.
filters = _DEFAULT_FILTERS[:]
990 """Sets the output format for errors.""" 994 """Sets the module's verbosity, and returns the previous setting.""" 997 return last_verbose_level
1000 """Sets the module's counting options.""" 1004 """Sets the error-message filters. 1006 These filters are applied when deciding whether to emit a given 1010 filters: A string of comma-separated filters (eg "+whitespace/indent"). 1011 Each filter should start with + or -; else we die. 1014 ValueError: The comma-separated filters did not all start with '+' or '-'. 1015 E.g. "-,+whitespace,-whitespace/indent,whitespace/badfilter" 1018 self.
filters = _DEFAULT_FILTERS[:]
1022 """ Adds more filters to the existing list of error-message filters. """ 1023 for filt
in filters.split(
','):
1024 clean_filt = filt.strip()
1026 self.
filters.append(clean_filt)
1028 if not (filt.startswith(
'+')
or filt.startswith(
'-')):
1029 raise ValueError(
'Every filter in --filters must start with + or -' 1030 ' (%s does not)' % filt)
1033 """ Saves the current filter list to backup storage.""" 1037 """ Restores filters previously backed up.""" 1041 """Sets the module's error statistic back to zero.""" 1046 """Bumps the module's error statistic.""" 1048 if self.
counting in (
'toplevel',
'detailed'):
1050 category = category.split(
'/')[0]
1056 """Print a summary of errors by category, and the total.""" 1058 self.
PrintInfo(
'Category \'%s\' errors found: %d\n' %
1065 sys.stderr.write(message)
1071 sys.stderr.write(message)
1081 testsuite = xml.etree.ElementTree.Element(
'testsuite')
1082 testsuite.attrib[
'name'] =
'cpplint' 1083 testsuite.attrib[
'errors'] =
str(num_errors)
1084 testsuite.attrib[
'failures'] =
str(num_failures)
1086 if num_errors == 0
and num_failures == 0:
1087 testsuite.attrib[
'tests'] =
str(1)
1088 xml.etree.ElementTree.SubElement(testsuite,
'testcase', name=
'passed')
1091 testsuite.attrib[
'tests'] =
str(num_errors + num_failures)
1093 testcase = xml.etree.ElementTree.SubElement(testsuite,
'testcase')
1094 testcase.attrib[
'name'] =
'errors' 1095 error = xml.etree.ElementTree.SubElement(testcase,
'error')
1097 if num_failures > 0:
1099 failed_file_order = []
1100 failures_by_file = {}
1102 failed_file = failure[0]
1103 if failed_file
not in failed_file_order:
1104 failed_file_order.append(failed_file)
1105 failures_by_file[failed_file] = []
1106 failures_by_file[failed_file].append(failure)
1108 for failed_file
in failed_file_order:
1109 failures = failures_by_file[failed_file]
1110 testcase = xml.etree.ElementTree.SubElement(testsuite,
'testcase')
1111 testcase.attrib[
'name'] = failed_file
1112 failure = xml.etree.ElementTree.SubElement(testcase,
'failure')
1113 template =
'{0}: {1} [{2}] [{3}]' 1114 texts = [template.format(f[1], f[2], f[3], f[4])
for f
in failures]
1115 failure.text =
'\n'.join(texts)
1117 xml_decl =
'<?xml version="1.0" encoding="UTF-8" ?>\n' 1118 return xml_decl + xml.etree.ElementTree.tostring(testsuite,
'utf-8').decode(
'utf-8')
1125 """Gets the module's output format.""" 1126 return _cpplint_state.output_format
1130 """Sets the module's output format.""" 1131 _cpplint_state.SetOutputFormat(output_format)
1135 """Returns the module's verbosity setting.""" 1136 return _cpplint_state.verbose_level
1140 """Sets the module's verbosity, and returns the previous setting.""" 1141 return _cpplint_state.SetVerboseLevel(level)
1145 """Sets the module's counting options.""" 1146 _cpplint_state.SetCountingStyle(level)
1150 """Returns the module's list of output filters, as a list.""" 1151 return _cpplint_state.filters
1155 """Sets the module's error-message filters. 1157 These filters are applied when deciding whether to emit a given 1161 filters: A string of comma-separated filters (eg "whitespace/indent"). 1162 Each filter should start with + or -; else we die. 1164 _cpplint_state.SetFilters(filters)
1167 """Adds more filter overrides. 1169 Unlike _SetFilters, this function does not reset the current list of filters 1173 filters: A string of comma-separated filters (eg "whitespace/indent"). 1174 Each filter should start with + or -; else we die. 1176 _cpplint_state.AddFilters(filters)
1179 """ Saves the current filter list to backup storage.""" 1180 _cpplint_state.BackupFilters()
1183 """ Restores filters previously backed up.""" 1184 _cpplint_state.RestoreFilters()
1187 """Tracks current function name and the number of lines in its body.""" 1189 _NORMAL_TRIGGER = 250
1198 """Start analyzing function body. 1201 function_name: The name of the function being tracked. 1208 """Count line in current function body.""" 1212 def Check(self, error, filename, linenum):
1213 """Report if too many lines in function body. 1216 error: The function to call with any errors found. 1217 filename: The name of the current file. 1218 linenum: The number of the line to check. 1234 error(filename, linenum,
'readability/fn_size', error_level,
1235 'Small and focused functions are preferred:' 1236 ' %s has %d non-comment lines' 1237 ' (error triggered by exceeding %d lines).' % (
1241 """Stop analyzing function body.""" 1246 """Indicates a problem with the include order in a file.""" 1250 class FileInfo(object):
1251 """Provides utility functions for filenames. 1253 FileInfo provides easy access to the components of a file's path 1254 relative to the project root. 1261 """Make Windows paths like Unix.""" 1262 return os.path.abspath(self.
_filename).replace(
'\\',
'/')
1265 r"""FullName after removing the local path to the repository. 1267 If we have a real absolute path name here we can try to do something smart: 1268 detecting the root of the checkout and truncating /path/to/checkout from 1269 the name so that we get header guards that don't include things like 1270 "C:\Documents and Settings\..." or "/home/username/..." in them and thus 1271 people on different computers who have checked the source out to different 1272 locations won't see bogus errors. 1276 if os.path.exists(fullname):
1277 project_dir = os.path.dirname(fullname)
1283 root_dir = project_dir
1284 while os.path.exists(root_dir):
1286 if os.path.normcase(root_dir) == os.path.normcase(repo):
1287 return os.path.relpath(fullname, root_dir).replace(
'\\',
'/')
1288 one_up_dir = os.path.dirname(root_dir)
1289 if one_up_dir == root_dir:
1291 root_dir = one_up_dir
1293 if os.path.exists(os.path.join(project_dir,
".svn")):
1296 root_dir = project_dir
1297 one_up_dir = os.path.dirname(root_dir)
1298 while os.path.exists(os.path.join(one_up_dir,
".svn")):
1299 root_dir = os.path.dirname(root_dir)
1300 one_up_dir = os.path.dirname(one_up_dir)
1302 prefix = os.path.commonprefix([root_dir, project_dir])
1303 return fullname[
len(prefix) + 1:]
1307 root_dir = current_dir = os.path.dirname(fullname)
1308 while current_dir != os.path.dirname(current_dir):
1309 if (os.path.exists(os.path.join(current_dir,
".git"))
or 1310 os.path.exists(os.path.join(current_dir,
".hg"))
or 1311 os.path.exists(os.path.join(current_dir,
".svn"))):
1312 root_dir = current_dir
1314 current_dir = os.path.dirname(current_dir)
1316 if (os.path.exists(os.path.join(root_dir,
".git"))
or 1317 os.path.exists(os.path.join(root_dir,
".hg"))
or 1318 os.path.exists(os.path.join(root_dir,
".svn"))):
1319 prefix = os.path.commonprefix([root_dir, project_dir])
1320 return fullname[
len(prefix) + 1:]
1326 """Splits the file into the directory, basename, and extension. 1328 For 'chrome/browser/browser.cc', Split() would 1329 return ('chrome/browser', 'browser', '.cc') 1332 A tuple of (directory, basename, extension). 1336 project, rest = os.path.split(googlename)
1337 return (project,) + os.path.splitext(rest)
1340 """File base name - text after the final slash, before the final period.""" 1341 return self.
Split()[1]
1344 """File extension - text following the final period, includes that period.""" 1345 return self.
Split()[2]
1348 """File has no source file extension.""" 1349 return '/'.join(self.
Split()[0:2])
1352 """File has a source file extension.""" 1357 """If confidence >= verbose, category passes filter and is not suppressed.""" 1365 if confidence < _cpplint_state.verbose_level:
1370 if one_filter.startswith(
'-'):
1371 if category.startswith(one_filter[1:]):
1373 elif one_filter.startswith(
'+'):
1374 if category.startswith(one_filter[1:]):
1384 def Error(filename, linenum, category, confidence, message):
1385 """Logs the fact we've found a lint error. 1387 We log where the error was found, and also our confidence in the error, 1388 that is, how certain we are this is a legitimate style regression, and 1389 not a misidentification or a use that's sometimes justified. 1391 False positives can be suppressed by the use of 1392 "cpplint(category)" comments on the offending line. These are 1393 parsed into _error_suppressions. 1396 filename: The name of the file containing the error. 1397 linenum: The number of the line containing the error. 1398 category: A string used to describe the "category" this bug 1399 falls under: "whitespace", say, or "runtime". Categories 1400 may have a hierarchy separated by slashes: "whitespace/indent". 1401 confidence: A number from 1-5 representing a confidence score for 1402 the error, with 5 meaning that we are certain of the problem, 1403 and 1 meaning that it could be a legitimate construct. 1404 message: The error message. 1407 _cpplint_state.IncrementErrorCount(category)
1408 if _cpplint_state.output_format ==
'vs7':
1409 _cpplint_state.PrintError(
'%s(%s): warning: %s [%s] [%d]\n' % (
1410 filename, linenum, message, category, confidence))
1411 elif _cpplint_state.output_format ==
'eclipse':
1412 sys.stderr.write(
'%s:%s: warning: %s [%s] [%d]\n' % (
1413 filename, linenum, message, category, confidence))
1414 elif _cpplint_state.output_format ==
'junit':
1415 _cpplint_state.AddJUnitFailure(filename, linenum, message, category,
1418 final_message =
'%s:%s: %s [%s] [%d]\n' % (
1419 filename, linenum, message, category, confidence)
1420 sys.stderr.write(final_message)
1423 _RE_PATTERN_CLEANSE_LINE_ESCAPES = re.compile(
1424 r'\\([abfnrtv?"\\\']|\d+|x[0-9a-fA-F]+)')
1426 _RE_PATTERN_C_COMMENTS =
r'/\*(?:[^*]|\*(?!/))*\*/' 1435 _RE_PATTERN_CLEANSE_LINE_C_COMMENTS = re.compile(
1436 r'(\s*' + _RE_PATTERN_C_COMMENTS +
r'\s*$|' +
1437 _RE_PATTERN_C_COMMENTS +
r'\s+|' +
1438 r'\s+' + _RE_PATTERN_C_COMMENTS +
r'(?=\W)|' +
1439 _RE_PATTERN_C_COMMENTS +
r')')
1443 """Does line terminate so, that the next symbol is in string constant. 1445 This function does not consider single-line nor multi-line comments. 1448 line: is a partial line of code starting from the 0..n. 1451 True, if next character appended to 'line' is inside a 1455 line = line.replace(
r'\\',
'XX')
1456 return ((line.count(
'"') - line.count(
r'\"') - line.count(
"'\"'")) & 1) == 1
1460 """Removes C++11 raw strings from lines. 1463 static const char kData[] = R"( 1468 static const char kData[] = "" 1469 (replaced by blank line) 1473 raw_lines: list of raw lines. 1476 list of lines with C++11 raw strings replaced by empty strings. 1480 lines_without_raw_strings = []
1481 for line
in raw_lines:
1484 end = line.find(delimiter)
1489 leading_space =
Match(
r'^(\s*)\S', line)
1490 line = leading_space.group(1) +
'""' + line[end +
len(delimiter):]
1499 while delimiter
is None:
1510 matched =
Match(
r'^(.*?)\b(?:R|u8R|uR|UR|LR)"([^\s\\()]*)\((.*)$', line)
1512 not Match(
r'^([^\'"]|\'(\\.|[^\'])*\'|"(\\.|[^"])*")*//',
1514 delimiter =
')' + matched.group(2) +
'"' 1516 end = matched.group(3).find(delimiter)
1519 line = (matched.group(1) +
'""' +
1520 matched.group(3)[end +
len(delimiter):])
1524 line = matched.group(1) +
'""' 1528 lines_without_raw_strings.append(line)
1532 return lines_without_raw_strings
1536 """Find the beginning marker for a multiline comment.""" 1537 while lineix <
len(lines):
1538 if lines[lineix].strip().startswith(
'/*'):
1540 if lines[lineix].strip().find(
'*/', 2) < 0:
1547 """We are inside a comment, find the end marker.""" 1548 while lineix <
len(lines):
1549 if lines[lineix].strip().endswith(
'*/'):
1556 """Clears a range of lines for multi-line comments.""" 1559 for i
in range(begin, end):
1564 """Removes multiline (c-style) comments from lines.""" 1566 while lineix <
len(lines):
1568 if lineix_begin >=
len(lines):
1571 if lineix_end >=
len(lines):
1572 error(filename, lineix_begin + 1,
'readability/multiline_comment', 5,
1573 'Could not find end of multi-line comment')
1576 lineix = lineix_end + 1
1580 """Removes //-comments and single-line C-style /* */ comments. 1583 line: A line of C++ source. 1586 The line with single-line comments removed. 1588 commentpos = line.find(
'//')
1589 if commentpos != -1
and not IsCppString(line[:commentpos]):
1590 line = line[:commentpos].rstrip()
1592 return _RE_PATTERN_CLEANSE_LINE_C_COMMENTS.sub(
'', line)
1596 """Holds 4 copies of all lines with different preprocessing applied to them. 1598 1) elided member contains lines without strings and comments. 1599 2) lines member contains lines without comments. 1600 3) raw_lines member contains all the lines without processing. 1601 4) lines_without_raw_strings member is same as raw_lines, but with C++11 raw 1603 All these members are of <type 'list'>, and of the same length. 1619 """Returns the number of lines represented.""" 1624 """Collapses strings and chars on a line to simple "" or '' blocks. 1626 We nix strings first so we're not fooled by text like '"http://"' 1629 elided: The line being processed. 1632 The line with collapsed strings. 1634 if _RE_PATTERN_INCLUDE.match(elided):
1640 elided = _RE_PATTERN_CLEANSE_LINE_ESCAPES.sub(
'', elided)
1648 match =
Match(
r'^([^\'"]*)([\'"])(.*)$', elided)
1652 head, quote, tail = match.groups()
1656 second_quote = tail.find(
'"')
1657 if second_quote >= 0:
1658 collapsed += head +
'""' 1659 elided = tail[second_quote + 1:]
1673 if Search(
r'\b(?:0[bBxX]?|[1-9])[0-9a-fA-F]*$', head):
1674 match_literal =
Match(
r'^((?:\'?[0-9a-zA-Z_])*)(.*)$',
"'" + tail)
1675 collapsed += head + match_literal.group(1).replace(
"'",
'')
1676 elided = match_literal.group(2)
1678 second_quote = tail.find(
'\'')
1679 if second_quote >= 0:
1680 collapsed += head +
"''" 1681 elided = tail[second_quote + 1:]
1691 """Find the position just after the end of current parenthesized expression. 1694 line: a CleansedLines line. 1695 startpos: start searching at this position. 1696 stack: nesting stack at startpos. 1699 On finding matching end: (index just after matching end, None) 1700 On finding an unclosed expression: (-1, None) 1701 Otherwise: (-1, new stack at end of this line) 1710 if i > 0
and line[i - 1] ==
'<':
1712 if stack
and stack[-1] ==
'<':
1716 elif i > 0
and Search(
r'\boperator\s*$', line[0:i]):
1727 while stack
and stack[-1] ==
'<':
1731 if ((stack[-1] ==
'(' and char ==
')')
or 1732 (stack[-1] ==
'[' and char ==
']')
or 1733 (stack[-1] ==
'{' and char ==
'}')):
1736 return (i + 1,
None)
1745 (line[i - 1] ==
'-' or Search(
r'\boperator\s*$', line[0:i - 1]))):
1751 if stack[-1] ==
'<':
1754 return (i + 1,
None)
1759 while stack
and stack[-1] ==
'<':
1769 """If input points to ( or { or [ or <, finds the position that closes it. 1771 If lines[linenum][pos] points to a '(' or '{' or '[' or '<', finds the 1772 linenum/pos that correspond to the closing of the expression. 1774 TODO(unknown): cpplint spends a fair bit of time matching parentheses. 1775 Ideally we would want to index all opening and closing parentheses once 1776 and have CloseExpression be just a simple lookup, but due to preprocessor 1777 tricks, this is not so easy. 1780 clean_lines: A CleansedLines instance containing the file. 1781 linenum: The number of the line to check. 1782 pos: A position on the line. 1785 A tuple (line, linenum, pos) pointer *past* the closing brace, or 1786 (line, len(lines), -1) if we never find a close. Note we ignore 1787 strings and comments when matching; and the line we return is the 1788 'cleansed' line at linenum. 1791 line = clean_lines.elided[linenum]
1792 if (line[pos]
not in '({[<')
or Match(
r'<[<=]', line[pos:]):
1793 return (line, clean_lines.NumLines(), -1)
1798 return (line, linenum, end_pos)
1801 while stack
and linenum < clean_lines.NumLines() - 1:
1803 line = clean_lines.elided[linenum]
1806 return (line, linenum, end_pos)
1809 return (line, clean_lines.NumLines(), -1)
1813 """Find position at the matching start of current expression. 1815 This is almost the reverse of FindEndOfExpressionInLine, but note 1816 that the input position and returned position differs by 1. 1819 line: a CleansedLines line. 1820 endpos: start searching at this position. 1821 stack: nesting stack at endpos. 1824 On finding matching start: (index at matching start, None) 1825 On finding an unclosed expression: (-1, None) 1826 Otherwise: (-1, new stack at beginning of this line) 1839 (line[i - 1] ==
'-' or 1840 Match(
r'\s>=\s', line[i - 1:])
or 1841 Search(
r'\boperator\s*$', line[0:i]))):
1847 if i > 0
and line[i - 1] ==
'<':
1853 if stack
and stack[-1] ==
'>':
1862 while stack
and stack[-1] ==
'>':
1866 if ((char ==
'(' and stack[-1] ==
')')
or 1867 (char ==
'[' and stack[-1] ==
']')
or 1868 (char ==
'{' and stack[-1] ==
'}')):
1879 while stack
and stack[-1] ==
'>':
1890 """If input points to ) or } or ] or >, finds the position that opens it. 1892 If lines[linenum][pos] points to a ')' or '}' or ']' or '>', finds the 1893 linenum/pos that correspond to the opening of the expression. 1896 clean_lines: A CleansedLines instance containing the file. 1897 linenum: The number of the line to check. 1898 pos: A position on the line. 1901 A tuple (line, linenum, pos) pointer *at* the opening brace, or 1902 (line, 0, -1) if we never find the matching opening brace. Note 1903 we ignore strings and comments when matching; and the line we 1904 return is the 'cleansed' line at linenum. 1906 line = clean_lines.elided[linenum]
1907 if line[pos]
not in ')}]>':
1908 return (line, 0, -1)
1913 return (line, linenum, start_pos)
1916 while stack
and linenum > 0:
1918 line = clean_lines.elided[linenum]
1921 return (line, linenum, start_pos)
1924 return (line, 0, -1)
1928 """Logs an error if no Copyright message appears at the top of the file.""" 1932 for line
in range(1,
min(
len(lines), 11)):
1933 if re.search(
r'Copyright', lines[line], re.I):
break 1935 error(filename, 0,
'legal/copyright', 5,
1936 'No copyright message found. ' 1937 'You should have a line: "Copyright [year] <Copyright Owner>"')
1941 """Return the number of leading spaces in line. 1944 line: A string to check. 1947 An integer count of leading spaces, possibly zero. 1949 indent =
Match(
r'^( *)\S', line)
1951 return len(indent.group(1))
1957 """Returns the CPP variable that should be used as a header guard. 1960 filename: The name of a C++ header file. 1963 The CPP variable that should be used as a header guard in the 1970 filename = re.sub(
r'_flymake\.h$',
'.h', filename)
1971 filename = re.sub(
r'/\.flymake/([^/]*)$',
r'/\1', filename)
1973 filename = filename.replace(
'C++',
'cpp').replace(
'c++',
'cpp')
1976 file_path_from_root = fileinfo.RepositoryName()
1983 file_path_from_root = re.sub(
'^' + _root + suffix,
'', file_path_from_root)
1984 return re.sub(
r'[^a-zA-Z0-9]',
'_', file_path_from_root).
upper() +
'_' 1988 """Checks that the file contains a header guard. 1990 Logs an error if no #ifndef header guard is present. For other 1991 headers, checks that the full pathname is used. 1994 filename: The name of the C++ header file. 1995 clean_lines: A CleansedLines instance containing the file. 1996 error: The function to call with any errors found. 2005 raw_lines = clean_lines.lines_without_raw_strings
2007 if Search(
r'//\s*NOLINT\(build/header_guard\)', i):
2012 if Search(
r'^\s*#pragma\s+once', i):
2022 for linenum, line
in enumerate(raw_lines):
2023 linesplit = line.split()
2024 if len(linesplit) >= 2:
2026 if not ifndef
and linesplit[0] ==
'#ifndef':
2028 ifndef = linesplit[1]
2029 ifndef_linenum = linenum
2030 if not define
and linesplit[0] ==
'#define':
2031 define = linesplit[1]
2033 if line.startswith(
'#endif'):
2035 endif_linenum = linenum
2037 if not ifndef
or not define
or ifndef != define:
2038 error(filename, 0,
'build/header_guard', 5,
2039 'No #ifndef header guard found, suggested CPP variable is: %s' %
2045 if ifndef != cppvar:
2047 if ifndef != cppvar +
'_':
2052 error(filename, ifndef_linenum,
'build/header_guard', error_level,
2053 '#ifndef header guard has wrong style, please use: %s' % cppvar)
2058 match =
Match(
r'#endif\s*//\s*' + cppvar +
r'(_)?\b', endif)
2060 if match.group(1) ==
'_':
2062 error(filename, endif_linenum,
'build/header_guard', 0,
2063 '#endif line should be "#endif // %s"' % cppvar)
2069 no_single_line_comments =
True 2072 if Match(
r'^(?:(?:\'(?:\.|[^\'])*\')|(?:"(?:\.|[^"])*")|[^\'"])*//', line):
2073 no_single_line_comments =
False 2076 if no_single_line_comments:
2077 match =
Match(
r'#endif\s*/\*\s*' + cppvar +
r'(_)?\s*\*/', endif)
2079 if match.group(1) ==
'_':
2081 error(filename, endif_linenum,
'build/header_guard', 0,
2082 '#endif line should be "#endif /* %s */"' % cppvar)
2086 error(filename, endif_linenum,
'build/header_guard', 5,
2087 '#endif line should be "#endif // %s"' % cppvar)
2091 """Logs an error if a source file does not include its header.""" 2095 if Search(_TEST_FILE_SUFFIX, fileinfo.BaseName()):
2099 basefilename = filename[0:
len(filename) -
len(fileinfo.Extension())]
2100 headerfile = basefilename +
'.' + ext
2101 if not os.path.exists(headerfile):
2103 headername =
FileInfo(headerfile).RepositoryName()
2104 first_include =
None 2105 for section_list
in include_state.include_list:
2106 for f
in section_list:
2107 if headername
in f[0]
or f[0]
in headername:
2109 if not first_include:
2110 first_include = f[1]
2112 error(filename, first_include,
'build/include', 5,
2113 '%s should include its header file %s' % (fileinfo.RepositoryName(),
2118 """Logs an error for each line containing bad characters. 2120 Two kinds of bad characters: 2122 1. Unicode replacement characters: These indicate that either the file 2123 contained invalid UTF-8 (likely) or Unicode replacement characters (which 2124 it shouldn't). Note that it's possible for this to throw off line 2125 numbering if the invalid UTF-8 occurred adjacent to a newline. 2127 2. NUL bytes. These are problematic for some tools. 2130 filename: The name of the current file. 2131 lines: An array of strings, each representing a line of the file. 2132 error: The function to call with any errors found. 2134 for linenum, line
in enumerate(lines):
2136 error(filename, linenum,
'readability/utf8', 5,
2137 'Line contains invalid UTF-8 (or Unicode replacement character).')
2139 error(filename, linenum,
'readability/nul', 5,
'Line contains NUL byte.')
2143 """Logs an error if there is no newline char at the end of the file. 2146 filename: The name of the current file. 2147 lines: An array of strings, each representing a line of the file. 2148 error: The function to call with any errors found. 2155 if len(lines) < 3
or lines[-2]:
2156 error(filename,
len(lines) - 2,
'whitespace/ending_newline', 5,
2157 'Could not find a newline character at the end of the file.')
2161 """Logs an error if we see /* ... */ or "..." that extend past one line. 2163 /* ... */ comments are legit inside macros, for one line. 2164 Otherwise, we prefer // comments, so it's ok to warn about the 2165 other. Likewise, it's ok for strings to extend across multiple 2166 lines, as long as a line continuation character (backslash) 2167 terminates each line. Although not currently prohibited by the C++ 2168 style guide, it's ugly and unnecessary. We don't do well with either 2169 in this lint program, so we warn about both. 2172 filename: The name of the current file. 2173 clean_lines: A CleansedLines instance containing the file. 2174 linenum: The number of the line to check. 2175 error: The function to call with any errors found. 2177 line = clean_lines.elided[linenum]
2181 line = line.replace(
'\\\\',
'')
2183 if line.count(
'/*') > line.count(
'*/'):
2184 error(filename, linenum,
'readability/multiline_comment', 5,
2185 'Complex multi-line /*...*/-style comment found. ' 2186 'Lint may give bogus warnings. ' 2187 'Consider replacing these with //-style comments, ' 2188 'with #if 0...#endif, ' 2189 'or with more clearly structured multi-line comments.')
2191 if (line.count(
'"') - line.count(
'\\"')) % 2:
2192 error(filename, linenum,
'readability/multiline_string', 5,
2193 'Multi-line string ("...") found. This lint script doesn\'t ' 2194 'do well with such strings, and may give bogus warnings. ' 2195 'Use C++11 raw strings or concatenation instead.')
2210 _UNSAFE_FUNC_PREFIX =
r'(?:[-+*/=%^&|(<]\s*|>\s+)' 2212 (
'asctime(',
'asctime_r(', _UNSAFE_FUNC_PREFIX +
r'asctime\([^)]+\)'),
2213 (
'ctime(',
'ctime_r(', _UNSAFE_FUNC_PREFIX +
r'ctime\([^)]+\)'),
2214 (
'getgrgid(',
'getgrgid_r(', _UNSAFE_FUNC_PREFIX +
r'getgrgid\([^)]+\)'),
2215 (
'getgrnam(',
'getgrnam_r(', _UNSAFE_FUNC_PREFIX +
r'getgrnam\([^)]+\)'),
2216 (
'getlogin(',
'getlogin_r(', _UNSAFE_FUNC_PREFIX +
r'getlogin\(\)'),
2217 (
'getpwnam(',
'getpwnam_r(', _UNSAFE_FUNC_PREFIX +
r'getpwnam\([^)]+\)'),
2218 (
'getpwuid(',
'getpwuid_r(', _UNSAFE_FUNC_PREFIX +
r'getpwuid\([^)]+\)'),
2219 (
'gmtime(',
'gmtime_r(', _UNSAFE_FUNC_PREFIX +
r'gmtime\([^)]+\)'),
2220 (
'localtime(',
'localtime_r(', _UNSAFE_FUNC_PREFIX +
r'localtime\([^)]+\)'),
2221 (
'rand(',
'rand_r(', _UNSAFE_FUNC_PREFIX +
r'rand\(\)'),
2222 (
'strtok(',
'strtok_r(',
2223 _UNSAFE_FUNC_PREFIX +
r'strtok\([^)]+\)'),
2224 (
'ttyname(',
'ttyname_r(', _UNSAFE_FUNC_PREFIX +
r'ttyname\([^)]+\)'),
2229 """Checks for calls to thread-unsafe functions. 2231 Much code has been originally written without consideration of 2232 multi-threading. Also, engineers are relying on their old experience; 2233 they have learned posix before threading extensions were added. These 2234 tests guide the engineers to use thread-safe functions (when using 2238 filename: The name of the current file. 2239 clean_lines: A CleansedLines instance containing the file. 2240 linenum: The number of the line to check. 2241 error: The function to call with any errors found. 2243 line = clean_lines.elided[linenum]
2244 for single_thread_func, multithread_safe_func, pattern
in _THREADING_LIST:
2247 if Search(pattern, line):
2248 error(filename, linenum,
'runtime/threadsafe_fn', 2,
2249 'Consider using ' + multithread_safe_func +
2250 '...) instead of ' + single_thread_func +
2251 '...) for improved thread safety.')
2255 """Checks that VLOG() is only used for defining a logging level. 2257 For example, VLOG(2) is correct. VLOG(INFO), VLOG(WARNING), VLOG(ERROR), and 2258 VLOG(FATAL) are not. 2261 filename: The name of the current file. 2262 clean_lines: A CleansedLines instance containing the file. 2263 linenum: The number of the line to check. 2264 error: The function to call with any errors found. 2266 line = clean_lines.elided[linenum]
2267 if Search(
r'\bVLOG\((INFO|ERROR|WARNING|DFATAL|FATAL)\)', line):
2268 error(filename, linenum,
'runtime/vlog', 5,
2269 'VLOG() should be used with numeric verbosity level. ' 2270 'Use LOG() if you want symbolic severity levels.')
2274 _RE_PATTERN_INVALID_INCREMENT = re.compile(
2275 r'^\s*\*\w+(\+\+|--);')
2279 """Checks for invalid increment *count++. 2281 For example following function: 2282 void increment_counter(int* count) { 2285 is invalid, because it effectively does count++, moving pointer, and should 2286 be replaced with ++*count, (*count)++ or *count += 1. 2289 filename: The name of the current file. 2290 clean_lines: A CleansedLines instance containing the file. 2291 linenum: The number of the line to check. 2292 error: The function to call with any errors found. 2294 line = clean_lines.elided[linenum]
2295 if _RE_PATTERN_INVALID_INCREMENT.match(line):
2296 error(filename, linenum,
'runtime/invalid_increment', 5,
2297 'Changing pointer instead of value (or unused value of operator*).')
2301 if Search(
r'^#define', clean_lines[linenum]):
2304 if linenum > 0
and Search(
r'\\$', clean_lines[linenum - 1]):
2311 return Match(
r'^\s*(\btemplate\b)*.*class\s+\w+;\s*$', clean_lines[linenum])
2315 """Stores information about a generic block of code.""" 2325 """Run checks that applies to text up to the opening brace. 2327 This is mostly for checking the text after the class identifier 2328 and the "{", usually where the base class is specified. For other 2329 blocks, there isn't much to check, so we always pass. 2332 filename: The name of the current file. 2333 clean_lines: A CleansedLines instance containing the file. 2334 linenum: The number of the line to check. 2335 error: The function to call with any errors found. 2339 def CheckEnd(self, filename, clean_lines, linenum, error):
2340 """Run checks that applies to text after the closing brace. 2342 This is mostly used for checking end of namespace comments. 2345 filename: The name of the current file. 2346 clean_lines: A CleansedLines instance containing the file. 2347 linenum: The number of the line to check. 2348 error: The function to call with any errors found. 2353 """Returns true if this block is a _BlockInfo. 2355 This is convenient for verifying that an object is an instance of 2356 a _BlockInfo, but not an instance of any of the derived classes. 2359 True for this class, False for derived classes. 2361 return self.__class__ == _BlockInfo
2365 """Stores information about an 'extern "C"' block.""" 2368 _BlockInfo.__init__(self, linenum,
True)
2372 """Stores information about a class.""" 2374 def __init__(self, name, class_or_struct, clean_lines, linenum):
2375 _BlockInfo.__init__(self, linenum,
False)
2379 if class_or_struct ==
'struct':
2397 for i
in range(linenum, clean_lines.NumLines()):
2398 line = clean_lines.elided[i]
2399 depth += line.count(
'{') - line.count(
'}')
2406 if Search(
'(^|[^:]):($|[^:])', clean_lines.elided[linenum]):
2409 def CheckEnd(self, filename, clean_lines, linenum, error):
2412 seen_last_thing_in_class =
False 2415 r'\b(DISALLOW_COPY_AND_ASSIGN|DISALLOW_IMPLICIT_CONSTRUCTORS)\(' +
2417 clean_lines.elided[i])
2419 if seen_last_thing_in_class:
2420 error(filename, i,
'readability/constructors', 3,
2421 match.group(1) +
' should be the last thing in the class')
2424 if not Match(
r'^\s*$', clean_lines.elided[i]):
2425 seen_last_thing_in_class =
True 2430 indent =
Match(
r'^( *)\}', clean_lines.elided[linenum])
2433 parent =
'struct ' + self.
name 2435 parent =
'class ' + self.
name 2436 error(filename, linenum,
'whitespace/indent', 3,
2437 'Closing brace should be aligned with beginning of %s' % parent)
2441 """Stores information about a namespace.""" 2444 _BlockInfo.__init__(self, linenum,
False)
2445 self.
name = name
or '' 2448 def CheckEnd(self, filename, clean_lines, linenum, error):
2449 """Check end of namespace comments.""" 2450 line = clean_lines.raw_lines[linenum]
2464 and not Match(
r'^\s*};*\s*(//|/\*).*\bnamespace\b', line)):
2481 if not Match((
r'^\s*};*\s*(//|/\*).*\bnamespace\s+' +
2482 re.escape(self.
name) +
r'[\*/\.\\\s]*$'),
2484 error(filename, linenum,
'readability/namespace', 5,
2485 'Namespace should be terminated with "// namespace %s"' %
2489 if not Match(
r'^\s*};*\s*(//|/\*).*\bnamespace[\*/\.\\\s]*$', line):
2492 if Match(
r'^\s*}.*\b(namespace anonymous|anonymous namespace)\b', line):
2493 error(filename, linenum,
'readability/namespace', 5,
2494 'Anonymous namespace should be terminated with "// namespace"' 2495 ' or "// anonymous namespace"')
2497 error(filename, linenum,
'readability/namespace', 5,
2498 'Anonymous namespace should be terminated with "// namespace"')
2502 """Stores checkpoints of nesting stacks when #if/#else is seen.""" 2516 """Holds states related to parsing braces.""" 2542 """Check if we have seen the opening brace for the innermost block. 2545 True if we have seen the opening brace, False if the innermost 2546 block is still expecting an opening brace. 2548 return (
not self.
stack)
or self.
stack[-1].seen_open_brace
2551 """Check if we are currently one level inside a namespace body. 2554 True if top of the stack is a namespace block, False otherwise. 2556 return self.
stack and isinstance(self.
stack[-1], _NamespaceInfo)
2559 """Check if we are currently one level inside an 'extern "C"' block. 2562 True if top of the stack is an extern block, False otherwise. 2564 return self.
stack and isinstance(self.
stack[-1], _ExternCInfo)
2567 """Check if we are currently one level inside a class or struct declaration. 2570 True if top of the stack is a class/struct, False otherwise. 2572 return self.
stack and isinstance(self.
stack[-1], _ClassInfo)
2575 """Check if we are currently one level inside an inline ASM block. 2578 True if the top of the stack is a block containing inline ASM. 2580 return self.
stack and self.
stack[-1].inline_asm != _NO_ASM
2583 """Check if current position is inside template argument list. 2586 clean_lines: A CleansedLines instance containing the file. 2587 linenum: The number of the line to check. 2588 pos: position just after the suspected template argument. 2590 True if (linenum, pos) is inside template arguments. 2592 while linenum < clean_lines.NumLines():
2594 line = clean_lines.elided[linenum]
2595 match =
Match(
r'^[^{};=\[\]\.<>]*(.)', line[pos:])
2600 token = match.group(1)
2601 pos +=
len(match.group(0))
2606 if token
in (
'{',
'}',
';'):
return False 2613 if token
in (
'>',
'=',
'[',
']',
'.'):
return True 2619 if pos >=
len(line):
2626 (_, end_line, end_pos) =
CloseExpression(clean_lines, linenum, pos - 1)
2635 """Update preprocessor stack. 2637 We need to handle preprocessors due to classes like this: 2639 struct ResultDetailsPageElementExtensionPoint { 2641 struct ResultDetailsPageElementExtensionPoint : public Extension { 2644 We make the following assumptions (good enough for most files): 2645 - Preprocessor condition evaluates to true from #if up to first 2648 - Preprocessor condition evaluates to false from #else/#elif up 2649 to #endif. We still perform lint checks on these lines, but 2650 these do not affect nesting stack. 2653 line: current line to check. 2655 if Match(
r'^\s*#\s*(if|ifdef|ifndef)\b', line):
2659 elif Match(
r'^\s*#\s*(else|elif)\b', line):
2662 if not self.
pp_stack[-1].seen_else:
2667 self.
pp_stack[-1].stack_before_else = copy.deepcopy(self.
stack)
2670 self.
stack = copy.deepcopy(self.
pp_stack[-1].stack_before_if)
2674 elif Match(
r'^\s*#\s*endif\b', line):
2691 def Update(self, filename, clean_lines, linenum, error):
2692 """Update nesting state with current line. 2695 filename: The name of the current file. 2696 clean_lines: A CleansedLines instance containing the file. 2697 linenum: The number of the line to check. 2698 error: The function to call with any errors found. 2700 line = clean_lines.elided[linenum]
2718 inner_block = self.
stack[-1]
2719 depth_change = line.count(
'(') - line.count(
')')
2720 inner_block.open_parentheses += depth_change
2723 if inner_block.inline_asm
in (_NO_ASM, _END_ASM):
2724 if (depth_change != 0
and 2725 inner_block.open_parentheses == 1
and 2726 _MATCH_ASM.match(line)):
2728 inner_block.inline_asm = _INSIDE_ASM
2732 inner_block.inline_asm = _NO_ASM
2733 elif (inner_block.inline_asm == _INSIDE_ASM
and 2734 inner_block.open_parentheses == 0):
2736 inner_block.inline_asm = _END_ASM
2746 namespace_decl_match =
Match(
r'^\s*namespace\b\s*([:\w]+)?(.*)$', line)
2747 if not namespace_decl_match:
2750 new_namespace =
_NamespaceInfo(namespace_decl_match.group(1), linenum)
2751 self.
stack.append(new_namespace)
2753 line = namespace_decl_match.group(2)
2754 if line.find(
'{') != -1:
2755 new_namespace.seen_open_brace =
True 2756 line = line[line.find(
'{') + 1:]
2763 class_decl_match =
Match(
2764 r'^(\s*(?:template\s*<[\w\s<>,:=]*>\s*)?' 2765 r'(class|struct)\s+(?:[A-Z_]+\s+)*(\w+(?:::\w+)*))' 2767 if (class_decl_match
and 2768 (
not self.
stack or self.
stack[-1].open_parentheses == 0)):
2778 end_declaration =
len(class_decl_match.group(1))
2781 class_decl_match.group(3), class_decl_match.group(2),
2782 clean_lines, linenum))
2783 line = class_decl_match.group(4)
2788 self.
stack[-1].CheckBegin(filename, clean_lines, linenum, error)
2791 if self.
stack and isinstance(self.
stack[-1], _ClassInfo):
2792 classinfo = self.
stack[-1]
2793 access_match =
Match(
2794 r'^(.*)\b(public|private|protected|signals)(\s+(?:slots\s*)?)?' 2798 classinfo.access = access_match.group(2)
2802 indent = access_match.group(1)
2803 if (
len(indent) != classinfo.class_indent + 1
and 2804 Match(
r'^\s*$', indent)):
2805 if classinfo.is_struct:
2806 parent =
'struct ' + classinfo.name
2808 parent =
'class ' + classinfo.name
2810 if access_match.group(3):
2811 slots = access_match.group(3)
2812 error(filename, linenum,
'whitespace/indent', 3,
2813 '%s%s: should be indented +1 space inside %s' % (
2814 access_match.group(2), slots, parent))
2819 matched =
Match(
r'^[^{;)}]*([{;)}])(.*)$', line)
2823 token = matched.group(1)
2829 self.
stack[-1].seen_open_brace =
True 2830 elif Match(
r'^extern\s*"[^"]*"\s*\{', line):
2834 if _MATCH_ASM.match(line):
2835 self.
stack[-1].inline_asm = _BLOCK_ASM
2837 elif token ==
';' or token ==
')':
2851 self.
stack[-1].CheckEnd(filename, clean_lines, linenum, error)
2853 line = matched.group(2)
2856 """Get class info on the top of the stack. 2859 A _ClassInfo object if we are inside a class, or None otherwise. 2861 for i
in range(
len(self.
stack), 0, -1):
2862 classinfo = self.
stack[i - 1]
2863 if isinstance(classinfo, _ClassInfo):
2868 """Checks that all classes and namespaces have been completely parsed. 2870 Call this when all lines in a file have been processed. 2872 filename: The name of the current file. 2873 error: The function to call with any errors found. 2878 for obj
in self.
stack:
2879 if isinstance(obj, _ClassInfo):
2880 error(filename, obj.starting_linenum,
'build/class', 5,
2881 'Failed to find complete declaration of class %s' %
2883 elif isinstance(obj, _NamespaceInfo):
2884 error(filename, obj.starting_linenum,
'build/namespaces', 5,
2885 'Failed to find complete declaration of namespace %s' %
2890 nesting_state, error):
2891 r"""Logs an error if we see certain non-ANSI constructs ignored by gcc-2. 2893 Complain about several constructs which gcc-2 accepts, but which are 2894 not standard C++. Warning about these in lint is one way to ease the 2895 transition to new compilers. 2896 - put storage class first (e.g. "static const" instead of "const static"). 2897 - "%lld" instead of %qd" in printf-type functions. 2898 - "%1$d" is non-standard in printf-type functions. 2899 - "\%" is an undefined character escape sequence. 2900 - text after #endif is not allowed. 2901 - invalid inner-style forward declaration. 2902 - >? and <? operators, and their >?= and <?= cousins. 2904 Additionally, check for constructor/destructor style violations and reference 2905 members, as it is very convenient to do so while checking for 2909 filename: The name of the current file. 2910 clean_lines: A CleansedLines instance containing the file. 2911 linenum: The number of the line to check. 2912 nesting_state: A NestingState instance which maintains information about 2913 the current stack of nested blocks being parsed. 2914 error: A callable to which errors are reported, which takes 4 arguments: 2915 filename, line number, error level, and message 2919 line = clean_lines.lines[linenum]
2921 if Search(
r'printf\s*\(.*".*%[-+ ]?\d*q', line):
2922 error(filename, linenum,
'runtime/printf_format', 3,
2923 '%q in format strings is deprecated. Use %ll instead.')
2925 if Search(
r'printf\s*\(.*".*%\d+\$', line):
2926 error(filename, linenum,
'runtime/printf_format', 2,
2927 '%N$ formats are unconventional. Try rewriting to avoid them.')
2930 line = line.replace(
'\\\\',
'')
2932 if Search(
r'("|\').*\\(%|\[|\(|{)', line):
2933 error(filename, linenum,
'build/printf_format', 3,
2934 '%, [, (, and { are undefined character escapes. Unescape them.')
2937 line = clean_lines.elided[linenum]
2939 if Search(
r'\b(const|volatile|void|char|short|int|long' 2940 r'|float|double|signed|unsigned' 2941 r'|schar|u?int8|u?int16|u?int32|u?int64)' 2942 r'\s+(register|static|extern|typedef)\b',
2944 error(filename, linenum,
'build/storage_class', 5,
2945 'Storage-class specifier (static, extern, typedef, etc) should be ' 2946 'at the beginning of the declaration.')
2948 if Match(
r'\s*#\s*endif\s*[^/\s]+', line):
2949 error(filename, linenum,
'build/endif_comment', 5,
2950 'Uncommented text after #endif is non-standard. Use a comment.')
2952 if Match(
r'\s*class\s+(\w+\s*::\s*)+\w+\s*;', line):
2953 error(filename, linenum,
'build/forward_decl', 5,
2954 'Inner-style forward declarations are invalid. Remove this line.')
2956 if Search(
r'(\w+|[+-]?\d+(\.\d*)?)\s*(<|>)\?=?\s*(\w+|[+-]?\d+)(\.\d*)?',
2958 error(filename, linenum,
'build/deprecated', 3,
2959 '>? and <? (max and min) operators are non-standard and deprecated.')
2961 if Search(
r'^\s*const\s*string\s*&\s*\w+\s*;', line):
2969 error(filename, linenum,
'runtime/member_string_references', 2,
2970 'const string& members are dangerous. It is much better to use ' 2971 'alternatives, such as pointers or simple constants.')
2976 classinfo = nesting_state.InnermostClass()
2977 if not classinfo
or not classinfo.seen_open_brace:
2982 base_classname = classinfo.name.split(
'::')[-1]
2986 explicit_constructor_match =
Match(
2987 r'\s+(?:inline\s+)?(explicit\s+)?(?:inline\s+)?%s\s*' 2988 r'\(((?:[^()]|\([^()]*\))*)\)' 2989 % re.escape(base_classname),
2992 if explicit_constructor_match:
2993 is_marked_explicit = explicit_constructor_match.group(1)
2995 if not explicit_constructor_match.group(2):
2996 constructor_args = []
2998 constructor_args = explicit_constructor_match.group(2).split(
',')
3003 while i <
len(constructor_args):
3004 constructor_arg = constructor_args[i]
3005 while (constructor_arg.count(
'<') > constructor_arg.count(
'>')
or 3006 constructor_arg.count(
'(') > constructor_arg.count(
')')):
3007 constructor_arg +=
',' + constructor_args[i + 1]
3008 del constructor_args[i + 1]
3009 constructor_args[i] = constructor_arg
3012 variadic_args = [arg
for arg
in constructor_args
if '&&...' in arg]
3013 defaulted_args = [arg
for arg
in constructor_args
if '=' in arg]
3014 noarg_constructor = (
not constructor_args
or 3016 (
len(constructor_args) == 1
and 3017 constructor_args[0].strip() ==
'void'))
3018 onearg_constructor = ((
len(constructor_args) == 1
and 3019 not noarg_constructor)
or 3021 (
len(constructor_args) >= 1
and 3022 not noarg_constructor
and 3023 len(defaulted_args) >=
len(constructor_args) - 1)
or 3025 (
len(constructor_args) <= 2
and 3026 len(variadic_args) >= 1))
3027 initializer_list_constructor = bool(
3028 onearg_constructor
and 3029 Search(
r'\bstd\s*::\s*initializer_list\b', constructor_args[0]))
3030 copy_constructor = bool(
3031 onearg_constructor
and 3032 Match(
r'(const\s+)?%s(\s*<[^>]*>)?(\s+const)?\s*(?:<\w+>\s*)?&' 3033 % re.escape(base_classname), constructor_args[0].strip()))
3035 if (
not is_marked_explicit
and 3036 onearg_constructor
and 3037 not initializer_list_constructor
and 3038 not copy_constructor):
3039 if defaulted_args
or variadic_args:
3040 error(filename, linenum,
'runtime/explicit', 5,
3041 'Constructors callable with one argument ' 3042 'should be marked explicit.')
3044 error(filename, linenum,
'runtime/explicit', 5,
3045 'Single-parameter constructors should be marked explicit.')
3046 elif is_marked_explicit
and not onearg_constructor:
3047 if noarg_constructor:
3048 error(filename, linenum,
'runtime/explicit', 5,
3049 'Zero-parameter constructors should not be marked explicit.')
3053 """Checks for the correctness of various spacing around function calls. 3056 filename: The name of the current file. 3057 clean_lines: A CleansedLines instance containing the file. 3058 linenum: The number of the line to check. 3059 error: The function to call with any errors found. 3061 line = clean_lines.elided[linenum]
3068 for pattern
in (
r'\bif\s*\((.*)\)\s*{',
3069 r'\bfor\s*\((.*)\)\s*{',
3070 r'\bwhile\s*\((.*)\)\s*[{;]',
3071 r'\bswitch\s*\((.*)\)\s*{'):
3072 match =
Search(pattern, line)
3074 fncall = match.group(1)
3091 not Search(
r'\b(if|for|while|switch|return|new|delete|catch|sizeof)\b',
3094 not Search(
r' \([^)]+\)\([^)]*(\)|,$)', fncall)
and 3096 not Search(
r' \([^)]+\)\[[^\]]+\]', fncall)):
3097 if Search(
r'\w\s*\(\s(?!\s*\\$)', fncall):
3098 error(filename, linenum,
'whitespace/parens', 4,
3099 'Extra space after ( in function call')
3100 elif Search(
r'\(\s+(?!(\s*\\)|\()', fncall):
3101 error(filename, linenum,
'whitespace/parens', 2,
3102 'Extra space after (')
3103 if (
Search(
r'\w\s+\(', fncall)
and 3104 not Search(
r'_{0,2}asm_{0,2}\s+_{0,2}volatile_{0,2}\s+\(', fncall)
and 3105 not Search(
r'#\s*define|typedef|using\s+\w+\s*=', fncall)
and 3106 not Search(
r'\w\s+\((\w+::)*\*\w+\)\(', fncall)
and 3107 not Search(
r'\bcase\s+\(', fncall)):
3110 if Search(
r'\boperator_*\b', line):
3111 error(filename, linenum,
'whitespace/parens', 0,
3112 'Extra space before ( in function call')
3114 error(filename, linenum,
'whitespace/parens', 4,
3115 'Extra space before ( in function call')
3118 if Search(
r'[^)]\s+\)\s*[^{\s]', fncall):
3121 if Search(
r'^\s+\)', fncall):
3122 error(filename, linenum,
'whitespace/parens', 2,
3123 'Closing ) should be moved to the previous line')
3125 error(filename, linenum,
'whitespace/parens', 2,
3126 'Extra space before )')
3130 """Returns true if the given line is blank. 3132 We consider a line to be blank if the line is empty or consists of 3136 line: A line of a string. 3139 True, if the given line is blank. 3141 return not line
or line.isspace()
3146 is_namespace_indent_item = (
3147 len(nesting_state.stack) > 1
and 3148 nesting_state.stack[-1].check_namespace_indentation
and 3149 isinstance(nesting_state.previous_stack_top, _NamespaceInfo)
and 3150 nesting_state.previous_stack_top == nesting_state.stack[-2])
3153 clean_lines.elided, line):
3159 function_state, error):
3160 """Reports for long function bodies. 3162 For an overview why this is done, see: 3163 https://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Write_Short_Functions 3165 Uses a simplistic algorithm assuming other style guidelines 3166 (especially spacing) are followed. 3167 Only checks unindented functions, so class members are unchecked. 3168 Trivial bodies are unchecked, so constructors with huge initializer lists 3170 Blank/comment lines are not counted so as to avoid encouraging the removal 3171 of vertical space and comments just to get through a lint check. 3172 NOLINT *on the last line of a function* disables this check. 3175 filename: The name of the current file. 3176 clean_lines: A CleansedLines instance containing the file. 3177 linenum: The number of the line to check. 3178 function_state: Current function name and lines in body so far. 3179 error: The function to call with any errors found. 3181 lines = clean_lines.lines
3182 line = lines[linenum]
3185 starting_func =
False 3186 regexp =
r'(\w(\w|::|\*|\&|\s)*)\(' 3187 match_result =
Match(regexp, line)
3191 function_name = match_result.group(1).split()[-1]
3192 if function_name ==
'TEST' or function_name ==
'TEST_F' or (
3193 not Match(
r'[A-Z_]+$', function_name)):
3194 starting_func =
True 3198 for start_linenum
in range(linenum, clean_lines.NumLines()):
3199 start_line = lines[start_linenum]
3200 joined_line +=
' ' + start_line.lstrip()
3201 if Search(
r'(;|})', start_line):
3204 elif Search(
r'{', start_line):
3206 function =
Search(
r'((\w|:)*)\(', line).group(1)
3207 if Match(
r'TEST', function):
3208 parameter_regexp =
Search(
r'(\(.*\))', joined_line)
3209 if parameter_regexp:
3210 function += parameter_regexp.group(1)
3213 function_state.Begin(function)
3217 error(filename, linenum,
'readability/fn_size', 5,
3218 'Lint failed to find start of function body.')
3219 elif Match(
r'^\}\s*$', line):
3220 function_state.Check(error, filename, linenum)
3221 function_state.End()
3222 elif not Match(
r'^\s*$', line):
3223 function_state.Count()
3226 _RE_PATTERN_TODO = re.compile(
r'^//(\s*)TODO(\(.+?\))?:?(\s|$)?')
3229 def CheckComment(line, filename, linenum, next_line_start, error):
3230 """Checks for common mistakes in comments. 3233 line: The line in question. 3234 filename: The name of the current file. 3235 linenum: The number of the line to check. 3236 next_line_start: The first non-whitespace column of the next line. 3237 error: The function to call with any errors found. 3239 commentpos = line.find(
'//')
3240 if commentpos != -1:
3242 if re.sub(
r'\\.',
'', line[0:commentpos]).count(
'"') % 2 == 0:
3244 if (
not (
Match(
r'^.*{ *//', line)
and next_line_start == commentpos)
and 3245 ((commentpos >= 1
and 3246 line[commentpos-1]
not in string.whitespace)
or 3247 (commentpos >= 2
and 3248 line[commentpos-2]
not in string.whitespace))):
3249 error(filename, linenum,
'whitespace/comments', 2,
3250 'At least two spaces is best between code and comments')
3253 comment = line[commentpos:]
3254 match = _RE_PATTERN_TODO.match(comment)
3257 leading_whitespace = match.group(1)
3258 if len(leading_whitespace) > 1:
3259 error(filename, linenum,
'whitespace/todo', 2,
3260 'Too many spaces before TODO')
3262 username = match.group(2)
3264 error(filename, linenum,
'readability/todo', 2,
3265 'Missing username in TODO; it should look like ' 3266 '"// TODO(my_username): Stuff."')
3268 middle_whitespace = match.group(3)
3270 if middle_whitespace !=
' ' and middle_whitespace !=
'':
3271 error(filename, linenum,
'whitespace/todo', 2,
3272 'TODO(my_username) should be followed by a space')
3277 if (
Match(
r'//[^ ]*\w', comment)
and 3278 not Match(
r'(///|//\!)(\s+|$)', comment)):
3279 error(filename, linenum,
'whitespace/comments', 4,
3280 'Should have a space between // and comment')
3283 def CheckAccess(filename, clean_lines, linenum, nesting_state, error):
3284 """Checks for improper use of DISALLOW* macros. 3287 filename: The name of the current file. 3288 clean_lines: A CleansedLines instance containing the file. 3289 linenum: The number of the line to check. 3290 nesting_state: A NestingState instance which maintains information about 3291 the current stack of nested blocks being parsed. 3292 error: The function to call with any errors found. 3294 line = clean_lines.elided[linenum]
3296 matched =
Match((
r'\s*(DISALLOW_COPY_AND_ASSIGN|' 3297 r'DISALLOW_IMPLICIT_CONSTRUCTORS)'), line)
3300 if nesting_state.stack
and isinstance(nesting_state.stack[-1], _ClassInfo):
3301 if nesting_state.stack[-1].access !=
'private':
3302 error(filename, linenum,
'readability/constructors', 3,
3303 '%s must be in the private: section' % matched.group(1))
3313 def CheckSpacing(filename, clean_lines, linenum, nesting_state, error):
3314 """Checks for the correctness of various spacing issues in the code. 3316 Things we check for: spaces around operators, spaces after 3317 if/for/while/switch, no spaces around parens in function calls, two 3318 spaces between code and comment, don't start a block with a blank 3319 line, don't end a function with a blank line, don't add a blank line 3320 after public/protected/private, don't have too many blank lines in a row. 3323 filename: The name of the current file. 3324 clean_lines: A CleansedLines instance containing the file. 3325 linenum: The number of the line to check. 3326 nesting_state: A NestingState instance which maintains information about 3327 the current stack of nested blocks being parsed. 3328 error: The function to call with any errors found. 3334 raw = clean_lines.lines_without_raw_strings
3353 not nesting_state.InNamespaceBody()
and 3354 not nesting_state.InExternC()):
3355 elided = clean_lines.elided
3356 prev_line = elided[linenum - 1]
3357 prevbrace = prev_line.rfind(
'{')
3362 if prevbrace != -1
and prev_line[prevbrace:].find(
'}') == -1:
3371 if Match(
r' {6}\w', prev_line):
3374 search_position = linenum-2
3375 while (search_position >= 0
3376 and Match(
r' {6}\w', elided[search_position])):
3377 search_position -= 1
3378 exception = (search_position >= 0
3379 and elided[search_position][:5] ==
' :')
3387 exception = (
Match(
r' {4}\w[^\(]*\)\s*(const\s*)?(\{\s*$|:)',
3389 or Match(
r' {4}:', prev_line))
3392 error(filename, linenum,
'whitespace/blank_line', 2,
3393 'Redundant blank line at the start of a code block ' 3394 'should be deleted.')
3403 if linenum + 1 < clean_lines.NumLines():
3404 next_line = raw[linenum + 1]
3406 and Match(
r'\s*}', next_line)
3407 and next_line.find(
'} else ') == -1):
3408 error(filename, linenum,
'whitespace/blank_line', 3,
3409 'Redundant blank line at the end of a code block ' 3410 'should be deleted.')
3412 matched =
Match(
r'\s*(public|protected|private):', prev_line)
3414 error(filename, linenum,
'whitespace/blank_line', 3,
3415 'Do not leave a blank line after "%s:"' % matched.group(1))
3419 if linenum + 1 < clean_lines.NumLines():
3420 next_line = raw[linenum + 1]
3421 next_line_start =
len(next_line) -
len(next_line.lstrip())
3422 CheckComment(line, filename, linenum, next_line_start, error)
3425 line = clean_lines.elided[linenum]
3429 if Search(
r'\w\s+\[', line)
and not Search(
r'(?:delete|return)\s+\[', line):
3430 error(filename, linenum,
'whitespace/braces', 5,
3431 'Extra space before [')
3435 if (
Search(
r'for *\(.*[^:]:[^: ]', line)
or 3436 Search(
r'for *\(.*[^: ]:[^:]', line)):
3437 error(filename, linenum,
'whitespace/forcolon', 2,
3438 'Missing space around colon in range-based for loop')
3442 """Checks for horizontal spacing around operators. 3445 filename: The name of the current file. 3446 clean_lines: A CleansedLines instance containing the file. 3447 linenum: The number of the line to check. 3448 error: The function to call with any errors found. 3450 line = clean_lines.elided[linenum]
3459 match =
Match(
r'^(.*\boperator\b)(\S+)(\s*\(.*)$', line)
3461 line = match.group(1) + (
'_' *
len(match.group(2))) + match.group(3)
3469 if ((
Search(
r'[\w.]=', line)
or 3471 and not Search(
r'\b(if|while|for) ', line)
3473 and not Search(
r'(>=|<=|==|!=|&=|\^=|\|=|\+=|\*=|\/=|\%=)', line)
3474 and not Search(
r'operator=', line)):
3475 error(filename, linenum,
'whitespace/operators', 4,
3476 'Missing spaces around =')
3493 match =
Search(
r'[^<>=!\s](==|!=|<=|>=|\|\|)[^<>=!\s,;\)]', line)
3495 error(filename, linenum,
'whitespace/operators', 3,
3496 'Missing spaces around %s' % match.group(1))
3497 elif not Match(
r'#.*include', line):
3502 match =
Match(
r'^(.*[^\s<])<[^\s=<,]', line)
3505 clean_lines, linenum,
len(match.group(1)))
3507 error(filename, linenum,
'whitespace/operators', 3,
3508 'Missing spaces around <')
3513 match =
Match(
r'^(.*[^-\s>])>[^\s=>,]', line)
3516 clean_lines, linenum,
len(match.group(1)))
3518 error(filename, linenum,
'whitespace/operators', 3,
3519 'Missing spaces around >')
3526 match =
Search(
r'(operator|[^\s(<])(?:L|UL|LL|ULL|l|ul|ll|ull)?<<([^\s,=<])', line)
3527 if (match
and not (match.group(1).isdigit()
and match.group(2).isdigit())
and 3528 not (match.group(1) ==
'operator' and match.group(2) ==
';')):
3529 error(filename, linenum,
'whitespace/operators', 3,
3530 'Missing spaces around <<')
3544 match =
Search(
r'>>[a-zA-Z_]', line)
3546 error(filename, linenum,
'whitespace/operators', 3,
3547 'Missing spaces around >>')
3550 match =
Search(
r'(!\s|~\s|[\s]--[\s;]|[\s]\+\+[\s;])', line)
3552 error(filename, linenum,
'whitespace/operators', 4,
3553 'Extra space for operator %s' % match.group(1))
3557 """Checks for horizontal spacing around parentheses. 3560 filename: The name of the current file. 3561 clean_lines: A CleansedLines instance containing the file. 3562 linenum: The number of the line to check. 3563 error: The function to call with any errors found. 3565 line = clean_lines.elided[linenum]
3568 match =
Search(
r' (if\(|for\(|while\(|switch\()', line)
3570 error(filename, linenum,
'whitespace/parens', 5,
3571 'Missing space before ( in %s' % match.group(1))
3578 match =
Search(
r'\b(if|for|while|switch)\s*' 3579 r'\(([ ]*)(.).*[^ ]+([ ]*)\)\s*{\s*$',
3582 if len(match.group(2)) !=
len(match.group(4)):
3583 if not (match.group(3) ==
';' and 3584 len(match.group(2)) == 1 +
len(match.group(4))
or 3585 not match.group(2)
and Search(
r'\bfor\s*\(.*; \)', line)):
3586 error(filename, linenum,
'whitespace/parens', 5,
3587 'Mismatching spaces inside () in %s' % match.group(1))
3588 if len(match.group(2))
not in [0, 1]:
3589 error(filename, linenum,
'whitespace/parens', 5,
3590 'Should have zero or one spaces inside ( and ) in %s' %
3595 """Checks for horizontal spacing near commas and semicolons. 3598 filename: The name of the current file. 3599 clean_lines: A CleansedLines instance containing the file. 3600 linenum: The number of the line to check. 3601 error: The function to call with any errors found. 3603 raw = clean_lines.lines_without_raw_strings
3604 line = clean_lines.elided[linenum]
3617 Search(
r',[^,\s]', raw[linenum])):
3618 error(filename, linenum,
'whitespace/comma', 3,
3619 'Missing space after ,')
3625 if Search(
r';[^\s};\\)/]', line):
3626 error(filename, linenum,
'whitespace/semicolon', 3,
3627 'Missing space after ;')
3630 def _IsType(clean_lines, nesting_state, expr):
3631 """Check if expression looks like a type name, returns true if so. 3634 clean_lines: A CleansedLines instance containing the file. 3635 nesting_state: A NestingState instance which maintains information about 3636 the current stack of nested blocks being parsed. 3637 expr: The expression to check. 3639 True, if token looks like a type. 3642 last_word =
Match(
r'^.*(\b\S+)$', expr)
3644 token = last_word.group(1)
3649 if _TYPES.match(token):
3655 typename_pattern = (
r'\b(?:typename|class|struct)\s+' + re.escape(token) +
3657 block_index =
len(nesting_state.stack) - 1
3658 while block_index >= 0:
3659 if isinstance(nesting_state.stack[block_index], _NamespaceInfo):
3668 last_line = nesting_state.stack[block_index].starting_linenum
3670 next_block_start = 0
3672 next_block_start = nesting_state.stack[block_index - 1].starting_linenum
3673 first_line = last_line
3674 while first_line >= next_block_start:
3675 if clean_lines.elided[first_line].find(
'template') >= 0:
3678 if first_line < next_block_start:
3685 for i
in xrange(first_line, last_line + 1, 1):
3686 if Search(typename_pattern, clean_lines.elided[i]):
3694 """Checks for horizontal spacing near commas. 3697 filename: The name of the current file. 3698 clean_lines: A CleansedLines instance containing the file. 3699 linenum: The number of the line to check. 3700 nesting_state: A NestingState instance which maintains information about 3701 the current stack of nested blocks being parsed. 3702 error: The function to call with any errors found. 3704 line = clean_lines.elided[linenum]
3712 match =
Match(
r'^(.*[^ ({>]){', line)
3743 leading_text = match.group(1)
3745 clean_lines, linenum,
len(match.group(1)))
3748 trailing_text = endline[endpos:]
3749 for offset
in xrange(endlinenum + 1,
3750 min(endlinenum + 3, clean_lines.NumLines() - 1)):
3751 trailing_text += clean_lines.elided[offset]
3755 if (
not Match(
r'^[\s}]*[{.;,)<>\]:]', trailing_text)
3756 and not _IsType(clean_lines, nesting_state, leading_text)):
3757 error(filename, linenum,
'whitespace/braces', 5,
3758 'Missing space before {')
3761 if Search(
r'}else', line):
3762 error(filename, linenum,
'whitespace/braces', 5,
3763 'Missing space before else')
3768 if Search(
r':\s*;\s*$', line):
3769 error(filename, linenum,
'whitespace/semicolon', 5,
3770 'Semicolon defining empty statement. Use {} instead.')
3771 elif Search(
r'^\s*;\s*$', line):
3772 error(filename, linenum,
'whitespace/semicolon', 5,
3773 'Line contains only semicolon. If this should be an empty statement, ' 3775 elif (
Search(
r'\s+;\s*$', line)
and 3776 not Search(
r'\bfor\b', line)):
3777 error(filename, linenum,
'whitespace/semicolon', 5,
3778 'Extra space before last semicolon. If this should be an empty ' 3779 'statement, use {} instead.')
3782 def IsDecltype(clean_lines, linenum, column):
3783 """Check if the token ending on (linenum, column) is decltype(). 3786 clean_lines: A CleansedLines instance containing the file. 3787 linenum: the number of the line to check. 3788 column: end column of the token to check. 3790 True if this token is decltype() expression, False otherwise. 3795 if Search(
r'\bdecltype\s*$', text[0:start_col]):
3800 """Checks for additional blank line issues related to sections. 3802 Currently the only thing checked here is blank line before protected/private. 3805 filename: The name of the current file. 3806 clean_lines: A CleansedLines instance containing the file. 3807 class_info: A _ClassInfo objects. 3808 linenum: The number of the line to check. 3809 error: The function to call with any errors found. 3822 if (class_info.last_line - class_info.starting_linenum <= 24
or 3823 linenum <= class_info.starting_linenum):
3826 matched =
Match(
r'\s*(public|protected|private):', clean_lines.lines[linenum])
3836 prev_line = clean_lines.lines[linenum - 1]
3838 not Search(
r'\b(class|struct)\b', prev_line)
and 3839 not Search(
r'\\$', prev_line)):
3844 end_class_head = class_info.starting_linenum
3845 for i
in range(class_info.starting_linenum, linenum):
3846 if Search(
r'\{\s*$', clean_lines.lines[i]):
3849 if end_class_head < linenum - 1:
3850 error(filename, linenum,
'whitespace/blank_line', 3,
3851 '"%s:" should be preceded by a blank line' % matched.group(1))
3855 """Return the most recent non-blank line and its line number. 3858 clean_lines: A CleansedLines instance containing the file contents. 3859 linenum: The number of the line to check. 3862 A tuple with two elements. The first element is the contents of the last 3863 non-blank line before the current line, or the empty string if this is the 3864 first non-blank line. The second is the line number of that line, or -1 3865 if this is the first non-blank line. 3868 prevlinenum = linenum - 1
3869 while prevlinenum >= 0:
3870 prevline = clean_lines.elided[prevlinenum]
3872 return (prevline, prevlinenum)
3877 def CheckBraces(filename, clean_lines, linenum, error):
3878 """Looks for misplaced braces (e.g. at the end of line). 3881 filename: The name of the current file. 3882 clean_lines: A CleansedLines instance containing the file. 3883 linenum: The number of the line to check. 3884 error: The function to call with any errors found. 3887 line = clean_lines.elided[linenum]
3907 if Match(
r'\s*else\b\s*(?:if\b|\{|$)', line):
3909 if Match(
r'\s*}\s*$', prevline):
3910 error(filename, linenum,
'whitespace/newline', 4,
3911 'An else should appear on the same line as the preceding }')
3915 if Search(
r'else if\s*\(', line):
3916 brace_on_left = bool(
Search(
r'}\s*else if\s*\(', line))
3918 pos = line.find(
'else if')
3919 pos = line.find(
'(', pos)
3922 brace_on_right = endline[endpos:].find(
'{') != -1
3923 if brace_on_left != brace_on_right:
3924 error(filename, linenum,
'readability/braces', 5,
3925 'If an else has a brace on one side, it should have it on both')
3926 elif Search(
r'}\s*else[^{]*$', line)
or Match(
r'[^}]*else\s*{', line):
3927 error(filename, linenum,
'readability/braces', 5,
3928 'If an else has a brace on one side, it should have it on both')
3931 if Search(
r'\belse [^\s{]', line)
and not Search(
r'\belse if\b', line):
3932 error(filename, linenum,
'whitespace/newline', 4,
3933 'Else clause should never be on same line as else (use 2 lines)')
3936 if Match(
r'\s*do [^\s{]', line):
3937 error(filename, linenum,
'whitespace/newline', 4,
3938 'do/while clauses should not be on a single line')
3947 if_else_match =
Search(
r'\b(if\s*\(|else\b)', line)
3948 if if_else_match
and not Match(
r'\s*#', line):
3950 endline, endlinenum, endpos = line, linenum, if_else_match.end()
3951 if_match =
Search(
r'\bif\s*\(', line)
3954 pos = if_match.end() - 1
3955 (endline, endlinenum, endpos) =
CloseExpression(clean_lines, linenum, pos)
3958 if (
not Match(
r'\s*{', endline[endpos:])
3959 and not (
Match(
r'\s*$', endline[endpos:])
3960 and endlinenum < (
len(clean_lines.elided) - 1)
3961 and Match(
r'\s*{', clean_lines.elided[endlinenum + 1]))):
3962 while (endlinenum <
len(clean_lines.elided)
3963 and ';' not in clean_lines.elided[endlinenum][endpos:]):
3966 if endlinenum <
len(clean_lines.elided):
3967 endline = clean_lines.elided[endlinenum]
3970 endpos = endline.find(
';')
3971 if not Match(
r';[\s}]*(\\?)$', endline[endpos:]):
3975 if not Match(
r'^[^{};]*\[[^\[\]]*\][^{}]*\{[^{}]*\}\s*\)*[;,]\s*$',
3977 error(filename, linenum,
'readability/braces', 4,
3978 'If/else bodies with multiple statements require braces')
3979 elif endlinenum <
len(clean_lines.elided) - 1:
3981 next_line = clean_lines.elided[endlinenum + 1]
3986 if (if_match
and Match(
r'\s*else\b', next_line)
3987 and next_indent != if_indent):
3988 error(filename, linenum,
'readability/braces', 4,
3989 'Else clause should be indented at the same level as if. ' 3990 'Ambiguous nested if/else chains require braces.')
3991 elif next_indent > if_indent:
3992 error(filename, linenum,
'readability/braces', 4,
3993 'If/else bodies with multiple statements require braces')
3997 """Looks for redundant trailing semicolon. 4000 filename: The name of the current file. 4001 clean_lines: A CleansedLines instance containing the file. 4002 linenum: The number of the line to check. 4003 error: The function to call with any errors found. 4006 line = clean_lines.elided[linenum]
4052 match =
Match(
r'^(.*\)\s*)\{', line)
4080 closing_brace_pos = match.group(1).rfind(
')')
4082 clean_lines, linenum, closing_brace_pos)
4083 if opening_parenthesis[2] > -1:
4084 line_prefix = opening_parenthesis[0][0:opening_parenthesis[2]]
4085 macro =
Search(
r'\b([A-Z_][A-Z0-9_]*)\s*$', line_prefix)
4086 func =
Match(
r'^(.*\])\s*$', line_prefix)
4088 macro.group(1)
not in (
4089 'TEST',
'TEST_F',
'MATCHER',
'MATCHER_P',
'TYPED_TEST',
4090 'EXCLUSIVE_LOCKS_REQUIRED',
'SHARED_LOCKS_REQUIRED',
4091 'LOCKS_EXCLUDED',
'INTERFACE_DEF'))
or 4092 (func
and not Search(
r'\boperator\s*\[\s*\]', func.group(1)))
or 4093 Search(
r'\b(?:struct|union)\s+alignas\s*$', line_prefix)
or 4094 Search(
r'\bdecltype$', line_prefix)
or 4095 Search(
r'\s+=\s*$', line_prefix)):
4098 opening_parenthesis[1] > 1
and 4099 Search(
r'\]\s*$', clean_lines.elided[opening_parenthesis[1] - 1])):
4105 match =
Match(
r'^(.*(?:else|\)\s*const)\s*)\{', line)
4116 if prevline
and Search(
r'[;{}]\s*$', prevline):
4117 match =
Match(
r'^(\s*)\{', line)
4122 clean_lines, linenum,
len(match.group(1)))
4123 if endpos > -1
and Match(
r'^\s*;', endline[endpos:]):
4133 raw_lines = clean_lines.raw_lines
4139 error(filename, endlinenum,
'readability/braces', 4,
4140 "You don't need a ; after a }")
4144 """Look for empty loop/conditional body with only a single semicolon. 4147 filename: The name of the current file. 4148 clean_lines: A CleansedLines instance containing the file. 4149 linenum: The number of the line to check. 4150 error: The function to call with any errors found. 4159 line = clean_lines.elided[linenum]
4160 matched =
Match(
r'\s*(for|while|if)\s*\(', line)
4164 clean_lines, linenum, line.find(
'('))
4169 if end_pos >= 0
and Match(
r';', end_line[end_pos:]):
4170 if matched.group(1) ==
'if':
4171 error(filename, end_linenum,
'whitespace/empty_conditional_body', 5,
4172 'Empty conditional bodies should use {}')
4174 error(filename, end_linenum,
'whitespace/empty_loop_body', 5,
4175 'Empty loop bodies should use {} or continue')
4179 if end_pos >= 0
and matched.group(1) ==
'if':
4182 opening_linenum = end_linenum
4183 opening_line_fragment = end_line[end_pos:]
4185 while not Search(
r'^\s*\{', opening_line_fragment):
4186 if Search(
r'^(?!\s*$)', opening_line_fragment):
4189 opening_linenum += 1
4190 if opening_linenum ==
len(clean_lines.elided):
4193 opening_line_fragment = clean_lines.elided[opening_linenum]
4195 opening_line = clean_lines.elided[opening_linenum]
4198 opening_pos = opening_line_fragment.find(
'{')
4199 if opening_linenum == end_linenum:
4201 opening_pos += end_pos
4203 clean_lines, opening_linenum, opening_pos)
4210 if (clean_lines.raw_lines[opening_linenum] !=
4214 if closing_linenum > opening_linenum:
4216 bodylist = list(opening_line[opening_pos+1:])
4218 bodylist.extend(clean_lines.raw_lines[opening_linenum+1:closing_linenum])
4220 bodylist.append(clean_lines.elided[closing_linenum][:closing_pos-1])
4221 body =
'\n'.join(bodylist)
4224 body = opening_line[opening_pos+1:closing_pos-1]
4227 if not _EMPTY_CONDITIONAL_BODY_PATTERN.search(body):
4230 current_linenum = closing_linenum
4231 current_line_fragment = closing_line[closing_pos:]
4233 while Search(
r'^\s*$|^(?=\s*else)', current_line_fragment):
4234 if Search(
r'^(?=\s*else)', current_line_fragment):
4237 current_linenum += 1
4238 if current_linenum ==
len(clean_lines.elided):
4240 current_line_fragment = clean_lines.elided[current_linenum]
4243 error(filename, end_linenum,
'whitespace/empty_if_body', 4,
4244 (
'If statement had no body and no else clause'))
4248 """Find a replaceable CHECK-like macro. 4251 line: line to search on. 4253 (macro name, start position), or (None, -1) if no replaceable 4256 for macro
in _CHECK_MACROS:
4257 i = line.find(macro)
4263 matched =
Match(
r'^(.*\b' + macro +
r'\s*)\(', line)
4266 return (macro,
len(matched.group(1)))
4270 def CheckCheck(filename, clean_lines, linenum, error):
4271 """Checks the use of CHECK and EXPECT macros. 4274 filename: The name of the current file. 4275 clean_lines: A CleansedLines instance containing the file. 4276 linenum: The number of the line to check. 4277 error: The function to call with any errors found. 4281 lines = clean_lines.elided
4288 clean_lines, linenum, start_pos)
4295 if not Match(
r'\s*;', last_line[end_pos:]):
4298 if linenum == end_line:
4299 expression = lines[linenum][start_pos + 1:end_pos - 1]
4301 expression = lines[linenum][start_pos + 1:]
4302 for i
in xrange(linenum + 1, end_line):
4303 expression += lines[i]
4304 expression += last_line[0:end_pos - 1]
4313 matched =
Match(
r'^\s*(<<|<<=|>>|>>=|->\*|->|&&|\|\||' 4314 r'==|!=|>=|>|<=|<|\()(.*)$', expression)
4316 token = matched.group(1)
4319 expression = matched.group(2)
4323 lhs +=
'(' + expression[0:end]
4324 expression = expression[end:]
4325 elif token
in (
'&&',
'||'):
4332 elif token
in (
'<<',
'<<=',
'>>',
'>>=',
'->*',
'->'):
4335 expression = matched.group(2)
4339 rhs = matched.group(2)
4347 matched =
Match(
r'^([^-=!<>()&|]+)(.*)$', expression)
4349 matched =
Match(
r'^(\s*\S)(.*)$', expression)
4352 lhs += matched.group(1)
4353 expression = matched.group(2)
4356 if not (lhs
and operator
and rhs):
4361 if rhs.find(
'&&') > -1
or rhs.find(
'||') > -1:
4372 match_constant =
r'^([-+]?(\d+|0[xX][0-9a-fA-F]+)[lLuU]{0,3}|".*"|\'.*\')$' 4373 if Match(match_constant, lhs)
or Match(match_constant, rhs):
4382 error(filename, linenum,
'readability/check', 2,
4383 'Consider using %s instead of %s(a %s b)' % (
4384 _CHECK_REPLACEMENT[check_macro][operator],
4385 check_macro, operator))
4389 """Check alternative keywords being used in boolean expressions. 4392 filename: The name of the current file. 4393 clean_lines: A CleansedLines instance containing the file. 4394 linenum: The number of the line to check. 4395 error: The function to call with any errors found. 4397 line = clean_lines.elided[linenum]
4400 if Match(
r'^\s*#', line):
4411 if line.find(
'/*') >= 0
or line.find(
'*/') >= 0:
4414 for match
in _ALT_TOKEN_REPLACEMENT_PATTERN.finditer(line):
4415 error(filename, linenum,
'readability/alt_tokens', 2,
4416 'Use operator %s instead of %s' % (
4417 _ALT_TOKEN_REPLACEMENT[match.group(1)], match.group(1)))
4421 """Determines the width of the line in column positions. 4424 line: A string, which may be a Unicode string. 4427 The width of the line in column positions, accounting for Unicode 4428 combining characters and wide characters. 4430 if isinstance(line, unicode):
4432 for uc
in unicodedata.normalize(
'NFC', line):
4433 if unicodedata.east_asian_width(uc)
in (
'W',
'F'):
4435 elif not unicodedata.combining(uc):
4442 def CheckStyle(filename, clean_lines, linenum, file_extension, nesting_state,
4444 """Checks rules from the 'C++ style rules' section of cppguide.html. 4446 Most of these rules are hard to test (naming, comment style), but we 4447 do what we can. In particular we check for 2-space indents, line lengths, 4448 tab usage, spaces inside code, etc. 4451 filename: The name of the current file. 4452 clean_lines: A CleansedLines instance containing the file. 4453 linenum: The number of the line to check. 4454 file_extension: The extension (without the dot) of the filename. 4455 nesting_state: A NestingState instance which maintains information about 4456 the current stack of nested blocks being parsed. 4457 error: The function to call with any errors found. 4463 raw_lines = clean_lines.lines_without_raw_strings
4464 line = raw_lines[linenum]
4465 prev = raw_lines[linenum - 1]
if linenum > 0
else '' 4467 if line.find(
'\t') != -1:
4468 error(filename, linenum,
'whitespace/tab', 1,
4469 'Tab found; better to use spaces')
4483 scope_or_label_pattern =
r'\s*\w+\s*:\s*\\?$' 4484 classinfo = nesting_state.InnermostClass()
4486 cleansed_line = clean_lines.elided[linenum]
4487 while initial_spaces <
len(line)
and line[initial_spaces] ==
' ':
4494 if (
not Search(
r'[",=><] *$', prev)
and 4495 (initial_spaces == 1
or initial_spaces == 3)
and 4496 not Match(scope_or_label_pattern, cleansed_line)
and 4497 not (clean_lines.raw_lines[linenum] != line
and 4498 Match(
r'^\s*""', line))):
4499 error(filename, linenum,
'whitespace/indent', 3,
4500 'Weird number of spaces at line-start. ' 4501 'Are you using a 2-space indent?')
4503 if line
and line[-1].isspace():
4504 error(filename, linenum,
'whitespace/end_of_line', 4,
4505 'Line ends in whitespace. Consider deleting these extra spaces.')
4508 is_header_guard =
False 4511 if (line.startswith(
'#ifndef %s' % cppvar)
or 4512 line.startswith(
'#define %s' % cppvar)
or 4513 line.startswith(
'#endif // %s' % cppvar)):
4514 is_header_guard =
True 4526 if (
not line.startswith(
'#include')
and not is_header_guard
and 4527 not Match(
r'^\s*//.*http(s?)://\S*$', line)
and 4528 not Match(
r'^\s*//\s*[^\s]*$', line)
and 4529 not Match(
r'^// \$Id:.*#[0-9]+ \$$', line)
and 4530 not Match(
r'^\s*/// [@\\](copydoc|copydetails|copybrief) .*$', line)):
4532 if line_width > _line_length:
4533 error(filename, linenum,
'whitespace/line_length', 2,
4534 'Lines should be <= %i characters long' % _line_length)
4536 if (cleansed_line.count(
';') > 1
and 4538 not Match(
r'^[^{};]*\[[^\[\]]*\][^{}]*\{[^{}\n\r]*\}',
4541 cleansed_line.find(
'for') == -1
and 4545 not ((cleansed_line.find(
'case ') != -1
or 4546 cleansed_line.find(
'default:') != -1)
and 4547 cleansed_line.find(
'break;') != -1)):
4548 error(filename, linenum,
'whitespace/newline', 0,
4549 'More than one command on the same line')
4552 CheckBraces(filename, clean_lines, linenum, error)
4555 CheckAccess(filename, clean_lines, linenum, nesting_state, error)
4556 CheckSpacing(filename, clean_lines, linenum, nesting_state, error)
4562 CheckCheck(filename, clean_lines, linenum, error)
4564 classinfo = nesting_state.InnermostClass()
4569 _RE_PATTERN_INCLUDE = re.compile(
r'^\s*#\s*include\s*([<"])([^>"]*)[>"].*$')
4575 _RE_FIRST_COMPONENT = re.compile(
r'^[^-_.]+')
4579 """Drops common suffixes like _test.cc or -inl.h from filename. 4582 >>> _DropCommonSuffixes('foo/foo-inl.h') 4584 >>> _DropCommonSuffixes('foo/bar/foo.cc') 4586 >>> _DropCommonSuffixes('foo/foo_internal.h') 4588 >>> _DropCommonSuffixes('foo/foo_unusualinternal.h') 4589 'foo/foo_unusualinternal' 4592 filename: The input filename. 4595 The filename with the common suffix removed. 4597 for suffix
in itertools.chain(
4598 (
'%s.%s' % (test_suffix.lstrip(
'_'), ext)
4600 (
'%s.%s' % (suffix, ext)
4601 for suffix, ext
in itertools.product([
'inl',
'imp',
'internal'],
GetHeaderExtensions()))):
4602 if (filename.endswith(suffix)
and len(filename) >
len(suffix)
and 4603 filename[-
len(suffix) - 1]
in (
'-',
'_')):
4604 return filename[:-
len(suffix) - 1]
4605 return os.path.splitext(filename)[0]
4609 """Figures out what kind of header 'include' is. 4612 fileinfo: The current file cpplint is running over. A FileInfo instance. 4613 include: The path to a #included file. 4614 is_system: True if the #include used <> rather than "". 4617 One of the _XXX_HEADER constants. 4620 >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'stdio.h', True) 4622 >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'string', True) 4624 >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'foo/foo.h', False) 4626 >>> _ClassifyInclude(FileInfo('foo/foo_unknown_extension.cc'), 4627 ... 'bar/foo_other_ext.h', False) 4629 >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'foo/bar.h', False) 4634 is_cpp_h = include
in _CPP_HEADERS
4637 if is_system
and os.path.splitext(include)[1]
in [
'.hpp',
'.hxx',
'.h++']:
4642 return _CPP_SYS_HEADER
4644 return _C_SYS_HEADER
4649 target_dir, target_base = (
4652 target_dir_pub = os.path.normpath(target_dir +
'/../public')
4653 target_dir_pub = target_dir_pub.replace(
'\\',
'/')
4654 if target_base == include_base
and (
4655 include_dir == target_dir
or 4656 include_dir == target_dir_pub):
4657 return _LIKELY_MY_HEADER
4663 target_first_component = _RE_FIRST_COMPONENT.match(target_base)
4664 include_first_component = _RE_FIRST_COMPONENT.match(include_base)
4665 if (target_first_component
and include_first_component
and 4666 target_first_component.group(0) ==
4667 include_first_component.group(0)):
4668 return _POSSIBLE_MY_HEADER
4670 return _OTHER_HEADER
4674 def CheckIncludeLine(filename, clean_lines, linenum, include_state, error):
4675 """Check rules that are applicable to #include lines. 4677 Strings on #include lines are NOT removed from elided line, to make 4678 certain tasks easier. However, to prevent false positives, checks 4679 applicable to #include lines in CheckLanguage must be put here. 4682 filename: The name of the current file. 4683 clean_lines: A CleansedLines instance containing the file. 4684 linenum: The number of the line to check. 4685 include_state: An _IncludeState instance in which the headers are inserted. 4686 error: The function to call with any errors found. 4689 line = clean_lines.lines[linenum]
4698 match =
Match(
r'#include\s*"([^/]+\.h)"', line)
4699 if match
and not _THIRD_PARTY_HEADERS_PATTERN.match(match.group(1)):
4700 error(filename, linenum,
'build/include_subdir', 4,
4701 'Include the directory when naming .h files')
4706 match = _RE_PATTERN_INCLUDE.search(line)
4708 include = match.group(2)
4709 is_system = (match.group(1) ==
'<')
4710 duplicate_line = include_state.FindHeader(include)
4711 if duplicate_line >= 0:
4712 error(filename, linenum,
'build/include', 4,
4713 '"%s" already included at %s:%s' %
4714 (include, filename, duplicate_line))
4718 if (include.endswith(
'.' + extension)
and 4719 os.path.dirname(fileinfo.RepositoryName()) != os.path.dirname(include)):
4720 error(filename, linenum,
'build/include', 4,
4721 'Do not include .' + extension +
' files from other packages')
4724 if not _THIRD_PARTY_HEADERS_PATTERN.match(include):
4725 include_state.include_list[-1].append((include, linenum))
4738 error_message = include_state.CheckNextIncludeOrder(
4741 error(filename, linenum,
'build/include_order', 4,
4742 '%s. Should be: %s.h, c system, c++ system, other.' %
4743 (error_message, fileinfo.BaseName()))
4744 canonical_include = include_state.CanonicalizeAlphabeticalOrder(include)
4745 if not include_state.IsInAlphabeticalOrder(
4746 clean_lines, linenum, canonical_include):
4747 error(filename, linenum,
'build/include_alpha', 4,
4748 'Include "%s" not in alphabetical order' % include)
4749 include_state.SetLastHeader(canonical_include)
4754 r"""Retrieves all the text between matching open and close parentheses. 4756 Given a string of lines and a regular expression string, retrieve all the text 4757 following the expression and between opening punctuation symbols like 4758 (, [, or {, and the matching close-punctuation symbol. This properly nested 4759 occurrences of the punctuations, so for the text like 4760 printf(a(), b(c())); 4761 a call to _GetTextInside(text, r'printf\(') will return 'a(), b(c())'. 4762 start_pattern must match string having an open punctuation symbol at the end. 4765 text: The lines to extract text. Its comments and strings must be elided. 4766 It can be single line and can span multiple lines. 4767 start_pattern: The regexp string indicating where to start extracting 4771 None if either the opening string or ending punctuation could not be found. 4777 matching_punctuation = {
'(':
')',
'{':
'}',
'[':
']'}
4781 match = re.search(start_pattern, text, re.M)
4784 start_position = match.end(0)
4786 assert start_position > 0, (
4787 'start_pattern must ends with an opening punctuation.')
4788 assert text[start_position - 1]
in matching_punctuation, (
4789 'start_pattern must ends with an opening punctuation.')
4791 punctuation_stack = [matching_punctuation[text[start_position - 1]]]
4792 position = start_position
4793 while punctuation_stack
and position <
len(text):
4794 if text[position] == punctuation_stack[-1]:
4795 punctuation_stack.pop()
4796 elif text[position]
in closing_punctuation:
4799 elif text[position]
in matching_punctuation:
4800 punctuation_stack.append(matching_punctuation[text[position]])
4802 if punctuation_stack:
4806 return text[start_position:position - 1]
4818 _RE_PATTERN_IDENT =
r'[_a-zA-Z]\w*' 4819 _RE_PATTERN_TYPE = (
4820 r'(?:const\s+)?(?:typename\s+|class\s+|struct\s+|union\s+|enum\s+)?' 4822 r'\s*<(?:<(?:<[^<>]*>|[^<>])*>|[^<>])*>|' 4825 _RE_PATTERN_REF_PARAM = re.compile(
4826 r'(' + _RE_PATTERN_TYPE +
r'(?:\s*(?:\bconst\b|[*]))*\s*' 4827 r'&\s*' + _RE_PATTERN_IDENT +
r')\s*(?:=[^,()]+)?[,)]')
4830 _RE_PATTERN_CONST_REF_PARAM = (
4831 r'(?:.*\s*\bconst\s*&\s*' + _RE_PATTERN_IDENT +
4832 r'|const\s+' + _RE_PATTERN_TYPE +
r'\s*&\s*' + _RE_PATTERN_IDENT +
r')')
4834 _RE_PATTERN_REF_STREAM_PARAM = (
4835 r'(?:.*stream\s*&\s*' + _RE_PATTERN_IDENT +
r')')
4838 def CheckLanguage(filename, clean_lines, linenum, file_extension,
4839 include_state, nesting_state, error):
4840 """Checks rules from the 'C++ language rules' section of cppguide.html. 4842 Some of these rules are hard to test (function overloading, using 4843 uint32 inappropriately), but we do the best we can. 4846 filename: The name of the current file. 4847 clean_lines: A CleansedLines instance containing the file. 4848 linenum: The number of the line to check. 4849 file_extension: The extension (without the dot) of the filename. 4850 include_state: An _IncludeState instance in which the headers are inserted. 4851 nesting_state: A NestingState instance which maintains information about 4852 the current stack of nested blocks being parsed. 4853 error: The function to call with any errors found. 4857 line = clean_lines.elided[linenum]
4861 match = _RE_PATTERN_INCLUDE.search(line)
4868 match =
Match(
r'^\s*#\s*(if|ifdef|ifndef|elif|else|endif)\b', line)
4870 include_state.ResetSection(match.group(1))
4874 CheckCasts(filename, clean_lines, linenum, error)
4876 CheckPrintf(filename, clean_lines, linenum, error)
4888 if Search(
r'\bshort port\b', line):
4889 if not Search(
r'\bunsigned short port\b', line):
4890 error(filename, linenum,
'runtime/int', 4,
4891 'Use "unsigned short" for ports, not "short"')
4893 match =
Search(
r'\b(short|long(?! +double)|long long)\b', line)
4895 error(filename, linenum,
'runtime/int', 4,
4896 'Use int16/int64/etc, rather than the C type %s' % match.group(1))
4904 if Search(
r'\boperator\s*&\s*\(\s*\)', line):
4905 error(filename, linenum,
'runtime/operator', 4,
4906 'Unary operator& is dangerous. Do not use it.')
4910 if Search(
r'\}\s*if\s*\(', line):
4911 error(filename, linenum,
'readability/braces', 4,
4912 'Did you mean "else if"? If not, start a new line for "if".')
4921 printf_args =
_GetTextInside(line,
r'(?i)\b(string)?printf\s*\(')
4923 match =
Match(
r'([\w.\->()]+)$', printf_args)
4924 if match
and match.group(1) !=
'__VA_ARGS__':
4925 function_name = re.search(
r'\b((?:string)?printf)\s*\(',
4926 line, re.I).group(1)
4927 error(filename, linenum,
'runtime/printf', 4,
4928 'Potential format string bug. Do %s("%%s", %s) instead.' 4929 % (function_name, match.group(1)))
4932 match =
Search(
r'memset\s*\(([^,]*),\s*([^,]*),\s*0\s*\)', line)
4933 if match
and not Match(
r"^''|-?[0-9]+|0x[0-9A-Fa-f]$", match.group(2)):
4934 error(filename, linenum,
'runtime/memset', 4,
4935 'Did you mean "memset(%s, 0, %s)"?' 4936 % (match.group(1), match.group(2)))
4938 if Search(
r'\busing namespace\b', line):
4939 if Search(
r'\bliterals\b', line):
4940 error(filename, linenum,
'build/namespaces_literals', 5,
4941 'Do not use namespace using-directives. ' 4942 'Use using-declarations instead.')
4944 error(filename, linenum,
'build/namespaces', 5,
4945 'Do not use namespace using-directives. ' 4946 'Use using-declarations instead.')
4949 match =
Match(
r'\s*(.+::)?(\w+) [a-z]\w*\[(.+)];', line)
4950 if (match
and match.group(2) !=
'return' and match.group(2) !=
'delete' and 4951 match.group(3).find(
']') == -1):
4955 tokens = re.split(
r'\s|\+|\-|\*|\/|<<|>>]', match.group(3))
4963 if Search(
r'sizeof\(.+\)', tok):
continue 4964 if Search(
r'arraysize\(\w+\)', tok):
continue 4966 tok = tok.lstrip(
'(')
4967 tok = tok.rstrip(
')')
4968 if not tok:
continue 4969 if Match(
r'\d+', tok):
continue 4970 if Match(
r'0[xX][0-9a-fA-F]+', tok):
continue 4971 if Match(
r'k[A-Z0-9]\w*', tok):
continue 4972 if Match(
r'(.+::)?k[A-Z0-9]\w*', tok):
continue 4973 if Match(
r'(.+::)?[A-Z][A-Z0-9_]*', tok):
continue 4977 if tok.startswith(
'sizeof'):
4983 error(filename, linenum,
'runtime/arrays', 1,
4984 'Do not use variable-length arrays. Use an appropriately named ' 4985 "('k' followed by CamelCase) compile-time constant for the size.")
4991 and Search(
r'\bnamespace\s*{', line)
4992 and line[-1] !=
'\\'):
4993 error(filename, linenum,
'build/namespaces', 4,
4994 'Do not use unnamed namespaces in header files. See ' 4995 'https://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Namespaces' 4996 ' for more information.')
5000 """Check for unsafe global or static objects. 5003 filename: The name of the current file. 5004 clean_lines: A CleansedLines instance containing the file. 5005 linenum: The number of the line to check. 5006 error: The function to call with any errors found. 5008 line = clean_lines.elided[linenum]
5011 if linenum + 1 < clean_lines.NumLines()
and not Search(
r'[;({]', line):
5012 line += clean_lines.elided[linenum + 1].strip()
5021 r'((?:|static +)(?:|const +))(?::*std::)?string( +const)? +' 5022 r'([a-zA-Z0-9_:]+)\b(.*)',
5042 not Search(
r'\bstring\b(\s+const)?\s*[\*\&]\s*(const\s+)?\w', line)
and 5043 not Search(
r'\boperator\W', line)
and 5044 not Match(
r'\s*(<.*>)?(::[a-zA-Z0-9_]+)*\s*\(([^"]|$)', match.group(4))):
5045 if Search(
r'\bconst\b', line):
5046 error(filename, linenum,
'runtime/string', 4,
5047 'For a static/global string constant, use a C style string ' 5048 'instead: "%schar%s %s[]".' %
5049 (match.group(1), match.group(2)
or '', match.group(3)))
5051 error(filename, linenum,
'runtime/string', 4,
5052 'Static/global string variables are not permitted.')
5054 if (
Search(
r'\b([A-Za-z0-9_]*_)\(\1\)', line)
or 5055 Search(
r'\b([A-Za-z0-9_]*_)\(CHECK_NOTNULL\(\1\)\)', line)):
5056 error(filename, linenum,
'runtime/init', 4,
5057 'You seem to be initializing a member variable with itself.')
5060 def CheckPrintf(filename, clean_lines, linenum, error):
5061 """Check for printf related issues. 5064 filename: The name of the current file. 5065 clean_lines: A CleansedLines instance containing the file. 5066 linenum: The number of the line to check. 5067 error: The function to call with any errors found. 5069 line = clean_lines.elided[linenum]
5072 match =
Search(
r'snprintf\s*\(([^,]*),\s*([0-9]*)\s*,', line)
5073 if match
and match.group(2) !=
'0':
5075 error(filename, linenum,
'runtime/printf', 3,
5076 'If you can, use sizeof(%s) instead of %s as the 2nd arg ' 5077 'to snprintf.' % (match.group(1), match.group(2)))
5080 if Search(
r'\bsprintf\s*\(', line):
5081 error(filename, linenum,
'runtime/printf', 5,
5082 'Never use sprintf. Use snprintf instead.')
5083 match =
Search(
r'\b(strcpy|strcat)\s*\(', line)
5085 error(filename, linenum,
'runtime/printf', 4,
5086 'Almost always, snprintf is better than %s' % match.group(1))
5090 """Check if current line contains an inherited function. 5093 clean_lines: A CleansedLines instance containing the file. 5094 linenum: The number of the line to check. 5096 True if current line contains a function with "override" 5100 for i
in xrange(linenum,
max(-1, linenum - 10), -1):
5101 match =
Match(
r'^([^()]*\w+)\(', clean_lines.elided[i])
5105 clean_lines, i,
len(match.group(1)))
5106 return (closing_paren >= 0
and 5107 Search(
r'\boverride\b', line[closing_paren:]))
5112 """Check if current line contains an out-of-line method definition. 5115 clean_lines: A CleansedLines instance containing the file. 5116 linenum: The number of the line to check. 5118 True if current line contains an out-of-line method definition. 5121 for i
in xrange(linenum,
max(-1, linenum - 10), -1):
5122 if Match(
r'^([^()]*\w+)\(', clean_lines.elided[i]):
5123 return Match(
r'^[^()]*\w+::\w+\(', clean_lines.elided[i])
is not None 5128 """Check if current line is inside constructor initializer list. 5131 clean_lines: A CleansedLines instance containing the file. 5132 linenum: The number of the line to check. 5134 True if current line appears to be inside constructor initializer 5135 list, False otherwise. 5137 for i
in xrange(linenum, 1, -1):
5138 line = clean_lines.elided[i]
5140 remove_function_body =
Match(
r'^(.*)\{\s*$', line)
5141 if remove_function_body:
5142 line = remove_function_body.group(1)
5144 if Search(
r'\s:\s*\w+[({]', line):
5150 if Search(
r'\}\s*,\s*$', line):
5154 if Search(
r'[{};]\s*$', line):
5170 nesting_state, error):
5171 """Check for non-const references. 5173 Separate from CheckLanguage since it scans backwards from current 5174 line, instead of scanning forward. 5177 filename: The name of the current file. 5178 clean_lines: A CleansedLines instance containing the file. 5179 linenum: The number of the line to check. 5180 nesting_state: A NestingState instance which maintains information about 5181 the current stack of nested blocks being parsed. 5182 error: The function to call with any errors found. 5185 line = clean_lines.elided[linenum]
5218 if Match(
r'\s*::(?:[\w<>]|::)+\s*&\s*\S', line):
5220 previous =
Search(
r'\b((?:const\s*)?(?:[\w<>]|::)+[\w<>])\s*$',
5221 clean_lines.elided[linenum - 1])
5222 elif Match(
r'\s*[a-zA-Z_]([\w<>]|::)+\s*&\s*\S', line):
5224 previous =
Search(
r'\b((?:const\s*)?(?:[\w<>]|::)+::)\s*$',
5225 clean_lines.elided[linenum - 1])
5227 line = previous.group(1) + line.lstrip()
5230 endpos = line.rfind(
'>')
5233 clean_lines, linenum, endpos)
5234 if startpos > -1
and startline < linenum:
5238 for i
in xrange(startline, linenum + 1):
5239 line += clean_lines.elided[i].strip()
5249 if (nesting_state.previous_stack_top
and 5250 not (isinstance(nesting_state.previous_stack_top, _ClassInfo)
or 5251 isinstance(nesting_state.previous_stack_top, _NamespaceInfo))):
5262 for i
in xrange(linenum - 1,
max(0, linenum - 10), -1):
5263 previous_line = clean_lines.elided[i]
5264 if not Search(
r'[),]\s*$', previous_line):
5266 if Match(
r'^\s*:\s+\S', previous_line):
5270 if Search(
r'\\\s*$', line):
5283 whitelisted_functions = (
r'(?:[sS]wap(?:<\w:+>)?|' 5284 r'operator\s*[<>][<>]|' 5285 r'static_assert|COMPILE_ASSERT' 5287 if Search(whitelisted_functions, line):
5289 elif not Search(
r'\S+\([^)]*$', line):
5295 Search(whitelisted_functions, clean_lines.elided[linenum - i - 1])):
5299 for parameter
in re.findall(_RE_PATTERN_REF_PARAM, decls):
5300 if (
not Match(_RE_PATTERN_CONST_REF_PARAM, parameter)
and 5301 not Match(_RE_PATTERN_REF_STREAM_PARAM, parameter)):
5302 error(filename, linenum,
'runtime/references', 2,
5303 'Is this a non-const reference? ' 5304 'If so, make const or use a pointer: ' +
5308 def CheckCasts(filename, clean_lines, linenum, error):
5309 """Various cast related checks. 5312 filename: The name of the current file. 5313 clean_lines: A CleansedLines instance containing the file. 5314 linenum: The number of the line to check. 5315 error: The function to call with any errors found. 5317 line = clean_lines.elided[linenum]
5324 r'(\bnew\s+(?:const\s+)?|\S<\s*(?:const\s+)?)?\b' 5325 r'(int|float|double|bool|char|int32|uint32|int64|uint64)' 5326 r'(\([^)].*)', line)
5328 if match
and not expecting_function:
5329 matched_type = match.group(2)
5343 matched_new_or_template = match.group(1)
5347 if Match(
r'\([^()]+\)\s*\[', match.group(3)):
5355 matched_funcptr = match.group(3)
5356 if (matched_new_or_template
is None and 5357 not (matched_funcptr
and 5358 (
Match(
r'\((?:[^() ]+::\s*\*\s*)?[^() ]+\)\s*\(',
5360 matched_funcptr.startswith(
'(*)')))
and 5361 not Match(
r'\s*using\s+\S+\s*=\s*' + matched_type, line)
and 5362 not Search(
r'new\(\S+\)\s*' + matched_type, line)):
5363 error(filename, linenum,
'readability/casting', 4,
5364 'Using deprecated casting style. ' 5365 'Use static_cast<%s>(...) instead' %
5368 if not expecting_function:
5370 r'\((int|float|double|bool|char|u?int(16|32|64))\)', error)
5377 r'\((char\s?\*+\s?)\)\s*"', error):
5382 r'\((\w+\s?\*+\s?)\)', error)
5396 r'(?:[^\w]&\(([^)*][^)]*)\)[\w(])|' 5397 r'(?:[^\w]&(static|dynamic|down|reinterpret)_cast\b)', line)
5402 parenthesis_error =
False 5403 match =
Match(
r'^(.*&(?:static|dynamic|down|reinterpret)_cast\b)<', line)
5406 if x1 >= 0
and clean_lines.elided[y1][x1] ==
'(':
5409 extended_line = clean_lines.elided[y2][x2:]
5410 if y2 < clean_lines.NumLines() - 1:
5411 extended_line += clean_lines.elided[y2 + 1]
5412 if Match(
r'\s*(?:->|\[)', extended_line):
5413 parenthesis_error =
True 5415 if parenthesis_error:
5416 error(filename, linenum,
'readability/casting', 4,
5417 (
'Are you taking an address of something dereferenced ' 5418 'from a cast? Wrapping the dereferenced expression in ' 5419 'parentheses will make the binding more obvious'))
5421 error(filename, linenum,
'runtime/casting', 4,
5422 (
'Are you taking an address of a cast? ' 5423 'This is dangerous: could be a temp var. ' 5424 'Take the address before doing the cast, rather than after'))
5427 def CheckCStyleCast(filename, clean_lines, linenum, cast_type, pattern, error):
5428 """Checks for a C-style cast by looking for the pattern. 5431 filename: The name of the current file. 5432 clean_lines: A CleansedLines instance containing the file. 5433 linenum: The number of the line to check. 5434 cast_type: The string for the C++ cast to recommend. This is either 5435 reinterpret_cast, static_cast, or const_cast, depending. 5436 pattern: The regular expression used to find C-style casts. 5437 error: The function to call with any errors found. 5440 True if an error was emitted. 5443 line = clean_lines.elided[linenum]
5444 match =
Search(pattern, line)
5449 context = line[0:match.start(1) - 1]
5450 if Match(
r'.*\b(?:sizeof|alignof|alignas|[_A-Z][_A-Z0-9]*)\s*$', context):
5456 for i
in xrange(linenum - 1,
max(0, linenum - 5), -1):
5457 context = clean_lines.elided[i] + context
5458 if Match(
r'.*\b[_A-Z][_A-Z0-9]*\s*\((?:\([^()]*\)|[^()])*$', context):
5462 if context.endswith(
' operator++')
or context.endswith(
' operator--'):
5467 remainder = line[match.end(0):]
5468 if Match(
r'^\s*(?:;|const\b|throw\b|final\b|override\b|[=>{),]|->)',
5473 error(filename, linenum,
'readability/casting', 4,
5474 'Using C-style cast. Use %s<%s>(...) instead' %
5475 (cast_type, match.group(1)))
5481 """Checks whether where function type arguments are expected. 5484 clean_lines: A CleansedLines instance containing the file. 5485 linenum: The number of the line to check. 5488 True if the line at 'linenum' is inside something that expects arguments 5491 line = clean_lines.elided[linenum]
5492 return (
Match(
r'^\s*MOCK_(CONST_)?METHOD\d+(_T)?\(', line)
or 5494 (
Match(
r'^\s*MOCK_(?:CONST_)?METHOD\d+(?:_T)?\((?:\S+,)?\s*$',
5495 clean_lines.elided[linenum - 1])
or 5496 Match(
r'^\s*MOCK_(?:CONST_)?METHOD\d+(?:_T)?\(\s*$',
5497 clean_lines.elided[linenum - 2])
or 5498 Search(
r'\bstd::m?function\s*<\s*$',
5499 clean_lines.elided[linenum - 1]))))
5502 _HEADERS_CONTAINING_TEMPLATES = (
5503 (
'<deque>', (
'deque',)),
5504 (
'<functional>', (
'unary_function',
'binary_function',
5505 'plus',
'minus',
'multiplies',
'divides',
'modulus',
5507 'equal_to',
'not_equal_to',
'greater',
'less',
5508 'greater_equal',
'less_equal',
5509 'logical_and',
'logical_or',
'logical_not',
5510 'unary_negate',
'not1',
'binary_negate',
'not2',
5511 'bind1st',
'bind2nd',
5512 'pointer_to_unary_function',
5513 'pointer_to_binary_function',
5515 'mem_fun_t',
'mem_fun',
'mem_fun1_t',
'mem_fun1_ref_t',
5517 'const_mem_fun_t',
'const_mem_fun1_t',
5518 'const_mem_fun_ref_t',
'const_mem_fun1_ref_t',
5521 (
'<limits>', (
'numeric_limits',)),
5522 (
'<list>', (
'list',)),
5523 (
'<map>', (
'map',
'multimap',)),
5524 (
'<memory>', (
'allocator',
'make_shared',
'make_unique',
'shared_ptr',
5525 'unique_ptr',
'weak_ptr')),
5526 (
'<queue>', (
'queue',
'priority_queue',)),
5527 (
'<set>', (
'set',
'multiset',)),
5528 (
'<stack>', (
'stack',)),
5529 (
'<string>', (
'char_traits',
'basic_string',)),
5530 (
'<tuple>', (
'tuple',)),
5531 (
'<unordered_map>', (
'unordered_map',
'unordered_multimap')),
5532 (
'<unordered_set>', (
'unordered_set',
'unordered_multiset')),
5533 (
'<utility>', (
'pair',)),
5534 (
'<vector>', (
'vector',)),
5538 (
'<hash_map>', (
'hash_map',
'hash_multimap',)),
5539 (
'<hash_set>', (
'hash_set',
'hash_multiset',)),
5540 (
'<slist>', (
'slist',)),
5543 _HEADERS_MAYBE_TEMPLATES = (
5544 (
'<algorithm>', (
'copy',
'max',
'min',
'min_element',
'sort',
5547 (
'<utility>', (
'forward',
'make_pair',
'move',
'swap')),
5550 _RE_PATTERN_STRING = re.compile(
r'\bstring\b')
5552 _re_pattern_headers_maybe_templates = []
5553 for _header, _templates
in _HEADERS_MAYBE_TEMPLATES:
5554 for _template
in _templates:
5557 _re_pattern_headers_maybe_templates.append(
5558 (re.compile(
r'[^>.]\b' + _template +
r'(<.*?>)?\([^\)]'),
5563 _re_pattern_templates = []
5564 for _header, _templates
in _HEADERS_CONTAINING_TEMPLATES:
5565 for _template
in _templates:
5566 _re_pattern_templates.append(
5567 (re.compile(
r'(<|\b)' + _template +
r'\s*<'),
5573 """Check if these two filenames belong to the same module. 5575 The concept of a 'module' here is a as follows: 5576 foo.h, foo-inl.h, foo.cc, foo_test.cc and foo_unittest.cc belong to the 5577 same 'module' if they are in the same directory. 5578 some/path/public/xyzzy and some/path/internal/xyzzy are also considered 5579 to belong to the same module here. 5581 If the filename_cc contains a longer path than the filename_h, for example, 5582 '/absolute/path/to/base/sysinfo.cc', and this file would include 5583 'base/sysinfo.h', this function also produces the prefix needed to open the 5584 header. This is used by the caller of this function to more robustly open the 5585 header file. We don't have access to the real include paths in this context, 5586 so we need this guesswork here. 5588 Known bugs: tools/base/bar.cc and base/bar.h belong to the same module 5589 according to this implementation. Because of this, this function gives 5590 some false positives. This should be sufficiently rare in practice. 5593 filename_cc: is the path for the source (e.g. .cc) file 5594 filename_h: is the path for the header path 5597 Tuple with a bool and a string: 5598 bool: True if filename_cc and filename_h belong to the same module. 5599 string: the additional prefix needed to open the header file. 5601 fileinfo_cc =
FileInfo(filename_cc)
5609 filename_cc = filename_cc[:-(
len(fileinfo_cc.Extension()))]
5610 matched_test_suffix =
Search(_TEST_FILE_SUFFIX, fileinfo_cc.BaseName())
5611 if matched_test_suffix:
5612 filename_cc = filename_cc[:-
len(matched_test_suffix.group(1))]
5614 filename_cc = filename_cc.replace(
'/public/',
'/')
5615 filename_cc = filename_cc.replace(
'/internal/',
'/')
5617 filename_h = filename_h[:-(
len(fileinfo_h.Extension()))]
5618 if filename_h.endswith(
'-inl'):
5619 filename_h = filename_h[:-
len(
'-inl')]
5620 filename_h = filename_h.replace(
'/public/',
'/')
5621 filename_h = filename_h.replace(
'/internal/',
'/')
5623 files_belong_to_same_module = filename_cc.endswith(filename_h)
5625 if files_belong_to_same_module:
5626 common_path = filename_cc[:-
len(filename_h)]
5627 return files_belong_to_same_module, common_path
5631 """Fill up the include_dict with new includes found from the file. 5634 filename: the name of the header to read. 5635 include_dict: a dictionary in which the headers are inserted. 5636 io: The io factory to use to read the file. Provided for testability. 5639 True if a header was successfully added. False otherwise. 5643 headerfile = io.open(filename,
'r', 'utf8', 'replace')
5647 for line
in headerfile:
5650 match = _RE_PATTERN_INCLUDE.search(clean_line)
5652 include = match.group(2)
5653 include_dict.setdefault(include, linenum)
5659 """Reports for missing stl includes. 5661 This function will output warnings to make sure you are including the headers 5662 necessary for the stl containers and functions that you use. We only give one 5663 reason to include a header. For example, if you use both equal_to<> and 5664 less<> in a .h file, only one (the latter in the file) of these will be 5665 reported as a reason to include the <functional>. 5668 filename: The name of the current file. 5669 clean_lines: A CleansedLines instance containing the file. 5670 include_state: An _IncludeState instance. 5671 error: The function to call with any errors found. 5672 io: The IO factory to use to read the header file. Provided for unittest 5678 for linenum
in range(clean_lines.NumLines()):
5679 line = clean_lines.elided[linenum]
5680 if not line
or line[0] ==
'#':
5684 matched = _RE_PATTERN_STRING.search(line)
5688 prefix = line[:matched.start()]
5689 if prefix.endswith(
'std::')
or not prefix.endswith(
'::'):
5690 required[
'<string>'] = (linenum,
'string')
5692 for pattern, template, header
in _re_pattern_headers_maybe_templates:
5693 if pattern.search(line):
5694 required[header] = (linenum, template)
5700 for pattern, template, header
in _re_pattern_templates:
5701 matched = pattern.search(line)
5705 prefix = line[:matched.start()]
5706 if prefix.endswith(
'std::')
or not prefix.endswith(
'::'):
5707 required[header] = (linenum, template)
5712 include_dict = dict([item
for sublist
in include_state.include_list
5713 for item
in sublist])
5716 header_found =
False 5719 abs_filename =
FileInfo(filename).FullName()
5728 abs_filename = re.sub(
r'_flymake\.cc$',
'.cc', abs_filename)
5732 header_keys = list(include_dict.keys())
5733 for header
in header_keys:
5735 fullpath = common_path + header
5744 if not header_found:
5746 if filename.endswith(
'.' + extension):
5750 for required_header_unstripped
in sorted(required, key=required.__getitem__):
5751 template = required[required_header_unstripped][1]
5752 if required_header_unstripped.strip(
'<>"')
not in include_dict:
5753 error(filename, required[required_header_unstripped][0],
5754 'build/include_what_you_use', 4,
5755 'Add #include ' + required_header_unstripped +
' for ' + template)
5758 _RE_PATTERN_EXPLICIT_MAKEPAIR = re.compile(
r'\bmake_pair\s*<')
5762 """Check that make_pair's template arguments are deduced. 5764 G++ 4.6 in C++11 mode fails badly if make_pair's template arguments are 5765 specified explicitly, and such use isn't intended in any case. 5768 filename: The name of the current file. 5769 clean_lines: A CleansedLines instance containing the file. 5770 linenum: The number of the line to check. 5771 error: The function to call with any errors found. 5773 line = clean_lines.elided[linenum]
5774 match = _RE_PATTERN_EXPLICIT_MAKEPAIR.search(line)
5776 error(filename, linenum,
'build/explicit_make_pair',
5778 'For C++11-compatibility, omit template arguments from make_pair' 5779 ' OR use pair directly OR if appropriate, construct a pair directly')
5783 """Check if line contains a redundant "virtual" function-specifier. 5786 filename: The name of the current file. 5787 clean_lines: A CleansedLines instance containing the file. 5788 linenum: The number of the line to check. 5789 error: The function to call with any errors found. 5792 line = clean_lines.elided[linenum]
5793 virtual =
Match(
r'^(.*)(\bvirtual\b)(.*)$', line)
5794 if not virtual:
return 5799 if (
Search(
r'\b(public|protected|private)\s+$', virtual.group(1))
or 5800 Match(
r'^\s+(public|protected|private)\b', virtual.group(3))):
5806 if Match(
r'^.*[^:]:[^:].*$', line):
return 5815 start_col =
len(virtual.group(2))
5816 for start_line
in xrange(linenum,
min(linenum + 3, clean_lines.NumLines())):
5817 line = clean_lines.elided[start_line][start_col:]
5818 parameter_list =
Match(
r'^([^(]*)\(', line)
5822 clean_lines, start_line, start_col +
len(parameter_list.group(1)))
5831 for i
in xrange(end_line,
min(end_line + 3, clean_lines.NumLines())):
5832 line = clean_lines.elided[i][end_col:]
5833 match =
Search(
r'\b(override|final)\b', line)
5835 error(filename, linenum,
'readability/inheritance', 4,
5836 (
'"virtual" is redundant since function is ' 5837 'already declared as "%s"' % match.group(1)))
5842 if Search(
r'[^\w]\s*$', line):
5847 """Check if line contains a redundant "override" or "final" virt-specifier. 5850 filename: The name of the current file. 5851 clean_lines: A CleansedLines instance containing the file. 5852 linenum: The number of the line to check. 5853 error: The function to call with any errors found. 5858 line = clean_lines.elided[linenum]
5859 declarator_end = line.rfind(
')')
5860 if declarator_end >= 0:
5861 fragment = line[declarator_end:]
5863 if linenum > 1
and clean_lines.elided[linenum - 1].rfind(
')') >= 0:
5869 if Search(
r'\boverride\b', fragment)
and Search(
r'\bfinal\b', fragment):
5870 error(filename, linenum,
'readability/inheritance', 4,
5871 (
'"override" is redundant since function is ' 5872 'already declared as "final"'))
5880 """Checks that the new block is directly in a namespace. 5883 nesting_state: The _NestingState object that contains info about our state. 5884 is_forward_declaration: If the class is a forward declared class. 5886 Whether or not the new block is directly in a namespace. 5888 if is_forward_declaration:
5889 return len(nesting_state.stack) >= 1
and (
5890 isinstance(nesting_state.stack[-1], _NamespaceInfo))
5893 return (
len(nesting_state.stack) > 1
and 5894 nesting_state.stack[-1].check_namespace_indentation
and 5895 isinstance(nesting_state.stack[-2], _NamespaceInfo))
5899 raw_lines_no_comments, linenum):
5900 """This method determines if we should apply our namespace indentation check. 5903 nesting_state: The current nesting state. 5904 is_namespace_indent_item: If we just put a new class on the stack, True. 5905 If the top of the stack is not a class, or we did not recently 5906 add the class, False. 5907 raw_lines_no_comments: The lines without the comments. 5908 linenum: The current line number we are processing. 5911 True if we should apply our namespace indentation check. Currently, it 5912 only works for classes and namespaces inside of a namespace. 5918 if not (is_namespace_indent_item
or is_forward_declaration):
5933 line = raw_lines_no_comments[linenum]
5934 if Match(
r'^\s+', line):
5935 error(filename, linenum,
'runtime/indentation_namespace', 4,
5936 'Do not indent within a namespace')
5939 def ProcessLine(filename, file_extension, clean_lines, line,
5940 include_state, function_state, nesting_state, error,
5941 extra_check_functions=None):
5942 """Processes a single line in the file. 5945 filename: Filename of the file that is being processed. 5946 file_extension: The extension (dot not included) of the file. 5947 clean_lines: An array of strings, each representing a line of the file, 5948 with comments stripped. 5949 line: Number of line being processed. 5950 include_state: An _IncludeState instance in which the headers are inserted. 5951 function_state: A _FunctionState instance which counts function lines, etc. 5952 nesting_state: A NestingState instance which maintains information about 5953 the current stack of nested blocks being parsed. 5954 error: A callable to which errors are reported, which takes 4 arguments: 5955 filename, line number, error level, and message 5956 extra_check_functions: An array of additional check functions that will be 5957 run on each source line. Each function takes 4 5958 arguments: filename, clean_lines, line, error 5960 raw_lines = clean_lines.raw_lines
5962 nesting_state.Update(filename, clean_lines, line, error)
5965 if nesting_state.InAsmBlock():
return 5968 CheckStyle(filename, clean_lines, line, file_extension, nesting_state, error)
5969 CheckLanguage(filename, clean_lines, line, file_extension, include_state,
5970 nesting_state, error)
5973 nesting_state, error)
5980 if extra_check_functions:
5981 for check_fn
in extra_check_functions:
5982 check_fn(filename, clean_lines, line, error)
5985 """Flag those c++11 features that we only allow in certain places. 5988 filename: The name of the current file. 5989 clean_lines: A CleansedLines instance containing the file. 5990 linenum: The number of the line to check. 5991 error: The function to call with any errors found. 5993 line = clean_lines.elided[linenum]
5995 include =
Match(
r'\s*#\s*include\s+[<"]([^<"]+)[">]', line)
5998 if include
and include.group(1).startswith(
'tr1/'):
5999 error(filename, linenum,
'build/c++tr1', 5,
6000 (
'C++ TR1 headers such as <%s> are unapproved.') % include.group(1))
6003 if include
and include.group(1)
in (
'cfenv',
6004 'condition_variable',
6014 error(filename, linenum,
'build/c++11', 5,
6015 (
'<%s> is an unapproved C++11 header.') % include.group(1))
6019 if Match(
r'\s*#', line)
and not Match(
r'\s*#\s*define\b', line):
return 6029 if Search(
r'\bstd::%s\b' % top_name, line):
6030 error(filename, linenum,
'build/c++11', 5,
6031 (
'std::%s is an unapproved C++11 class or function. Send c-style ' 6032 'an example of where it would make your code more readable, and ' 6033 'they may let you use it.') % top_name)
6037 """Flag those C++14 features that we restrict. 6040 filename: The name of the current file. 6041 clean_lines: A CleansedLines instance containing the file. 6042 linenum: The number of the line to check. 6043 error: The function to call with any errors found. 6045 line = clean_lines.elided[linenum]
6047 include =
Match(
r'\s*#\s*include\s+[<"]([^<"]+)[">]', line)
6050 if include
and include.group(1)
in (
'scoped_allocator',
'shared_mutex'):
6051 error(filename, linenum,
'build/c++14', 5,
6052 (
'<%s> is an unapproved C++14 header.') % include.group(1))
6056 extra_check_functions=None):
6057 """Performs lint checks and reports any errors to the given error function. 6060 filename: Filename of the file that is being processed. 6061 file_extension: The extension (dot not included) of the file. 6062 lines: An array of strings, each representing a line of the file, with the 6063 last element being empty if the file is terminated with a newline. 6064 error: A callable to which errors are reported, which takes 4 arguments: 6065 filename, line number, error level, and message 6066 extra_check_functions: An array of additional check functions that will be 6067 run on each source line. Each function takes 4 6068 arguments: filename, clean_lines, line, error 6070 lines = ([
'// marker so line numbers and indices both start at 1'] + lines +
6071 [
'// marker so line numbers end in a known way'])
6087 for line
in range(clean_lines.NumLines()):
6088 ProcessLine(filename, file_extension, clean_lines, line,
6089 include_state, function_state, nesting_state, error,
6090 extra_check_functions)
6092 nesting_state.CheckCompletedBlocks(filename, error)
6107 """ Loads the configuration files and processes the config overrides. 6110 filename: The name of the file being processed by the linter. 6113 False if the current |filename| should not be processed further. 6116 abs_filename = os.path.abspath(filename)
6120 abs_path, base_name = os.path.split(abs_filename)
6124 cfg_file = os.path.join(abs_path,
"CPPLINT.cfg")
6125 abs_filename = abs_path
6126 if not os.path.isfile(cfg_file):
6130 with open(cfg_file)
as file_handle:
6131 for line
in file_handle:
6132 line, _, _ = line.partition(
'#')
6133 if not line.strip():
6136 name, _, val = line.partition(
'=')
6139 if name ==
'set noparent':
6140 keep_looking =
False 6141 elif name ==
'filter':
6142 cfg_filters.append(val)
6143 elif name ==
'exclude_files':
6151 pattern = re.compile(val)
6152 if pattern.match(base_name):
6153 _cpplint_state.PrintInfo(
'Ignoring "%s": file excluded by ' 6154 '"%s". File path component "%s" matches pattern "%s"\n' %
6155 (filename, cfg_file, base_name, val))
6157 elif name ==
'linelength':
6160 _line_length = int(val)
6162 _cpplint_state.PrintError(
'Line length must be numeric.')
6163 elif name ==
'extensions':
6164 global _valid_extensions
6166 extensions = [ext.strip()
for ext
in val.split(
',')]
6167 _valid_extensions =
set(extensions)
6169 sys.stderr.write(
'Extensions should be a comma-separated list of values;' 6170 'for example: extensions=hpp,cpp\n' 6171 'This could not be parsed: "%s"' % (val,))
6172 elif name ==
'headers':
6173 global _header_extensions
6175 extensions = [ext.strip()
for ext
in val.split(
',')]
6176 _header_extensions =
set(extensions)
6178 sys.stderr.write(
'Extensions should be a comma-separated list of values;' 6179 'for example: extensions=hpp,cpp\n' 6180 'This could not be parsed: "%s"' % (val,))
6181 elif name ==
'root':
6185 _cpplint_state.PrintError(
6186 'Invalid configuration option (%s) in file %s\n' %
6190 _cpplint_state.PrintError(
6191 "Skipping config file '%s': Can't open for reading\n" % cfg_file)
6192 keep_looking =
False 6196 for cfg_filter
in reversed(cfg_filters):
6202 def ProcessFile(filename, vlevel, extra_check_functions=None):
6203 """Does google-lint on a single file. 6206 filename: The name of the file to parse. 6208 vlevel: The level of errors to report. Every error of confidence 6209 >= verbose_level will be reported. 0 is a good default. 6211 extra_check_functions: An array of additional check functions that will be 6212 run on each source line. Each function takes 4 6213 arguments: filename, clean_lines, line, error 6234 lines = codecs.StreamReaderWriter(sys.stdin,
6235 codecs.getreader(
'utf8'),
6236 codecs.getwriter(
'utf8'),
6237 'replace').read().split(
'\n')
6239 lines = codecs.open(filename,
'r', 'utf8', 'replace').read().split('\n')
6243 for linenum
in range(
len(lines) - 1):
6244 if lines[linenum].endswith(
'\r'):
6245 lines[linenum] = lines[linenum].rstrip(
'\r')
6246 crlf_lines.append(linenum + 1)
6248 lf_lines.append(linenum + 1)
6251 _cpplint_state.PrintError(
6252 "Skipping input '%s': Can't open for reading\n" % filename)
6257 file_extension = filename[filename.rfind(
'.') + 1:]
6262 _cpplint_state.PrintError(
'Ignoring %s; not a valid file name ' 6266 extra_check_functions)
6278 if lf_lines
and crlf_lines:
6282 for linenum
in crlf_lines:
6283 Error(filename, linenum,
'whitespace/newline', 1,
6284 'Unexpected \\r (^M) found; better to use only \\n')
6286 _cpplint_state.PrintInfo(
'Done processing %s\n' % filename)
6291 """Prints a brief usage string and exits, optionally with an error message. 6294 message: The optional error message. 6296 sys.stderr.write(_USAGE)
6299 sys.exit(
'\nFATAL ERROR: ' + message)
6305 """Prints a list of all the error-categories used by error messages. 6307 These are the categories used to filter messages via --filter. 6309 sys.stderr.write(
''.join(
' %s\n' % cat
for cat
in _ERROR_CATEGORIES))
6314 """Parses the command line arguments. 6316 This may set the output format and verbosity level as side-effects. 6319 args: The command line arguments: 6322 The list of filenames to lint. 6325 (opts, filenames) = getopt.getopt(args,
'', [
'help',
'output=',
'verbose=',
6336 except getopt.GetoptError:
6345 for (opt, val)
in opts:
6348 elif opt ==
'--output':
6349 if val
not in (
'emacs',
'vs7',
'eclipse',
'junit'):
6350 PrintUsage(
'The only allowed output formats are emacs, vs7, eclipse ' 6353 elif opt ==
'--verbose':
6354 verbosity = int(val)
6355 elif opt ==
'--filter':
6359 elif opt ==
'--counting':
6360 if val
not in (
'total',
'toplevel',
'detailed'):
6361 PrintUsage(
'Valid counting options are total, toplevel, and detailed')
6362 counting_style = val
6363 elif opt ==
'--root':
6366 elif opt ==
'--repository':
6369 elif opt ==
'--linelength':
6372 _line_length = int(val)
6375 elif opt ==
'--exclude':
6379 _excludes.update(glob.glob(val))
6380 elif opt ==
'--extensions':
6381 global _valid_extensions
6383 _valid_extensions =
set(val.split(
','))
6385 PrintUsage(
'Extensions must be comma seperated list.')
6386 elif opt ==
'--headers':
6387 global _header_extensions
6389 _header_extensions =
set(val.split(
','))
6391 PrintUsage(
'Extensions must be comma seperated list.')
6392 elif opt ==
'--recursive':
6394 elif opt ==
'--quiet':
6415 """Searches a list of filenames and replaces directories in the list with 6416 all files descending from those directories. Files with extensions not in 6417 the valid extensions list are excluded. 6420 filenames: A list of files or directories 6423 A list of all files that are members of filenames or descended from a 6424 directory in filenames 6427 for filename
in filenames:
6428 if not os.path.isdir(filename):
6429 expanded.add(filename)
6432 for root, _, files
in os.walk(filename):
6433 for loopfile
in files:
6434 fullname = os.path.join(root, loopfile)
6435 if fullname.startswith(
'.' + os.path.sep):
6436 fullname = fullname[
len(
'.' + os.path.sep):]
6437 expanded.add(fullname)
6440 for filename
in expanded:
6442 filtered.append(filename)
6447 """Filters out files listed in the --exclude command line switch. File paths 6448 in the switch are evaluated relative to the current working directory 6450 exclude_paths = [os.path.abspath(f)
for f
in _excludes]
6451 return [f
for f
in filenames
if os.path.abspath(f)
not in exclude_paths]
6455 backup_err = sys.stderr
6459 sys.stderr = codecs.StreamReader(sys.stderr,
'replace')
6461 _cpplint_state.ResetErrorCounts()
6462 for filename
in filenames:
6463 ProcessFile(filename, _cpplint_state.verbose_level)
6464 _cpplint_state.PrintErrorCounts()
6466 if _cpplint_state.output_format ==
'junit':
6467 sys.stderr.write(_cpplint_state.FormatJUnitXML())
6470 sys.stderr = backup_err
6472 sys.exit(_cpplint_state.error_count > 0)
6475 if __name__ ==
'__main__':
def Update(self, filename, clean_lines, linenum, error)
def CleanseRawStrings(raw_lines)
def IsBlockInNameSpace(nesting_state, is_forward_declaration)
def CheckIncludeLine(filename, clean_lines, linenum, include_state, error)
def CheckPrintf(filename, clean_lines, linenum, error)
def CheckRedundantOverrideOrFinal(filename, clean_lines, linenum, error)
def ParseNolintSuppressions(filename, raw_line, linenum, error)
def CheckParenthesisSpacing(filename, clean_lines, linenum, error)
def CheckForNewlineAtEOF(filename, lines, error)
def CheckCommaSpacing(filename, clean_lines, linenum, error)
def CheckEnd(self, filename, clean_lines, linenum, error)
def ShouldCheckNamespaceIndentation(nesting_state, is_namespace_indent_item, raw_lines_no_comments, linenum)
def CheckHeaderFileIncluded(filename, include_state, error)
def SetOutputFormat(self, output_format)
def CheckSpacing(filename, clean_lines, linenum, nesting_state, error)
def CheckAccess(filename, clean_lines, linenum, nesting_state, error)
def _CollapseStrings(elided)
def CleanseComments(line)
def RemoveMultiLineCommentsFromRange(lines, begin, end)
def SetLastHeader(self, header_path)
def _IsSourceExtension(s)
def CheckCStyleCast(filename, clean_lines, linenum, cast_type, pattern, error)
def IsMacroDefinition(clean_lines, linenum)
def _SetOutputFormat(output_format)
def CheckBracesSpacing(filename, clean_lines, linenum, nesting_state, error)
def ResetSection(self, directive)
def FilesBelongToSameModule(filename_cc, filename_h)
def FlagCxx14Features(filename, clean_lines, linenum, error)
def CheckLanguage(filename, clean_lines, linenum, file_extension, include_state, nesting_state, error)
def __init__(self, filename)
def CheckForNonConstReference(filename, clean_lines, linenum, nesting_state, error)
def InTemplateArgumentList(self, clean_lines, linenum, pos)
def CheckPosixThreading(filename, clean_lines, linenum, error)
lines_without_raw_strings
def _ShouldPrintError(category, confidence, linenum)
def AddFilters(self, filters)
def _ClassifyInclude(fileinfo, include, is_system)
def Begin(self, function_name)
def CheckBegin(self, filename, clean_lines, linenum, error)
def CheckSpacingForFunctionCall(filename, clean_lines, linenum, error)
def _DropCommonSuffixes(filename)
def CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error, io=codecs)
def CheckRedundantVirtual(filename, clean_lines, linenum, error)
def FindStartOfExpressionInLine(line, endpos, stack)
def SetCountingStyle(self, counting_style)
def _ExpandDirectories(filenames)
subroutine upper(string, length)
def IsDecltype(clean_lines, linenum, column)
def _IsType(clean_lines, nesting_state, expr)
def ExpectingFunctionArgs(clean_lines, linenum)
def _SetVerboseLevel(level)
def RemoveMultiLineComments(filename, lines, error)
def CheckForHeaderGuard(filename, clean_lines, error)
def FindNextMultiLineCommentEnd(lines, lineix)
def GetHeaderExtensions()
def ResetNolintSuppressions()
def CheckComment(line, filename, linenum, next_line_start, error)
def CheckBraces(filename, clean_lines, linenum, error)
def Check(self, error, filename, linenum)
def ProcessConfigOverrides(filename)
check_namespace_indentation
def __init__(self, name, linenum)
def CheckForCopyright(filename, lines, error)
def CloseExpression(clean_lines, linenum, pos)
def CheckNextIncludeOrder(self, header_type)
def FindEndOfExpressionInLine(line, startpos, stack)
def GetHeaderGuardCPPVariable(filename)
def FlagCxx11Features(filename, clean_lines, linenum, error)
def CheckVlogArguments(filename, clean_lines, linenum, error)
def CheckCompletedBlocks(self, filename, error)
def CheckForBadCharacters(filename, lines, error)
def FindHeader(self, header)
def InNamespaceBody(self)
def CheckCheck(filename, clean_lines, linenum, error)
def UpdateIncludeState(filename, include_dict, io=codecs)
def CheckEmptyBlockBody(filename, clean_lines, linenum, error)
def ProcessFile(filename, vlevel, extra_check_functions=None)
def unicode_escape_decode(x)
def GetPreviousNonBlankLine(clean_lines, linenum)
def CheckCasts(filename, clean_lines, linenum, error)
def CheckGlobalStatic(filename, clean_lines, linenum, error)
def CheckForNamespaceIndentation(filename, nesting_state, clean_lines, line, error)
def Error(filename, linenum, category, confidence, message)
def SetVerboseLevel(self, level)
def PrintErrorCounts(self)
def PrintError(self, message)
def __init__(self, name, class_or_struct, clean_lines, linenum)
def _FilterExcludedFiles(filenames)
def AddJUnitFailure(self, filename, linenum, message, category, confidence)
def IsOutOfLineMethodDefinition(clean_lines, linenum)
def IsInAlphabeticalOrder(self, clean_lines, linenum, header_path)
def InClassDeclaration(self)
def CheckTrailingSemicolon(filename, clean_lines, linenum, error)
def CheckAltTokens(filename, clean_lines, linenum, error)
def CanonicalizeAlphabeticalOrder(self, header_path)
def ProcessLine(filename, file_extension, clean_lines, line, include_state, function_state, nesting_state, error, extra_check_functions=None)
def IsDerivedFunction(clean_lines, linenum)
def CheckStyle(filename, clean_lines, linenum, file_extension, nesting_state, error)
def UpdatePreprocessor(self, line)
def CheckForMultilineCommentsAndStrings(filename, clean_lines, linenum, error)
def __init__(self, stack_before_if)
def CheckBegin(self, filename, clean_lines, linenum, error)
def IsErrorSuppressedByNolint(category, linenum)
def FindNextMultiLineCommentStart(lines, lineix)
def CheckSectionSpacing(filename, clean_lines, class_info, linenum, error)
def __init__(self, linenum, seen_open_brace)
def CheckEnd(self, filename, clean_lines, linenum, error)
def __init__(self, lines)
def GetNonHeaderExtensions()
def CheckForFunctionLengths(filename, clean_lines, linenum, function_state, error)
def CheckMakePairUsesDeduction(filename, clean_lines, linenum, error)
def CheckEnd(self, filename, clean_lines, linenum, error)
def CheckOperatorSpacing(filename, clean_lines, linenum, error)
def CheckItemIndentationInNamespace(filename, raw_lines_no_comments, linenum, error)
def ReplaceAll(pattern, rep, s)
def __init__(self, linenum)
dictionary _SECTION_NAMES
def CheckForNonStandardConstructs(filename, clean_lines, linenum, nesting_state, error)
def ProcessGlobalSuppresions(lines)
def IncrementErrorCount(self, category)
def ResetErrorCounts(self)
def ProcessFileData(filename, file_extension, lines, error, extra_check_functions=None)
def _SetCountingStyle(level)
def IsForwardClassDeclaration(clean_lines, linenum)
def _GetTextInside(text, start_pattern)
def SetFilters(self, filters)
def IsInitializerList(clean_lines, linenum)
def CheckInvalidIncrement(filename, clean_lines, linenum, error)
def PrintInfo(self, message)
def ReverseCloseExpression(clean_lines, linenum, pos)