1#!/usr/bin/env python 2# 3# Copyright (c) 2009 Google Inc. All rights reserved. 4# 5# Redistribution and use in source and binary forms, with or without 6# modification, are permitted provided that the following conditions are 7# met: 8# 9# * Redistributions of source code must retain the above copyright 10# notice, this list of conditions and the following disclaimer. 11# * Redistributions in binary form must reproduce the above 12# copyright notice, this list of conditions and the following disclaimer 13# in the documentation and/or other materials provided with the 14# distribution. 15# * Neither the name of Google Inc. nor the names of its 16# contributors may be used to endorse or promote products derived from 17# this software without specific prior written permission. 18# 19# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31"""Does google-lint on c++ files. 32 33The goal of this script is to identify places in the code that *may* 34be in non-compliance with google style. It does not attempt to fix 35up these problems -- the point is to educate. It does also not 36attempt to find all problems, or to ensure that everything it does 37find is legitimately a problem. 38 39In particular, we can get very confused by /* and // inside strings! 40We do a small hack, which is to ignore //'s with "'s after them on the 41same line, but it is far from perfect (in either direction). 42""" 43 44import codecs 45import copy 46import getopt 47import glob 48import itertools 49import math # for log 50import os 51import re 52import sre_compile 53import string 54import sys 55import sysconfig 56import unicodedata 57import xml.etree.ElementTree 58 59# if empty, use defaults 60_valid_extensions = set([]) 61 62__VERSION__ = '1.4.6' 63 64try: 65 xrange # Python 2 66except NameError: 67 # -- pylint: disable=redefined-builtin 68 xrange = range # Python 3 69 70 71_USAGE = """ 72Syntax: cpplint.py [--verbose=#] [--output=emacs|eclipse|vs7|junit] 73 [--filter=-x,+y,...] 74 [--counting=total|toplevel|detailed] [--root=subdir] 75 [--repository=path] 76 [--linelength=digits] [--headers=x,y,...] 77 [--recursive] 78 [--exclude=path] 79 [--extensions=hpp,cpp,...] 80 [--quiet] 81 [--version] 82 <file> [file] ... 83 84 Style checker for C/C++ source files. 85 This is a fork of the Google style checker with minor extensions. 86 87 The style guidelines this tries to follow are those in 88 https://google.github.io/styleguide/cppguide.html 89 90 Every problem is given a confidence score from 1-5, with 5 meaning we are 91 certain of the problem, and 1 meaning it could be a legitimate construct. 92 This will miss some errors, and is not a substitute for a code review. 93 94 To suppress false-positive errors of a certain category, add a 95 'NOLINT(category)' comment to the line. NOLINT or NOLINT(*) 96 suppresses errors of all categories on that line. 97 98 The files passed in will be linted; at least one file must be provided. 99 Default linted extensions are %s. 100 Other file types will be ignored. 101 Change the extensions with the --extensions flag. 102 103 Flags: 104 105 output=emacs|eclipse|vs7|junit 106 By default, the output is formatted to ease emacs parsing. Visual Studio 107 compatible output (vs7) may also be used. Further support exists for 108 eclipse (eclipse), and JUnit (junit). XML parsers such as those used 109 in Jenkins and Bamboo may also be used. Other formats are unsupported. 110 111 verbose=# 112 Specify a number 0-5 to restrict errors to certain verbosity levels. 113 Errors with lower verbosity levels have lower confidence and are more 114 likely to be false positives. 115 116 quiet 117 Don't print anything if no errors are found. 118 119 filter=-x,+y,... 120 Specify a comma-separated list of category-filters to apply: only 121 error messages whose category names pass the filters will be printed. 122 (Category names are printed with the message and look like 123 "[whitespace/indent]".) Filters are evaluated left to right. 124 "-FOO" and "FOO" means "do not print categories that start with FOO". 125 "+FOO" means "do print categories that start with FOO". 126 127 Examples: --filter=-whitespace,+whitespace/braces 128 --filter=whitespace,runtime/printf,+runtime/printf_format 129 --filter=-,+build/include_what_you_use 130 131 To see a list of all the categories used in cpplint, pass no arg: 132 --filter= 133 134 counting=total|toplevel|detailed 135 The total number of errors found is always printed. If 136 'toplevel' is provided, then the count of errors in each of 137 the top-level categories like 'build' and 'whitespace' will 138 also be printed. If 'detailed' is provided, then a count 139 is provided for each category like 'build/class'. 140 141 repository=path 142 The top level directory of the repository, used to derive the header 143 guard CPP variable. By default, this is determined by searching for a 144 path that contains .git, .hg, or .svn. When this flag is specified, the 145 given path is used instead. This option allows the header guard CPP 146 variable to remain consistent even if members of a team have different 147 repository root directories (such as when checking out a subdirectory 148 with SVN). In addition, users of non-mainstream version control systems 149 can use this flag to ensure readable header guard CPP variables. 150 151 Examples: 152 Assuming that Alice checks out ProjectName and Bob checks out 153 ProjectName/trunk and trunk contains src/chrome/ui/browser.h, then 154 with no --repository flag, the header guard CPP variable will be: 155 156 Alice => TRUNK_SRC_CHROME_BROWSER_UI_BROWSER_H_ 157 Bob => SRC_CHROME_BROWSER_UI_BROWSER_H_ 158 159 If Alice uses the --repository=trunk flag and Bob omits the flag or 160 uses --repository=. then the header guard CPP variable will be: 161 162 Alice => SRC_CHROME_BROWSER_UI_BROWSER_H_ 163 Bob => SRC_CHROME_BROWSER_UI_BROWSER_H_ 164 165 root=subdir 166 The root directory used for deriving header guard CPP variable. 167 This directory is relative to the top level directory of the repository 168 which by default is determined by searching for a directory that contains 169 .git, .hg, or .svn but can also be controlled with the --repository flag. 170 If the specified directory does not exist, this flag is ignored. 171 172 Examples: 173 Assuming that src is the top level directory of the repository (and 174 cwd=top/src), the header guard CPP variables for 175 src/chrome/browser/ui/browser.h are: 176 177 No flag => CHROME_BROWSER_UI_BROWSER_H_ 178 --root=chrome => BROWSER_UI_BROWSER_H_ 179 --root=chrome/browser => UI_BROWSER_H_ 180 --root=.. => SRC_CHROME_BROWSER_UI_BROWSER_H_ 181 182 linelength=digits 183 This is the allowed line length for the project. The default value is 184 80 characters. 185 186 Examples: 187 --linelength=120 188 189 recursive 190 Search for files to lint recursively. Each directory given in the list 191 of files to be linted is replaced by all files that descend from that 192 directory. Files with extensions not in the valid extensions list are 193 excluded. 194 195 exclude=path 196 Exclude the given path from the list of files to be linted. Relative 197 paths are evaluated relative to the current directory and shell globbing 198 is performed. This flag can be provided multiple times to exclude 199 multiple files. 200 201 Examples: 202 --exclude=one.cc 203 --exclude=src/*.cc 204 --exclude=src/*.cc --exclude=test/*.cc 205 206 extensions=extension,extension,... 207 The allowed file extensions that cpplint will check 208 209 Examples: 210 --extensions=%s 211 212 headers=x,y,... 213 The header extensions that cpplint will treat as .h in checks. Values are 214 automatically added to --extensions list. 215 (by default, only files with extensions %s will be assumed to be headers) 216 217 Examples: 218 --headers=%s 219 --headers=hpp,hxx 220 --headers=hpp 221 222 cpplint.py supports per-directory configurations specified in CPPLINT.cfg 223 files. CPPLINT.cfg file can contain a number of key=value pairs. 224 Currently the following options are supported: 225 226 set noparent 227 filter=+filter1,-filter2,... 228 exclude_files=regex 229 linelength=80 230 root=subdir 231 headers=x,y,... 232 233 "set noparent" option prevents cpplint from traversing directory tree 234 upwards looking for more .cfg files in parent directories. This option 235 is usually placed in the top-level project directory. 236 237 The "filter" option is similar in function to --filter flag. It specifies 238 message filters in addition to the |_DEFAULT_FILTERS| and those specified 239 through --filter command-line flag. 240 241 "exclude_files" allows to specify a regular expression to be matched against 242 a file name. If the expression matches, the file is skipped and not run 243 through the linter. 244 245 "linelength" allows to specify the allowed line length for the project. 246 247 The "root" option is similar in function to the --root flag (see example 248 above). Paths are relative to the directory of the CPPLINT.cfg. 249 250 The "headers" option is similar in function to the --headers flag 251 (see example above). 252 253 CPPLINT.cfg has an effect on files in the same directory and all 254 sub-directories, unless overridden by a nested configuration file. 255 256 Example file: 257 filter=-build/include_order,+build/include_alpha 258 exclude_files=.*\\.cc 259 260 The above example disables build/include_order warning and enables 261 build/include_alpha as well as excludes all .cc from being 262 processed by linter, in the current directory (where the .cfg 263 file is located) and all sub-directories. 264""" 265 266# We categorize each error message we print. Here are the categories. 267# We want an explicit list so we can list them all in cpplint --filter=. 268# If you add a new error message with a new category, add it to the list 269# here! cpplint_unittest.py should tell you if you forget to do this. 270_ERROR_CATEGORIES = [ 271 'build/class', 272 'build/c++11', 273 'build/c++14', 274 'build/c++tr1', 275 'build/deprecated', 276 'build/endif_comment', 277 'build/explicit_make_pair', 278 'build/forward_decl', 279 'build/header_guard', 280 'build/include', 281 'build/include_subdir', 282 'build/include_alpha', 283 'build/include_inline', 284 'build/include_order', 285 'build/include_what_you_use', 286 'build/namespaces_literals', 287 'build/namespaces', 288 'build/printf_format', 289 'build/storage_class', 290 'legal/copyright', 291 'readability/alt_tokens', 292 'readability/braces', 293 'readability/casting', 294 'readability/check', 295 'readability/constructors', 296 'readability/fn_size', 297 'readability/inheritance', 298 'readability/pointer_notation', 299 'readability/multiline_comment', 300 'readability/multiline_string', 301 'readability/namespace', 302 'readability/nolint', 303 'readability/nul', 304 'readability/null_usage', 305 'readability/strings', 306 'readability/todo', 307 'readability/utf8', 308 'runtime/arrays', 309 'runtime/casting', 310 'runtime/explicit', 311 'runtime/int', 312 'runtime/init', 313 'runtime/invalid_increment', 314 'runtime/member_string_references', 315 'runtime/memset', 316 'runtime/indentation_namespace', 317 'runtime/operator', 318 'runtime/printf', 319 'runtime/printf_format', 320 'runtime/references', 321 'runtime/string', 322 'runtime/threadsafe_fn', 323 'runtime/vlog', 324 'runtime/v8_persistent', 325 'whitespace/blank_line', 326 'whitespace/braces', 327 'whitespace/comma', 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', 335 'whitespace/indent', 336 'whitespace/line_length', 337 'whitespace/newline', 338 'whitespace/operators', 339 'whitespace/parens', 340 'whitespace/semicolon', 341 'whitespace/tab', 342 'whitespace/todo', 343 ] 344 345# These error categories are no longer enforced by cpplint, but for backwards- 346# compatibility they may still appear in NOLINT comments. 347_LEGACY_ERROR_CATEGORIES = [ 348 'readability/streams', 349 'readability/function', 350 ] 351 352# The default state of the category filter. This is overridden by the --filter= 353# flag. By default all errors are on, so only add here categories that should be 354# off by default (i.e., categories that must be enabled by the --filter= flags). 355# All entries here should start with a '-' or '+', as in the --filter= flag. 356_DEFAULT_FILTERS = ['-build/include_alpha'] 357 358# The default list of categories suppressed for C (not C++) files. 359_DEFAULT_C_SUPPRESSED_CATEGORIES = [ 360 'readability/casting', 361 ] 362 363# The default list of categories suppressed for Linux Kernel files. 364_DEFAULT_KERNEL_SUPPRESSED_CATEGORIES = [ 365 'whitespace/tab', 366 ] 367 368# We used to check for high-bit characters, but after much discussion we 369# decided those were OK, as long as they were in UTF-8 and didn't represent 370# hard-coded international strings, which belong in a separate i18n file. 371 372# C++ headers 373_CPP_HEADERS = frozenset([ 374 # Legacy 375 'algobase.h', 376 'algo.h', 377 'alloc.h', 378 'builtinbuf.h', 379 'bvector.h', 380 'complex.h', 381 'defalloc.h', 382 'deque.h', 383 'editbuf.h', 384 'fstream.h', 385 'function.h', 386 'hash_map', 387 'hash_map.h', 388 'hash_set', 389 'hash_set.h', 390 'hashtable.h', 391 'heap.h', 392 'indstream.h', 393 'iomanip.h', 394 'iostream.h', 395 'istream.h', 396 'iterator.h', 397 'list.h', 398 'map.h', 399 'multimap.h', 400 'multiset.h', 401 'ostream.h', 402 'pair.h', 403 'parsestream.h', 404 'pfstream.h', 405 'procbuf.h', 406 'pthread_alloc', 407 'pthread_alloc.h', 408 'rope', 409 'rope.h', 410 'ropeimpl.h', 411 'set.h', 412 'slist', 413 'slist.h', 414 'stack.h', 415 'stdiostream.h', 416 'stl_alloc.h', 417 'stl_relops.h', 418 'streambuf.h', 419 'stream.h', 420 'strfile.h', 421 'strstream.h', 422 'tempbuf.h', 423 'tree.h', 424 'type_traits.h', 425 'vector.h', 426 # 17.6.1.2 C++ library headers 427 'algorithm', 428 'array', 429 'atomic', 430 'bitset', 431 'chrono', 432 'codecvt', 433 'complex', 434 'condition_variable', 435 'deque', 436 'exception', 437 'forward_list', 438 'fstream', 439 'functional', 440 'future', 441 'initializer_list', 442 'iomanip', 443 'ios', 444 'iosfwd', 445 'iostream', 446 'istream', 447 'iterator', 448 'limits', 449 'list', 450 'locale', 451 'map', 452 'memory', 453 'mutex', 454 'new', 455 'numeric', 456 'ostream', 457 'queue', 458 'random', 459 'ratio', 460 'regex', 461 'scoped_allocator', 462 'set', 463 'sstream', 464 'stack', 465 'stdexcept', 466 'streambuf', 467 'string', 468 'strstream', 469 'system_error', 470 'thread', 471 'tuple', 472 'typeindex', 473 'typeinfo', 474 'type_traits', 475 'unordered_map', 476 'unordered_set', 477 'utility', 478 'valarray', 479 'vector', 480 # 17.6.1.2 C++14 headers 481 'shared_mutex', 482 # 17.6.1.2 C++17 headers 483 'any', 484 'charconv', 485 'codecvt', 486 'execution', 487 'filesystem', 488 'memory_resource', 489 'optional', 490 'string_view', 491 'variant', 492 # 17.6.1.2 C++ headers for C library facilities 493 'cassert', 494 'ccomplex', 495 'cctype', 496 'cerrno', 497 'cfenv', 498 'cfloat', 499 'cinttypes', 500 'ciso646', 501 'climits', 502 'clocale', 503 'cmath', 504 'csetjmp', 505 'csignal', 506 'cstdalign', 507 'cstdarg', 508 'cstdbool', 509 'cstddef', 510 'cstdint', 511 'cstdio', 512 'cstdlib', 513 'cstring', 514 'ctgmath', 515 'ctime', 516 'cuchar', 517 'cwchar', 518 'cwctype', 519 ]) 520 521# Type names 522_TYPES = re.compile( 523 r'^(?:' 524 # [dcl.type.simple] 525 r'(char(16_t|32_t)?)|wchar_t|' 526 r'bool|short|int|long|signed|unsigned|float|double|' 527 # [support.types] 528 r'(ptrdiff_t|size_t|max_align_t|nullptr_t)|' 529 # [cstdint.syn] 530 r'(u?int(_fast|_least)?(8|16|32|64)_t)|' 531 r'(u?int(max|ptr)_t)|' 532 r')$') 533 534 535# These headers are excluded from [build/include] and [build/include_order] 536# checks: 537# - Anything not following google file name conventions (containing an 538# uppercase character, such as Python.h or nsStringAPI.h, for example). 539# - Lua headers. 540_THIRD_PARTY_HEADERS_PATTERN = re.compile( 541 r'^(?:[^/]*[A-Z][^/]*\.h|lua\.h|lauxlib\.h|lualib\.h)$') 542 543# Pattern for matching FileInfo.BaseName() against test file name 544_test_suffixes = ['_test', '_regtest', '_unittest'] 545_TEST_FILE_SUFFIX = '(' + '|'.join(_test_suffixes) + r')$' 546 547# Pattern that matches only complete whitespace, possibly across multiple lines. 548_EMPTY_CONDITIONAL_BODY_PATTERN = re.compile(r'^\s*$', re.DOTALL) 549 550# Assertion macros. These are defined in base/logging.h and 551# testing/base/public/gunit.h. 552_CHECK_MACROS = [ 553 'DCHECK', 'CHECK', 554 'EXPECT_TRUE', 'ASSERT_TRUE', 555 'EXPECT_FALSE', 'ASSERT_FALSE', 556 ] 557 558# Replacement macros for CHECK/DCHECK/EXPECT_TRUE/EXPECT_FALSE 559_CHECK_REPLACEMENT = dict([(macro_var, {}) for macro_var in _CHECK_MACROS]) 560 561for op, replacement in [('==', 'EQ'), ('!=', 'NE'), 562 ('>=', 'GE'), ('>', 'GT'), 563 ('<=', 'LE'), ('<', 'LT')]: 564 _CHECK_REPLACEMENT['DCHECK'][op] = 'DCHECK_%s' % replacement 565 _CHECK_REPLACEMENT['CHECK'][op] = 'CHECK_%s' % replacement 566 _CHECK_REPLACEMENT['EXPECT_TRUE'][op] = 'EXPECT_%s' % replacement 567 _CHECK_REPLACEMENT['ASSERT_TRUE'][op] = 'ASSERT_%s' % replacement 568 569for op, inv_replacement in [('==', 'NE'), ('!=', 'EQ'), 570 ('>=', 'LT'), ('>', 'LE'), 571 ('<=', 'GT'), ('<', 'GE')]: 572 _CHECK_REPLACEMENT['EXPECT_FALSE'][op] = 'EXPECT_%s' % inv_replacement 573 _CHECK_REPLACEMENT['ASSERT_FALSE'][op] = 'ASSERT_%s' % inv_replacement 574 575# Alternative tokens and their replacements. For full list, see section 2.5 576# Alternative tokens [lex.digraph] in the C++ standard. 577# 578# Digraphs (such as '%:') are not included here since it's a mess to 579# match those on a word boundary. 580_ALT_TOKEN_REPLACEMENT = { 581 'and': '&&', 582 'bitor': '|', 583 'or': '||', 584 'xor': '^', 585 'compl': '~', 586 'bitand': '&', 587 'and_eq': '&=', 588 'or_eq': '|=', 589 'xor_eq': '^=', 590 'not': '!', 591 'not_eq': '!=' 592 } 593 594# Compile regular expression that matches all the above keywords. The "[ =()]" 595# bit is meant to avoid matching these keywords outside of boolean expressions. 596# 597# False positives include C-style multi-line comments and multi-line strings 598# but those have always been troublesome for cpplint. 599_ALT_TOKEN_REPLACEMENT_PATTERN = re.compile( 600 r'[ =()](' + ('|'.join(_ALT_TOKEN_REPLACEMENT.keys())) + r')(?=[ (]|$)') 601 602 603# These constants define types of headers for use with 604# _IncludeState.CheckNextIncludeOrder(). 605_C_SYS_HEADER = 1 606_CPP_SYS_HEADER = 2 607_LIKELY_MY_HEADER = 3 608_POSSIBLE_MY_HEADER = 4 609_OTHER_HEADER = 5 610 611# These constants define the current inline assembly state 612_NO_ASM = 0 # Outside of inline assembly block 613_INSIDE_ASM = 1 # Inside inline assembly block 614_END_ASM = 2 # Last line of inline assembly block 615_BLOCK_ASM = 3 # The whole block is an inline assembly block 616 617# Match start of assembly blocks 618_MATCH_ASM = re.compile(r'^\s*(?:asm|_asm|__asm|__asm__)' 619 r'(?:\s+(volatile|__volatile__))?' 620 r'\s*[{(]') 621 622# Match strings that indicate we're working on a C (not C++) file. 623_SEARCH_C_FILE = re.compile(r'\b(?:LINT_C_FILE|' 624 r'vim?:\s*.*(\s*|:)filetype=c(\s*|:|$))') 625 626# Match string that indicates we're working on a Linux Kernel file. 627_SEARCH_KERNEL_FILE = re.compile(r'\b(?:LINT_KERNEL_FILE)') 628 629_NULL_TOKEN_PATTERN = re.compile(r'\bNULL\b') 630 631_V8_PERSISTENT_PATTERN = re.compile(r'\bv8::Persistent\b') 632 633_RIGHT_LEANING_POINTER_PATTERN = re.compile(r'[^=|(,\s><);&?:}]' 634 r'(?<!(sizeof|return))' 635 r'\s\*[a-zA-Z_][0-9a-zA-Z_]*') 636 637_regexp_compile_cache = {} 638 639# {str, set(int)}: a map from error categories to sets of linenumbers 640# on which those errors are expected and should be suppressed. 641_error_suppressions = {} 642 643# The root directory used for deriving header guard CPP variable. 644# This is set by --root flag. 645_root = None 646_root_debug = False 647 648# The top level repository directory. If set, _root is calculated relative to 649# this directory instead of the directory containing version control artifacts. 650# This is set by the --repository flag. 651_repository = None 652 653# Files to exclude from linting. This is set by the --exclude flag. 654_excludes = None 655 656# Whether to suppress PrintInfo messages 657_quiet = False 658 659# The allowed line length of files. 660# This is set by --linelength flag. 661_line_length = 80 662 663try: 664 unicode 665except NameError: 666 # -- pylint: disable=redefined-builtin 667 basestring = unicode = str 668 669try: 670 long 671except NameError: 672 # -- pylint: disable=redefined-builtin 673 long = int 674 675if sys.version_info < (3,): 676 # -- pylint: disable=no-member 677 # BINARY_TYPE = str 678 itervalues = dict.itervalues 679 iteritems = dict.iteritems 680else: 681 # BINARY_TYPE = bytes 682 itervalues = dict.values 683 iteritems = dict.items 684 685def unicode_escape_decode(x): 686 if sys.version_info < (3,): 687 return codecs.unicode_escape_decode(x)[0] 688 else: 689 return x 690 691# Treat all headers starting with 'h' equally: .h, .hpp, .hxx etc. 692# This is set by --headers flag. 693_hpp_headers = set([]) 694 695# {str, bool}: a map from error categories to booleans which indicate if the 696# category should be suppressed for every line. 697_global_error_suppressions = {} 698 699def ProcessHppHeadersOption(val): 700 global _hpp_headers 701 try: 702 _hpp_headers = {ext.strip() for ext in val.split(',')} 703 except ValueError: 704 PrintUsage('Header extensions must be comma separated list.') 705 706def IsHeaderExtension(file_extension): 707 return file_extension in GetHeaderExtensions() 708 709def GetHeaderExtensions(): 710 if _hpp_headers: 711 return _hpp_headers 712 if _valid_extensions: 713 return {h for h in _valid_extensions if 'h' in h} 714 return set(['h', 'hh', 'hpp', 'hxx', 'h++', 'cuh']) 715 716# The allowed extensions for file names 717# This is set by --extensions flag 718def GetAllExtensions(): 719 return GetHeaderExtensions().union(_valid_extensions or set( 720 ['c', 'cc', 'cpp', 'cxx', 'c++', 'cu'])) 721 722def ProcessExtensionsOption(val): 723 global _valid_extensions 724 try: 725 extensions = [ext.strip() for ext in val.split(',')] 726 _valid_extensions = set(extensions) 727 except ValueError: 728 PrintUsage('Extensions should be a comma-separated list of values;' 729 'for example: extensions=hpp,cpp\n' 730 'This could not be parsed: "%s"' % (val,)) 731 732def GetNonHeaderExtensions(): 733 return GetAllExtensions().difference(GetHeaderExtensions()) 734 735def ParseNolintSuppressions(filename, raw_line, linenum, error): 736 """Updates the global list of line error-suppressions. 737 738 Parses any NOLINT comments on the current line, updating the global 739 error_suppressions store. Reports an error if the NOLINT comment 740 was malformed. 741 742 Args: 743 filename: str, the name of the input file. 744 raw_line: str, the line of input text, with comments. 745 linenum: int, the number of the current line. 746 error: function, an error handler. 747 """ 748 matched = Search(r'\bNOLINT(NEXTLINE)?\b(\([^)]+\))?', raw_line) 749 if matched: 750 if matched.group(1): 751 suppressed_line = linenum + 1 752 else: 753 suppressed_line = linenum 754 category = matched.group(2) 755 if category in (None, '(*)'): # => "suppress all" 756 _error_suppressions.setdefault(None, set()).add(suppressed_line) 757 else: 758 if category.startswith('(') and category.endswith(')'): 759 category = category[1:-1] 760 if category in _ERROR_CATEGORIES: 761 _error_suppressions.setdefault(category, set()).add(suppressed_line) 762 elif category not in _LEGACY_ERROR_CATEGORIES: 763 error(filename, linenum, 'readability/nolint', 5, 764 'Unknown NOLINT error category: %s' % category) 765 766 767def ProcessGlobalSuppresions(lines): 768 """Updates the list of global error suppressions. 769 770 Parses any lint directives in the file that have global effect. 771 772 Args: 773 lines: An array of strings, each representing a line of the file, with the 774 last element being empty if the file is terminated with a newline. 775 """ 776 for line in lines: 777 if _SEARCH_C_FILE.search(line): 778 for category in _DEFAULT_C_SUPPRESSED_CATEGORIES: 779 _global_error_suppressions[category] = True 780 if _SEARCH_KERNEL_FILE.search(line): 781 for category in _DEFAULT_KERNEL_SUPPRESSED_CATEGORIES: 782 _global_error_suppressions[category] = True 783 784 785def ResetNolintSuppressions(): 786 """Resets the set of NOLINT suppressions to empty.""" 787 _error_suppressions.clear() 788 _global_error_suppressions.clear() 789 790 791def IsErrorSuppressedByNolint(category, linenum): 792 """Returns true if the specified error category is suppressed on this line. 793 794 Consults the global error_suppressions map populated by 795 ParseNolintSuppressions/ProcessGlobalSuppresions/ResetNolintSuppressions. 796 797 Args: 798 category: str, the category of the error. 799 linenum: int, the current line number. 800 Returns: 801 bool, True iff the error should be suppressed due to a NOLINT comment or 802 global suppression. 803 """ 804 return (_global_error_suppressions.get(category, False) or 805 linenum in _error_suppressions.get(category, set()) or 806 linenum in _error_suppressions.get(None, set())) 807 808 809def Match(pattern, s): 810 """Matches the string with the pattern, caching the compiled regexp.""" 811 # The regexp compilation caching is inlined in both Match and Search for 812 # performance reasons; factoring it out into a separate function turns out 813 # to be noticeably expensive. 814 if pattern not in _regexp_compile_cache: 815 _regexp_compile_cache[pattern] = sre_compile.compile(pattern) 816 return _regexp_compile_cache[pattern].match(s) 817 818 819def ReplaceAll(pattern, rep, s): 820 """Replaces instances of pattern in a string with a replacement. 821 822 The compiled regex is kept in a cache shared by Match and Search. 823 824 Args: 825 pattern: regex pattern 826 rep: replacement text 827 s: search string 828 829 Returns: 830 string with replacements made (or original string if no replacements) 831 """ 832 if pattern not in _regexp_compile_cache: 833 _regexp_compile_cache[pattern] = sre_compile.compile(pattern) 834 return _regexp_compile_cache[pattern].sub(rep, s) 835 836 837def Search(pattern, s): 838 """Searches the string for the pattern, caching the compiled regexp.""" 839 if pattern not in _regexp_compile_cache: 840 _regexp_compile_cache[pattern] = sre_compile.compile(pattern) 841 return _regexp_compile_cache[pattern].search(s) 842 843 844def _IsSourceExtension(s): 845 """File extension (excluding dot) matches a source file extension.""" 846 return s in GetNonHeaderExtensions() 847 848 849class _IncludeState(object): 850 """Tracks line numbers for includes, and the order in which includes appear. 851 852 include_list contains list of lists of (header, line number) pairs. 853 It's a lists of lists rather than just one flat list to make it 854 easier to update across preprocessor boundaries. 855 856 Call CheckNextIncludeOrder() once for each header in the file, passing 857 in the type constants defined above. Calls in an illegal order will 858 raise an _IncludeError with an appropriate error message. 859 860 """ 861 # self._section will move monotonically through this set. If it ever 862 # needs to move backwards, CheckNextIncludeOrder will raise an error. 863 _INITIAL_SECTION = 0 864 _MY_H_SECTION = 1 865 _OTHER_H_SECTION = 2 866 _C_SECTION = 3 867 _CPP_SECTION = 4 868 869 _TYPE_NAMES = { 870 _C_SYS_HEADER: 'C system header', 871 _CPP_SYS_HEADER: 'C++ system header', 872 _LIKELY_MY_HEADER: 'header this file implements', 873 _POSSIBLE_MY_HEADER: 'header this file may implement', 874 _OTHER_HEADER: 'other header', 875 } 876 _SECTION_NAMES = { 877 _INITIAL_SECTION: "... nothing. (This can't be an error.)", 878 _MY_H_SECTION: 'a header this file implements', 879 _OTHER_H_SECTION: 'other header', 880 _C_SECTION: 'C system header', 881 _CPP_SECTION: 'C++ system header', 882 } 883 884 def __init__(self): 885 self.include_list = [[]] 886 self._section = None 887 self._last_header = None 888 self.ResetSection('') 889 890 def FindHeader(self, header): 891 """Check if a header has already been included. 892 893 Args: 894 header: header to check. 895 Returns: 896 Line number of previous occurrence, or -1 if the header has not 897 been seen before. 898 """ 899 for section_list in self.include_list: 900 for f in section_list: 901 if f[0] == header: 902 return f[1] 903 return -1 904 905 def ResetSection(self, directive): 906 """Reset section checking for preprocessor directive. 907 908 Args: 909 directive: preprocessor directive (e.g. "if", "else"). 910 """ 911 # The name of the current section. 912 self._section = self._INITIAL_SECTION 913 # The path of last found header. 914 self._last_header = '' 915 916 # Update list of includes. Note that we never pop from the 917 # include list. 918 if directive in ('if', 'ifdef', 'ifndef'): 919 self.include_list.append([]) 920 elif directive in ('else', 'elif'): 921 self.include_list[-1] = [] 922 923 def SetLastHeader(self, header_path): 924 self._last_header = header_path 925 926 def CanonicalizeAlphabeticalOrder(self, header_path): 927 """Returns a path canonicalized for alphabetical comparison. 928 929 - replaces "-" with "_" so they both cmp the same. 930 - removes '-inl' since we don't require them to be after the main header. 931 - lowercase everything, just in case. 932 933 Args: 934 header_path: Path to be canonicalized. 935 936 Returns: 937 Canonicalized path. 938 """ 939 return header_path.replace('-inl.h', '.h').replace('-', '_').lower() 940 941 def IsInAlphabeticalOrder(self, clean_lines, linenum, header_path): 942 """Check if a header is in alphabetical order with the previous header. 943 944 Args: 945 clean_lines: A CleansedLines instance containing the file. 946 linenum: The number of the line to check. 947 header_path: Canonicalized header to be checked. 948 949 Returns: 950 Returns true if the header is in alphabetical order. 951 """ 952 # If previous section is different from current section, _last_header will 953 # be reset to empty string, so it's always less than current header. 954 # 955 # If previous line was a blank line, assume that the headers are 956 # intentionally sorted the way they are. 957 if (self._last_header > header_path and 958 Match(r'^\s*#\s*include\b', clean_lines.elided[linenum - 1])): 959 return False 960 return True 961 962 def CheckNextIncludeOrder(self, header_type): 963 """Returns a non-empty error message if the next header is out of order. 964 965 This function also updates the internal state to be ready to check 966 the next include. 967 968 Args: 969 header_type: One of the _XXX_HEADER constants defined above. 970 971 Returns: 972 The empty string if the header is in the right order, or an 973 error message describing what's wrong. 974 975 """ 976 error_message = ('Found %s after %s' % 977 (self._TYPE_NAMES[header_type], 978 self._SECTION_NAMES[self._section])) 979 980 last_section = self._section 981 982 if header_type == _C_SYS_HEADER: 983 if self._section <= self._C_SECTION: 984 self._section = self._C_SECTION 985 else: 986 self._last_header = '' 987 return error_message 988 elif header_type == _CPP_SYS_HEADER: 989 if self._section <= self._CPP_SECTION: 990 self._section = self._CPP_SECTION 991 else: 992 self._last_header = '' 993 return error_message 994 elif header_type == _LIKELY_MY_HEADER: 995 if self._section <= self._MY_H_SECTION: 996 self._section = self._MY_H_SECTION 997 else: 998 self._section = self._OTHER_H_SECTION 999 elif header_type == _POSSIBLE_MY_HEADER: 1000 if self._section <= self._MY_H_SECTION: 1001 self._section = self._MY_H_SECTION 1002 else: 1003 # This will always be the fallback because we're not sure 1004 # enough that the header is associated with this file. 1005 self._section = self._OTHER_H_SECTION 1006 else: 1007 assert header_type == _OTHER_HEADER 1008 self._section = self._OTHER_H_SECTION 1009 1010 if last_section != self._section: 1011 self._last_header = '' 1012 1013 return '' 1014 1015 1016class _CppLintState(object): 1017 """Maintains module-wide state..""" 1018 1019 def __init__(self): 1020 self.verbose_level = 1 # global setting. 1021 self.error_count = 0 # global count of reported errors 1022 # filters to apply when emitting error messages 1023 self.filters = _DEFAULT_FILTERS[:] 1024 # backup of filter list. Used to restore the state after each file. 1025 self._filters_backup = self.filters[:] 1026 self.counting = 'total' # In what way are we counting errors? 1027 self.errors_by_category = {} # string to int dict storing error counts 1028 self.quiet = False # Suppress non-error messagess? 1029 1030 # output format: 1031 # "emacs" - format that emacs can parse (default) 1032 # "eclipse" - format that eclipse can parse 1033 # "vs7" - format that Microsoft Visual Studio 7 can parse 1034 # "junit" - format that Jenkins, Bamboo, etc can parse 1035 self.output_format = 'emacs' 1036 1037 # For JUnit output, save errors and failures until the end so that they 1038 # can be written into the XML 1039 self._junit_errors = [] 1040 self._junit_failures = [] 1041 1042 def SetOutputFormat(self, output_format): 1043 """Sets the output format for errors.""" 1044 self.output_format = output_format 1045 1046 def SetQuiet(self, quiet): 1047 """Sets the module's quiet settings, and returns the previous setting.""" 1048 last_quiet = self.quiet 1049 self.quiet = quiet 1050 return last_quiet 1051 1052 def SetVerboseLevel(self, level): 1053 """Sets the module's verbosity, and returns the previous setting.""" 1054 last_verbose_level = self.verbose_level 1055 self.verbose_level = level 1056 return last_verbose_level 1057 1058 def SetCountingStyle(self, counting_style): 1059 """Sets the module's counting options.""" 1060 self.counting = counting_style 1061 1062 def SetFilters(self, filters): 1063 """Sets the error-message filters. 1064 1065 These filters are applied when deciding whether to emit a given 1066 error message. 1067 1068 Args: 1069 filters: A string of comma-separated filters (eg "+whitespace/indent"). 1070 Each filter should start with + or -; else we die. 1071 1072 Raises: 1073 ValueError: The comma-separated filters did not all start with '+' or '-'. 1074 E.g. "-,+whitespace,-whitespace/indent,whitespace/badfilter" 1075 """ 1076 # Default filters always have less priority than the flag ones. 1077 self.filters = _DEFAULT_FILTERS[:] 1078 self.AddFilters(filters) 1079 1080 def AddFilters(self, filters): 1081 """ Adds more filters to the existing list of error-message filters. """ 1082 for filt in filters.split(','): 1083 clean_filt = filt.strip() 1084 if clean_filt: 1085 self.filters.append(clean_filt) 1086 for filt in self.filters: 1087 if not (filt.startswith('+') or filt.startswith('-')): 1088 raise ValueError('Every filter in --filters must start with + or -' 1089 ' (%s does not)' % filt) 1090 1091 def BackupFilters(self): 1092 """ Saves the current filter list to backup storage.""" 1093 self._filters_backup = self.filters[:] 1094 1095 def RestoreFilters(self): 1096 """ Restores filters previously backed up.""" 1097 self.filters = self._filters_backup[:] 1098 1099 def ResetErrorCounts(self): 1100 """Sets the module's error statistic back to zero.""" 1101 self.error_count = 0 1102 self.errors_by_category = {} 1103 1104 def IncrementErrorCount(self, category): 1105 """Bumps the module's error statistic.""" 1106 self.error_count += 1 1107 if self.counting in ('toplevel', 'detailed'): 1108 if self.counting != 'detailed': 1109 category = category.split('/')[0] 1110 if category not in self.errors_by_category: 1111 self.errors_by_category[category] = 0 1112 self.errors_by_category[category] += 1 1113 1114 def PrintErrorCounts(self): 1115 """Print a summary of errors by category, and the total.""" 1116 for category, count in sorted(iteritems(self.errors_by_category)): 1117 self.PrintInfo('Category \'%s\' errors found: %d\n' % 1118 (category, count)) 1119 if self.error_count > 0: 1120 self.PrintInfo('Total errors found: %d\n' % self.error_count) 1121 1122 def PrintInfo(self, message): 1123 if not _quiet and self.output_format != 'junit': 1124 sys.stdout.write(message) 1125 1126 def PrintError(self, message): 1127 if self.output_format == 'junit': 1128 self._junit_errors.append(message) 1129 else: 1130 sys.stderr.write(message) 1131 1132 def AddJUnitFailure(self, filename, linenum, message, category, confidence): 1133 self._junit_failures.append((filename, linenum, message, category, 1134 confidence)) 1135 1136 def FormatJUnitXML(self): 1137 num_errors = len(self._junit_errors) 1138 num_failures = len(self._junit_failures) 1139 1140 testsuite = xml.etree.ElementTree.Element('testsuite') 1141 testsuite.attrib['errors'] = str(num_errors) 1142 testsuite.attrib['failures'] = str(num_failures) 1143 testsuite.attrib['name'] = 'cpplint' 1144 1145 if num_errors == 0 and num_failures == 0: 1146 testsuite.attrib['tests'] = str(1) 1147 xml.etree.ElementTree.SubElement(testsuite, 'testcase', name='passed') 1148 1149 else: 1150 testsuite.attrib['tests'] = str(num_errors + num_failures) 1151 if num_errors > 0: 1152 testcase = xml.etree.ElementTree.SubElement(testsuite, 'testcase') 1153 testcase.attrib['name'] = 'errors' 1154 error = xml.etree.ElementTree.SubElement(testcase, 'error') 1155 error.text = '\n'.join(self._junit_errors) 1156 if num_failures > 0: 1157 # Group failures by file 1158 failed_file_order = [] 1159 failures_by_file = {} 1160 for failure in self._junit_failures: 1161 failed_file = failure[0] 1162 if failed_file not in failed_file_order: 1163 failed_file_order.append(failed_file) 1164 failures_by_file[failed_file] = [] 1165 failures_by_file[failed_file].append(failure) 1166 # Create a testcase for each file 1167 for failed_file in failed_file_order: 1168 failures = failures_by_file[failed_file] 1169 testcase = xml.etree.ElementTree.SubElement(testsuite, 'testcase') 1170 testcase.attrib['name'] = failed_file 1171 failure = xml.etree.ElementTree.SubElement(testcase, 'failure') 1172 template = '{0}: {1} [{2}] [{3}]' 1173 texts = [template.format(f[1], f[2], f[3], f[4]) for f in failures] 1174 failure.text = '\n'.join(texts) 1175 1176 xml_decl = '<?xml version="1.0" encoding="UTF-8" ?>\n' 1177 return xml_decl + xml.etree.ElementTree.tostring(testsuite, 'utf-8').decode('utf-8') 1178 1179 1180_cpplint_state = _CppLintState() 1181 1182 1183def _OutputFormat(): 1184 """Gets the module's output format.""" 1185 return _cpplint_state.output_format 1186 1187 1188def _SetOutputFormat(output_format): 1189 """Sets the module's output format.""" 1190 _cpplint_state.SetOutputFormat(output_format) 1191 1192def _Quiet(): 1193 """Return's the module's quiet setting.""" 1194 return _cpplint_state.quiet 1195 1196def _SetQuiet(quiet): 1197 """Set the module's quiet status, and return previous setting.""" 1198 return _cpplint_state.SetQuiet(quiet) 1199 1200 1201def _VerboseLevel(): 1202 """Returns the module's verbosity setting.""" 1203 return _cpplint_state.verbose_level 1204 1205 1206def _SetVerboseLevel(level): 1207 """Sets the module's verbosity, and returns the previous setting.""" 1208 return _cpplint_state.SetVerboseLevel(level) 1209 1210 1211def _SetCountingStyle(level): 1212 """Sets the module's counting options.""" 1213 _cpplint_state.SetCountingStyle(level) 1214 1215 1216def _Filters(): 1217 """Returns the module's list of output filters, as a list.""" 1218 return _cpplint_state.filters 1219 1220 1221def _SetFilters(filters): 1222 """Sets the module's error-message filters. 1223 1224 These filters are applied when deciding whether to emit a given 1225 error message. 1226 1227 Args: 1228 filters: A string of comma-separated filters (eg "whitespace/indent"). 1229 Each filter should start with + or -; else we die. 1230 """ 1231 _cpplint_state.SetFilters(filters) 1232 1233def _AddFilters(filters): 1234 """Adds more filter overrides. 1235 1236 Unlike _SetFilters, this function does not reset the current list of filters 1237 available. 1238 1239 Args: 1240 filters: A string of comma-separated filters (eg "whitespace/indent"). 1241 Each filter should start with + or -; else we die. 1242 """ 1243 _cpplint_state.AddFilters(filters) 1244 1245def _BackupFilters(): 1246 """ Saves the current filter list to backup storage.""" 1247 _cpplint_state.BackupFilters() 1248 1249def _RestoreFilters(): 1250 """ Restores filters previously backed up.""" 1251 _cpplint_state.RestoreFilters() 1252 1253class _FunctionState(object): 1254 """Tracks current function name and the number of lines in its body.""" 1255 1256 _NORMAL_TRIGGER = 250 # for --v=0, 500 for --v=1, etc. 1257 _TEST_TRIGGER = 400 # about 50% more than _NORMAL_TRIGGER. 1258 1259 def __init__(self): 1260 self.in_a_function = False 1261 self.lines_in_function = 0 1262 self.current_function = '' 1263 1264 def Begin(self, function_name): 1265 """Start analyzing function body. 1266 1267 Args: 1268 function_name: The name of the function being tracked. 1269 """ 1270 self.in_a_function = True 1271 self.lines_in_function = 0 1272 self.current_function = function_name 1273 1274 def Count(self): 1275 """Count line in current function body.""" 1276 if self.in_a_function: 1277 self.lines_in_function += 1 1278 1279 def Check(self, error, filename, linenum): 1280 """Report if too many lines in function body. 1281 1282 Args: 1283 error: The function to call with any errors found. 1284 filename: The name of the current file. 1285 linenum: The number of the line to check. 1286 """ 1287 if not self.in_a_function: 1288 return 1289 1290 if Match(r'T(EST|est)', self.current_function): 1291 base_trigger = self._TEST_TRIGGER 1292 else: 1293 base_trigger = self._NORMAL_TRIGGER 1294 trigger = base_trigger * 2**_VerboseLevel() 1295 1296 if self.lines_in_function > trigger: 1297 error_level = int(math.log(self.lines_in_function / base_trigger, 2)) 1298 # 50 => 0, 100 => 1, 200 => 2, 400 => 3, 800 => 4, 1600 => 5, ... 1299 if error_level > 5: 1300 error_level = 5 1301 error(filename, linenum, 'readability/fn_size', error_level, 1302 'Small and focused functions are preferred:' 1303 ' %s has %d non-comment lines' 1304 ' (error triggered by exceeding %d lines).' % ( 1305 self.current_function, self.lines_in_function, trigger)) 1306 1307 def End(self): 1308 """Stop analyzing function body.""" 1309 self.in_a_function = False 1310 1311 1312class _IncludeError(Exception): 1313 """Indicates a problem with the include order in a file.""" 1314 pass 1315 1316 1317class FileInfo(object): 1318 """Provides utility functions for filenames. 1319 1320 FileInfo provides easy access to the components of a file's path 1321 relative to the project root. 1322 """ 1323 1324 def __init__(self, filename): 1325 self._filename = filename 1326 1327 def FullName(self): 1328 """Make Windows paths like Unix.""" 1329 return os.path.abspath(self._filename).replace('\\', '/') 1330 1331 def RepositoryName(self): 1332 r"""FullName after removing the local path to the repository. 1333 1334 If we have a real absolute path name here we can try to do something smart: 1335 detecting the root of the checkout and truncating /path/to/checkout from 1336 the name so that we get header guards that don't include things like 1337 "C:\\Documents and Settings\\..." or "/home/username/..." in them and thus 1338 people on different computers who have checked the source out to different 1339 locations won't see bogus errors. 1340 """ 1341 fullname = self.FullName() 1342 1343 if os.path.exists(fullname): 1344 project_dir = os.path.dirname(fullname) 1345 1346 # If the user specified a repository path, it exists, and the file is 1347 # contained in it, use the specified repository path 1348 if _repository: 1349 repo = FileInfo(_repository).FullName() 1350 root_dir = project_dir 1351 while os.path.exists(root_dir): 1352 # allow case insensitive compare on Windows 1353 if os.path.normcase(root_dir) == os.path.normcase(repo): 1354 return os.path.relpath(fullname, root_dir).replace('\\', '/') 1355 one_up_dir = os.path.dirname(root_dir) 1356 if one_up_dir == root_dir: 1357 break 1358 root_dir = one_up_dir 1359 1360 if os.path.exists(os.path.join(project_dir, ".svn")): 1361 # If there's a .svn file in the current directory, we recursively look 1362 # up the directory tree for the top of the SVN checkout 1363 root_dir = project_dir 1364 one_up_dir = os.path.dirname(root_dir) 1365 while os.path.exists(os.path.join(one_up_dir, ".svn")): 1366 root_dir = os.path.dirname(root_dir) 1367 one_up_dir = os.path.dirname(one_up_dir) 1368 1369 prefix = os.path.commonprefix([root_dir, project_dir]) 1370 return fullname[len(prefix) + 1:] 1371 1372 # Not SVN <= 1.6? Try to find a git, hg, or svn top level directory by 1373 # searching up from the current path. 1374 root_dir = current_dir = os.path.dirname(fullname) 1375 while current_dir != os.path.dirname(current_dir): 1376 if (os.path.exists(os.path.join(current_dir, ".git")) or 1377 os.path.exists(os.path.join(current_dir, ".hg")) or 1378 os.path.exists(os.path.join(current_dir, ".svn"))): 1379 root_dir = current_dir 1380 current_dir = os.path.dirname(current_dir) 1381 1382 if (os.path.exists(os.path.join(root_dir, ".git")) or 1383 os.path.exists(os.path.join(root_dir, ".hg")) or 1384 os.path.exists(os.path.join(root_dir, ".svn"))): 1385 prefix = os.path.commonprefix([root_dir, project_dir]) 1386 return fullname[len(prefix) + 1:] 1387 1388 # Don't know what to do; header guard warnings may be wrong... 1389 return fullname 1390 1391 def Split(self): 1392 """Splits the file into the directory, basename, and extension. 1393 1394 For 'chrome/browser/browser.cc', Split() would 1395 return ('chrome/browser', 'browser', '.cc') 1396 1397 Returns: 1398 A tuple of (directory, basename, extension). 1399 """ 1400 1401 googlename = self.RepositoryName() 1402 project, rest = os.path.split(googlename) 1403 return (project,) + os.path.splitext(rest) 1404 1405 def BaseName(self): 1406 """File base name - text after the final slash, before the final period.""" 1407 return self.Split()[1] 1408 1409 def Extension(self): 1410 """File extension - text following the final period, includes that period.""" 1411 return self.Split()[2] 1412 1413 def NoExtension(self): 1414 """File has no source file extension.""" 1415 return '/'.join(self.Split()[0:2]) 1416 1417 def IsSource(self): 1418 """File has a source file extension.""" 1419 return _IsSourceExtension(self.Extension()[1:]) 1420 1421 1422def _ShouldPrintError(category, confidence, linenum): 1423 """If confidence >= verbose, category passes filter and is not suppressed.""" 1424 1425 # There are three ways we might decide not to print an error message: 1426 # a "NOLINT(category)" comment appears in the source, 1427 # the verbosity level isn't high enough, or the filters filter it out. 1428 if IsErrorSuppressedByNolint(category, linenum): 1429 return False 1430 1431 if confidence < _cpplint_state.verbose_level: 1432 return False 1433 1434 is_filtered = False 1435 for one_filter in _Filters(): 1436 if one_filter.startswith('-'): 1437 if category.startswith(one_filter[1:]): 1438 is_filtered = True 1439 elif one_filter.startswith('+'): 1440 if category.startswith(one_filter[1:]): 1441 is_filtered = False 1442 else: 1443 assert False # should have been checked for in SetFilter. 1444 if is_filtered: 1445 return False 1446 1447 return True 1448 1449 1450def Error(filename, linenum, category, confidence, message): 1451 """Logs the fact we've found a lint error. 1452 1453 We log where the error was found, and also our confidence in the error, 1454 that is, how certain we are this is a legitimate style regression, and 1455 not a misidentification or a use that's sometimes justified. 1456 1457 False positives can be suppressed by the use of 1458 "cpplint(category)" comments on the offending line. These are 1459 parsed into _error_suppressions. 1460 1461 Args: 1462 filename: The name of the file containing the error. 1463 linenum: The number of the line containing the error. 1464 category: A string used to describe the "category" this bug 1465 falls under: "whitespace", say, or "runtime". Categories 1466 may have a hierarchy separated by slashes: "whitespace/indent". 1467 confidence: A number from 1-5 representing a confidence score for 1468 the error, with 5 meaning that we are certain of the problem, 1469 and 1 meaning that it could be a legitimate construct. 1470 message: The error message. 1471 """ 1472 if _ShouldPrintError(category, confidence, linenum): 1473 _cpplint_state.IncrementErrorCount(category) 1474 if _cpplint_state.output_format == 'vs7': 1475 _cpplint_state.PrintError('%s(%s): error cpplint: [%s] %s [%d]\n' % ( 1476 filename, linenum, category, message, confidence)) 1477 elif _cpplint_state.output_format == 'eclipse': 1478 sys.stderr.write('%s:%s: warning: %s [%s] [%d]\n' % ( 1479 filename, linenum, message, category, confidence)) 1480 elif _cpplint_state.output_format == 'junit': 1481 _cpplint_state.AddJUnitFailure(filename, linenum, message, category, 1482 confidence) 1483 else: 1484 final_message = '%s:%s: %s [%s] [%d]\n' % ( 1485 filename, linenum, message, category, confidence) 1486 sys.stderr.write(final_message) 1487 1488# Matches standard C++ escape sequences per 2.13.2.3 of the C++ standard. 1489_RE_PATTERN_CLEANSE_LINE_ESCAPES = re.compile( 1490 r'\\([abfnrtv?"\\\']|\d+|x[0-9a-fA-F]+)') 1491# Match a single C style comment on the same line. 1492_RE_PATTERN_C_COMMENTS = r'/\*(?:[^*]|\*(?!/))*\*/' 1493# Matches multi-line C style comments. 1494# This RE is a little bit more complicated than one might expect, because we 1495# have to take care of space removals tools so we can handle comments inside 1496# statements better. 1497# The current rule is: We only clear spaces from both sides when we're at the 1498# end of the line. Otherwise, we try to remove spaces from the right side, 1499# if this doesn't work we try on left side but only if there's a non-character 1500# on the right. 1501_RE_PATTERN_CLEANSE_LINE_C_COMMENTS = re.compile( 1502 r'(\s*' + _RE_PATTERN_C_COMMENTS + r'\s*$|' + 1503 _RE_PATTERN_C_COMMENTS + r'\s+|' + 1504 r'\s+' + _RE_PATTERN_C_COMMENTS + r'(?=\W)|' + 1505 _RE_PATTERN_C_COMMENTS + r')') 1506 1507 1508def IsCppString(line): 1509 """Does line terminate so, that the next symbol is in string constant. 1510 1511 This function does not consider single-line nor multi-line comments. 1512 1513 Args: 1514 line: is a partial line of code starting from the 0..n. 1515 1516 Returns: 1517 True, if next character appended to 'line' is inside a 1518 string constant. 1519 """ 1520 1521 line = line.replace(r'\\', 'XX') # after this, \\" does not match to \" 1522 return ((line.count('"') - line.count(r'\"') - line.count("'\"'")) & 1) == 1 1523 1524 1525def CleanseRawStrings(raw_lines): 1526 """Removes C++11 raw strings from lines. 1527 1528 Before: 1529 static const char kData[] = R"( 1530 multi-line string 1531 )"; 1532 1533 After: 1534 static const char kData[] = "" 1535 (replaced by blank line) 1536 ""; 1537 1538 Args: 1539 raw_lines: list of raw lines. 1540 1541 Returns: 1542 list of lines with C++11 raw strings replaced by empty strings. 1543 """ 1544 1545 delimiter = None 1546 lines_without_raw_strings = [] 1547 for line in raw_lines: 1548 if delimiter: 1549 # Inside a raw string, look for the end 1550 end = line.find(delimiter) 1551 if end >= 0: 1552 # Found the end of the string, match leading space for this 1553 # line and resume copying the original lines, and also insert 1554 # a "" on the last line. 1555 leading_space = Match(r'^(\s*)\S', line) 1556 line = leading_space.group(1) + '""' + line[end + len(delimiter):] 1557 delimiter = None 1558 else: 1559 # Haven't found the end yet, append a blank line. 1560 line = '""' 1561 1562 # Look for beginning of a raw string, and replace them with 1563 # empty strings. This is done in a loop to handle multiple raw 1564 # strings on the same line. 1565 while delimiter is None: 1566 # Look for beginning of a raw string. 1567 # See 2.14.15 [lex.string] for syntax. 1568 # 1569 # Once we have matched a raw string, we check the prefix of the 1570 # line to make sure that the line is not part of a single line 1571 # comment. It's done this way because we remove raw strings 1572 # before removing comments as opposed to removing comments 1573 # before removing raw strings. This is because there are some 1574 # cpplint checks that requires the comments to be preserved, but 1575 # we don't want to check comments that are inside raw strings. 1576 matched = Match(r'^(.*?)\b(?:R|u8R|uR|UR|LR)"([^\s\\()]*)\((.*)$', line) 1577 if (matched and 1578 not Match(r'^([^\'"]|\'(\\.|[^\'])*\'|"(\\.|[^"])*")*//', 1579 matched.group(1))): 1580 delimiter = ')' + matched.group(2) + '"' 1581 1582 end = matched.group(3).find(delimiter) 1583 if end >= 0: 1584 # Raw string ended on same line 1585 line = (matched.group(1) + '""' + 1586 matched.group(3)[end + len(delimiter):]) 1587 delimiter = None 1588 else: 1589 # Start of a multi-line raw string 1590 line = matched.group(1) + '""' 1591 else: 1592 break 1593 1594 lines_without_raw_strings.append(line) 1595 1596 # TODO(unknown): if delimiter is not None here, we might want to 1597 # emit a warning for unterminated string. 1598 return lines_without_raw_strings 1599 1600 1601def FindNextMultiLineCommentStart(lines, lineix): 1602 """Find the beginning marker for a multiline comment.""" 1603 while lineix < len(lines): 1604 if lines[lineix].strip().startswith('/*'): 1605 # Only return this marker if the comment goes beyond this line 1606 if lines[lineix].strip().find('*/', 2) < 0: 1607 return lineix 1608 lineix += 1 1609 return len(lines) 1610 1611 1612def FindNextMultiLineCommentEnd(lines, lineix): 1613 """We are inside a comment, find the end marker.""" 1614 while lineix < len(lines): 1615 if lines[lineix].strip().endswith('*/'): 1616 return lineix 1617 lineix += 1 1618 return len(lines) 1619 1620 1621def RemoveMultiLineCommentsFromRange(lines, begin, end): 1622 """Clears a range of lines for multi-line comments.""" 1623 # Having // dummy comments makes the lines non-empty, so we will not get 1624 # unnecessary blank line warnings later in the code. 1625 for i in range(begin, end): 1626 lines[i] = '/**/' 1627 1628 1629def RemoveMultiLineComments(filename, lines, error): 1630 """Removes multiline (c-style) comments from lines.""" 1631 lineix = 0 1632 while lineix < len(lines): 1633 lineix_begin = FindNextMultiLineCommentStart(lines, lineix) 1634 if lineix_begin >= len(lines): 1635 return 1636 lineix_end = FindNextMultiLineCommentEnd(lines, lineix_begin) 1637 if lineix_end >= len(lines): 1638 error(filename, lineix_begin + 1, 'readability/multiline_comment', 5, 1639 'Could not find end of multi-line comment') 1640 return 1641 RemoveMultiLineCommentsFromRange(lines, lineix_begin, lineix_end + 1) 1642 lineix = lineix_end + 1 1643 1644 1645def CleanseComments(line): 1646 """Removes //-comments and single-line C-style /* */ comments. 1647 1648 Args: 1649 line: A line of C++ source. 1650 1651 Returns: 1652 The line with single-line comments removed. 1653 """ 1654 commentpos = line.find('//') 1655 if commentpos != -1 and not IsCppString(line[:commentpos]): 1656 line = line[:commentpos].rstrip() 1657 # get rid of /* ... */ 1658 return _RE_PATTERN_CLEANSE_LINE_C_COMMENTS.sub('', line) 1659 1660 1661class CleansedLines(object): 1662 """Holds 4 copies of all lines with different preprocessing applied to them. 1663 1664 1) elided member contains lines without strings and comments. 1665 2) lines member contains lines without comments. 1666 3) raw_lines member contains all the lines without processing. 1667 4) lines_without_raw_strings member is same as raw_lines, but with C++11 raw 1668 strings removed. 1669 All these members are of <type 'list'>, and of the same length. 1670 """ 1671 1672 def __init__(self, lines): 1673 self.elided = [] 1674 self.lines = [] 1675 self.raw_lines = lines 1676 self.num_lines = len(lines) 1677 self.lines_without_raw_strings = CleanseRawStrings(lines) 1678 for linenum in range(len(self.lines_without_raw_strings)): 1679 self.lines.append(CleanseComments( 1680 self.lines_without_raw_strings[linenum])) 1681 elided = self._CollapseStrings(self.lines_without_raw_strings[linenum]) 1682 self.elided.append(CleanseComments(elided)) 1683 1684 def NumLines(self): 1685 """Returns the number of lines represented.""" 1686 return self.num_lines 1687 1688 @staticmethod 1689 def _CollapseStrings(elided): 1690 """Collapses strings and chars on a line to simple "" or '' blocks. 1691 1692 We nix strings first so we're not fooled by text like '"http://"' 1693 1694 Args: 1695 elided: The line being processed. 1696 1697 Returns: 1698 The line with collapsed strings. 1699 """ 1700 if _RE_PATTERN_INCLUDE.match(elided): 1701 return elided 1702 1703 # Remove escaped characters first to make quote/single quote collapsing 1704 # basic. Things that look like escaped characters shouldn't occur 1705 # outside of strings and chars. 1706 elided = _RE_PATTERN_CLEANSE_LINE_ESCAPES.sub('', elided) 1707 1708 # Replace quoted strings and digit separators. Both single quotes 1709 # and double quotes are processed in the same loop, otherwise 1710 # nested quotes wouldn't work. 1711 collapsed = '' 1712 while True: 1713 # Find the first quote character 1714 match = Match(r'^([^\'"]*)([\'"])(.*)$', elided) 1715 if not match: 1716 collapsed += elided 1717 break 1718 head, quote, tail = match.groups() 1719 1720 if quote == '"': 1721 # Collapse double quoted strings 1722 second_quote = tail.find('"') 1723 if second_quote >= 0: 1724 collapsed += head + '""' 1725 elided = tail[second_quote + 1:] 1726 else: 1727 # Unmatched double quote, don't bother processing the rest 1728 # of the line since this is probably a multiline string. 1729 collapsed += elided 1730 break 1731 else: 1732 # Found single quote, check nearby text to eliminate digit separators. 1733 # 1734 # There is no special handling for floating point here, because 1735 # the integer/fractional/exponent parts would all be parsed 1736 # correctly as long as there are digits on both sides of the 1737 # separator. So we are fine as long as we don't see something 1738 # like "0.'3" (gcc 4.9.0 will not allow this literal). 1739 if Search(r'\b(?:0[bBxX]?|[1-9])[0-9a-fA-F]*$', head): 1740 match_literal = Match(r'^((?:\'?[0-9a-zA-Z_])*)(.*)$', "'" + tail) 1741 collapsed += head + match_literal.group(1).replace("'", '') 1742 elided = match_literal.group(2) 1743 else: 1744 second_quote = tail.find('\'') 1745 if second_quote >= 0: 1746 collapsed += head + "''" 1747 elided = tail[second_quote + 1:] 1748 else: 1749 # Unmatched single quote 1750 collapsed += elided 1751 break 1752 1753 return collapsed 1754 1755 1756def FindEndOfExpressionInLine(line, startpos, stack): 1757 """Find the position just after the end of current parenthesized expression. 1758 1759 Args: 1760 line: a CleansedLines line. 1761 startpos: start searching at this position. 1762 stack: nesting stack at startpos. 1763 1764 Returns: 1765 On finding matching end: (index just after matching end, None) 1766 On finding an unclosed expression: (-1, None) 1767 Otherwise: (-1, new stack at end of this line) 1768 """ 1769 for i in xrange(startpos, len(line)): 1770 char = line[i] 1771 if char in '([{': 1772 # Found start of parenthesized expression, push to expression stack 1773 stack.append(char) 1774 elif char == '<': 1775 # Found potential start of template argument list 1776 if i > 0 and line[i - 1] == '<': 1777 # Left shift operator 1778 if stack and stack[-1] == '<': 1779 stack.pop() 1780 if not stack: 1781 return (-1, None) 1782 elif i > 0 and Search(r'\boperator\s*$', line[0:i]): 1783 # operator<, don't add to stack 1784 continue 1785 else: 1786 # Tentative start of template argument list 1787 stack.append('<') 1788 elif char in ')]}': 1789 # Found end of parenthesized expression. 1790 # 1791 # If we are currently expecting a matching '>', the pending '<' 1792 # must have been an operator. Remove them from expression stack. 1793 while stack and stack[-1] == '<': 1794 stack.pop() 1795 if not stack: 1796 return (-1, None) 1797 if ((stack[-1] == '(' and char == ')') or 1798 (stack[-1] == '[' and char == ']') or 1799 (stack[-1] == '{' and char == '}')): 1800 stack.pop() 1801 if not stack: 1802 return (i + 1, None) 1803 else: 1804 # Mismatched parentheses 1805 return (-1, None) 1806 elif char == '>': 1807 # Found potential end of template argument list. 1808 1809 # Ignore "->" and operator functions 1810 if (i > 0 and 1811 (line[i - 1] == '-' or Search(r'\boperator\s*$', line[0:i - 1]))): 1812 continue 1813 1814 # Pop the stack if there is a matching '<'. Otherwise, ignore 1815 # this '>' since it must be an operator. 1816 if stack: 1817 if stack[-1] == '<': 1818 stack.pop() 1819 if not stack: 1820 return (i + 1, None) 1821 elif char == ';': 1822 # Found something that look like end of statements. If we are currently 1823 # expecting a '>', the matching '<' must have been an operator, since 1824 # template argument list should not contain statements. 1825 while stack and stack[-1] == '<': 1826 stack.pop() 1827 if not stack: 1828 return (-1, None) 1829 1830 # Did not find end of expression or unbalanced parentheses on this line 1831 return (-1, stack) 1832 1833 1834def CloseExpression(clean_lines, linenum, pos): 1835 """If input points to ( or { or [ or <, finds the position that closes it. 1836 1837 If lines[linenum][pos] points to a '(' or '{' or '[' or '<', finds the 1838 linenum/pos that correspond to the closing of the expression. 1839 1840 TODO(unknown): cpplint spends a fair bit of time matching parentheses. 1841 Ideally we would want to index all opening and closing parentheses once 1842 and have CloseExpression be just a simple lookup, but due to preprocessor 1843 tricks, this is not so easy. 1844 1845 Args: 1846 clean_lines: A CleansedLines instance containing the file. 1847 linenum: The number of the line to check. 1848 pos: A position on the line. 1849 1850 Returns: 1851 A tuple (line, linenum, pos) pointer *past* the closing brace, or 1852 (line, len(lines), -1) if we never find a close. Note we ignore 1853 strings and comments when matching; and the line we return is the 1854 'cleansed' line at linenum. 1855 """ 1856 1857 line = clean_lines.elided[linenum] 1858 if (line[pos] not in '({[<') or Match(r'<[<=]', line[pos:]): 1859 return (line, clean_lines.NumLines(), -1) 1860 1861 # Check first line 1862 (end_pos, stack) = FindEndOfExpressionInLine(line, pos, []) 1863 if end_pos > -1: 1864 return (line, linenum, end_pos) 1865 1866 # Continue scanning forward 1867 while stack and linenum < clean_lines.NumLines() - 1: 1868 linenum += 1 1869 line = clean_lines.elided[linenum] 1870 (end_pos, stack) = FindEndOfExpressionInLine(line, 0, stack) 1871 if end_pos > -1: 1872 return (line, linenum, end_pos) 1873 1874 # Did not find end of expression before end of file, give up 1875 return (line, clean_lines.NumLines(), -1) 1876 1877 1878def FindStartOfExpressionInLine(line, endpos, stack): 1879 """Find position at the matching start of current expression. 1880 1881 This is almost the reverse of FindEndOfExpressionInLine, but note 1882 that the input position and returned position differs by 1. 1883 1884 Args: 1885 line: a CleansedLines line. 1886 endpos: start searching at this position. 1887 stack: nesting stack at endpos. 1888 1889 Returns: 1890 On finding matching start: (index at matching start, None) 1891 On finding an unclosed expression: (-1, None) 1892 Otherwise: (-1, new stack at beginning of this line) 1893 """ 1894 i = endpos 1895 while i >= 0: 1896 char = line[i] 1897 if char in ')]}': 1898 # Found end of expression, push to expression stack 1899 stack.append(char) 1900 elif char == '>': 1901 # Found potential end of template argument list. 1902 # 1903 # Ignore it if it's a "->" or ">=" or "operator>" 1904 if (i > 0 and 1905 (line[i - 1] == '-' or 1906 Match(r'\s>=\s', line[i - 1:]) or 1907 Search(r'\boperator\s*$', line[0:i]))): 1908 i -= 1 1909 else: 1910 stack.append('>') 1911 elif char == '<': 1912 # Found potential start of template argument list 1913 if i > 0 and line[i - 1] == '<': 1914 # Left shift operator 1915 i -= 1 1916 else: 1917 # If there is a matching '>', we can pop the expression stack. 1918 # Otherwise, ignore this '<' since it must be an operator. 1919 if stack and stack[-1] == '>': 1920 stack.pop() 1921 if not stack: 1922 return (i, None) 1923 elif char in '([{': 1924 # Found start of expression. 1925 # 1926 # If there are any unmatched '>' on the stack, they must be 1927 # operators. Remove those. 1928 while stack and stack[-1] == '>': 1929 stack.pop() 1930 if not stack: 1931 return (-1, None) 1932 if ((char == '(' and stack[-1] == ')') or 1933 (char == '[' and stack[-1] == ']') or 1934 (char == '{' and stack[-1] == '}')): 1935 stack.pop() 1936 if not stack: 1937 return (i, None) 1938 else: 1939 # Mismatched parentheses 1940 return (-1, None) 1941 elif char == ';': 1942 # Found something that look like end of statements. If we are currently 1943 # expecting a '<', the matching '>' must have been an operator, since 1944 # template argument list should not contain statements. 1945 while stack and stack[-1] == '>': 1946 stack.pop() 1947 if not stack: 1948 return (-1, None) 1949 1950 i -= 1 1951 1952 return (-1, stack) 1953 1954 1955def ReverseCloseExpression(clean_lines, linenum, pos): 1956 """If input points to ) or } or ] or >, finds the position that opens it. 1957 1958 If lines[linenum][pos] points to a ')' or '}' or ']' or '>', finds the 1959 linenum/pos that correspond to the opening of the expression. 1960 1961 Args: 1962 clean_lines: A CleansedLines instance containing the file. 1963 linenum: The number of the line to check. 1964 pos: A position on the line. 1965 1966 Returns: 1967 A tuple (line, linenum, pos) pointer *at* the opening brace, or 1968 (line, 0, -1) if we never find the matching opening brace. Note 1969 we ignore strings and comments when matching; and the line we 1970 return is the 'cleansed' line at linenum. 1971 """ 1972 line = clean_lines.elided[linenum] 1973 if line[pos] not in ')}]>': 1974 return (line, 0, -1) 1975 1976 # Check last line 1977 (start_pos, stack) = FindStartOfExpressionInLine(line, pos, []) 1978 if start_pos > -1: 1979 return (line, linenum, start_pos) 1980 1981 # Continue scanning backward 1982 while stack and linenum > 0: 1983 linenum -= 1 1984 line = clean_lines.elided[linenum] 1985 (start_pos, stack) = FindStartOfExpressionInLine(line, len(line) - 1, stack) 1986 if start_pos > -1: 1987 return (line, linenum, start_pos) 1988 1989 # Did not find start of expression before beginning of file, give up 1990 return (line, 0, -1) 1991 1992 1993def CheckForCopyright(filename, lines, error): 1994 """Logs an error if no Copyright message appears at the top of the file.""" 1995 1996 # We'll say it should occur by line 10. Don't forget there's a 1997 # dummy line at the front. 1998 for line in xrange(1, min(len(lines), 11)): 1999 if re.search(r'Copyright', lines[line], re.I): break 2000 else: # means no copyright line was found 2001 error(filename, 0, 'legal/copyright', 5, 2002 'No copyright message found. ' 2003 'You should have a line: "Copyright [year] <Copyright Owner>"') 2004 2005 2006def GetIndentLevel(line): 2007 """Return the number of leading spaces in line. 2008 2009 Args: 2010 line: A string to check. 2011 2012 Returns: 2013 An integer count of leading spaces, possibly zero. 2014 """ 2015 indent = Match(r'^( *)\S', line) 2016 if indent: 2017 return len(indent.group(1)) 2018 else: 2019 return 0 2020 2021def PathSplitToList(path): 2022 """Returns the path split into a list by the separator. 2023 2024 Args: 2025 path: An absolute or relative path (e.g. '/a/b/c/' or '../a') 2026 2027 Returns: 2028 A list of path components (e.g. ['a', 'b', 'c]). 2029 """ 2030 lst = [] 2031 while True: 2032 (head, tail) = os.path.split(path) 2033 if head == path: # absolute paths end 2034 lst.append(head) 2035 break 2036 if tail == path: # relative paths end 2037 lst.append(tail) 2038 break 2039 2040 path = head 2041 lst.append(tail) 2042 2043 lst.reverse() 2044 return lst 2045 2046def GetHeaderGuardCPPVariable(filename): 2047 """Returns the CPP variable that should be used as a header guard. 2048 2049 Args: 2050 filename: The name of a C++ header file. 2051 2052 Returns: 2053 The CPP variable that should be used as a header guard in the 2054 named file. 2055 2056 """ 2057 2058 # Restores original filename in case that cpplint is invoked from Emacs's 2059 # flymake. 2060 filename = re.sub(r'_flymake\.h$', '.h', filename) 2061 filename = re.sub(r'/\.flymake/([^/]*)$', r'/\1', filename) 2062 # Replace 'c++' with 'cpp'. 2063 filename = filename.replace('C++', 'cpp').replace('c++', 'cpp') 2064 2065 fileinfo = FileInfo(filename) 2066 file_path_from_root = fileinfo.RepositoryName() 2067 2068 def FixupPathFromRoot(): 2069 if _root_debug: 2070 sys.stderr.write("\n_root fixup, _root = '%s', repository name = '%s'\n" 2071 % (_root, fileinfo.RepositoryName())) 2072 2073 # Process the file path with the --root flag if it was set. 2074 if not _root: 2075 if _root_debug: 2076 sys.stderr.write("_root unspecified\n") 2077 return file_path_from_root 2078 2079 def StripListPrefix(lst, prefix): 2080 # f(['x', 'y'], ['w, z']) -> None (not a valid prefix) 2081 if lst[:len(prefix)] != prefix: 2082 return None 2083 # f(['a, 'b', 'c', 'd'], ['a', 'b']) -> ['c', 'd'] 2084 return lst[(len(prefix)):] 2085 2086 # root behavior: 2087 # --root=subdir , lstrips subdir from the header guard 2088 maybe_path = StripListPrefix(PathSplitToList(file_path_from_root), 2089 PathSplitToList(_root)) 2090 2091 if _root_debug: 2092 sys.stderr.write(("_root lstrip (maybe_path=%s, file_path_from_root=%s," + 2093 " _root=%s)\n") % (maybe_path, file_path_from_root, _root)) 2094 2095 if maybe_path: 2096 return os.path.join(*maybe_path) 2097 2098 # --root=.. , will prepend the outer directory to the header guard 2099 full_path = fileinfo.FullName() 2100 root_abspath = os.path.abspath(_root) 2101 2102 maybe_path = StripListPrefix(PathSplitToList(full_path), 2103 PathSplitToList(root_abspath)) 2104 2105 if _root_debug: 2106 sys.stderr.write(("_root prepend (maybe_path=%s, full_path=%s, " + 2107 "root_abspath=%s)\n") % (maybe_path, full_path, root_abspath)) 2108 2109 if maybe_path: 2110 return os.path.join(*maybe_path) 2111 2112 if _root_debug: 2113 sys.stderr.write("_root ignore, returning %s\n" % (file_path_from_root)) 2114 2115 # --root=FAKE_DIR is ignored 2116 return file_path_from_root 2117 2118 file_path_from_root = FixupPathFromRoot() 2119 return re.sub(r'[^a-zA-Z0-9]', '_', file_path_from_root).upper() + '_' 2120 2121 2122def CheckForHeaderGuard(filename, clean_lines, error): 2123 """Checks that the file contains a header guard. 2124 2125 Logs an error if no #ifndef header guard is present. For other 2126 headers, checks that the full pathname is used. 2127 2128 Args: 2129 filename: The name of the C++ header file. 2130 clean_lines: A CleansedLines instance containing the file. 2131 error: The function to call with any errors found. 2132 """ 2133 2134 # Don't check for header guards if there are error suppression 2135 # comments somewhere in this file. 2136 # 2137 # Because this is silencing a warning for a nonexistent line, we 2138 # only support the very specific NOLINT(build/header_guard) syntax, 2139 # and not the general NOLINT or NOLINT(*) syntax. 2140 raw_lines = clean_lines.lines_without_raw_strings 2141 for i in raw_lines: 2142 if Search(r'//\s*NOLINT\(build/header_guard\)', i): 2143 return 2144 2145 # Allow pragma once instead of header guards 2146 for i in raw_lines: 2147 if Search(r'^\s*#pragma\s+once', i): 2148 return 2149 2150 cppvar = GetHeaderGuardCPPVariable(filename) 2151 2152 ifndef = '' 2153 ifndef_linenum = 0 2154 define = '' 2155 endif = '' 2156 endif_linenum = 0 2157 for linenum, line in enumerate(raw_lines): 2158 linesplit = line.split() 2159 if len(linesplit) >= 2: 2160 # find the first occurrence of #ifndef and #define, save arg 2161 if not ifndef and linesplit[0] == '#ifndef': 2162 # set ifndef to the header guard presented on the #ifndef line. 2163 ifndef = linesplit[1] 2164 ifndef_linenum = linenum 2165 if not define and linesplit[0] == '#define': 2166 define = linesplit[1] 2167 # find the last occurrence of #endif, save entire line 2168 if line.startswith('#endif'): 2169 endif = line 2170 endif_linenum = linenum 2171 2172 if not ifndef or not define or ifndef != define: 2173 error(filename, 0, 'build/header_guard', 5, 2174 'No #ifndef header guard found, suggested CPP variable is: %s' % 2175 cppvar) 2176 return 2177 2178 # The guard should be PATH_FILE_H_, but we also allow PATH_FILE_H__ 2179 # for backward compatibility. 2180 if ifndef != cppvar: 2181 error_level = 0 2182 if ifndef != cppvar + '_': 2183 error_level = 5 2184 2185 ParseNolintSuppressions(filename, raw_lines[ifndef_linenum], ifndef_linenum, 2186 error) 2187 error(filename, ifndef_linenum, 'build/header_guard', error_level, 2188 '#ifndef header guard has wrong style, please use: %s' % cppvar) 2189 2190 # Check for "//" comments on endif line. 2191 ParseNolintSuppressions(filename, raw_lines[endif_linenum], endif_linenum, 2192 error) 2193 match = Match(r'#endif\s*//\s*' + cppvar + r'(_)?\b', endif) 2194 if match: 2195 if match.group(1) == '_': 2196 # Issue low severity warning for deprecated double trailing underscore 2197 error(filename, endif_linenum, 'build/header_guard', 0, 2198 '#endif line should be "#endif // %s"' % cppvar) 2199 return 2200 2201 # Didn't find the corresponding "//" comment. If this file does not 2202 # contain any "//" comments at all, it could be that the compiler 2203 # only wants "/**/" comments, look for those instead. 2204 no_single_line_comments = True 2205 for i in xrange(1, len(raw_lines) - 1): 2206 line = raw_lines[i] 2207 if Match(r'^(?:(?:\'(?:\.|[^\'])*\')|(?:"(?:\.|[^"])*")|[^\'"])*//', line): 2208 no_single_line_comments = False 2209 break 2210 2211 if no_single_line_comments: 2212 match = Match(r'#endif\s*/\*\s*' + cppvar + r'(_)?\s*\*/', endif) 2213 if match: 2214 if match.group(1) == '_': 2215 # Low severity warning for double trailing underscore 2216 error(filename, endif_linenum, 'build/header_guard', 0, 2217 '#endif line should be "#endif /* %s */"' % cppvar) 2218 return 2219 2220 # Didn't find anything 2221 error(filename, endif_linenum, 'build/header_guard', 5, 2222 '#endif line should be "#endif // %s"' % cppvar) 2223 2224 2225def CheckHeaderFileIncluded(filename, include_state, error): 2226 """Logs an error if a source file does not include its header.""" 2227 2228 # Do not check test files 2229 fileinfo = FileInfo(filename) 2230 if Search(_TEST_FILE_SUFFIX, fileinfo.BaseName()): 2231 return 2232 2233 for ext in GetHeaderExtensions(): 2234 basefilename = filename[0:len(filename) - len(fileinfo.Extension())] 2235 headerfile = basefilename + '.' + ext 2236 if not os.path.exists(headerfile): 2237 continue 2238 headername = FileInfo(headerfile).RepositoryName() 2239 first_include = None 2240 for section_list in include_state.include_list: 2241 for f in section_list: 2242 if headername in f[0] or f[0] in headername: 2243 return 2244 if not first_include: 2245 first_include = f[1] 2246 2247 error(filename, first_include, 'build/include', 5, 2248 '%s should include its header file %s' % (fileinfo.RepositoryName(), 2249 headername)) 2250 2251 2252def CheckForBadCharacters(filename, lines, error): 2253 """Logs an error for each line containing bad characters. 2254 2255 Two kinds of bad characters: 2256 2257 1. Unicode replacement characters: These indicate that either the file 2258 contained invalid UTF-8 (likely) or Unicode replacement characters (which 2259 it shouldn't). Note that it's possible for this to throw off line 2260 numbering if the invalid UTF-8 occurred adjacent to a newline. 2261 2262 2. NUL bytes. These are problematic for some tools. 2263 2264 Args: 2265 filename: The name of the current file. 2266 lines: An array of strings, each representing a line of the file. 2267 error: The function to call with any errors found. 2268 """ 2269 for linenum, line in enumerate(lines): 2270 if unicode_escape_decode('\ufffd') in line: 2271 error(filename, linenum, 'readability/utf8', 5, 2272 'Line contains invalid UTF-8 (or Unicode replacement character).') 2273 if '\0' in line: 2274 error(filename, linenum, 'readability/nul', 5, 'Line contains NUL byte.') 2275 2276 2277def CheckInlineHeader(filename, include_state, error): 2278 """Logs an error if both a header and its inline variant are included.""" 2279 2280 all_headers = dict(item for sublist in include_state.include_list 2281 for item in sublist) 2282 bad_headers = set('%s.h' % name[:-6] for name in all_headers.keys() 2283 if name.endswith('-inl.h')) 2284 bad_headers &= set(all_headers.keys()) 2285 2286 for name in bad_headers: 2287 err = '%s includes both %s and %s-inl.h' % (filename, name, name) 2288 linenum = all_headers[name] 2289 error(filename, linenum, 'build/include_inline', 5, err) 2290 2291 2292def CheckForNewlineAtEOF(filename, lines, error): 2293 """Logs an error if there is no newline char at the end of the file. 2294 2295 Args: 2296 filename: The name of the current file. 2297 lines: An array of strings, each representing a line of the file. 2298 error: The function to call with any errors found. 2299 """ 2300 2301 # The array lines() was created by adding two newlines to the 2302 # original file (go figure), then splitting on \n. 2303 # To verify that the file ends in \n, we just have to make sure the 2304 # last-but-two element of lines() exists and is empty. 2305 if len(lines) < 3 or lines[-2]: 2306 error(filename, len(lines) - 2, 'whitespace/ending_newline', 5, 2307 'Could not find a newline character at the end of the file.') 2308 2309 2310def CheckForMultilineCommentsAndStrings(filename, clean_lines, linenum, error): 2311 """Logs an error if we see /* ... */ or "..." that extend past one line. 2312 2313 /* ... */ comments are legit inside macros, for one line. 2314 Otherwise, we prefer // comments, so it's ok to warn about the 2315 other. Likewise, it's ok for strings to extend across multiple 2316 lines, as long as a line continuation character (backslash) 2317 terminates each line. Although not currently prohibited by the C++ 2318 style guide, it's ugly and unnecessary. We don't do well with either 2319 in this lint program, so we warn about both. 2320 2321 Args: 2322 filename: The name of the current file. 2323 clean_lines: A CleansedLines instance containing the file. 2324 linenum: The number of the line to check. 2325 error: The function to call with any errors found. 2326 """ 2327 line = clean_lines.elided[linenum] 2328 2329 # Remove all \\ (escaped backslashes) from the line. They are OK, and the 2330 # second (escaped) slash may trigger later \" detection erroneously. 2331 line = line.replace('\\\\', '') 2332 2333 if line.count('/*') > line.count('*/'): 2334 error(filename, linenum, 'readability/multiline_comment', 5, 2335 'Complex multi-line /*...*/-style comment found. ' 2336 'Lint may give bogus warnings. ' 2337 'Consider replacing these with //-style comments, ' 2338 'with #if 0...#endif, ' 2339 'or with more clearly structured multi-line comments.') 2340 2341 if (line.count('"') - line.count('\\"')) % 2: 2342 error(filename, linenum, 'readability/multiline_string', 5, 2343 'Multi-line string ("...") found. This lint script doesn\'t ' 2344 'do well with such strings, and may give bogus warnings. ' 2345 'Use C++11 raw strings or concatenation instead.') 2346 2347 2348# (non-threadsafe name, thread-safe alternative, validation pattern) 2349# 2350# The validation pattern is used to eliminate false positives such as: 2351# _rand(); // false positive due to substring match. 2352# ->rand(); // some member function rand(). 2353# ACMRandom rand(seed); // some variable named rand. 2354# ISAACRandom rand(); // another variable named rand. 2355# 2356# Basically we require the return value of these functions to be used 2357# in some expression context on the same line by matching on some 2358# operator before the function name. This eliminates constructors and 2359# member function calls. 2360_UNSAFE_FUNC_PREFIX = r'(?:[-+*/=%^&|(<]\s*|>\s+)' 2361_THREADING_LIST = ( 2362 ('asctime(', 'asctime_r(', _UNSAFE_FUNC_PREFIX + r'asctime\([^)]+\)'), 2363 ('ctime(', 'ctime_r(', _UNSAFE_FUNC_PREFIX + r'ctime\([^)]+\)'), 2364 ('getgrgid(', 'getgrgid_r(', _UNSAFE_FUNC_PREFIX + r'getgrgid\([^)]+\)'), 2365 ('getgrnam(', 'getgrnam_r(', _UNSAFE_FUNC_PREFIX + r'getgrnam\([^)]+\)'), 2366 ('getlogin(', 'getlogin_r(', _UNSAFE_FUNC_PREFIX + r'getlogin\(\)'), 2367 ('getpwnam(', 'getpwnam_r(', _UNSAFE_FUNC_PREFIX + r'getpwnam\([^)]+\)'), 2368 ('getpwuid(', 'getpwuid_r(', _UNSAFE_FUNC_PREFIX + r'getpwuid\([^)]+\)'), 2369 ('gmtime(', 'gmtime_r(', _UNSAFE_FUNC_PREFIX + r'gmtime\([^)]+\)'), 2370 ('localtime(', 'localtime_r(', _UNSAFE_FUNC_PREFIX + r'localtime\([^)]+\)'), 2371 ('rand(', 'rand_r(', _UNSAFE_FUNC_PREFIX + r'rand\(\)'), 2372 ('strtok(', 'strtok_r(', 2373 _UNSAFE_FUNC_PREFIX + r'strtok\([^)]+\)'), 2374 ('ttyname(', 'ttyname_r(', _UNSAFE_FUNC_PREFIX + r'ttyname\([^)]+\)'), 2375 ) 2376 2377 2378def CheckPosixThreading(filename, clean_lines, linenum, error): 2379 """Checks for calls to thread-unsafe functions. 2380 2381 Much code has been originally written without consideration of 2382 multi-threading. Also, engineers are relying on their old experience; 2383 they have learned posix before threading extensions were added. These 2384 tests guide the engineers to use thread-safe functions (when using 2385 posix directly). 2386 2387 Args: 2388 filename: The name of the current file. 2389 clean_lines: A CleansedLines instance containing the file. 2390 linenum: The number of the line to check. 2391 error: The function to call with any errors found. 2392 """ 2393 line = clean_lines.elided[linenum] 2394 for single_thread_func, multithread_safe_func, pattern in _THREADING_LIST: 2395 # Additional pattern matching check to confirm that this is the 2396 # function we are looking for 2397 if Search(pattern, line): 2398 error(filename, linenum, 'runtime/threadsafe_fn', 2, 2399 'Consider using ' + multithread_safe_func + 2400 '...) instead of ' + single_thread_func + 2401 '...) for improved thread safety.') 2402 2403 2404def CheckVlogArguments(filename, clean_lines, linenum, error): 2405 """Checks that VLOG() is only used for defining a logging level. 2406 2407 For example, VLOG(2) is correct. VLOG(INFO), VLOG(WARNING), VLOG(ERROR), and 2408 VLOG(FATAL) are not. 2409 2410 Args: 2411 filename: The name of the current file. 2412 clean_lines: A CleansedLines instance containing the file. 2413 linenum: The number of the line to check. 2414 error: The function to call with any errors found. 2415 """ 2416 line = clean_lines.elided[linenum] 2417 if Search(r'\bVLOG\((INFO|ERROR|WARNING|DFATAL|FATAL)\)', line): 2418 error(filename, linenum, 'runtime/vlog', 5, 2419 'VLOG() should be used with numeric verbosity level. ' 2420 'Use LOG() if you want symbolic severity levels.') 2421 2422# Matches invalid increment: *count++, which moves pointer instead of 2423# incrementing a value. 2424_RE_PATTERN_INVALID_INCREMENT = re.compile( 2425 r'^\s*\*\w+(\+\+|--);') 2426 2427 2428def CheckInvalidIncrement(filename, clean_lines, linenum, error): 2429 """Checks for invalid increment *count++. 2430 2431 For example following function: 2432 void increment_counter(int* count) { 2433 *count++; 2434 } 2435 is invalid, because it effectively does count++, moving pointer, and should 2436 be replaced with ++*count, (*count)++ or *count += 1. 2437 2438 Args: 2439 filename: The name of the current file. 2440 clean_lines: A CleansedLines instance containing the file. 2441 linenum: The number of the line to check. 2442 error: The function to call with any errors found. 2443 """ 2444 line = clean_lines.elided[linenum] 2445 if _RE_PATTERN_INVALID_INCREMENT.match(line): 2446 error(filename, linenum, 'runtime/invalid_increment', 5, 2447 'Changing pointer instead of value (or unused value of operator*).') 2448 2449 2450def IsMacroDefinition(clean_lines, linenum): 2451 if Search(r'^#define', clean_lines[linenum]): 2452 return True 2453 2454 if linenum > 0 and Search(r'\\$', clean_lines[linenum - 1]): 2455 return True 2456 2457 return False 2458 2459 2460def IsForwardClassDeclaration(clean_lines, linenum): 2461 return Match(r'^\s*(\btemplate\b)*.*class\s+\w+;\s*$', clean_lines[linenum]) 2462 2463 2464class _BlockInfo(object): 2465 """Stores information about a generic block of code.""" 2466 2467 def __init__(self, linenum, seen_open_brace): 2468 self.starting_linenum = linenum 2469 self.seen_open_brace = seen_open_brace 2470 self.open_parentheses = 0 2471 self.inline_asm = _NO_ASM 2472 self.check_namespace_indentation = False 2473 2474 def CheckBegin(self, filename, clean_lines, linenum, error): 2475 """Run checks that applies to text up to the opening brace. 2476 2477 This is mostly for checking the text after the class identifier 2478 and the "{", usually where the base class is specified. For other 2479 blocks, there isn't much to check, so we always pass. 2480 2481 Args: 2482 filename: The name of the current file. 2483 clean_lines: A CleansedLines instance containing the file. 2484 linenum: The number of the line to check. 2485 error: The function to call with any errors found. 2486 """ 2487 pass 2488 2489 def CheckEnd(self, filename, clean_lines, linenum, error): 2490 """Run checks that applies to text after the closing brace. 2491 2492 This is mostly used for checking end of namespace comments. 2493 2494 Args: 2495 filename: The name of the current file. 2496 clean_lines: A CleansedLines instance containing the file. 2497 linenum: The number of the line to check. 2498 error: The function to call with any errors found. 2499 """ 2500 pass 2501 2502 def IsBlockInfo(self): 2503 """Returns true if this block is a _BlockInfo. 2504 2505 This is convenient for verifying that an object is an instance of 2506 a _BlockInfo, but not an instance of any of the derived classes. 2507 2508 Returns: 2509 True for this class, False for derived classes. 2510 """ 2511 return self.__class__ == _BlockInfo 2512 2513 2514class _ExternCInfo(_BlockInfo): 2515 """Stores information about an 'extern "C"' block.""" 2516 2517 def __init__(self, linenum): 2518 _BlockInfo.__init__(self, linenum, True) 2519 2520 2521class _ClassInfo(_BlockInfo): 2522 """Stores information about a class.""" 2523 2524 def __init__(self, name, class_or_struct, clean_lines, linenum): 2525 _BlockInfo.__init__(self, linenum, False) 2526 self.name = name 2527 self.is_derived = False 2528 self.check_namespace_indentation = True 2529 if class_or_struct == 'struct': 2530 self.access = 'public' 2531 self.is_struct = True 2532 else: 2533 self.access = 'private' 2534 self.is_struct = False 2535 2536 # Remember initial indentation level for this class. Using raw_lines here 2537 # instead of elided to account for leading comments. 2538 self.class_indent = GetIndentLevel(clean_lines.raw_lines[linenum]) 2539 2540 # Try to find the end of the class. This will be confused by things like: 2541 # class A { 2542 # } *x = { ... 2543 # 2544 # But it's still good enough for CheckSectionSpacing. 2545 self.last_line = 0 2546 depth = 0 2547 for i in range(linenum, clean_lines.NumLines()): 2548 line = clean_lines.elided[i] 2549 depth += line.count('{') - line.count('}') 2550 if not depth: 2551 self.last_line = i 2552 break 2553 2554 def CheckBegin(self, filename, clean_lines, linenum, error): 2555 # Look for a bare ':' 2556 if Search('(^|[^:]):($|[^:])', clean_lines.elided[linenum]): 2557 self.is_derived = True 2558 2559 def CheckEnd(self, filename, clean_lines, linenum, error): 2560 # If there is a DISALLOW macro, it should appear near the end of 2561 # the class. 2562 seen_last_thing_in_class = False 2563 for i in xrange(linenum - 1, self.starting_linenum, -1): 2564 match = Search( 2565 r'\b(DISALLOW_COPY_AND_ASSIGN|DISALLOW_IMPLICIT_CONSTRUCTORS)\(' + 2566 self.name + r'\)', 2567 clean_lines.elided[i]) 2568 if match: 2569 if seen_last_thing_in_class: 2570 error(filename, i, 'readability/constructors', 3, 2571 match.group(1) + ' should be the last thing in the class') 2572 break 2573 2574 if not Match(r'^\s*$', clean_lines.elided[i]): 2575 seen_last_thing_in_class = True 2576 2577 # Check that closing brace is aligned with beginning of the class. 2578 # Only do this if the closing brace is indented by only whitespaces. 2579 # This means we will not check single-line class definitions. 2580 indent = Match(r'^( *)\}', clean_lines.elided[linenum]) 2581 if indent and len(indent.group(1)) != self.class_indent: 2582 if self.is_struct: 2583 parent = 'struct ' + self.name 2584 else: 2585 parent = 'class ' + self.name 2586 error(filename, linenum, 'whitespace/indent', 3, 2587 'Closing brace should be aligned with beginning of %s' % parent) 2588 2589 2590class _NamespaceInfo(_BlockInfo): 2591 """Stores information about a namespace.""" 2592 2593 def __init__(self, name, linenum): 2594 _BlockInfo.__init__(self, linenum, False) 2595 self.name = name or '' 2596 self.check_namespace_indentation = True 2597 2598 def CheckEnd(self, filename, clean_lines, linenum, error): 2599 """Check end of namespace comments.""" 2600 line = clean_lines.raw_lines[linenum] 2601 2602 # Check how many lines is enclosed in this namespace. Don't issue 2603 # warning for missing namespace comments if there aren't enough 2604 # lines. However, do apply checks if there is already an end of 2605 # namespace comment and it's incorrect. 2606 # 2607 # TODO(unknown): We always want to check end of namespace comments 2608 # if a namespace is large, but sometimes we also want to apply the 2609 # check if a short namespace contained nontrivial things (something 2610 # other than forward declarations). There is currently no logic on 2611 # deciding what these nontrivial things are, so this check is 2612 # triggered by namespace size only, which works most of the time. 2613 if (linenum - self.starting_linenum < 10 2614 and not Match(r'^\s*};*\s*(//|/\*).*\bnamespace\b', line)): 2615 return 2616 2617 # Look for matching comment at end of namespace. 2618 # 2619 # Note that we accept C style "/* */" comments for terminating 2620 # namespaces, so that code that terminate namespaces inside 2621 # preprocessor macros can be cpplint clean. 2622 # 2623 # We also accept stuff like "// end of namespace <name>." with the 2624 # period at the end. 2625 # 2626 # Besides these, we don't accept anything else, otherwise we might 2627 # get false negatives when existing comment is a substring of the 2628 # expected namespace. 2629 if self.name: 2630 # Named namespace 2631 if not Match((r'^\s*};*\s*(//|/\*).*\bnamespace\s+' + 2632 re.escape(self.name) + r'[\*/\.\\\s]*$'), 2633 line): 2634 error(filename, linenum, 'readability/namespace', 5, 2635 'Namespace should be terminated with "// namespace %s"' % 2636 self.name) 2637 else: 2638 # Anonymous namespace 2639 if not Match(r'^\s*};*\s*(//|/\*).*\bnamespace[\*/\.\\\s]*$', line): 2640 # If "// namespace anonymous" or "// anonymous namespace (more text)", 2641 # mention "// anonymous namespace" as an acceptable form 2642 if Match(r'^\s*}.*\b(namespace anonymous|anonymous namespace)\b', line): 2643 error(filename, linenum, 'readability/namespace', 5, 2644 'Anonymous namespace should be terminated with "// namespace"' 2645 ' or "// anonymous namespace"') 2646 else: 2647 error(filename, linenum, 'readability/namespace', 5, 2648 'Anonymous namespace should be terminated with "// namespace"') 2649 2650 2651class _PreprocessorInfo(object): 2652 """Stores checkpoints of nesting stacks when #if/#else is seen.""" 2653 2654 def __init__(self, stack_before_if): 2655 # The entire nesting stack before #if 2656 self.stack_before_if = stack_before_if 2657 2658 # The entire nesting stack up to #else 2659 self.stack_before_else = [] 2660 2661 # Whether we have already seen #else or #elif 2662 self.seen_else = False 2663 2664 2665class NestingState(object): 2666 """Holds states related to parsing braces.""" 2667 2668 def __init__(self): 2669 # Stack for tracking all braces. An object is pushed whenever we 2670 # see a "{", and popped when we see a "}". Only 3 types of 2671 # objects are possible: 2672 # - _ClassInfo: a class or struct. 2673 # - _NamespaceInfo: a namespace. 2674 # - _BlockInfo: some other type of block. 2675 self.stack = [] 2676 2677 # Top of the previous stack before each Update(). 2678 # 2679 # Because the nesting_stack is updated at the end of each line, we 2680 # had to do some convoluted checks to find out what is the current 2681 # scope at the beginning of the line. This check is simplified by 2682 # saving the previous top of nesting stack. 2683 # 2684 # We could save the full stack, but we only need the top. Copying 2685 # the full nesting stack would slow down cpplint by ~10%. 2686 self.previous_stack_top = [] 2687 2688 # Stack of _PreprocessorInfo objects. 2689 self.pp_stack = [] 2690 2691 def SeenOpenBrace(self): 2692 """Check if we have seen the opening brace for the innermost block. 2693 2694 Returns: 2695 True if we have seen the opening brace, False if the innermost 2696 block is still expecting an opening brace. 2697 """ 2698 return (not self.stack) or self.stack[-1].seen_open_brace 2699 2700 def InNamespaceBody(self): 2701 """Check if we are currently one level inside a namespace body. 2702 2703 Returns: 2704 True if top of the stack is a namespace block, False otherwise. 2705 """ 2706 return self.stack and isinstance(self.stack[-1], _NamespaceInfo) 2707 2708 def InExternC(self): 2709 """Check if we are currently one level inside an 'extern "C"' block. 2710 2711 Returns: 2712 True if top of the stack is an extern block, False otherwise. 2713 """ 2714 return self.stack and isinstance(self.stack[-1], _ExternCInfo) 2715 2716 def InClassDeclaration(self): 2717 """Check if we are currently one level inside a class or struct declaration. 2718 2719 Returns: 2720 True if top of the stack is a class/struct, False otherwise. 2721 """ 2722 return self.stack and isinstance(self.stack[-1], _ClassInfo) 2723 2724 def InAsmBlock(self): 2725 """Check if we are currently one level inside an inline ASM block. 2726 2727 Returns: 2728 True if the top of the stack is a block containing inline ASM. 2729 """ 2730 return self.stack and self.stack[-1].inline_asm != _NO_ASM 2731 2732 def InTemplateArgumentList(self, clean_lines, linenum, pos): 2733 """Check if current position is inside template argument list. 2734 2735 Args: 2736 clean_lines: A CleansedLines instance containing the file. 2737 linenum: The number of the line to check. 2738 pos: position just after the suspected template argument. 2739 Returns: 2740 True if (linenum, pos) is inside template arguments. 2741 """ 2742 while linenum < clean_lines.NumLines(): 2743 # Find the earliest character that might indicate a template argument 2744 line = clean_lines.elided[linenum] 2745 match = Match(r'^[^{};=\[\]\.<>]*(.)', line[pos:]) 2746 if not match: 2747 linenum += 1 2748 pos = 0 2749 continue 2750 token = match.group(1) 2751 pos += len(match.group(0)) 2752 2753 # These things do not look like template argument list: 2754 # class Suspect { 2755 # class Suspect x; } 2756 if token in ('{', '}', ';'): return False 2757 2758 # These things look like template argument list: 2759 # template <class Suspect> 2760 # template <class Suspect = default_value> 2761 # template <class Suspect[]> 2762 # template <class Suspect...> 2763 if token in ('>', '=', '[', ']', '.'): return True 2764 2765 # Check if token is an unmatched '<'. 2766 # If not, move on to the next character. 2767 if token != '<': 2768 pos += 1 2769 if pos >= len(line): 2770 linenum += 1 2771 pos = 0 2772 continue 2773 2774 # We can't be sure if we just find a single '<', and need to 2775 # find the matching '>'. 2776 (_, end_line, end_pos) = CloseExpression(clean_lines, linenum, pos - 1) 2777 if end_pos < 0: 2778 # Not sure if template argument list or syntax error in file 2779 return False 2780 linenum = end_line 2781 pos = end_pos 2782 return False 2783 2784 def UpdatePreprocessor(self, line): 2785 """Update preprocessor stack. 2786 2787 We need to handle preprocessors due to classes like this: 2788 #ifdef SWIG 2789 struct ResultDetailsPageElementExtensionPoint { 2790 #else 2791 struct ResultDetailsPageElementExtensionPoint : public Extension { 2792 #endif 2793 2794 We make the following assumptions (good enough for most files): 2795 - Preprocessor condition evaluates to true from #if up to first 2796 #else/#elif/#endif. 2797 2798 - Preprocessor condition evaluates to false from #else/#elif up 2799 to #endif. We still perform lint checks on these lines, but 2800 these do not affect nesting stack. 2801 2802 Args: 2803 line: current line to check. 2804 """ 2805 if Match(r'^\s*#\s*(if|ifdef|ifndef)\b', line): 2806 # Beginning of #if block, save the nesting stack here. The saved 2807 # stack will allow us to restore the parsing state in the #else case. 2808 self.pp_stack.append(_PreprocessorInfo(copy.deepcopy(self.stack))) 2809 elif Match(r'^\s*#\s*(else|elif)\b', line): 2810 # Beginning of #else block 2811 if self.pp_stack: 2812 if not self.pp_stack[-1].seen_else: 2813 # This is the first #else or #elif block. Remember the 2814 # whole nesting stack up to this point. This is what we 2815 # keep after the #endif. 2816 self.pp_stack[-1].seen_else = True 2817 self.pp_stack[-1].stack_before_else = copy.deepcopy(self.stack) 2818 2819 # Restore the stack to how it was before the #if 2820 self.stack = copy.deepcopy(self.pp_stack[-1].stack_before_if) 2821 else: 2822 # TODO(unknown): unexpected #else, issue warning? 2823 pass 2824 elif Match(r'^\s*#\s*endif\b', line): 2825 # End of #if or #else blocks. 2826 if self.pp_stack: 2827 # If we saw an #else, we will need to restore the nesting 2828 # stack to its former state before the #else, otherwise we 2829 # will just continue from where we left off. 2830 if self.pp_stack[-1].seen_else: 2831 # Here we can just use a shallow copy since we are the last 2832 # reference to it. 2833 self.stack = self.pp_stack[-1].stack_before_else 2834 # Drop the corresponding #if 2835 self.pp_stack.pop() 2836 else: 2837 # TODO(unknown): unexpected #endif, issue warning? 2838 pass 2839 2840 # TODO(unknown): Update() is too long, but we will refactor later. 2841 def Update(self, filename, clean_lines, linenum, error): 2842 """Update nesting state with current line. 2843 2844 Args: 2845 filename: The name of the current file. 2846 clean_lines: A CleansedLines instance containing the file. 2847 linenum: The number of the line to check. 2848 error: The function to call with any errors found. 2849 """ 2850 line = clean_lines.elided[linenum] 2851 2852 # Remember top of the previous nesting stack. 2853 # 2854 # The stack is always pushed/popped and not modified in place, so 2855 # we can just do a shallow copy instead of copy.deepcopy. Using 2856 # deepcopy would slow down cpplint by ~28%. 2857 if self.stack: 2858 self.previous_stack_top = self.stack[-1] 2859 else: 2860 self.previous_stack_top = None 2861 2862 # Update pp_stack 2863 self.UpdatePreprocessor(line) 2864 2865 # Count parentheses. This is to avoid adding struct arguments to 2866 # the nesting stack. 2867 if self.stack: 2868 inner_block = self.stack[-1] 2869 depth_change = line.count('(') - line.count(')') 2870 inner_block.open_parentheses += depth_change 2871 2872 # Also check if we are starting or ending an inline assembly block. 2873 if inner_block.inline_asm in (_NO_ASM, _END_ASM): 2874 if (depth_change != 0 and 2875 inner_block.open_parentheses == 1 and 2876 _MATCH_ASM.match(line)): 2877 # Enter assembly block 2878 inner_block.inline_asm = _INSIDE_ASM 2879 else: 2880 # Not entering assembly block. If previous line was _END_ASM, 2881 # we will now shift to _NO_ASM state. 2882 inner_block.inline_asm = _NO_ASM 2883 elif (inner_block.inline_asm == _INSIDE_ASM and 2884 inner_block.open_parentheses == 0): 2885 # Exit assembly block 2886 inner_block.inline_asm = _END_ASM 2887 2888 # Consume namespace declaration at the beginning of the line. Do 2889 # this in a loop so that we catch same line declarations like this: 2890 # namespace proto2 { namespace bridge { class MessageSet; } } 2891 while True: 2892 # Match start of namespace. The "\b\s*" below catches namespace 2893 # declarations even if it weren't followed by a whitespace, this 2894 # is so that we don't confuse our namespace checker. The 2895 # missing spaces will be flagged by CheckSpacing. 2896 namespace_decl_match = Match(r'^\s*namespace\b\s*([:\w]+)?(.*)$', line) 2897 if not namespace_decl_match: 2898 break 2899 2900 new_namespace = _NamespaceInfo(namespace_decl_match.group(1), linenum) 2901 self.stack.append(new_namespace) 2902 2903 line = namespace_decl_match.group(2) 2904 if line.find('{') != -1: 2905 new_namespace.seen_open_brace = True 2906 line = line[line.find('{') + 1:] 2907 2908 # Look for a class declaration in whatever is left of the line 2909 # after parsing namespaces. The regexp accounts for decorated classes 2910 # such as in: 2911 # class LOCKABLE API Object { 2912 # }; 2913 class_decl_match = Match( 2914 r'^(\s*(?:template\s*<[\w\s<>,:=]*>\s*)?' 2915 r'(class|struct)\s+(?:[A-Z_]+\s+)*(\w+(?:::\w+)*))' 2916 r'(.*)$', line) 2917 if (class_decl_match and 2918 (not self.stack or self.stack[-1].open_parentheses == 0)): 2919 # We do not want to accept classes that are actually template arguments: 2920 # template <class Ignore1, 2921 # class Ignore2 = Default<Args>, 2922 # template <Args> class Ignore3> 2923 # void Function() {}; 2924 # 2925 # To avoid template argument cases, we scan forward and look for 2926 # an unmatched '>'. If we see one, assume we are inside a 2927 # template argument list. 2928 end_declaration = len(class_decl_match.group(1)) 2929 if not self.InTemplateArgumentList(clean_lines, linenum, end_declaration): 2930 self.stack.append(_ClassInfo( 2931 class_decl_match.group(3), class_decl_match.group(2), 2932 clean_lines, linenum)) 2933 line = class_decl_match.group(4) 2934 2935 # If we have not yet seen the opening brace for the innermost block, 2936 # run checks here. 2937 if not self.SeenOpenBrace(): 2938 self.stack[-1].CheckBegin(filename, clean_lines, linenum, error) 2939 2940 # Update access control if we are inside a class/struct 2941 if self.stack and isinstance(self.stack[-1], _ClassInfo): 2942 classinfo = self.stack[-1] 2943 access_match = Match( 2944 r'^(.*)\b(public|private|protected|signals)(\s+(?:slots\s*)?)?' 2945 r':(?:[^:]|$)', 2946 line) 2947 if access_match: 2948 classinfo.access = access_match.group(2) 2949 2950 # Check that access keywords are indented +1 space. Skip this 2951 # check if the keywords are not preceded by whitespaces. 2952 indent = access_match.group(1) 2953 if (len(indent) != classinfo.class_indent + 1 and 2954 Match(r'^\s*$', indent)): 2955 if classinfo.is_struct: 2956 parent = 'struct ' + classinfo.name 2957 else: 2958 parent = 'class ' + classinfo.name 2959 slots = '' 2960 if access_match.group(3): 2961 slots = access_match.group(3) 2962 error(filename, linenum, 'whitespace/indent', 3, 2963 '%s%s: should be indented +1 space inside %s' % ( 2964 access_match.group(2), slots, parent)) 2965 2966 # Consume braces or semicolons from what's left of the line 2967 while True: 2968 # Match first brace, semicolon, or closed parenthesis. 2969 matched = Match(r'^[^{;)}]*([{;)}])(.*)$', line) 2970 if not matched: 2971 break 2972 2973 token = matched.group(1) 2974 if token == '{': 2975 # If namespace or class hasn't seen a opening brace yet, mark 2976 # namespace/class head as complete. Push a new block onto the 2977 # stack otherwise. 2978 if not self.SeenOpenBrace(): 2979 self.stack[-1].seen_open_brace = True 2980 elif Match(r'^extern\s*"[^"]*"\s*\{', line): 2981 self.stack.append(_ExternCInfo(linenum)) 2982 else: 2983 self.stack.append(_BlockInfo(linenum, True)) 2984 if _MATCH_ASM.match(line): 2985 self.stack[-1].inline_asm = _BLOCK_ASM 2986 2987 elif token == ';' or token == ')': 2988 # If we haven't seen an opening brace yet, but we already saw 2989 # a semicolon, this is probably a forward declaration. Pop 2990 # the stack for these. 2991 # 2992 # Similarly, if we haven't seen an opening brace yet, but we 2993 # already saw a closing parenthesis, then these are probably 2994 # function arguments with extra "class" or "struct" keywords. 2995 # Also pop these stack for these. 2996 if not self.SeenOpenBrace(): 2997 self.stack.pop() 2998 else: # token == '}' 2999 # Perform end of block checks and pop the stack. 3000 if self.stack: 3001 self.stack[-1].CheckEnd(filename, clean_lines, linenum, error) 3002 self.stack.pop() 3003 line = matched.group(2) 3004 3005 def InnermostClass(self): 3006 """Get class info on the top of the stack. 3007 3008 Returns: 3009 A _ClassInfo object if we are inside a class, or None otherwise. 3010 """ 3011 for i in range(len(self.stack), 0, -1): 3012 classinfo = self.stack[i - 1] 3013 if isinstance(classinfo, _ClassInfo): 3014 return classinfo 3015 return None 3016 3017 def CheckCompletedBlocks(self, filename, error): 3018 """Checks that all classes and namespaces have been completely parsed. 3019 3020 Call this when all lines in a file have been processed. 3021 Args: 3022 filename: The name of the current file. 3023 error: The function to call with any errors found. 3024 """ 3025 # Note: This test can result in false positives if #ifdef constructs 3026 # get in the way of brace matching. See the testBuildClass test in 3027 # cpplint_unittest.py for an example of this. 3028 for obj in self.stack: 3029 if isinstance(obj, _ClassInfo): 3030 error(filename, obj.starting_linenum, 'build/class', 5, 3031 'Failed to find complete declaration of class %s' % 3032 obj.name) 3033 elif isinstance(obj, _NamespaceInfo): 3034 error(filename, obj.starting_linenum, 'build/namespaces', 5, 3035 'Failed to find complete declaration of namespace %s' % 3036 obj.name) 3037 3038 3039def CheckForNonStandardConstructs(filename, clean_lines, linenum, 3040 nesting_state, error): 3041 r"""Logs an error if we see certain non-ANSI constructs ignored by gcc-2. 3042 3043 Complain about several constructs which gcc-2 accepts, but which are 3044 not standard C++. Warning about these in lint is one way to ease the 3045 transition to new compilers. 3046 - put storage class first (e.g. "static const" instead of "const static"). 3047 - "%lld" instead of %qd" in printf-type functions. 3048 - "%1$d" is non-standard in printf-type functions. 3049 - "\%" is an undefined character escape sequence. 3050 - text after #endif is not allowed. 3051 - invalid inner-style forward declaration. 3052 - >? and <? operators, and their >?= and <?= cousins. 3053 3054 Additionally, check for constructor/destructor style violations and reference 3055 members, as it is very convenient to do so while checking for 3056 gcc-2 compliance. 3057 3058 Args: 3059 filename: The name of the current file. 3060 clean_lines: A CleansedLines instance containing the file. 3061 linenum: The number of the line to check. 3062 nesting_state: A NestingState instance which maintains information about 3063 the current stack of nested blocks being parsed. 3064 error: A callable to which errors are reported, which takes 4 arguments: 3065 filename, line number, error level, and message 3066 """ 3067 3068 # Remove comments from the line, but leave in strings for now. 3069 line = clean_lines.lines[linenum] 3070 3071 if Search(r'printf\s*\(.*".*%[-+ ]?\d*q', line): 3072 error(filename, linenum, 'runtime/printf_format', 3, 3073 '%q in format strings is deprecated. Use %ll instead.') 3074 3075 if Search(r'printf\s*\(.*".*%\d+\$', line): 3076 error(filename, linenum, 'runtime/printf_format', 2, 3077 '%N$ formats are unconventional. Try rewriting to avoid them.') 3078 3079 # Remove escaped backslashes before looking for undefined escapes. 3080 line = line.replace('\\\\', '') 3081 3082 if Search(r'("|\').*\\(%|\[|\(|{)', line): 3083 error(filename, linenum, 'build/printf_format', 3, 3084 '%, [, (, and { are undefined character escapes. Unescape them.') 3085 3086 # For the rest, work with both comments and strings removed. 3087 line = clean_lines.elided[linenum] 3088 3089 if Search(r'\b(const|volatile|void|char|short|int|long' 3090 r'|float|double|signed|unsigned' 3091 r'|schar|u?int8|u?int16|u?int32|u?int64)' 3092 r'\s+(register|static|extern|typedef)\b', 3093 line): 3094 error(filename, linenum, 'build/storage_class', 5, 3095 'Storage-class specifier (static, extern, typedef, etc) should be ' 3096 'at the beginning of the declaration.') 3097 3098 if Match(r'\s*#\s*endif\s*[^/\s]+', line): 3099 error(filename, linenum, 'build/endif_comment', 5, 3100 'Uncommented text after #endif is non-standard. Use a comment.') 3101 3102 if Match(r'\s*class\s+(\w+\s*::\s*)+\w+\s*;', line): 3103 error(filename, linenum, 'build/forward_decl', 5, 3104 'Inner-style forward declarations are invalid. Remove this line.') 3105 3106 if Search(r'(\w+|[+-]?\d+(\.\d*)?)\s*(<|>)\?=?\s*(\w+|[+-]?\d+)(\.\d*)?', 3107 line): 3108 error(filename, linenum, 'build/deprecated', 3, 3109 '>? and <? (max and min) operators are non-standard and deprecated.') 3110 3111 if Search(r'^\s*const\s*string\s*&\s*\w+\s*;', line): 3112 # TODO(unknown): Could it be expanded safely to arbitrary references, 3113 # without triggering too many false positives? The first 3114 # attempt triggered 5 warnings for mostly benign code in the regtest, hence 3115 # the restriction. 3116 # Here's the original regexp, for the reference: 3117 # type_name = r'\w+((\s*::\s*\w+)|(\s*<\s*\w+?\s*>))?' 3118 # r'\s*const\s*' + type_name + '\s*&\s*\w+\s*;' 3119 error(filename, linenum, 'runtime/member_string_references', 2, 3120 'const string& members are dangerous. It is much better to use ' 3121 'alternatives, such as pointers or simple constants.') 3122 3123 # Everything else in this function operates on class declarations. 3124 # Return early if the top of the nesting stack is not a class, or if 3125 # the class head is not completed yet. 3126 classinfo = nesting_state.InnermostClass() 3127 if not classinfo or not classinfo.seen_open_brace: 3128 return 3129 3130 # The class may have been declared with namespace or classname qualifiers. 3131 # The constructor and destructor will not have those qualifiers. 3132 base_classname = classinfo.name.split('::')[-1] 3133 3134 # Look for single-argument constructors that aren't marked explicit. 3135 # Technically a valid construct, but against style. 3136 explicit_constructor_match = Match( 3137 r'\s+(?:(?:inline|constexpr)\s+)*(explicit\s+)?' 3138 r'(?:(?:inline|constexpr)\s+)*%s\s*' 3139 r'\(((?:[^()]|\([^()]*\))*)\)' 3140 % re.escape(base_classname), 3141 line) 3142 3143 if explicit_constructor_match: 3144 is_marked_explicit = explicit_constructor_match.group(1) 3145 3146 if not explicit_constructor_match.group(2): 3147 constructor_args = [] 3148 else: 3149 constructor_args = explicit_constructor_match.group(2).split(',') 3150 3151 # collapse arguments so that commas in template parameter lists and function 3152 # argument parameter lists don't split arguments in two 3153 i = 0 3154 while i < len(constructor_args): 3155 constructor_arg = constructor_args[i] 3156 while (constructor_arg.count('<') > constructor_arg.count('>') or 3157 constructor_arg.count('(') > constructor_arg.count(')')): 3158 constructor_arg += ',' + constructor_args[i + 1] 3159 del constructor_args[i + 1] 3160 constructor_args[i] = constructor_arg 3161 i += 1 3162 3163 variadic_args = [arg for arg in constructor_args if '&&...' in arg] 3164 defaulted_args = [arg for arg in constructor_args if '=' in arg] 3165 noarg_constructor = (not constructor_args or # empty arg list 3166 # 'void' arg specifier 3167 (len(constructor_args) == 1 and 3168 constructor_args[0].strip() == 'void')) 3169 onearg_constructor = ((len(constructor_args) == 1 and # exactly one arg 3170 not noarg_constructor) or 3171 # all but at most one arg defaulted 3172 (len(constructor_args) >= 1 and 3173 not noarg_constructor and 3174 len(defaulted_args) >= len(constructor_args) - 1) or 3175 # variadic arguments with zero or one argument 3176 (len(constructor_args) <= 2 and 3177 len(variadic_args) >= 1)) 3178 initializer_list_constructor = bool( 3179 onearg_constructor and 3180 Search(r'\bstd\s*::\s*initializer_list\b', constructor_args[0])) 3181 copy_constructor = bool( 3182 onearg_constructor and 3183 Match(r'((const\s+(volatile\s+)?)?|(volatile\s+(const\s+)?))?' 3184 r'%s(\s*<[^>]*>)?(\s+const)?\s*(?:<\w+>\s*)?&' 3185 % re.escape(base_classname), constructor_args[0].strip())) 3186 3187 if (not is_marked_explicit and 3188 onearg_constructor and 3189 not initializer_list_constructor and 3190 not copy_constructor): 3191 if defaulted_args or variadic_args: 3192 error(filename, linenum, 'runtime/explicit', 5, 3193 'Constructors callable with one argument ' 3194 'should be marked explicit.') 3195 else: 3196 error(filename, linenum, 'runtime/explicit', 5, 3197 'Single-parameter constructors should be marked explicit.') 3198 elif is_marked_explicit and not onearg_constructor: 3199 if noarg_constructor: 3200 error(filename, linenum, 'runtime/explicit', 5, 3201 'Zero-parameter constructors should not be marked explicit.') 3202 3203 3204def CheckSpacingForFunctionCall(filename, clean_lines, linenum, error): 3205 """Checks for the correctness of various spacing around function calls. 3206 3207 Args: 3208 filename: The name of the current file. 3209 clean_lines: A CleansedLines instance containing the file. 3210 linenum: The number of the line to check. 3211 error: The function to call with any errors found. 3212 """ 3213 line = clean_lines.elided[linenum] 3214 3215 # Since function calls often occur inside if/for/while/switch 3216 # expressions - which have their own, more liberal conventions - we 3217 # first see if we should be looking inside such an expression for a 3218 # function call, to which we can apply more strict standards. 3219 fncall = line # if there's no control flow construct, look at whole line 3220 for pattern in (r'\bif\s*\((.*)\)\s*{', 3221 r'\bfor\s*\((.*)\)\s*{', 3222 r'\bwhile\s*\((.*)\)\s*[{;]', 3223 r'\bswitch\s*\((.*)\)\s*{'): 3224 match = Search(pattern, line) 3225 if match: 3226 fncall = match.group(1) # look inside the parens for function calls 3227 break 3228 3229 # Except in if/for/while/switch, there should never be space 3230 # immediately inside parens (eg "f( 3, 4 )"). We make an exception 3231 # for nested parens ( (a+b) + c ). Likewise, there should never be 3232 # a space before a ( when it's a function argument. I assume it's a 3233 # function argument when the char before the whitespace is legal in 3234 # a function name (alnum + _) and we're not starting a macro. Also ignore 3235 # pointers and references to arrays and functions coz they're too tricky: 3236 # we use a very simple way to recognize these: 3237 # " (something)(maybe-something)" or 3238 # " (something)(maybe-something," or 3239 # " (something)[something]" 3240 # Note that we assume the contents of [] to be short enough that 3241 # they'll never need to wrap. 3242 if ( # Ignore control structures. 3243 not Search(r'\b(if|for|while|switch|return|new|delete|catch|sizeof)\b', 3244 fncall) and 3245 # Ignore pointers/references to functions. 3246 not Search(r' \([^)]+\)\([^)]*(\)|,$)', fncall) and 3247 # Ignore pointers/references to arrays. 3248 not Search(r' \([^)]+\)\[[^\]]+\]', fncall)): 3249 if Search(r'\w\s*\(\s(?!\s*\\$)', fncall): # a ( used for a fn call 3250 error(filename, linenum, 'whitespace/parens', 4, 3251 'Extra space after ( in function call') 3252 elif Search(r'\(\s+(?!(\s*\\)|\()', fncall): 3253 error(filename, linenum, 'whitespace/parens', 2, 3254 'Extra space after (') 3255 if (Search(r'\w\s+\(', fncall) and 3256 not Search(r'_{0,2}asm_{0,2}\s+_{0,2}volatile_{0,2}\s+\(', fncall) and 3257 not Search(r'#\s*define|typedef|using\s+\w+\s*=', fncall) and 3258 not Search(r'\w\s+\((\w+::)*\*\w+\)\(', fncall) and 3259 not Search(r'\bcase\s+\(', fncall)): 3260 # TODO(unknown): Space after an operator function seem to be a common 3261 # error, silence those for now by restricting them to highest verbosity. 3262 if Search(r'\boperator_*\b', line): 3263 error(filename, linenum, 'whitespace/parens', 0, 3264 'Extra space before ( in function call') 3265 else: 3266 error(filename, linenum, 'whitespace/parens', 4, 3267 'Extra space before ( in function call') 3268 # If the ) is followed only by a newline or a { + newline, assume it's 3269 # part of a control statement (if/while/etc), and don't complain 3270 if Search(r'[^)]\s+\)\s*[^{\s]', fncall): 3271 # If the closing parenthesis is preceded by only whitespaces, 3272 # try to give a more descriptive error message. 3273 if Search(r'^\s+\)', fncall): 3274 error(filename, linenum, 'whitespace/parens', 2, 3275 'Closing ) should be moved to the previous line') 3276 else: 3277 error(filename, linenum, 'whitespace/parens', 2, 3278 'Extra space before )') 3279 3280 3281def IsBlankLine(line): 3282 """Returns true if the given line is blank. 3283 3284 We consider a line to be blank if the line is empty or consists of 3285 only white spaces. 3286 3287 Args: 3288 line: A line of a string. 3289 3290 Returns: 3291 True, if the given line is blank. 3292 """ 3293 return not line or line.isspace() 3294 3295 3296def CheckForNamespaceIndentation(filename, nesting_state, clean_lines, line, 3297 error): 3298 is_namespace_indent_item = ( 3299 len(nesting_state.stack) > 1 and 3300 nesting_state.stack[-1].check_namespace_indentation and 3301 isinstance(nesting_state.previous_stack_top, _NamespaceInfo) and 3302 nesting_state.previous_stack_top == nesting_state.stack[-2]) 3303 3304 if ShouldCheckNamespaceIndentation(nesting_state, is_namespace_indent_item, 3305 clean_lines.elided, line): 3306 CheckItemIndentationInNamespace(filename, clean_lines.elided, 3307 line, error) 3308 3309 3310def CheckForFunctionLengths(filename, clean_lines, linenum, 3311 function_state, error): 3312 """Reports for long function bodies. 3313 3314 For an overview why this is done, see: 3315 https://google.github.io/styleguide/cppguide.html#Write_Short_Functions 3316 3317 Uses a simplistic algorithm assuming other style guidelines 3318 (especially spacing) are followed. 3319 Only checks unindented functions, so class members are unchecked. 3320 Trivial bodies are unchecked, so constructors with huge initializer lists 3321 may be missed. 3322 Blank/comment lines are not counted so as to avoid encouraging the removal 3323 of vertical space and comments just to get through a lint check. 3324 NOLINT *on the last line of a function* disables this check. 3325 3326 Args: 3327 filename: The name of the current file. 3328 clean_lines: A CleansedLines instance containing the file. 3329 linenum: The number of the line to check. 3330 function_state: Current function name and lines in body so far. 3331 error: The function to call with any errors found. 3332 """ 3333 lines = clean_lines.lines 3334 line = lines[linenum] 3335 joined_line = '' 3336 3337 starting_func = False 3338 regexp = r'(\w(\w|::|\*|\&|\s)*)\(' # decls * & space::name( ... 3339 match_result = Match(regexp, line) 3340 if match_result: 3341 # If the name is all caps and underscores, figure it's a macro and 3342 # ignore it, unless it's TEST or TEST_F. 3343 function_name = match_result.group(1).split()[-1] 3344 if function_name == 'TEST' or function_name == 'TEST_F' or ( 3345 not Match(r'[A-Z_]+$', function_name)): 3346 starting_func = True 3347 3348 if starting_func: 3349 body_found = False 3350 for start_linenum in xrange(linenum, clean_lines.NumLines()): 3351 start_line = lines[start_linenum] 3352 joined_line += ' ' + start_line.lstrip() 3353 if Search(r'(;|})', start_line): # Declarations and trivial functions 3354 body_found = True 3355 break # ... ignore 3356 if Search(r'{', start_line): 3357 body_found = True 3358 function = Search(r'((\w|:)*)\(', line).group(1) 3359 if Match(r'TEST', function): # Handle TEST... macros 3360 parameter_regexp = Search(r'(\(.*\))', joined_line) 3361 if parameter_regexp: # Ignore bad syntax 3362 function += parameter_regexp.group(1) 3363 else: 3364 function += '()' 3365 function_state.Begin(function) 3366 break 3367 if not body_found: 3368 # No body for the function (or evidence of a non-function) was found. 3369 error(filename, linenum, 'readability/fn_size', 5, 3370 'Lint failed to find start of function body.') 3371 elif Match(r'^\}\s*$', line): # function end 3372 function_state.Check(error, filename, linenum) 3373 function_state.End() 3374 elif not Match(r'^\s*$', line): 3375 function_state.Count() # Count non-blank/non-comment lines. 3376 3377 3378_RE_PATTERN_TODO = re.compile(r'^//(\s*)TODO(\(.+?\))?:?(\s|$)?') 3379 3380 3381def CheckComment(line, filename, linenum, next_line_start, error): 3382 """Checks for common mistakes in comments. 3383 3384 Args: 3385 line: The line in question. 3386 filename: The name of the current file. 3387 linenum: The number of the line to check. 3388 next_line_start: The first non-whitespace column of the next line. 3389 error: The function to call with any errors found. 3390 """ 3391 commentpos = line.find('//') 3392 if commentpos != -1: 3393 # Check if the // may be in quotes. If so, ignore it 3394 if re.sub(r'\\.', '', line[0:commentpos]).count('"') % 2 == 0: 3395 # Allow one space for new scopes, two spaces otherwise: 3396 if (not (Match(r'^.*{ *//', line) and next_line_start == commentpos) and 3397 ((commentpos >= 1 and 3398 line[commentpos-1] not in string.whitespace) or 3399 (commentpos >= 2 and 3400 line[commentpos-2] not in string.whitespace))): 3401 error(filename, linenum, 'whitespace/comments', 2, 3402 'At least two spaces is best between code and comments') 3403 3404 # Checks for common mistakes in TODO comments. 3405 comment = line[commentpos:] 3406 match = _RE_PATTERN_TODO.match(comment) 3407 if match: 3408 # One whitespace is correct; zero whitespace is handled elsewhere. 3409 leading_whitespace = match.group(1) 3410 if len(leading_whitespace) > 1: 3411 error(filename, linenum, 'whitespace/todo', 2, 3412 'Too many spaces before TODO') 3413 3414 username = match.group(2) 3415 if not username: 3416 error(filename, linenum, 'readability/todo', 2, 3417 'Missing username in TODO; it should look like ' 3418 '"// TODO(my_username): Stuff."') 3419 3420 middle_whitespace = match.group(3) 3421 # Comparisons made explicit for correctness -- pylint: disable=g-explicit-bool-comparison 3422 if middle_whitespace != ' ' and middle_whitespace != '': 3423 error(filename, linenum, 'whitespace/todo', 2, 3424 'TODO(my_username) should be followed by a space') 3425 3426 # If the comment contains an alphanumeric character, there 3427 # should be a space somewhere between it and the // unless 3428 # it's a /// or //! Doxygen comment. 3429 if (Match(r'//[^ ]*\w', comment) and 3430 not Match(r'(///|//\!)(\s+|$)', comment)): 3431 error(filename, linenum, 'whitespace/comments', 4, 3432 'Should have a space between // and comment') 3433 3434 3435def CheckSpacing(filename, clean_lines, linenum, nesting_state, error): 3436 """Checks for the correctness of various spacing issues in the code. 3437 3438 Things we check for: spaces around operators, spaces after 3439 if/for/while/switch, no spaces around parens in function calls, two 3440 spaces between code and comment, don't start a block with a blank 3441 line, don't end a function with a blank line, don't add a blank line 3442 after public/protected/private, don't have too many blank lines in a row. 3443 3444 Args: 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 nesting_state: A NestingState instance which maintains information about 3449 the current stack of nested blocks being parsed. 3450 error: The function to call with any errors found. 3451 """ 3452 3453 # Don't use "elided" lines here, otherwise we can't check commented lines. 3454 # Don't want to use "raw" either, because we don't want to check inside C++11 3455 # raw strings, 3456 raw = clean_lines.lines_without_raw_strings 3457 line = raw[linenum] 3458 3459 # Before nixing comments, check if the line is blank for no good 3460 # reason. This includes the first line after a block is opened, and 3461 # blank lines at the end of a function (ie, right before a line like '}' 3462 # 3463 # Skip all the blank line checks if we are immediately inside a 3464 # namespace body. In other words, don't issue blank line warnings 3465 # for this block: 3466 # namespace { 3467 # 3468 # } 3469 # 3470 # A warning about missing end of namespace comments will be issued instead. 3471 # 3472 # Also skip blank line checks for 'extern "C"' blocks, which are formatted 3473 # like namespaces. 3474 if (IsBlankLine(line) and 3475 not nesting_state.InNamespaceBody() and 3476 not nesting_state.InExternC()): 3477 elided = clean_lines.elided 3478 prev_line = elided[linenum - 1] 3479 prevbrace = prev_line.rfind('{') 3480 # TODO(unknown): Don't complain if line before blank line, and line after, 3481 # both start with alnums and are indented the same amount. 3482 # This ignores whitespace at the start of a namespace block 3483 # because those are not usually indented. 3484 if prevbrace != -1 and prev_line[prevbrace:].find('}') == -1: 3485 # OK, we have a blank line at the start of a code block. Before we 3486 # complain, we check if it is an exception to the rule: The previous 3487 # non-empty line has the parameters of a function header that are indented 3488 # 4 spaces (because they did not fit in a 80 column line when placed on 3489 # the same line as the function name). We also check for the case where 3490 # the previous line is indented 6 spaces, which may happen when the 3491 # initializers of a constructor do not fit into a 80 column line. 3492 exception = False 3493 if Match(r' {6}\w', prev_line): # Initializer list? 3494 # We are looking for the opening column of initializer list, which 3495 # should be indented 4 spaces to cause 6 space indentation afterwards. 3496 search_position = linenum-2 3497 while (search_position >= 0 3498 and Match(r' {6}\w', elided[search_position])): 3499 search_position -= 1 3500 exception = (search_position >= 0 3501 and elided[search_position][:5] == ' :') 3502 else: 3503 # Search for the function arguments or an initializer list. We use a 3504 # simple heuristic here: If the line is indented 4 spaces; and we have a 3505 # closing paren, without the opening paren, followed by an opening brace 3506 # or colon (for initializer lists) we assume that it is the last line of 3507 # a function header. If we have a colon indented 4 spaces, it is an 3508 # initializer list. 3509 exception = (Match(r' {4}\w[^\(]*\)\s*(const\s*)?(\{\s*$|:)', 3510 prev_line) 3511 or Match(r' {4}:', prev_line)) 3512 3513 if not exception: 3514 error(filename, linenum, 'whitespace/blank_line', 2, 3515 'Redundant blank line at the start of a code block ' 3516 'should be deleted.') 3517 # Ignore blank lines at the end of a block in a long if-else 3518 # chain, like this: 3519 # if (condition1) { 3520 # // Something followed by a blank line 3521 # 3522 # } else if (condition2) { 3523 # // Something else 3524 # } 3525 if linenum + 1 < clean_lines.NumLines(): 3526 next_line = raw[linenum + 1] 3527 if (next_line 3528 and Match(r'\s*}', next_line) 3529 and next_line.find('} else ') == -1): 3530 error(filename, linenum, 'whitespace/blank_line', 3, 3531 'Redundant blank line at the end of a code block ' 3532 'should be deleted.') 3533 3534 matched = Match(r'\s*(public|protected|private):', prev_line) 3535 if matched: 3536 error(filename, linenum, 'whitespace/blank_line', 3, 3537 'Do not leave a blank line after "%s:"' % matched.group(1)) 3538 3539 # Next, check comments 3540 next_line_start = 0 3541 if linenum + 1 < clean_lines.NumLines(): 3542 next_line = raw[linenum + 1] 3543 next_line_start = len(next_line) - len(next_line.lstrip()) 3544 CheckComment(line, filename, linenum, next_line_start, error) 3545 3546 # get rid of comments and strings 3547 line = clean_lines.elided[linenum] 3548 3549 # You shouldn't have spaces before your brackets, except maybe after 3550 # 'delete []', 'return []() {};', or 'auto [abc, ...] = ...;'. 3551 if Search(r'\w\s+\[', line) and not Search(r'(?:auto&?|delete|return)\s+\[', line): 3552 error(filename, linenum, 'whitespace/braces', 5, 3553 'Extra space before [') 3554 3555 # In range-based for, we wanted spaces before and after the colon, but 3556 # not around "::" tokens that might appear. 3557 if (Search(r'for *\(.*[^:]:[^: ]', line) or 3558 Search(r'for *\(.*[^: ]:[^:]', line)): 3559 error(filename, linenum, 'whitespace/forcolon', 2, 3560 'Missing space around colon in range-based for loop') 3561 3562 3563def CheckOperatorSpacing(filename, clean_lines, linenum, error): 3564 """Checks for horizontal spacing around operators. 3565 3566 Args: 3567 filename: The name of the current file. 3568 clean_lines: A CleansedLines instance containing the file. 3569 linenum: The number of the line to check. 3570 error: The function to call with any errors found. 3571 """ 3572 line = clean_lines.elided[linenum] 3573 3574 # Don't try to do spacing checks for operator methods. Do this by 3575 # replacing the troublesome characters with something else, 3576 # preserving column position for all other characters. 3577 # 3578 # The replacement is done repeatedly to avoid false positives from 3579 # operators that call operators. 3580 while True: 3581 match = Match(r'^(.*\boperator\b)(\S+)(\s*\(.*)$', line) 3582 if match: 3583 line = match.group(1) + ('_' * len(match.group(2))) + match.group(3) 3584 else: 3585 break 3586 3587 # We allow no-spaces around = within an if: "if ( (a=Foo()) == 0 )". 3588 # Otherwise not. Note we only check for non-spaces on *both* sides; 3589 # sometimes people put non-spaces on one side when aligning ='s among 3590 # many lines (not that this is behavior that I approve of...) 3591 if ((Search(r'[\w.]=', line) or 3592 Search(r'=[\w.]', line)) 3593 and not Search(r'\b(if|while|for) ', line) 3594 # Operators taken from [lex.operators] in C++11 standard. 3595 and not Search(r'(>=|<=|==|!=|&=|\^=|\|=|\+=|\*=|\/=|\%=)', line) 3596 and not Search(r'operator=', line)): 3597 error(filename, linenum, 'whitespace/operators', 4, 3598 'Missing spaces around =') 3599 3600 # It's ok not to have spaces around binary operators like + - * /, but if 3601 # there's too little whitespace, we get concerned. It's hard to tell, 3602 # though, so we punt on this one for now. TODO. 3603 3604 # You should always have whitespace around binary operators. 3605 # 3606 # Check <= and >= first to avoid false positives with < and >, then 3607 # check non-include lines for spacing around < and >. 3608 # 3609 # If the operator is followed by a comma, assume it's be used in a 3610 # macro context and don't do any checks. This avoids false 3611 # positives. 3612 # 3613 # Note that && is not included here. This is because there are too 3614 # many false positives due to RValue references. 3615 match = Search(r'[^<>=!\s](==|!=|<=|>=|\|\|)[^<>=!\s,;\)]', line) 3616 if match: 3617 error(filename, linenum, 'whitespace/operators', 3, 3618 'Missing spaces around %s' % match.group(1)) 3619 elif not Match(r'#.*include', line): 3620 # Look for < that is not surrounded by spaces. This is only 3621 # triggered if both sides are missing spaces, even though 3622 # technically should should flag if at least one side is missing a 3623 # space. This is done to avoid some false positives with shifts. 3624 match = Match(r'^(.*[^\s<])<[^\s=<,]', line) 3625 if match: 3626 (_, _, end_pos) = CloseExpression( 3627 clean_lines, linenum, len(match.group(1))) 3628 if end_pos <= -1: 3629 error(filename, linenum, 'whitespace/operators', 3, 3630 'Missing spaces around <') 3631 3632 # Look for > that is not surrounded by spaces. Similar to the 3633 # above, we only trigger if both sides are missing spaces to avoid 3634 # false positives with shifts. 3635 match = Match(r'^(.*[^-\s>])>[^\s=>,]', line) 3636 if match: 3637 (_, _, start_pos) = ReverseCloseExpression( 3638 clean_lines, linenum, len(match.group(1))) 3639 if start_pos <= -1: 3640 error(filename, linenum, 'whitespace/operators', 3, 3641 'Missing spaces around >') 3642 3643 # We allow no-spaces around << when used like this: 10<<20, but 3644 # not otherwise (particularly, not when used as streams) 3645 # 3646 # We also allow operators following an opening parenthesis, since 3647 # those tend to be macros that deal with operators. 3648 match = Search(r'(operator|[^\s(<])(?:L|UL|LL|ULL|l|ul|ll|ull)?<<([^\s,=<])', line) 3649 if (match and not (match.group(1).isdigit() and match.group(2).isdigit()) and 3650 not (match.group(1) == 'operator' and match.group(2) == ';')): 3651 error(filename, linenum, 'whitespace/operators', 3, 3652 'Missing spaces around <<') 3653 3654 # We allow no-spaces around >> for almost anything. This is because 3655 # C++11 allows ">>" to close nested templates, which accounts for 3656 # most cases when ">>" is not followed by a space. 3657 # 3658 # We still warn on ">>" followed by alpha character, because that is 3659 # likely due to ">>" being used for right shifts, e.g.: 3660 # value >> alpha 3661 # 3662 # When ">>" is used to close templates, the alphanumeric letter that 3663 # follows would be part of an identifier, and there should still be 3664 # a space separating the template type and the identifier. 3665 # type<type<type>> alpha 3666 match = Search(r'>>[a-zA-Z_]', line) 3667 if match: 3668 error(filename, linenum, 'whitespace/operators', 3, 3669 'Missing spaces around >>') 3670 3671 # There shouldn't be space around unary operators 3672 match = Search(r'(!\s|~\s|[\s]--[\s;]|[\s]\+\+[\s;])', line) 3673 if match: 3674 error(filename, linenum, 'whitespace/operators', 4, 3675 'Extra space for operator %s' % match.group(1)) 3676 3677 3678def CheckParenthesisSpacing(filename, clean_lines, linenum, error): 3679 """Checks for horizontal spacing around parentheses. 3680 3681 Args: 3682 filename: The name of the current file. 3683 clean_lines: A CleansedLines instance containing the file. 3684 linenum: The number of the line to check. 3685 error: The function to call with any errors found. 3686 """ 3687 line = clean_lines.elided[linenum] 3688 3689 # No spaces after an if, while, switch, or for 3690 match = Search(r' (if\(|for\(|while\(|switch\()', line) 3691 if match: 3692 error(filename, linenum, 'whitespace/parens', 5, 3693 'Missing space before ( in %s' % match.group(1)) 3694 3695 # For if/for/while/switch, the left and right parens should be 3696 # consistent about how many spaces are inside the parens, and 3697 # there should either be zero or one spaces inside the parens. 3698 # We don't want: "if ( foo)" or "if ( foo )". 3699 # Exception: "for ( ; foo; bar)" and "for (foo; bar; )" are allowed. 3700 match = Search(r'\b(if|for|while|switch)\s*' 3701 r'\(([ ]*)(.).*[^ ]+([ ]*)\)\s*{\s*$', 3702 line) 3703 if match: 3704 if len(match.group(2)) != len(match.group(4)): 3705 if not (match.group(3) == ';' and 3706 len(match.group(2)) == 1 + len(match.group(4)) or 3707 not match.group(2) and Search(r'\bfor\s*\(.*; \)', line)): 3708 error(filename, linenum, 'whitespace/parens', 5, 3709 'Mismatching spaces inside () in %s' % match.group(1)) 3710 if len(match.group(2)) not in [0, 1]: 3711 error(filename, linenum, 'whitespace/parens', 5, 3712 'Should have zero or one spaces inside ( and ) in %s' % 3713 match.group(1)) 3714 3715 3716def CheckCommaSpacing(filename, clean_lines, linenum, error): 3717 """Checks for horizontal spacing near commas and semicolons. 3718 3719 Args: 3720 filename: The name of the current file. 3721 clean_lines: A CleansedLines instance containing the file. 3722 linenum: The number of the line to check. 3723 error: The function to call with any errors found. 3724 """ 3725 raw = clean_lines.lines_without_raw_strings 3726 line = clean_lines.elided[linenum] 3727 3728 # You should always have a space after a comma (either as fn arg or operator) 3729 # 3730 # This does not apply when the non-space character following the 3731 # comma is another comma, since the only time when that happens is 3732 # for empty macro arguments. 3733 # 3734 # We run this check in two passes: first pass on elided lines to 3735 # verify that lines contain missing whitespaces, second pass on raw 3736 # lines to confirm that those missing whitespaces are not due to 3737 # elided comments. 3738 if (Search(r',[^,\s]', ReplaceAll(r'\boperator\s*,\s*\(', 'F(', line)) and 3739 Search(r',[^,\s]', raw[linenum])): 3740 error(filename, linenum, 'whitespace/comma', 3, 3741 'Missing space after ,') 3742 3743 # You should always have a space after a semicolon 3744 # except for few corner cases 3745 # TODO(unknown): clarify if 'if (1) { return 1;}' is requires one more 3746 # space after ; 3747 if Search(r';[^\s};\\)/]', line): 3748 error(filename, linenum, 'whitespace/semicolon', 3, 3749 'Missing space after ;') 3750 3751 3752def _IsType(clean_lines, nesting_state, expr): 3753 """Check if expression looks like a type name, returns true if so. 3754 3755 Args: 3756 clean_lines: A CleansedLines instance containing the file. 3757 nesting_state: A NestingState instance which maintains information about 3758 the current stack of nested blocks being parsed. 3759 expr: The expression to check. 3760 Returns: 3761 True, if token looks like a type. 3762 """ 3763 # Keep only the last token in the expression 3764 last_word = Match(r'^.*(\b\S+)$', expr) 3765 if last_word: 3766 token = last_word.group(1) 3767 else: 3768 token = expr 3769 3770 # Match native types and stdint types 3771 if _TYPES.match(token): 3772 return True 3773 3774 # Try a bit harder to match templated types. Walk up the nesting 3775 # stack until we find something that resembles a typename 3776 # declaration for what we are looking for. 3777 typename_pattern = (r'\b(?:typename|class|struct)\s+' + re.escape(token) + 3778 r'\b') 3779 block_index = len(nesting_state.stack) - 1 3780 while block_index >= 0: 3781 if isinstance(nesting_state.stack[block_index], _NamespaceInfo): 3782 return False 3783 3784 # Found where the opening brace is. We want to scan from this 3785 # line up to the beginning of the function, minus a few lines. 3786 # template <typename Type1, // stop scanning here 3787 # ...> 3788 # class C 3789 # : public ... { // start scanning here 3790 last_line = nesting_state.stack[block_index].starting_linenum 3791 3792 next_block_start = 0 3793 if block_index > 0: 3794 next_block_start = nesting_state.stack[block_index - 1].starting_linenum 3795 first_line = last_line 3796 while first_line >= next_block_start: 3797 if clean_lines.elided[first_line].find('template') >= 0: 3798 break 3799 first_line -= 1 3800 if first_line < next_block_start: 3801 # Didn't find any "template" keyword before reaching the next block, 3802 # there are probably no template things to check for this block 3803 block_index -= 1 3804 continue 3805 3806 # Look for typename in the specified range 3807 for i in xrange(first_line, last_line + 1, 1): 3808 if Search(typename_pattern, clean_lines.elided[i]): 3809 return True 3810 block_index -= 1 3811 3812 return False 3813 3814 3815def CheckBracesSpacing(filename, clean_lines, linenum, nesting_state, error): 3816 """Checks for horizontal spacing near commas. 3817 3818 Args: 3819 filename: The name of the current file. 3820 clean_lines: A CleansedLines instance containing the file. 3821 linenum: The number of the line to check. 3822 nesting_state: A NestingState instance which maintains information about 3823 the current stack of nested blocks being parsed. 3824 error: The function to call with any errors found. 3825 """ 3826 line = clean_lines.elided[linenum] 3827 3828 # Except after an opening paren, or after another opening brace (in case of 3829 # an initializer list, for instance), you should have spaces before your 3830 # braces when they are delimiting blocks, classes, namespaces etc. 3831 # And since you should never have braces at the beginning of a line, 3832 # this is an easy test. Except that braces used for initialization don't 3833 # follow the same rule; we often don't want spaces before those. 3834 match = Match(r'^(.*[^ ({>]){', line) 3835 3836 if match: 3837 # Try a bit harder to check for brace initialization. This 3838 # happens in one of the following forms: 3839 # Constructor() : initializer_list_{} { ... } 3840 # Constructor{}.MemberFunction() 3841 # Type variable{}; 3842 # FunctionCall(type{}, ...); 3843 # LastArgument(..., type{}); 3844 # LOG(INFO) << type{} << " ..."; 3845 # map_of_type[{...}] = ...; 3846 # ternary = expr ? new type{} : nullptr; 3847 # OuterTemplate<InnerTemplateConstructor<Type>{}> 3848 # 3849 # We check for the character following the closing brace, and 3850 # silence the warning if it's one of those listed above, i.e. 3851 # "{.;,)<>]:". 3852 # 3853 # To account for nested initializer list, we allow any number of 3854 # closing braces up to "{;,)<". We can't simply silence the 3855 # warning on first sight of closing brace, because that would 3856 # cause false negatives for things that are not initializer lists. 3857 # Silence this: But not this: 3858 # Outer{ if (...) { 3859 # Inner{...} if (...){ // Missing space before { 3860 # }; } 3861 # 3862 # There is a false negative with this approach if people inserted 3863 # spurious semicolons, e.g. "if (cond){};", but we will catch the 3864 # spurious semicolon with a separate check. 3865 leading_text = match.group(1) 3866 (endline, endlinenum, endpos) = CloseExpression( 3867 clean_lines, linenum, len(match.group(1))) 3868 trailing_text = '' 3869 if endpos > -1: 3870 trailing_text = endline[endpos:] 3871 for offset in xrange(endlinenum + 1, 3872 min(endlinenum + 3, clean_lines.NumLines() - 1)): 3873 trailing_text += clean_lines.elided[offset] 3874 # We also suppress warnings for `uint64_t{expression}` etc., as the style 3875 # guide recommends brace initialization for integral types to avoid 3876 # overflow/truncation. 3877 if (not Match(r'^[\s}]*[{.;,)<>\]:]', trailing_text) 3878 and not _IsType(clean_lines, nesting_state, leading_text)): 3879 error(filename, linenum, 'whitespace/braces', 5, 3880 'Missing space before {') 3881 3882 # Make sure '} else {' has spaces. 3883 if Search(r'}else', line): 3884 error(filename, linenum, 'whitespace/braces', 5, 3885 'Missing space before else') 3886 3887 # You shouldn't have a space before a semicolon at the end of the line. 3888 # There's a special case for "for" since the style guide allows space before 3889 # the semicolon there. 3890 if Search(r':\s*;\s*$', line): 3891 error(filename, linenum, 'whitespace/semicolon', 5, 3892 'Semicolon defining empty statement. Use {} instead.') 3893 elif Search(r'^\s*;\s*$', line): 3894 error(filename, linenum, 'whitespace/semicolon', 5, 3895 'Line contains only semicolon. If this should be an empty statement, ' 3896 'use {} instead.') 3897 elif (Search(r'\s+;\s*$', line) and 3898 not Search(r'\bfor\b', line)): 3899 error(filename, linenum, 'whitespace/semicolon', 5, 3900 'Extra space before last semicolon. If this should be an empty ' 3901 'statement, use {} instead.') 3902 3903 3904def IsDecltype(clean_lines, linenum, column): 3905 """Check if the token ending on (linenum, column) is decltype(). 3906 3907 Args: 3908 clean_lines: A CleansedLines instance containing the file. 3909 linenum: the number of the line to check. 3910 column: end column of the token to check. 3911 Returns: 3912 True if this token is decltype() expression, False otherwise. 3913 """ 3914 (text, _, start_col) = ReverseCloseExpression(clean_lines, linenum, column) 3915 if start_col < 0: 3916 return False 3917 if Search(r'\bdecltype\s*$', text[0:start_col]): 3918 return True 3919 return False 3920 3921def CheckSectionSpacing(filename, clean_lines, class_info, linenum, error): 3922 """Checks for additional blank line issues related to sections. 3923 3924 Currently the only thing checked here is blank line before protected/private. 3925 3926 Args: 3927 filename: The name of the current file. 3928 clean_lines: A CleansedLines instance containing the file. 3929 class_info: A _ClassInfo objects. 3930 linenum: The number of the line to check. 3931 error: The function to call with any errors found. 3932 """ 3933 # Skip checks if the class is small, where small means 25 lines or less. 3934 # 25 lines seems like a good cutoff since that's the usual height of 3935 # terminals, and any class that can't fit in one screen can't really 3936 # be considered "small". 3937 # 3938 # Also skip checks if we are on the first line. This accounts for 3939 # classes that look like 3940 # class Foo { public: ... }; 3941 # 3942 # If we didn't find the end of the class, last_line would be zero, 3943 # and the check will be skipped by the first condition. 3944 if (class_info.last_line - class_info.starting_linenum <= 24 or 3945 linenum <= class_info.starting_linenum): 3946 return 3947 3948 matched = Match(r'\s*(public|protected|private):', clean_lines.lines[linenum]) 3949 if matched: 3950 # Issue warning if the line before public/protected/private was 3951 # not a blank line, but don't do this if the previous line contains 3952 # "class" or "struct". This can happen two ways: 3953 # - We are at the beginning of the class. 3954 # - We are forward-declaring an inner class that is semantically 3955 # private, but needed to be public for implementation reasons. 3956 # Also ignores cases where the previous line ends with a backslash as can be 3957 # common when defining classes in C macros. 3958 prev_line = clean_lines.lines[linenum - 1] 3959 if (not IsBlankLine(prev_line) and 3960 not Search(r'\b(class|struct)\b', prev_line) and 3961 not Search(r'\\$', prev_line)): 3962 # Try a bit harder to find the beginning of the class. This is to 3963 # account for multi-line base-specifier lists, e.g.: 3964 # class Derived 3965 # : public Base { 3966 end_class_head = class_info.starting_linenum 3967 for i in range(class_info.starting_linenum, linenum): 3968 if Search(r'\{\s*$', clean_lines.lines[i]): 3969 end_class_head = i 3970 break 3971 if end_class_head < linenum - 1: 3972 error(filename, linenum, 'whitespace/blank_line', 3, 3973 '"%s:" should be preceded by a blank line' % matched.group(1)) 3974 3975 3976def GetPreviousNonBlankLine(clean_lines, linenum): 3977 """Return the most recent non-blank line and its line number. 3978 3979 Args: 3980 clean_lines: A CleansedLines instance containing the file contents. 3981 linenum: The number of the line to check. 3982 3983 Returns: 3984 A tuple with two elements. The first element is the contents of the last 3985 non-blank line before the current line, or the empty string if this is the 3986 first non-blank line. The second is the line number of that line, or -1 3987 if this is the first non-blank line. 3988 """ 3989 3990 prevlinenum = linenum - 1 3991 while prevlinenum >= 0: 3992 prevline = clean_lines.elided[prevlinenum] 3993 if not IsBlankLine(prevline): # if not a blank line... 3994 return (prevline, prevlinenum) 3995 prevlinenum -= 1 3996 return ('', -1) 3997 3998 3999def CheckBraces(filename, clean_lines, linenum, error): 4000 """Looks for misplaced braces (e.g. at the end of line). 4001 4002 Args: 4003 filename: The name of the current file. 4004 clean_lines: A CleansedLines instance containing the file. 4005 linenum: The number of the line to check. 4006 error: The function to call with any errors found. 4007 """ 4008 4009 line = clean_lines.elided[linenum] # get rid of comments and strings 4010 4011 if Match(r'\s*{\s*$', line): 4012 # We allow an open brace to start a line in the case where someone is using 4013 # braces in a block to explicitly create a new scope, which is commonly used 4014 # to control the lifetime of stack-allocated variables. Braces are also 4015 # used for brace initializers inside function calls. We don't detect this 4016 # perfectly: we just don't complain if the last non-whitespace character on 4017 # the previous non-blank line is ',', ';', ':', '(', '{', or '}', or if the 4018 # previous line starts a preprocessor block. We also allow a brace on the 4019 # following line if it is part of an array initialization and would not fit 4020 # within the 80 character limit of the preceding line. 4021 prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0] 4022 if (not Search(r'[,;:}{(]\s*$', prevline) and 4023 not Match(r'\s*#', prevline) and 4024 not (GetLineWidth(prevline) > _line_length - 2 and '[]' in prevline)): 4025 error(filename, linenum, 'whitespace/braces', 4, 4026 '{ should almost always be at the end of the previous line') 4027 4028 # An else clause should be on the same line as the preceding closing brace. 4029 if Match(r'\s*else\b\s*(?:if\b|\{|$)', line): 4030 prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0] 4031 if Match(r'\s*}\s*$', prevline): 4032 error(filename, linenum, 'whitespace/newline', 4, 4033 'An else should appear on the same line as the preceding }') 4034 4035 # If braces come on one side of an else, they should be on both. 4036 # However, we have to worry about "else if" that spans multiple lines! 4037 if Search(r'else if\s*\(', line): # could be multi-line if 4038 brace_on_left = bool(Search(r'}\s*else if\s*\(', line)) 4039 # find the ( after the if 4040 pos = line.find('else if') 4041 pos = line.find('(', pos) 4042 if pos > 0: 4043 (endline, _, endpos) = CloseExpression(clean_lines, linenum, pos) 4044 brace_on_right = endline[endpos:].find('{') != -1 4045 if brace_on_left != brace_on_right: # must be brace after if 4046 error(filename, linenum, 'readability/braces', 5, 4047 'If an else has a brace on one side, it should have it on both') 4048 elif Search(r'}\s*else[^{]*$', line) or Match(r'[^}]*else\s*{', line): 4049 error(filename, linenum, 'readability/braces', 5, 4050 'If an else has a brace on one side, it should have it on both') 4051 4052 # Likewise, an else should never have the else clause on the same line 4053 if Search(r'\belse [^\s{]', line) and not Search(r'\belse if\b', line): 4054 error(filename, linenum, 'whitespace/newline', 4, 4055 'Else clause should never be on same line as else (use 2 lines)') 4056 4057 # In the same way, a do/while should never be on one line 4058 if Match(r'\s*do [^\s{]', line): 4059 error(filename, linenum, 'whitespace/newline', 4, 4060 'do/while clauses should not be on a single line') 4061 4062 # Check single-line if/else bodies. The style guide says 'curly braces are not 4063 # required for single-line statements'. We additionally allow multi-line, 4064 # single statements, but we reject anything with more than one semicolon in 4065 # it. This means that the first semicolon after the if should be at the end of 4066 # its line, and the line after that should have an indent level equal to or 4067 # lower than the if. We also check for ambiguous if/else nesting without 4068 # braces. 4069 if_else_match = Search(r'\b(if\s*(|constexpr)\s*\(|else\b)', line) 4070 if if_else_match and not Match(r'\s*#', line): 4071 if_indent = GetIndentLevel(line) 4072 endline, endlinenum, endpos = line, linenum, if_else_match.end() 4073 if_match = Search(r'\bif\s*(|constexpr)\s*\(', line) 4074 if if_match: 4075 # This could be a multiline if condition, so find the end first. 4076 pos = if_match.end() - 1 4077 (endline, endlinenum, endpos) = CloseExpression(clean_lines, linenum, pos) 4078 # Check for an opening brace, either directly after the if or on the next 4079 # line. If found, this isn't a single-statement conditional. 4080 if (not Match(r'\s*{', endline[endpos:]) 4081 and not (Match(r'\s*$', endline[endpos:]) 4082 and endlinenum < (len(clean_lines.elided) - 1) 4083 and Match(r'\s*{', clean_lines.elided[endlinenum + 1]))): 4084 while (endlinenum < len(clean_lines.elided) 4085 and ';' not in clean_lines.elided[endlinenum][endpos:]): 4086 endlinenum += 1 4087 endpos = 0 4088 if endlinenum < len(clean_lines.elided): 4089 endline = clean_lines.elided[endlinenum] 4090 # We allow a mix of whitespace and closing braces (e.g. for one-liner 4091 # methods) and a single \ after the semicolon (for macros) 4092 endpos = endline.find(';') 4093 if not Match(r';[\s}]*(\\?)$', endline[endpos:]): 4094 # Semicolon isn't the last character, there's something trailing. 4095 # Output a warning if the semicolon is not contained inside 4096 # a lambda expression. 4097 if not Match(r'^[^{};]*\[[^\[\]]*\][^{}]*\{[^{}]*\}\s*\)*[;,]\s*$', 4098 endline): 4099 error(filename, linenum, 'readability/braces', 4, 4100 'If/else bodies with multiple statements require braces') 4101 elif endlinenum < len(clean_lines.elided) - 1: 4102 # Make sure the next line is dedented 4103 next_line = clean_lines.elided[endlinenum + 1] 4104 next_indent = GetIndentLevel(next_line) 4105 # With ambiguous nested if statements, this will error out on the 4106 # if that *doesn't* match the else, regardless of whether it's the 4107 # inner one or outer one. 4108 if (if_match and Match(r'\s*else\b', next_line) 4109 and next_indent != if_indent): 4110 error(filename, linenum, 'readability/braces', 4, 4111 'Else clause should be indented at the same level as if. ' 4112 'Ambiguous nested if/else chains require braces.') 4113 elif next_indent > if_indent: 4114 error(filename, linenum, 'readability/braces', 4, 4115 'If/else bodies with multiple statements require braces') 4116 4117 4118def CheckTrailingSemicolon(filename, clean_lines, linenum, error): 4119 """Looks for redundant trailing semicolon. 4120 4121 Args: 4122 filename: The name of the current file. 4123 clean_lines: A CleansedLines instance containing the file. 4124 linenum: The number of the line to check. 4125 error: The function to call with any errors found. 4126 """ 4127 4128 line = clean_lines.elided[linenum] 4129 4130 # Block bodies should not be followed by a semicolon. Due to C++11 4131 # brace initialization, there are more places where semicolons are 4132 # required than not, so we use a whitelist approach to check these 4133 # rather than a blacklist. These are the places where "};" should 4134 # be replaced by just "}": 4135 # 1. Some flavor of block following closing parenthesis: 4136 # for (;;) {}; 4137 # while (...) {}; 4138 # switch (...) {}; 4139 # Function(...) {}; 4140 # if (...) {}; 4141 # if (...) else if (...) {}; 4142 # 4143 # 2. else block: 4144 # if (...) else {}; 4145 # 4146 # 3. const member function: 4147 # Function(...) const {}; 4148 # 4149 # 4. Block following some statement: 4150 # x = 42; 4151 # {}; 4152 # 4153 # 5. Block at the beginning of a function: 4154 # Function(...) { 4155 # {}; 4156 # } 4157 # 4158 # Note that naively checking for the preceding "{" will also match 4159 # braces inside multi-dimensional arrays, but this is fine since 4160 # that expression will not contain semicolons. 4161 # 4162 # 6. Block following another block: 4163 # while (true) {} 4164 # {}; 4165 # 4166 # 7. End of namespaces: 4167 # namespace {}; 4168 # 4169 # These semicolons seems far more common than other kinds of 4170 # redundant semicolons, possibly due to people converting classes 4171 # to namespaces. For now we do not warn for this case. 4172 # 4173 # Try matching case 1 first. 4174 match = Match(r'^(.*\)\s*)\{', line) 4175 if match: 4176 # Matched closing parenthesis (case 1). Check the token before the 4177 # matching opening parenthesis, and don't warn if it looks like a 4178 # macro. This avoids these false positives: 4179 # - macro that defines a base class 4180 # - multi-line macro that defines a base class 4181 # - macro that defines the whole class-head 4182 # 4183 # But we still issue warnings for macros that we know are safe to 4184 # warn, specifically: 4185 # - TEST, TEST_F, TEST_P, MATCHER, MATCHER_P 4186 # - TYPED_TEST 4187 # - INTERFACE_DEF 4188 # - EXCLUSIVE_LOCKS_REQUIRED, SHARED_LOCKS_REQUIRED, LOCKS_EXCLUDED: 4189 # 4190 # We implement a whitelist of safe macros instead of a blacklist of 4191 # unsafe macros, even though the latter appears less frequently in 4192 # google code and would have been easier to implement. This is because 4193 # the downside for getting the whitelist wrong means some extra 4194 # semicolons, while the downside for getting the blacklist wrong 4195 # would result in compile errors. 4196 # 4197 # In addition to macros, we also don't want to warn on 4198 # - Compound literals 4199 # - Lambdas 4200 # - alignas specifier with anonymous structs 4201 # - decltype 4202 closing_brace_pos = match.group(1).rfind(')') 4203 opening_parenthesis = ReverseCloseExpression( 4204 clean_lines, linenum, closing_brace_pos) 4205 if opening_parenthesis[2] > -1: 4206 line_prefix = opening_parenthesis[0][0:opening_parenthesis[2]] 4207 macro = Search(r'\b([A-Z_][A-Z0-9_]*)\s*$', line_prefix) 4208 func = Match(r'^(.*\])\s*$', line_prefix) 4209 if ((macro and 4210 macro.group(1) not in ( 4211 'TEST', 'TEST_F', 'MATCHER', 'MATCHER_P', 'TYPED_TEST', 4212 'EXCLUSIVE_LOCKS_REQUIRED', 'SHARED_LOCKS_REQUIRED', 4213 'LOCKS_EXCLUDED', 'INTERFACE_DEF')) or 4214 (func and not Search(r'\boperator\s*\[\s*\]', func.group(1))) or 4215 Search(r'\b(?:struct|union)\s+alignas\s*$', line_prefix) or 4216 Search(r'\bdecltype$', line_prefix) or 4217 Search(r'\s+=\s*$', line_prefix)): 4218 match = None 4219 if (match and 4220 opening_parenthesis[1] > 1 and 4221 Search(r'\]\s*$', clean_lines.elided[opening_parenthesis[1] - 1])): 4222 # Multi-line lambda-expression 4223 match = None 4224 4225 else: 4226 # Try matching cases 2-3. 4227 match = Match(r'^(.*(?:else|\)\s*const)\s*)\{', line) 4228 if not match: 4229 # Try matching cases 4-6. These are always matched on separate lines. 4230 # 4231 # Note that we can't simply concatenate the previous line to the 4232 # current line and do a single match, otherwise we may output 4233 # duplicate warnings for the blank line case: 4234 # if (cond) { 4235 # // blank line 4236 # } 4237 prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0] 4238 if prevline and Search(r'[;{}]\s*$', prevline): 4239 match = Match(r'^(\s*)\{', line) 4240 4241 # Check matching closing brace 4242 if match: 4243 (endline, endlinenum, endpos) = CloseExpression( 4244 clean_lines, linenum, len(match.group(1))) 4245 if endpos > -1 and Match(r'^\s*;', endline[endpos:]): 4246 # Current {} pair is eligible for semicolon check, and we have found 4247 # the redundant semicolon, output warning here. 4248 # 4249 # Note: because we are scanning forward for opening braces, and 4250 # outputting warnings for the matching closing brace, if there are 4251 # nested blocks with trailing semicolons, we will get the error 4252 # messages in reversed order. 4253 4254 # We need to check the line forward for NOLINT 4255 raw_lines = clean_lines.raw_lines 4256 ParseNolintSuppressions(filename, raw_lines[endlinenum-1], endlinenum-1, 4257 error) 4258 ParseNolintSuppressions(filename, raw_lines[endlinenum], endlinenum, 4259 error) 4260 4261 error(filename, endlinenum, 'readability/braces', 4, 4262 "You don't need a ; after a }") 4263 4264 4265def CheckEmptyBlockBody(filename, clean_lines, linenum, error): 4266 """Look for empty loop/conditional body with only a single semicolon. 4267 4268 Args: 4269 filename: The name of the current file. 4270 clean_lines: A CleansedLines instance containing the file. 4271 linenum: The number of the line to check. 4272 error: The function to call with any errors found. 4273 """ 4274 4275 # Search for loop keywords at the beginning of the line. Because only 4276 # whitespaces are allowed before the keywords, this will also ignore most 4277 # do-while-loops, since those lines should start with closing brace. 4278 # 4279 # We also check "if" blocks here, since an empty conditional block 4280 # is likely an error. 4281 line = clean_lines.elided[linenum] 4282 matched = Match(r'\s*(for|while|if)\s*\(', line) 4283 if matched: 4284 # Find the end of the conditional expression. 4285 (end_line, end_linenum, end_pos) = CloseExpression( 4286 clean_lines, linenum, line.find('(')) 4287 4288 # Output warning if what follows the condition expression is a semicolon. 4289 # No warning for all other cases, including whitespace or newline, since we 4290 # have a separate check for semicolons preceded by whitespace. 4291 if end_pos >= 0 and Match(r';', end_line[end_pos:]): 4292 if matched.group(1) == 'if': 4293 error(filename, end_linenum, 'whitespace/empty_conditional_body', 5, 4294 'Empty conditional bodies should use {}') 4295 else: 4296 error(filename, end_linenum, 'whitespace/empty_loop_body', 5, 4297 'Empty loop bodies should use {} or continue') 4298 4299 # Check for if statements that have completely empty bodies (no comments) 4300 # and no else clauses. 4301 if end_pos >= 0 and matched.group(1) == 'if': 4302 # Find the position of the opening { for the if statement. 4303 # Return without logging an error if it has no brackets. 4304 opening_linenum = end_linenum 4305 opening_line_fragment = end_line[end_pos:] 4306 # Loop until EOF or find anything that's not whitespace or opening {. 4307 while not Search(r'^\s*\{', opening_line_fragment): 4308 if Search(r'^(?!\s*$)', opening_line_fragment): 4309 # Conditional has no brackets. 4310 return 4311 opening_linenum += 1 4312 if opening_linenum == len(clean_lines.elided): 4313 # Couldn't find conditional's opening { or any code before EOF. 4314 return 4315 opening_line_fragment = clean_lines.elided[opening_linenum] 4316 # Set opening_line (opening_line_fragment may not be entire opening line). 4317 opening_line = clean_lines.elided[opening_linenum] 4318 4319 # Find the position of the closing }. 4320 opening_pos = opening_line_fragment.find('{') 4321 if opening_linenum == end_linenum: 4322 # We need to make opening_pos relative to the start of the entire line. 4323 opening_pos += end_pos 4324 (closing_line, closing_linenum, closing_pos) = CloseExpression( 4325 clean_lines, opening_linenum, opening_pos) 4326 if closing_pos < 0: 4327 return 4328 4329 # Now construct the body of the conditional. This consists of the portion 4330 # of the opening line after the {, all lines until the closing line, 4331 # and the portion of the closing line before the }. 4332 if (clean_lines.raw_lines[opening_linenum] != 4333 CleanseComments(clean_lines.raw_lines[opening_linenum])): 4334 # Opening line ends with a comment, so conditional isn't empty. 4335 return 4336 if closing_linenum > opening_linenum: 4337 # Opening line after the {. Ignore comments here since we checked above. 4338 bodylist = list(opening_line[opening_pos+1:]) 4339 # All lines until closing line, excluding closing line, with comments. 4340 bodylist.extend(clean_lines.raw_lines[opening_linenum+1:closing_linenum]) 4341 # Closing line before the }. Won't (and can't) have comments. 4342 bodylist.append(clean_lines.elided[closing_linenum][:closing_pos-1]) 4343 body = '\n'.join(bodylist) 4344 else: 4345 # If statement has brackets and fits on a single line. 4346 body = opening_line[opening_pos+1:closing_pos-1] 4347 4348 # Check if the body is empty 4349 if not _EMPTY_CONDITIONAL_BODY_PATTERN.search(body): 4350 return 4351 # The body is empty. Now make sure there's not an else clause. 4352 current_linenum = closing_linenum 4353 current_line_fragment = closing_line[closing_pos:] 4354 # Loop until EOF or find anything that's not whitespace or else clause. 4355 while Search(r'^\s*$|^(?=\s*else)', current_line_fragment): 4356 if Search(r'^(?=\s*else)', current_line_fragment): 4357 # Found an else clause, so don't log an error. 4358 return 4359 current_linenum += 1 4360 if current_linenum == len(clean_lines.elided): 4361 break 4362 current_line_fragment = clean_lines.elided[current_linenum] 4363 4364 # The body is empty and there's no else clause until EOF or other code. 4365 error(filename, end_linenum, 'whitespace/empty_if_body', 4, 4366 ('If statement had no body and no else clause')) 4367 4368 4369def FindCheckMacro(line): 4370 """Find a replaceable CHECK-like macro. 4371 4372 Args: 4373 line: line to search on. 4374 Returns: 4375 (macro name, start position), or (None, -1) if no replaceable 4376 macro is found. 4377 """ 4378 for macro in _CHECK_MACROS: 4379 i = line.find(macro) 4380 if i >= 0: 4381 # Find opening parenthesis. Do a regular expression match here 4382 # to make sure that we are matching the expected CHECK macro, as 4383 # opposed to some other macro that happens to contain the CHECK 4384 # substring. 4385 matched = Match(r'^(.*\b' + macro + r'\s*)\(', line) 4386 if not matched: 4387 continue 4388 return (macro, len(matched.group(1))) 4389 return (None, -1) 4390 4391 4392def CheckCheck(filename, clean_lines, linenum, error): 4393 """Checks the use of CHECK and EXPECT macros. 4394 4395 Args: 4396 filename: The name of the current file. 4397 clean_lines: A CleansedLines instance containing the file. 4398 linenum: The number of the line to check. 4399 error: The function to call with any errors found. 4400 """ 4401 4402 # Decide the set of replacement macros that should be suggested 4403 lines = clean_lines.elided 4404 (check_macro, start_pos) = FindCheckMacro(lines[linenum]) 4405 if not check_macro: 4406 return 4407 4408 # Find end of the boolean expression by matching parentheses 4409 (last_line, end_line, end_pos) = CloseExpression( 4410 clean_lines, linenum, start_pos) 4411 if end_pos < 0: 4412 return 4413 4414 # If the check macro is followed by something other than a 4415 # semicolon, assume users will log their own custom error messages 4416 # and don't suggest any replacements. 4417 if not Match(r'\s*;', last_line[end_pos:]): 4418 return 4419 4420 if linenum == end_line: 4421 expression = lines[linenum][start_pos + 1:end_pos - 1] 4422 else: 4423 expression = lines[linenum][start_pos + 1:] 4424 for i in xrange(linenum + 1, end_line): 4425 expression += lines[i] 4426 expression += last_line[0:end_pos - 1] 4427 4428 # Parse expression so that we can take parentheses into account. 4429 # This avoids false positives for inputs like "CHECK((a < 4) == b)", 4430 # which is not replaceable by CHECK_LE. 4431 lhs = '' 4432 rhs = '' 4433 operator = None 4434 while expression: 4435 matched = Match(r'^\s*(<<|<<=|>>|>>=|->\*|->|&&|\|\||' 4436 r'==|!=|>=|>|<=|<|\()(.*)$', expression) 4437 if matched: 4438 token = matched.group(1) 4439 if token == '(': 4440 # Parenthesized operand 4441 expression = matched.group(2) 4442 (end, _) = FindEndOfExpressionInLine(expression, 0, ['(']) 4443 if end < 0: 4444 return # Unmatched parenthesis 4445 lhs += '(' + expression[0:end] 4446 expression = expression[end:] 4447 elif token in ('&&', '||'): 4448 # Logical and/or operators. This means the expression 4449 # contains more than one term, for example: 4450 # CHECK(42 < a && a < b); 4451 # 4452 # These are not replaceable with CHECK_LE, so bail out early. 4453 return 4454 elif token in ('<<', '<<=', '>>', '>>=', '->*', '->'): 4455 # Non-relational operator 4456 lhs += token 4457 expression = matched.group(2) 4458 else: 4459 # Relational operator 4460 operator = token 4461 rhs = matched.group(2) 4462 break 4463 else: 4464 # Unparenthesized operand. Instead of appending to lhs one character 4465 # at a time, we do another regular expression match to consume several 4466 # characters at once if possible. Trivial benchmark shows that this 4467 # is more efficient when the operands are longer than a single 4468 # character, which is generally the case. 4469 matched = Match(r'^([^-=!<>()&|]+)(.*)$', expression) 4470 if not matched: 4471 matched = Match(r'^(\s*\S)(.*)$', expression) 4472 if not matched: 4473 break 4474 lhs += matched.group(1) 4475 expression = matched.group(2) 4476 4477 # Only apply checks if we got all parts of the boolean expression 4478 if not (lhs and operator and rhs): 4479 return 4480 4481 # Check that rhs do not contain logical operators. We already know 4482 # that lhs is fine since the loop above parses out && and ||. 4483 if rhs.find('&&') > -1 or rhs.find('||') > -1: 4484 return 4485 4486 # At least one of the operands must be a constant literal. This is 4487 # to avoid suggesting replacements for unprintable things like 4488 # CHECK(variable != iterator) 4489 # 4490 # The following pattern matches decimal, hex integers, strings, and 4491 # characters (in that order). 4492 lhs = lhs.strip() 4493 rhs = rhs.strip() 4494 match_constant = r'^([-+]?(\d+|0[xX][0-9a-fA-F]+)[lLuU]{0,3}|".*"|\'.*\')$' 4495 if Match(match_constant, lhs) or Match(match_constant, rhs): 4496 # Note: since we know both lhs and rhs, we can provide a more 4497 # descriptive error message like: 4498 # Consider using CHECK_EQ(x, 42) instead of CHECK(x == 42) 4499 # Instead of: 4500 # Consider using CHECK_EQ instead of CHECK(a == b) 4501 # 4502 # We are still keeping the less descriptive message because if lhs 4503 # or rhs gets long, the error message might become unreadable. 4504 error(filename, linenum, 'readability/check', 2, 4505 'Consider using %s instead of %s(a %s b)' % ( 4506 _CHECK_REPLACEMENT[check_macro][operator], 4507 check_macro, operator)) 4508 4509 4510def CheckAltTokens(filename, clean_lines, linenum, error): 4511 """Check alternative keywords being used in boolean expressions. 4512 4513 Args: 4514 filename: The name of the current file. 4515 clean_lines: A CleansedLines instance containing the file. 4516 linenum: The number of the line to check. 4517 error: The function to call with any errors found. 4518 """ 4519 line = clean_lines.elided[linenum] 4520 4521 # Avoid preprocessor lines 4522 if Match(r'^\s*#', line): 4523 return 4524 4525 # Last ditch effort to avoid multi-line comments. This will not help 4526 # if the comment started before the current line or ended after the 4527 # current line, but it catches most of the false positives. At least, 4528 # it provides a way to workaround this warning for people who use 4529 # multi-line comments in preprocessor macros. 4530 # 4531 # TODO(unknown): remove this once cpplint has better support for 4532 # multi-line comments. 4533 if line.find('/*') >= 0 or line.find('*/') >= 0: 4534 return 4535 4536 for match in _ALT_TOKEN_REPLACEMENT_PATTERN.finditer(line): 4537 error(filename, linenum, 'readability/alt_tokens', 2, 4538 'Use operator %s instead of %s' % ( 4539 _ALT_TOKEN_REPLACEMENT[match.group(1)], match.group(1))) 4540 4541def CheckNullTokens(filename, clean_lines, linenum, error): 4542 """Check NULL usage. 4543 4544 Args: 4545 filename: The name of the current file. 4546 clean_lines: A CleansedLines instance containing the file. 4547 linenum: The number of the line to check. 4548 error: The function to call with any errors found. 4549 """ 4550 line = clean_lines.elided[linenum] 4551 4552 # Avoid preprocessor lines 4553 if Match(r'^\s*#', line): 4554 return 4555 4556 if line.find('/*') >= 0 or line.find('*/') >= 0: 4557 return 4558 4559 for match in _NULL_TOKEN_PATTERN.finditer(line): 4560 error(filename, linenum, 'readability/null_usage', 2, 4561 'Use nullptr instead of NULL') 4562 4563def CheckV8PersistentTokens(filename, clean_lines, linenum, error): 4564 """Check v8::Persistent usage. 4565 4566 Args: 4567 filename: The name of the current file. 4568 clean_lines: A CleansedLines instance containing the file. 4569 linenum: The number of the line to check. 4570 error: The function to call with any errors found. 4571 """ 4572 line = clean_lines.elided[linenum] 4573 4574 # Avoid preprocessor lines 4575 if Match(r'^\s*#', line): 4576 return 4577 4578 if line.find('/*') >= 0 or line.find('*/') >= 0: 4579 return 4580 4581 for match in _V8_PERSISTENT_PATTERN.finditer(line): 4582 error(filename, linenum, 'runtime/v8_persistent', 2, 4583 'Use v8::Global instead of v8::Persistent') 4584 4585def CheckLeftLeaningPointer(filename, clean_lines, linenum, error): 4586 """Check for left-leaning pointer placement. 4587 4588 Args: 4589 filename: The name of the current file. 4590 clean_lines: A CleansedLines instance containing the file. 4591 linenum: The number of the line to check. 4592 error: The function to call with any errors found. 4593 """ 4594 line = clean_lines.elided[linenum] 4595 4596 # Avoid preprocessor lines 4597 if Match(r'^\s*#', line): 4598 return 4599 4600 if '/*' in line or '*/' in line: 4601 return 4602 4603 for match in _RIGHT_LEANING_POINTER_PATTERN.finditer(line): 4604 error(filename, linenum, 'readability/pointer_notation', 2, 4605 'Use left leaning pointer instead of right leaning') 4606 4607def GetLineWidth(line): 4608 """Determines the width of the line in column positions. 4609 4610 Args: 4611 line: A string, which may be a Unicode string. 4612 4613 Returns: 4614 The width of the line in column positions, accounting for Unicode 4615 combining characters and wide characters. 4616 """ 4617 if isinstance(line, unicode): 4618 width = 0 4619 for uc in unicodedata.normalize('NFC', line): 4620 if unicodedata.east_asian_width(uc) in ('W', 'F'): 4621 width += 2 4622 elif not unicodedata.combining(uc): 4623 # Issue 337 4624 # https://mail.python.org/pipermail/python-list/2012-August/628809.html 4625 if (sys.version_info.major, sys.version_info.minor) <= (3, 2): 4626 # https://github.com/python/cpython/blob/2.7/Include/unicodeobject.h#L81 4627 is_wide_build = sysconfig.get_config_var("Py_UNICODE_SIZE") >= 4 4628 # https://github.com/python/cpython/blob/2.7/Objects/unicodeobject.c#L564 4629 is_low_surrogate = 0xDC00 <= ord(uc) <= 0xDFFF 4630 if not is_wide_build and is_low_surrogate: 4631 width -= 1 4632 4633 width += 1 4634 return width 4635 else: 4636 return len(line) 4637 4638 4639def CheckStyle(filename, clean_lines, linenum, file_extension, nesting_state, 4640 error): 4641 """Checks rules from the 'C++ style rules' section of cppguide.html. 4642 4643 Most of these rules are hard to test (naming, comment style), but we 4644 do what we can. In particular we check for 2-space indents, line lengths, 4645 tab usage, spaces inside code, etc. 4646 4647 Args: 4648 filename: The name of the current file. 4649 clean_lines: A CleansedLines instance containing the file. 4650 linenum: The number of the line to check. 4651 file_extension: The extension (without the dot) of the filename. 4652 nesting_state: A NestingState instance which maintains information about 4653 the current stack of nested blocks being parsed. 4654 error: The function to call with any errors found. 4655 """ 4656 4657 # Don't use "elided" lines here, otherwise we can't check commented lines. 4658 # Don't want to use "raw" either, because we don't want to check inside C++11 4659 # raw strings, 4660 raw_lines = clean_lines.lines_without_raw_strings 4661 line = raw_lines[linenum] 4662 prev = raw_lines[linenum - 1] if linenum > 0 else '' 4663 4664 if line.find('\t') != -1: 4665 error(filename, linenum, 'whitespace/tab', 1, 4666 'Tab found; better to use spaces') 4667 4668 # One or three blank spaces at the beginning of the line is weird; it's 4669 # hard to reconcile that with 2-space indents. 4670 # NOTE: here are the conditions rob pike used for his tests. Mine aren't 4671 # as sophisticated, but it may be worth becoming so: RLENGTH==initial_spaces 4672 # if(RLENGTH > 20) complain = 0; 4673 # if(match($0, " +(error|private|public|protected):")) complain = 0; 4674 # if(match(prev, "&& *$")) complain = 0; 4675 # if(match(prev, "\\|\\| *$")) complain = 0; 4676 # if(match(prev, "[\",=><] *$")) complain = 0; 4677 # if(match($0, " <<")) complain = 0; 4678 # if(match(prev, " +for \\(")) complain = 0; 4679 # if(prevodd && match(prevprev, " +for \\(")) complain = 0; 4680 scope_or_label_pattern = r'\s*\w+\s*:\s*\\?$' 4681 classinfo = nesting_state.InnermostClass() 4682 initial_spaces = 0 4683 cleansed_line = clean_lines.elided[linenum] 4684 while initial_spaces < len(line) and line[initial_spaces] == ' ': 4685 initial_spaces += 1 4686 # There are certain situations we allow one space, notably for 4687 # section labels, and also lines containing multi-line raw strings. 4688 # We also don't check for lines that look like continuation lines 4689 # (of lines ending in double quotes, commas, equals, or angle brackets) 4690 # because the rules for how to indent those are non-trivial. 4691 if (not Search(r'[",=><] *$', prev) and 4692 (initial_spaces == 1 or initial_spaces == 3) and 4693 not Match(scope_or_label_pattern, cleansed_line) and 4694 not (clean_lines.raw_lines[linenum] != line and 4695 Match(r'^\s*""', line))): 4696 error(filename, linenum, 'whitespace/indent', 3, 4697 'Weird number of spaces at line-start. ' 4698 'Are you using a 2-space indent?') 4699 4700 if line and line[-1].isspace(): 4701 error(filename, linenum, 'whitespace/end_of_line', 4, 4702 'Line ends in whitespace. Consider deleting these extra spaces.') 4703 4704 # Check if the line is a header guard. 4705 is_header_guard = False 4706 if IsHeaderExtension(file_extension): 4707 cppvar = GetHeaderGuardCPPVariable(filename) 4708 if (line.startswith('#ifndef %s' % cppvar) or 4709 line.startswith('#define %s' % cppvar) or 4710 line.startswith('#endif // %s' % cppvar)): 4711 is_header_guard = True 4712 # #include lines and header guards can be long, since there's no clean way to 4713 # split them. 4714 # 4715 # URLs can be long too. It's possible to split these, but it makes them 4716 # harder to cut&paste. 4717 # 4718 # The "$Id:...$" comment may also get very long without it being the 4719 # developers fault. 4720 # 4721 # Doxygen documentation copying can get pretty long when using an overloaded 4722 # function declaration 4723 if (not line.startswith('#include') and not is_header_guard and 4724 not Match(r'^\s*//.*http(s?)://\S*$', line) and 4725 not Match(r'^\s*//\s*[^\s]*$', line) and 4726 not Match(r'^// \$Id:.*#[0-9]+ \$$', line) and 4727 not Match(r'^\s*/// [@\\](copydoc|copydetails|copybrief) .*$', line)): 4728 line_width = GetLineWidth(line) 4729 if line_width > _line_length: 4730 error(filename, linenum, 'whitespace/line_length', 2, 4731 'Lines should be <= %i characters long' % _line_length) 4732 4733 if (cleansed_line.count(';') > 1 and 4734 # allow simple single line lambdas 4735 not Match(r'^[^{};]*\[[^\[\]]*\][^{}]*\{[^{}\n\r]*\}', 4736 line) and 4737 # for loops are allowed two ;'s (and may run over two lines). 4738 cleansed_line.find('for') == -1 and 4739 (GetPreviousNonBlankLine(clean_lines, linenum)[0].find('for') == -1 or 4740 GetPreviousNonBlankLine(clean_lines, linenum)[0].find(';') != -1) and 4741 # It's ok to have many commands in a switch case that fits in 1 line 4742 not ((cleansed_line.find('case ') != -1 or 4743 cleansed_line.find('default:') != -1) and 4744 cleansed_line.find('break;') != -1)): 4745 error(filename, linenum, 'whitespace/newline', 0, 4746 'More than one command on the same line') 4747 4748 # Some more style checks 4749 CheckBraces(filename, clean_lines, linenum, error) 4750 CheckTrailingSemicolon(filename, clean_lines, linenum, error) 4751 CheckEmptyBlockBody(filename, clean_lines, linenum, error) 4752 CheckSpacing(filename, clean_lines, linenum, nesting_state, error) 4753 CheckOperatorSpacing(filename, clean_lines, linenum, error) 4754 CheckParenthesisSpacing(filename, clean_lines, linenum, error) 4755 CheckCommaSpacing(filename, clean_lines, linenum, error) 4756 CheckBracesSpacing(filename, clean_lines, linenum, nesting_state, error) 4757 CheckSpacingForFunctionCall(filename, clean_lines, linenum, error) 4758 CheckCheck(filename, clean_lines, linenum, error) 4759 CheckAltTokens(filename, clean_lines, linenum, error) 4760 CheckNullTokens(filename, clean_lines, linenum, error) 4761 CheckV8PersistentTokens(filename, clean_lines, linenum, error) 4762 CheckLeftLeaningPointer(filename, clean_lines, linenum, error) 4763 classinfo = nesting_state.InnermostClass() 4764 if classinfo: 4765 CheckSectionSpacing(filename, clean_lines, classinfo, linenum, error) 4766 4767 4768_RE_PATTERN_INCLUDE = re.compile(r'^\s*#\s*include\s*([<"])([^>"]*)[>"].*$') 4769# Matches the first component of a filename delimited by -s and _s. That is: 4770# _RE_FIRST_COMPONENT.match('foo').group(0) == 'foo' 4771# _RE_FIRST_COMPONENT.match('foo.cc').group(0) == 'foo' 4772# _RE_FIRST_COMPONENT.match('foo-bar_baz.cc').group(0) == 'foo' 4773# _RE_FIRST_COMPONENT.match('foo_bar-baz.cc').group(0) == 'foo' 4774_RE_FIRST_COMPONENT = re.compile(r'^[^-_.]+') 4775 4776 4777def _DropCommonSuffixes(filename): 4778 """Drops common suffixes like _test.cc or -inl.h from filename. 4779 4780 For example: 4781 >>> _DropCommonSuffixes('foo/foo-inl.h') 4782 'foo/foo' 4783 >>> _DropCommonSuffixes('foo/bar/foo.cc') 4784 'foo/bar/foo' 4785 >>> _DropCommonSuffixes('foo/foo_internal.h') 4786 'foo/foo' 4787 >>> _DropCommonSuffixes('foo/foo_unusualinternal.h') 4788 'foo/foo_unusualinternal' 4789 4790 Args: 4791 filename: The input filename. 4792 4793 Returns: 4794 The filename with the common suffix removed. 4795 """ 4796 for suffix in itertools.chain( 4797 ('%s.%s' % (test_suffix.lstrip('_'), ext) 4798 for test_suffix, ext in itertools.product(_test_suffixes, GetNonHeaderExtensions())), 4799 ('%s.%s' % (suffix, ext) 4800 for suffix, ext in itertools.product(['inl', 'imp', 'internal'], GetHeaderExtensions()))): 4801 if (filename.endswith(suffix) and len(filename) > len(suffix) and 4802 filename[-len(suffix) - 1] in ('-', '_')): 4803 return filename[:-len(suffix) - 1] 4804 return os.path.splitext(filename)[0] 4805 4806 4807def _ClassifyInclude(fileinfo, include, is_system): 4808 """Figures out what kind of header 'include' is. 4809 4810 Args: 4811 fileinfo: The current file cpplint is running over. A FileInfo instance. 4812 include: The path to a #included file. 4813 is_system: True if the #include used <> rather than "". 4814 4815 Returns: 4816 One of the _XXX_HEADER constants. 4817 4818 For example: 4819 >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'stdio.h', True) 4820 _C_SYS_HEADER 4821 >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'string', True) 4822 _CPP_SYS_HEADER 4823 >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'foo/foo.h', False) 4824 _LIKELY_MY_HEADER 4825 >>> _ClassifyInclude(FileInfo('foo/foo_unknown_extension.cc'), 4826 ... 'bar/foo_other_ext.h', False) 4827 _POSSIBLE_MY_HEADER 4828 >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'foo/bar.h', False) 4829 _OTHER_HEADER 4830 """ 4831 # This is a list of all standard c++ header files, except 4832 # those already checked for above. 4833 is_cpp_h = include in _CPP_HEADERS 4834 4835 # Headers with C++ extensions shouldn't be considered C system headers 4836 if is_system and os.path.splitext(include)[1] in ['.hpp', '.hxx', '.h++']: 4837 is_system = False 4838 4839 if is_system: 4840 if is_cpp_h: 4841 return _CPP_SYS_HEADER 4842 else: 4843 return _C_SYS_HEADER 4844 4845 # If the target file and the include we're checking share a 4846 # basename when we drop common extensions, and the include 4847 # lives in . , then it's likely to be owned by the target file. 4848 target_dir, target_base = ( 4849 os.path.split(_DropCommonSuffixes(fileinfo.RepositoryName()))) 4850 include_dir, include_base = os.path.split(_DropCommonSuffixes(include)) 4851 target_dir_pub = os.path.normpath(target_dir + '/../public') 4852 target_dir_pub = target_dir_pub.replace('\\', '/') 4853 if target_base == include_base and ( 4854 include_dir == target_dir or 4855 include_dir == target_dir_pub): 4856 return _LIKELY_MY_HEADER 4857 4858 # If the target and include share some initial basename 4859 # component, it's possible the target is implementing the 4860 # include, so it's allowed to be first, but we'll never 4861 # complain if it's not there. 4862 target_first_component = _RE_FIRST_COMPONENT.match(target_base) 4863 include_first_component = _RE_FIRST_COMPONENT.match(include_base) 4864 if (target_first_component and include_first_component and 4865 target_first_component.group(0) == 4866 include_first_component.group(0)): 4867 return _POSSIBLE_MY_HEADER 4868 4869 return _OTHER_HEADER 4870 4871 4872 4873def CheckIncludeLine(filename, clean_lines, linenum, include_state, error): 4874 """Check rules that are applicable to #include lines. 4875 4876 Strings on #include lines are NOT removed from elided line, to make 4877 certain tasks easier. However, to prevent false positives, checks 4878 applicable to #include lines in CheckLanguage must be put here. 4879 4880 Args: 4881 filename: The name of the current file. 4882 clean_lines: A CleansedLines instance containing the file. 4883 linenum: The number of the line to check. 4884 include_state: An _IncludeState instance in which the headers are inserted. 4885 error: The function to call with any errors found. 4886 """ 4887 fileinfo = FileInfo(filename) 4888 line = clean_lines.lines[linenum] 4889 4890 # "include" should use the new style "foo/bar.h" instead of just "bar.h" 4891 # Only do this check if the included header follows google naming 4892 # conventions. If not, assume that it's a 3rd party API that 4893 # requires special include conventions. 4894 # 4895 # We also make an exception for Lua headers, which follow google 4896 # naming convention but not the include convention. 4897 match = Match(r'#include\s*"([^/]+\.h)"', line) 4898 if match and not _THIRD_PARTY_HEADERS_PATTERN.match(match.group(1)): 4899 error(filename, linenum, 'build/include_subdir', 4, 4900 'Include the directory when naming .h files') 4901 4902 # we shouldn't include a file more than once. actually, there are a 4903 # handful of instances where doing so is okay, but in general it's 4904 # not. 4905 match = _RE_PATTERN_INCLUDE.search(line) 4906 if match: 4907 include = match.group(2) 4908 is_system = (match.group(1) == '<') 4909 duplicate_line = include_state.FindHeader(include) 4910 if duplicate_line >= 0: 4911 error(filename, linenum, 'build/include', 4, 4912 '"%s" already included at %s:%s' % 4913 (include, filename, duplicate_line)) 4914 return 4915 4916 for extension in GetNonHeaderExtensions(): 4917 if (include.endswith('.' + extension) and 4918 os.path.dirname(fileinfo.RepositoryName()) != os.path.dirname(include)): 4919 error(filename, linenum, 'build/include', 4, 4920 'Do not include .' + extension + ' files from other packages') 4921 return 4922 4923 # We DO want to include a 3rd party looking header if it matches the 4924 # filename. Otherwise we get an erroneous error "...should include its 4925 # header" error later. 4926 third_src_header = False 4927 for ext in GetHeaderExtensions(): 4928 basefilename = filename[0:len(filename) - len(fileinfo.Extension())] 4929 headerfile = basefilename + '.' + ext 4930 headername = FileInfo(headerfile).RepositoryName() 4931 if headername in include or include in headername: 4932 third_src_header = True 4933 break 4934 4935 if third_src_header or not _THIRD_PARTY_HEADERS_PATTERN.match(include): 4936 include_state.include_list[-1].append((include, linenum)) 4937 4938 # We want to ensure that headers appear in the right order: 4939 # 1) for foo.cc, foo.h 4940 # 2) other project headers 4941 # 3) c system files 4942 # 4) cpp system files 4943 # 4944 # We classify each include statement as one of those 5 types 4945 # using a number of techniques. The include_state object keeps 4946 # track of the highest type seen, and complains if we see a 4947 # lower type after that. 4948 error_message = include_state.CheckNextIncludeOrder( 4949 _ClassifyInclude(fileinfo, include, is_system)) 4950 if error_message: 4951 error(filename, linenum, 'build/include_order', 4, 4952 '%s. Should be: %s.h, c system, c++ system, other.' % 4953 (error_message, fileinfo.BaseName())) 4954 canonical_include = include_state.CanonicalizeAlphabeticalOrder(include) 4955 if not include_state.IsInAlphabeticalOrder( 4956 clean_lines, linenum, canonical_include): 4957 error(filename, linenum, 'build/include_alpha', 4, 4958 'Include "%s" not in alphabetical order' % include) 4959 include_state.SetLastHeader(canonical_include) 4960 4961 4962 4963def _GetTextInside(text, start_pattern): 4964 r"""Retrieves all the text between matching open and close parentheses. 4965 4966 Given a string of lines and a regular expression string, retrieve all the text 4967 following the expression and between opening punctuation symbols like 4968 (, [, or {, and the matching close-punctuation symbol. This properly nested 4969 occurrences of the punctuations, so for the text like 4970 printf(a(), b(c())); 4971 a call to _GetTextInside(text, r'printf\(') will return 'a(), b(c())'. 4972 start_pattern must match string having an open punctuation symbol at the end. 4973 4974 Args: 4975 text: The lines to extract text. Its comments and strings must be elided. 4976 It can be single line and can span multiple lines. 4977 start_pattern: The regexp string indicating where to start extracting 4978 the text. 4979 Returns: 4980 The extracted text. 4981 None if either the opening string or ending punctuation could not be found. 4982 """ 4983 # TODO(unknown): Audit cpplint.py to see what places could be profitably 4984 # rewritten to use _GetTextInside (and use inferior regexp matching today). 4985 4986 # Give opening punctuations to get the matching close-punctuations. 4987 matching_punctuation = {'(': ')', '{': '}', '[': ']'} 4988 closing_punctuation = set(itervalues(matching_punctuation)) 4989 4990 # Find the position to start extracting text. 4991 match = re.search(start_pattern, text, re.M) 4992 if not match: # start_pattern not found in text. 4993 return None 4994 start_position = match.end(0) 4995 4996 assert start_position > 0, ( 4997 'start_pattern must ends with an opening punctuation.') 4998 assert text[start_position - 1] in matching_punctuation, ( 4999 'start_pattern must ends with an opening punctuation.') 5000 # Stack of closing punctuations we expect to have in text after position. 5001 punctuation_stack = [matching_punctuation[text[start_position - 1]]] 5002 position = start_position 5003 while punctuation_stack and position < len(text): 5004 if text[position] == punctuation_stack[-1]: 5005 punctuation_stack.pop() 5006 elif text[position] in closing_punctuation: 5007 # A closing punctuation without matching opening punctuations. 5008 return None 5009 elif text[position] in matching_punctuation: 5010 punctuation_stack.append(matching_punctuation[text[position]]) 5011 position += 1 5012 if punctuation_stack: 5013 # Opening punctuations left without matching close-punctuations. 5014 return None 5015 # punctuations match. 5016 return text[start_position:position - 1] 5017 5018 5019# Patterns for matching call-by-reference parameters. 5020# 5021# Supports nested templates up to 2 levels deep using this messy pattern: 5022# < (?: < (?: < [^<>]* 5023# > 5024# | [^<>] )* 5025# > 5026# | [^<>] )* 5027# > 5028_RE_PATTERN_IDENT = r'[_a-zA-Z]\w*' # =~ [[:alpha:]][[:alnum:]]* 5029_RE_PATTERN_TYPE = ( 5030 r'(?:const\s+)?(?:typename\s+|class\s+|struct\s+|union\s+|enum\s+)?' 5031 r'(?:\w|' 5032 r'\s*<(?:<(?:<[^<>]*>|[^<>])*>|[^<>])*>|' 5033 r'::)+') 5034# A call-by-reference parameter ends with '& identifier'. 5035_RE_PATTERN_REF_PARAM = re.compile( 5036 r'(' + _RE_PATTERN_TYPE + r'(?:\s*(?:\bconst\b|[*]))*\s*' 5037 r'&\s*' + _RE_PATTERN_IDENT + r')\s*(?:=[^,()]+)?[,)]') 5038# A call-by-const-reference parameter either ends with 'const& identifier' 5039# or looks like 'const type& identifier' when 'type' is atomic. 5040_RE_PATTERN_CONST_REF_PARAM = ( 5041 r'(?:.*\s*\bconst\s*&\s*' + _RE_PATTERN_IDENT + 5042 r'|const\s+' + _RE_PATTERN_TYPE + r'\s*&\s*' + _RE_PATTERN_IDENT + r')') 5043# Stream types. 5044_RE_PATTERN_REF_STREAM_PARAM = ( 5045 r'(?:.*stream\s*&\s*' + _RE_PATTERN_IDENT + r')') 5046 5047 5048def CheckLanguage(filename, clean_lines, linenum, file_extension, 5049 include_state, nesting_state, error): 5050 """Checks rules from the 'C++ language rules' section of cppguide.html. 5051 5052 Some of these rules are hard to test (function overloading, using 5053 uint32 inappropriately), but we do the best we can. 5054 5055 Args: 5056 filename: The name of the current file. 5057 clean_lines: A CleansedLines instance containing the file. 5058 linenum: The number of the line to check. 5059 file_extension: The extension (without the dot) of the filename. 5060 include_state: An _IncludeState instance in which the headers are inserted. 5061 nesting_state: A NestingState instance which maintains information about 5062 the current stack of nested blocks being parsed. 5063 error: The function to call with any errors found. 5064 """ 5065 # If the line is empty or consists of entirely a comment, no need to 5066 # check it. 5067 line = clean_lines.elided[linenum] 5068 if not line: 5069 return 5070 5071 match = _RE_PATTERN_INCLUDE.search(line) 5072 if match: 5073 CheckIncludeLine(filename, clean_lines, linenum, include_state, error) 5074 return 5075 5076 # Reset include state across preprocessor directives. This is meant 5077 # to silence warnings for conditional includes. 5078 match = Match(r'^\s*#\s*(if|ifdef|ifndef|elif|else|endif)\b', line) 5079 if match: 5080 include_state.ResetSection(match.group(1)) 5081 5082 5083 # Perform other checks now that we are sure that this is not an include line 5084 CheckCasts(filename, clean_lines, linenum, error) 5085 CheckGlobalStatic(filename, clean_lines, linenum, error) 5086 CheckPrintf(filename, clean_lines, linenum, error) 5087 5088 if IsHeaderExtension(file_extension): 5089 # TODO(unknown): check that 1-arg constructors are explicit. 5090 # How to tell it's a constructor? 5091 # (handled in CheckForNonStandardConstructs for now) 5092 # TODO(unknown): check that classes declare or disable copy/assign 5093 # (level 1 error) 5094 pass 5095 5096 # Check if people are using the verboten C basic types. The only exception 5097 # we regularly allow is "unsigned short port" for port. 5098 if Search(r'\bshort port\b', line): 5099 if not Search(r'\bunsigned short port\b', line): 5100 error(filename, linenum, 'runtime/int', 4, 5101 'Use "unsigned short" for ports, not "short"') 5102 else: 5103 match = Search(r'\b(short|long(?! +double)|long long)\b', line) 5104 if match: 5105 error(filename, linenum, 'runtime/int', 4, 5106 'Use int16/int64/etc, rather than the C type %s' % match.group(1)) 5107 5108 # Check if some verboten operator overloading is going on 5109 # TODO(unknown): catch out-of-line unary operator&: 5110 # class X {}; 5111 # int operator&(const X& x) { return 42; } // unary operator& 5112 # The trick is it's hard to tell apart from binary operator&: 5113 # class Y { int operator&(const Y& x) { return 23; } }; // binary operator& 5114 if Search(r'\boperator\s*&\s*\(\s*\)', line): 5115 error(filename, linenum, 'runtime/operator', 4, 5116 'Unary operator& is dangerous. Do not use it.') 5117 5118 # Check for suspicious usage of "if" like 5119 # } if (a == b) { 5120 if Search(r'\}\s*if\s*\(', line): 5121 error(filename, linenum, 'readability/braces', 4, 5122 'Did you mean "else if"? If not, start a new line for "if".') 5123 5124 # Check for potential format string bugs like printf(foo). 5125 # We constrain the pattern not to pick things like DocidForPrintf(foo). 5126 # Not perfect but it can catch printf(foo.c_str()) and printf(foo->c_str()) 5127 # TODO(unknown): Catch the following case. Need to change the calling 5128 # convention of the whole function to process multiple line to handle it. 5129 # printf( 5130 # boy_this_is_a_really_long_variable_that_cannot_fit_on_the_prev_line); 5131 printf_args = _GetTextInside(line, r'(?i)\b(string)?printf\s*\(') 5132 if printf_args: 5133 match = Match(r'([\w.\->()]+)$', printf_args) 5134 if match and match.group(1) != '__VA_ARGS__': 5135 function_name = re.search(r'\b((?:string)?printf)\s*\(', 5136 line, re.I).group(1) 5137 error(filename, linenum, 'runtime/printf', 4, 5138 'Potential format string bug. Do %s("%%s", %s) instead.' 5139 % (function_name, match.group(1))) 5140 5141 # Check for potential memset bugs like memset(buf, sizeof(buf), 0). 5142 match = Search(r'memset\s*\(([^,]*),\s*([^,]*),\s*0\s*\)', line) 5143 if match and not Match(r"^''|-?[0-9]+|0x[0-9A-Fa-f]$", match.group(2)): 5144 error(filename, linenum, 'runtime/memset', 4, 5145 'Did you mean "memset(%s, 0, %s)"?' 5146 % (match.group(1), match.group(2))) 5147 5148 if Search(r'\busing namespace\b', line): 5149 if Search(r'\bliterals\b', line): 5150 error(filename, linenum, 'build/namespaces_literals', 5, 5151 'Do not use namespace using-directives. ' 5152 'Use using-declarations instead.') 5153 else: 5154 error(filename, linenum, 'build/namespaces', 5, 5155 'Do not use namespace using-directives. ' 5156 'Use using-declarations instead.') 5157 5158 # Detect variable-length arrays. 5159 match = Match(r'\s*(.+::)?(\w+) [a-z]\w*\[(.+)];', line) 5160 if (match and match.group(2) != 'return' and match.group(2) != 'delete' and 5161 match.group(3).find(']') == -1): 5162 # Split the size using space and arithmetic operators as delimiters. 5163 # If any of the resulting tokens are not compile time constants then 5164 # report the error. 5165 tokens = re.split(r'\s|\+|\-|\*|\/|<<|>>]', match.group(3)) 5166 is_const = True 5167 skip_next = False 5168 for tok in tokens: 5169 if skip_next: 5170 skip_next = False 5171 continue 5172 5173 if Search(r'sizeof\(.+\)', tok): continue 5174 if Search(r'arraysize\(\w+\)', tok): continue 5175 5176 tok = tok.lstrip('(') 5177 tok = tok.rstrip(')') 5178 if not tok: continue 5179 if Match(r'\d+', tok): continue 5180 if Match(r'0[xX][0-9a-fA-F]+', tok): continue 5181 if Match(r'k[A-Z0-9]\w*', tok): continue 5182 if Match(r'(.+::)?k[A-Z0-9]\w*', tok): continue 5183 if Match(r'(.+::)?[A-Z][A-Z0-9_]*', tok): continue 5184 # A catch all for tricky sizeof cases, including 'sizeof expression', 5185 # 'sizeof(*type)', 'sizeof(const type)', 'sizeof(struct StructName)' 5186 # requires skipping the next token because we split on ' ' and '*'. 5187 if tok.startswith('sizeof'): 5188 skip_next = True 5189 continue 5190 is_const = False 5191 break 5192 if not is_const: 5193 error(filename, linenum, 'runtime/arrays', 1, 5194 'Do not use variable-length arrays. Use an appropriately named ' 5195 "('k' followed by CamelCase) compile-time constant for the size.") 5196 5197 # Check for use of unnamed namespaces in header files. Registration 5198 # macros are typically OK, so we allow use of "namespace {" on lines 5199 # that end with backslashes. 5200 if (IsHeaderExtension(file_extension) 5201 and Search(r'\bnamespace\s*{', line) 5202 and line[-1] != '\\'): 5203 error(filename, linenum, 'build/namespaces', 4, 5204 'Do not use unnamed namespaces in header files. See ' 5205 'https://google.github.io/styleguide/cppguide.html#Namespaces' 5206 ' for more information.') 5207 5208 5209def CheckGlobalStatic(filename, clean_lines, linenum, error): 5210 """Check for unsafe global or static objects. 5211 5212 Args: 5213 filename: The name of the current file. 5214 clean_lines: A CleansedLines instance containing the file. 5215 linenum: The number of the line to check. 5216 error: The function to call with any errors found. 5217 """ 5218 line = clean_lines.elided[linenum] 5219 5220 # Match two lines at a time to support multiline declarations 5221 if linenum + 1 < clean_lines.NumLines() and not Search(r'[;({]', line): 5222 line += clean_lines.elided[linenum + 1].strip() 5223 5224 # Check for people declaring static/global STL strings at the top level. 5225 # This is dangerous because the C++ language does not guarantee that 5226 # globals with constructors are initialized before the first access, and 5227 # also because globals can be destroyed when some threads are still running. 5228 # TODO(unknown): Generalize this to also find static unique_ptr instances. 5229 # TODO(unknown): File bugs for clang-tidy to find these. 5230 match = Match( 5231 r'((?:|static +)(?:|const +))(?::*std::)?string( +const)? +' 5232 r'([a-zA-Z0-9_:]+)\b(.*)', 5233 line) 5234 5235 # Remove false positives: 5236 # - String pointers (as opposed to values). 5237 # string *pointer 5238 # const string *pointer 5239 # string const *pointer 5240 # string *const pointer 5241 # 5242 # - Functions and template specializations. 5243 # string Function<Type>(... 5244 # string Class<Type>::Method(... 5245 # 5246 # - Operators. These are matched separately because operator names 5247 # cross non-word boundaries, and trying to match both operators 5248 # and functions at the same time would decrease accuracy of 5249 # matching identifiers. 5250 # string Class::operator*() 5251 if (match and 5252 not Search(r'\bstring\b(\s+const)?\s*[\*\&]\s*(const\s+)?\w', line) and 5253 not Search(r'\boperator\W', line) and 5254 not Match(r'\s*(<.*>)?(::[a-zA-Z0-9_]+)*\s*\(([^"]|$)', match.group(4))): 5255 if Search(r'\bconst\b', line): 5256 error(filename, linenum, 'runtime/string', 4, 5257 'For a static/global string constant, use a C style string ' 5258 'instead: "%schar%s %s[]".' % 5259 (match.group(1), match.group(2) or '', match.group(3))) 5260 else: 5261 error(filename, linenum, 'runtime/string', 4, 5262 'Static/global string variables are not permitted.') 5263 5264 if (Search(r'\b([A-Za-z0-9_]*_)\(\1\)', line) or 5265 Search(r'\b([A-Za-z0-9_]*_)\(CHECK_NOTNULL\(\1\)\)', line)): 5266 error(filename, linenum, 'runtime/init', 4, 5267 'You seem to be initializing a member variable with itself.') 5268 5269 5270def CheckPrintf(filename, clean_lines, linenum, error): 5271 """Check for printf related issues. 5272 5273 Args: 5274 filename: The name of the current file. 5275 clean_lines: A CleansedLines instance containing the file. 5276 linenum: The number of the line to check. 5277 error: The function to call with any errors found. 5278 """ 5279 line = clean_lines.elided[linenum] 5280 5281 # When snprintf is used, the second argument shouldn't be a literal. 5282 match = Search(r'snprintf\s*\(([^,]*),\s*([0-9]*)\s*,', line) 5283 if match and match.group(2) != '0': 5284 # If 2nd arg is zero, snprintf is used to calculate size. 5285 error(filename, linenum, 'runtime/printf', 3, 5286 'If you can, use sizeof(%s) instead of %s as the 2nd arg ' 5287 'to snprintf.' % (match.group(1), match.group(2))) 5288 5289 # Check if some verboten C functions are being used. 5290 if Search(r'\bsprintf\s*\(', line): 5291 error(filename, linenum, 'runtime/printf', 5, 5292 'Never use sprintf. Use snprintf instead.') 5293 match = Search(r'\b(strcpy|strcat)\s*\(', line) 5294 if match: 5295 error(filename, linenum, 'runtime/printf', 4, 5296 'Almost always, snprintf is better than %s' % match.group(1)) 5297 5298 5299def IsDerivedFunction(clean_lines, linenum): 5300 """Check if current line contains an inherited function. 5301 5302 Args: 5303 clean_lines: A CleansedLines instance containing the file. 5304 linenum: The number of the line to check. 5305 Returns: 5306 True if current line contains a function with "override" 5307 virt-specifier. 5308 """ 5309 # Scan back a few lines for start of current function 5310 for i in xrange(linenum, max(-1, linenum - 10), -1): 5311 match = Match(r'^([^()]*\w+)\(', clean_lines.elided[i]) 5312 if match: 5313 # Look for "override" after the matching closing parenthesis 5314 line, _, closing_paren = CloseExpression( 5315 clean_lines, i, len(match.group(1))) 5316 return (closing_paren >= 0 and 5317 Search(r'\boverride\b', line[closing_paren:])) 5318 return False 5319 5320 5321def IsOutOfLineMethodDefinition(clean_lines, linenum): 5322 """Check if current line contains an out-of-line method definition. 5323 5324 Args: 5325 clean_lines: A CleansedLines instance containing the file. 5326 linenum: The number of the line to check. 5327 Returns: 5328 True if current line contains an out-of-line method definition. 5329 """ 5330 # Scan back a few lines for start of current function 5331 for i in xrange(linenum, max(-1, linenum - 10), -1): 5332 if Match(r'^([^()]*\w+)\(', clean_lines.elided[i]): 5333 return Match(r'^[^()]*\w+::\w+\(', clean_lines.elided[i]) is not None 5334 return False 5335 5336 5337def IsInitializerList(clean_lines, linenum): 5338 """Check if current line is inside constructor initializer list. 5339 5340 Args: 5341 clean_lines: A CleansedLines instance containing the file. 5342 linenum: The number of the line to check. 5343 Returns: 5344 True if current line appears to be inside constructor initializer 5345 list, False otherwise. 5346 """ 5347 for i in xrange(linenum, 1, -1): 5348 line = clean_lines.elided[i] 5349 if i == linenum: 5350 remove_function_body = Match(r'^(.*)\{\s*$', line) 5351 if remove_function_body: 5352 line = remove_function_body.group(1) 5353 5354 if Search(r'\s:\s*\w+[({]', line): 5355 # A lone colon tend to indicate the start of a constructor 5356 # initializer list. It could also be a ternary operator, which 5357 # also tend to appear in constructor initializer lists as 5358 # opposed to parameter lists. 5359 return True 5360 if Search(r'\}\s*,\s*$', line): 5361 # A closing brace followed by a comma is probably the end of a 5362 # brace-initialized member in constructor initializer list. 5363 return True 5364 if Search(r'[{};]\s*$', line): 5365 # Found one of the following: 5366 # - A closing brace or semicolon, probably the end of the previous 5367 # function. 5368 # - An opening brace, probably the start of current class or namespace. 5369 # 5370 # Current line is probably not inside an initializer list since 5371 # we saw one of those things without seeing the starting colon. 5372 return False 5373 5374 # Got to the beginning of the file without seeing the start of 5375 # constructor initializer list. 5376 return False 5377 5378 5379def CheckForNonConstReference(filename, clean_lines, linenum, 5380 nesting_state, error): 5381 """Check for non-const references. 5382 5383 Separate from CheckLanguage since it scans backwards from current 5384 line, instead of scanning forward. 5385 5386 Args: 5387 filename: The name of the current file. 5388 clean_lines: A CleansedLines instance containing the file. 5389 linenum: The number of the line to check. 5390 nesting_state: A NestingState instance which maintains information about 5391 the current stack of nested blocks being parsed. 5392 error: The function to call with any errors found. 5393 """ 5394 # Do nothing if there is no '&' on current line. 5395 line = clean_lines.elided[linenum] 5396 if '&' not in line: 5397 return 5398 5399 # If a function is inherited, current function doesn't have much of 5400 # a choice, so any non-const references should not be blamed on 5401 # derived function. 5402 if IsDerivedFunction(clean_lines, linenum): 5403 return 5404 5405 # Don't warn on out-of-line method definitions, as we would warn on the 5406 # in-line declaration, if it isn't marked with 'override'. 5407 if IsOutOfLineMethodDefinition(clean_lines, linenum): 5408 return 5409 5410 # Long type names may be broken across multiple lines, usually in one 5411 # of these forms: 5412 # LongType 5413 # ::LongTypeContinued &identifier 5414 # LongType:: 5415 # LongTypeContinued &identifier 5416 # LongType< 5417 # ...>::LongTypeContinued &identifier 5418 # 5419 # If we detected a type split across two lines, join the previous 5420 # line to current line so that we can match const references 5421 # accordingly. 5422 # 5423 # Note that this only scans back one line, since scanning back 5424 # arbitrary number of lines would be expensive. If you have a type 5425 # that spans more than 2 lines, please use a typedef. 5426 if linenum > 1: 5427 previous = None 5428 if Match(r'\s*::(?:[\w<>]|::)+\s*&\s*\S', line): 5429 # previous_line\n + ::current_line 5430 previous = Search(r'\b((?:const\s*)?(?:[\w<>]|::)+[\w<>])\s*$', 5431 clean_lines.elided[linenum - 1]) 5432 elif Match(r'\s*[a-zA-Z_]([\w<>]|::)+\s*&\s*\S', line): 5433 # previous_line::\n + current_line 5434 previous = Search(r'\b((?:const\s*)?(?:[\w<>]|::)+::)\s*$', 5435 clean_lines.elided[linenum - 1]) 5436 if previous: 5437 line = previous.group(1) + line.lstrip() 5438 else: 5439 # Check for templated parameter that is split across multiple lines 5440 endpos = line.rfind('>') 5441 if endpos > -1: 5442 (_, startline, startpos) = ReverseCloseExpression( 5443 clean_lines, linenum, endpos) 5444 if startpos > -1 and startline < linenum: 5445 # Found the matching < on an earlier line, collect all 5446 # pieces up to current line. 5447 line = '' 5448 for i in xrange(startline, linenum + 1): 5449 line += clean_lines.elided[i].strip() 5450 5451 # Check for non-const references in function parameters. A single '&' may 5452 # found in the following places: 5453 # inside expression: binary & for bitwise AND 5454 # inside expression: unary & for taking the address of something 5455 # inside declarators: reference parameter 5456 # We will exclude the first two cases by checking that we are not inside a 5457 # function body, including one that was just introduced by a trailing '{'. 5458 # TODO(unknown): Doesn't account for 'catch(Exception& e)' [rare]. 5459 if (nesting_state.previous_stack_top and 5460 not (isinstance(nesting_state.previous_stack_top, _ClassInfo) or 5461 isinstance(nesting_state.previous_stack_top, _NamespaceInfo))): 5462 # Not at toplevel, not within a class, and not within a namespace 5463 return 5464 5465 # Avoid initializer lists. We only need to scan back from the 5466 # current line for something that starts with ':'. 5467 # 5468 # We don't need to check the current line, since the '&' would 5469 # appear inside the second set of parentheses on the current line as 5470 # opposed to the first set. 5471 if linenum > 0: 5472 for i in xrange(linenum - 1, max(0, linenum - 10), -1): 5473 previous_line = clean_lines.elided[i] 5474 if not Search(r'[),]\s*$', previous_line): 5475 break 5476 if Match(r'^\s*:\s+\S', previous_line): 5477 return 5478 5479 # Avoid preprocessors 5480 if Search(r'\\\s*$', line): 5481 return 5482 5483 # Avoid constructor initializer lists 5484 if IsInitializerList(clean_lines, linenum): 5485 return 5486 5487 # We allow non-const references in a few standard places, like functions 5488 # called "swap()" or iostream operators like "<<" or ">>". Do not check 5489 # those function parameters. 5490 # 5491 # We also accept & in static_assert, which looks like a function but 5492 # it's actually a declaration expression. 5493 whitelisted_functions = (r'(?:[sS]wap(?:<\w:+>)?|' 5494 r'operator\s*[<>][<>]|' 5495 r'static_assert|COMPILE_ASSERT' 5496 r')\s*\(') 5497 if Search(whitelisted_functions, line): 5498 return 5499 elif not Search(r'\S+\([^)]*$', line): 5500 # Don't see a whitelisted function on this line. Actually we 5501 # didn't see any function name on this line, so this is likely a 5502 # multi-line parameter list. Try a bit harder to catch this case. 5503 for i in xrange(2): 5504 if (linenum > i and 5505 Search(whitelisted_functions, clean_lines.elided[linenum - i - 1])): 5506 return 5507 5508 decls = ReplaceAll(r'{[^}]*}', ' ', line) # exclude function body 5509 for parameter in re.findall(_RE_PATTERN_REF_PARAM, decls): 5510 if (not Match(_RE_PATTERN_CONST_REF_PARAM, parameter) and 5511 not Match(_RE_PATTERN_REF_STREAM_PARAM, parameter)): 5512 error(filename, linenum, 'runtime/references', 2, 5513 'Is this a non-const reference? ' 5514 'If so, make const or use a pointer: ' + 5515 ReplaceAll(' *<', '<', parameter)) 5516 5517 5518def CheckCasts(filename, clean_lines, linenum, error): 5519 """Various cast related checks. 5520 5521 Args: 5522 filename: The name of the current file. 5523 clean_lines: A CleansedLines instance containing the file. 5524 linenum: The number of the line to check. 5525 error: The function to call with any errors found. 5526 """ 5527 line = clean_lines.elided[linenum] 5528 5529 # Check to see if they're using an conversion function cast. 5530 # I just try to capture the most common basic types, though there are more. 5531 # Parameterless conversion functions, such as bool(), are allowed as they are 5532 # probably a member operator declaration or default constructor. 5533 match = Search( 5534 r'(\bnew\s+(?:const\s+)?|\S<\s*(?:const\s+)?)?\b' 5535 r'(int|float|double|bool|char|int32|uint32|int64|uint64)' 5536 r'(\([^)].*)', line) 5537 expecting_function = ExpectingFunctionArgs(clean_lines, linenum) 5538 if match and not expecting_function: 5539 matched_type = match.group(2) 5540 5541 # matched_new_or_template is used to silence two false positives: 5542 # - New operators 5543 # - Template arguments with function types 5544 # 5545 # For template arguments, we match on types immediately following 5546 # an opening bracket without any spaces. This is a fast way to 5547 # silence the common case where the function type is the first 5548 # template argument. False negative with less-than comparison is 5549 # avoided because those operators are usually followed by a space. 5550 # 5551 # function<double(double)> // bracket + no space = false positive 5552 # value < double(42) // bracket + space = true positive 5553 matched_new_or_template = match.group(1) 5554 5555 # Avoid arrays by looking for brackets that come after the closing 5556 # parenthesis. 5557 if Match(r'\([^()]+\)\s*\[', match.group(3)): 5558 return 5559 5560 # Other things to ignore: 5561 # - Function pointers 5562 # - Casts to pointer types 5563 # - Placement new 5564 # - Alias declarations 5565 matched_funcptr = match.group(3) 5566 if (matched_new_or_template is None and 5567 not (matched_funcptr and 5568 (Match(r'\((?:[^() ]+::\s*\*\s*)?[^() ]+\)\s*\(', 5569 matched_funcptr) or 5570 matched_funcptr.startswith('(*)'))) and 5571 not Match(r'\s*using\s+\S+\s*=\s*' + matched_type, line) and 5572 not Search(r'new\(\S+\)\s*' + matched_type, line)): 5573 error(filename, linenum, 'readability/casting', 4, 5574 'Using deprecated casting style. ' 5575 'Use static_cast<%s>(...) instead' % 5576 matched_type) 5577 5578 if not expecting_function: 5579 CheckCStyleCast(filename, clean_lines, linenum, 'static_cast', 5580 r'\((int|float|double|bool|char|u?int(16|32|64))\)', error) 5581 5582 # This doesn't catch all cases. Consider (const char * const)"hello". 5583 # 5584 # (char *) "foo" should always be a const_cast (reinterpret_cast won't 5585 # compile). 5586 if CheckCStyleCast(filename, clean_lines, linenum, 'const_cast', 5587 r'\((char\s?\*+\s?)\)\s*"', error): 5588 pass 5589 else: 5590 # Check pointer casts for other than string constants 5591 CheckCStyleCast(filename, clean_lines, linenum, 'reinterpret_cast', 5592 r'\((\w+\s?\*+\s?)\)', error) 5593 5594 # In addition, we look for people taking the address of a cast. This 5595 # is dangerous -- casts can assign to temporaries, so the pointer doesn't 5596 # point where you think. 5597 # 5598 # Some non-identifier character is required before the '&' for the 5599 # expression to be recognized as a cast. These are casts: 5600 # expression = &static_cast<int*>(temporary()); 5601 # function(&(int*)(temporary())); 5602 # 5603 # This is not a cast: 5604 # reference_type&(int* function_param); 5605 match = Search( 5606 r'(?:[^\w]&\(([^)*][^)]*)\)[\w(])|' 5607 r'(?:[^\w]&(static|dynamic|down|reinterpret)_cast\b)', line) 5608 if match: 5609 # Try a better error message when the & is bound to something 5610 # dereferenced by the casted pointer, as opposed to the casted 5611 # pointer itself. 5612 parenthesis_error = False 5613 match = Match(r'^(.*&(?:static|dynamic|down|reinterpret)_cast\b)<', line) 5614 if match: 5615 _, y1, x1 = CloseExpression(clean_lines, linenum, len(match.group(1))) 5616 if x1 >= 0 and clean_lines.elided[y1][x1] == '(': 5617 _, y2, x2 = CloseExpression(clean_lines, y1, x1) 5618 if x2 >= 0: 5619 extended_line = clean_lines.elided[y2][x2:] 5620 if y2 < clean_lines.NumLines() - 1: 5621 extended_line += clean_lines.elided[y2 + 1] 5622 if Match(r'\s*(?:->|\[)', extended_line): 5623 parenthesis_error = True 5624 5625 if parenthesis_error: 5626 error(filename, linenum, 'readability/casting', 4, 5627 ('Are you taking an address of something dereferenced ' 5628 'from a cast? Wrapping the dereferenced expression in ' 5629 'parentheses will make the binding more obvious')) 5630 else: 5631 error(filename, linenum, 'runtime/casting', 4, 5632 ('Are you taking an address of a cast? ' 5633 'This is dangerous: could be a temp var. ' 5634 'Take the address before doing the cast, rather than after')) 5635 5636 5637def CheckCStyleCast(filename, clean_lines, linenum, cast_type, pattern, error): 5638 """Checks for a C-style cast by looking for the pattern. 5639 5640 Args: 5641 filename: The name of the current file. 5642 clean_lines: A CleansedLines instance containing the file. 5643 linenum: The number of the line to check. 5644 cast_type: The string for the C++ cast to recommend. This is either 5645 reinterpret_cast, static_cast, or const_cast, depending. 5646 pattern: The regular expression used to find C-style casts. 5647 error: The function to call with any errors found. 5648 5649 Returns: 5650 True if an error was emitted. 5651 False otherwise. 5652 """ 5653 line = clean_lines.elided[linenum] 5654 match = Search(pattern, line) 5655 if not match: 5656 return False 5657 5658 # Exclude lines with keywords that tend to look like casts 5659 context = line[0:match.start(1) - 1] 5660 if Match(r'.*\b(?:sizeof|alignof|alignas|[_A-Z][_A-Z0-9]*)\s*$', context): 5661 return False 5662 5663 # Try expanding current context to see if we one level of 5664 # parentheses inside a macro. 5665 if linenum > 0: 5666 for i in xrange(linenum - 1, max(0, linenum - 5), -1): 5667 context = clean_lines.elided[i] + context 5668 if Match(r'.*\b[_A-Z][_A-Z0-9]*\s*\((?:\([^()]*\)|[^()])*$', context): 5669 return False 5670 5671 # operator++(int) and operator--(int) 5672 if context.endswith(' operator++') or context.endswith(' operator--'): 5673 return False 5674 5675 # A single unnamed argument for a function tends to look like old style cast. 5676 # If we see those, don't issue warnings for deprecated casts. 5677 remainder = line[match.end(0):] 5678 if Match(r'^\s*(?:;|const\b|throw\b|final\b|override\b|[=>{),]|->)', 5679 remainder): 5680 return False 5681 5682 # At this point, all that should be left is actual casts. 5683 error(filename, linenum, 'readability/casting', 4, 5684 'Using C-style cast. Use %s<%s>(...) instead' % 5685 (cast_type, match.group(1))) 5686 5687 return True 5688 5689 5690def ExpectingFunctionArgs(clean_lines, linenum): 5691 """Checks whether where function type arguments are expected. 5692 5693 Args: 5694 clean_lines: A CleansedLines instance containing the file. 5695 linenum: The number of the line to check. 5696 5697 Returns: 5698 True if the line at 'linenum' is inside something that expects arguments 5699 of function types. 5700 """ 5701 line = clean_lines.elided[linenum] 5702 return (Match(r'^\s*MOCK_(CONST_)?METHOD\d+(_T)?\(', line) or 5703 (linenum >= 2 and 5704 (Match(r'^\s*MOCK_(?:CONST_)?METHOD\d+(?:_T)?\((?:\S+,)?\s*$', 5705 clean_lines.elided[linenum - 1]) or 5706 Match(r'^\s*MOCK_(?:CONST_)?METHOD\d+(?:_T)?\(\s*$', 5707 clean_lines.elided[linenum - 2]) or 5708 Search(r'\bstd::m?function\s*\<\s*$', 5709 clean_lines.elided[linenum - 1])))) 5710 5711 5712_HEADERS_CONTAINING_TEMPLATES = ( 5713 ('<deque>', ('deque',)), 5714 ('<functional>', ('unary_function', 'binary_function', 5715 'plus', 'minus', 'multiplies', 'divides', 'modulus', 5716 'negate', 5717 'equal_to', 'not_equal_to', 'greater', 'less', 5718 'greater_equal', 'less_equal', 5719 'logical_and', 'logical_or', 'logical_not', 5720 'unary_negate', 'not1', 'binary_negate', 'not2', 5721 'bind1st', 'bind2nd', 5722 'pointer_to_unary_function', 5723 'pointer_to_binary_function', 5724 'ptr_fun', 5725 'mem_fun_t', 'mem_fun', 'mem_fun1_t', 'mem_fun1_ref_t', 5726 'mem_fun_ref_t', 5727 'const_mem_fun_t', 'const_mem_fun1_t', 5728 'const_mem_fun_ref_t', 'const_mem_fun1_ref_t', 5729 'mem_fun_ref', 5730 )), 5731 ('<limits>', ('numeric_limits',)), 5732 ('<list>', ('list',)), 5733 ('<map>', ('multimap',)), 5734 ('<memory>', ('allocator', 'make_shared', 'make_unique', 'shared_ptr', 5735 'unique_ptr', 'weak_ptr')), 5736 ('<queue>', ('queue', 'priority_queue',)), 5737 ('<set>', ('multiset',)), 5738 ('<stack>', ('stack',)), 5739 ('<string>', ('char_traits', 'basic_string',)), 5740 ('<tuple>', ('tuple',)), 5741 ('<unordered_map>', ('unordered_map', 'unordered_multimap')), 5742 ('<unordered_set>', ('unordered_set', 'unordered_multiset')), 5743 ('<utility>', ('pair',)), 5744 ('<vector>', ('vector',)), 5745 5746 # gcc extensions. 5747 # Note: std::hash is their hash, ::hash is our hash 5748 ('<hash_map>', ('hash_map', 'hash_multimap',)), 5749 ('<hash_set>', ('hash_set', 'hash_multiset',)), 5750 ('<slist>', ('slist',)), 5751 ) 5752 5753_HEADERS_MAYBE_TEMPLATES = ( 5754 ('<algorithm>', ('copy', 'max', 'min', 'min_element', 'sort', 5755 'transform', 5756 )), 5757 ('<utility>', ('forward', 'make_pair', 'move', 'swap')), 5758 ) 5759 5760_RE_PATTERN_STRING = re.compile(r'\bstring\b') 5761 5762_re_pattern_headers_maybe_templates = [] 5763for _header, _templates in _HEADERS_MAYBE_TEMPLATES: 5764 for _template in _templates: 5765 # Match max<type>(..., ...), max(..., ...), but not foo->max, foo.max or 5766 # 'type::max()'. 5767 _re_pattern_headers_maybe_templates.append( 5768 (re.compile(r'[^>.]\b' + _template + r'(<.*?>)?\([^\)]'), 5769 _template, 5770 _header)) 5771# Match set<type>, but not foo->set<type>, foo.set<type> 5772_re_pattern_headers_maybe_templates.append( 5773 (re.compile(r'[^>.]\bset\s*\<'), 5774 'set<>', 5775 '<set>')) 5776# Match 'map<type> var' and 'std::map<type>(...)', but not 'map<type>(...)'' 5777_re_pattern_headers_maybe_templates.append( 5778 (re.compile(r'(std\b::\bmap\s*\<)|(^(std\b::\b)map\b\(\s*\<)'), 5779 'map<>', 5780 '<map>')) 5781 5782# Other scripts may reach in and modify this pattern. 5783_re_pattern_templates = [] 5784for _header, _templates in _HEADERS_CONTAINING_TEMPLATES: 5785 for _template in _templates: 5786 _re_pattern_templates.append( 5787 (re.compile(r'(\<|\b)' + _template + r'\s*\<'), 5788 _template + '<>', 5789 _header)) 5790 5791 5792def FilesBelongToSameModule(filename_cc, filename_h): 5793 """Check if these two filenames belong to the same module. 5794 5795 The concept of a 'module' here is a as follows: 5796 foo.h, foo-inl.h, foo.cc, foo_test.cc and foo_unittest.cc belong to the 5797 same 'module' if they are in the same directory. 5798 some/path/public/xyzzy and some/path/internal/xyzzy are also considered 5799 to belong to the same module here. 5800 5801 If the filename_cc contains a longer path than the filename_h, for example, 5802 '/absolute/path/to/base/sysinfo.cc', and this file would include 5803 'base/sysinfo.h', this function also produces the prefix needed to open the 5804 header. This is used by the caller of this function to more robustly open the 5805 header file. We don't have access to the real include paths in this context, 5806 so we need this guesswork here. 5807 5808 Known bugs: tools/base/bar.cc and base/bar.h belong to the same module 5809 according to this implementation. Because of this, this function gives 5810 some false positives. This should be sufficiently rare in practice. 5811 5812 Args: 5813 filename_cc: is the path for the source (e.g. .cc) file 5814 filename_h: is the path for the header path 5815 5816 Returns: 5817 Tuple with a bool and a string: 5818 bool: True if filename_cc and filename_h belong to the same module. 5819 string: the additional prefix needed to open the header file. 5820 """ 5821 fileinfo_cc = FileInfo(filename_cc) 5822 if not fileinfo_cc.Extension().lstrip('.') in GetNonHeaderExtensions(): 5823 return (False, '') 5824 5825 fileinfo_h = FileInfo(filename_h) 5826 if not IsHeaderExtension(fileinfo_h.Extension().lstrip('.')): 5827 return (False, '') 5828 5829 filename_cc = filename_cc[:-(len(fileinfo_cc.Extension()))] 5830 matched_test_suffix = Search(_TEST_FILE_SUFFIX, fileinfo_cc.BaseName()) 5831 if matched_test_suffix: 5832 filename_cc = filename_cc[:-len(matched_test_suffix.group(1))] 5833 5834 filename_cc = filename_cc.replace('/public/', '/') 5835 filename_cc = filename_cc.replace('/internal/', '/') 5836 5837 filename_h = filename_h[:-(len(fileinfo_h.Extension()))] 5838 if filename_h.endswith('-inl'): 5839 filename_h = filename_h[:-len('-inl')] 5840 filename_h = filename_h.replace('/public/', '/') 5841 filename_h = filename_h.replace('/internal/', '/') 5842 5843 files_belong_to_same_module = filename_cc.endswith(filename_h) 5844 common_path = '' 5845 if files_belong_to_same_module: 5846 common_path = filename_cc[:-len(filename_h)] 5847 return files_belong_to_same_module, common_path 5848 5849 5850def UpdateIncludeState(filename, include_dict, io=codecs): 5851 """Fill up the include_dict with new includes found from the file. 5852 5853 Args: 5854 filename: the name of the header to read. 5855 include_dict: a dictionary in which the headers are inserted. 5856 io: The io factory to use to read the file. Provided for testability. 5857 5858 Returns: 5859 True if a header was successfully added. False otherwise. 5860 """ 5861 headerfile = None 5862 try: 5863 with io.open(filename, 'r', 'utf8', 'replace') as headerfile: 5864 linenum = 0 5865 for line in headerfile: 5866 linenum += 1 5867 clean_line = CleanseComments(line) 5868 match = _RE_PATTERN_INCLUDE.search(clean_line) 5869 if match: 5870 include = match.group(2) 5871 include_dict.setdefault(include, linenum) 5872 return True 5873 except IOError: 5874 return False 5875 5876 5877 5878def CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error, 5879 io=codecs): 5880 """Reports for missing stl includes. 5881 5882 This function will output warnings to make sure you are including the headers 5883 necessary for the stl containers and functions that you use. We only give one 5884 reason to include a header. For example, if you use both equal_to<> and 5885 less<> in a .h file, only one (the latter in the file) of these will be 5886 reported as a reason to include the <functional>. 5887 5888 Args: 5889 filename: The name of the current file. 5890 clean_lines: A CleansedLines instance containing the file. 5891 include_state: An _IncludeState instance. 5892 error: The function to call with any errors found. 5893 io: The IO factory to use to read the header file. Provided for unittest 5894 injection. 5895 """ 5896 required = {} # A map of header name to linenumber and the template entity. 5897 # Example of required: { '<functional>': (1219, 'less<>') } 5898 5899 for linenum in xrange(clean_lines.NumLines()): 5900 line = clean_lines.elided[linenum] 5901 if not line or line[0] == '#': 5902 continue 5903 5904 # String is special -- it is a non-templatized type in STL. 5905 matched = _RE_PATTERN_STRING.search(line) 5906 if matched: 5907 # Don't warn about strings in non-STL namespaces: 5908 # (We check only the first match per line; good enough.) 5909 prefix = line[:matched.start()] 5910 if prefix.endswith('std::') or not prefix.endswith('::'): 5911 required['<string>'] = (linenum, 'string') 5912 5913 for pattern, template, header in _re_pattern_headers_maybe_templates: 5914 if pattern.search(line): 5915 required[header] = (linenum, template) 5916 5917 # The following function is just a speed up, no semantics are changed. 5918 if not '<' in line: # Reduces the cpu time usage by skipping lines. 5919 continue 5920 5921 for pattern, template, header in _re_pattern_templates: 5922 matched = pattern.search(line) 5923 if matched: 5924 # Don't warn about IWYU in non-STL namespaces: 5925 # (We check only the first match per line; good enough.) 5926 prefix = line[:matched.start()] 5927 if prefix.endswith('std::') or not prefix.endswith('::'): 5928 required[header] = (linenum, template) 5929 5930 # The policy is that if you #include something in foo.h you don't need to 5931 # include it again in foo.cc. Here, we will look at possible includes. 5932 # Let's flatten the include_state include_list and copy it into a dictionary. 5933 include_dict = dict([item for sublist in include_state.include_list 5934 for item in sublist]) 5935 5936 # Did we find the header for this file (if any) and successfully load it? 5937 header_found = False 5938 5939 # Use the absolute path so that matching works properly. 5940 abs_filename = FileInfo(filename).FullName() 5941 5942 # For Emacs's flymake. 5943 # If cpplint is invoked from Emacs's flymake, a temporary file is generated 5944 # by flymake and that file name might end with '_flymake.cc'. In that case, 5945 # restore original file name here so that the corresponding header file can be 5946 # found. 5947 # e.g. If the file name is 'foo_flymake.cc', we should search for 'foo.h' 5948 # instead of 'foo_flymake.h' 5949 abs_filename = re.sub(r'_flymake\.cc$', '.cc', abs_filename) 5950 5951 # include_dict is modified during iteration, so we iterate over a copy of 5952 # the keys. 5953 header_keys = list(include_dict.keys()) 5954 for header in header_keys: 5955 (same_module, common_path) = FilesBelongToSameModule(abs_filename, header) 5956 fullpath = common_path + header 5957 if same_module and UpdateIncludeState(fullpath, include_dict, io): 5958 header_found = True 5959 5960 # If we can't find the header file for a .cc, assume it's because we don't 5961 # know where to look. In that case we'll give up as we're not sure they 5962 # didn't include it in the .h file. 5963 # TODO(unknown): Do a better job of finding .h files so we are confident that 5964 # not having the .h file means there isn't one. 5965 if not header_found: 5966 for extension in GetNonHeaderExtensions(): 5967 if filename.endswith('.' + extension): 5968 return 5969 5970 # All the lines have been processed, report the errors found. 5971 for required_header_unstripped in sorted(required, key=required.__getitem__): 5972 template = required[required_header_unstripped][1] 5973 if required_header_unstripped.strip('<>"') not in include_dict: 5974 error(filename, required[required_header_unstripped][0], 5975 'build/include_what_you_use', 4, 5976 'Add #include ' + required_header_unstripped + ' for ' + template) 5977 5978 5979_RE_PATTERN_EXPLICIT_MAKEPAIR = re.compile(r'\bmake_pair\s*<') 5980 5981 5982def CheckMakePairUsesDeduction(filename, clean_lines, linenum, error): 5983 """Check that make_pair's template arguments are deduced. 5984 5985 G++ 4.6 in C++11 mode fails badly if make_pair's template arguments are 5986 specified explicitly, and such use isn't intended in any case. 5987 5988 Args: 5989 filename: The name of the current file. 5990 clean_lines: A CleansedLines instance containing the file. 5991 linenum: The number of the line to check. 5992 error: The function to call with any errors found. 5993 """ 5994 line = clean_lines.elided[linenum] 5995 match = _RE_PATTERN_EXPLICIT_MAKEPAIR.search(line) 5996 if match: 5997 error(filename, linenum, 'build/explicit_make_pair', 5998 4, # 4 = high confidence 5999 'For C++11-compatibility, omit template arguments from make_pair' 6000 ' OR use pair directly OR if appropriate, construct a pair directly') 6001 6002 6003def CheckRedundantVirtual(filename, clean_lines, linenum, error): 6004 """Check if line contains a redundant "virtual" function-specifier. 6005 6006 Args: 6007 filename: The name of the current file. 6008 clean_lines: A CleansedLines instance containing the file. 6009 linenum: The number of the line to check. 6010 error: The function to call with any errors found. 6011 """ 6012 # Look for "virtual" on current line. 6013 line = clean_lines.elided[linenum] 6014 virtual = Match(r'^(.*)(\bvirtual\b)(.*)$', line) 6015 if not virtual: return 6016 6017 # Ignore "virtual" keywords that are near access-specifiers. These 6018 # are only used in class base-specifier and do not apply to member 6019 # functions. 6020 if (Search(r'\b(public|protected|private)\s+$', virtual.group(1)) or 6021 Match(r'^\s+(public|protected|private)\b', virtual.group(3))): 6022 return 6023 6024 # Ignore the "virtual" keyword from virtual base classes. Usually 6025 # there is a column on the same line in these cases (virtual base 6026 # classes are rare in google3 because multiple inheritance is rare). 6027 if Match(r'^.*[^:]:[^:].*$', line): return 6028 6029 # Look for the next opening parenthesis. This is the start of the 6030 # parameter list (possibly on the next line shortly after virtual). 6031 # TODO(unknown): doesn't work if there are virtual functions with 6032 # decltype() or other things that use parentheses, but csearch suggests 6033 # that this is rare. 6034 end_col = -1 6035 end_line = -1 6036 start_col = len(virtual.group(2)) 6037 for start_line in xrange(linenum, min(linenum + 3, clean_lines.NumLines())): 6038 line = clean_lines.elided[start_line][start_col:] 6039 parameter_list = Match(r'^([^(]*)\(', line) 6040 if parameter_list: 6041 # Match parentheses to find the end of the parameter list 6042 (_, end_line, end_col) = CloseExpression( 6043 clean_lines, start_line, start_col + len(parameter_list.group(1))) 6044 break 6045 start_col = 0 6046 6047 if end_col < 0: 6048 return # Couldn't find end of parameter list, give up 6049 6050 # Look for "override" or "final" after the parameter list 6051 # (possibly on the next few lines). 6052 for i in xrange(end_line, min(end_line + 3, clean_lines.NumLines())): 6053 line = clean_lines.elided[i][end_col:] 6054 match = Search(r'\b(override|final)\b', line) 6055 if match: 6056 error(filename, linenum, 'readability/inheritance', 4, 6057 ('"virtual" is redundant since function is ' 6058 'already declared as "%s"' % match.group(1))) 6059 6060 # Set end_col to check whole lines after we are done with the 6061 # first line. 6062 end_col = 0 6063 if Search(r'[^\w]\s*$', line): 6064 break 6065 6066 6067def CheckRedundantOverrideOrFinal(filename, clean_lines, linenum, error): 6068 """Check if line contains a redundant "override" or "final" virt-specifier. 6069 6070 Args: 6071 filename: The name of the current file. 6072 clean_lines: A CleansedLines instance containing the file. 6073 linenum: The number of the line to check. 6074 error: The function to call with any errors found. 6075 """ 6076 # Look for closing parenthesis nearby. We need one to confirm where 6077 # the declarator ends and where the virt-specifier starts to avoid 6078 # false positives. 6079 line = clean_lines.elided[linenum] 6080 declarator_end = line.rfind(')') 6081 if declarator_end >= 0: 6082 fragment = line[declarator_end:] 6083 else: 6084 if linenum > 1 and clean_lines.elided[linenum - 1].rfind(')') >= 0: 6085 fragment = line 6086 else: 6087 return 6088 6089 # Check that at most one of "override" or "final" is present, not both 6090 if Search(r'\boverride\b', fragment) and Search(r'\bfinal\b', fragment): 6091 error(filename, linenum, 'readability/inheritance', 4, 6092 ('"override" is redundant since function is ' 6093 'already declared as "final"')) 6094 6095 6096 6097 6098# Returns true if we are at a new block, and it is directly 6099# inside of a namespace. 6100def IsBlockInNameSpace(nesting_state, is_forward_declaration): 6101 """Checks that the new block is directly in a namespace. 6102 6103 Args: 6104 nesting_state: The _NestingState object that contains info about our state. 6105 is_forward_declaration: If the class is a forward declared class. 6106 Returns: 6107 Whether or not the new block is directly in a namespace. 6108 """ 6109 if is_forward_declaration: 6110 return len(nesting_state.stack) >= 1 and ( 6111 isinstance(nesting_state.stack[-1], _NamespaceInfo)) 6112 6113 6114 return (len(nesting_state.stack) > 1 and 6115 nesting_state.stack[-1].check_namespace_indentation and 6116 isinstance(nesting_state.stack[-2], _NamespaceInfo)) 6117 6118 6119def ShouldCheckNamespaceIndentation(nesting_state, is_namespace_indent_item, 6120 raw_lines_no_comments, linenum): 6121 """This method determines if we should apply our namespace indentation check. 6122 6123 Args: 6124 nesting_state: The current nesting state. 6125 is_namespace_indent_item: If we just put a new class on the stack, True. 6126 If the top of the stack is not a class, or we did not recently 6127 add the class, False. 6128 raw_lines_no_comments: The lines without the comments. 6129 linenum: The current line number we are processing. 6130 6131 Returns: 6132 True if we should apply our namespace indentation check. Currently, it 6133 only works for classes and namespaces inside of a namespace. 6134 """ 6135 6136 is_forward_declaration = IsForwardClassDeclaration(raw_lines_no_comments, 6137 linenum) 6138 6139 if not (is_namespace_indent_item or is_forward_declaration): 6140 return False 6141 6142 # If we are in a macro, we do not want to check the namespace indentation. 6143 if IsMacroDefinition(raw_lines_no_comments, linenum): 6144 return False 6145 6146 return IsBlockInNameSpace(nesting_state, is_forward_declaration) 6147 6148 6149# Call this method if the line is directly inside of a namespace. 6150# If the line above is blank (excluding comments) or the start of 6151# an inner namespace, it cannot be indented. 6152def CheckItemIndentationInNamespace(filename, raw_lines_no_comments, linenum, 6153 error): 6154 line = raw_lines_no_comments[linenum] 6155 if Match(r'^\s+', line): 6156 error(filename, linenum, 'runtime/indentation_namespace', 4, 6157 'Do not indent within a namespace') 6158 6159 6160def ProcessLine(filename, file_extension, clean_lines, line, 6161 include_state, function_state, nesting_state, error, 6162 extra_check_functions=None): 6163 """Processes a single line in the file. 6164 6165 Args: 6166 filename: Filename of the file that is being processed. 6167 file_extension: The extension (dot not included) of the file. 6168 clean_lines: An array of strings, each representing a line of the file, 6169 with comments stripped. 6170 line: Number of line being processed. 6171 include_state: An _IncludeState instance in which the headers are inserted. 6172 function_state: A _FunctionState instance which counts function lines, etc. 6173 nesting_state: A NestingState instance which maintains information about 6174 the current stack of nested blocks being parsed. 6175 error: A callable to which errors are reported, which takes 4 arguments: 6176 filename, line number, error level, and message 6177 extra_check_functions: An array of additional check functions that will be 6178 run on each source line. Each function takes 4 6179 arguments: filename, clean_lines, line, error 6180 """ 6181 raw_lines = clean_lines.raw_lines 6182 ParseNolintSuppressions(filename, raw_lines[line], line, error) 6183 nesting_state.Update(filename, clean_lines, line, error) 6184 CheckForNamespaceIndentation(filename, nesting_state, clean_lines, line, 6185 error) 6186 if nesting_state.InAsmBlock(): return 6187 CheckForFunctionLengths(filename, clean_lines, line, function_state, error) 6188 CheckForMultilineCommentsAndStrings(filename, clean_lines, line, error) 6189 CheckStyle(filename, clean_lines, line, file_extension, nesting_state, error) 6190 CheckLanguage(filename, clean_lines, line, file_extension, include_state, 6191 nesting_state, error) 6192 CheckForNonConstReference(filename, clean_lines, line, nesting_state, error) 6193 CheckForNonStandardConstructs(filename, clean_lines, line, 6194 nesting_state, error) 6195 CheckVlogArguments(filename, clean_lines, line, error) 6196 CheckPosixThreading(filename, clean_lines, line, error) 6197 CheckInvalidIncrement(filename, clean_lines, line, error) 6198 CheckMakePairUsesDeduction(filename, clean_lines, line, error) 6199 CheckRedundantVirtual(filename, clean_lines, line, error) 6200 CheckRedundantOverrideOrFinal(filename, clean_lines, line, error) 6201 if extra_check_functions: 6202 for check_fn in extra_check_functions: 6203 check_fn(filename, clean_lines, line, error) 6204 6205def FlagCxx11Features(filename, clean_lines, linenum, error): 6206 """Flag those c++11 features that we only allow in certain places. 6207 6208 Args: 6209 filename: The name of the current file. 6210 clean_lines: A CleansedLines instance containing the file. 6211 linenum: The number of the line to check. 6212 error: The function to call with any errors found. 6213 """ 6214 line = clean_lines.elided[linenum] 6215 6216 include = Match(r'\s*#\s*include\s+[<"]([^<"]+)[">]', line) 6217 6218 # Flag unapproved C++ TR1 headers. 6219 if include and include.group(1).startswith('tr1/'): 6220 error(filename, linenum, 'build/c++tr1', 5, 6221 ('C++ TR1 headers such as <%s> are unapproved.') % include.group(1)) 6222 6223 # Flag unapproved C++11 headers. 6224 if include and include.group(1) in ('cfenv', 6225 'condition_variable', 6226 'fenv.h', 6227 'future', 6228 'mutex', 6229 'thread', 6230 'chrono', 6231 'ratio', 6232 'regex', 6233 'system_error', 6234 ): 6235 error(filename, linenum, 'build/c++11', 5, 6236 ('<%s> is an unapproved C++11 header.') % include.group(1)) 6237 6238 # The only place where we need to worry about C++11 keywords and library 6239 # features in preprocessor directives is in macro definitions. 6240 if Match(r'\s*#', line) and not Match(r'\s*#\s*define\b', line): return 6241 6242 # These are classes and free functions. The classes are always 6243 # mentioned as std::*, but we only catch the free functions if 6244 # they're not found by ADL. They're alphabetical by header. 6245 for top_name in ( 6246 # type_traits 6247 'alignment_of', 6248 'aligned_union', 6249 ): 6250 if Search(r'\bstd::%s\b' % top_name, line): 6251 error(filename, linenum, 'build/c++11', 5, 6252 ('std::%s is an unapproved C++11 class or function. Send c-style ' 6253 'an example of where it would make your code more readable, and ' 6254 'they may let you use it.') % top_name) 6255 6256 6257def FlagCxx14Features(filename, clean_lines, linenum, error): 6258 """Flag those C++14 features that we restrict. 6259 6260 Args: 6261 filename: The name of the current file. 6262 clean_lines: A CleansedLines instance containing the file. 6263 linenum: The number of the line to check. 6264 error: The function to call with any errors found. 6265 """ 6266 line = clean_lines.elided[linenum] 6267 6268 include = Match(r'\s*#\s*include\s+[<"]([^<"]+)[">]', line) 6269 6270 # Flag unapproved C++14 headers. 6271 if include and include.group(1) in ('scoped_allocator', 'shared_mutex'): 6272 error(filename, linenum, 'build/c++14', 5, 6273 ('<%s> is an unapproved C++14 header.') % include.group(1)) 6274 6275 6276def ProcessFileData(filename, file_extension, lines, error, 6277 extra_check_functions=None): 6278 """Performs lint checks and reports any errors to the given error function. 6279 6280 Args: 6281 filename: Filename of the file that is being processed. 6282 file_extension: The extension (dot not included) of the file. 6283 lines: An array of strings, each representing a line of the file, with the 6284 last element being empty if the file is terminated with a newline. 6285 error: A callable to which errors are reported, which takes 4 arguments: 6286 filename, line number, error level, and message 6287 extra_check_functions: An array of additional check functions that will be 6288 run on each source line. Each function takes 4 6289 arguments: filename, clean_lines, line, error 6290 """ 6291 lines = (['// marker so line numbers and indices both start at 1'] + lines + 6292 ['// marker so line numbers end in a known way']) 6293 6294 include_state = _IncludeState() 6295 function_state = _FunctionState() 6296 nesting_state = NestingState() 6297 6298 ResetNolintSuppressions() 6299 6300 CheckForCopyright(filename, lines, error) 6301 ProcessGlobalSuppresions(lines) 6302 RemoveMultiLineComments(filename, lines, error) 6303 clean_lines = CleansedLines(lines) 6304 6305 if IsHeaderExtension(file_extension): 6306 CheckForHeaderGuard(filename, clean_lines, error) 6307 6308 for line in xrange(clean_lines.NumLines()): 6309 ProcessLine(filename, file_extension, clean_lines, line, 6310 include_state, function_state, nesting_state, error, 6311 extra_check_functions) 6312 FlagCxx11Features(filename, clean_lines, line, error) 6313 nesting_state.CheckCompletedBlocks(filename, error) 6314 6315 CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error) 6316 6317 # Check that the .cc file has included its header if it exists. 6318 if _IsSourceExtension(file_extension): 6319 CheckHeaderFileIncluded(filename, include_state, error) 6320 6321 # We check here rather than inside ProcessLine so that we see raw 6322 # lines rather than "cleaned" lines. 6323 CheckForBadCharacters(filename, lines, error) 6324 6325 CheckForNewlineAtEOF(filename, lines, error) 6326 6327 CheckInlineHeader(filename, include_state, error) 6328 6329def ProcessConfigOverrides(filename): 6330 """ Loads the configuration files and processes the config overrides. 6331 6332 Args: 6333 filename: The name of the file being processed by the linter. 6334 6335 Returns: 6336 False if the current |filename| should not be processed further. 6337 """ 6338 6339 abs_filename = os.path.abspath(filename) 6340 cfg_filters = [] 6341 keep_looking = True 6342 while keep_looking: 6343 abs_path, base_name = os.path.split(abs_filename) 6344 if not base_name: 6345 break # Reached the root directory. 6346 6347 cfg_file = os.path.join(abs_path, ".cpplint") 6348 abs_filename = abs_path 6349 if not os.path.isfile(cfg_file): 6350 continue 6351 6352 try: 6353 with open(cfg_file) as file_handle: 6354 for line in file_handle: 6355 line, _, _ = line.partition('#') # Remove comments. 6356 if not line.strip(): 6357 continue 6358 6359 name, _, val = line.partition('=') 6360 name = name.strip() 6361 val = val.strip() 6362 if name == 'set noparent': 6363 keep_looking = False 6364 elif name == 'filter': 6365 cfg_filters.append(val) 6366 elif name == 'exclude_files': 6367 # When matching exclude_files pattern, use the base_name of 6368 # the current file name or the directory name we are processing. 6369 # For example, if we are checking for lint errors in /foo/bar/baz.cc 6370 # and we found the .cfg file at /foo/CPPLINT.cfg, then the config 6371 # file's "exclude_files" filter is meant to be checked against "bar" 6372 # and not "baz" nor "bar/baz.cc". 6373 if base_name: 6374 pattern = re.compile(val) 6375 if pattern.match(base_name): 6376 if _cpplint_state.quiet: 6377 # Suppress "Ignoring file" warning when using --quiet. 6378 return False 6379 _cpplint_state.PrintInfo('Ignoring "%s": file excluded by "%s". ' 6380 'File path component "%s" matches ' 6381 'pattern "%s"\n' % 6382 (filename, cfg_file, base_name, val)) 6383 return False 6384 elif name == 'linelength': 6385 global _line_length 6386 try: 6387 _line_length = int(val) 6388 except ValueError: 6389 _cpplint_state.PrintError('Line length must be numeric.') 6390 elif name == 'extensions': 6391 ProcessExtensionsOption(val) 6392 elif name == 'root': 6393 global _root 6394 # root directories are specified relative to CPPLINT.cfg dir. 6395 _root = os.path.join(os.path.dirname(cfg_file), val) 6396 elif name == 'headers': 6397 ProcessHppHeadersOption(val) 6398 else: 6399 _cpplint_state.PrintError( 6400 'Invalid configuration option (%s) in file %s\n' % 6401 (name, cfg_file)) 6402 6403 except IOError: 6404 _cpplint_state.PrintError( 6405 "Skipping config file '%s': Can't open for reading\n" % cfg_file) 6406 keep_looking = False 6407 6408 # Apply all the accumulated filters in reverse order (top-level directory 6409 # config options having the least priority). 6410 for cfg_filter in reversed(cfg_filters): 6411 _AddFilters(cfg_filter) 6412 6413 return True 6414 6415 6416def ProcessFile(filename, vlevel, extra_check_functions=None): 6417 """Does google-lint on a single file. 6418 6419 Args: 6420 filename: The name of the file to parse. 6421 6422 vlevel: The level of errors to report. Every error of confidence 6423 >= verbose_level will be reported. 0 is a good default. 6424 6425 extra_check_functions: An array of additional check functions that will be 6426 run on each source line. Each function takes 4 6427 arguments: filename, clean_lines, line, error 6428 """ 6429 6430 _SetVerboseLevel(vlevel) 6431 _BackupFilters() 6432 old_errors = _cpplint_state.error_count 6433 6434 if not ProcessConfigOverrides(filename): 6435 _RestoreFilters() 6436 return 6437 6438 lf_lines = [] 6439 crlf_lines = [] 6440 try: 6441 # Support the UNIX convention of using "-" for stdin. Note that 6442 # we are not opening the file with universal newline support 6443 # (which codecs doesn't support anyway), so the resulting lines do 6444 # contain trailing '\r' characters if we are reading a file that 6445 # has CRLF endings. 6446 # If after the split a trailing '\r' is present, it is removed 6447 # below. 6448 if filename == '-': 6449 lines = codecs.StreamReaderWriter(sys.stdin, 6450 codecs.getreader('utf8'), 6451 codecs.getwriter('utf8'), 6452 'replace').read().split('\n') 6453 else: 6454 with codecs.open(filename, 'r', 'utf8', 'replace') as target_file: 6455 lines = target_file.read().split('\n') 6456 6457 # Remove trailing '\r'. 6458 # The -1 accounts for the extra trailing blank line we get from split() 6459 for linenum in range(len(lines) - 1): 6460 if lines[linenum].endswith('\r'): 6461 lines[linenum] = lines[linenum].rstrip('\r') 6462 crlf_lines.append(linenum + 1) 6463 else: 6464 lf_lines.append(linenum + 1) 6465 6466 except IOError: 6467 _cpplint_state.PrintError( 6468 "Skipping input '%s': Can't open for reading\n" % filename) 6469 _RestoreFilters() 6470 return 6471 6472 # Note, if no dot is found, this will give the entire filename as the ext. 6473 file_extension = filename[filename.rfind('.') + 1:] 6474 6475 # When reading from stdin, the extension is unknown, so no cpplint tests 6476 # should rely on the extension. 6477 if filename != '-' and file_extension not in GetAllExtensions(): 6478 _cpplint_state.PrintError('Ignoring %s; not a valid file name ' 6479 '(%s)\n' % (filename, ', '.join(GetAllExtensions()))) 6480 else: 6481 ProcessFileData(filename, file_extension, lines, Error, 6482 extra_check_functions) 6483 6484 # If end-of-line sequences are a mix of LF and CR-LF, issue 6485 # warnings on the lines with CR. 6486 # 6487 # Don't issue any warnings if all lines are uniformly LF or CR-LF, 6488 # since critique can handle these just fine, and the style guide 6489 # doesn't dictate a particular end of line sequence. 6490 # 6491 # We can't depend on os.linesep to determine what the desired 6492 # end-of-line sequence should be, since that will return the 6493 # server-side end-of-line sequence. 6494 if lf_lines and crlf_lines: 6495 # Warn on every line with CR. An alternative approach might be to 6496 # check whether the file is mostly CRLF or just LF, and warn on the 6497 # minority, we bias toward LF here since most tools prefer LF. 6498 for linenum in crlf_lines: 6499 Error(filename, linenum, 'whitespace/newline', 1, 6500 'Unexpected \\r (^M) found; better to use only \\n') 6501 6502 # Suppress printing anything if --quiet was passed unless the error 6503 # count has increased after processing this file. 6504 if not _cpplint_state.quiet or old_errors != _cpplint_state.error_count: 6505 _cpplint_state.PrintInfo('Done processing %s\n' % filename) 6506 _RestoreFilters() 6507 6508 6509def PrintUsage(message): 6510 """Prints a brief usage string and exits, optionally with an error message. 6511 6512 Args: 6513 message: The optional error message. 6514 """ 6515 sys.stderr.write(_USAGE % (list(GetAllExtensions()), 6516 ','.join(list(GetAllExtensions())), 6517 GetHeaderExtensions(), 6518 ','.join(GetHeaderExtensions()))) 6519 6520 if message: 6521 sys.exit('\nFATAL ERROR: ' + message) 6522 else: 6523 sys.exit(0) 6524 6525def PrintVersion(): 6526 sys.stdout.write('Cpplint fork (https://github.com/cpplint/cpplint)\n') 6527 sys.stdout.write('cpplint ' + __VERSION__ + '\n') 6528 sys.stdout.write('Python ' + sys.version + '\n') 6529 sys.exit(0) 6530 6531def PrintCategories(): 6532 """Prints a list of all the error-categories used by error messages. 6533 6534 These are the categories used to filter messages via --filter. 6535 """ 6536 sys.stderr.write(''.join(' %s\n' % cat for cat in _ERROR_CATEGORIES)) 6537 sys.exit(0) 6538 6539 6540def ParseArguments(args): 6541 """Parses the command line arguments. 6542 6543 This may set the output format and verbosity level as side-effects. 6544 6545 Args: 6546 args: The command line arguments: 6547 6548 Returns: 6549 The list of filenames to lint. 6550 """ 6551 try: 6552 (opts, filenames) = getopt.getopt(args, '', ['help', 'output=', 'verbose=', 6553 'v=', 6554 'version', 6555 'counting=', 6556 'filter=', 6557 'root=', 6558 'repository=', 6559 'linelength=', 6560 'extensions=', 6561 'exclude=', 6562 'recursive', 6563 'headers=', 6564 'quiet']) 6565 except getopt.GetoptError: 6566 PrintUsage('Invalid arguments.') 6567 6568 verbosity = _VerboseLevel() 6569 output_format = _OutputFormat() 6570 filters = '' 6571 quiet = _Quiet() 6572 counting_style = '' 6573 recursive = False 6574 6575 for (opt, val) in opts: 6576 if opt == '--help': 6577 PrintUsage(None) 6578 if opt == '--version': 6579 PrintVersion() 6580 elif opt == '--output': 6581 if val not in ('emacs', 'vs7', 'eclipse', 'junit'): 6582 PrintUsage('The only allowed output formats are emacs, vs7, eclipse ' 6583 'and junit.') 6584 output_format = val 6585 elif opt == '--quiet': 6586 quiet = True 6587 elif opt == '--verbose' or opt == '--v': 6588 verbosity = int(val) 6589 elif opt == '--filter': 6590 filters = val 6591 if not filters: 6592 PrintCategories() 6593 elif opt == '--counting': 6594 if val not in ('total', 'toplevel', 'detailed'): 6595 PrintUsage('Valid counting options are total, toplevel, and detailed') 6596 counting_style = val 6597 elif opt == '--root': 6598 global _root 6599 _root = val 6600 elif opt == '--repository': 6601 global _repository 6602 _repository = val 6603 elif opt == '--linelength': 6604 global _line_length 6605 try: 6606 _line_length = int(val) 6607 except ValueError: 6608 PrintUsage('Line length must be digits.') 6609 elif opt == '--exclude': 6610 global _excludes 6611 if not _excludes: 6612 _excludes = set() 6613 _excludes.update(glob.glob(val)) 6614 elif opt == '--extensions': 6615 ProcessExtensionsOption(val) 6616 elif opt == '--headers': 6617 ProcessHppHeadersOption(val) 6618 elif opt == '--recursive': 6619 recursive = True 6620 6621 if not filenames: 6622 PrintUsage('No files were specified.') 6623 6624 if recursive: 6625 filenames = _ExpandDirectories(filenames) 6626 6627 if _excludes: 6628 filenames = _FilterExcludedFiles(filenames) 6629 6630 _SetOutputFormat(output_format) 6631 _SetQuiet(quiet) 6632 _SetVerboseLevel(verbosity) 6633 _SetFilters(filters) 6634 _SetCountingStyle(counting_style) 6635 6636 return filenames 6637 6638def _ExpandDirectories(filenames): 6639 """Searches a list of filenames and replaces directories in the list with 6640 all files descending from those directories. Files with extensions not in 6641 the valid extensions list are excluded. 6642 6643 Args: 6644 filenames: A list of files or directories 6645 6646 Returns: 6647 A list of all files that are members of filenames or descended from a 6648 directory in filenames 6649 """ 6650 expanded = set() 6651 for filename in filenames: 6652 if not os.path.isdir(filename): 6653 expanded.add(filename) 6654 continue 6655 6656 for root, _, files in os.walk(filename): 6657 for loopfile in files: 6658 fullname = os.path.join(root, loopfile) 6659 if fullname.startswith('.' + os.path.sep): 6660 fullname = fullname[len('.' + os.path.sep):] 6661 expanded.add(fullname) 6662 6663 filtered = [] 6664 for filename in expanded: 6665 if os.path.splitext(filename)[1][1:] in GetAllExtensions(): 6666 filtered.append(filename) 6667 return filtered 6668 6669def _FilterExcludedFiles(fnames): 6670 """Filters out files listed in the --exclude command line switch. File paths 6671 in the switch are evaluated relative to the current working directory 6672 """ 6673 exclude_paths = [os.path.abspath(f) for f in _excludes] 6674 # because globbing does not work recursively, exclude all subpath of all excluded entries 6675 return [f for f in fnames 6676 if not any(e for e in exclude_paths 6677 if _IsParentOrSame(e, os.path.abspath(f)))] 6678 6679def _IsParentOrSame(parent, child): 6680 """Return true if child is subdirectory of parent. 6681 Assumes both paths are absolute and don't contain symlinks. 6682 """ 6683 parent = os.path.normpath(parent) 6684 child = os.path.normpath(child) 6685 if parent == child: 6686 return True 6687 6688 prefix = os.path.commonprefix([parent, child]) 6689 if prefix != parent: 6690 return False 6691 # Note: os.path.commonprefix operates on character basis, so 6692 # take extra care of situations like '/foo/ba' and '/foo/bar/baz' 6693 child_suffix = child[len(prefix):] 6694 child_suffix = child_suffix.lstrip(os.sep) 6695 return child == os.path.join(prefix, child_suffix) 6696 6697def main(): 6698 filenames = ParseArguments(sys.argv[1:]) 6699 backup_err = sys.stderr 6700 try: 6701 # Change stderr to write with replacement characters so we don't die 6702 # if we try to print something containing non-ASCII characters. 6703 sys.stderr = codecs.StreamReader(sys.stderr, 'replace') 6704 6705 _cpplint_state.ResetErrorCounts() 6706 for filename in filenames: 6707 ProcessFile(filename, _cpplint_state.verbose_level) 6708 # If --quiet is passed, suppress printing error count unless there are errors. 6709 if not _cpplint_state.quiet or _cpplint_state.error_count > 0: 6710 _cpplint_state.PrintErrorCounts() 6711 6712 if _cpplint_state.output_format == 'junit': 6713 sys.stderr.write(_cpplint_state.FormatJUnitXML()) 6714 6715 finally: 6716 sys.stderr = backup_err 6717 6718 sys.exit(_cpplint_state.error_count > 0) 6719 6720 6721if __name__ == '__main__': 6722 main() 6723