| OLD | NEW |
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # | 2 # |
| 3 # Copyright (c) 2009 Google Inc. All rights reserved. | 3 # Copyright (c) 2009 Google Inc. All rights reserved. |
| 4 # | 4 # |
| 5 # Redistribution and use in source and binary forms, with or without | 5 # Redistribution and use in source and binary forms, with or without |
| 6 # modification, are permitted provided that the following conditions are | 6 # modification, are permitted provided that the following conditions are |
| 7 # met: | 7 # met: |
| 8 # | 8 # |
| 9 # * Redistributions of source code must retain the above copyright | 9 # * Redistributions of source code must retain the above copyright |
| 10 # notice, this list of conditions and the following disclaimer. | 10 # notice, this list of conditions and the following disclaimer. |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 53 import unicodedata | 53 import unicodedata |
| 54 | 54 |
| 55 | 55 |
| 56 _USAGE = """ | 56 _USAGE = """ |
| 57 Syntax: cpplint.py [--verbose=#] [--output=vs7] [--filter=-x,+y,...] | 57 Syntax: cpplint.py [--verbose=#] [--output=vs7] [--filter=-x,+y,...] |
| 58 [--counting=total|toplevel|detailed] [--root=subdir] | 58 [--counting=total|toplevel|detailed] [--root=subdir] |
| 59 [--linelength=digits] | 59 [--linelength=digits] |
| 60 <file> [file] ... | 60 <file> [file] ... |
| 61 | 61 |
| 62 The style guidelines this tries to follow are those in | 62 The style guidelines this tries to follow are those in |
| 63 http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml | 63 https://google-styleguide.googlecode.com/svn/trunk/cppguide.xml |
| 64 | 64 |
| 65 Every problem is given a confidence score from 1-5, with 5 meaning we are | 65 Every problem is given a confidence score from 1-5, with 5 meaning we are |
| 66 certain of the problem, and 1 meaning it could be a legitimate construct. | 66 certain of the problem, and 1 meaning it could be a legitimate construct. |
| 67 This will miss some errors, and is not a substitute for a code review. | 67 This will miss some errors, and is not a substitute for a code review. |
| 68 | 68 |
| 69 To suppress false-positive errors of a certain category, add a | 69 To suppress false-positive errors of a certain category, add a |
| 70 'NOLINT(category)' comment to the line. NOLINT or NOLINT(*) | 70 'NOLINT(category)' comment to the line. NOLINT or NOLINT(*) |
| 71 suppresses errors of all categories on that line. | 71 suppresses errors of all categories on that line. |
| 72 | 72 |
| 73 The files passed in will be linted; at least one file must be provided. | 73 The files passed in will be linted; at least one file must be provided. |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 170 file is located) and all sub-directories. | 170 file is located) and all sub-directories. |
| 171 """ | 171 """ |
| 172 | 172 |
| 173 # We categorize each error message we print. Here are the categories. | 173 # We categorize each error message we print. Here are the categories. |
| 174 # We want an explicit list so we can list them all in cpplint --filter=. | 174 # We want an explicit list so we can list them all in cpplint --filter=. |
| 175 # If you add a new error message with a new category, add it to the list | 175 # If you add a new error message with a new category, add it to the list |
| 176 # here! cpplint_unittest.py should tell you if you forget to do this. | 176 # here! cpplint_unittest.py should tell you if you forget to do this. |
| 177 _ERROR_CATEGORIES = [ | 177 _ERROR_CATEGORIES = [ |
| 178 'build/class', | 178 'build/class', |
| 179 'build/c++11', | 179 'build/c++11', |
| 180 'build/c++14', |
| 181 'build/c++tr1', |
| 180 'build/deprecated', | 182 'build/deprecated', |
| 181 'build/endif_comment', | 183 'build/endif_comment', |
| 182 'build/explicit_make_pair', | 184 'build/explicit_make_pair', |
| 183 'build/forward_decl', | 185 'build/forward_decl', |
| 184 'build/header_guard', | 186 'build/header_guard', |
| 185 'build/include', | 187 'build/include', |
| 186 'build/include_alpha', | 188 'build/include_alpha', |
| 187 'build/include_order', | 189 'build/include_order', |
| 188 'build/include_what_you_use', | 190 'build/include_what_you_use', |
| 189 'build/namespaces', | 191 'build/namespaces', |
| 190 'build/printf_format', | 192 'build/printf_format', |
| 191 'build/storage_class', | 193 'build/storage_class', |
| 192 'legal/copyright', | 194 'legal/copyright', |
| 193 'readability/alt_tokens', | 195 'readability/alt_tokens', |
| 194 'readability/braces', | 196 'readability/braces', |
| 195 'readability/casting', | 197 'readability/casting', |
| 196 'readability/check', | 198 'readability/check', |
| 197 'readability/constructors', | 199 'readability/constructors', |
| 198 'readability/fn_size', | 200 'readability/fn_size', |
| 199 'readability/function', | |
| 200 'readability/inheritance', | 201 'readability/inheritance', |
| 201 'readability/multiline_comment', | 202 'readability/multiline_comment', |
| 202 'readability/multiline_string', | 203 'readability/multiline_string', |
| 203 'readability/namespace', | 204 'readability/namespace', |
| 204 'readability/nolint', | 205 'readability/nolint', |
| 205 'readability/nul', | 206 'readability/nul', |
| 206 'readability/strings', | 207 'readability/strings', |
| 207 'readability/todo', | 208 'readability/todo', |
| 208 'readability/utf8', | 209 'readability/utf8', |
| 209 'runtime/arrays', | 210 'runtime/arrays', |
| (...skipping 10 matching lines...) Expand all Loading... |
| 220 'runtime/printf_format', | 221 'runtime/printf_format', |
| 221 'runtime/references', | 222 'runtime/references', |
| 222 'runtime/string', | 223 'runtime/string', |
| 223 'runtime/threadsafe_fn', | 224 'runtime/threadsafe_fn', |
| 224 'runtime/vlog', | 225 'runtime/vlog', |
| 225 'whitespace/blank_line', | 226 'whitespace/blank_line', |
| 226 'whitespace/braces', | 227 'whitespace/braces', |
| 227 'whitespace/comma', | 228 'whitespace/comma', |
| 228 'whitespace/comments', | 229 'whitespace/comments', |
| 229 'whitespace/empty_conditional_body', | 230 'whitespace/empty_conditional_body', |
| 231 'whitespace/empty_if_body', |
| 230 'whitespace/empty_loop_body', | 232 'whitespace/empty_loop_body', |
| 231 'whitespace/end_of_line', | 233 'whitespace/end_of_line', |
| 232 'whitespace/ending_newline', | 234 'whitespace/ending_newline', |
| 233 'whitespace/forcolon', | 235 'whitespace/forcolon', |
| 234 'whitespace/indent', | 236 'whitespace/indent', |
| 235 'whitespace/line_length', | 237 'whitespace/line_length', |
| 236 'whitespace/newline', | 238 'whitespace/newline', |
| 237 'whitespace/operators', | 239 'whitespace/operators', |
| 238 'whitespace/parens', | 240 'whitespace/parens', |
| 239 'whitespace/semicolon', | 241 'whitespace/semicolon', |
| 240 'whitespace/tab', | 242 'whitespace/tab', |
| 241 'whitespace/todo', | 243 'whitespace/todo', |
| 242 ] | 244 ] |
| 243 | 245 |
| 244 # These error categories are no longer enforced by cpplint, but for backwards- | 246 # These error categories are no longer enforced by cpplint, but for backwards- |
| 245 # compatibility they may still appear in NOLINT comments. | 247 # compatibility they may still appear in NOLINT comments. |
| 246 _LEGACY_ERROR_CATEGORIES = [ | 248 _LEGACY_ERROR_CATEGORIES = [ |
| 247 'readability/streams', | 249 'readability/streams', |
| 250 'readability/function', |
| 248 ] | 251 ] |
| 249 | 252 |
| 250 # The default state of the category filter. This is overridden by the --filter= | 253 # The default state of the category filter. This is overridden by the --filter= |
| 251 # flag. By default all errors are on, so only add here categories that should be | 254 # flag. By default all errors are on, so only add here categories that should be |
| 252 # off by default (i.e., categories that must be enabled by the --filter= flags). | 255 # off by default (i.e., categories that must be enabled by the --filter= flags). |
| 253 # All entries here should start with a '-' or '+', as in the --filter= flag. | 256 # All entries here should start with a '-' or '+', as in the --filter= flag. |
| 254 _DEFAULT_FILTERS = ['-build/include_alpha'] | 257 _DEFAULT_FILTERS = ['-build/include_alpha'] |
| 255 | 258 |
| 259 # The default list of categories suppressed for C (not C++) files. |
| 260 _DEFAULT_C_SUPPRESSED_CATEGORIES = [ |
| 261 'readability/casting', |
| 262 ] |
| 263 |
| 264 # The default list of categories suppressed for Linux Kernel files. |
| 265 _DEFAULT_KERNEL_SUPPRESSED_CATEGORIES = [ |
| 266 'whitespace/tab', |
| 267 ] |
| 268 |
| 256 # We used to check for high-bit characters, but after much discussion we | 269 # We used to check for high-bit characters, but after much discussion we |
| 257 # decided those were OK, as long as they were in UTF-8 and didn't represent | 270 # decided those were OK, as long as they were in UTF-8 and didn't represent |
| 258 # hard-coded international strings, which belong in a separate i18n file. | 271 # hard-coded international strings, which belong in a separate i18n file. |
| 259 | 272 |
| 260 # C++ headers | 273 # C++ headers |
| 261 _CPP_HEADERS = frozenset([ | 274 _CPP_HEADERS = frozenset([ |
| 262 # Legacy | 275 # Legacy |
| 263 'algobase.h', | 276 'algobase.h', |
| 264 'algo.h', | 277 'algo.h', |
| 265 'alloc.h', | 278 'alloc.h', |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 339 'map', | 352 'map', |
| 340 'memory', | 353 'memory', |
| 341 'mutex', | 354 'mutex', |
| 342 'new', | 355 'new', |
| 343 'numeric', | 356 'numeric', |
| 344 'ostream', | 357 'ostream', |
| 345 'queue', | 358 'queue', |
| 346 'random', | 359 'random', |
| 347 'ratio', | 360 'ratio', |
| 348 'regex', | 361 'regex', |
| 362 'scoped_allocator', |
| 349 'set', | 363 'set', |
| 350 'sstream', | 364 'sstream', |
| 351 'stack', | 365 'stack', |
| 352 'stdexcept', | 366 'stdexcept', |
| 353 'streambuf', | 367 'streambuf', |
| 354 'string', | 368 'string', |
| 355 'strstream', | 369 'strstream', |
| 356 'system_error', | 370 'system_error', |
| 357 'thread', | 371 'thread', |
| 358 'tuple', | 372 'tuple', |
| (...skipping 27 matching lines...) Expand all Loading... |
| 386 'cstdio', | 400 'cstdio', |
| 387 'cstdlib', | 401 'cstdlib', |
| 388 'cstring', | 402 'cstring', |
| 389 'ctgmath', | 403 'ctgmath', |
| 390 'ctime', | 404 'ctime', |
| 391 'cuchar', | 405 'cuchar', |
| 392 'cwchar', | 406 'cwchar', |
| 393 'cwctype', | 407 'cwctype', |
| 394 ]) | 408 ]) |
| 395 | 409 |
| 410 # Type names |
| 411 _TYPES = re.compile( |
| 412 r'^(?:' |
| 413 # [dcl.type.simple] |
| 414 r'(char(16_t|32_t)?)|wchar_t|' |
| 415 r'bool|short|int|long|signed|unsigned|float|double|' |
| 416 # [support.types] |
| 417 r'(ptrdiff_t|size_t|max_align_t|nullptr_t)|' |
| 418 # [cstdint.syn] |
| 419 r'(u?int(_fast|_least)?(8|16|32|64)_t)|' |
| 420 r'(u?int(max|ptr)_t)|' |
| 421 r')$') |
| 422 |
| 396 | 423 |
| 397 # These headers are excluded from [build/include] and [build/include_order] | 424 # These headers are excluded from [build/include] and [build/include_order] |
| 398 # checks: | 425 # checks: |
| 399 # - Anything not following google file name conventions (containing an | 426 # - Anything not following google file name conventions (containing an |
| 400 # uppercase character, such as Python.h or nsStringAPI.h, for example). | 427 # uppercase character, such as Python.h or nsStringAPI.h, for example). |
| 401 # - Lua headers. | 428 # - Lua headers. |
| 402 _THIRD_PARTY_HEADERS_PATTERN = re.compile( | 429 _THIRD_PARTY_HEADERS_PATTERN = re.compile( |
| 403 r'^(?:[^/]*[A-Z][^/]*\.h|lua\.h|lauxlib\.h|lualib\.h)$') | 430 r'^(?:[^/]*[A-Z][^/]*\.h|lua\.h|lauxlib\.h|lualib\.h)$') |
| 404 | 431 |
| 432 # Pattern for matching FileInfo.BaseName() against test file name |
| 433 _TEST_FILE_SUFFIX = r'(_test|_unittest|_regtest)$' |
| 434 |
| 435 # Pattern that matches only complete whitespace, possibly across multiple lines. |
| 436 _EMPTY_CONDITIONAL_BODY_PATTERN = re.compile(r'^\s*$', re.DOTALL) |
| 405 | 437 |
| 406 # Assertion macros. These are defined in base/logging.h and | 438 # Assertion macros. These are defined in base/logging.h and |
| 407 # testing/base/gunit.h. Note that the _M versions need to come first | 439 # testing/base/public/gunit.h. |
| 408 # for substring matching to work. | |
| 409 _CHECK_MACROS = [ | 440 _CHECK_MACROS = [ |
| 410 'DCHECK', 'CHECK', | 441 'DCHECK', 'CHECK', |
| 411 'EXPECT_TRUE_M', 'EXPECT_TRUE', | 442 'EXPECT_TRUE', 'ASSERT_TRUE', |
| 412 'ASSERT_TRUE_M', 'ASSERT_TRUE', | 443 'EXPECT_FALSE', 'ASSERT_FALSE', |
| 413 'EXPECT_FALSE_M', 'EXPECT_FALSE', | |
| 414 'ASSERT_FALSE_M', 'ASSERT_FALSE', | |
| 415 ] | 444 ] |
| 416 | 445 |
| 417 # Replacement macros for CHECK/DCHECK/EXPECT_TRUE/EXPECT_FALSE | 446 # Replacement macros for CHECK/DCHECK/EXPECT_TRUE/EXPECT_FALSE |
| 418 _CHECK_REPLACEMENT = dict([(m, {}) for m in _CHECK_MACROS]) | 447 _CHECK_REPLACEMENT = dict([(m, {}) for m in _CHECK_MACROS]) |
| 419 | 448 |
| 420 for op, replacement in [('==', 'EQ'), ('!=', 'NE'), | 449 for op, replacement in [('==', 'EQ'), ('!=', 'NE'), |
| 421 ('>=', 'GE'), ('>', 'GT'), | 450 ('>=', 'GE'), ('>', 'GT'), |
| 422 ('<=', 'LE'), ('<', 'LT')]: | 451 ('<=', 'LE'), ('<', 'LT')]: |
| 423 _CHECK_REPLACEMENT['DCHECK'][op] = 'DCHECK_%s' % replacement | 452 _CHECK_REPLACEMENT['DCHECK'][op] = 'DCHECK_%s' % replacement |
| 424 _CHECK_REPLACEMENT['CHECK'][op] = 'CHECK_%s' % replacement | 453 _CHECK_REPLACEMENT['CHECK'][op] = 'CHECK_%s' % replacement |
| 425 _CHECK_REPLACEMENT['EXPECT_TRUE'][op] = 'EXPECT_%s' % replacement | 454 _CHECK_REPLACEMENT['EXPECT_TRUE'][op] = 'EXPECT_%s' % replacement |
| 426 _CHECK_REPLACEMENT['ASSERT_TRUE'][op] = 'ASSERT_%s' % replacement | 455 _CHECK_REPLACEMENT['ASSERT_TRUE'][op] = 'ASSERT_%s' % replacement |
| 427 _CHECK_REPLACEMENT['EXPECT_TRUE_M'][op] = 'EXPECT_%s_M' % replacement | |
| 428 _CHECK_REPLACEMENT['ASSERT_TRUE_M'][op] = 'ASSERT_%s_M' % replacement | |
| 429 | 456 |
| 430 for op, inv_replacement in [('==', 'NE'), ('!=', 'EQ'), | 457 for op, inv_replacement in [('==', 'NE'), ('!=', 'EQ'), |
| 431 ('>=', 'LT'), ('>', 'LE'), | 458 ('>=', 'LT'), ('>', 'LE'), |
| 432 ('<=', 'GT'), ('<', 'GE')]: | 459 ('<=', 'GT'), ('<', 'GE')]: |
| 433 _CHECK_REPLACEMENT['EXPECT_FALSE'][op] = 'EXPECT_%s' % inv_replacement | 460 _CHECK_REPLACEMENT['EXPECT_FALSE'][op] = 'EXPECT_%s' % inv_replacement |
| 434 _CHECK_REPLACEMENT['ASSERT_FALSE'][op] = 'ASSERT_%s' % inv_replacement | 461 _CHECK_REPLACEMENT['ASSERT_FALSE'][op] = 'ASSERT_%s' % inv_replacement |
| 435 _CHECK_REPLACEMENT['EXPECT_FALSE_M'][op] = 'EXPECT_%s_M' % inv_replacement | |
| 436 _CHECK_REPLACEMENT['ASSERT_FALSE_M'][op] = 'ASSERT_%s_M' % inv_replacement | |
| 437 | 462 |
| 438 # Alternative tokens and their replacements. For full list, see section 2.5 | 463 # Alternative tokens and their replacements. For full list, see section 2.5 |
| 439 # Alternative tokens [lex.digraph] in the C++ standard. | 464 # Alternative tokens [lex.digraph] in the C++ standard. |
| 440 # | 465 # |
| 441 # Digraphs (such as '%:') are not included here since it's a mess to | 466 # Digraphs (such as '%:') are not included here since it's a mess to |
| 442 # match those on a word boundary. | 467 # match those on a word boundary. |
| 443 _ALT_TOKEN_REPLACEMENT = { | 468 _ALT_TOKEN_REPLACEMENT = { |
| 444 'and': '&&', | 469 'and': '&&', |
| 445 'bitor': '|', | 470 'bitor': '|', |
| 446 'or': '||', | 471 'or': '||', |
| (...skipping 28 matching lines...) Expand all Loading... |
| 475 _NO_ASM = 0 # Outside of inline assembly block | 500 _NO_ASM = 0 # Outside of inline assembly block |
| 476 _INSIDE_ASM = 1 # Inside inline assembly block | 501 _INSIDE_ASM = 1 # Inside inline assembly block |
| 477 _END_ASM = 2 # Last line of inline assembly block | 502 _END_ASM = 2 # Last line of inline assembly block |
| 478 _BLOCK_ASM = 3 # The whole block is an inline assembly block | 503 _BLOCK_ASM = 3 # The whole block is an inline assembly block |
| 479 | 504 |
| 480 # Match start of assembly blocks | 505 # Match start of assembly blocks |
| 481 _MATCH_ASM = re.compile(r'^\s*(?:asm|_asm|__asm|__asm__)' | 506 _MATCH_ASM = re.compile(r'^\s*(?:asm|_asm|__asm|__asm__)' |
| 482 r'(?:\s+(volatile|__volatile__))?' | 507 r'(?:\s+(volatile|__volatile__))?' |
| 483 r'\s*[{(]') | 508 r'\s*[{(]') |
| 484 | 509 |
| 510 # Match strings that indicate we're working on a C (not C++) file. |
| 511 _SEARCH_C_FILE = re.compile(r'\b(?:LINT_C_FILE|' |
| 512 r'vim?:\s*.*(\s*|:)filetype=c(\s*|:|$))') |
| 513 |
| 514 # Match string that indicates we're working on a Linux Kernel file. |
| 515 _SEARCH_KERNEL_FILE = re.compile(r'\b(?:LINT_KERNEL_FILE)') |
| 485 | 516 |
| 486 _regexp_compile_cache = {} | 517 _regexp_compile_cache = {} |
| 487 | 518 |
| 488 # {str, set(int)}: a map from error categories to sets of linenumbers | 519 # {str, set(int)}: a map from error categories to sets of linenumbers |
| 489 # on which those errors are expected and should be suppressed. | 520 # on which those errors are expected and should be suppressed. |
| 490 _error_suppressions = {} | 521 _error_suppressions = {} |
| 491 | 522 |
| 492 # The root directory used for deriving header guard CPP variable. | 523 # The root directory used for deriving header guard CPP variable. |
| 493 # This is set by --root flag. | 524 # This is set by --root flag. |
| 494 _root = None | 525 _root = None |
| 495 | 526 |
| 496 # The allowed line length of files. | 527 # The allowed line length of files. |
| 497 # This is set by --linelength flag. | 528 # This is set by --linelength flag. |
| 498 _line_length = 80 | 529 _line_length = 80 |
| 499 | 530 |
| 500 # The allowed extensions for file names | 531 # The allowed extensions for file names |
| 501 # This is set by --extensions flag. | 532 # This is set by --extensions flag. |
| 502 _valid_extensions = set(['cc', 'h', 'cpp', 'cu', 'cuh']) | 533 _valid_extensions = set(['cc', 'h', 'cpp', 'cu', 'cuh']) |
| 503 | 534 |
| 535 # {str, bool}: a map from error categories to booleans which indicate if the |
| 536 # category should be suppressed for every line. |
| 537 _global_error_suppressions = {} |
| 538 |
| 539 |
| 504 def ParseNolintSuppressions(filename, raw_line, linenum, error): | 540 def ParseNolintSuppressions(filename, raw_line, linenum, error): |
| 505 """Updates the global list of error-suppressions. | 541 """Updates the global list of line error-suppressions. |
| 506 | 542 |
| 507 Parses any NOLINT comments on the current line, updating the global | 543 Parses any NOLINT comments on the current line, updating the global |
| 508 error_suppressions store. Reports an error if the NOLINT comment | 544 error_suppressions store. Reports an error if the NOLINT comment |
| 509 was malformed. | 545 was malformed. |
| 510 | 546 |
| 511 Args: | 547 Args: |
| 512 filename: str, the name of the input file. | 548 filename: str, the name of the input file. |
| 513 raw_line: str, the line of input text, with comments. | 549 raw_line: str, the line of input text, with comments. |
| 514 linenum: int, the number of the current line. | 550 linenum: int, the number of the current line. |
| 515 error: function, an error handler. | 551 error: function, an error handler. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 526 else: | 562 else: |
| 527 if category.startswith('(') and category.endswith(')'): | 563 if category.startswith('(') and category.endswith(')'): |
| 528 category = category[1:-1] | 564 category = category[1:-1] |
| 529 if category in _ERROR_CATEGORIES: | 565 if category in _ERROR_CATEGORIES: |
| 530 _error_suppressions.setdefault(category, set()).add(suppressed_line) | 566 _error_suppressions.setdefault(category, set()).add(suppressed_line) |
| 531 elif category not in _LEGACY_ERROR_CATEGORIES: | 567 elif category not in _LEGACY_ERROR_CATEGORIES: |
| 532 error(filename, linenum, 'readability/nolint', 5, | 568 error(filename, linenum, 'readability/nolint', 5, |
| 533 'Unknown NOLINT error category: %s' % category) | 569 'Unknown NOLINT error category: %s' % category) |
| 534 | 570 |
| 535 | 571 |
| 572 def ProcessGlobalSuppresions(lines): |
| 573 """Updates the list of global error suppressions. |
| 574 |
| 575 Parses any lint directives in the file that have global effect. |
| 576 |
| 577 Args: |
| 578 lines: An array of strings, each representing a line of the file, with the |
| 579 last element being empty if the file is terminated with a newline. |
| 580 """ |
| 581 for line in lines: |
| 582 if _SEARCH_C_FILE.search(line): |
| 583 for category in _DEFAULT_C_SUPPRESSED_CATEGORIES: |
| 584 _global_error_suppressions[category] = True |
| 585 if _SEARCH_KERNEL_FILE.search(line): |
| 586 for category in _DEFAULT_KERNEL_SUPPRESSED_CATEGORIES: |
| 587 _global_error_suppressions[category] = True |
| 588 |
| 589 |
| 536 def ResetNolintSuppressions(): | 590 def ResetNolintSuppressions(): |
| 537 """Resets the set of NOLINT suppressions to empty.""" | 591 """Resets the set of NOLINT suppressions to empty.""" |
| 538 _error_suppressions.clear() | 592 _error_suppressions.clear() |
| 593 _global_error_suppressions.clear() |
| 539 | 594 |
| 540 | 595 |
| 541 def IsErrorSuppressedByNolint(category, linenum): | 596 def IsErrorSuppressedByNolint(category, linenum): |
| 542 """Returns true if the specified error category is suppressed on this line. | 597 """Returns true if the specified error category is suppressed on this line. |
| 543 | 598 |
| 544 Consults the global error_suppressions map populated by | 599 Consults the global error_suppressions map populated by |
| 545 ParseNolintSuppressions/ResetNolintSuppressions. | 600 ParseNolintSuppressions/ProcessGlobalSuppresions/ResetNolintSuppressions. |
| 546 | 601 |
| 547 Args: | 602 Args: |
| 548 category: str, the category of the error. | 603 category: str, the category of the error. |
| 549 linenum: int, the current line number. | 604 linenum: int, the current line number. |
| 550 Returns: | 605 Returns: |
| 551 bool, True iff the error should be suppressed due to a NOLINT comment. | 606 bool, True iff the error should be suppressed due to a NOLINT comment or |
| 607 global suppression. |
| 552 """ | 608 """ |
| 553 return (linenum in _error_suppressions.get(category, set()) or | 609 return (_global_error_suppressions.get(category, False) or |
| 610 linenum in _error_suppressions.get(category, set()) or |
| 554 linenum in _error_suppressions.get(None, set())) | 611 linenum in _error_suppressions.get(None, set())) |
| 555 | 612 |
| 556 | 613 |
| 557 def Match(pattern, s): | 614 def Match(pattern, s): |
| 558 """Matches the string with the pattern, caching the compiled regexp.""" | 615 """Matches the string with the pattern, caching the compiled regexp.""" |
| 559 # The regexp compilation caching is inlined in both Match and Search for | 616 # The regexp compilation caching is inlined in both Match and Search for |
| 560 # performance reasons; factoring it out into a separate function turns out | 617 # performance reasons; factoring it out into a separate function turns out |
| 561 # to be noticeably expensive. | 618 # to be noticeably expensive. |
| 562 if pattern not in _regexp_compile_cache: | 619 if pattern not in _regexp_compile_cache: |
| 563 _regexp_compile_cache[pattern] = sre_compile.compile(pattern) | 620 _regexp_compile_cache[pattern] = sre_compile.compile(pattern) |
| (...skipping 18 matching lines...) Expand all Loading... |
| 582 return _regexp_compile_cache[pattern].sub(rep, s) | 639 return _regexp_compile_cache[pattern].sub(rep, s) |
| 583 | 640 |
| 584 | 641 |
| 585 def Search(pattern, s): | 642 def Search(pattern, s): |
| 586 """Searches the string for the pattern, caching the compiled regexp.""" | 643 """Searches the string for the pattern, caching the compiled regexp.""" |
| 587 if pattern not in _regexp_compile_cache: | 644 if pattern not in _regexp_compile_cache: |
| 588 _regexp_compile_cache[pattern] = sre_compile.compile(pattern) | 645 _regexp_compile_cache[pattern] = sre_compile.compile(pattern) |
| 589 return _regexp_compile_cache[pattern].search(s) | 646 return _regexp_compile_cache[pattern].search(s) |
| 590 | 647 |
| 591 | 648 |
| 649 def _IsSourceExtension(s): |
| 650 """File extension (excluding dot) matches a source file extension.""" |
| 651 return s in ('c', 'cc', 'cpp', 'cxx') |
| 652 |
| 653 |
| 592 class _IncludeState(object): | 654 class _IncludeState(object): |
| 593 """Tracks line numbers for includes, and the order in which includes appear. | 655 """Tracks line numbers for includes, and the order in which includes appear. |
| 594 | 656 |
| 595 include_list contains list of lists of (header, line number) pairs. | 657 include_list contains list of lists of (header, line number) pairs. |
| 596 It's a lists of lists rather than just one flat list to make it | 658 It's a lists of lists rather than just one flat list to make it |
| 597 easier to update across preprocessor boundaries. | 659 easier to update across preprocessor boundaries. |
| 598 | 660 |
| 599 Call CheckNextIncludeOrder() once for each header in the file, passing | 661 Call CheckNextIncludeOrder() once for each header in the file, passing |
| 600 in the type constants defined above. Calls in an illegal order will | 662 in the type constants defined above. Calls in an illegal order will |
| 601 raise an _IncludeError with an appropriate error message. | 663 raise an _IncludeError with an appropriate error message. |
| (...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 937 self.lines_in_function += 1 | 999 self.lines_in_function += 1 |
| 938 | 1000 |
| 939 def Check(self, error, filename, linenum): | 1001 def Check(self, error, filename, linenum): |
| 940 """Report if too many lines in function body. | 1002 """Report if too many lines in function body. |
| 941 | 1003 |
| 942 Args: | 1004 Args: |
| 943 error: The function to call with any errors found. | 1005 error: The function to call with any errors found. |
| 944 filename: The name of the current file. | 1006 filename: The name of the current file. |
| 945 linenum: The number of the line to check. | 1007 linenum: The number of the line to check. |
| 946 """ | 1008 """ |
| 1009 if not self.in_a_function: |
| 1010 return |
| 1011 |
| 947 if Match(r'T(EST|est)', self.current_function): | 1012 if Match(r'T(EST|est)', self.current_function): |
| 948 base_trigger = self._TEST_TRIGGER | 1013 base_trigger = self._TEST_TRIGGER |
| 949 else: | 1014 else: |
| 950 base_trigger = self._NORMAL_TRIGGER | 1015 base_trigger = self._NORMAL_TRIGGER |
| 951 trigger = base_trigger * 2**_VerboseLevel() | 1016 trigger = base_trigger * 2**_VerboseLevel() |
| 952 | 1017 |
| 953 if self.lines_in_function > trigger: | 1018 if self.lines_in_function > trigger: |
| 954 error_level = int(math.log(self.lines_in_function / base_trigger, 2)) | 1019 error_level = int(math.log(self.lines_in_function / base_trigger, 2)) |
| 955 # 50 => 0, 100 => 1, 200 => 2, 400 => 3, 800 => 4, 1600 => 5, ... | 1020 # 50 => 0, 100 => 1, 200 => 2, 400 => 3, 800 => 4, 1600 => 5, ... |
| 956 if error_level > 5: | 1021 if error_level > 5: |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1051 def Extension(self): | 1116 def Extension(self): |
| 1052 """File extension - text following the final period.""" | 1117 """File extension - text following the final period.""" |
| 1053 return self.Split()[2] | 1118 return self.Split()[2] |
| 1054 | 1119 |
| 1055 def NoExtension(self): | 1120 def NoExtension(self): |
| 1056 """File has no source file extension.""" | 1121 """File has no source file extension.""" |
| 1057 return '/'.join(self.Split()[0:2]) | 1122 return '/'.join(self.Split()[0:2]) |
| 1058 | 1123 |
| 1059 def IsSource(self): | 1124 def IsSource(self): |
| 1060 """File has a source file extension.""" | 1125 """File has a source file extension.""" |
| 1061 return self.Extension()[1:] in ('c', 'cc', 'cpp', 'cxx') | 1126 return _IsSourceExtension(self.Extension()[1:]) |
| 1062 | 1127 |
| 1063 | 1128 |
| 1064 def _ShouldPrintError(category, confidence, linenum): | 1129 def _ShouldPrintError(category, confidence, linenum): |
| 1065 """If confidence >= verbose, category passes filter and is not suppressed.""" | 1130 """If confidence >= verbose, category passes filter and is not suppressed.""" |
| 1066 | 1131 |
| 1067 # There are three ways we might decide not to print an error message: | 1132 # There are three ways we might decide not to print an error message: |
| 1068 # a "NOLINT(category)" comment appears in the source, | 1133 # a "NOLINT(category)" comment appears in the source, |
| 1069 # the verbosity level isn't high enough, or the filters filter it out. | 1134 # the verbosity level isn't high enough, or the filters filter it out. |
| 1070 if IsErrorSuppressedByNolint(category, linenum): | 1135 if IsErrorSuppressedByNolint(category, linenum): |
| 1071 return False | 1136 return False |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1197 else: | 1262 else: |
| 1198 # Haven't found the end yet, append a blank line. | 1263 # Haven't found the end yet, append a blank line. |
| 1199 line = '""' | 1264 line = '""' |
| 1200 | 1265 |
| 1201 # Look for beginning of a raw string, and replace them with | 1266 # Look for beginning of a raw string, and replace them with |
| 1202 # empty strings. This is done in a loop to handle multiple raw | 1267 # empty strings. This is done in a loop to handle multiple raw |
| 1203 # strings on the same line. | 1268 # strings on the same line. |
| 1204 while delimiter is None: | 1269 while delimiter is None: |
| 1205 # Look for beginning of a raw string. | 1270 # Look for beginning of a raw string. |
| 1206 # See 2.14.15 [lex.string] for syntax. | 1271 # See 2.14.15 [lex.string] for syntax. |
| 1207 matched = Match(r'^(.*)\b(?:R|u8R|uR|UR|LR)"([^\s\\()]*)\((.*)$', line) | 1272 # |
| 1208 if matched: | 1273 # Once we have matched a raw string, we check the prefix of the |
| 1274 # line to make sure that the line is not part of a single line |
| 1275 # comment. It's done this way because we remove raw strings |
| 1276 # before removing comments as opposed to removing comments |
| 1277 # before removing raw strings. This is because there are some |
| 1278 # cpplint checks that requires the comments to be preserved, but |
| 1279 # we don't want to check comments that are inside raw strings. |
| 1280 matched = Match(r'^(.*?)\b(?:R|u8R|uR|UR|LR)"([^\s\\()]*)\((.*)$', line) |
| 1281 if (matched and |
| 1282 not Match(r'^([^\'"]|\'(\\.|[^\'])*\'|"(\\.|[^"])*")*//', |
| 1283 matched.group(1))): |
| 1209 delimiter = ')' + matched.group(2) + '"' | 1284 delimiter = ')' + matched.group(2) + '"' |
| 1210 | 1285 |
| 1211 end = matched.group(3).find(delimiter) | 1286 end = matched.group(3).find(delimiter) |
| 1212 if end >= 0: | 1287 if end >= 0: |
| 1213 # Raw string ended on same line | 1288 # Raw string ended on same line |
| 1214 line = (matched.group(1) + '""' + | 1289 line = (matched.group(1) + '""' + |
| 1215 matched.group(3)[end + len(delimiter):]) | 1290 matched.group(3)[end + len(delimiter):]) |
| 1216 delimiter = None | 1291 delimiter = None |
| 1217 else: | 1292 else: |
| 1218 # Start of a multi-line raw string | 1293 # Start of a multi-line raw string |
| (...skipping 550 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1769 | 1844 |
| 1770 # Didn't find anything | 1845 # Didn't find anything |
| 1771 error(filename, endif_linenum, 'build/header_guard', 5, | 1846 error(filename, endif_linenum, 'build/header_guard', 5, |
| 1772 '#endif line should be "#endif // %s"' % cppvar) | 1847 '#endif line should be "#endif // %s"' % cppvar) |
| 1773 | 1848 |
| 1774 | 1849 |
| 1775 def CheckHeaderFileIncluded(filename, include_state, error): | 1850 def CheckHeaderFileIncluded(filename, include_state, error): |
| 1776 """Logs an error if a .cc file does not include its header.""" | 1851 """Logs an error if a .cc file does not include its header.""" |
| 1777 | 1852 |
| 1778 # Do not check test files | 1853 # Do not check test files |
| 1779 if filename.endswith('_test.cc') or filename.endswith('_unittest.cc'): | 1854 fileinfo = FileInfo(filename) |
| 1855 if Search(_TEST_FILE_SUFFIX, fileinfo.BaseName()): |
| 1780 return | 1856 return |
| 1781 | 1857 |
| 1782 fileinfo = FileInfo(filename) | 1858 headerfile = filename[0:len(filename) - len(fileinfo.Extension())] + '.h' |
| 1783 headerfile = filename[0:len(filename) - 2] + 'h' | |
| 1784 if not os.path.exists(headerfile): | 1859 if not os.path.exists(headerfile): |
| 1785 return | 1860 return |
| 1786 headername = FileInfo(headerfile).RepositoryName() | 1861 headername = FileInfo(headerfile).RepositoryName() |
| 1787 first_include = 0 | 1862 first_include = 0 |
| 1788 for section_list in include_state.include_list: | 1863 for section_list in include_state.include_list: |
| 1789 for f in section_list: | 1864 for f in section_list: |
| 1790 if headername in f[0] or f[0] in headername: | 1865 if headername in f[0] or f[0] in headername: |
| 1791 return | 1866 return |
| 1792 if not first_include: | 1867 if not first_include: |
| 1793 first_include = f[1] | 1868 first_include = f[1] |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1990 return False | 2065 return False |
| 1991 | 2066 |
| 1992 | 2067 |
| 1993 def IsForwardClassDeclaration(clean_lines, linenum): | 2068 def IsForwardClassDeclaration(clean_lines, linenum): |
| 1994 return Match(r'^\s*(\btemplate\b)*.*class\s+\w+;\s*$', clean_lines[linenum]) | 2069 return Match(r'^\s*(\btemplate\b)*.*class\s+\w+;\s*$', clean_lines[linenum]) |
| 1995 | 2070 |
| 1996 | 2071 |
| 1997 class _BlockInfo(object): | 2072 class _BlockInfo(object): |
| 1998 """Stores information about a generic block of code.""" | 2073 """Stores information about a generic block of code.""" |
| 1999 | 2074 |
| 2000 def __init__(self, seen_open_brace): | 2075 def __init__(self, linenum, seen_open_brace): |
| 2076 self.starting_linenum = linenum |
| 2001 self.seen_open_brace = seen_open_brace | 2077 self.seen_open_brace = seen_open_brace |
| 2002 self.open_parentheses = 0 | 2078 self.open_parentheses = 0 |
| 2003 self.inline_asm = _NO_ASM | 2079 self.inline_asm = _NO_ASM |
| 2004 self.check_namespace_indentation = False | 2080 self.check_namespace_indentation = False |
| 2005 | 2081 |
| 2006 def CheckBegin(self, filename, clean_lines, linenum, error): | 2082 def CheckBegin(self, filename, clean_lines, linenum, error): |
| 2007 """Run checks that applies to text up to the opening brace. | 2083 """Run checks that applies to text up to the opening brace. |
| 2008 | 2084 |
| 2009 This is mostly for checking the text after the class identifier | 2085 This is mostly for checking the text after the class identifier |
| 2010 and the "{", usually where the base class is specified. For other | 2086 and the "{", usually where the base class is specified. For other |
| (...skipping 28 matching lines...) Expand all Loading... |
| 2039 | 2115 |
| 2040 Returns: | 2116 Returns: |
| 2041 True for this class, False for derived classes. | 2117 True for this class, False for derived classes. |
| 2042 """ | 2118 """ |
| 2043 return self.__class__ == _BlockInfo | 2119 return self.__class__ == _BlockInfo |
| 2044 | 2120 |
| 2045 | 2121 |
| 2046 class _ExternCInfo(_BlockInfo): | 2122 class _ExternCInfo(_BlockInfo): |
| 2047 """Stores information about an 'extern "C"' block.""" | 2123 """Stores information about an 'extern "C"' block.""" |
| 2048 | 2124 |
| 2049 def __init__(self): | 2125 def __init__(self, linenum): |
| 2050 _BlockInfo.__init__(self, True) | 2126 _BlockInfo.__init__(self, linenum, True) |
| 2051 | 2127 |
| 2052 | 2128 |
| 2053 class _ClassInfo(_BlockInfo): | 2129 class _ClassInfo(_BlockInfo): |
| 2054 """Stores information about a class.""" | 2130 """Stores information about a class.""" |
| 2055 | 2131 |
| 2056 def __init__(self, name, class_or_struct, clean_lines, linenum): | 2132 def __init__(self, name, class_or_struct, clean_lines, linenum): |
| 2057 _BlockInfo.__init__(self, False) | 2133 _BlockInfo.__init__(self, linenum, False) |
| 2058 self.name = name | 2134 self.name = name |
| 2059 self.starting_linenum = linenum | |
| 2060 self.is_derived = False | 2135 self.is_derived = False |
| 2061 self.check_namespace_indentation = True | 2136 self.check_namespace_indentation = True |
| 2062 if class_or_struct == 'struct': | 2137 if class_or_struct == 'struct': |
| 2063 self.access = 'public' | 2138 self.access = 'public' |
| 2064 self.is_struct = True | 2139 self.is_struct = True |
| 2065 else: | 2140 else: |
| 2066 self.access = 'private' | 2141 self.access = 'private' |
| 2067 self.is_struct = False | 2142 self.is_struct = False |
| 2068 | 2143 |
| 2069 # Remember initial indentation level for this class. Using raw_lines here | 2144 # Remember initial indentation level for this class. Using raw_lines here |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2117 else: | 2192 else: |
| 2118 parent = 'class ' + self.name | 2193 parent = 'class ' + self.name |
| 2119 error(filename, linenum, 'whitespace/indent', 3, | 2194 error(filename, linenum, 'whitespace/indent', 3, |
| 2120 'Closing brace should be aligned with beginning of %s' % parent) | 2195 'Closing brace should be aligned with beginning of %s' % parent) |
| 2121 | 2196 |
| 2122 | 2197 |
| 2123 class _NamespaceInfo(_BlockInfo): | 2198 class _NamespaceInfo(_BlockInfo): |
| 2124 """Stores information about a namespace.""" | 2199 """Stores information about a namespace.""" |
| 2125 | 2200 |
| 2126 def __init__(self, name, linenum): | 2201 def __init__(self, name, linenum): |
| 2127 _BlockInfo.__init__(self, False) | 2202 _BlockInfo.__init__(self, linenum, False) |
| 2128 self.name = name or '' | 2203 self.name = name or '' |
| 2129 self.starting_linenum = linenum | |
| 2130 self.check_namespace_indentation = True | 2204 self.check_namespace_indentation = True |
| 2131 | 2205 |
| 2132 def CheckEnd(self, filename, clean_lines, linenum, error): | 2206 def CheckEnd(self, filename, clean_lines, linenum, error): |
| 2133 """Check end of namespace comments.""" | 2207 """Check end of namespace comments.""" |
| 2134 line = clean_lines.raw_lines[linenum] | 2208 line = clean_lines.raw_lines[linenum] |
| 2135 | 2209 |
| 2136 # Check how many lines is enclosed in this namespace. Don't issue | 2210 # Check how many lines is enclosed in this namespace. Don't issue |
| 2137 # warning for missing namespace comments if there aren't enough | 2211 # warning for missing namespace comments if there aren't enough |
| 2138 # lines. However, do apply checks if there is already an end of | 2212 # lines. However, do apply checks if there is already an end of |
| 2139 # namespace comment and it's incorrect. | 2213 # namespace comment and it's incorrect. |
| 2140 # | 2214 # |
| 2141 # TODO(unknown): We always want to check end of namespace comments | 2215 # TODO(unknown): We always want to check end of namespace comments |
| 2142 # if a namespace is large, but sometimes we also want to apply the | 2216 # if a namespace is large, but sometimes we also want to apply the |
| 2143 # check if a short namespace contained nontrivial things (something | 2217 # check if a short namespace contained nontrivial things (something |
| 2144 # other than forward declarations). There is currently no logic on | 2218 # other than forward declarations). There is currently no logic on |
| 2145 # deciding what these nontrivial things are, so this check is | 2219 # deciding what these nontrivial things are, so this check is |
| 2146 # triggered by namespace size only, which works most of the time. | 2220 # triggered by namespace size only, which works most of the time. |
| 2147 if (linenum - self.starting_linenum < 10 | 2221 if (linenum - self.starting_linenum < 10 |
| 2148 and not Match(r'};*\s*(//|/\*).*\bnamespace\b', line)): | 2222 and not Match(r'^\s*};*\s*(//|/\*).*\bnamespace\b', line)): |
| 2149 return | 2223 return |
| 2150 | 2224 |
| 2151 # Look for matching comment at end of namespace. | 2225 # Look for matching comment at end of namespace. |
| 2152 # | 2226 # |
| 2153 # Note that we accept C style "/* */" comments for terminating | 2227 # Note that we accept C style "/* */" comments for terminating |
| 2154 # namespaces, so that code that terminate namespaces inside | 2228 # namespaces, so that code that terminate namespaces inside |
| 2155 # preprocessor macros can be cpplint clean. | 2229 # preprocessor macros can be cpplint clean. |
| 2156 # | 2230 # |
| 2157 # We also accept stuff like "// end of namespace <name>." with the | 2231 # We also accept stuff like "// end of namespace <name>." with the |
| 2158 # period at the end. | 2232 # period at the end. |
| 2159 # | 2233 # |
| 2160 # Besides these, we don't accept anything else, otherwise we might | 2234 # Besides these, we don't accept anything else, otherwise we might |
| 2161 # get false negatives when existing comment is a substring of the | 2235 # get false negatives when existing comment is a substring of the |
| 2162 # expected namespace. | 2236 # expected namespace. |
| 2163 if self.name: | 2237 if self.name: |
| 2164 # Named namespace | 2238 # Named namespace |
| 2165 if not Match((r'};*\s*(//|/\*).*\bnamespace\s+' + re.escape(self.name) + | 2239 if not Match((r'^\s*};*\s*(//|/\*).*\bnamespace\s+' + |
| 2166 r'[\*/\.\\\s]*$'), | 2240 re.escape(self.name) + r'[\*/\.\\\s]*$'), |
| 2167 line): | 2241 line): |
| 2168 error(filename, linenum, 'readability/namespace', 5, | 2242 error(filename, linenum, 'readability/namespace', 5, |
| 2169 'Namespace should be terminated with "// namespace %s"' % | 2243 'Namespace should be terminated with "// namespace %s"' % |
| 2170 self.name) | 2244 self.name) |
| 2171 else: | 2245 else: |
| 2172 # Anonymous namespace | 2246 # Anonymous namespace |
| 2173 if not Match(r'};*\s*(//|/\*).*\bnamespace[\*/\.\\\s]*$', line): | 2247 if not Match(r'^\s*};*\s*(//|/\*).*\bnamespace[\*/\.\\\s]*$', line): |
| 2174 # If "// namespace anonymous" or "// anonymous namespace (more text)", | 2248 # If "// namespace anonymous" or "// anonymous namespace (more text)", |
| 2175 # mention "// anonymous namespace" as an acceptable form | 2249 # mention "// anonymous namespace" as an acceptable form |
| 2176 if Match(r'}.*\b(namespace anonymous|anonymous namespace)\b', line): | 2250 if Match(r'^\s*}.*\b(namespace anonymous|anonymous namespace)\b', line): |
| 2177 error(filename, linenum, 'readability/namespace', 5, | 2251 error(filename, linenum, 'readability/namespace', 5, |
| 2178 'Anonymous namespace should be terminated with "// namespace"' | 2252 'Anonymous namespace should be terminated with "// namespace"' |
| 2179 ' or "// anonymous namespace"') | 2253 ' or "// anonymous namespace"') |
| 2180 else: | 2254 else: |
| 2181 error(filename, linenum, 'readability/namespace', 5, | 2255 error(filename, linenum, 'readability/namespace', 5, |
| 2182 'Anonymous namespace should be terminated with "// namespace"') | 2256 'Anonymous namespace should be terminated with "// namespace"') |
| 2183 | 2257 |
| 2184 | 2258 |
| 2185 class _PreprocessorInfo(object): | 2259 class _PreprocessorInfo(object): |
| 2186 """Stores checkpoints of nesting stacks when #if/#else is seen.""" | 2260 """Stores checkpoints of nesting stacks when #if/#else is seen.""" |
| (...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2505 break | 2579 break |
| 2506 | 2580 |
| 2507 token = matched.group(1) | 2581 token = matched.group(1) |
| 2508 if token == '{': | 2582 if token == '{': |
| 2509 # If namespace or class hasn't seen a opening brace yet, mark | 2583 # If namespace or class hasn't seen a opening brace yet, mark |
| 2510 # namespace/class head as complete. Push a new block onto the | 2584 # namespace/class head as complete. Push a new block onto the |
| 2511 # stack otherwise. | 2585 # stack otherwise. |
| 2512 if not self.SeenOpenBrace(): | 2586 if not self.SeenOpenBrace(): |
| 2513 self.stack[-1].seen_open_brace = True | 2587 self.stack[-1].seen_open_brace = True |
| 2514 elif Match(r'^extern\s*"[^"]*"\s*\{', line): | 2588 elif Match(r'^extern\s*"[^"]*"\s*\{', line): |
| 2515 self.stack.append(_ExternCInfo()) | 2589 self.stack.append(_ExternCInfo(linenum)) |
| 2516 else: | 2590 else: |
| 2517 self.stack.append(_BlockInfo(True)) | 2591 self.stack.append(_BlockInfo(linenum, True)) |
| 2518 if _MATCH_ASM.match(line): | 2592 if _MATCH_ASM.match(line): |
| 2519 self.stack[-1].inline_asm = _BLOCK_ASM | 2593 self.stack[-1].inline_asm = _BLOCK_ASM |
| 2520 | 2594 |
| 2521 elif token == ';' or token == ')': | 2595 elif token == ';' or token == ')': |
| 2522 # If we haven't seen an opening brace yet, but we already saw | 2596 # If we haven't seen an opening brace yet, but we already saw |
| 2523 # a semicolon, this is probably a forward declaration. Pop | 2597 # a semicolon, this is probably a forward declaration. Pop |
| 2524 # the stack for these. | 2598 # the stack for these. |
| 2525 # | 2599 # |
| 2526 # Similarly, if we haven't seen an opening brace yet, but we | 2600 # Similarly, if we haven't seen an opening brace yet, but we |
| 2527 # already saw a closing parenthesis, then these are probably | 2601 # already saw a closing parenthesis, then these are probably |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2619 | 2693 |
| 2620 # For the rest, work with both comments and strings removed. | 2694 # For the rest, work with both comments and strings removed. |
| 2621 line = clean_lines.elided[linenum] | 2695 line = clean_lines.elided[linenum] |
| 2622 | 2696 |
| 2623 if Search(r'\b(const|volatile|void|char|short|int|long' | 2697 if Search(r'\b(const|volatile|void|char|short|int|long' |
| 2624 r'|float|double|signed|unsigned' | 2698 r'|float|double|signed|unsigned' |
| 2625 r'|schar|u?int8|u?int16|u?int32|u?int64)' | 2699 r'|schar|u?int8|u?int16|u?int32|u?int64)' |
| 2626 r'\s+(register|static|extern|typedef)\b', | 2700 r'\s+(register|static|extern|typedef)\b', |
| 2627 line): | 2701 line): |
| 2628 error(filename, linenum, 'build/storage_class', 5, | 2702 error(filename, linenum, 'build/storage_class', 5, |
| 2629 'Storage class (static, extern, typedef, etc) should be first.') | 2703 'Storage-class specifier (static, extern, typedef, etc) should be ' |
| 2704 'at the beginning of the declaration.') |
| 2630 | 2705 |
| 2631 if Match(r'\s*#\s*endif\s*[^/\s]+', line): | 2706 if Match(r'\s*#\s*endif\s*[^/\s]+', line): |
| 2632 error(filename, linenum, 'build/endif_comment', 5, | 2707 error(filename, linenum, 'build/endif_comment', 5, |
| 2633 'Uncommented text after #endif is non-standard. Use a comment.') | 2708 'Uncommented text after #endif is non-standard. Use a comment.') |
| 2634 | 2709 |
| 2635 if Match(r'\s*class\s+(\w+\s*::\s*)+\w+\s*;', line): | 2710 if Match(r'\s*class\s+(\w+\s*::\s*)+\w+\s*;', line): |
| 2636 error(filename, linenum, 'build/forward_decl', 5, | 2711 error(filename, linenum, 'build/forward_decl', 5, |
| 2637 'Inner-style forward declarations are invalid. Remove this line.') | 2712 'Inner-style forward declarations are invalid. Remove this line.') |
| 2638 | 2713 |
| 2639 if Search(r'(\w+|[+-]?\d+(\.\d*)?)\s*(<|>)\?=?\s*(\w+|[+-]?\d+)(\.\d*)?', | 2714 if Search(r'(\w+|[+-]?\d+(\.\d*)?)\s*(<|>)\?=?\s*(\w+|[+-]?\d+)(\.\d*)?', |
| (...skipping 18 matching lines...) Expand all Loading... |
| 2658 # the class head is not completed yet. | 2733 # the class head is not completed yet. |
| 2659 classinfo = nesting_state.InnermostClass() | 2734 classinfo = nesting_state.InnermostClass() |
| 2660 if not classinfo or not classinfo.seen_open_brace: | 2735 if not classinfo or not classinfo.seen_open_brace: |
| 2661 return | 2736 return |
| 2662 | 2737 |
| 2663 # The class may have been declared with namespace or classname qualifiers. | 2738 # The class may have been declared with namespace or classname qualifiers. |
| 2664 # The constructor and destructor will not have those qualifiers. | 2739 # The constructor and destructor will not have those qualifiers. |
| 2665 base_classname = classinfo.name.split('::')[-1] | 2740 base_classname = classinfo.name.split('::')[-1] |
| 2666 | 2741 |
| 2667 # Look for single-argument constructors that aren't marked explicit. | 2742 # Look for single-argument constructors that aren't marked explicit. |
| 2668 # Technically a valid construct, but against style. Also look for | 2743 # Technically a valid construct, but against style. |
| 2669 # non-single-argument constructors which are also technically valid, but | |
| 2670 # strongly suggest something is wrong. | |
| 2671 explicit_constructor_match = Match( | 2744 explicit_constructor_match = Match( |
| 2672 r'\s+(?:inline\s+)?(explicit\s+)?(?:inline\s+)?%s\s*' | 2745 r'\s+(?:inline\s+)?(explicit\s+)?(?:inline\s+)?%s\s*' |
| 2673 r'\(((?:[^()]|\([^()]*\))*)\)' | 2746 r'\(((?:[^()]|\([^()]*\))*)\)' |
| 2674 % re.escape(base_classname), | 2747 % re.escape(base_classname), |
| 2675 line) | 2748 line) |
| 2676 | 2749 |
| 2677 if explicit_constructor_match: | 2750 if explicit_constructor_match: |
| 2678 is_marked_explicit = explicit_constructor_match.group(1) | 2751 is_marked_explicit = explicit_constructor_match.group(1) |
| 2679 | 2752 |
| 2680 if not explicit_constructor_match.group(2): | 2753 if not explicit_constructor_match.group(2): |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2721 error(filename, linenum, 'runtime/explicit', 5, | 2794 error(filename, linenum, 'runtime/explicit', 5, |
| 2722 'Constructors callable with one argument ' | 2795 'Constructors callable with one argument ' |
| 2723 'should be marked explicit.') | 2796 'should be marked explicit.') |
| 2724 else: | 2797 else: |
| 2725 error(filename, linenum, 'runtime/explicit', 5, | 2798 error(filename, linenum, 'runtime/explicit', 5, |
| 2726 'Single-parameter constructors should be marked explicit.') | 2799 'Single-parameter constructors should be marked explicit.') |
| 2727 elif is_marked_explicit and not onearg_constructor: | 2800 elif is_marked_explicit and not onearg_constructor: |
| 2728 if noarg_constructor: | 2801 if noarg_constructor: |
| 2729 error(filename, linenum, 'runtime/explicit', 5, | 2802 error(filename, linenum, 'runtime/explicit', 5, |
| 2730 'Zero-parameter constructors should not be marked explicit.') | 2803 'Zero-parameter constructors should not be marked explicit.') |
| 2731 else: | |
| 2732 error(filename, linenum, 'runtime/explicit', 0, | |
| 2733 'Constructors that require multiple arguments ' | |
| 2734 'should not be marked explicit.') | |
| 2735 | 2804 |
| 2736 | 2805 |
| 2737 def CheckSpacingForFunctionCall(filename, clean_lines, linenum, error): | 2806 def CheckSpacingForFunctionCall(filename, clean_lines, linenum, error): |
| 2738 """Checks for the correctness of various spacing around function calls. | 2807 """Checks for the correctness of various spacing around function calls. |
| 2739 | 2808 |
| 2740 Args: | 2809 Args: |
| 2741 filename: The name of the current file. | 2810 filename: The name of the current file. |
| 2742 clean_lines: A CleansedLines instance containing the file. | 2811 clean_lines: A CleansedLines instance containing the file. |
| 2743 linenum: The number of the line to check. | 2812 linenum: The number of the line to check. |
| 2744 error: The function to call with any errors found. | 2813 error: The function to call with any errors found. |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2779 not Search(r' \([^)]+\)\([^)]*(\)|,$)', fncall) and | 2848 not Search(r' \([^)]+\)\([^)]*(\)|,$)', fncall) and |
| 2780 # Ignore pointers/references to arrays. | 2849 # Ignore pointers/references to arrays. |
| 2781 not Search(r' \([^)]+\)\[[^\]]+\]', fncall)): | 2850 not Search(r' \([^)]+\)\[[^\]]+\]', fncall)): |
| 2782 if Search(r'\w\s*\(\s(?!\s*\\$)', fncall): # a ( used for a fn call | 2851 if Search(r'\w\s*\(\s(?!\s*\\$)', fncall): # a ( used for a fn call |
| 2783 error(filename, linenum, 'whitespace/parens', 4, | 2852 error(filename, linenum, 'whitespace/parens', 4, |
| 2784 'Extra space after ( in function call') | 2853 'Extra space after ( in function call') |
| 2785 elif Search(r'\(\s+(?!(\s*\\)|\()', fncall): | 2854 elif Search(r'\(\s+(?!(\s*\\)|\()', fncall): |
| 2786 error(filename, linenum, 'whitespace/parens', 2, | 2855 error(filename, linenum, 'whitespace/parens', 2, |
| 2787 'Extra space after (') | 2856 'Extra space after (') |
| 2788 if (Search(r'\w\s+\(', fncall) and | 2857 if (Search(r'\w\s+\(', fncall) and |
| 2858 not Search(r'_{0,2}asm_{0,2}\s+_{0,2}volatile_{0,2}\s+\(', fncall) and |
| 2789 not Search(r'#\s*define|typedef|using\s+\w+\s*=', fncall) and | 2859 not Search(r'#\s*define|typedef|using\s+\w+\s*=', fncall) and |
| 2790 not Search(r'\w\s+\((\w+::)*\*\w+\)\(', fncall) and | 2860 not Search(r'\w\s+\((\w+::)*\*\w+\)\(', fncall) and |
| 2791 not Search(r'\bcase\s+\(', fncall)): | 2861 not Search(r'\bcase\s+\(', fncall)): |
| 2792 # TODO(unknown): Space after an operator function seem to be a common | 2862 # TODO(unknown): Space after an operator function seem to be a common |
| 2793 # error, silence those for now by restricting them to highest verbosity. | 2863 # error, silence those for now by restricting them to highest verbosity. |
| 2794 if Search(r'\boperator_*\b', line): | 2864 if Search(r'\boperator_*\b', line): |
| 2795 error(filename, linenum, 'whitespace/parens', 0, | 2865 error(filename, linenum, 'whitespace/parens', 0, |
| 2796 'Extra space before ( in function call') | 2866 'Extra space before ( in function call') |
| 2797 else: | 2867 else: |
| 2798 error(filename, linenum, 'whitespace/parens', 4, | 2868 error(filename, linenum, 'whitespace/parens', 4, |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2837 clean_lines.elided, line): | 2907 clean_lines.elided, line): |
| 2838 CheckItemIndentationInNamespace(filename, clean_lines.elided, | 2908 CheckItemIndentationInNamespace(filename, clean_lines.elided, |
| 2839 line, error) | 2909 line, error) |
| 2840 | 2910 |
| 2841 | 2911 |
| 2842 def CheckForFunctionLengths(filename, clean_lines, linenum, | 2912 def CheckForFunctionLengths(filename, clean_lines, linenum, |
| 2843 function_state, error): | 2913 function_state, error): |
| 2844 """Reports for long function bodies. | 2914 """Reports for long function bodies. |
| 2845 | 2915 |
| 2846 For an overview why this is done, see: | 2916 For an overview why this is done, see: |
| 2847 http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Write_Short_Fun
ctions | 2917 https://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Write_Short_Fu
nctions |
| 2848 | 2918 |
| 2849 Uses a simplistic algorithm assuming other style guidelines | 2919 Uses a simplistic algorithm assuming other style guidelines |
| 2850 (especially spacing) are followed. | 2920 (especially spacing) are followed. |
| 2851 Only checks unindented functions, so class members are unchecked. | 2921 Only checks unindented functions, so class members are unchecked. |
| 2852 Trivial bodies are unchecked, so constructors with huge initializer lists | 2922 Trivial bodies are unchecked, so constructors with huge initializer lists |
| 2853 may be missed. | 2923 may be missed. |
| 2854 Blank/comment lines are not counted so as to avoid encouraging the removal | 2924 Blank/comment lines are not counted so as to avoid encouraging the removal |
| 2855 of vertical space and comments just to get through a lint check. | 2925 of vertical space and comments just to get through a lint check. |
| 2856 NOLINT *on the last line of a function* disables this check. | 2926 NOLINT *on the last line of a function* disables this check. |
| 2857 | 2927 |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2916 Args: | 2986 Args: |
| 2917 line: The line in question. | 2987 line: The line in question. |
| 2918 filename: The name of the current file. | 2988 filename: The name of the current file. |
| 2919 linenum: The number of the line to check. | 2989 linenum: The number of the line to check. |
| 2920 next_line_start: The first non-whitespace column of the next line. | 2990 next_line_start: The first non-whitespace column of the next line. |
| 2921 error: The function to call with any errors found. | 2991 error: The function to call with any errors found. |
| 2922 """ | 2992 """ |
| 2923 commentpos = line.find('//') | 2993 commentpos = line.find('//') |
| 2924 if commentpos != -1: | 2994 if commentpos != -1: |
| 2925 # Check if the // may be in quotes. If so, ignore it | 2995 # Check if the // may be in quotes. If so, ignore it |
| 2926 # Comparisons made explicit for clarity -- pylint: disable=g-explicit-bool-c
omparison | 2996 if re.sub(r'\\.', '', line[0:commentpos]).count('"') % 2 == 0: |
| 2927 if (line.count('"', 0, commentpos) - | |
| 2928 line.count('\\"', 0, commentpos)) % 2 == 0: # not in quotes | |
| 2929 # Allow one space for new scopes, two spaces otherwise: | 2997 # Allow one space for new scopes, two spaces otherwise: |
| 2930 if (not (Match(r'^.*{ *//', line) and next_line_start == commentpos) and | 2998 if (not (Match(r'^.*{ *//', line) and next_line_start == commentpos) and |
| 2931 ((commentpos >= 1 and | 2999 ((commentpos >= 1 and |
| 2932 line[commentpos-1] not in string.whitespace) or | 3000 line[commentpos-1] not in string.whitespace) or |
| 2933 (commentpos >= 2 and | 3001 (commentpos >= 2 and |
| 2934 line[commentpos-2] not in string.whitespace))): | 3002 line[commentpos-2] not in string.whitespace))): |
| 2935 error(filename, linenum, 'whitespace/comments', 2, | 3003 error(filename, linenum, 'whitespace/comments', 2, |
| 2936 'At least two spaces is best between code and comments') | 3004 'At least two spaces is best between code and comments') |
| 2937 | 3005 |
| 2938 # Checks for common mistakes in TODO comments. | 3006 # Checks for common mistakes in TODO comments. |
| (...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3167 | 3235 |
| 3168 # You should always have whitespace around binary operators. | 3236 # You should always have whitespace around binary operators. |
| 3169 # | 3237 # |
| 3170 # Check <= and >= first to avoid false positives with < and >, then | 3238 # Check <= and >= first to avoid false positives with < and >, then |
| 3171 # check non-include lines for spacing around < and >. | 3239 # check non-include lines for spacing around < and >. |
| 3172 # | 3240 # |
| 3173 # If the operator is followed by a comma, assume it's be used in a | 3241 # If the operator is followed by a comma, assume it's be used in a |
| 3174 # macro context and don't do any checks. This avoids false | 3242 # macro context and don't do any checks. This avoids false |
| 3175 # positives. | 3243 # positives. |
| 3176 # | 3244 # |
| 3177 # Note that && is not included here. Those are checked separately | 3245 # Note that && is not included here. This is because there are too |
| 3178 # in CheckRValueReference | 3246 # many false positives due to RValue references. |
| 3179 match = Search(r'[^<>=!\s](==|!=|<=|>=|\|\|)[^<>=!\s,;\)]', line) | 3247 match = Search(r'[^<>=!\s](==|!=|<=|>=|\|\|)[^<>=!\s,;\)]', line) |
| 3180 if match: | 3248 if match: |
| 3181 error(filename, linenum, 'whitespace/operators', 3, | 3249 error(filename, linenum, 'whitespace/operators', 3, |
| 3182 'Missing spaces around %s' % match.group(1)) | 3250 'Missing spaces around %s' % match.group(1)) |
| 3183 elif not Match(r'#.*include', line): | 3251 elif not Match(r'#.*include', line): |
| 3184 # Look for < that is not surrounded by spaces. This is only | 3252 # Look for < that is not surrounded by spaces. This is only |
| 3185 # triggered if both sides are missing spaces, even though | 3253 # triggered if both sides are missing spaces, even though |
| 3186 # technically should should flag if at least one side is missing a | 3254 # technically should should flag if at least one side is missing a |
| 3187 # space. This is done to avoid some false positives with shifts. | 3255 # space. This is done to avoid some false positives with shifts. |
| 3188 match = Match(r'^(.*[^\s<])<[^\s=<,]', line) | 3256 match = Match(r'^(.*[^\s<])<[^\s=<,]', line) |
| (...skipping 13 matching lines...) Expand all Loading... |
| 3202 clean_lines, linenum, len(match.group(1))) | 3270 clean_lines, linenum, len(match.group(1))) |
| 3203 if start_pos <= -1: | 3271 if start_pos <= -1: |
| 3204 error(filename, linenum, 'whitespace/operators', 3, | 3272 error(filename, linenum, 'whitespace/operators', 3, |
| 3205 'Missing spaces around >') | 3273 'Missing spaces around >') |
| 3206 | 3274 |
| 3207 # We allow no-spaces around << when used like this: 10<<20, but | 3275 # We allow no-spaces around << when used like this: 10<<20, but |
| 3208 # not otherwise (particularly, not when used as streams) | 3276 # not otherwise (particularly, not when used as streams) |
| 3209 # | 3277 # |
| 3210 # We also allow operators following an opening parenthesis, since | 3278 # We also allow operators following an opening parenthesis, since |
| 3211 # those tend to be macros that deal with operators. | 3279 # those tend to be macros that deal with operators. |
| 3212 match = Search(r'(operator|[^\s(<])(?:L|UL|ULL|l|ul|ull)?<<([^\s,=<])', line) | 3280 match = Search(r'(operator|[^\s(<])(?:L|UL|LL|ULL|l|ul|ll|ull)?<<([^\s,=<])',
line) |
| 3213 if (match and not (match.group(1).isdigit() and match.group(2).isdigit()) and | 3281 if (match and not (match.group(1).isdigit() and match.group(2).isdigit()) and |
| 3214 not (match.group(1) == 'operator' and match.group(2) == ';')): | 3282 not (match.group(1) == 'operator' and match.group(2) == ';')): |
| 3215 error(filename, linenum, 'whitespace/operators', 3, | 3283 error(filename, linenum, 'whitespace/operators', 3, |
| 3216 'Missing spaces around <<') | 3284 'Missing spaces around <<') |
| 3217 | 3285 |
| 3218 # We allow no-spaces around >> for almost anything. This is because | 3286 # We allow no-spaces around >> for almost anything. This is because |
| 3219 # C++11 allows ">>" to close nested templates, which accounts for | 3287 # C++11 allows ">>" to close nested templates, which accounts for |
| 3220 # most cases when ">>" is not followed by a space. | 3288 # most cases when ">>" is not followed by a space. |
| 3221 # | 3289 # |
| 3222 # We still warn on ">>" followed by alpha character, because that is | 3290 # We still warn on ">>" followed by alpha character, because that is |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3306 | 3374 |
| 3307 # You should always have a space after a semicolon | 3375 # You should always have a space after a semicolon |
| 3308 # except for few corner cases | 3376 # except for few corner cases |
| 3309 # TODO(unknown): clarify if 'if (1) { return 1;}' is requires one more | 3377 # TODO(unknown): clarify if 'if (1) { return 1;}' is requires one more |
| 3310 # space after ; | 3378 # space after ; |
| 3311 if Search(r';[^\s};\\)/]', line): | 3379 if Search(r';[^\s};\\)/]', line): |
| 3312 error(filename, linenum, 'whitespace/semicolon', 3, | 3380 error(filename, linenum, 'whitespace/semicolon', 3, |
| 3313 'Missing space after ;') | 3381 'Missing space after ;') |
| 3314 | 3382 |
| 3315 | 3383 |
| 3316 def CheckBracesSpacing(filename, clean_lines, linenum, error): | 3384 def _IsType(clean_lines, nesting_state, expr): |
| 3385 """Check if expression looks like a type name, returns true if so. |
| 3386 |
| 3387 Args: |
| 3388 clean_lines: A CleansedLines instance containing the file. |
| 3389 nesting_state: A NestingState instance which maintains information about |
| 3390 the current stack of nested blocks being parsed. |
| 3391 expr: The expression to check. |
| 3392 Returns: |
| 3393 True, if token looks like a type. |
| 3394 """ |
| 3395 # Keep only the last token in the expression |
| 3396 last_word = Match(r'^.*(\b\S+)$', expr) |
| 3397 if last_word: |
| 3398 token = last_word.group(1) |
| 3399 else: |
| 3400 token = expr |
| 3401 |
| 3402 # Match native types and stdint types |
| 3403 if _TYPES.match(token): |
| 3404 return True |
| 3405 |
| 3406 # Try a bit harder to match templated types. Walk up the nesting |
| 3407 # stack until we find something that resembles a typename |
| 3408 # declaration for what we are looking for. |
| 3409 typename_pattern = (r'\b(?:typename|class|struct)\s+' + re.escape(token) + |
| 3410 r'\b') |
| 3411 block_index = len(nesting_state.stack) - 1 |
| 3412 while block_index >= 0: |
| 3413 if isinstance(nesting_state.stack[block_index], _NamespaceInfo): |
| 3414 return False |
| 3415 |
| 3416 # Found where the opening brace is. We want to scan from this |
| 3417 # line up to the beginning of the function, minus a few lines. |
| 3418 # template <typename Type1, // stop scanning here |
| 3419 # ...> |
| 3420 # class C |
| 3421 # : public ... { // start scanning here |
| 3422 last_line = nesting_state.stack[block_index].starting_linenum |
| 3423 |
| 3424 next_block_start = 0 |
| 3425 if block_index > 0: |
| 3426 next_block_start = nesting_state.stack[block_index - 1].starting_linenum |
| 3427 first_line = last_line |
| 3428 while first_line >= next_block_start: |
| 3429 if clean_lines.elided[first_line].find('template') >= 0: |
| 3430 break |
| 3431 first_line -= 1 |
| 3432 if first_line < next_block_start: |
| 3433 # Didn't find any "template" keyword before reaching the next block, |
| 3434 # there are probably no template things to check for this block |
| 3435 block_index -= 1 |
| 3436 continue |
| 3437 |
| 3438 # Look for typename in the specified range |
| 3439 for i in xrange(first_line, last_line + 1, 1): |
| 3440 if Search(typename_pattern, clean_lines.elided[i]): |
| 3441 return True |
| 3442 block_index -= 1 |
| 3443 |
| 3444 return False |
| 3445 |
| 3446 |
| 3447 def CheckBracesSpacing(filename, clean_lines, linenum, nesting_state, error): |
| 3317 """Checks for horizontal spacing near commas. | 3448 """Checks for horizontal spacing near commas. |
| 3318 | 3449 |
| 3319 Args: | 3450 Args: |
| 3320 filename: The name of the current file. | 3451 filename: The name of the current file. |
| 3321 clean_lines: A CleansedLines instance containing the file. | 3452 clean_lines: A CleansedLines instance containing the file. |
| 3322 linenum: The number of the line to check. | 3453 linenum: The number of the line to check. |
| 3454 nesting_state: A NestingState instance which maintains information about |
| 3455 the current stack of nested blocks being parsed. |
| 3323 error: The function to call with any errors found. | 3456 error: The function to call with any errors found. |
| 3324 """ | 3457 """ |
| 3325 line = clean_lines.elided[linenum] | 3458 line = clean_lines.elided[linenum] |
| 3326 | 3459 |
| 3327 # Except after an opening paren, or after another opening brace (in case of | 3460 # Except after an opening paren, or after another opening brace (in case of |
| 3328 # an initializer list, for instance), you should have spaces before your | 3461 # an initializer list, for instance), you should have spaces before your |
| 3329 # braces. And since you should never have braces at the beginning of a line, | 3462 # braces when they are delimiting blocks, classes, namespaces etc. |
| 3330 # this is an easy test. | 3463 # And since you should never have braces at the beginning of a line, |
| 3464 # this is an easy test. Except that braces used for initialization don't |
| 3465 # follow the same rule; we often don't want spaces before those. |
| 3331 match = Match(r'^(.*[^ ({>]){', line) | 3466 match = Match(r'^(.*[^ ({>]){', line) |
| 3467 |
| 3332 if match: | 3468 if match: |
| 3333 # Try a bit harder to check for brace initialization. This | 3469 # Try a bit harder to check for brace initialization. This |
| 3334 # happens in one of the following forms: | 3470 # happens in one of the following forms: |
| 3335 # Constructor() : initializer_list_{} { ... } | 3471 # Constructor() : initializer_list_{} { ... } |
| 3336 # Constructor{}.MemberFunction() | 3472 # Constructor{}.MemberFunction() |
| 3337 # Type variable{}; | 3473 # Type variable{}; |
| 3338 # FunctionCall(type{}, ...); | 3474 # FunctionCall(type{}, ...); |
| 3339 # LastArgument(..., type{}); | 3475 # LastArgument(..., type{}); |
| 3340 # LOG(INFO) << type{} << " ..."; | 3476 # LOG(INFO) << type{} << " ..."; |
| 3341 # map_of_type[{...}] = ...; | 3477 # map_of_type[{...}] = ...; |
| 3342 # ternary = expr ? new type{} : nullptr; | 3478 # ternary = expr ? new type{} : nullptr; |
| 3343 # OuterTemplate<InnerTemplateConstructor<Type>{}> | 3479 # OuterTemplate<InnerTemplateConstructor<Type>{}> |
| 3344 # | 3480 # |
| 3345 # We check for the character following the closing brace, and | 3481 # We check for the character following the closing brace, and |
| 3346 # silence the warning if it's one of those listed above, i.e. | 3482 # silence the warning if it's one of those listed above, i.e. |
| 3347 # "{.;,)<>]:". | 3483 # "{.;,)<>]:". |
| 3348 # | 3484 # |
| 3349 # To account for nested initializer list, we allow any number of | 3485 # To account for nested initializer list, we allow any number of |
| 3350 # closing braces up to "{;,)<". We can't simply silence the | 3486 # closing braces up to "{;,)<". We can't simply silence the |
| 3351 # warning on first sight of closing brace, because that would | 3487 # warning on first sight of closing brace, because that would |
| 3352 # cause false negatives for things that are not initializer lists. | 3488 # cause false negatives for things that are not initializer lists. |
| 3353 # Silence this: But not this: | 3489 # Silence this: But not this: |
| 3354 # Outer{ if (...) { | 3490 # Outer{ if (...) { |
| 3355 # Inner{...} if (...){ // Missing space before { | 3491 # Inner{...} if (...){ // Missing space before { |
| 3356 # }; } | 3492 # }; } |
| 3357 # | 3493 # |
| 3358 # There is a false negative with this approach if people inserted | 3494 # There is a false negative with this approach if people inserted |
| 3359 # spurious semicolons, e.g. "if (cond){};", but we will catch the | 3495 # spurious semicolons, e.g. "if (cond){};", but we will catch the |
| 3360 # spurious semicolon with a separate check. | 3496 # spurious semicolon with a separate check. |
| 3497 leading_text = match.group(1) |
| 3361 (endline, endlinenum, endpos) = CloseExpression( | 3498 (endline, endlinenum, endpos) = CloseExpression( |
| 3362 clean_lines, linenum, len(match.group(1))) | 3499 clean_lines, linenum, len(match.group(1))) |
| 3363 trailing_text = '' | 3500 trailing_text = '' |
| 3364 if endpos > -1: | 3501 if endpos > -1: |
| 3365 trailing_text = endline[endpos:] | 3502 trailing_text = endline[endpos:] |
| 3366 for offset in xrange(endlinenum + 1, | 3503 for offset in xrange(endlinenum + 1, |
| 3367 min(endlinenum + 3, clean_lines.NumLines() - 1)): | 3504 min(endlinenum + 3, clean_lines.NumLines() - 1)): |
| 3368 trailing_text += clean_lines.elided[offset] | 3505 trailing_text += clean_lines.elided[offset] |
| 3369 if not Match(r'^[\s}]*[{.;,)<>\]:]', trailing_text): | 3506 # We also suppress warnings for `uint64_t{expression}` etc., as the style |
| 3507 # guide recommends brace initialization for integral types to avoid |
| 3508 # overflow/truncation. |
| 3509 if (not Match(r'^[\s}]*[{.;,)<>\]:]', trailing_text) |
| 3510 and not _IsType(clean_lines, nesting_state, leading_text)): |
| 3370 error(filename, linenum, 'whitespace/braces', 5, | 3511 error(filename, linenum, 'whitespace/braces', 5, |
| 3371 'Missing space before {') | 3512 'Missing space before {') |
| 3372 | 3513 |
| 3373 # Make sure '} else {' has spaces. | 3514 # Make sure '} else {' has spaces. |
| 3374 if Search(r'}else', line): | 3515 if Search(r'}else', line): |
| 3375 error(filename, linenum, 'whitespace/braces', 5, | 3516 error(filename, linenum, 'whitespace/braces', 5, |
| 3376 'Missing space before else') | 3517 'Missing space before else') |
| 3377 | 3518 |
| 3378 # You shouldn't have a space before a semicolon at the end of the line. | 3519 # You shouldn't have a space before a semicolon at the end of the line. |
| 3379 # There's a special case for "for" since the style guide allows space before | 3520 # There's a special case for "for" since the style guide allows space before |
| (...skipping 23 matching lines...) Expand all Loading... |
| 3403 True if this token is decltype() expression, False otherwise. | 3544 True if this token is decltype() expression, False otherwise. |
| 3404 """ | 3545 """ |
| 3405 (text, _, start_col) = ReverseCloseExpression(clean_lines, linenum, column) | 3546 (text, _, start_col) = ReverseCloseExpression(clean_lines, linenum, column) |
| 3406 if start_col < 0: | 3547 if start_col < 0: |
| 3407 return False | 3548 return False |
| 3408 if Search(r'\bdecltype\s*$', text[0:start_col]): | 3549 if Search(r'\bdecltype\s*$', text[0:start_col]): |
| 3409 return True | 3550 return True |
| 3410 return False | 3551 return False |
| 3411 | 3552 |
| 3412 | 3553 |
| 3413 def IsTemplateParameterList(clean_lines, linenum, column): | |
| 3414 """Check if the token ending on (linenum, column) is the end of template<>. | |
| 3415 | |
| 3416 Args: | |
| 3417 clean_lines: A CleansedLines instance containing the file. | |
| 3418 linenum: the number of the line to check. | |
| 3419 column: end column of the token to check. | |
| 3420 Returns: | |
| 3421 True if this token is end of a template parameter list, False otherwise. | |
| 3422 """ | |
| 3423 (_, startline, startpos) = ReverseCloseExpression( | |
| 3424 clean_lines, linenum, column) | |
| 3425 if (startpos > -1 and | |
| 3426 Search(r'\btemplate\s*$', clean_lines.elided[startline][0:startpos])): | |
| 3427 return True | |
| 3428 return False | |
| 3429 | |
| 3430 | |
| 3431 def IsRValueType(typenames, clean_lines, nesting_state, linenum, column): | |
| 3432 """Check if the token ending on (linenum, column) is a type. | |
| 3433 | |
| 3434 Assumes that text to the right of the column is "&&" or a function | |
| 3435 name. | |
| 3436 | |
| 3437 Args: | |
| 3438 typenames: set of type names from template-argument-list. | |
| 3439 clean_lines: A CleansedLines instance containing the file. | |
| 3440 nesting_state: A NestingState instance which maintains information about | |
| 3441 the current stack of nested blocks being parsed. | |
| 3442 linenum: the number of the line to check. | |
| 3443 column: end column of the token to check. | |
| 3444 Returns: | |
| 3445 True if this token is a type, False if we are not sure. | |
| 3446 """ | |
| 3447 prefix = clean_lines.elided[linenum][0:column] | |
| 3448 | |
| 3449 # Get one word to the left. If we failed to do so, this is most | |
| 3450 # likely not a type, since it's unlikely that the type name and "&&" | |
| 3451 # would be split across multiple lines. | |
| 3452 match = Match(r'^(.*)(\b\w+|[>*)&])\s*$', prefix) | |
| 3453 if not match: | |
| 3454 return False | |
| 3455 | |
| 3456 # Check text following the token. If it's "&&>" or "&&," or "&&...", it's | |
| 3457 # most likely a rvalue reference used inside a template. | |
| 3458 suffix = clean_lines.elided[linenum][column:] | |
| 3459 if Match(r'&&\s*(?:[>,]|\.\.\.)', suffix): | |
| 3460 return True | |
| 3461 | |
| 3462 # Check for known types and end of templates: | |
| 3463 # int&& variable | |
| 3464 # vector<int>&& variable | |
| 3465 # | |
| 3466 # Because this function is called recursively, we also need to | |
| 3467 # recognize pointer and reference types: | |
| 3468 # int* Function() | |
| 3469 # int& Function() | |
| 3470 if (match.group(2) in typenames or | |
| 3471 match.group(2) in ['char', 'char16_t', 'char32_t', 'wchar_t', 'bool', | |
| 3472 'short', 'int', 'long', 'signed', 'unsigned', | |
| 3473 'float', 'double', 'void', 'auto', '>', '*', '&']): | |
| 3474 return True | |
| 3475 | |
| 3476 # If we see a close parenthesis, look for decltype on the other side. | |
| 3477 # decltype would unambiguously identify a type, anything else is | |
| 3478 # probably a parenthesized expression and not a type. | |
| 3479 if match.group(2) == ')': | |
| 3480 return IsDecltype( | |
| 3481 clean_lines, linenum, len(match.group(1)) + len(match.group(2)) - 1) | |
| 3482 | |
| 3483 # Check for casts and cv-qualifiers. | |
| 3484 # match.group(1) remainder | |
| 3485 # -------------- --------- | |
| 3486 # const_cast< type&& | |
| 3487 # const type&& | |
| 3488 # type const&& | |
| 3489 if Search(r'\b(?:const_cast\s*<|static_cast\s*<|dynamic_cast\s*<|' | |
| 3490 r'reinterpret_cast\s*<|\w+\s)\s*$', | |
| 3491 match.group(1)): | |
| 3492 return True | |
| 3493 | |
| 3494 # Look for a preceding symbol that might help differentiate the context. | |
| 3495 # These are the cases that would be ambiguous: | |
| 3496 # match.group(1) remainder | |
| 3497 # -------------- --------- | |
| 3498 # Call ( expression && | |
| 3499 # Declaration ( type&& | |
| 3500 # sizeof ( type&& | |
| 3501 # if ( expression && | |
| 3502 # while ( expression && | |
| 3503 # for ( type&& | |
| 3504 # for( ; expression && | |
| 3505 # statement ; type&& | |
| 3506 # block { type&& | |
| 3507 # constructor { expression && | |
| 3508 start = linenum | |
| 3509 line = match.group(1) | |
| 3510 match_symbol = None | |
| 3511 while start >= 0: | |
| 3512 # We want to skip over identifiers and commas to get to a symbol. | |
| 3513 # Commas are skipped so that we can find the opening parenthesis | |
| 3514 # for function parameter lists. | |
| 3515 match_symbol = Match(r'^(.*)([^\w\s,])[\w\s,]*$', line) | |
| 3516 if match_symbol: | |
| 3517 break | |
| 3518 start -= 1 | |
| 3519 line = clean_lines.elided[start] | |
| 3520 | |
| 3521 if not match_symbol: | |
| 3522 # Probably the first statement in the file is an rvalue reference | |
| 3523 return True | |
| 3524 | |
| 3525 if match_symbol.group(2) == '}': | |
| 3526 # Found closing brace, probably an indicate of this: | |
| 3527 # block{} type&& | |
| 3528 return True | |
| 3529 | |
| 3530 if match_symbol.group(2) == ';': | |
| 3531 # Found semicolon, probably one of these: | |
| 3532 # for(; expression && | |
| 3533 # statement; type&& | |
| 3534 | |
| 3535 # Look for the previous 'for(' in the previous lines. | |
| 3536 before_text = match_symbol.group(1) | |
| 3537 for i in xrange(start - 1, max(start - 6, 0), -1): | |
| 3538 before_text = clean_lines.elided[i] + before_text | |
| 3539 if Search(r'for\s*\([^{};]*$', before_text): | |
| 3540 # This is the condition inside a for-loop | |
| 3541 return False | |
| 3542 | |
| 3543 # Did not find a for-init-statement before this semicolon, so this | |
| 3544 # is probably a new statement and not a condition. | |
| 3545 return True | |
| 3546 | |
| 3547 if match_symbol.group(2) == '{': | |
| 3548 # Found opening brace, probably one of these: | |
| 3549 # block{ type&& = ... ; } | |
| 3550 # constructor{ expression && expression } | |
| 3551 | |
| 3552 # Look for a closing brace or a semicolon. If we see a semicolon | |
| 3553 # first, this is probably a rvalue reference. | |
| 3554 line = clean_lines.elided[start][0:len(match_symbol.group(1)) + 1] | |
| 3555 end = start | |
| 3556 depth = 1 | |
| 3557 while True: | |
| 3558 for ch in line: | |
| 3559 if ch == ';': | |
| 3560 return True | |
| 3561 elif ch == '{': | |
| 3562 depth += 1 | |
| 3563 elif ch == '}': | |
| 3564 depth -= 1 | |
| 3565 if depth == 0: | |
| 3566 return False | |
| 3567 end += 1 | |
| 3568 if end >= clean_lines.NumLines(): | |
| 3569 break | |
| 3570 line = clean_lines.elided[end] | |
| 3571 # Incomplete program? | |
| 3572 return False | |
| 3573 | |
| 3574 if match_symbol.group(2) == '(': | |
| 3575 # Opening parenthesis. Need to check what's to the left of the | |
| 3576 # parenthesis. Look back one extra line for additional context. | |
| 3577 before_text = match_symbol.group(1) | |
| 3578 if linenum > 1: | |
| 3579 before_text = clean_lines.elided[linenum - 1] + before_text | |
| 3580 before_text = match_symbol.group(1) | |
| 3581 | |
| 3582 # Patterns that are likely to be types: | |
| 3583 # [](type&& | |
| 3584 # for (type&& | |
| 3585 # sizeof(type&& | |
| 3586 # operator=(type&& | |
| 3587 # | |
| 3588 if Search(r'(?:\]|\bfor|\bsizeof|\boperator\s*\S+\s*)\s*$', before_text): | |
| 3589 return True | |
| 3590 | |
| 3591 # Patterns that are likely to be expressions: | |
| 3592 # if (expression && | |
| 3593 # while (expression && | |
| 3594 # : initializer(expression && | |
| 3595 # , initializer(expression && | |
| 3596 # ( FunctionCall(expression && | |
| 3597 # + FunctionCall(expression && | |
| 3598 # + (expression && | |
| 3599 # | |
| 3600 # The last '+' represents operators such as '+' and '-'. | |
| 3601 if Search(r'(?:\bif|\bwhile|[-+=%^(<!?:,&*]\s*)$', before_text): | |
| 3602 return False | |
| 3603 | |
| 3604 # Something else. Check that tokens to the left look like | |
| 3605 # return_type function_name | |
| 3606 match_func = Match(r'^(.*\S.*)\s+\w(?:\w|::)*(?:<[^<>]*>)?\s*$', | |
| 3607 match_symbol.group(1)) | |
| 3608 if match_func: | |
| 3609 # Check for constructors, which don't have return types. | |
| 3610 if Search(r'\b(?:explicit|inline)$', match_func.group(1)): | |
| 3611 return True | |
| 3612 implicit_constructor = Match(r'\s*(\w+)\((?:const\s+)?(\w+)', prefix) | |
| 3613 if (implicit_constructor and | |
| 3614 implicit_constructor.group(1) == implicit_constructor.group(2)): | |
| 3615 return True | |
| 3616 return IsRValueType(typenames, clean_lines, nesting_state, linenum, | |
| 3617 len(match_func.group(1))) | |
| 3618 | |
| 3619 # Nothing before the function name. If this is inside a block scope, | |
| 3620 # this is probably a function call. | |
| 3621 return not (nesting_state.previous_stack_top and | |
| 3622 nesting_state.previous_stack_top.IsBlockInfo()) | |
| 3623 | |
| 3624 if match_symbol.group(2) == '>': | |
| 3625 # Possibly a closing bracket, check that what's on the other side | |
| 3626 # looks like the start of a template. | |
| 3627 return IsTemplateParameterList( | |
| 3628 clean_lines, start, len(match_symbol.group(1))) | |
| 3629 | |
| 3630 # Some other symbol, usually something like "a=b&&c". This is most | |
| 3631 # likely not a type. | |
| 3632 return False | |
| 3633 | |
| 3634 | |
| 3635 def IsDeletedOrDefault(clean_lines, linenum): | |
| 3636 """Check if current constructor or operator is deleted or default. | |
| 3637 | |
| 3638 Args: | |
| 3639 clean_lines: A CleansedLines instance containing the file. | |
| 3640 linenum: The number of the line to check. | |
| 3641 Returns: | |
| 3642 True if this is a deleted or default constructor. | |
| 3643 """ | |
| 3644 open_paren = clean_lines.elided[linenum].find('(') | |
| 3645 if open_paren < 0: | |
| 3646 return False | |
| 3647 (close_line, _, close_paren) = CloseExpression( | |
| 3648 clean_lines, linenum, open_paren) | |
| 3649 if close_paren < 0: | |
| 3650 return False | |
| 3651 return Match(r'\s*=\s*(?:delete|default)\b', close_line[close_paren:]) | |
| 3652 | |
| 3653 | |
| 3654 def IsRValueAllowed(clean_lines, linenum, typenames): | |
| 3655 """Check if RValue reference is allowed on a particular line. | |
| 3656 | |
| 3657 Args: | |
| 3658 clean_lines: A CleansedLines instance containing the file. | |
| 3659 linenum: The number of the line to check. | |
| 3660 typenames: set of type names from template-argument-list. | |
| 3661 Returns: | |
| 3662 True if line is within the region where RValue references are allowed. | |
| 3663 """ | |
| 3664 # Allow region marked by PUSH/POP macros | |
| 3665 for i in xrange(linenum, 0, -1): | |
| 3666 line = clean_lines.elided[i] | |
| 3667 if Match(r'GOOGLE_ALLOW_RVALUE_REFERENCES_(?:PUSH|POP)', line): | |
| 3668 if not line.endswith('PUSH'): | |
| 3669 return False | |
| 3670 for j in xrange(linenum, clean_lines.NumLines(), 1): | |
| 3671 line = clean_lines.elided[j] | |
| 3672 if Match(r'GOOGLE_ALLOW_RVALUE_REFERENCES_(?:PUSH|POP)', line): | |
| 3673 return line.endswith('POP') | |
| 3674 | |
| 3675 # Allow operator= | |
| 3676 line = clean_lines.elided[linenum] | |
| 3677 if Search(r'\boperator\s*=\s*\(', line): | |
| 3678 return IsDeletedOrDefault(clean_lines, linenum) | |
| 3679 | |
| 3680 # Allow constructors | |
| 3681 match = Match(r'\s*(?:[\w<>]+::)*([\w<>]+)\s*::\s*([\w<>]+)\s*\(', line) | |
| 3682 if match and match.group(1) == match.group(2): | |
| 3683 return IsDeletedOrDefault(clean_lines, linenum) | |
| 3684 if Search(r'\b(?:explicit|inline)\s+[\w<>]+\s*\(', line): | |
| 3685 return IsDeletedOrDefault(clean_lines, linenum) | |
| 3686 | |
| 3687 if Match(r'\s*[\w<>]+\s*\(', line): | |
| 3688 previous_line = 'ReturnType' | |
| 3689 if linenum > 0: | |
| 3690 previous_line = clean_lines.elided[linenum - 1] | |
| 3691 if Match(r'^\s*$', previous_line) or Search(r'[{}:;]\s*$', previous_line): | |
| 3692 return IsDeletedOrDefault(clean_lines, linenum) | |
| 3693 | |
| 3694 # Reject types not mentioned in template-argument-list | |
| 3695 while line: | |
| 3696 match = Match(r'^.*?(\w+)\s*&&(.*)$', line) | |
| 3697 if not match: | |
| 3698 break | |
| 3699 if match.group(1) not in typenames: | |
| 3700 return False | |
| 3701 line = match.group(2) | |
| 3702 | |
| 3703 # All RValue types that were in template-argument-list should have | |
| 3704 # been removed by now. Those were allowed, assuming that they will | |
| 3705 # be forwarded. | |
| 3706 # | |
| 3707 # If there are no remaining RValue types left (i.e. types that were | |
| 3708 # not found in template-argument-list), flag those as not allowed. | |
| 3709 return line.find('&&') < 0 | |
| 3710 | |
| 3711 | |
| 3712 def GetTemplateArgs(clean_lines, linenum): | |
| 3713 """Find list of template arguments associated with this function declaration. | |
| 3714 | |
| 3715 Args: | |
| 3716 clean_lines: A CleansedLines instance containing the file. | |
| 3717 linenum: Line number containing the start of the function declaration, | |
| 3718 usually one line after the end of the template-argument-list. | |
| 3719 Returns: | |
| 3720 Set of type names, or empty set if this does not appear to have | |
| 3721 any template parameters. | |
| 3722 """ | |
| 3723 # Find start of function | |
| 3724 func_line = linenum | |
| 3725 while func_line > 0: | |
| 3726 line = clean_lines.elided[func_line] | |
| 3727 if Match(r'^\s*$', line): | |
| 3728 return set() | |
| 3729 if line.find('(') >= 0: | |
| 3730 break | |
| 3731 func_line -= 1 | |
| 3732 if func_line == 0: | |
| 3733 return set() | |
| 3734 | |
| 3735 # Collapse template-argument-list into a single string | |
| 3736 argument_list = '' | |
| 3737 match = Match(r'^(\s*template\s*)<', clean_lines.elided[func_line]) | |
| 3738 if match: | |
| 3739 # template-argument-list on the same line as function name | |
| 3740 start_col = len(match.group(1)) | |
| 3741 _, end_line, end_col = CloseExpression(clean_lines, func_line, start_col) | |
| 3742 if end_col > -1 and end_line == func_line: | |
| 3743 start_col += 1 # Skip the opening bracket | |
| 3744 argument_list = clean_lines.elided[func_line][start_col:end_col] | |
| 3745 | |
| 3746 elif func_line > 1: | |
| 3747 # template-argument-list one line before function name | |
| 3748 match = Match(r'^(.*)>\s*$', clean_lines.elided[func_line - 1]) | |
| 3749 if match: | |
| 3750 end_col = len(match.group(1)) | |
| 3751 _, start_line, start_col = ReverseCloseExpression( | |
| 3752 clean_lines, func_line - 1, end_col) | |
| 3753 if start_col > -1: | |
| 3754 start_col += 1 # Skip the opening bracket | |
| 3755 while start_line < func_line - 1: | |
| 3756 argument_list += clean_lines.elided[start_line][start_col:] | |
| 3757 start_col = 0 | |
| 3758 start_line += 1 | |
| 3759 argument_list += clean_lines.elided[func_line - 1][start_col:end_col] | |
| 3760 | |
| 3761 if not argument_list: | |
| 3762 return set() | |
| 3763 | |
| 3764 # Extract type names | |
| 3765 typenames = set() | |
| 3766 while True: | |
| 3767 match = Match(r'^[,\s]*(?:typename|class)(?:\.\.\.)?\s+(\w+)(.*)$', | |
| 3768 argument_list) | |
| 3769 if not match: | |
| 3770 break | |
| 3771 typenames.add(match.group(1)) | |
| 3772 argument_list = match.group(2) | |
| 3773 return typenames | |
| 3774 | |
| 3775 | |
| 3776 def CheckRValueReference(filename, clean_lines, linenum, nesting_state, error): | |
| 3777 """Check for rvalue references. | |
| 3778 | |
| 3779 Args: | |
| 3780 filename: The name of the current file. | |
| 3781 clean_lines: A CleansedLines instance containing the file. | |
| 3782 linenum: The number of the line to check. | |
| 3783 nesting_state: A NestingState instance which maintains information about | |
| 3784 the current stack of nested blocks being parsed. | |
| 3785 error: The function to call with any errors found. | |
| 3786 """ | |
| 3787 # Find lines missing spaces around &&. | |
| 3788 # TODO(unknown): currently we don't check for rvalue references | |
| 3789 # with spaces surrounding the && to avoid false positives with | |
| 3790 # boolean expressions. | |
| 3791 line = clean_lines.elided[linenum] | |
| 3792 match = Match(r'^(.*\S)&&', line) | |
| 3793 if not match: | |
| 3794 match = Match(r'(.*)&&\S', line) | |
| 3795 if (not match) or '(&&)' in line or Search(r'\boperator\s*$', match.group(1)): | |
| 3796 return | |
| 3797 | |
| 3798 # Either poorly formed && or an rvalue reference, check the context | |
| 3799 # to get a more accurate error message. Mostly we want to determine | |
| 3800 # if what's to the left of "&&" is a type or not. | |
| 3801 typenames = GetTemplateArgs(clean_lines, linenum) | |
| 3802 and_pos = len(match.group(1)) | |
| 3803 if IsRValueType(typenames, clean_lines, nesting_state, linenum, and_pos): | |
| 3804 if not IsRValueAllowed(clean_lines, linenum, typenames): | |
| 3805 error(filename, linenum, 'build/c++11', 3, | |
| 3806 'RValue references are an unapproved C++ feature.') | |
| 3807 else: | |
| 3808 error(filename, linenum, 'whitespace/operators', 3, | |
| 3809 'Missing spaces around &&') | |
| 3810 | |
| 3811 | |
| 3812 def CheckSectionSpacing(filename, clean_lines, class_info, linenum, error): | 3554 def CheckSectionSpacing(filename, clean_lines, class_info, linenum, error): |
| 3813 """Checks for additional blank line issues related to sections. | 3555 """Checks for additional blank line issues related to sections. |
| 3814 | 3556 |
| 3815 Currently the only thing checked here is blank line before protected/private. | 3557 Currently the only thing checked here is blank line before protected/private. |
| 3816 | 3558 |
| 3817 Args: | 3559 Args: |
| 3818 filename: The name of the current file. | 3560 filename: The name of the current file. |
| 3819 clean_lines: A CleansedLines instance containing the file. | 3561 clean_lines: A CleansedLines instance containing the file. |
| 3820 class_info: A _ClassInfo objects. | 3562 class_info: A _ClassInfo objects. |
| 3821 linenum: The number of the line to check. | 3563 linenum: The number of the line to check. |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3899 | 3641 |
| 3900 line = clean_lines.elided[linenum] # get rid of comments and strings | 3642 line = clean_lines.elided[linenum] # get rid of comments and strings |
| 3901 | 3643 |
| 3902 if Match(r'\s*{\s*$', line): | 3644 if Match(r'\s*{\s*$', line): |
| 3903 # We allow an open brace to start a line in the case where someone is using | 3645 # We allow an open brace to start a line in the case where someone is using |
| 3904 # braces in a block to explicitly create a new scope, which is commonly used | 3646 # braces in a block to explicitly create a new scope, which is commonly used |
| 3905 # to control the lifetime of stack-allocated variables. Braces are also | 3647 # to control the lifetime of stack-allocated variables. Braces are also |
| 3906 # used for brace initializers inside function calls. We don't detect this | 3648 # used for brace initializers inside function calls. We don't detect this |
| 3907 # perfectly: we just don't complain if the last non-whitespace character on | 3649 # perfectly: we just don't complain if the last non-whitespace character on |
| 3908 # the previous non-blank line is ',', ';', ':', '(', '{', or '}', or if the | 3650 # the previous non-blank line is ',', ';', ':', '(', '{', or '}', or if the |
| 3909 # previous line starts a preprocessor block. | 3651 # previous line starts a preprocessor block. We also allow a brace on the |
| 3652 # following line if it is part of an array initialization and would not fit |
| 3653 # within the 80 character limit of the preceding line. |
| 3910 prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0] | 3654 prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0] |
| 3911 if (not Search(r'[,;:}{(]\s*$', prevline) and | 3655 if (not Search(r'[,;:}{(]\s*$', prevline) and |
| 3912 not Match(r'\s*#', prevline)): | 3656 not Match(r'\s*#', prevline) and |
| 3657 not (GetLineWidth(prevline) > _line_length - 2 and '[]' in prevline)): |
| 3913 error(filename, linenum, 'whitespace/braces', 4, | 3658 error(filename, linenum, 'whitespace/braces', 4, |
| 3914 '{ should almost always be at the end of the previous line') | 3659 '{ should almost always be at the end of the previous line') |
| 3915 | 3660 |
| 3916 # An else clause should be on the same line as the preceding closing brace. | 3661 # An else clause should be on the same line as the preceding closing brace. |
| 3917 if Match(r'\s*else\b\s*(?:if\b|\{|$)', line): | 3662 if Match(r'\s*else\b\s*(?:if\b|\{|$)', line): |
| 3918 prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0] | 3663 prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0] |
| 3919 if Match(r'\s*}\s*$', prevline): | 3664 if Match(r'\s*}\s*$', prevline): |
| 3920 error(filename, linenum, 'whitespace/newline', 4, | 3665 error(filename, linenum, 'whitespace/newline', 4, |
| 3921 'An else should appear on the same line as the preceding }') | 3666 'An else should appear on the same line as the preceding }') |
| 3922 | 3667 |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4078 # We implement a whitelist of safe macros instead of a blacklist of | 3823 # We implement a whitelist of safe macros instead of a blacklist of |
| 4079 # unsafe macros, even though the latter appears less frequently in | 3824 # unsafe macros, even though the latter appears less frequently in |
| 4080 # google code and would have been easier to implement. This is because | 3825 # google code and would have been easier to implement. This is because |
| 4081 # the downside for getting the whitelist wrong means some extra | 3826 # the downside for getting the whitelist wrong means some extra |
| 4082 # semicolons, while the downside for getting the blacklist wrong | 3827 # semicolons, while the downside for getting the blacklist wrong |
| 4083 # would result in compile errors. | 3828 # would result in compile errors. |
| 4084 # | 3829 # |
| 4085 # In addition to macros, we also don't want to warn on | 3830 # In addition to macros, we also don't want to warn on |
| 4086 # - Compound literals | 3831 # - Compound literals |
| 4087 # - Lambdas | 3832 # - Lambdas |
| 4088 # - alignas specifier with anonymous structs: | 3833 # - alignas specifier with anonymous structs |
| 3834 # - decltype |
| 4089 closing_brace_pos = match.group(1).rfind(')') | 3835 closing_brace_pos = match.group(1).rfind(')') |
| 4090 opening_parenthesis = ReverseCloseExpression( | 3836 opening_parenthesis = ReverseCloseExpression( |
| 4091 clean_lines, linenum, closing_brace_pos) | 3837 clean_lines, linenum, closing_brace_pos) |
| 4092 if opening_parenthesis[2] > -1: | 3838 if opening_parenthesis[2] > -1: |
| 4093 line_prefix = opening_parenthesis[0][0:opening_parenthesis[2]] | 3839 line_prefix = opening_parenthesis[0][0:opening_parenthesis[2]] |
| 4094 macro = Search(r'\b([A-Z_]+)\s*$', line_prefix) | 3840 macro = Search(r'\b([A-Z_][A-Z0-9_]*)\s*$', line_prefix) |
| 4095 func = Match(r'^(.*\])\s*$', line_prefix) | 3841 func = Match(r'^(.*\])\s*$', line_prefix) |
| 4096 if ((macro and | 3842 if ((macro and |
| 4097 macro.group(1) not in ( | 3843 macro.group(1) not in ( |
| 4098 'TEST', 'TEST_F', 'MATCHER', 'MATCHER_P', 'TYPED_TEST', | 3844 'TEST', 'TEST_F', 'MATCHER', 'MATCHER_P', 'TYPED_TEST', |
| 4099 'EXCLUSIVE_LOCKS_REQUIRED', 'SHARED_LOCKS_REQUIRED', | 3845 'EXCLUSIVE_LOCKS_REQUIRED', 'SHARED_LOCKS_REQUIRED', |
| 4100 'LOCKS_EXCLUDED', 'INTERFACE_DEF')) or | 3846 'LOCKS_EXCLUDED', 'INTERFACE_DEF')) or |
| 4101 (func and not Search(r'\boperator\s*\[\s*\]', func.group(1))) or | 3847 (func and not Search(r'\boperator\s*\[\s*\]', func.group(1))) or |
| 4102 Search(r'\b(?:struct|union)\s+alignas\s*$', line_prefix) or | 3848 Search(r'\b(?:struct|union)\s+alignas\s*$', line_prefix) or |
| 3849 Search(r'\bdecltype$', line_prefix) or |
| 4103 Search(r'\s+=\s*$', line_prefix)): | 3850 Search(r'\s+=\s*$', line_prefix)): |
| 4104 match = None | 3851 match = None |
| 4105 if (match and | 3852 if (match and |
| 4106 opening_parenthesis[1] > 1 and | 3853 opening_parenthesis[1] > 1 and |
| 4107 Search(r'\]\s*$', clean_lines.elided[opening_parenthesis[1] - 1])): | 3854 Search(r'\]\s*$', clean_lines.elided[opening_parenthesis[1] - 1])): |
| 4108 # Multi-line lambda-expression | 3855 # Multi-line lambda-expression |
| 4109 match = None | 3856 match = None |
| 4110 | 3857 |
| 4111 else: | 3858 else: |
| 4112 # Try matching cases 2-3. | 3859 # Try matching cases 2-3. |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4152 | 3899 |
| 4153 # Search for loop keywords at the beginning of the line. Because only | 3900 # Search for loop keywords at the beginning of the line. Because only |
| 4154 # whitespaces are allowed before the keywords, this will also ignore most | 3901 # whitespaces are allowed before the keywords, this will also ignore most |
| 4155 # do-while-loops, since those lines should start with closing brace. | 3902 # do-while-loops, since those lines should start with closing brace. |
| 4156 # | 3903 # |
| 4157 # We also check "if" blocks here, since an empty conditional block | 3904 # We also check "if" blocks here, since an empty conditional block |
| 4158 # is likely an error. | 3905 # is likely an error. |
| 4159 line = clean_lines.elided[linenum] | 3906 line = clean_lines.elided[linenum] |
| 4160 matched = Match(r'\s*(for|while|if)\s*\(', line) | 3907 matched = Match(r'\s*(for|while|if)\s*\(', line) |
| 4161 if matched: | 3908 if matched: |
| 4162 # Find the end of the conditional expression | 3909 # Find the end of the conditional expression. |
| 4163 (end_line, end_linenum, end_pos) = CloseExpression( | 3910 (end_line, end_linenum, end_pos) = CloseExpression( |
| 4164 clean_lines, linenum, line.find('(')) | 3911 clean_lines, linenum, line.find('(')) |
| 4165 | 3912 |
| 4166 # Output warning if what follows the condition expression is a semicolon. | 3913 # Output warning if what follows the condition expression is a semicolon. |
| 4167 # No warning for all other cases, including whitespace or newline, since we | 3914 # No warning for all other cases, including whitespace or newline, since we |
| 4168 # have a separate check for semicolons preceded by whitespace. | 3915 # have a separate check for semicolons preceded by whitespace. |
| 4169 if end_pos >= 0 and Match(r';', end_line[end_pos:]): | 3916 if end_pos >= 0 and Match(r';', end_line[end_pos:]): |
| 4170 if matched.group(1) == 'if': | 3917 if matched.group(1) == 'if': |
| 4171 error(filename, end_linenum, 'whitespace/empty_conditional_body', 5, | 3918 error(filename, end_linenum, 'whitespace/empty_conditional_body', 5, |
| 4172 'Empty conditional bodies should use {}') | 3919 'Empty conditional bodies should use {}') |
| 4173 else: | 3920 else: |
| 4174 error(filename, end_linenum, 'whitespace/empty_loop_body', 5, | 3921 error(filename, end_linenum, 'whitespace/empty_loop_body', 5, |
| 4175 'Empty loop bodies should use {} or continue') | 3922 'Empty loop bodies should use {} or continue') |
| 4176 | 3923 |
| 3924 # Check for if statements that have completely empty bodies (no comments) |
| 3925 # and no else clauses. |
| 3926 if end_pos >= 0 and matched.group(1) == 'if': |
| 3927 # Find the position of the opening { for the if statement. |
| 3928 # Return without logging an error if it has no brackets. |
| 3929 opening_linenum = end_linenum |
| 3930 opening_line_fragment = end_line[end_pos:] |
| 3931 # Loop until EOF or find anything that's not whitespace or opening {. |
| 3932 while not Search(r'^\s*\{', opening_line_fragment): |
| 3933 if Search(r'^(?!\s*$)', opening_line_fragment): |
| 3934 # Conditional has no brackets. |
| 3935 return |
| 3936 opening_linenum += 1 |
| 3937 if opening_linenum == len(clean_lines.elided): |
| 3938 # Couldn't find conditional's opening { or any code before EOF. |
| 3939 return |
| 3940 opening_line_fragment = clean_lines.elided[opening_linenum] |
| 3941 # Set opening_line (opening_line_fragment may not be entire opening line). |
| 3942 opening_line = clean_lines.elided[opening_linenum] |
| 3943 |
| 3944 # Find the position of the closing }. |
| 3945 opening_pos = opening_line_fragment.find('{') |
| 3946 if opening_linenum == end_linenum: |
| 3947 # We need to make opening_pos relative to the start of the entire line. |
| 3948 opening_pos += end_pos |
| 3949 (closing_line, closing_linenum, closing_pos) = CloseExpression( |
| 3950 clean_lines, opening_linenum, opening_pos) |
| 3951 if closing_pos < 0: |
| 3952 return |
| 3953 |
| 3954 # Now construct the body of the conditional. This consists of the portion |
| 3955 # of the opening line after the {, all lines until the closing line, |
| 3956 # and the portion of the closing line before the }. |
| 3957 if (clean_lines.raw_lines[opening_linenum] != |
| 3958 CleanseComments(clean_lines.raw_lines[opening_linenum])): |
| 3959 # Opening line ends with a comment, so conditional isn't empty. |
| 3960 return |
| 3961 if closing_linenum > opening_linenum: |
| 3962 # Opening line after the {. Ignore comments here since we checked above. |
| 3963 body = list(opening_line[opening_pos+1:]) |
| 3964 # All lines until closing line, excluding closing line, with comments. |
| 3965 body.extend(clean_lines.raw_lines[opening_linenum+1:closing_linenum]) |
| 3966 # Closing line before the }. Won't (and can't) have comments. |
| 3967 body.append(clean_lines.elided[closing_linenum][:closing_pos-1]) |
| 3968 body = '\n'.join(body) |
| 3969 else: |
| 3970 # If statement has brackets and fits on a single line. |
| 3971 body = opening_line[opening_pos+1:closing_pos-1] |
| 3972 |
| 3973 # Check if the body is empty |
| 3974 if not _EMPTY_CONDITIONAL_BODY_PATTERN.search(body): |
| 3975 return |
| 3976 # The body is empty. Now make sure there's not an else clause. |
| 3977 current_linenum = closing_linenum |
| 3978 current_line_fragment = closing_line[closing_pos:] |
| 3979 # Loop until EOF or find anything that's not whitespace or else clause. |
| 3980 while Search(r'^\s*$|^(?=\s*else)', current_line_fragment): |
| 3981 if Search(r'^(?=\s*else)', current_line_fragment): |
| 3982 # Found an else clause, so don't log an error. |
| 3983 return |
| 3984 current_linenum += 1 |
| 3985 if current_linenum == len(clean_lines.elided): |
| 3986 break |
| 3987 current_line_fragment = clean_lines.elided[current_linenum] |
| 3988 |
| 3989 # The body is empty and there's no else clause until EOF or other code. |
| 3990 error(filename, end_linenum, 'whitespace/empty_if_body', 4, |
| 3991 ('If statement had no body and no else clause')) |
| 3992 |
| 4177 | 3993 |
| 4178 def FindCheckMacro(line): | 3994 def FindCheckMacro(line): |
| 4179 """Find a replaceable CHECK-like macro. | 3995 """Find a replaceable CHECK-like macro. |
| 4180 | 3996 |
| 4181 Args: | 3997 Args: |
| 4182 line: line to search on. | 3998 line: line to search on. |
| 4183 Returns: | 3999 Returns: |
| 4184 (macro name, start position), or (None, -1) if no replaceable | 4000 (macro name, start position), or (None, -1) if no replaceable |
| 4185 macro is found. | 4001 macro is found. |
| 4186 """ | 4002 """ |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4386 nesting_state: A NestingState instance which maintains information about | 4202 nesting_state: A NestingState instance which maintains information about |
| 4387 the current stack of nested blocks being parsed. | 4203 the current stack of nested blocks being parsed. |
| 4388 error: The function to call with any errors found. | 4204 error: The function to call with any errors found. |
| 4389 """ | 4205 """ |
| 4390 | 4206 |
| 4391 # Don't use "elided" lines here, otherwise we can't check commented lines. | 4207 # Don't use "elided" lines here, otherwise we can't check commented lines. |
| 4392 # Don't want to use "raw" either, because we don't want to check inside C++11 | 4208 # Don't want to use "raw" either, because we don't want to check inside C++11 |
| 4393 # raw strings, | 4209 # raw strings, |
| 4394 raw_lines = clean_lines.lines_without_raw_strings | 4210 raw_lines = clean_lines.lines_without_raw_strings |
| 4395 line = raw_lines[linenum] | 4211 line = raw_lines[linenum] |
| 4212 prev = raw_lines[linenum - 1] if linenum > 0 else '' |
| 4396 | 4213 |
| 4397 if line.find('\t') != -1: | 4214 if line.find('\t') != -1: |
| 4398 error(filename, linenum, 'whitespace/tab', 1, | 4215 error(filename, linenum, 'whitespace/tab', 1, |
| 4399 'Tab found; better to use spaces') | 4216 'Tab found; better to use spaces') |
| 4400 | 4217 |
| 4401 # One or three blank spaces at the beginning of the line is weird; it's | 4218 # One or three blank spaces at the beginning of the line is weird; it's |
| 4402 # hard to reconcile that with 2-space indents. | 4219 # hard to reconcile that with 2-space indents. |
| 4403 # NOTE: here are the conditions rob pike used for his tests. Mine aren't | 4220 # NOTE: here are the conditions rob pike used for his tests. Mine aren't |
| 4404 # as sophisticated, but it may be worth becoming so: RLENGTH==initial_spaces | 4221 # as sophisticated, but it may be worth becoming so: RLENGTH==initial_spaces |
| 4405 # if(RLENGTH > 20) complain = 0; | 4222 # if(RLENGTH > 20) complain = 0; |
| 4406 # if(match($0, " +(error|private|public|protected):")) complain = 0; | 4223 # if(match($0, " +(error|private|public|protected):")) complain = 0; |
| 4407 # if(match(prev, "&& *$")) complain = 0; | 4224 # if(match(prev, "&& *$")) complain = 0; |
| 4408 # if(match(prev, "\\|\\| *$")) complain = 0; | 4225 # if(match(prev, "\\|\\| *$")) complain = 0; |
| 4409 # if(match(prev, "[\",=><] *$")) complain = 0; | 4226 # if(match(prev, "[\",=><] *$")) complain = 0; |
| 4410 # if(match($0, " <<")) complain = 0; | 4227 # if(match($0, " <<")) complain = 0; |
| 4411 # if(match(prev, " +for \\(")) complain = 0; | 4228 # if(match(prev, " +for \\(")) complain = 0; |
| 4412 # if(prevodd && match(prevprev, " +for \\(")) complain = 0; | 4229 # if(prevodd && match(prevprev, " +for \\(")) complain = 0; |
| 4413 scope_or_label_pattern = r'\s*\w+\s*:\s*\\?$' | 4230 scope_or_label_pattern = r'\s*\w+\s*:\s*\\?$' |
| 4414 classinfo = nesting_state.InnermostClass() | 4231 classinfo = nesting_state.InnermostClass() |
| 4415 initial_spaces = 0 | 4232 initial_spaces = 0 |
| 4416 cleansed_line = clean_lines.elided[linenum] | 4233 cleansed_line = clean_lines.elided[linenum] |
| 4417 while initial_spaces < len(line) and line[initial_spaces] == ' ': | 4234 while initial_spaces < len(line) and line[initial_spaces] == ' ': |
| 4418 initial_spaces += 1 | 4235 initial_spaces += 1 |
| 4419 if line and line[-1].isspace(): | |
| 4420 error(filename, linenum, 'whitespace/end_of_line', 4, | |
| 4421 'Line ends in whitespace. Consider deleting these extra spaces.') | |
| 4422 # There are certain situations we allow one space, notably for | 4236 # There are certain situations we allow one space, notably for |
| 4423 # section labels, and also lines containing multi-line raw strings. | 4237 # section labels, and also lines containing multi-line raw strings. |
| 4424 elif ((initial_spaces == 1 or initial_spaces == 3) and | 4238 # We also don't check for lines that look like continuation lines |
| 4425 not Match(scope_or_label_pattern, cleansed_line) and | 4239 # (of lines ending in double quotes, commas, equals, or angle brackets) |
| 4426 not (clean_lines.raw_lines[linenum] != line and | 4240 # because the rules for how to indent those are non-trivial. |
| 4427 Match(r'^\s*""', line))): | 4241 if (not Search(r'[",=><] *$', prev) and |
| 4242 (initial_spaces == 1 or initial_spaces == 3) and |
| 4243 not Match(scope_or_label_pattern, cleansed_line) and |
| 4244 not (clean_lines.raw_lines[linenum] != line and |
| 4245 Match(r'^\s*""', line))): |
| 4428 error(filename, linenum, 'whitespace/indent', 3, | 4246 error(filename, linenum, 'whitespace/indent', 3, |
| 4429 'Weird number of spaces at line-start. ' | 4247 'Weird number of spaces at line-start. ' |
| 4430 'Are you using a 2-space indent?') | 4248 'Are you using a 2-space indent?') |
| 4431 | 4249 |
| 4250 if line and line[-1].isspace(): |
| 4251 error(filename, linenum, 'whitespace/end_of_line', 4, |
| 4252 'Line ends in whitespace. Consider deleting these extra spaces.') |
| 4253 |
| 4432 # Check if the line is a header guard. | 4254 # Check if the line is a header guard. |
| 4433 is_header_guard = False | 4255 is_header_guard = False |
| 4434 if file_extension == 'h': | 4256 if file_extension == 'h': |
| 4435 cppvar = GetHeaderGuardCPPVariable(filename) | 4257 cppvar = GetHeaderGuardCPPVariable(filename) |
| 4436 if (line.startswith('#ifndef %s' % cppvar) or | 4258 if (line.startswith('#ifndef %s' % cppvar) or |
| 4437 line.startswith('#define %s' % cppvar) or | 4259 line.startswith('#define %s' % cppvar) or |
| 4438 line.startswith('#endif // %s' % cppvar)): | 4260 line.startswith('#endif // %s' % cppvar)): |
| 4439 is_header_guard = True | 4261 is_header_guard = True |
| 4440 # #include lines and header guards can be long, since there's no clean way to | 4262 # #include lines and header guards can be long, since there's no clean way to |
| 4441 # split them. | 4263 # split them. |
| 4442 # | 4264 # |
| 4443 # URLs can be long too. It's possible to split these, but it makes them | 4265 # URLs can be long too. It's possible to split these, but it makes them |
| 4444 # harder to cut&paste. | 4266 # harder to cut&paste. |
| 4445 # | 4267 # |
| 4446 # The "$Id:...$" comment may also get very long without it being the | 4268 # The "$Id:...$" comment may also get very long without it being the |
| 4447 # developers fault. | 4269 # developers fault. |
| 4448 if (not line.startswith('#include') and not is_header_guard and | 4270 if (not line.startswith('#include') and not is_header_guard and |
| 4449 not Match(r'^\s*//.*http(s?)://\S*$', line) and | 4271 not Match(r'^\s*//.*http(s?)://\S*$', line) and |
| 4272 not Match(r'^\s*//\s*[^\s]*$', line) and |
| 4450 not Match(r'^// \$Id:.*#[0-9]+ \$$', line)): | 4273 not Match(r'^// \$Id:.*#[0-9]+ \$$', line)): |
| 4451 line_width = GetLineWidth(line) | 4274 line_width = GetLineWidth(line) |
| 4452 extended_length = int((_line_length * 1.25)) | 4275 if line_width > _line_length: |
| 4453 if line_width > extended_length: | |
| 4454 error(filename, linenum, 'whitespace/line_length', 4, | |
| 4455 'Lines should very rarely be longer than %i characters' % | |
| 4456 extended_length) | |
| 4457 elif line_width > _line_length: | |
| 4458 error(filename, linenum, 'whitespace/line_length', 2, | 4276 error(filename, linenum, 'whitespace/line_length', 2, |
| 4459 'Lines should be <= %i characters long' % _line_length) | 4277 'Lines should be <= %i characters long' % _line_length) |
| 4460 | 4278 |
| 4461 if (cleansed_line.count(';') > 1 and | 4279 if (cleansed_line.count(';') > 1 and |
| 4462 # for loops are allowed two ;'s (and may run over two lines). | 4280 # for loops are allowed two ;'s (and may run over two lines). |
| 4463 cleansed_line.find('for') == -1 and | 4281 cleansed_line.find('for') == -1 and |
| 4464 (GetPreviousNonBlankLine(clean_lines, linenum)[0].find('for') == -1 or | 4282 (GetPreviousNonBlankLine(clean_lines, linenum)[0].find('for') == -1 or |
| 4465 GetPreviousNonBlankLine(clean_lines, linenum)[0].find(';') != -1) and | 4283 GetPreviousNonBlankLine(clean_lines, linenum)[0].find(';') != -1) and |
| 4466 # It's ok to have many commands in a switch case that fits in 1 line | 4284 # It's ok to have many commands in a switch case that fits in 1 line |
| 4467 not ((cleansed_line.find('case ') != -1 or | 4285 not ((cleansed_line.find('case ') != -1 or |
| 4468 cleansed_line.find('default:') != -1) and | 4286 cleansed_line.find('default:') != -1) and |
| 4469 cleansed_line.find('break;') != -1)): | 4287 cleansed_line.find('break;') != -1)): |
| 4470 error(filename, linenum, 'whitespace/newline', 0, | 4288 error(filename, linenum, 'whitespace/newline', 0, |
| 4471 'More than one command on the same line') | 4289 'More than one command on the same line') |
| 4472 | 4290 |
| 4473 # Some more style checks | 4291 # Some more style checks |
| 4474 CheckBraces(filename, clean_lines, linenum, error) | 4292 CheckBraces(filename, clean_lines, linenum, error) |
| 4475 CheckTrailingSemicolon(filename, clean_lines, linenum, error) | 4293 CheckTrailingSemicolon(filename, clean_lines, linenum, error) |
| 4476 CheckEmptyBlockBody(filename, clean_lines, linenum, error) | 4294 CheckEmptyBlockBody(filename, clean_lines, linenum, error) |
| 4477 CheckAccess(filename, clean_lines, linenum, nesting_state, error) | 4295 CheckAccess(filename, clean_lines, linenum, nesting_state, error) |
| 4478 CheckSpacing(filename, clean_lines, linenum, nesting_state, error) | 4296 CheckSpacing(filename, clean_lines, linenum, nesting_state, error) |
| 4479 CheckOperatorSpacing(filename, clean_lines, linenum, error) | 4297 CheckOperatorSpacing(filename, clean_lines, linenum, error) |
| 4480 CheckParenthesisSpacing(filename, clean_lines, linenum, error) | 4298 CheckParenthesisSpacing(filename, clean_lines, linenum, error) |
| 4481 CheckCommaSpacing(filename, clean_lines, linenum, error) | 4299 CheckCommaSpacing(filename, clean_lines, linenum, error) |
| 4482 CheckBracesSpacing(filename, clean_lines, linenum, error) | 4300 CheckBracesSpacing(filename, clean_lines, linenum, nesting_state, error) |
| 4483 CheckSpacingForFunctionCall(filename, clean_lines, linenum, error) | 4301 CheckSpacingForFunctionCall(filename, clean_lines, linenum, error) |
| 4484 CheckRValueReference(filename, clean_lines, linenum, nesting_state, error) | |
| 4485 CheckCheck(filename, clean_lines, linenum, error) | 4302 CheckCheck(filename, clean_lines, linenum, error) |
| 4486 CheckAltTokens(filename, clean_lines, linenum, error) | 4303 CheckAltTokens(filename, clean_lines, linenum, error) |
| 4487 classinfo = nesting_state.InnermostClass() | 4304 classinfo = nesting_state.InnermostClass() |
| 4488 if classinfo: | 4305 if classinfo: |
| 4489 CheckSectionSpacing(filename, clean_lines, classinfo, linenum, error) | 4306 CheckSectionSpacing(filename, clean_lines, classinfo, linenum, error) |
| 4490 | 4307 |
| 4491 | 4308 |
| 4492 _RE_PATTERN_INCLUDE = re.compile(r'^\s*#\s*include\s*([<"])([^>"]*)[>"].*$') | 4309 _RE_PATTERN_INCLUDE = re.compile(r'^\s*#\s*include\s*([<"])([^>"]*)[>"].*$') |
| 4493 # Matches the first component of a filename delimited by -s and _s. That is: | 4310 # Matches the first component of a filename delimited by -s and _s. That is: |
| 4494 # _RE_FIRST_COMPONENT.match('foo').group(0) == 'foo' | 4311 # _RE_FIRST_COMPONENT.match('foo').group(0) == 'foo' |
| (...skipping 23 matching lines...) Expand all Loading... |
| 4518 The filename with the common suffix removed. | 4335 The filename with the common suffix removed. |
| 4519 """ | 4336 """ |
| 4520 for suffix in ('test.cc', 'regtest.cc', 'unittest.cc', | 4337 for suffix in ('test.cc', 'regtest.cc', 'unittest.cc', |
| 4521 'inl.h', 'impl.h', 'internal.h'): | 4338 'inl.h', 'impl.h', 'internal.h'): |
| 4522 if (filename.endswith(suffix) and len(filename) > len(suffix) and | 4339 if (filename.endswith(suffix) and len(filename) > len(suffix) and |
| 4523 filename[-len(suffix) - 1] in ('-', '_')): | 4340 filename[-len(suffix) - 1] in ('-', '_')): |
| 4524 return filename[:-len(suffix) - 1] | 4341 return filename[:-len(suffix) - 1] |
| 4525 return os.path.splitext(filename)[0] | 4342 return os.path.splitext(filename)[0] |
| 4526 | 4343 |
| 4527 | 4344 |
| 4528 def _IsTestFilename(filename): | |
| 4529 """Determines if the given filename has a suffix that identifies it as a test. | |
| 4530 | |
| 4531 Args: | |
| 4532 filename: The input filename. | |
| 4533 | |
| 4534 Returns: | |
| 4535 True if 'filename' looks like a test, False otherwise. | |
| 4536 """ | |
| 4537 if (filename.endswith('_test.cc') or | |
| 4538 filename.endswith('_unittest.cc') or | |
| 4539 filename.endswith('_regtest.cc')): | |
| 4540 return True | |
| 4541 else: | |
| 4542 return False | |
| 4543 | |
| 4544 | |
| 4545 def _ClassifyInclude(fileinfo, include, is_system): | 4345 def _ClassifyInclude(fileinfo, include, is_system): |
| 4546 """Figures out what kind of header 'include' is. | 4346 """Figures out what kind of header 'include' is. |
| 4547 | 4347 |
| 4548 Args: | 4348 Args: |
| 4549 fileinfo: The current file cpplint is running over. A FileInfo instance. | 4349 fileinfo: The current file cpplint is running over. A FileInfo instance. |
| 4550 include: The path to a #included file. | 4350 include: The path to a #included file. |
| 4551 is_system: True if the #include used <> rather than "". | 4351 is_system: True if the #include used <> rather than "". |
| 4552 | 4352 |
| 4553 Returns: | 4353 Returns: |
| 4554 One of the _XXX_HEADER constants. | 4354 One of the _XXX_HEADER constants. |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4749 r'::)+') | 4549 r'::)+') |
| 4750 # A call-by-reference parameter ends with '& identifier'. | 4550 # A call-by-reference parameter ends with '& identifier'. |
| 4751 _RE_PATTERN_REF_PARAM = re.compile( | 4551 _RE_PATTERN_REF_PARAM = re.compile( |
| 4752 r'(' + _RE_PATTERN_TYPE + r'(?:\s*(?:\bconst\b|[*]))*\s*' | 4552 r'(' + _RE_PATTERN_TYPE + r'(?:\s*(?:\bconst\b|[*]))*\s*' |
| 4753 r'&\s*' + _RE_PATTERN_IDENT + r')\s*(?:=[^,()]+)?[,)]') | 4553 r'&\s*' + _RE_PATTERN_IDENT + r')\s*(?:=[^,()]+)?[,)]') |
| 4754 # A call-by-const-reference parameter either ends with 'const& identifier' | 4554 # A call-by-const-reference parameter either ends with 'const& identifier' |
| 4755 # or looks like 'const type& identifier' when 'type' is atomic. | 4555 # or looks like 'const type& identifier' when 'type' is atomic. |
| 4756 _RE_PATTERN_CONST_REF_PARAM = ( | 4556 _RE_PATTERN_CONST_REF_PARAM = ( |
| 4757 r'(?:.*\s*\bconst\s*&\s*' + _RE_PATTERN_IDENT + | 4557 r'(?:.*\s*\bconst\s*&\s*' + _RE_PATTERN_IDENT + |
| 4758 r'|const\s+' + _RE_PATTERN_TYPE + r'\s*&\s*' + _RE_PATTERN_IDENT + r')') | 4558 r'|const\s+' + _RE_PATTERN_TYPE + r'\s*&\s*' + _RE_PATTERN_IDENT + r')') |
| 4559 # Stream types. |
| 4560 _RE_PATTERN_REF_STREAM_PARAM = ( |
| 4561 r'(?:.*stream\s*&\s*' + _RE_PATTERN_IDENT + r')') |
| 4759 | 4562 |
| 4760 | 4563 |
| 4761 def CheckLanguage(filename, clean_lines, linenum, file_extension, | 4564 def CheckLanguage(filename, clean_lines, linenum, file_extension, |
| 4762 include_state, nesting_state, error): | 4565 include_state, nesting_state, error): |
| 4763 """Checks rules from the 'C++ language rules' section of cppguide.html. | 4566 """Checks rules from the 'C++ language rules' section of cppguide.html. |
| 4764 | 4567 |
| 4765 Some of these rules are hard to test (function overloading, using | 4568 Some of these rules are hard to test (function overloading, using |
| 4766 uint32 inappropriately), but we do the best we can. | 4569 uint32 inappropriately), but we do the best we can. |
| 4767 | 4570 |
| 4768 Args: | 4571 Args: |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4905 "('k' followed by CamelCase) compile-time constant for the size.") | 4708 "('k' followed by CamelCase) compile-time constant for the size.") |
| 4906 | 4709 |
| 4907 # Check for use of unnamed namespaces in header files. Registration | 4710 # Check for use of unnamed namespaces in header files. Registration |
| 4908 # macros are typically OK, so we allow use of "namespace {" on lines | 4711 # macros are typically OK, so we allow use of "namespace {" on lines |
| 4909 # that end with backslashes. | 4712 # that end with backslashes. |
| 4910 if (file_extension == 'h' | 4713 if (file_extension == 'h' |
| 4911 and Search(r'\bnamespace\s*{', line) | 4714 and Search(r'\bnamespace\s*{', line) |
| 4912 and line[-1] != '\\'): | 4715 and line[-1] != '\\'): |
| 4913 error(filename, linenum, 'build/namespaces', 4, | 4716 error(filename, linenum, 'build/namespaces', 4, |
| 4914 'Do not use unnamed namespaces in header files. See ' | 4717 'Do not use unnamed namespaces in header files. See ' |
| 4915 'http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Namesp
aces' | 4718 'https://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Names
paces' |
| 4916 ' for more information.') | 4719 ' for more information.') |
| 4917 | 4720 |
| 4918 | 4721 |
| 4919 def CheckGlobalStatic(filename, clean_lines, linenum, error): | 4722 def CheckGlobalStatic(filename, clean_lines, linenum, error): |
| 4920 """Check for unsafe global or static objects. | 4723 """Check for unsafe global or static objects. |
| 4921 | 4724 |
| 4922 Args: | 4725 Args: |
| 4923 filename: The name of the current file. | 4726 filename: The name of the current file. |
| 4924 clean_lines: A CleansedLines instance containing the file. | 4727 clean_lines: A CleansedLines instance containing the file. |
| 4925 linenum: The number of the line to check. | 4728 linenum: The number of the line to check. |
| 4926 error: The function to call with any errors found. | 4729 error: The function to call with any errors found. |
| 4927 """ | 4730 """ |
| 4928 line = clean_lines.elided[linenum] | 4731 line = clean_lines.elided[linenum] |
| 4929 | 4732 |
| 4930 # Match two lines at a time to support multiline declarations | 4733 # Match two lines at a time to support multiline declarations |
| 4931 if linenum + 1 < clean_lines.NumLines() and not Search(r'[;({]', line): | 4734 if linenum + 1 < clean_lines.NumLines() and not Search(r'[;({]', line): |
| 4932 line += clean_lines.elided[linenum + 1].strip() | 4735 line += clean_lines.elided[linenum + 1].strip() |
| 4933 | 4736 |
| 4934 # Check for people declaring static/global STL strings at the top level. | 4737 # Check for people declaring static/global STL strings at the top level. |
| 4935 # This is dangerous because the C++ language does not guarantee that | 4738 # This is dangerous because the C++ language does not guarantee that |
| 4936 # globals with constructors are initialized before the first access. | 4739 # globals with constructors are initialized before the first access, and |
| 4740 # also because globals can be destroyed when some threads are still running. |
| 4741 # TODO(unknown): Generalize this to also find static unique_ptr instances. |
| 4742 # TODO(unknown): File bugs for clang-tidy to find these. |
| 4937 match = Match( | 4743 match = Match( |
| 4938 r'((?:|static +)(?:|const +))string +([a-zA-Z0-9_:]+)\b(.*)', | 4744 r'((?:|static +)(?:|const +))(?::*std::)?string( +const)? +' |
| 4745 r'([a-zA-Z0-9_:]+)\b(.*)', |
| 4939 line) | 4746 line) |
| 4940 | 4747 |
| 4941 # Remove false positives: | 4748 # Remove false positives: |
| 4942 # - String pointers (as opposed to values). | 4749 # - String pointers (as opposed to values). |
| 4943 # string *pointer | 4750 # string *pointer |
| 4944 # const string *pointer | 4751 # const string *pointer |
| 4945 # string const *pointer | 4752 # string const *pointer |
| 4946 # string *const pointer | 4753 # string *const pointer |
| 4947 # | 4754 # |
| 4948 # - Functions and template specializations. | 4755 # - Functions and template specializations. |
| 4949 # string Function<Type>(... | 4756 # string Function<Type>(... |
| 4950 # string Class<Type>::Method(... | 4757 # string Class<Type>::Method(... |
| 4951 # | 4758 # |
| 4952 # - Operators. These are matched separately because operator names | 4759 # - Operators. These are matched separately because operator names |
| 4953 # cross non-word boundaries, and trying to match both operators | 4760 # cross non-word boundaries, and trying to match both operators |
| 4954 # and functions at the same time would decrease accuracy of | 4761 # and functions at the same time would decrease accuracy of |
| 4955 # matching identifiers. | 4762 # matching identifiers. |
| 4956 # string Class::operator*() | 4763 # string Class::operator*() |
| 4957 if (match and | 4764 if (match and |
| 4958 not Search(r'\bstring\b(\s+const)?\s*\*\s*(const\s+)?\w', line) and | 4765 not Search(r'\bstring\b(\s+const)?\s*[\*\&]\s*(const\s+)?\w', line) and |
| 4959 not Search(r'\boperator\W', line) and | 4766 not Search(r'\boperator\W', line) and |
| 4960 not Match(r'\s*(<.*>)?(::[a-zA-Z0-9_]+)*\s*\(([^"]|$)', match.group(3))): | 4767 not Match(r'\s*(<.*>)?(::[a-zA-Z0-9_]+)*\s*\(([^"]|$)', match.group(4))): |
| 4961 error(filename, linenum, 'runtime/string', 4, | 4768 if Search(r'\bconst\b', line): |
| 4962 'For a static/global string constant, use a C style string instead: ' | 4769 error(filename, linenum, 'runtime/string', 4, |
| 4963 '"%schar %s[]".' % | 4770 'For a static/global string constant, use a C style string ' |
| 4964 (match.group(1), match.group(2))) | 4771 'instead: "%schar%s %s[]".' % |
| 4772 (match.group(1), match.group(2) or '', match.group(3))) |
| 4773 else: |
| 4774 error(filename, linenum, 'runtime/string', 4, |
| 4775 'Static/global string variables are not permitted.') |
| 4965 | 4776 |
| 4966 if Search(r'\b([A-Za-z0-9_]*_)\(\1\)', line): | 4777 if (Search(r'\b([A-Za-z0-9_]*_)\(\1\)', line) or |
| 4778 Search(r'\b([A-Za-z0-9_]*_)\(CHECK_NOTNULL\(\1\)\)', line)): |
| 4967 error(filename, linenum, 'runtime/init', 4, | 4779 error(filename, linenum, 'runtime/init', 4, |
| 4968 'You seem to be initializing a member variable with itself.') | 4780 'You seem to be initializing a member variable with itself.') |
| 4969 | 4781 |
| 4970 | 4782 |
| 4971 def CheckPrintf(filename, clean_lines, linenum, error): | 4783 def CheckPrintf(filename, clean_lines, linenum, error): |
| 4972 """Check for printf related issues. | 4784 """Check for printf related issues. |
| 4973 | 4785 |
| 4974 Args: | 4786 Args: |
| 4975 filename: The name of the current file. | 4787 filename: The name of the current file. |
| 4976 clean_lines: A CleansedLines instance containing the file. | 4788 clean_lines: A CleansedLines instance containing the file. |
| (...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5201 # Don't see a whitelisted function on this line. Actually we | 5013 # Don't see a whitelisted function on this line. Actually we |
| 5202 # didn't see any function name on this line, so this is likely a | 5014 # didn't see any function name on this line, so this is likely a |
| 5203 # multi-line parameter list. Try a bit harder to catch this case. | 5015 # multi-line parameter list. Try a bit harder to catch this case. |
| 5204 for i in xrange(2): | 5016 for i in xrange(2): |
| 5205 if (linenum > i and | 5017 if (linenum > i and |
| 5206 Search(whitelisted_functions, clean_lines.elided[linenum - i - 1])): | 5018 Search(whitelisted_functions, clean_lines.elided[linenum - i - 1])): |
| 5207 return | 5019 return |
| 5208 | 5020 |
| 5209 decls = ReplaceAll(r'{[^}]*}', ' ', line) # exclude function body | 5021 decls = ReplaceAll(r'{[^}]*}', ' ', line) # exclude function body |
| 5210 for parameter in re.findall(_RE_PATTERN_REF_PARAM, decls): | 5022 for parameter in re.findall(_RE_PATTERN_REF_PARAM, decls): |
| 5211 if not Match(_RE_PATTERN_CONST_REF_PARAM, parameter): | 5023 if (not Match(_RE_PATTERN_CONST_REF_PARAM, parameter) and |
| 5024 not Match(_RE_PATTERN_REF_STREAM_PARAM, parameter)): |
| 5212 error(filename, linenum, 'runtime/references', 2, | 5025 error(filename, linenum, 'runtime/references', 2, |
| 5213 'Is this a non-const reference? ' | 5026 'Is this a non-const reference? ' |
| 5214 'If so, make const or use a pointer: ' + | 5027 'If so, make const or use a pointer: ' + |
| 5215 ReplaceAll(' *<', '<', parameter)) | 5028 ReplaceAll(' *<', '<', parameter)) |
| 5216 | 5029 |
| 5217 | 5030 |
| 5218 def CheckCasts(filename, clean_lines, linenum, error): | 5031 def CheckCasts(filename, clean_lines, linenum, error): |
| 5219 """Various cast related checks. | 5032 """Various cast related checks. |
| 5220 | 5033 |
| 5221 Args: | 5034 Args: |
| 5222 filename: The name of the current file. | 5035 filename: The name of the current file. |
| 5223 clean_lines: A CleansedLines instance containing the file. | 5036 clean_lines: A CleansedLines instance containing the file. |
| 5224 linenum: The number of the line to check. | 5037 linenum: The number of the line to check. |
| 5225 error: The function to call with any errors found. | 5038 error: The function to call with any errors found. |
| 5226 """ | 5039 """ |
| 5227 line = clean_lines.elided[linenum] | 5040 line = clean_lines.elided[linenum] |
| 5228 | 5041 |
| 5229 # Check to see if they're using an conversion function cast. | 5042 # Check to see if they're using an conversion function cast. |
| 5230 # I just try to capture the most common basic types, though there are more. | 5043 # I just try to capture the most common basic types, though there are more. |
| 5231 # Parameterless conversion functions, such as bool(), are allowed as they are | 5044 # Parameterless conversion functions, such as bool(), are allowed as they are |
| 5232 # probably a member operator declaration or default constructor. | 5045 # probably a member operator declaration or default constructor. |
| 5233 match = Search( | 5046 match = Search( |
| 5234 r'(\bnew\s+|\S<\s*(?:const\s+)?)?\b' | 5047 r'(\bnew\s+(?:const\s+)?|\S<\s*(?:const\s+)?)?\b' |
| 5235 r'(int|float|double|bool|char|int32|uint32|int64|uint64)' | 5048 r'(int|float|double|bool|char|int32|uint32|int64|uint64)' |
| 5236 r'(\([^)].*)', line) | 5049 r'(\([^)].*)', line) |
| 5237 expecting_function = ExpectingFunctionArgs(clean_lines, linenum) | 5050 expecting_function = ExpectingFunctionArgs(clean_lines, linenum) |
| 5238 if match and not expecting_function: | 5051 if match and not expecting_function: |
| 5239 matched_type = match.group(2) | 5052 matched_type = match.group(2) |
| 5240 | 5053 |
| 5241 # matched_new_or_template is used to silence two false positives: | 5054 # matched_new_or_template is used to silence two false positives: |
| 5242 # - New operators | 5055 # - New operators |
| 5243 # - Template arguments with function types | 5056 # - Template arguments with function types |
| 5244 # | 5057 # |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5365 if linenum > 0: | 5178 if linenum > 0: |
| 5366 for i in xrange(linenum - 1, max(0, linenum - 5), -1): | 5179 for i in xrange(linenum - 1, max(0, linenum - 5), -1): |
| 5367 context = clean_lines.elided[i] + context | 5180 context = clean_lines.elided[i] + context |
| 5368 if Match(r'.*\b[_A-Z][_A-Z0-9]*\s*\((?:\([^()]*\)|[^()])*$', context): | 5181 if Match(r'.*\b[_A-Z][_A-Z0-9]*\s*\((?:\([^()]*\)|[^()])*$', context): |
| 5369 return False | 5182 return False |
| 5370 | 5183 |
| 5371 # operator++(int) and operator--(int) | 5184 # operator++(int) and operator--(int) |
| 5372 if context.endswith(' operator++') or context.endswith(' operator--'): | 5185 if context.endswith(' operator++') or context.endswith(' operator--'): |
| 5373 return False | 5186 return False |
| 5374 | 5187 |
| 5375 # A single unnamed argument for a function tends to look like old | 5188 # A single unnamed argument for a function tends to look like old style cast. |
| 5376 # style cast. If we see those, don't issue warnings for deprecated | 5189 # If we see those, don't issue warnings for deprecated casts. |
| 5377 # casts, instead issue warnings for unnamed arguments where | |
| 5378 # appropriate. | |
| 5379 # | |
| 5380 # These are things that we want warnings for, since the style guide | |
| 5381 # explicitly require all parameters to be named: | |
| 5382 # Function(int); | |
| 5383 # Function(int) { | |
| 5384 # ConstMember(int) const; | |
| 5385 # ConstMember(int) const { | |
| 5386 # ExceptionMember(int) throw (...); | |
| 5387 # ExceptionMember(int) throw (...) { | |
| 5388 # PureVirtual(int) = 0; | |
| 5389 # [](int) -> bool { | |
| 5390 # | |
| 5391 # These are functions of some sort, where the compiler would be fine | |
| 5392 # if they had named parameters, but people often omit those | |
| 5393 # identifiers to reduce clutter: | |
| 5394 # (FunctionPointer)(int); | |
| 5395 # (FunctionPointer)(int) = value; | |
| 5396 # Function((function_pointer_arg)(int)) | |
| 5397 # Function((function_pointer_arg)(int), int param) | |
| 5398 # <TemplateArgument(int)>; | |
| 5399 # <(FunctionPointerTemplateArgument)(int)>; | |
| 5400 remainder = line[match.end(0):] | 5190 remainder = line[match.end(0):] |
| 5401 if Match(r'^\s*(?:;|const\b|throw\b|final\b|override\b|[=>{),]|->)', | 5191 if Match(r'^\s*(?:;|const\b|throw\b|final\b|override\b|[=>{),]|->)', |
| 5402 remainder): | 5192 remainder): |
| 5403 # Looks like an unnamed parameter. | 5193 return False |
| 5404 | |
| 5405 # Don't warn on any kind of template arguments. | |
| 5406 if Match(r'^\s*>', remainder): | |
| 5407 return False | |
| 5408 | |
| 5409 # Don't warn on assignments to function pointers, but keep warnings for | |
| 5410 # unnamed parameters to pure virtual functions. Note that this pattern | |
| 5411 # will also pass on assignments of "0" to function pointers, but the | |
| 5412 # preferred values for those would be "nullptr" or "NULL". | |
| 5413 matched_zero = Match(r'^\s=\s*(\S+)\s*;', remainder) | |
| 5414 if matched_zero and matched_zero.group(1) != '0': | |
| 5415 return False | |
| 5416 | |
| 5417 # Don't warn on function pointer declarations. For this we need | |
| 5418 # to check what came before the "(type)" string. | |
| 5419 if Match(r'.*\)\s*$', line[0:match.start(0)]): | |
| 5420 return False | |
| 5421 | |
| 5422 # Don't warn if the parameter is named with block comments, e.g.: | |
| 5423 # Function(int /*unused_param*/); | |
| 5424 raw_line = clean_lines.raw_lines[linenum] | |
| 5425 if '/*' in raw_line: | |
| 5426 return False | |
| 5427 | |
| 5428 # Passed all filters, issue warning here. | |
| 5429 error(filename, linenum, 'readability/function', 3, | |
| 5430 'All parameters should be named in a function') | |
| 5431 return True | |
| 5432 | 5194 |
| 5433 # At this point, all that should be left is actual casts. | 5195 # At this point, all that should be left is actual casts. |
| 5434 error(filename, linenum, 'readability/casting', 4, | 5196 error(filename, linenum, 'readability/casting', 4, |
| 5435 'Using C-style cast. Use %s<%s>(...) instead' % | 5197 'Using C-style cast. Use %s<%s>(...) instead' % |
| 5436 (cast_type, match.group(1))) | 5198 (cast_type, match.group(1))) |
| 5437 | 5199 |
| 5438 return True | 5200 return True |
| 5439 | 5201 |
| 5440 | 5202 |
| 5441 def ExpectingFunctionArgs(clean_lines, linenum): | 5203 def ExpectingFunctionArgs(clean_lines, linenum): |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5550 Args: | 5312 Args: |
| 5551 filename_cc: is the path for the .cc file | 5313 filename_cc: is the path for the .cc file |
| 5552 filename_h: is the path for the header path | 5314 filename_h: is the path for the header path |
| 5553 | 5315 |
| 5554 Returns: | 5316 Returns: |
| 5555 Tuple with a bool and a string: | 5317 Tuple with a bool and a string: |
| 5556 bool: True if filename_cc and filename_h belong to the same module. | 5318 bool: True if filename_cc and filename_h belong to the same module. |
| 5557 string: the additional prefix needed to open the header file. | 5319 string: the additional prefix needed to open the header file. |
| 5558 """ | 5320 """ |
| 5559 | 5321 |
| 5560 if not filename_cc.endswith('.cc'): | 5322 fileinfo = FileInfo(filename_cc) |
| 5323 if not fileinfo.IsSource(): |
| 5561 return (False, '') | 5324 return (False, '') |
| 5562 filename_cc = filename_cc[:-len('.cc')] | 5325 filename_cc = filename_cc[:-len(fileinfo.Extension())] |
| 5563 if filename_cc.endswith('_unittest'): | 5326 matched_test_suffix = Search(_TEST_FILE_SUFFIX, fileinfo.BaseName()) |
| 5564 filename_cc = filename_cc[:-len('_unittest')] | 5327 if matched_test_suffix: |
| 5565 elif filename_cc.endswith('_test'): | 5328 filename_cc = filename_cc[:-len(matched_test_suffix.group(1))] |
| 5566 filename_cc = filename_cc[:-len('_test')] | |
| 5567 filename_cc = filename_cc.replace('/public/', '/') | 5329 filename_cc = filename_cc.replace('/public/', '/') |
| 5568 filename_cc = filename_cc.replace('/internal/', '/') | 5330 filename_cc = filename_cc.replace('/internal/', '/') |
| 5569 | 5331 |
| 5570 if not filename_h.endswith('.h'): | 5332 if not filename_h.endswith('.h'): |
| 5571 return (False, '') | 5333 return (False, '') |
| 5572 filename_h = filename_h[:-len('.h')] | 5334 filename_h = filename_h[:-len('.h')] |
| 5573 if filename_h.endswith('-inl'): | 5335 if filename_h.endswith('-inl'): |
| 5574 filename_h = filename_h[:-len('-inl')] | 5336 filename_h = filename_h[:-len('-inl')] |
| 5575 filename_h = filename_h.replace('/public/', '/') | 5337 filename_h = filename_h.replace('/public/', '/') |
| 5576 filename_h = filename_h.replace('/internal/', '/') | 5338 filename_h = filename_h.replace('/internal/', '/') |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5720 """ | 5482 """ |
| 5721 line = clean_lines.elided[linenum] | 5483 line = clean_lines.elided[linenum] |
| 5722 match = _RE_PATTERN_EXPLICIT_MAKEPAIR.search(line) | 5484 match = _RE_PATTERN_EXPLICIT_MAKEPAIR.search(line) |
| 5723 if match: | 5485 if match: |
| 5724 error(filename, linenum, 'build/explicit_make_pair', | 5486 error(filename, linenum, 'build/explicit_make_pair', |
| 5725 4, # 4 = high confidence | 5487 4, # 4 = high confidence |
| 5726 'For C++11-compatibility, omit template arguments from make_pair' | 5488 'For C++11-compatibility, omit template arguments from make_pair' |
| 5727 ' OR use pair directly OR if appropriate, construct a pair directly') | 5489 ' OR use pair directly OR if appropriate, construct a pair directly') |
| 5728 | 5490 |
| 5729 | 5491 |
| 5730 def CheckDefaultLambdaCaptures(filename, clean_lines, linenum, error): | |
| 5731 """Check that default lambda captures are not used. | |
| 5732 | |
| 5733 Args: | |
| 5734 filename: The name of the current file. | |
| 5735 clean_lines: A CleansedLines instance containing the file. | |
| 5736 linenum: The number of the line to check. | |
| 5737 error: The function to call with any errors found. | |
| 5738 """ | |
| 5739 line = clean_lines.elided[linenum] | |
| 5740 | |
| 5741 # A lambda introducer specifies a default capture if it starts with "[=" | |
| 5742 # or if it starts with "[&" _not_ followed by an identifier. | |
| 5743 match = Match(r'^(.*)\[\s*(?:=|&[^\w])', line) | |
| 5744 if match: | |
| 5745 # Found a potential error, check what comes after the lambda-introducer. | |
| 5746 # If it's not open parenthesis (for lambda-declarator) or open brace | |
| 5747 # (for compound-statement), it's not a lambda. | |
| 5748 line, _, pos = CloseExpression(clean_lines, linenum, len(match.group(1))) | |
| 5749 if pos >= 0 and Match(r'^\s*[{(]', line[pos:]): | |
| 5750 error(filename, linenum, 'build/c++11', | |
| 5751 4, # 4 = high confidence | |
| 5752 'Default lambda captures are an unapproved C++ feature.') | |
| 5753 | |
| 5754 | |
| 5755 def CheckRedundantVirtual(filename, clean_lines, linenum, error): | 5492 def CheckRedundantVirtual(filename, clean_lines, linenum, error): |
| 5756 """Check if line contains a redundant "virtual" function-specifier. | 5493 """Check if line contains a redundant "virtual" function-specifier. |
| 5757 | 5494 |
| 5758 Args: | 5495 Args: |
| 5759 filename: The name of the current file. | 5496 filename: The name of the current file. |
| 5760 clean_lines: A CleansedLines instance containing the file. | 5497 clean_lines: A CleansedLines instance containing the file. |
| 5761 linenum: The number of the line to check. | 5498 linenum: The number of the line to check. |
| 5762 error: The function to call with any errors found. | 5499 error: The function to call with any errors found. |
| 5763 """ | 5500 """ |
| 5764 # Look for "virtual" on current line. | 5501 # Look for "virtual" on current line. |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5943 CheckStyle(filename, clean_lines, line, file_extension, nesting_state, error) | 5680 CheckStyle(filename, clean_lines, line, file_extension, nesting_state, error) |
| 5944 CheckLanguage(filename, clean_lines, line, file_extension, include_state, | 5681 CheckLanguage(filename, clean_lines, line, file_extension, include_state, |
| 5945 nesting_state, error) | 5682 nesting_state, error) |
| 5946 CheckForNonConstReference(filename, clean_lines, line, nesting_state, error) | 5683 CheckForNonConstReference(filename, clean_lines, line, nesting_state, error) |
| 5947 CheckForNonStandardConstructs(filename, clean_lines, line, | 5684 CheckForNonStandardConstructs(filename, clean_lines, line, |
| 5948 nesting_state, error) | 5685 nesting_state, error) |
| 5949 CheckVlogArguments(filename, clean_lines, line, error) | 5686 CheckVlogArguments(filename, clean_lines, line, error) |
| 5950 CheckPosixThreading(filename, clean_lines, line, error) | 5687 CheckPosixThreading(filename, clean_lines, line, error) |
| 5951 CheckInvalidIncrement(filename, clean_lines, line, error) | 5688 CheckInvalidIncrement(filename, clean_lines, line, error) |
| 5952 CheckMakePairUsesDeduction(filename, clean_lines, line, error) | 5689 CheckMakePairUsesDeduction(filename, clean_lines, line, error) |
| 5953 CheckDefaultLambdaCaptures(filename, clean_lines, line, error) | |
| 5954 CheckRedundantVirtual(filename, clean_lines, line, error) | 5690 CheckRedundantVirtual(filename, clean_lines, line, error) |
| 5955 CheckRedundantOverrideOrFinal(filename, clean_lines, line, error) | 5691 CheckRedundantOverrideOrFinal(filename, clean_lines, line, error) |
| 5956 for check_fn in extra_check_functions: | 5692 for check_fn in extra_check_functions: |
| 5957 check_fn(filename, clean_lines, line, error) | 5693 check_fn(filename, clean_lines, line, error) |
| 5958 | 5694 |
| 5959 def FlagCxx11Features(filename, clean_lines, linenum, error): | 5695 def FlagCxx11Features(filename, clean_lines, linenum, error): |
| 5960 """Flag those c++11 features that we only allow in certain places. | 5696 """Flag those c++11 features that we only allow in certain places. |
| 5961 | 5697 |
| 5962 Args: | 5698 Args: |
| 5963 filename: The name of the current file. | 5699 filename: The name of the current file. |
| 5964 clean_lines: A CleansedLines instance containing the file. | 5700 clean_lines: A CleansedLines instance containing the file. |
| 5965 linenum: The number of the line to check. | 5701 linenum: The number of the line to check. |
| 5966 error: The function to call with any errors found. | 5702 error: The function to call with any errors found. |
| 5967 """ | 5703 """ |
| 5968 line = clean_lines.elided[linenum] | 5704 line = clean_lines.elided[linenum] |
| 5969 | 5705 |
| 5706 include = Match(r'\s*#\s*include\s+[<"]([^<"]+)[">]', line) |
| 5707 |
| 5708 # Flag unapproved C++ TR1 headers. |
| 5709 if include and include.group(1).startswith('tr1/'): |
| 5710 error(filename, linenum, 'build/c++tr1', 5, |
| 5711 ('C++ TR1 headers such as <%s> are unapproved.') % include.group(1)) |
| 5712 |
| 5970 # Flag unapproved C++11 headers. | 5713 # Flag unapproved C++11 headers. |
| 5971 include = Match(r'\s*#\s*include\s+[<"]([^<"]+)[">]', line) | |
| 5972 if include and include.group(1) in ('cfenv', | 5714 if include and include.group(1) in ('cfenv', |
| 5973 'condition_variable', | 5715 'condition_variable', |
| 5974 'fenv.h', | 5716 'fenv.h', |
| 5975 'future', | 5717 'future', |
| 5976 'mutex', | 5718 'mutex', |
| 5977 'thread', | 5719 'thread', |
| 5978 'chrono', | 5720 'chrono', |
| 5979 'ratio', | 5721 'ratio', |
| 5980 'regex', | 5722 'regex', |
| 5981 'system_error', | 5723 'system_error', |
| (...skipping 13 matching lines...) Expand all Loading... |
| 5995 'alignment_of', | 5737 'alignment_of', |
| 5996 'aligned_union', | 5738 'aligned_union', |
| 5997 ): | 5739 ): |
| 5998 if Search(r'\bstd::%s\b' % top_name, line): | 5740 if Search(r'\bstd::%s\b' % top_name, line): |
| 5999 error(filename, linenum, 'build/c++11', 5, | 5741 error(filename, linenum, 'build/c++11', 5, |
| 6000 ('std::%s is an unapproved C++11 class or function. Send c-style ' | 5742 ('std::%s is an unapproved C++11 class or function. Send c-style ' |
| 6001 'an example of where it would make your code more readable, and ' | 5743 'an example of where it would make your code more readable, and ' |
| 6002 'they may let you use it.') % top_name) | 5744 'they may let you use it.') % top_name) |
| 6003 | 5745 |
| 6004 | 5746 |
| 5747 def FlagCxx14Features(filename, clean_lines, linenum, error): |
| 5748 """Flag those C++14 features that we restrict. |
| 5749 |
| 5750 Args: |
| 5751 filename: The name of the current file. |
| 5752 clean_lines: A CleansedLines instance containing the file. |
| 5753 linenum: The number of the line to check. |
| 5754 error: The function to call with any errors found. |
| 5755 """ |
| 5756 line = clean_lines.elided[linenum] |
| 5757 |
| 5758 include = Match(r'\s*#\s*include\s+[<"]([^<"]+)[">]', line) |
| 5759 |
| 5760 # Flag unapproved C++14 headers. |
| 5761 if include and include.group(1) in ('scoped_allocator', 'shared_mutex'): |
| 5762 error(filename, linenum, 'build/c++14', 5, |
| 5763 ('<%s> is an unapproved C++14 header.') % include.group(1)) |
| 5764 |
| 5765 |
| 6005 def ProcessFileData(filename, file_extension, lines, error, | 5766 def ProcessFileData(filename, file_extension, lines, error, |
| 6006 extra_check_functions=[]): | 5767 extra_check_functions=[]): |
| 6007 """Performs lint checks and reports any errors to the given error function. | 5768 """Performs lint checks and reports any errors to the given error function. |
| 6008 | 5769 |
| 6009 Args: | 5770 Args: |
| 6010 filename: Filename of the file that is being processed. | 5771 filename: Filename of the file that is being processed. |
| 6011 file_extension: The extension (dot not included) of the file. | 5772 file_extension: The extension (dot not included) of the file. |
| 6012 lines: An array of strings, each representing a line of the file, with the | 5773 lines: An array of strings, each representing a line of the file, with the |
| 6013 last element being empty if the file is terminated with a newline. | 5774 last element being empty if the file is terminated with a newline. |
| 6014 error: A callable to which errors are reported, which takes 4 arguments: | 5775 error: A callable to which errors are reported, which takes 4 arguments: |
| 6015 filename, line number, error level, and message | 5776 filename, line number, error level, and message |
| 6016 extra_check_functions: An array of additional check functions that will be | 5777 extra_check_functions: An array of additional check functions that will be |
| 6017 run on each source line. Each function takes 4 | 5778 run on each source line. Each function takes 4 |
| 6018 arguments: filename, clean_lines, line, error | 5779 arguments: filename, clean_lines, line, error |
| 6019 """ | 5780 """ |
| 6020 lines = (['// marker so line numbers and indices both start at 1'] + lines + | 5781 lines = (['// marker so line numbers and indices both start at 1'] + lines + |
| 6021 ['// marker so line numbers end in a known way']) | 5782 ['// marker so line numbers end in a known way']) |
| 6022 | 5783 |
| 6023 include_state = _IncludeState() | 5784 include_state = _IncludeState() |
| 6024 function_state = _FunctionState() | 5785 function_state = _FunctionState() |
| 6025 nesting_state = NestingState() | 5786 nesting_state = NestingState() |
| 6026 | 5787 |
| 6027 ResetNolintSuppressions() | 5788 ResetNolintSuppressions() |
| 6028 | 5789 |
| 6029 CheckForCopyright(filename, lines, error) | 5790 CheckForCopyright(filename, lines, error) |
| 6030 | 5791 ProcessGlobalSuppresions(lines) |
| 6031 RemoveMultiLineComments(filename, lines, error) | 5792 RemoveMultiLineComments(filename, lines, error) |
| 6032 clean_lines = CleansedLines(lines) | 5793 clean_lines = CleansedLines(lines) |
| 6033 | 5794 |
| 6034 if file_extension == 'h': | 5795 if file_extension == 'h': |
| 6035 CheckForHeaderGuard(filename, clean_lines, error) | 5796 CheckForHeaderGuard(filename, clean_lines, error) |
| 6036 | 5797 |
| 6037 for line in xrange(clean_lines.NumLines()): | 5798 for line in xrange(clean_lines.NumLines()): |
| 6038 ProcessLine(filename, file_extension, clean_lines, line, | 5799 ProcessLine(filename, file_extension, clean_lines, line, |
| 6039 include_state, function_state, nesting_state, error, | 5800 include_state, function_state, nesting_state, error, |
| 6040 extra_check_functions) | 5801 extra_check_functions) |
| 6041 FlagCxx11Features(filename, clean_lines, line, error) | 5802 FlagCxx11Features(filename, clean_lines, line, error) |
| 6042 nesting_state.CheckCompletedBlocks(filename, error) | 5803 nesting_state.CheckCompletedBlocks(filename, error) |
| 6043 | 5804 |
| 6044 CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error) | 5805 CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error) |
| 6045 | 5806 |
| 6046 # Check that the .cc file has included its header if it exists. | 5807 # Check that the .cc file has included its header if it exists. |
| 6047 if file_extension == 'cc': | 5808 if _IsSourceExtension(file_extension): |
| 6048 CheckHeaderFileIncluded(filename, include_state, error) | 5809 CheckHeaderFileIncluded(filename, include_state, error) |
| 6049 | 5810 |
| 6050 # We check here rather than inside ProcessLine so that we see raw | 5811 # We check here rather than inside ProcessLine so that we see raw |
| 6051 # lines rather than "cleaned" lines. | 5812 # lines rather than "cleaned" lines. |
| 6052 CheckForBadCharacters(filename, lines, error) | 5813 CheckForBadCharacters(filename, lines, error) |
| 6053 | 5814 |
| 6054 CheckForNewlineAtEOF(filename, lines, error) | 5815 CheckForNewlineAtEOF(filename, lines, error) |
| 6055 | 5816 |
| 6056 def ProcessConfigOverrides(filename): | 5817 def ProcessConfigOverrides(filename): |
| 6057 """ Loads the configuration files and processes the config overrides. | 5818 """ Loads the configuration files and processes the config overrides. |
| (...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6322 _cpplint_state.ResetErrorCounts() | 6083 _cpplint_state.ResetErrorCounts() |
| 6323 for filename in filenames: | 6084 for filename in filenames: |
| 6324 ProcessFile(filename, _cpplint_state.verbose_level) | 6085 ProcessFile(filename, _cpplint_state.verbose_level) |
| 6325 _cpplint_state.PrintErrorCounts() | 6086 _cpplint_state.PrintErrorCounts() |
| 6326 | 6087 |
| 6327 sys.exit(_cpplint_state.error_count > 0) | 6088 sys.exit(_cpplint_state.error_count > 0) |
| 6328 | 6089 |
| 6329 | 6090 |
| 6330 if __name__ == '__main__': | 6091 if __name__ == '__main__': |
| 6331 main() | 6092 main() |
| OLD | NEW |