1233d2500723e5594f3e7c70896ffeeef32b9c950ywan#!/usr/bin/python 2233d2500723e5594f3e7c70896ffeeef32b9c950ywan# 3233d2500723e5594f3e7c70896ffeeef32b9c950ywan# Copyright (c) 2009 Google Inc. All rights reserved. 4233d2500723e5594f3e7c70896ffeeef32b9c950ywan# 5233d2500723e5594f3e7c70896ffeeef32b9c950ywan# Redistribution and use in source and binary forms, with or without 6233d2500723e5594f3e7c70896ffeeef32b9c950ywan# modification, are permitted provided that the following conditions are 7233d2500723e5594f3e7c70896ffeeef32b9c950ywan# met: 8233d2500723e5594f3e7c70896ffeeef32b9c950ywan# 9233d2500723e5594f3e7c70896ffeeef32b9c950ywan# * Redistributions of source code must retain the above copyright 10233d2500723e5594f3e7c70896ffeeef32b9c950ywan# notice, this list of conditions and the following disclaimer. 11233d2500723e5594f3e7c70896ffeeef32b9c950ywan# * Redistributions in binary form must reproduce the above 12233d2500723e5594f3e7c70896ffeeef32b9c950ywan# copyright notice, this list of conditions and the following disclaimer 13233d2500723e5594f3e7c70896ffeeef32b9c950ywan# in the documentation and/or other materials provided with the 14233d2500723e5594f3e7c70896ffeeef32b9c950ywan# distribution. 15233d2500723e5594f3e7c70896ffeeef32b9c950ywan# * Neither the name of Google Inc. nor the names of its 16233d2500723e5594f3e7c70896ffeeef32b9c950ywan# contributors may be used to endorse or promote products derived from 17233d2500723e5594f3e7c70896ffeeef32b9c950ywan# this software without specific prior written permission. 18233d2500723e5594f3e7c70896ffeeef32b9c950ywan# 19233d2500723e5594f3e7c70896ffeeef32b9c950ywan# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20233d2500723e5594f3e7c70896ffeeef32b9c950ywan# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21233d2500723e5594f3e7c70896ffeeef32b9c950ywan# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22233d2500723e5594f3e7c70896ffeeef32b9c950ywan# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23233d2500723e5594f3e7c70896ffeeef32b9c950ywan# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24233d2500723e5594f3e7c70896ffeeef32b9c950ywan# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25233d2500723e5594f3e7c70896ffeeef32b9c950ywan# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26233d2500723e5594f3e7c70896ffeeef32b9c950ywan# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27233d2500723e5594f3e7c70896ffeeef32b9c950ywan# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28233d2500723e5594f3e7c70896ffeeef32b9c950ywan# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29233d2500723e5594f3e7c70896ffeeef32b9c950ywan# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30233d2500723e5594f3e7c70896ffeeef32b9c950ywan 31233d2500723e5594f3e7c70896ffeeef32b9c950ywan"""Does google-lint on c++ files. 32233d2500723e5594f3e7c70896ffeeef32b9c950ywan 33233d2500723e5594f3e7c70896ffeeef32b9c950ywanThe goal of this script is to identify places in the code that *may* 34233d2500723e5594f3e7c70896ffeeef32b9c950ywanbe in non-compliance with google style. It does not attempt to fix 35233d2500723e5594f3e7c70896ffeeef32b9c950ywanup these problems -- the point is to educate. It does also not 36233d2500723e5594f3e7c70896ffeeef32b9c950ywanattempt to find all problems, or to ensure that everything it does 37233d2500723e5594f3e7c70896ffeeef32b9c950ywanfind is legitimately a problem. 38233d2500723e5594f3e7c70896ffeeef32b9c950ywan 39233d2500723e5594f3e7c70896ffeeef32b9c950ywanIn particular, we can get very confused by /* and // inside strings! 40233d2500723e5594f3e7c70896ffeeef32b9c950ywanWe do a small hack, which is to ignore //'s with "'s after them on the 41233d2500723e5594f3e7c70896ffeeef32b9c950ywansame line, but it is far from perfect (in either direction). 42233d2500723e5594f3e7c70896ffeeef32b9c950ywan""" 43233d2500723e5594f3e7c70896ffeeef32b9c950ywan 44233d2500723e5594f3e7c70896ffeeef32b9c950ywanimport codecs 45233d2500723e5594f3e7c70896ffeeef32b9c950ywanimport copy 46233d2500723e5594f3e7c70896ffeeef32b9c950ywanimport getopt 47233d2500723e5594f3e7c70896ffeeef32b9c950ywanimport math # for log 48233d2500723e5594f3e7c70896ffeeef32b9c950ywanimport os 49233d2500723e5594f3e7c70896ffeeef32b9c950ywanimport re 50233d2500723e5594f3e7c70896ffeeef32b9c950ywanimport sre_compile 51233d2500723e5594f3e7c70896ffeeef32b9c950ywanimport string 52233d2500723e5594f3e7c70896ffeeef32b9c950ywanimport sys 53233d2500723e5594f3e7c70896ffeeef32b9c950ywanimport unicodedata 54233d2500723e5594f3e7c70896ffeeef32b9c950ywan 55233d2500723e5594f3e7c70896ffeeef32b9c950ywan 56233d2500723e5594f3e7c70896ffeeef32b9c950ywan_USAGE = """ 57233d2500723e5594f3e7c70896ffeeef32b9c950ywanSyntax: cpplint.py [--verbose=#] [--output=vs7] [--filter=-x,+y,...] 58233d2500723e5594f3e7c70896ffeeef32b9c950ywan [--counting=total|toplevel|detailed] [--root=subdir] 59233d2500723e5594f3e7c70896ffeeef32b9c950ywan [--linelength=digits] 60233d2500723e5594f3e7c70896ffeeef32b9c950ywan <file> [file] ... 61233d2500723e5594f3e7c70896ffeeef32b9c950ywan 62233d2500723e5594f3e7c70896ffeeef32b9c950ywan The style guidelines this tries to follow are those in 63233d2500723e5594f3e7c70896ffeeef32b9c950ywan http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml 64233d2500723e5594f3e7c70896ffeeef32b9c950ywan 65233d2500723e5594f3e7c70896ffeeef32b9c950ywan Every problem is given a confidence score from 1-5, with 5 meaning we are 66233d2500723e5594f3e7c70896ffeeef32b9c950ywan certain of the problem, and 1 meaning it could be a legitimate construct. 67233d2500723e5594f3e7c70896ffeeef32b9c950ywan This will miss some errors, and is not a substitute for a code review. 68233d2500723e5594f3e7c70896ffeeef32b9c950ywan 69233d2500723e5594f3e7c70896ffeeef32b9c950ywan To suppress false-positive errors of a certain category, add a 70233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'NOLINT(category)' comment to the line. NOLINT or NOLINT(*) 71233d2500723e5594f3e7c70896ffeeef32b9c950ywan suppresses errors of all categories on that line. 72233d2500723e5594f3e7c70896ffeeef32b9c950ywan 73233d2500723e5594f3e7c70896ffeeef32b9c950ywan The files passed in will be linted; at least one file must be provided. 74233d2500723e5594f3e7c70896ffeeef32b9c950ywan Default linted extensions are .cc, .cpp, .cu, .cuh and .h. Change the 75233d2500723e5594f3e7c70896ffeeef32b9c950ywan extensions with the --extensions flag. 76233d2500723e5594f3e7c70896ffeeef32b9c950ywan 77233d2500723e5594f3e7c70896ffeeef32b9c950ywan Flags: 78233d2500723e5594f3e7c70896ffeeef32b9c950ywan 79233d2500723e5594f3e7c70896ffeeef32b9c950ywan output=vs7 80233d2500723e5594f3e7c70896ffeeef32b9c950ywan By default, the output is formatted to ease emacs parsing. Visual Studio 81233d2500723e5594f3e7c70896ffeeef32b9c950ywan compatible output (vs7) may also be used. Other formats are unsupported. 82233d2500723e5594f3e7c70896ffeeef32b9c950ywan 83233d2500723e5594f3e7c70896ffeeef32b9c950ywan verbose=# 84233d2500723e5594f3e7c70896ffeeef32b9c950ywan Specify a number 0-5 to restrict errors to certain verbosity levels. 85233d2500723e5594f3e7c70896ffeeef32b9c950ywan 86233d2500723e5594f3e7c70896ffeeef32b9c950ywan filter=-x,+y,... 87233d2500723e5594f3e7c70896ffeeef32b9c950ywan Specify a comma-separated list of category-filters to apply: only 88233d2500723e5594f3e7c70896ffeeef32b9c950ywan error messages whose category names pass the filters will be printed. 89233d2500723e5594f3e7c70896ffeeef32b9c950ywan (Category names are printed with the message and look like 90233d2500723e5594f3e7c70896ffeeef32b9c950ywan "[whitespace/indent]".) Filters are evaluated left to right. 91233d2500723e5594f3e7c70896ffeeef32b9c950ywan "-FOO" and "FOO" means "do not print categories that start with FOO". 92233d2500723e5594f3e7c70896ffeeef32b9c950ywan "+FOO" means "do print categories that start with FOO". 93233d2500723e5594f3e7c70896ffeeef32b9c950ywan 94233d2500723e5594f3e7c70896ffeeef32b9c950ywan Examples: --filter=-whitespace,+whitespace/braces 95233d2500723e5594f3e7c70896ffeeef32b9c950ywan --filter=whitespace,runtime/printf,+runtime/printf_format 96233d2500723e5594f3e7c70896ffeeef32b9c950ywan --filter=-,+build/include_what_you_use 97233d2500723e5594f3e7c70896ffeeef32b9c950ywan 98233d2500723e5594f3e7c70896ffeeef32b9c950ywan To see a list of all the categories used in cpplint, pass no arg: 99233d2500723e5594f3e7c70896ffeeef32b9c950ywan --filter= 100233d2500723e5594f3e7c70896ffeeef32b9c950ywan 101233d2500723e5594f3e7c70896ffeeef32b9c950ywan counting=total|toplevel|detailed 102233d2500723e5594f3e7c70896ffeeef32b9c950ywan The total number of errors found is always printed. If 103233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'toplevel' is provided, then the count of errors in each of 104233d2500723e5594f3e7c70896ffeeef32b9c950ywan the top-level categories like 'build' and 'whitespace' will 105233d2500723e5594f3e7c70896ffeeef32b9c950ywan also be printed. If 'detailed' is provided, then a count 106233d2500723e5594f3e7c70896ffeeef32b9c950ywan is provided for each category like 'build/class'. 107233d2500723e5594f3e7c70896ffeeef32b9c950ywan 108233d2500723e5594f3e7c70896ffeeef32b9c950ywan root=subdir 109233d2500723e5594f3e7c70896ffeeef32b9c950ywan The root directory used for deriving header guard CPP variable. 110233d2500723e5594f3e7c70896ffeeef32b9c950ywan By default, the header guard CPP variable is calculated as the relative 111233d2500723e5594f3e7c70896ffeeef32b9c950ywan path to the directory that contains .git, .hg, or .svn. When this flag 112233d2500723e5594f3e7c70896ffeeef32b9c950ywan is specified, the relative path is calculated from the specified 113233d2500723e5594f3e7c70896ffeeef32b9c950ywan directory. If the specified directory does not exist, this flag is 114233d2500723e5594f3e7c70896ffeeef32b9c950ywan ignored. 115233d2500723e5594f3e7c70896ffeeef32b9c950ywan 116233d2500723e5594f3e7c70896ffeeef32b9c950ywan Examples: 117233d2500723e5594f3e7c70896ffeeef32b9c950ywan Assuing that src/.git exists, the header guard CPP variables for 118233d2500723e5594f3e7c70896ffeeef32b9c950ywan src/chrome/browser/ui/browser.h are: 119233d2500723e5594f3e7c70896ffeeef32b9c950ywan 120233d2500723e5594f3e7c70896ffeeef32b9c950ywan No flag => CHROME_BROWSER_UI_BROWSER_H_ 121233d2500723e5594f3e7c70896ffeeef32b9c950ywan --root=chrome => BROWSER_UI_BROWSER_H_ 122233d2500723e5594f3e7c70896ffeeef32b9c950ywan --root=chrome/browser => UI_BROWSER_H_ 123233d2500723e5594f3e7c70896ffeeef32b9c950ywan 124233d2500723e5594f3e7c70896ffeeef32b9c950ywan linelength=digits 125233d2500723e5594f3e7c70896ffeeef32b9c950ywan This is the allowed line length for the project. The default value is 126233d2500723e5594f3e7c70896ffeeef32b9c950ywan 80 characters. 127233d2500723e5594f3e7c70896ffeeef32b9c950ywan 128233d2500723e5594f3e7c70896ffeeef32b9c950ywan Examples: 129233d2500723e5594f3e7c70896ffeeef32b9c950ywan --linelength=120 130233d2500723e5594f3e7c70896ffeeef32b9c950ywan 131233d2500723e5594f3e7c70896ffeeef32b9c950ywan extensions=extension,extension,... 132233d2500723e5594f3e7c70896ffeeef32b9c950ywan The allowed file extensions that cpplint will check 133233d2500723e5594f3e7c70896ffeeef32b9c950ywan 134233d2500723e5594f3e7c70896ffeeef32b9c950ywan Examples: 135233d2500723e5594f3e7c70896ffeeef32b9c950ywan --extensions=hpp,cpp 136233d2500723e5594f3e7c70896ffeeef32b9c950ywan""" 137233d2500723e5594f3e7c70896ffeeef32b9c950ywan 138233d2500723e5594f3e7c70896ffeeef32b9c950ywan# We categorize each error message we print. Here are the categories. 139233d2500723e5594f3e7c70896ffeeef32b9c950ywan# We want an explicit list so we can list them all in cpplint --filter=. 140233d2500723e5594f3e7c70896ffeeef32b9c950ywan# If you add a new error message with a new category, add it to the list 141233d2500723e5594f3e7c70896ffeeef32b9c950ywan# here! cpplint_unittest.py should tell you if you forget to do this. 142233d2500723e5594f3e7c70896ffeeef32b9c950ywan_ERROR_CATEGORIES = [ 143233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'build/class', 144233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'build/deprecated', 145233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'build/endif_comment', 146233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'build/explicit_make_pair', 147233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'build/forward_decl', 148233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'build/header_guard', 149233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'build/include', 150233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'build/include_alpha', 151233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'build/include_order', 152233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'build/include_what_you_use', 153233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'build/namespaces', 154233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'build/printf_format', 155233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'build/storage_class', 156233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'legal/copyright', 157233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'readability/alt_tokens', 158233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'readability/braces', 159233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'readability/casting', 160233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'readability/check', 161233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'readability/constructors', 162233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'readability/fn_size', 163233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'readability/function', 164233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'readability/multiline_comment', 165233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'readability/multiline_string', 166233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'readability/namespace', 167233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'readability/nolint', 168233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'readability/nul', 169233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'readability/streams', 170233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'readability/todo', 171233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'readability/utf8', 172233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'runtime/arrays', 173233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'runtime/casting', 174233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'runtime/explicit', 175233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'runtime/int', 176233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'runtime/init', 177233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'runtime/invalid_increment', 178233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'runtime/member_string_references', 179233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'runtime/memset', 180233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'runtime/operator', 181233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'runtime/printf', 182233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'runtime/printf_format', 183233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'runtime/references', 184233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'runtime/sizeof', 185233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'runtime/string', 186233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'runtime/threadsafe_fn', 187233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'runtime/vlog', 188233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'whitespace/blank_line', 189233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'whitespace/braces', 190233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'whitespace/comma', 191233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'whitespace/comments', 192233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'whitespace/empty_conditional_body', 193233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'whitespace/empty_loop_body', 194233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'whitespace/end_of_line', 195233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'whitespace/ending_newline', 196233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'whitespace/forcolon', 197233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'whitespace/indent', 198233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'whitespace/line_length', 199233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'whitespace/newline', 200233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'whitespace/operators', 201233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'whitespace/parens', 202233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'whitespace/semicolon', 203233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'whitespace/tab', 204233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'whitespace/todo' 205233d2500723e5594f3e7c70896ffeeef32b9c950ywan ] 206233d2500723e5594f3e7c70896ffeeef32b9c950ywan 207233d2500723e5594f3e7c70896ffeeef32b9c950ywan# The default state of the category filter. This is overrided by the --filter= 208233d2500723e5594f3e7c70896ffeeef32b9c950ywan# flag. By default all errors are on, so only add here categories that should be 209233d2500723e5594f3e7c70896ffeeef32b9c950ywan# off by default (i.e., categories that must be enabled by the --filter= flags). 210233d2500723e5594f3e7c70896ffeeef32b9c950ywan# All entries here should start with a '-' or '+', as in the --filter= flag. 211233d2500723e5594f3e7c70896ffeeef32b9c950ywan_DEFAULT_FILTERS = ['-build/include_alpha'] 212233d2500723e5594f3e7c70896ffeeef32b9c950ywan 213233d2500723e5594f3e7c70896ffeeef32b9c950ywan# We used to check for high-bit characters, but after much discussion we 214233d2500723e5594f3e7c70896ffeeef32b9c950ywan# decided those were OK, as long as they were in UTF-8 and didn't represent 215233d2500723e5594f3e7c70896ffeeef32b9c950ywan# hard-coded international strings, which belong in a separate i18n file. 216233d2500723e5594f3e7c70896ffeeef32b9c950ywan 217233d2500723e5594f3e7c70896ffeeef32b9c950ywan 218233d2500723e5594f3e7c70896ffeeef32b9c950ywan# C++ headers 219233d2500723e5594f3e7c70896ffeeef32b9c950ywan_CPP_HEADERS = frozenset([ 220233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Legacy 221233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'algobase.h', 222233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'algo.h', 223233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'alloc.h', 224233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'builtinbuf.h', 225233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'bvector.h', 226233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'complex.h', 227233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'defalloc.h', 228233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'deque.h', 229233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'editbuf.h', 230233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'fstream.h', 231233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'function.h', 232233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'hash_map', 233233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'hash_map.h', 234233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'hash_set', 235233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'hash_set.h', 236233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'hashtable.h', 237233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'heap.h', 238233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'indstream.h', 239233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'iomanip.h', 240233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'iostream.h', 241233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'istream.h', 242233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'iterator.h', 243233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'list.h', 244233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'map.h', 245233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'multimap.h', 246233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'multiset.h', 247233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'ostream.h', 248233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'pair.h', 249233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'parsestream.h', 250233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'pfstream.h', 251233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'procbuf.h', 252233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'pthread_alloc', 253233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'pthread_alloc.h', 254233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'rope', 255233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'rope.h', 256233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'ropeimpl.h', 257233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'set.h', 258233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'slist', 259233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'slist.h', 260233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'stack.h', 261233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'stdiostream.h', 262233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'stl_alloc.h', 263233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'stl_relops.h', 264233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'streambuf.h', 265233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'stream.h', 266233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'strfile.h', 267233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'strstream.h', 268233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'tempbuf.h', 269233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'tree.h', 270233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'type_traits.h', 271233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'vector.h', 272233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 17.6.1.2 C++ library headers 273233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'algorithm', 274233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'array', 275233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'atomic', 276233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'bitset', 277233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'chrono', 278233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'codecvt', 279233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'complex', 280233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'condition_variable', 281233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'deque', 282233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'exception', 283233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'forward_list', 284233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'fstream', 285233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'functional', 286233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'future', 287233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'initializer_list', 288233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'iomanip', 289233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'ios', 290233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'iosfwd', 291233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'iostream', 292233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'istream', 293233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'iterator', 294233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'limits', 295233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'list', 296233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'locale', 297233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'map', 298233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'memory', 299233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'mutex', 300233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'new', 301233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'numeric', 302233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'ostream', 303233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'queue', 304233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'random', 305233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'ratio', 306233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'regex', 307233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'set', 308233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'sstream', 309233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'stack', 310233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'stdexcept', 311233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'streambuf', 312233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'string', 313233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'strstream', 314233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'system_error', 315233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'thread', 316233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'tuple', 317233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'typeindex', 318233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'typeinfo', 319233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'type_traits', 320233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'unordered_map', 321233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'unordered_set', 322233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'utility', 323233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'valarray', 324233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'vector', 325233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 17.6.1.2 C++ headers for C library facilities 326233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'cassert', 327233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'ccomplex', 328233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'cctype', 329233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'cerrno', 330233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'cfenv', 331233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'cfloat', 332233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'cinttypes', 333233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'ciso646', 334233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'climits', 335233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'clocale', 336233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'cmath', 337233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'csetjmp', 338233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'csignal', 339233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'cstdalign', 340233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'cstdarg', 341233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'cstdbool', 342233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'cstddef', 343233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'cstdint', 344233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'cstdio', 345233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'cstdlib', 346233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'cstring', 347233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'ctgmath', 348233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'ctime', 349233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'cuchar', 350233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'cwchar', 351233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'cwctype', 352233d2500723e5594f3e7c70896ffeeef32b9c950ywan ]) 353233d2500723e5594f3e7c70896ffeeef32b9c950ywan 354233d2500723e5594f3e7c70896ffeeef32b9c950ywan# Assertion macros. These are defined in base/logging.h and 355233d2500723e5594f3e7c70896ffeeef32b9c950ywan# testing/base/gunit.h. Note that the _M versions need to come first 356233d2500723e5594f3e7c70896ffeeef32b9c950ywan# for substring matching to work. 357233d2500723e5594f3e7c70896ffeeef32b9c950ywan_CHECK_MACROS = [ 358233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'DCHECK', 'CHECK', 359233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'EXPECT_TRUE_M', 'EXPECT_TRUE', 360233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'ASSERT_TRUE_M', 'ASSERT_TRUE', 361233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'EXPECT_FALSE_M', 'EXPECT_FALSE', 362233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'ASSERT_FALSE_M', 'ASSERT_FALSE', 363233d2500723e5594f3e7c70896ffeeef32b9c950ywan ] 364233d2500723e5594f3e7c70896ffeeef32b9c950ywan 365233d2500723e5594f3e7c70896ffeeef32b9c950ywan# Replacement macros for CHECK/DCHECK/EXPECT_TRUE/EXPECT_FALSE 366233d2500723e5594f3e7c70896ffeeef32b9c950ywan_CHECK_REPLACEMENT = dict([(m, {}) for m in _CHECK_MACROS]) 367233d2500723e5594f3e7c70896ffeeef32b9c950ywan 368233d2500723e5594f3e7c70896ffeeef32b9c950ywanfor op, replacement in [('==', 'EQ'), ('!=', 'NE'), 369233d2500723e5594f3e7c70896ffeeef32b9c950ywan ('>=', 'GE'), ('>', 'GT'), 370233d2500723e5594f3e7c70896ffeeef32b9c950ywan ('<=', 'LE'), ('<', 'LT')]: 371233d2500723e5594f3e7c70896ffeeef32b9c950ywan _CHECK_REPLACEMENT['DCHECK'][op] = 'DCHECK_%s' % replacement 372233d2500723e5594f3e7c70896ffeeef32b9c950ywan _CHECK_REPLACEMENT['CHECK'][op] = 'CHECK_%s' % replacement 373233d2500723e5594f3e7c70896ffeeef32b9c950ywan _CHECK_REPLACEMENT['EXPECT_TRUE'][op] = 'EXPECT_%s' % replacement 374233d2500723e5594f3e7c70896ffeeef32b9c950ywan _CHECK_REPLACEMENT['ASSERT_TRUE'][op] = 'ASSERT_%s' % replacement 375233d2500723e5594f3e7c70896ffeeef32b9c950ywan _CHECK_REPLACEMENT['EXPECT_TRUE_M'][op] = 'EXPECT_%s_M' % replacement 376233d2500723e5594f3e7c70896ffeeef32b9c950ywan _CHECK_REPLACEMENT['ASSERT_TRUE_M'][op] = 'ASSERT_%s_M' % replacement 377233d2500723e5594f3e7c70896ffeeef32b9c950ywan 378233d2500723e5594f3e7c70896ffeeef32b9c950ywanfor op, inv_replacement in [('==', 'NE'), ('!=', 'EQ'), 379233d2500723e5594f3e7c70896ffeeef32b9c950ywan ('>=', 'LT'), ('>', 'LE'), 380233d2500723e5594f3e7c70896ffeeef32b9c950ywan ('<=', 'GT'), ('<', 'GE')]: 381233d2500723e5594f3e7c70896ffeeef32b9c950ywan _CHECK_REPLACEMENT['EXPECT_FALSE'][op] = 'EXPECT_%s' % inv_replacement 382233d2500723e5594f3e7c70896ffeeef32b9c950ywan _CHECK_REPLACEMENT['ASSERT_FALSE'][op] = 'ASSERT_%s' % inv_replacement 383233d2500723e5594f3e7c70896ffeeef32b9c950ywan _CHECK_REPLACEMENT['EXPECT_FALSE_M'][op] = 'EXPECT_%s_M' % inv_replacement 384233d2500723e5594f3e7c70896ffeeef32b9c950ywan _CHECK_REPLACEMENT['ASSERT_FALSE_M'][op] = 'ASSERT_%s_M' % inv_replacement 385233d2500723e5594f3e7c70896ffeeef32b9c950ywan 386233d2500723e5594f3e7c70896ffeeef32b9c950ywan# Alternative tokens and their replacements. For full list, see section 2.5 387233d2500723e5594f3e7c70896ffeeef32b9c950ywan# Alternative tokens [lex.digraph] in the C++ standard. 388233d2500723e5594f3e7c70896ffeeef32b9c950ywan# 389233d2500723e5594f3e7c70896ffeeef32b9c950ywan# Digraphs (such as '%:') are not included here since it's a mess to 390233d2500723e5594f3e7c70896ffeeef32b9c950ywan# match those on a word boundary. 391233d2500723e5594f3e7c70896ffeeef32b9c950ywan_ALT_TOKEN_REPLACEMENT = { 392233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'and': '&&', 393233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'bitor': '|', 394233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'or': '||', 395233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'xor': '^', 396233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'compl': '~', 397233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'bitand': '&', 398233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'and_eq': '&=', 399233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'or_eq': '|=', 400233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'xor_eq': '^=', 401233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'not': '!', 402233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'not_eq': '!=' 403233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 404233d2500723e5594f3e7c70896ffeeef32b9c950ywan 405233d2500723e5594f3e7c70896ffeeef32b9c950ywan# Compile regular expression that matches all the above keywords. The "[ =()]" 406233d2500723e5594f3e7c70896ffeeef32b9c950ywan# bit is meant to avoid matching these keywords outside of boolean expressions. 407233d2500723e5594f3e7c70896ffeeef32b9c950ywan# 408233d2500723e5594f3e7c70896ffeeef32b9c950ywan# False positives include C-style multi-line comments and multi-line strings 409233d2500723e5594f3e7c70896ffeeef32b9c950ywan# but those have always been troublesome for cpplint. 410233d2500723e5594f3e7c70896ffeeef32b9c950ywan_ALT_TOKEN_REPLACEMENT_PATTERN = re.compile( 411233d2500723e5594f3e7c70896ffeeef32b9c950ywan r'[ =()](' + ('|'.join(_ALT_TOKEN_REPLACEMENT.keys())) + r')(?=[ (]|$)') 412233d2500723e5594f3e7c70896ffeeef32b9c950ywan 413233d2500723e5594f3e7c70896ffeeef32b9c950ywan 414233d2500723e5594f3e7c70896ffeeef32b9c950ywan# These constants define types of headers for use with 415233d2500723e5594f3e7c70896ffeeef32b9c950ywan# _IncludeState.CheckNextIncludeOrder(). 416233d2500723e5594f3e7c70896ffeeef32b9c950ywan_C_SYS_HEADER = 1 417233d2500723e5594f3e7c70896ffeeef32b9c950ywan_CPP_SYS_HEADER = 2 418233d2500723e5594f3e7c70896ffeeef32b9c950ywan_LIKELY_MY_HEADER = 3 419233d2500723e5594f3e7c70896ffeeef32b9c950ywan_POSSIBLE_MY_HEADER = 4 420233d2500723e5594f3e7c70896ffeeef32b9c950ywan_OTHER_HEADER = 5 421233d2500723e5594f3e7c70896ffeeef32b9c950ywan 422233d2500723e5594f3e7c70896ffeeef32b9c950ywan# These constants define the current inline assembly state 423233d2500723e5594f3e7c70896ffeeef32b9c950ywan_NO_ASM = 0 # Outside of inline assembly block 424233d2500723e5594f3e7c70896ffeeef32b9c950ywan_INSIDE_ASM = 1 # Inside inline assembly block 425233d2500723e5594f3e7c70896ffeeef32b9c950ywan_END_ASM = 2 # Last line of inline assembly block 426233d2500723e5594f3e7c70896ffeeef32b9c950ywan_BLOCK_ASM = 3 # The whole block is an inline assembly block 427233d2500723e5594f3e7c70896ffeeef32b9c950ywan 428233d2500723e5594f3e7c70896ffeeef32b9c950ywan# Match start of assembly blocks 429233d2500723e5594f3e7c70896ffeeef32b9c950ywan_MATCH_ASM = re.compile(r'^\s*(?:asm|_asm|__asm|__asm__)' 430233d2500723e5594f3e7c70896ffeeef32b9c950ywan r'(?:\s+(volatile|__volatile__))?' 431233d2500723e5594f3e7c70896ffeeef32b9c950ywan r'\s*[{(]') 432233d2500723e5594f3e7c70896ffeeef32b9c950ywan 433233d2500723e5594f3e7c70896ffeeef32b9c950ywan 434233d2500723e5594f3e7c70896ffeeef32b9c950ywan_regexp_compile_cache = {} 435233d2500723e5594f3e7c70896ffeeef32b9c950ywan 436233d2500723e5594f3e7c70896ffeeef32b9c950ywan# Finds occurrences of NOLINT or NOLINT(...). 437233d2500723e5594f3e7c70896ffeeef32b9c950ywan_RE_SUPPRESSION = re.compile(r'\bNOLINT\b(\([^)]*\))?') 438233d2500723e5594f3e7c70896ffeeef32b9c950ywan 439233d2500723e5594f3e7c70896ffeeef32b9c950ywan# {str, set(int)}: a map from error categories to sets of linenumbers 440233d2500723e5594f3e7c70896ffeeef32b9c950ywan# on which those errors are expected and should be suppressed. 441233d2500723e5594f3e7c70896ffeeef32b9c950ywan_error_suppressions = {} 442233d2500723e5594f3e7c70896ffeeef32b9c950ywan 443233d2500723e5594f3e7c70896ffeeef32b9c950ywan# The root directory used for deriving header guard CPP variable. 444233d2500723e5594f3e7c70896ffeeef32b9c950ywan# This is set by --root flag. 445233d2500723e5594f3e7c70896ffeeef32b9c950ywan_root = None 446233d2500723e5594f3e7c70896ffeeef32b9c950ywan 447233d2500723e5594f3e7c70896ffeeef32b9c950ywan# The allowed line length of files. 448233d2500723e5594f3e7c70896ffeeef32b9c950ywan# This is set by --linelength flag. 449233d2500723e5594f3e7c70896ffeeef32b9c950ywan_line_length = 80 450233d2500723e5594f3e7c70896ffeeef32b9c950ywan 451233d2500723e5594f3e7c70896ffeeef32b9c950ywan# The allowed extensions for file names 452233d2500723e5594f3e7c70896ffeeef32b9c950ywan# This is set by --extensions flag. 453233d2500723e5594f3e7c70896ffeeef32b9c950ywan_valid_extensions = set(['cc', 'h', 'cpp', 'cu', 'cuh']) 454233d2500723e5594f3e7c70896ffeeef32b9c950ywan 455233d2500723e5594f3e7c70896ffeeef32b9c950ywandef ParseNolintSuppressions(filename, raw_line, linenum, error): 456233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Updates the global list of error-suppressions. 457233d2500723e5594f3e7c70896ffeeef32b9c950ywan 458233d2500723e5594f3e7c70896ffeeef32b9c950ywan Parses any NOLINT comments on the current line, updating the global 459233d2500723e5594f3e7c70896ffeeef32b9c950ywan error_suppressions store. Reports an error if the NOLINT comment 460233d2500723e5594f3e7c70896ffeeef32b9c950ywan was malformed. 461233d2500723e5594f3e7c70896ffeeef32b9c950ywan 462233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 463233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename: str, the name of the input file. 464233d2500723e5594f3e7c70896ffeeef32b9c950ywan raw_line: str, the line of input text, with comments. 465233d2500723e5594f3e7c70896ffeeef32b9c950ywan linenum: int, the number of the current line. 466233d2500723e5594f3e7c70896ffeeef32b9c950ywan error: function, an error handler. 467233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 468233d2500723e5594f3e7c70896ffeeef32b9c950ywan # FIXME(adonovan): "NOLINT(" is misparsed as NOLINT(*). 469233d2500723e5594f3e7c70896ffeeef32b9c950ywan matched = _RE_SUPPRESSION.search(raw_line) 470233d2500723e5594f3e7c70896ffeeef32b9c950ywan if matched: 471233d2500723e5594f3e7c70896ffeeef32b9c950ywan category = matched.group(1) 472233d2500723e5594f3e7c70896ffeeef32b9c950ywan if category in (None, '(*)'): # => "suppress all" 473233d2500723e5594f3e7c70896ffeeef32b9c950ywan _error_suppressions.setdefault(None, set()).add(linenum) 474233d2500723e5594f3e7c70896ffeeef32b9c950ywan else: 475233d2500723e5594f3e7c70896ffeeef32b9c950ywan if category.startswith('(') and category.endswith(')'): 476233d2500723e5594f3e7c70896ffeeef32b9c950ywan category = category[1:-1] 477233d2500723e5594f3e7c70896ffeeef32b9c950ywan if category in _ERROR_CATEGORIES: 478233d2500723e5594f3e7c70896ffeeef32b9c950ywan _error_suppressions.setdefault(category, set()).add(linenum) 479233d2500723e5594f3e7c70896ffeeef32b9c950ywan else: 480233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'readability/nolint', 5, 481233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Unknown NOLINT error category: %s' % category) 482233d2500723e5594f3e7c70896ffeeef32b9c950ywan 483233d2500723e5594f3e7c70896ffeeef32b9c950ywan 484233d2500723e5594f3e7c70896ffeeef32b9c950ywandef ResetNolintSuppressions(): 485233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Resets the set of NOLINT suppressions to empty." 486233d2500723e5594f3e7c70896ffeeef32b9c950ywan _error_suppressions.clear() 487233d2500723e5594f3e7c70896ffeeef32b9c950ywan 488233d2500723e5594f3e7c70896ffeeef32b9c950ywan 489233d2500723e5594f3e7c70896ffeeef32b9c950ywandef IsErrorSuppressedByNolint(category, linenum): 490233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Returns true if the specified error category is suppressed on this line. 491233d2500723e5594f3e7c70896ffeeef32b9c950ywan 492233d2500723e5594f3e7c70896ffeeef32b9c950ywan Consults the global error_suppressions map populated by 493233d2500723e5594f3e7c70896ffeeef32b9c950ywan ParseNolintSuppressions/ResetNolintSuppressions. 494233d2500723e5594f3e7c70896ffeeef32b9c950ywan 495233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 496233d2500723e5594f3e7c70896ffeeef32b9c950ywan category: str, the category of the error. 497233d2500723e5594f3e7c70896ffeeef32b9c950ywan linenum: int, the current line number. 498233d2500723e5594f3e7c70896ffeeef32b9c950ywan Returns: 499233d2500723e5594f3e7c70896ffeeef32b9c950ywan bool, True iff the error should be suppressed due to a NOLINT comment. 500233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 501233d2500723e5594f3e7c70896ffeeef32b9c950ywan return (linenum in _error_suppressions.get(category, set()) or 502233d2500723e5594f3e7c70896ffeeef32b9c950ywan linenum in _error_suppressions.get(None, set())) 503233d2500723e5594f3e7c70896ffeeef32b9c950ywan 504233d2500723e5594f3e7c70896ffeeef32b9c950ywandef Match(pattern, s): 505233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Matches the string with the pattern, caching the compiled regexp.""" 506233d2500723e5594f3e7c70896ffeeef32b9c950ywan # The regexp compilation caching is inlined in both Match and Search for 507233d2500723e5594f3e7c70896ffeeef32b9c950ywan # performance reasons; factoring it out into a separate function turns out 508233d2500723e5594f3e7c70896ffeeef32b9c950ywan # to be noticeably expensive. 509233d2500723e5594f3e7c70896ffeeef32b9c950ywan if pattern not in _regexp_compile_cache: 510233d2500723e5594f3e7c70896ffeeef32b9c950ywan _regexp_compile_cache[pattern] = sre_compile.compile(pattern) 511233d2500723e5594f3e7c70896ffeeef32b9c950ywan return _regexp_compile_cache[pattern].match(s) 512233d2500723e5594f3e7c70896ffeeef32b9c950ywan 513233d2500723e5594f3e7c70896ffeeef32b9c950ywan 514233d2500723e5594f3e7c70896ffeeef32b9c950ywandef ReplaceAll(pattern, rep, s): 515233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Replaces instances of pattern in a string with a replacement. 516233d2500723e5594f3e7c70896ffeeef32b9c950ywan 517233d2500723e5594f3e7c70896ffeeef32b9c950ywan The compiled regex is kept in a cache shared by Match and Search. 518233d2500723e5594f3e7c70896ffeeef32b9c950ywan 519233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 520233d2500723e5594f3e7c70896ffeeef32b9c950ywan pattern: regex pattern 521233d2500723e5594f3e7c70896ffeeef32b9c950ywan rep: replacement text 522233d2500723e5594f3e7c70896ffeeef32b9c950ywan s: search string 523233d2500723e5594f3e7c70896ffeeef32b9c950ywan 524233d2500723e5594f3e7c70896ffeeef32b9c950ywan Returns: 525233d2500723e5594f3e7c70896ffeeef32b9c950ywan string with replacements made (or original string if no replacements) 526233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 527233d2500723e5594f3e7c70896ffeeef32b9c950ywan if pattern not in _regexp_compile_cache: 528233d2500723e5594f3e7c70896ffeeef32b9c950ywan _regexp_compile_cache[pattern] = sre_compile.compile(pattern) 529233d2500723e5594f3e7c70896ffeeef32b9c950ywan return _regexp_compile_cache[pattern].sub(rep, s) 530233d2500723e5594f3e7c70896ffeeef32b9c950ywan 531233d2500723e5594f3e7c70896ffeeef32b9c950ywan 532233d2500723e5594f3e7c70896ffeeef32b9c950ywandef Search(pattern, s): 533233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Searches the string for the pattern, caching the compiled regexp.""" 534233d2500723e5594f3e7c70896ffeeef32b9c950ywan if pattern not in _regexp_compile_cache: 535233d2500723e5594f3e7c70896ffeeef32b9c950ywan _regexp_compile_cache[pattern] = sre_compile.compile(pattern) 536233d2500723e5594f3e7c70896ffeeef32b9c950ywan return _regexp_compile_cache[pattern].search(s) 537233d2500723e5594f3e7c70896ffeeef32b9c950ywan 538233d2500723e5594f3e7c70896ffeeef32b9c950ywan 539233d2500723e5594f3e7c70896ffeeef32b9c950ywanclass _IncludeState(dict): 540233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Tracks line numbers for includes, and the order in which includes appear. 541233d2500723e5594f3e7c70896ffeeef32b9c950ywan 542233d2500723e5594f3e7c70896ffeeef32b9c950ywan As a dict, an _IncludeState object serves as a mapping between include 543233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename and line number on which that file was included. 544233d2500723e5594f3e7c70896ffeeef32b9c950ywan 545233d2500723e5594f3e7c70896ffeeef32b9c950ywan Call CheckNextIncludeOrder() once for each header in the file, passing 546233d2500723e5594f3e7c70896ffeeef32b9c950ywan in the type constants defined above. Calls in an illegal order will 547233d2500723e5594f3e7c70896ffeeef32b9c950ywan raise an _IncludeError with an appropriate error message. 548233d2500723e5594f3e7c70896ffeeef32b9c950ywan 549233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 550233d2500723e5594f3e7c70896ffeeef32b9c950ywan # self._section will move monotonically through this set. If it ever 551233d2500723e5594f3e7c70896ffeeef32b9c950ywan # needs to move backwards, CheckNextIncludeOrder will raise an error. 552233d2500723e5594f3e7c70896ffeeef32b9c950ywan _INITIAL_SECTION = 0 553233d2500723e5594f3e7c70896ffeeef32b9c950ywan _MY_H_SECTION = 1 554233d2500723e5594f3e7c70896ffeeef32b9c950ywan _C_SECTION = 2 555233d2500723e5594f3e7c70896ffeeef32b9c950ywan _CPP_SECTION = 3 556233d2500723e5594f3e7c70896ffeeef32b9c950ywan _OTHER_H_SECTION = 4 557233d2500723e5594f3e7c70896ffeeef32b9c950ywan 558233d2500723e5594f3e7c70896ffeeef32b9c950ywan _TYPE_NAMES = { 559233d2500723e5594f3e7c70896ffeeef32b9c950ywan _C_SYS_HEADER: 'C system header', 560233d2500723e5594f3e7c70896ffeeef32b9c950ywan _CPP_SYS_HEADER: 'C++ system header', 561233d2500723e5594f3e7c70896ffeeef32b9c950ywan _LIKELY_MY_HEADER: 'header this file implements', 562233d2500723e5594f3e7c70896ffeeef32b9c950ywan _POSSIBLE_MY_HEADER: 'header this file may implement', 563233d2500723e5594f3e7c70896ffeeef32b9c950ywan _OTHER_HEADER: 'other header', 564233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 565233d2500723e5594f3e7c70896ffeeef32b9c950ywan _SECTION_NAMES = { 566233d2500723e5594f3e7c70896ffeeef32b9c950ywan _INITIAL_SECTION: "... nothing. (This can't be an error.)", 567233d2500723e5594f3e7c70896ffeeef32b9c950ywan _MY_H_SECTION: 'a header this file implements', 568233d2500723e5594f3e7c70896ffeeef32b9c950ywan _C_SECTION: 'C system header', 569233d2500723e5594f3e7c70896ffeeef32b9c950ywan _CPP_SECTION: 'C++ system header', 570233d2500723e5594f3e7c70896ffeeef32b9c950ywan _OTHER_H_SECTION: 'other header', 571233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 572233d2500723e5594f3e7c70896ffeeef32b9c950ywan 573233d2500723e5594f3e7c70896ffeeef32b9c950ywan def __init__(self): 574233d2500723e5594f3e7c70896ffeeef32b9c950ywan dict.__init__(self) 575233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.ResetSection() 576233d2500723e5594f3e7c70896ffeeef32b9c950ywan 577233d2500723e5594f3e7c70896ffeeef32b9c950ywan def ResetSection(self): 578233d2500723e5594f3e7c70896ffeeef32b9c950ywan # The name of the current section. 579233d2500723e5594f3e7c70896ffeeef32b9c950ywan self._section = self._INITIAL_SECTION 580233d2500723e5594f3e7c70896ffeeef32b9c950ywan # The path of last found header. 581233d2500723e5594f3e7c70896ffeeef32b9c950ywan self._last_header = '' 582233d2500723e5594f3e7c70896ffeeef32b9c950ywan 583233d2500723e5594f3e7c70896ffeeef32b9c950ywan def SetLastHeader(self, header_path): 584233d2500723e5594f3e7c70896ffeeef32b9c950ywan self._last_header = header_path 585233d2500723e5594f3e7c70896ffeeef32b9c950ywan 586233d2500723e5594f3e7c70896ffeeef32b9c950ywan def CanonicalizeAlphabeticalOrder(self, header_path): 587233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Returns a path canonicalized for alphabetical comparison. 588233d2500723e5594f3e7c70896ffeeef32b9c950ywan 589233d2500723e5594f3e7c70896ffeeef32b9c950ywan - replaces "-" with "_" so they both cmp the same. 590233d2500723e5594f3e7c70896ffeeef32b9c950ywan - removes '-inl' since we don't require them to be after the main header. 591233d2500723e5594f3e7c70896ffeeef32b9c950ywan - lowercase everything, just in case. 592233d2500723e5594f3e7c70896ffeeef32b9c950ywan 593233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 594233d2500723e5594f3e7c70896ffeeef32b9c950ywan header_path: Path to be canonicalized. 595233d2500723e5594f3e7c70896ffeeef32b9c950ywan 596233d2500723e5594f3e7c70896ffeeef32b9c950ywan Returns: 597233d2500723e5594f3e7c70896ffeeef32b9c950ywan Canonicalized path. 598233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 599233d2500723e5594f3e7c70896ffeeef32b9c950ywan return header_path.replace('-inl.h', '.h').replace('-', '_').lower() 600233d2500723e5594f3e7c70896ffeeef32b9c950ywan 601233d2500723e5594f3e7c70896ffeeef32b9c950ywan def IsInAlphabeticalOrder(self, clean_lines, linenum, header_path): 602233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Check if a header is in alphabetical order with the previous header. 603233d2500723e5594f3e7c70896ffeeef32b9c950ywan 604233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 605233d2500723e5594f3e7c70896ffeeef32b9c950ywan clean_lines: A CleansedLines instance containing the file. 606233d2500723e5594f3e7c70896ffeeef32b9c950ywan linenum: The number of the line to check. 607233d2500723e5594f3e7c70896ffeeef32b9c950ywan header_path: Canonicalized header to be checked. 608233d2500723e5594f3e7c70896ffeeef32b9c950ywan 609233d2500723e5594f3e7c70896ffeeef32b9c950ywan Returns: 610233d2500723e5594f3e7c70896ffeeef32b9c950ywan Returns true if the header is in alphabetical order. 611233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 612233d2500723e5594f3e7c70896ffeeef32b9c950ywan # If previous section is different from current section, _last_header will 613233d2500723e5594f3e7c70896ffeeef32b9c950ywan # be reset to empty string, so it's always less than current header. 614233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 615233d2500723e5594f3e7c70896ffeeef32b9c950ywan # If previous line was a blank line, assume that the headers are 616233d2500723e5594f3e7c70896ffeeef32b9c950ywan # intentionally sorted the way they are. 617233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (self._last_header > header_path and 618233d2500723e5594f3e7c70896ffeeef32b9c950ywan not Match(r'^\s*$', clean_lines.elided[linenum - 1])): 619233d2500723e5594f3e7c70896ffeeef32b9c950ywan return False 620233d2500723e5594f3e7c70896ffeeef32b9c950ywan return True 621233d2500723e5594f3e7c70896ffeeef32b9c950ywan 622233d2500723e5594f3e7c70896ffeeef32b9c950ywan def CheckNextIncludeOrder(self, header_type): 623233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Returns a non-empty error message if the next header is out of order. 624233d2500723e5594f3e7c70896ffeeef32b9c950ywan 625233d2500723e5594f3e7c70896ffeeef32b9c950ywan This function also updates the internal state to be ready to check 626233d2500723e5594f3e7c70896ffeeef32b9c950ywan the next include. 627233d2500723e5594f3e7c70896ffeeef32b9c950ywan 628233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 629233d2500723e5594f3e7c70896ffeeef32b9c950ywan header_type: One of the _XXX_HEADER constants defined above. 630233d2500723e5594f3e7c70896ffeeef32b9c950ywan 631233d2500723e5594f3e7c70896ffeeef32b9c950ywan Returns: 632233d2500723e5594f3e7c70896ffeeef32b9c950ywan The empty string if the header is in the right order, or an 633233d2500723e5594f3e7c70896ffeeef32b9c950ywan error message describing what's wrong. 634233d2500723e5594f3e7c70896ffeeef32b9c950ywan 635233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 636233d2500723e5594f3e7c70896ffeeef32b9c950ywan error_message = ('Found %s after %s' % 637233d2500723e5594f3e7c70896ffeeef32b9c950ywan (self._TYPE_NAMES[header_type], 638233d2500723e5594f3e7c70896ffeeef32b9c950ywan self._SECTION_NAMES[self._section])) 639233d2500723e5594f3e7c70896ffeeef32b9c950ywan 640233d2500723e5594f3e7c70896ffeeef32b9c950ywan last_section = self._section 641233d2500723e5594f3e7c70896ffeeef32b9c950ywan 642233d2500723e5594f3e7c70896ffeeef32b9c950ywan if header_type == _C_SYS_HEADER: 643233d2500723e5594f3e7c70896ffeeef32b9c950ywan if self._section <= self._C_SECTION: 644233d2500723e5594f3e7c70896ffeeef32b9c950ywan self._section = self._C_SECTION 645233d2500723e5594f3e7c70896ffeeef32b9c950ywan else: 646233d2500723e5594f3e7c70896ffeeef32b9c950ywan self._last_header = '' 647233d2500723e5594f3e7c70896ffeeef32b9c950ywan return error_message 648233d2500723e5594f3e7c70896ffeeef32b9c950ywan elif header_type == _CPP_SYS_HEADER: 649233d2500723e5594f3e7c70896ffeeef32b9c950ywan if self._section <= self._CPP_SECTION: 650233d2500723e5594f3e7c70896ffeeef32b9c950ywan self._section = self._CPP_SECTION 651233d2500723e5594f3e7c70896ffeeef32b9c950ywan else: 652233d2500723e5594f3e7c70896ffeeef32b9c950ywan self._last_header = '' 653233d2500723e5594f3e7c70896ffeeef32b9c950ywan return error_message 654233d2500723e5594f3e7c70896ffeeef32b9c950ywan elif header_type == _LIKELY_MY_HEADER: 655233d2500723e5594f3e7c70896ffeeef32b9c950ywan if self._section <= self._MY_H_SECTION: 656233d2500723e5594f3e7c70896ffeeef32b9c950ywan self._section = self._MY_H_SECTION 657233d2500723e5594f3e7c70896ffeeef32b9c950ywan else: 658233d2500723e5594f3e7c70896ffeeef32b9c950ywan self._section = self._OTHER_H_SECTION 659233d2500723e5594f3e7c70896ffeeef32b9c950ywan elif header_type == _POSSIBLE_MY_HEADER: 660233d2500723e5594f3e7c70896ffeeef32b9c950ywan if self._section <= self._MY_H_SECTION: 661233d2500723e5594f3e7c70896ffeeef32b9c950ywan self._section = self._MY_H_SECTION 662233d2500723e5594f3e7c70896ffeeef32b9c950ywan else: 663233d2500723e5594f3e7c70896ffeeef32b9c950ywan # This will always be the fallback because we're not sure 664233d2500723e5594f3e7c70896ffeeef32b9c950ywan # enough that the header is associated with this file. 665233d2500723e5594f3e7c70896ffeeef32b9c950ywan self._section = self._OTHER_H_SECTION 666233d2500723e5594f3e7c70896ffeeef32b9c950ywan else: 667233d2500723e5594f3e7c70896ffeeef32b9c950ywan assert header_type == _OTHER_HEADER 668233d2500723e5594f3e7c70896ffeeef32b9c950ywan self._section = self._OTHER_H_SECTION 669233d2500723e5594f3e7c70896ffeeef32b9c950ywan 670233d2500723e5594f3e7c70896ffeeef32b9c950ywan if last_section != self._section: 671233d2500723e5594f3e7c70896ffeeef32b9c950ywan self._last_header = '' 672233d2500723e5594f3e7c70896ffeeef32b9c950ywan 673233d2500723e5594f3e7c70896ffeeef32b9c950ywan return '' 674233d2500723e5594f3e7c70896ffeeef32b9c950ywan 675233d2500723e5594f3e7c70896ffeeef32b9c950ywan 676233d2500723e5594f3e7c70896ffeeef32b9c950ywanclass _CppLintState(object): 677233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Maintains module-wide state..""" 678233d2500723e5594f3e7c70896ffeeef32b9c950ywan 679233d2500723e5594f3e7c70896ffeeef32b9c950ywan def __init__(self): 680233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.verbose_level = 1 # global setting. 681233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.error_count = 0 # global count of reported errors 682233d2500723e5594f3e7c70896ffeeef32b9c950ywan # filters to apply when emitting error messages 683233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.filters = _DEFAULT_FILTERS[:] 684233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.counting = 'total' # In what way are we counting errors? 685233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.errors_by_category = {} # string to int dict storing error counts 686233d2500723e5594f3e7c70896ffeeef32b9c950ywan 687233d2500723e5594f3e7c70896ffeeef32b9c950ywan # output format: 688233d2500723e5594f3e7c70896ffeeef32b9c950ywan # "emacs" - format that emacs can parse (default) 689233d2500723e5594f3e7c70896ffeeef32b9c950ywan # "vs7" - format that Microsoft Visual Studio 7 can parse 690233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.output_format = 'emacs' 691233d2500723e5594f3e7c70896ffeeef32b9c950ywan 692233d2500723e5594f3e7c70896ffeeef32b9c950ywan def SetOutputFormat(self, output_format): 693233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Sets the output format for errors.""" 694233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.output_format = output_format 695233d2500723e5594f3e7c70896ffeeef32b9c950ywan 696233d2500723e5594f3e7c70896ffeeef32b9c950ywan def SetVerboseLevel(self, level): 697233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Sets the module's verbosity, and returns the previous setting.""" 698233d2500723e5594f3e7c70896ffeeef32b9c950ywan last_verbose_level = self.verbose_level 699233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.verbose_level = level 700233d2500723e5594f3e7c70896ffeeef32b9c950ywan return last_verbose_level 701233d2500723e5594f3e7c70896ffeeef32b9c950ywan 702233d2500723e5594f3e7c70896ffeeef32b9c950ywan def SetCountingStyle(self, counting_style): 703233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Sets the module's counting options.""" 704233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.counting = counting_style 705233d2500723e5594f3e7c70896ffeeef32b9c950ywan 706233d2500723e5594f3e7c70896ffeeef32b9c950ywan def SetFilters(self, filters): 707233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Sets the error-message filters. 708233d2500723e5594f3e7c70896ffeeef32b9c950ywan 709233d2500723e5594f3e7c70896ffeeef32b9c950ywan These filters are applied when deciding whether to emit a given 710233d2500723e5594f3e7c70896ffeeef32b9c950ywan error message. 711233d2500723e5594f3e7c70896ffeeef32b9c950ywan 712233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 713233d2500723e5594f3e7c70896ffeeef32b9c950ywan filters: A string of comma-separated filters (eg "+whitespace/indent"). 714233d2500723e5594f3e7c70896ffeeef32b9c950ywan Each filter should start with + or -; else we die. 715233d2500723e5594f3e7c70896ffeeef32b9c950ywan 716233d2500723e5594f3e7c70896ffeeef32b9c950ywan Raises: 717233d2500723e5594f3e7c70896ffeeef32b9c950ywan ValueError: The comma-separated filters did not all start with '+' or '-'. 718233d2500723e5594f3e7c70896ffeeef32b9c950ywan E.g. "-,+whitespace,-whitespace/indent,whitespace/badfilter" 719233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 720233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Default filters always have less priority than the flag ones. 721233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.filters = _DEFAULT_FILTERS[:] 722233d2500723e5594f3e7c70896ffeeef32b9c950ywan for filt in filters.split(','): 723233d2500723e5594f3e7c70896ffeeef32b9c950ywan clean_filt = filt.strip() 724233d2500723e5594f3e7c70896ffeeef32b9c950ywan if clean_filt: 725233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.filters.append(clean_filt) 726233d2500723e5594f3e7c70896ffeeef32b9c950ywan for filt in self.filters: 727233d2500723e5594f3e7c70896ffeeef32b9c950ywan if not (filt.startswith('+') or filt.startswith('-')): 728233d2500723e5594f3e7c70896ffeeef32b9c950ywan raise ValueError('Every filter in --filters must start with + or -' 729233d2500723e5594f3e7c70896ffeeef32b9c950ywan ' (%s does not)' % filt) 730233d2500723e5594f3e7c70896ffeeef32b9c950ywan 731233d2500723e5594f3e7c70896ffeeef32b9c950ywan def ResetErrorCounts(self): 732233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Sets the module's error statistic back to zero.""" 733233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.error_count = 0 734233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.errors_by_category = {} 735233d2500723e5594f3e7c70896ffeeef32b9c950ywan 736233d2500723e5594f3e7c70896ffeeef32b9c950ywan def IncrementErrorCount(self, category): 737233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Bumps the module's error statistic.""" 738233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.error_count += 1 739233d2500723e5594f3e7c70896ffeeef32b9c950ywan if self.counting in ('toplevel', 'detailed'): 740233d2500723e5594f3e7c70896ffeeef32b9c950ywan if self.counting != 'detailed': 741233d2500723e5594f3e7c70896ffeeef32b9c950ywan category = category.split('/')[0] 742233d2500723e5594f3e7c70896ffeeef32b9c950ywan if category not in self.errors_by_category: 743233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.errors_by_category[category] = 0 744233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.errors_by_category[category] += 1 745233d2500723e5594f3e7c70896ffeeef32b9c950ywan 746233d2500723e5594f3e7c70896ffeeef32b9c950ywan def PrintErrorCounts(self): 747233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Print a summary of errors by category, and the total.""" 748233d2500723e5594f3e7c70896ffeeef32b9c950ywan for category, count in self.errors_by_category.iteritems(): 749233d2500723e5594f3e7c70896ffeeef32b9c950ywan sys.stderr.write('Category \'%s\' errors found: %d\n' % 750233d2500723e5594f3e7c70896ffeeef32b9c950ywan (category, count)) 751233d2500723e5594f3e7c70896ffeeef32b9c950ywan sys.stderr.write('Total errors found: %d\n' % self.error_count) 752233d2500723e5594f3e7c70896ffeeef32b9c950ywan 753233d2500723e5594f3e7c70896ffeeef32b9c950ywan_cpplint_state = _CppLintState() 754233d2500723e5594f3e7c70896ffeeef32b9c950ywan 755233d2500723e5594f3e7c70896ffeeef32b9c950ywan 756233d2500723e5594f3e7c70896ffeeef32b9c950ywandef _OutputFormat(): 757233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Gets the module's output format.""" 758233d2500723e5594f3e7c70896ffeeef32b9c950ywan return _cpplint_state.output_format 759233d2500723e5594f3e7c70896ffeeef32b9c950ywan 760233d2500723e5594f3e7c70896ffeeef32b9c950ywan 761233d2500723e5594f3e7c70896ffeeef32b9c950ywandef _SetOutputFormat(output_format): 762233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Sets the module's output format.""" 763233d2500723e5594f3e7c70896ffeeef32b9c950ywan _cpplint_state.SetOutputFormat(output_format) 764233d2500723e5594f3e7c70896ffeeef32b9c950ywan 765233d2500723e5594f3e7c70896ffeeef32b9c950ywan 766233d2500723e5594f3e7c70896ffeeef32b9c950ywandef _VerboseLevel(): 767233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Returns the module's verbosity setting.""" 768233d2500723e5594f3e7c70896ffeeef32b9c950ywan return _cpplint_state.verbose_level 769233d2500723e5594f3e7c70896ffeeef32b9c950ywan 770233d2500723e5594f3e7c70896ffeeef32b9c950ywan 771233d2500723e5594f3e7c70896ffeeef32b9c950ywandef _SetVerboseLevel(level): 772233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Sets the module's verbosity, and returns the previous setting.""" 773233d2500723e5594f3e7c70896ffeeef32b9c950ywan return _cpplint_state.SetVerboseLevel(level) 774233d2500723e5594f3e7c70896ffeeef32b9c950ywan 775233d2500723e5594f3e7c70896ffeeef32b9c950ywan 776233d2500723e5594f3e7c70896ffeeef32b9c950ywandef _SetCountingStyle(level): 777233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Sets the module's counting options.""" 778233d2500723e5594f3e7c70896ffeeef32b9c950ywan _cpplint_state.SetCountingStyle(level) 779233d2500723e5594f3e7c70896ffeeef32b9c950ywan 780233d2500723e5594f3e7c70896ffeeef32b9c950ywan 781233d2500723e5594f3e7c70896ffeeef32b9c950ywandef _Filters(): 782233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Returns the module's list of output filters, as a list.""" 783233d2500723e5594f3e7c70896ffeeef32b9c950ywan return _cpplint_state.filters 784233d2500723e5594f3e7c70896ffeeef32b9c950ywan 785233d2500723e5594f3e7c70896ffeeef32b9c950ywan 786233d2500723e5594f3e7c70896ffeeef32b9c950ywandef _SetFilters(filters): 787233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Sets the module's error-message filters. 788233d2500723e5594f3e7c70896ffeeef32b9c950ywan 789233d2500723e5594f3e7c70896ffeeef32b9c950ywan These filters are applied when deciding whether to emit a given 790233d2500723e5594f3e7c70896ffeeef32b9c950ywan error message. 791233d2500723e5594f3e7c70896ffeeef32b9c950ywan 792233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 793233d2500723e5594f3e7c70896ffeeef32b9c950ywan filters: A string of comma-separated filters (eg "whitespace/indent"). 794233d2500723e5594f3e7c70896ffeeef32b9c950ywan Each filter should start with + or -; else we die. 795233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 796233d2500723e5594f3e7c70896ffeeef32b9c950ywan _cpplint_state.SetFilters(filters) 797233d2500723e5594f3e7c70896ffeeef32b9c950ywan 798233d2500723e5594f3e7c70896ffeeef32b9c950ywan 799233d2500723e5594f3e7c70896ffeeef32b9c950ywanclass _FunctionState(object): 800233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Tracks current function name and the number of lines in its body.""" 801233d2500723e5594f3e7c70896ffeeef32b9c950ywan 802233d2500723e5594f3e7c70896ffeeef32b9c950ywan _NORMAL_TRIGGER = 250 # for --v=0, 500 for --v=1, etc. 803233d2500723e5594f3e7c70896ffeeef32b9c950ywan _TEST_TRIGGER = 400 # about 50% more than _NORMAL_TRIGGER. 804233d2500723e5594f3e7c70896ffeeef32b9c950ywan 805233d2500723e5594f3e7c70896ffeeef32b9c950ywan def __init__(self): 806233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.in_a_function = False 807233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.lines_in_function = 0 808233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.current_function = '' 809233d2500723e5594f3e7c70896ffeeef32b9c950ywan 810233d2500723e5594f3e7c70896ffeeef32b9c950ywan def Begin(self, function_name): 811233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Start analyzing function body. 812233d2500723e5594f3e7c70896ffeeef32b9c950ywan 813233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 814233d2500723e5594f3e7c70896ffeeef32b9c950ywan function_name: The name of the function being tracked. 815233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 816233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.in_a_function = True 817233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.lines_in_function = 0 818233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.current_function = function_name 819233d2500723e5594f3e7c70896ffeeef32b9c950ywan 820233d2500723e5594f3e7c70896ffeeef32b9c950ywan def Count(self): 821233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Count line in current function body.""" 822233d2500723e5594f3e7c70896ffeeef32b9c950ywan if self.in_a_function: 823233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.lines_in_function += 1 824233d2500723e5594f3e7c70896ffeeef32b9c950ywan 825233d2500723e5594f3e7c70896ffeeef32b9c950ywan def Check(self, error, filename, linenum): 826233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Report if too many lines in function body. 827233d2500723e5594f3e7c70896ffeeef32b9c950ywan 828233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 829233d2500723e5594f3e7c70896ffeeef32b9c950ywan error: The function to call with any errors found. 830233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename: The name of the current file. 831233d2500723e5594f3e7c70896ffeeef32b9c950ywan linenum: The number of the line to check. 832233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 833233d2500723e5594f3e7c70896ffeeef32b9c950ywan if Match(r'T(EST|est)', self.current_function): 834233d2500723e5594f3e7c70896ffeeef32b9c950ywan base_trigger = self._TEST_TRIGGER 835233d2500723e5594f3e7c70896ffeeef32b9c950ywan else: 836233d2500723e5594f3e7c70896ffeeef32b9c950ywan base_trigger = self._NORMAL_TRIGGER 837233d2500723e5594f3e7c70896ffeeef32b9c950ywan trigger = base_trigger * 2**_VerboseLevel() 838233d2500723e5594f3e7c70896ffeeef32b9c950ywan 839233d2500723e5594f3e7c70896ffeeef32b9c950ywan if self.lines_in_function > trigger: 840233d2500723e5594f3e7c70896ffeeef32b9c950ywan error_level = int(math.log(self.lines_in_function / base_trigger, 2)) 841233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 50 => 0, 100 => 1, 200 => 2, 400 => 3, 800 => 4, 1600 => 5, ... 842233d2500723e5594f3e7c70896ffeeef32b9c950ywan if error_level > 5: 843233d2500723e5594f3e7c70896ffeeef32b9c950ywan error_level = 5 844233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'readability/fn_size', error_level, 845233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Small and focused functions are preferred:' 846233d2500723e5594f3e7c70896ffeeef32b9c950ywan ' %s has %d non-comment lines' 847233d2500723e5594f3e7c70896ffeeef32b9c950ywan ' (error triggered by exceeding %d lines).' % ( 848233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.current_function, self.lines_in_function, trigger)) 849233d2500723e5594f3e7c70896ffeeef32b9c950ywan 850233d2500723e5594f3e7c70896ffeeef32b9c950ywan def End(self): 851233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Stop analyzing function body.""" 852233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.in_a_function = False 853233d2500723e5594f3e7c70896ffeeef32b9c950ywan 854233d2500723e5594f3e7c70896ffeeef32b9c950ywan 855233d2500723e5594f3e7c70896ffeeef32b9c950ywanclass _IncludeError(Exception): 856233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Indicates a problem with the include order in a file.""" 857233d2500723e5594f3e7c70896ffeeef32b9c950ywan pass 858233d2500723e5594f3e7c70896ffeeef32b9c950ywan 859233d2500723e5594f3e7c70896ffeeef32b9c950ywan 860233d2500723e5594f3e7c70896ffeeef32b9c950ywanclass FileInfo: 861233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Provides utility functions for filenames. 862233d2500723e5594f3e7c70896ffeeef32b9c950ywan 863233d2500723e5594f3e7c70896ffeeef32b9c950ywan FileInfo provides easy access to the components of a file's path 864233d2500723e5594f3e7c70896ffeeef32b9c950ywan relative to the project root. 865233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 866233d2500723e5594f3e7c70896ffeeef32b9c950ywan 867233d2500723e5594f3e7c70896ffeeef32b9c950ywan def __init__(self, filename): 868233d2500723e5594f3e7c70896ffeeef32b9c950ywan self._filename = filename 869233d2500723e5594f3e7c70896ffeeef32b9c950ywan 870233d2500723e5594f3e7c70896ffeeef32b9c950ywan def FullName(self): 871233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Make Windows paths like Unix.""" 872233d2500723e5594f3e7c70896ffeeef32b9c950ywan return os.path.abspath(self._filename).replace('\\', '/') 873233d2500723e5594f3e7c70896ffeeef32b9c950ywan 874233d2500723e5594f3e7c70896ffeeef32b9c950ywan def RepositoryName(self): 875233d2500723e5594f3e7c70896ffeeef32b9c950ywan """FullName after removing the local path to the repository. 876233d2500723e5594f3e7c70896ffeeef32b9c950ywan 877233d2500723e5594f3e7c70896ffeeef32b9c950ywan If we have a real absolute path name here we can try to do something smart: 878233d2500723e5594f3e7c70896ffeeef32b9c950ywan detecting the root of the checkout and truncating /path/to/checkout from 879233d2500723e5594f3e7c70896ffeeef32b9c950ywan the name so that we get header guards that don't include things like 880233d2500723e5594f3e7c70896ffeeef32b9c950ywan "C:\Documents and Settings\..." or "/home/username/..." in them and thus 881233d2500723e5594f3e7c70896ffeeef32b9c950ywan people on different computers who have checked the source out to different 882233d2500723e5594f3e7c70896ffeeef32b9c950ywan locations won't see bogus errors. 883233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 884233d2500723e5594f3e7c70896ffeeef32b9c950ywan fullname = self.FullName() 885233d2500723e5594f3e7c70896ffeeef32b9c950ywan 886233d2500723e5594f3e7c70896ffeeef32b9c950ywan if os.path.exists(fullname): 887233d2500723e5594f3e7c70896ffeeef32b9c950ywan project_dir = os.path.dirname(fullname) 888233d2500723e5594f3e7c70896ffeeef32b9c950ywan 889233d2500723e5594f3e7c70896ffeeef32b9c950ywan if os.path.exists(os.path.join(project_dir, ".svn")): 890233d2500723e5594f3e7c70896ffeeef32b9c950ywan # If there's a .svn file in the current directory, we recursively look 891233d2500723e5594f3e7c70896ffeeef32b9c950ywan # up the directory tree for the top of the SVN checkout 892233d2500723e5594f3e7c70896ffeeef32b9c950ywan root_dir = project_dir 893233d2500723e5594f3e7c70896ffeeef32b9c950ywan one_up_dir = os.path.dirname(root_dir) 894233d2500723e5594f3e7c70896ffeeef32b9c950ywan while os.path.exists(os.path.join(one_up_dir, ".svn")): 895233d2500723e5594f3e7c70896ffeeef32b9c950ywan root_dir = os.path.dirname(root_dir) 896233d2500723e5594f3e7c70896ffeeef32b9c950ywan one_up_dir = os.path.dirname(one_up_dir) 897233d2500723e5594f3e7c70896ffeeef32b9c950ywan 898233d2500723e5594f3e7c70896ffeeef32b9c950ywan prefix = os.path.commonprefix([root_dir, project_dir]) 899233d2500723e5594f3e7c70896ffeeef32b9c950ywan return fullname[len(prefix) + 1:] 900233d2500723e5594f3e7c70896ffeeef32b9c950ywan 901233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Not SVN <= 1.6? Try to find a git, hg, or svn top level directory by 902233d2500723e5594f3e7c70896ffeeef32b9c950ywan # searching up from the current path. 903233d2500723e5594f3e7c70896ffeeef32b9c950ywan root_dir = os.path.dirname(fullname) 904233d2500723e5594f3e7c70896ffeeef32b9c950ywan while (root_dir != os.path.dirname(root_dir) and 905233d2500723e5594f3e7c70896ffeeef32b9c950ywan not os.path.exists(os.path.join(root_dir, ".git")) and 906233d2500723e5594f3e7c70896ffeeef32b9c950ywan not os.path.exists(os.path.join(root_dir, ".hg")) and 907233d2500723e5594f3e7c70896ffeeef32b9c950ywan not os.path.exists(os.path.join(root_dir, ".svn"))): 908233d2500723e5594f3e7c70896ffeeef32b9c950ywan root_dir = os.path.dirname(root_dir) 909233d2500723e5594f3e7c70896ffeeef32b9c950ywan 910233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (os.path.exists(os.path.join(root_dir, ".git")) or 911233d2500723e5594f3e7c70896ffeeef32b9c950ywan os.path.exists(os.path.join(root_dir, ".hg")) or 912233d2500723e5594f3e7c70896ffeeef32b9c950ywan os.path.exists(os.path.join(root_dir, ".svn"))): 913233d2500723e5594f3e7c70896ffeeef32b9c950ywan prefix = os.path.commonprefix([root_dir, project_dir]) 914233d2500723e5594f3e7c70896ffeeef32b9c950ywan return fullname[len(prefix) + 1:] 915233d2500723e5594f3e7c70896ffeeef32b9c950ywan 916233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Don't know what to do; header guard warnings may be wrong... 917233d2500723e5594f3e7c70896ffeeef32b9c950ywan return fullname 918233d2500723e5594f3e7c70896ffeeef32b9c950ywan 919233d2500723e5594f3e7c70896ffeeef32b9c950ywan def Split(self): 920233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Splits the file into the directory, basename, and extension. 921233d2500723e5594f3e7c70896ffeeef32b9c950ywan 922233d2500723e5594f3e7c70896ffeeef32b9c950ywan For 'chrome/browser/browser.cc', Split() would 923233d2500723e5594f3e7c70896ffeeef32b9c950ywan return ('chrome/browser', 'browser', '.cc') 924233d2500723e5594f3e7c70896ffeeef32b9c950ywan 925233d2500723e5594f3e7c70896ffeeef32b9c950ywan Returns: 926233d2500723e5594f3e7c70896ffeeef32b9c950ywan A tuple of (directory, basename, extension). 927233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 928233d2500723e5594f3e7c70896ffeeef32b9c950ywan 929233d2500723e5594f3e7c70896ffeeef32b9c950ywan googlename = self.RepositoryName() 930233d2500723e5594f3e7c70896ffeeef32b9c950ywan project, rest = os.path.split(googlename) 931233d2500723e5594f3e7c70896ffeeef32b9c950ywan return (project,) + os.path.splitext(rest) 932233d2500723e5594f3e7c70896ffeeef32b9c950ywan 933233d2500723e5594f3e7c70896ffeeef32b9c950ywan def BaseName(self): 934233d2500723e5594f3e7c70896ffeeef32b9c950ywan """File base name - text after the final slash, before the final period.""" 935233d2500723e5594f3e7c70896ffeeef32b9c950ywan return self.Split()[1] 936233d2500723e5594f3e7c70896ffeeef32b9c950ywan 937233d2500723e5594f3e7c70896ffeeef32b9c950ywan def Extension(self): 938233d2500723e5594f3e7c70896ffeeef32b9c950ywan """File extension - text following the final period.""" 939233d2500723e5594f3e7c70896ffeeef32b9c950ywan return self.Split()[2] 940233d2500723e5594f3e7c70896ffeeef32b9c950ywan 941233d2500723e5594f3e7c70896ffeeef32b9c950ywan def NoExtension(self): 942233d2500723e5594f3e7c70896ffeeef32b9c950ywan """File has no source file extension.""" 943233d2500723e5594f3e7c70896ffeeef32b9c950ywan return '/'.join(self.Split()[0:2]) 944233d2500723e5594f3e7c70896ffeeef32b9c950ywan 945233d2500723e5594f3e7c70896ffeeef32b9c950ywan def IsSource(self): 946233d2500723e5594f3e7c70896ffeeef32b9c950ywan """File has a source file extension.""" 947233d2500723e5594f3e7c70896ffeeef32b9c950ywan return self.Extension()[1:] in ('c', 'cc', 'cpp', 'cxx') 948233d2500723e5594f3e7c70896ffeeef32b9c950ywan 949233d2500723e5594f3e7c70896ffeeef32b9c950ywan 950233d2500723e5594f3e7c70896ffeeef32b9c950ywandef _ShouldPrintError(category, confidence, linenum): 951233d2500723e5594f3e7c70896ffeeef32b9c950ywan """If confidence >= verbose, category passes filter and is not suppressed.""" 952233d2500723e5594f3e7c70896ffeeef32b9c950ywan 953233d2500723e5594f3e7c70896ffeeef32b9c950ywan # There are three ways we might decide not to print an error message: 954233d2500723e5594f3e7c70896ffeeef32b9c950ywan # a "NOLINT(category)" comment appears in the source, 955233d2500723e5594f3e7c70896ffeeef32b9c950ywan # the verbosity level isn't high enough, or the filters filter it out. 956233d2500723e5594f3e7c70896ffeeef32b9c950ywan if IsErrorSuppressedByNolint(category, linenum): 957233d2500723e5594f3e7c70896ffeeef32b9c950ywan return False 958233d2500723e5594f3e7c70896ffeeef32b9c950ywan if confidence < _cpplint_state.verbose_level: 959233d2500723e5594f3e7c70896ffeeef32b9c950ywan return False 960233d2500723e5594f3e7c70896ffeeef32b9c950ywan 961233d2500723e5594f3e7c70896ffeeef32b9c950ywan is_filtered = False 962233d2500723e5594f3e7c70896ffeeef32b9c950ywan for one_filter in _Filters(): 963233d2500723e5594f3e7c70896ffeeef32b9c950ywan if one_filter.startswith('-'): 964233d2500723e5594f3e7c70896ffeeef32b9c950ywan if category.startswith(one_filter[1:]): 965233d2500723e5594f3e7c70896ffeeef32b9c950ywan is_filtered = True 966233d2500723e5594f3e7c70896ffeeef32b9c950ywan elif one_filter.startswith('+'): 967233d2500723e5594f3e7c70896ffeeef32b9c950ywan if category.startswith(one_filter[1:]): 968233d2500723e5594f3e7c70896ffeeef32b9c950ywan is_filtered = False 969233d2500723e5594f3e7c70896ffeeef32b9c950ywan else: 970233d2500723e5594f3e7c70896ffeeef32b9c950ywan assert False # should have been checked for in SetFilter. 971233d2500723e5594f3e7c70896ffeeef32b9c950ywan if is_filtered: 972233d2500723e5594f3e7c70896ffeeef32b9c950ywan return False 973233d2500723e5594f3e7c70896ffeeef32b9c950ywan 974233d2500723e5594f3e7c70896ffeeef32b9c950ywan return True 975233d2500723e5594f3e7c70896ffeeef32b9c950ywan 976233d2500723e5594f3e7c70896ffeeef32b9c950ywan 977233d2500723e5594f3e7c70896ffeeef32b9c950ywandef Error(filename, linenum, category, confidence, message): 978233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Logs the fact we've found a lint error. 979233d2500723e5594f3e7c70896ffeeef32b9c950ywan 980233d2500723e5594f3e7c70896ffeeef32b9c950ywan We log where the error was found, and also our confidence in the error, 981233d2500723e5594f3e7c70896ffeeef32b9c950ywan that is, how certain we are this is a legitimate style regression, and 982233d2500723e5594f3e7c70896ffeeef32b9c950ywan not a misidentification or a use that's sometimes justified. 983233d2500723e5594f3e7c70896ffeeef32b9c950ywan 984233d2500723e5594f3e7c70896ffeeef32b9c950ywan False positives can be suppressed by the use of 985233d2500723e5594f3e7c70896ffeeef32b9c950ywan "cpplint(category)" comments on the offending line. These are 986233d2500723e5594f3e7c70896ffeeef32b9c950ywan parsed into _error_suppressions. 987233d2500723e5594f3e7c70896ffeeef32b9c950ywan 988233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 989233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename: The name of the file containing the error. 990233d2500723e5594f3e7c70896ffeeef32b9c950ywan linenum: The number of the line containing the error. 991233d2500723e5594f3e7c70896ffeeef32b9c950ywan category: A string used to describe the "category" this bug 992233d2500723e5594f3e7c70896ffeeef32b9c950ywan falls under: "whitespace", say, or "runtime". Categories 993233d2500723e5594f3e7c70896ffeeef32b9c950ywan may have a hierarchy separated by slashes: "whitespace/indent". 994233d2500723e5594f3e7c70896ffeeef32b9c950ywan confidence: A number from 1-5 representing a confidence score for 995233d2500723e5594f3e7c70896ffeeef32b9c950ywan the error, with 5 meaning that we are certain of the problem, 996233d2500723e5594f3e7c70896ffeeef32b9c950ywan and 1 meaning that it could be a legitimate construct. 997233d2500723e5594f3e7c70896ffeeef32b9c950ywan message: The error message. 998233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 999233d2500723e5594f3e7c70896ffeeef32b9c950ywan if _ShouldPrintError(category, confidence, linenum): 1000233d2500723e5594f3e7c70896ffeeef32b9c950ywan _cpplint_state.IncrementErrorCount(category) 1001233d2500723e5594f3e7c70896ffeeef32b9c950ywan if _cpplint_state.output_format == 'vs7': 1002233d2500723e5594f3e7c70896ffeeef32b9c950ywan sys.stderr.write('%s(%s): %s [%s] [%d]\n' % ( 1003233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename, linenum, message, category, confidence)) 1004233d2500723e5594f3e7c70896ffeeef32b9c950ywan elif _cpplint_state.output_format == 'eclipse': 1005233d2500723e5594f3e7c70896ffeeef32b9c950ywan sys.stderr.write('%s:%s: warning: %s [%s] [%d]\n' % ( 1006233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename, linenum, message, category, confidence)) 1007233d2500723e5594f3e7c70896ffeeef32b9c950ywan else: 1008233d2500723e5594f3e7c70896ffeeef32b9c950ywan sys.stderr.write('%s:%s: %s [%s] [%d]\n' % ( 1009233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename, linenum, message, category, confidence)) 1010233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1011233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1012233d2500723e5594f3e7c70896ffeeef32b9c950ywan# Matches standard C++ escape sequences per 2.13.2.3 of the C++ standard. 1013233d2500723e5594f3e7c70896ffeeef32b9c950ywan_RE_PATTERN_CLEANSE_LINE_ESCAPES = re.compile( 1014233d2500723e5594f3e7c70896ffeeef32b9c950ywan r'\\([abfnrtv?"\\\']|\d+|x[0-9a-fA-F]+)') 1015233d2500723e5594f3e7c70896ffeeef32b9c950ywan# Matches strings. Escape codes should already be removed by ESCAPES. 1016233d2500723e5594f3e7c70896ffeeef32b9c950ywan_RE_PATTERN_CLEANSE_LINE_DOUBLE_QUOTES = re.compile(r'"[^"]*"') 1017233d2500723e5594f3e7c70896ffeeef32b9c950ywan# Matches characters. Escape codes should already be removed by ESCAPES. 1018233d2500723e5594f3e7c70896ffeeef32b9c950ywan_RE_PATTERN_CLEANSE_LINE_SINGLE_QUOTES = re.compile(r"'.'") 1019233d2500723e5594f3e7c70896ffeeef32b9c950ywan# Matches multi-line C++ comments. 1020233d2500723e5594f3e7c70896ffeeef32b9c950ywan# This RE is a little bit more complicated than one might expect, because we 1021233d2500723e5594f3e7c70896ffeeef32b9c950ywan# have to take care of space removals tools so we can handle comments inside 1022233d2500723e5594f3e7c70896ffeeef32b9c950ywan# statements better. 1023233d2500723e5594f3e7c70896ffeeef32b9c950ywan# The current rule is: We only clear spaces from both sides when we're at the 1024233d2500723e5594f3e7c70896ffeeef32b9c950ywan# end of the line. Otherwise, we try to remove spaces from the right side, 1025233d2500723e5594f3e7c70896ffeeef32b9c950ywan# if this doesn't work we try on left side but only if there's a non-character 1026233d2500723e5594f3e7c70896ffeeef32b9c950ywan# on the right. 1027233d2500723e5594f3e7c70896ffeeef32b9c950ywan_RE_PATTERN_CLEANSE_LINE_C_COMMENTS = re.compile( 1028233d2500723e5594f3e7c70896ffeeef32b9c950ywan r"""(\s*/\*.*\*/\s*$| 1029233d2500723e5594f3e7c70896ffeeef32b9c950ywan /\*.*\*/\s+| 1030233d2500723e5594f3e7c70896ffeeef32b9c950ywan \s+/\*.*\*/(?=\W)| 1031233d2500723e5594f3e7c70896ffeeef32b9c950ywan /\*.*\*/)""", re.VERBOSE) 1032233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1033233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1034233d2500723e5594f3e7c70896ffeeef32b9c950ywandef IsCppString(line): 1035233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Does line terminate so, that the next symbol is in string constant. 1036233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1037233d2500723e5594f3e7c70896ffeeef32b9c950ywan This function does not consider single-line nor multi-line comments. 1038233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1039233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 1040233d2500723e5594f3e7c70896ffeeef32b9c950ywan line: is a partial line of code starting from the 0..n. 1041233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1042233d2500723e5594f3e7c70896ffeeef32b9c950ywan Returns: 1043233d2500723e5594f3e7c70896ffeeef32b9c950ywan True, if next character appended to 'line' is inside a 1044233d2500723e5594f3e7c70896ffeeef32b9c950ywan string constant. 1045233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 1046233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1047233d2500723e5594f3e7c70896ffeeef32b9c950ywan line = line.replace(r'\\', 'XX') # after this, \\" does not match to \" 1048233d2500723e5594f3e7c70896ffeeef32b9c950ywan return ((line.count('"') - line.count(r'\"') - line.count("'\"'")) & 1) == 1 1049233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1050233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1051233d2500723e5594f3e7c70896ffeeef32b9c950ywandef CleanseRawStrings(raw_lines): 1052233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Removes C++11 raw strings from lines. 1053233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1054233d2500723e5594f3e7c70896ffeeef32b9c950ywan Before: 1055233d2500723e5594f3e7c70896ffeeef32b9c950ywan static const char kData[] = R"( 1056233d2500723e5594f3e7c70896ffeeef32b9c950ywan multi-line string 1057233d2500723e5594f3e7c70896ffeeef32b9c950ywan )"; 1058233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1059233d2500723e5594f3e7c70896ffeeef32b9c950ywan After: 1060233d2500723e5594f3e7c70896ffeeef32b9c950ywan static const char kData[] = "" 1061233d2500723e5594f3e7c70896ffeeef32b9c950ywan (replaced by blank line) 1062233d2500723e5594f3e7c70896ffeeef32b9c950ywan ""; 1063233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1064233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 1065233d2500723e5594f3e7c70896ffeeef32b9c950ywan raw_lines: list of raw lines. 1066233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1067233d2500723e5594f3e7c70896ffeeef32b9c950ywan Returns: 1068233d2500723e5594f3e7c70896ffeeef32b9c950ywan list of lines with C++11 raw strings replaced by empty strings. 1069233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 1070233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1071233d2500723e5594f3e7c70896ffeeef32b9c950ywan delimiter = None 1072233d2500723e5594f3e7c70896ffeeef32b9c950ywan lines_without_raw_strings = [] 1073233d2500723e5594f3e7c70896ffeeef32b9c950ywan for line in raw_lines: 1074233d2500723e5594f3e7c70896ffeeef32b9c950ywan if delimiter: 1075233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Inside a raw string, look for the end 1076233d2500723e5594f3e7c70896ffeeef32b9c950ywan end = line.find(delimiter) 1077233d2500723e5594f3e7c70896ffeeef32b9c950ywan if end >= 0: 1078233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Found the end of the string, match leading space for this 1079233d2500723e5594f3e7c70896ffeeef32b9c950ywan # line and resume copying the original lines, and also insert 1080233d2500723e5594f3e7c70896ffeeef32b9c950ywan # a "" on the last line. 1081233d2500723e5594f3e7c70896ffeeef32b9c950ywan leading_space = Match(r'^(\s*)\S', line) 1082233d2500723e5594f3e7c70896ffeeef32b9c950ywan line = leading_space.group(1) + '""' + line[end + len(delimiter):] 1083233d2500723e5594f3e7c70896ffeeef32b9c950ywan delimiter = None 1084233d2500723e5594f3e7c70896ffeeef32b9c950ywan else: 1085233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Haven't found the end yet, append a blank line. 1086233d2500723e5594f3e7c70896ffeeef32b9c950ywan line = '' 1087233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1088233d2500723e5594f3e7c70896ffeeef32b9c950ywan else: 1089233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Look for beginning of a raw string. 1090233d2500723e5594f3e7c70896ffeeef32b9c950ywan # See 2.14.15 [lex.string] for syntax. 1091233d2500723e5594f3e7c70896ffeeef32b9c950ywan matched = Match(r'^(.*)\b(?:R|u8R|uR|UR|LR)"([^\s\\()]*)\((.*)$', line) 1092233d2500723e5594f3e7c70896ffeeef32b9c950ywan if matched: 1093233d2500723e5594f3e7c70896ffeeef32b9c950ywan delimiter = ')' + matched.group(2) + '"' 1094233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1095233d2500723e5594f3e7c70896ffeeef32b9c950ywan end = matched.group(3).find(delimiter) 1096233d2500723e5594f3e7c70896ffeeef32b9c950ywan if end >= 0: 1097233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Raw string ended on same line 1098233d2500723e5594f3e7c70896ffeeef32b9c950ywan line = (matched.group(1) + '""' + 1099233d2500723e5594f3e7c70896ffeeef32b9c950ywan matched.group(3)[end + len(delimiter):]) 1100233d2500723e5594f3e7c70896ffeeef32b9c950ywan delimiter = None 1101233d2500723e5594f3e7c70896ffeeef32b9c950ywan else: 1102233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Start of a multi-line raw string 1103233d2500723e5594f3e7c70896ffeeef32b9c950ywan line = matched.group(1) + '""' 1104233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1105233d2500723e5594f3e7c70896ffeeef32b9c950ywan lines_without_raw_strings.append(line) 1106233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1107233d2500723e5594f3e7c70896ffeeef32b9c950ywan # TODO(unknown): if delimiter is not None here, we might want to 1108233d2500723e5594f3e7c70896ffeeef32b9c950ywan # emit a warning for unterminated string. 1109233d2500723e5594f3e7c70896ffeeef32b9c950ywan return lines_without_raw_strings 1110233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1111233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1112233d2500723e5594f3e7c70896ffeeef32b9c950ywandef FindNextMultiLineCommentStart(lines, lineix): 1113233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Find the beginning marker for a multiline comment.""" 1114233d2500723e5594f3e7c70896ffeeef32b9c950ywan while lineix < len(lines): 1115233d2500723e5594f3e7c70896ffeeef32b9c950ywan if lines[lineix].strip().startswith('/*'): 1116233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Only return this marker if the comment goes beyond this line 1117233d2500723e5594f3e7c70896ffeeef32b9c950ywan if lines[lineix].strip().find('*/', 2) < 0: 1118233d2500723e5594f3e7c70896ffeeef32b9c950ywan return lineix 1119233d2500723e5594f3e7c70896ffeeef32b9c950ywan lineix += 1 1120233d2500723e5594f3e7c70896ffeeef32b9c950ywan return len(lines) 1121233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1122233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1123233d2500723e5594f3e7c70896ffeeef32b9c950ywandef FindNextMultiLineCommentEnd(lines, lineix): 1124233d2500723e5594f3e7c70896ffeeef32b9c950ywan """We are inside a comment, find the end marker.""" 1125233d2500723e5594f3e7c70896ffeeef32b9c950ywan while lineix < len(lines): 1126233d2500723e5594f3e7c70896ffeeef32b9c950ywan if lines[lineix].strip().endswith('*/'): 1127233d2500723e5594f3e7c70896ffeeef32b9c950ywan return lineix 1128233d2500723e5594f3e7c70896ffeeef32b9c950ywan lineix += 1 1129233d2500723e5594f3e7c70896ffeeef32b9c950ywan return len(lines) 1130233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1131233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1132233d2500723e5594f3e7c70896ffeeef32b9c950ywandef RemoveMultiLineCommentsFromRange(lines, begin, end): 1133233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Clears a range of lines for multi-line comments.""" 1134233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Having // dummy comments makes the lines non-empty, so we will not get 1135233d2500723e5594f3e7c70896ffeeef32b9c950ywan # unnecessary blank line warnings later in the code. 1136233d2500723e5594f3e7c70896ffeeef32b9c950ywan for i in range(begin, end): 1137233d2500723e5594f3e7c70896ffeeef32b9c950ywan lines[i] = '// dummy' 1138233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1139233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1140233d2500723e5594f3e7c70896ffeeef32b9c950ywandef RemoveMultiLineComments(filename, lines, error): 1141233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Removes multiline (c-style) comments from lines.""" 1142233d2500723e5594f3e7c70896ffeeef32b9c950ywan lineix = 0 1143233d2500723e5594f3e7c70896ffeeef32b9c950ywan while lineix < len(lines): 1144233d2500723e5594f3e7c70896ffeeef32b9c950ywan lineix_begin = FindNextMultiLineCommentStart(lines, lineix) 1145233d2500723e5594f3e7c70896ffeeef32b9c950ywan if lineix_begin >= len(lines): 1146233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 1147233d2500723e5594f3e7c70896ffeeef32b9c950ywan lineix_end = FindNextMultiLineCommentEnd(lines, lineix_begin) 1148233d2500723e5594f3e7c70896ffeeef32b9c950ywan if lineix_end >= len(lines): 1149233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, lineix_begin + 1, 'readability/multiline_comment', 5, 1150233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Could not find end of multi-line comment') 1151233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 1152233d2500723e5594f3e7c70896ffeeef32b9c950ywan RemoveMultiLineCommentsFromRange(lines, lineix_begin, lineix_end + 1) 1153233d2500723e5594f3e7c70896ffeeef32b9c950ywan lineix = lineix_end + 1 1154233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1155233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1156233d2500723e5594f3e7c70896ffeeef32b9c950ywandef CleanseComments(line): 1157233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Removes //-comments and single-line C-style /* */ comments. 1158233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1159233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 1160233d2500723e5594f3e7c70896ffeeef32b9c950ywan line: A line of C++ source. 1161233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1162233d2500723e5594f3e7c70896ffeeef32b9c950ywan Returns: 1163233d2500723e5594f3e7c70896ffeeef32b9c950ywan The line with single-line comments removed. 1164233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 1165233d2500723e5594f3e7c70896ffeeef32b9c950ywan commentpos = line.find('//') 1166233d2500723e5594f3e7c70896ffeeef32b9c950ywan if commentpos != -1 and not IsCppString(line[:commentpos]): 1167233d2500723e5594f3e7c70896ffeeef32b9c950ywan line = line[:commentpos].rstrip() 1168233d2500723e5594f3e7c70896ffeeef32b9c950ywan # get rid of /* ... */ 1169233d2500723e5594f3e7c70896ffeeef32b9c950ywan return _RE_PATTERN_CLEANSE_LINE_C_COMMENTS.sub('', line) 1170233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1171233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1172233d2500723e5594f3e7c70896ffeeef32b9c950ywanclass CleansedLines(object): 1173233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Holds 3 copies of all lines with different preprocessing applied to them. 1174233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1175233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1) elided member contains lines without strings and comments, 1176233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2) lines member contains lines without comments, and 1177233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3) raw_lines member contains all the lines without processing. 1178233d2500723e5594f3e7c70896ffeeef32b9c950ywan All these three members are of <type 'list'>, and of the same length. 1179233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 1180233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1181233d2500723e5594f3e7c70896ffeeef32b9c950ywan def __init__(self, lines): 1182233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.elided = [] 1183233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.lines = [] 1184233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.raw_lines = lines 1185233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.num_lines = len(lines) 1186233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.lines_without_raw_strings = CleanseRawStrings(lines) 1187233d2500723e5594f3e7c70896ffeeef32b9c950ywan for linenum in range(len(self.lines_without_raw_strings)): 1188233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.lines.append(CleanseComments( 1189233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.lines_without_raw_strings[linenum])) 1190233d2500723e5594f3e7c70896ffeeef32b9c950ywan elided = self._CollapseStrings(self.lines_without_raw_strings[linenum]) 1191233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.elided.append(CleanseComments(elided)) 1192233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1193233d2500723e5594f3e7c70896ffeeef32b9c950ywan def NumLines(self): 1194233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Returns the number of lines represented.""" 1195233d2500723e5594f3e7c70896ffeeef32b9c950ywan return self.num_lines 1196233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1197233d2500723e5594f3e7c70896ffeeef32b9c950ywan @staticmethod 1198233d2500723e5594f3e7c70896ffeeef32b9c950ywan def _CollapseStrings(elided): 1199233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Collapses strings and chars on a line to simple "" or '' blocks. 1200233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1201233d2500723e5594f3e7c70896ffeeef32b9c950ywan We nix strings first so we're not fooled by text like '"http://"' 1202233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1203233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 1204233d2500723e5594f3e7c70896ffeeef32b9c950ywan elided: The line being processed. 1205233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1206233d2500723e5594f3e7c70896ffeeef32b9c950ywan Returns: 1207233d2500723e5594f3e7c70896ffeeef32b9c950ywan The line with collapsed strings. 1208233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 1209233d2500723e5594f3e7c70896ffeeef32b9c950ywan if not _RE_PATTERN_INCLUDE.match(elided): 1210233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Remove escaped characters first to make quote/single quote collapsing 1211233d2500723e5594f3e7c70896ffeeef32b9c950ywan # basic. Things that look like escaped characters shouldn't occur 1212233d2500723e5594f3e7c70896ffeeef32b9c950ywan # outside of strings and chars. 1213233d2500723e5594f3e7c70896ffeeef32b9c950ywan elided = _RE_PATTERN_CLEANSE_LINE_ESCAPES.sub('', elided) 1214233d2500723e5594f3e7c70896ffeeef32b9c950ywan elided = _RE_PATTERN_CLEANSE_LINE_SINGLE_QUOTES.sub("''", elided) 1215233d2500723e5594f3e7c70896ffeeef32b9c950ywan elided = _RE_PATTERN_CLEANSE_LINE_DOUBLE_QUOTES.sub('""', elided) 1216233d2500723e5594f3e7c70896ffeeef32b9c950ywan return elided 1217233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1218233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1219233d2500723e5594f3e7c70896ffeeef32b9c950ywandef FindEndOfExpressionInLine(line, startpos, depth, startchar, endchar): 1220233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Find the position just after the matching endchar. 1221233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1222233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 1223233d2500723e5594f3e7c70896ffeeef32b9c950ywan line: a CleansedLines line. 1224233d2500723e5594f3e7c70896ffeeef32b9c950ywan startpos: start searching at this position. 1225233d2500723e5594f3e7c70896ffeeef32b9c950ywan depth: nesting level at startpos. 1226233d2500723e5594f3e7c70896ffeeef32b9c950ywan startchar: expression opening character. 1227233d2500723e5594f3e7c70896ffeeef32b9c950ywan endchar: expression closing character. 1228233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1229233d2500723e5594f3e7c70896ffeeef32b9c950ywan Returns: 1230233d2500723e5594f3e7c70896ffeeef32b9c950ywan On finding matching endchar: (index just after matching endchar, 0) 1231233d2500723e5594f3e7c70896ffeeef32b9c950ywan Otherwise: (-1, new depth at end of this line) 1232233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 1233233d2500723e5594f3e7c70896ffeeef32b9c950ywan for i in xrange(startpos, len(line)): 1234233d2500723e5594f3e7c70896ffeeef32b9c950ywan if line[i] == startchar: 1235233d2500723e5594f3e7c70896ffeeef32b9c950ywan depth += 1 1236233d2500723e5594f3e7c70896ffeeef32b9c950ywan elif line[i] == endchar: 1237233d2500723e5594f3e7c70896ffeeef32b9c950ywan depth -= 1 1238233d2500723e5594f3e7c70896ffeeef32b9c950ywan if depth == 0: 1239233d2500723e5594f3e7c70896ffeeef32b9c950ywan return (i + 1, 0) 1240233d2500723e5594f3e7c70896ffeeef32b9c950ywan return (-1, depth) 1241233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1242233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1243233d2500723e5594f3e7c70896ffeeef32b9c950ywandef CloseExpression(clean_lines, linenum, pos): 1244233d2500723e5594f3e7c70896ffeeef32b9c950ywan """If input points to ( or { or [ or <, finds the position that closes it. 1245233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1246233d2500723e5594f3e7c70896ffeeef32b9c950ywan If lines[linenum][pos] points to a '(' or '{' or '[' or '<', finds the 1247233d2500723e5594f3e7c70896ffeeef32b9c950ywan linenum/pos that correspond to the closing of the expression. 1248233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1249233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 1250233d2500723e5594f3e7c70896ffeeef32b9c950ywan clean_lines: A CleansedLines instance containing the file. 1251233d2500723e5594f3e7c70896ffeeef32b9c950ywan linenum: The number of the line to check. 1252233d2500723e5594f3e7c70896ffeeef32b9c950ywan pos: A position on the line. 1253233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1254233d2500723e5594f3e7c70896ffeeef32b9c950ywan Returns: 1255233d2500723e5594f3e7c70896ffeeef32b9c950ywan A tuple (line, linenum, pos) pointer *past* the closing brace, or 1256233d2500723e5594f3e7c70896ffeeef32b9c950ywan (line, len(lines), -1) if we never find a close. Note we ignore 1257233d2500723e5594f3e7c70896ffeeef32b9c950ywan strings and comments when matching; and the line we return is the 1258233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'cleansed' line at linenum. 1259233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 1260233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1261233d2500723e5594f3e7c70896ffeeef32b9c950ywan line = clean_lines.elided[linenum] 1262233d2500723e5594f3e7c70896ffeeef32b9c950ywan startchar = line[pos] 1263233d2500723e5594f3e7c70896ffeeef32b9c950ywan if startchar not in '({[<': 1264233d2500723e5594f3e7c70896ffeeef32b9c950ywan return (line, clean_lines.NumLines(), -1) 1265233d2500723e5594f3e7c70896ffeeef32b9c950ywan if startchar == '(': endchar = ')' 1266233d2500723e5594f3e7c70896ffeeef32b9c950ywan if startchar == '[': endchar = ']' 1267233d2500723e5594f3e7c70896ffeeef32b9c950ywan if startchar == '{': endchar = '}' 1268233d2500723e5594f3e7c70896ffeeef32b9c950ywan if startchar == '<': endchar = '>' 1269233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1270233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Check first line 1271233d2500723e5594f3e7c70896ffeeef32b9c950ywan (end_pos, num_open) = FindEndOfExpressionInLine( 1272233d2500723e5594f3e7c70896ffeeef32b9c950ywan line, pos, 0, startchar, endchar) 1273233d2500723e5594f3e7c70896ffeeef32b9c950ywan if end_pos > -1: 1274233d2500723e5594f3e7c70896ffeeef32b9c950ywan return (line, linenum, end_pos) 1275233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1276233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Continue scanning forward 1277233d2500723e5594f3e7c70896ffeeef32b9c950ywan while linenum < clean_lines.NumLines() - 1: 1278233d2500723e5594f3e7c70896ffeeef32b9c950ywan linenum += 1 1279233d2500723e5594f3e7c70896ffeeef32b9c950ywan line = clean_lines.elided[linenum] 1280233d2500723e5594f3e7c70896ffeeef32b9c950ywan (end_pos, num_open) = FindEndOfExpressionInLine( 1281233d2500723e5594f3e7c70896ffeeef32b9c950ywan line, 0, num_open, startchar, endchar) 1282233d2500723e5594f3e7c70896ffeeef32b9c950ywan if end_pos > -1: 1283233d2500723e5594f3e7c70896ffeeef32b9c950ywan return (line, linenum, end_pos) 1284233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1285233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Did not find endchar before end of file, give up 1286233d2500723e5594f3e7c70896ffeeef32b9c950ywan return (line, clean_lines.NumLines(), -1) 1287233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1288233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1289233d2500723e5594f3e7c70896ffeeef32b9c950ywandef FindStartOfExpressionInLine(line, endpos, depth, startchar, endchar): 1290233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Find position at the matching startchar. 1291233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1292233d2500723e5594f3e7c70896ffeeef32b9c950ywan This is almost the reverse of FindEndOfExpressionInLine, but note 1293233d2500723e5594f3e7c70896ffeeef32b9c950ywan that the input position and returned position differs by 1. 1294233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1295233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 1296233d2500723e5594f3e7c70896ffeeef32b9c950ywan line: a CleansedLines line. 1297233d2500723e5594f3e7c70896ffeeef32b9c950ywan endpos: start searching at this position. 1298233d2500723e5594f3e7c70896ffeeef32b9c950ywan depth: nesting level at endpos. 1299233d2500723e5594f3e7c70896ffeeef32b9c950ywan startchar: expression opening character. 1300233d2500723e5594f3e7c70896ffeeef32b9c950ywan endchar: expression closing character. 1301233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1302233d2500723e5594f3e7c70896ffeeef32b9c950ywan Returns: 1303233d2500723e5594f3e7c70896ffeeef32b9c950ywan On finding matching startchar: (index at matching startchar, 0) 1304233d2500723e5594f3e7c70896ffeeef32b9c950ywan Otherwise: (-1, new depth at beginning of this line) 1305233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 1306233d2500723e5594f3e7c70896ffeeef32b9c950ywan for i in xrange(endpos, -1, -1): 1307233d2500723e5594f3e7c70896ffeeef32b9c950ywan if line[i] == endchar: 1308233d2500723e5594f3e7c70896ffeeef32b9c950ywan depth += 1 1309233d2500723e5594f3e7c70896ffeeef32b9c950ywan elif line[i] == startchar: 1310233d2500723e5594f3e7c70896ffeeef32b9c950ywan depth -= 1 1311233d2500723e5594f3e7c70896ffeeef32b9c950ywan if depth == 0: 1312233d2500723e5594f3e7c70896ffeeef32b9c950ywan return (i, 0) 1313233d2500723e5594f3e7c70896ffeeef32b9c950ywan return (-1, depth) 1314233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1315233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1316233d2500723e5594f3e7c70896ffeeef32b9c950ywandef ReverseCloseExpression(clean_lines, linenum, pos): 1317233d2500723e5594f3e7c70896ffeeef32b9c950ywan """If input points to ) or } or ] or >, finds the position that opens it. 1318233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1319233d2500723e5594f3e7c70896ffeeef32b9c950ywan If lines[linenum][pos] points to a ')' or '}' or ']' or '>', finds the 1320233d2500723e5594f3e7c70896ffeeef32b9c950ywan linenum/pos that correspond to the opening of the expression. 1321233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1322233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 1323233d2500723e5594f3e7c70896ffeeef32b9c950ywan clean_lines: A CleansedLines instance containing the file. 1324233d2500723e5594f3e7c70896ffeeef32b9c950ywan linenum: The number of the line to check. 1325233d2500723e5594f3e7c70896ffeeef32b9c950ywan pos: A position on the line. 1326233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1327233d2500723e5594f3e7c70896ffeeef32b9c950ywan Returns: 1328233d2500723e5594f3e7c70896ffeeef32b9c950ywan A tuple (line, linenum, pos) pointer *at* the opening brace, or 1329233d2500723e5594f3e7c70896ffeeef32b9c950ywan (line, 0, -1) if we never find the matching opening brace. Note 1330233d2500723e5594f3e7c70896ffeeef32b9c950ywan we ignore strings and comments when matching; and the line we 1331233d2500723e5594f3e7c70896ffeeef32b9c950ywan return is the 'cleansed' line at linenum. 1332233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 1333233d2500723e5594f3e7c70896ffeeef32b9c950ywan line = clean_lines.elided[linenum] 1334233d2500723e5594f3e7c70896ffeeef32b9c950ywan endchar = line[pos] 1335233d2500723e5594f3e7c70896ffeeef32b9c950ywan if endchar not in ')}]>': 1336233d2500723e5594f3e7c70896ffeeef32b9c950ywan return (line, 0, -1) 1337233d2500723e5594f3e7c70896ffeeef32b9c950ywan if endchar == ')': startchar = '(' 1338233d2500723e5594f3e7c70896ffeeef32b9c950ywan if endchar == ']': startchar = '[' 1339233d2500723e5594f3e7c70896ffeeef32b9c950ywan if endchar == '}': startchar = '{' 1340233d2500723e5594f3e7c70896ffeeef32b9c950ywan if endchar == '>': startchar = '<' 1341233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1342233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Check last line 1343233d2500723e5594f3e7c70896ffeeef32b9c950ywan (start_pos, num_open) = FindStartOfExpressionInLine( 1344233d2500723e5594f3e7c70896ffeeef32b9c950ywan line, pos, 0, startchar, endchar) 1345233d2500723e5594f3e7c70896ffeeef32b9c950ywan if start_pos > -1: 1346233d2500723e5594f3e7c70896ffeeef32b9c950ywan return (line, linenum, start_pos) 1347233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1348233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Continue scanning backward 1349233d2500723e5594f3e7c70896ffeeef32b9c950ywan while linenum > 0: 1350233d2500723e5594f3e7c70896ffeeef32b9c950ywan linenum -= 1 1351233d2500723e5594f3e7c70896ffeeef32b9c950ywan line = clean_lines.elided[linenum] 1352233d2500723e5594f3e7c70896ffeeef32b9c950ywan (start_pos, num_open) = FindStartOfExpressionInLine( 1353233d2500723e5594f3e7c70896ffeeef32b9c950ywan line, len(line) - 1, num_open, startchar, endchar) 1354233d2500723e5594f3e7c70896ffeeef32b9c950ywan if start_pos > -1: 1355233d2500723e5594f3e7c70896ffeeef32b9c950ywan return (line, linenum, start_pos) 1356233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1357233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Did not find startchar before beginning of file, give up 1358233d2500723e5594f3e7c70896ffeeef32b9c950ywan return (line, 0, -1) 1359233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1360233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1361233d2500723e5594f3e7c70896ffeeef32b9c950ywandef CheckForCopyright(filename, lines, error): 1362233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Logs an error if no Copyright message appears at the top of the file.""" 1363233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1364233d2500723e5594f3e7c70896ffeeef32b9c950ywan # We'll say it should occur by line 10. Don't forget there's a 1365233d2500723e5594f3e7c70896ffeeef32b9c950ywan # dummy line at the front. 1366233d2500723e5594f3e7c70896ffeeef32b9c950ywan for line in xrange(1, min(len(lines), 11)): 1367233d2500723e5594f3e7c70896ffeeef32b9c950ywan if re.search(r'Copyright', lines[line], re.I): break 1368233d2500723e5594f3e7c70896ffeeef32b9c950ywan else: # means no copyright line was found 1369233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, 0, 'legal/copyright', 5, 1370233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'No copyright message found. ' 1371233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'You should have a line: "Copyright [year] <Copyright Owner>"') 1372233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1373233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1374233d2500723e5594f3e7c70896ffeeef32b9c950ywandef GetHeaderGuardCPPVariable(filename): 1375233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Returns the CPP variable that should be used as a header guard. 1376233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1377233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 1378233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename: The name of a C++ header file. 1379233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1380233d2500723e5594f3e7c70896ffeeef32b9c950ywan Returns: 1381233d2500723e5594f3e7c70896ffeeef32b9c950ywan The CPP variable that should be used as a header guard in the 1382233d2500723e5594f3e7c70896ffeeef32b9c950ywan named file. 1383233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1384233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 1385233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1386233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Restores original filename in case that cpplint is invoked from Emacs's 1387233d2500723e5594f3e7c70896ffeeef32b9c950ywan # flymake. 1388233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename = re.sub(r'_flymake\.h$', '.h', filename) 1389233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename = re.sub(r'/\.flymake/([^/]*)$', r'/\1', filename) 1390233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1391233d2500723e5594f3e7c70896ffeeef32b9c950ywan fileinfo = FileInfo(filename) 1392233d2500723e5594f3e7c70896ffeeef32b9c950ywan file_path_from_root = fileinfo.RepositoryName() 1393233d2500723e5594f3e7c70896ffeeef32b9c950ywan if _root: 1394233d2500723e5594f3e7c70896ffeeef32b9c950ywan file_path_from_root = re.sub('^' + _root + os.sep, '', file_path_from_root) 1395233d2500723e5594f3e7c70896ffeeef32b9c950ywan return re.sub(r'[-./\s]', '_', file_path_from_root).upper() + '_' 1396233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1397233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1398233d2500723e5594f3e7c70896ffeeef32b9c950ywandef CheckForHeaderGuard(filename, lines, error): 1399233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Checks that the file contains a header guard. 1400233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1401233d2500723e5594f3e7c70896ffeeef32b9c950ywan Logs an error if no #ifndef header guard is present. For other 1402233d2500723e5594f3e7c70896ffeeef32b9c950ywan headers, checks that the full pathname is used. 1403233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1404233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 1405233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename: The name of the C++ header file. 1406233d2500723e5594f3e7c70896ffeeef32b9c950ywan lines: An array of strings, each representing a line of the file. 1407233d2500723e5594f3e7c70896ffeeef32b9c950ywan error: The function to call with any errors found. 1408233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 1409233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1410233d2500723e5594f3e7c70896ffeeef32b9c950ywan cppvar = GetHeaderGuardCPPVariable(filename) 1411233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1412233d2500723e5594f3e7c70896ffeeef32b9c950ywan ifndef = None 1413233d2500723e5594f3e7c70896ffeeef32b9c950ywan ifndef_linenum = 0 1414233d2500723e5594f3e7c70896ffeeef32b9c950ywan define = None 1415233d2500723e5594f3e7c70896ffeeef32b9c950ywan endif = None 1416233d2500723e5594f3e7c70896ffeeef32b9c950ywan endif_linenum = 0 1417233d2500723e5594f3e7c70896ffeeef32b9c950ywan for linenum, line in enumerate(lines): 1418233d2500723e5594f3e7c70896ffeeef32b9c950ywan linesplit = line.split() 1419233d2500723e5594f3e7c70896ffeeef32b9c950ywan if len(linesplit) >= 2: 1420233d2500723e5594f3e7c70896ffeeef32b9c950ywan # find the first occurrence of #ifndef and #define, save arg 1421233d2500723e5594f3e7c70896ffeeef32b9c950ywan if not ifndef and linesplit[0] == '#ifndef': 1422233d2500723e5594f3e7c70896ffeeef32b9c950ywan # set ifndef to the header guard presented on the #ifndef line. 1423233d2500723e5594f3e7c70896ffeeef32b9c950ywan ifndef = linesplit[1] 1424233d2500723e5594f3e7c70896ffeeef32b9c950ywan ifndef_linenum = linenum 1425233d2500723e5594f3e7c70896ffeeef32b9c950ywan if not define and linesplit[0] == '#define': 1426233d2500723e5594f3e7c70896ffeeef32b9c950ywan define = linesplit[1] 1427233d2500723e5594f3e7c70896ffeeef32b9c950ywan # find the last occurrence of #endif, save entire line 1428233d2500723e5594f3e7c70896ffeeef32b9c950ywan if line.startswith('#endif'): 1429233d2500723e5594f3e7c70896ffeeef32b9c950ywan endif = line 1430233d2500723e5594f3e7c70896ffeeef32b9c950ywan endif_linenum = linenum 1431233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1432233d2500723e5594f3e7c70896ffeeef32b9c950ywan if not ifndef: 1433233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, 0, 'build/header_guard', 5, 1434233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'No #ifndef header guard found, suggested CPP variable is: %s' % 1435233d2500723e5594f3e7c70896ffeeef32b9c950ywan cppvar) 1436233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 1437233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1438233d2500723e5594f3e7c70896ffeeef32b9c950ywan if not define: 1439233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, 0, 'build/header_guard', 5, 1440233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'No #define header guard found, suggested CPP variable is: %s' % 1441233d2500723e5594f3e7c70896ffeeef32b9c950ywan cppvar) 1442233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 1443233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1444233d2500723e5594f3e7c70896ffeeef32b9c950ywan # The guard should be PATH_FILE_H_, but we also allow PATH_FILE_H__ 1445233d2500723e5594f3e7c70896ffeeef32b9c950ywan # for backward compatibility. 1446233d2500723e5594f3e7c70896ffeeef32b9c950ywan if ifndef != cppvar: 1447233d2500723e5594f3e7c70896ffeeef32b9c950ywan error_level = 0 1448233d2500723e5594f3e7c70896ffeeef32b9c950ywan if ifndef != cppvar + '_': 1449233d2500723e5594f3e7c70896ffeeef32b9c950ywan error_level = 5 1450233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1451233d2500723e5594f3e7c70896ffeeef32b9c950ywan ParseNolintSuppressions(filename, lines[ifndef_linenum], ifndef_linenum, 1452233d2500723e5594f3e7c70896ffeeef32b9c950ywan error) 1453233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, ifndef_linenum, 'build/header_guard', error_level, 1454233d2500723e5594f3e7c70896ffeeef32b9c950ywan '#ifndef header guard has wrong style, please use: %s' % cppvar) 1455233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1456233d2500723e5594f3e7c70896ffeeef32b9c950ywan if define != ifndef: 1457233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, 0, 'build/header_guard', 5, 1458233d2500723e5594f3e7c70896ffeeef32b9c950ywan '#ifndef and #define don\'t match, suggested CPP variable is: %s' % 1459233d2500723e5594f3e7c70896ffeeef32b9c950ywan cppvar) 1460233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 1461233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1462233d2500723e5594f3e7c70896ffeeef32b9c950ywan if endif != ('#endif // %s' % cppvar): 1463233d2500723e5594f3e7c70896ffeeef32b9c950ywan error_level = 0 1464233d2500723e5594f3e7c70896ffeeef32b9c950ywan if endif != ('#endif // %s' % (cppvar + '_')): 1465233d2500723e5594f3e7c70896ffeeef32b9c950ywan error_level = 5 1466233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1467233d2500723e5594f3e7c70896ffeeef32b9c950ywan ParseNolintSuppressions(filename, lines[endif_linenum], endif_linenum, 1468233d2500723e5594f3e7c70896ffeeef32b9c950ywan error) 1469233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, endif_linenum, 'build/header_guard', error_level, 1470233d2500723e5594f3e7c70896ffeeef32b9c950ywan '#endif line should be "#endif // %s"' % cppvar) 1471233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1472233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1473233d2500723e5594f3e7c70896ffeeef32b9c950ywandef CheckForBadCharacters(filename, lines, error): 1474233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Logs an error for each line containing bad characters. 1475233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1476233d2500723e5594f3e7c70896ffeeef32b9c950ywan Two kinds of bad characters: 1477233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1478233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1. Unicode replacement characters: These indicate that either the file 1479233d2500723e5594f3e7c70896ffeeef32b9c950ywan contained invalid UTF-8 (likely) or Unicode replacement characters (which 1480233d2500723e5594f3e7c70896ffeeef32b9c950ywan it shouldn't). Note that it's possible for this to throw off line 1481233d2500723e5594f3e7c70896ffeeef32b9c950ywan numbering if the invalid UTF-8 occurred adjacent to a newline. 1482233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1483233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2. NUL bytes. These are problematic for some tools. 1484233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1485233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 1486233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename: The name of the current file. 1487233d2500723e5594f3e7c70896ffeeef32b9c950ywan lines: An array of strings, each representing a line of the file. 1488233d2500723e5594f3e7c70896ffeeef32b9c950ywan error: The function to call with any errors found. 1489233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 1490233d2500723e5594f3e7c70896ffeeef32b9c950ywan for linenum, line in enumerate(lines): 1491233d2500723e5594f3e7c70896ffeeef32b9c950ywan if u'\ufffd' in line: 1492233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'readability/utf8', 5, 1493233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Line contains invalid UTF-8 (or Unicode replacement character).') 1494233d2500723e5594f3e7c70896ffeeef32b9c950ywan if '\0' in line: 1495233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'readability/nul', 5, 'Line contains NUL byte.') 1496233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1497233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1498233d2500723e5594f3e7c70896ffeeef32b9c950ywandef CheckForNewlineAtEOF(filename, lines, error): 1499233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Logs an error if there is no newline char at the end of the file. 1500233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1501233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 1502233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename: The name of the current file. 1503233d2500723e5594f3e7c70896ffeeef32b9c950ywan lines: An array of strings, each representing a line of the file. 1504233d2500723e5594f3e7c70896ffeeef32b9c950ywan error: The function to call with any errors found. 1505233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 1506233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1507233d2500723e5594f3e7c70896ffeeef32b9c950ywan # The array lines() was created by adding two newlines to the 1508233d2500723e5594f3e7c70896ffeeef32b9c950ywan # original file (go figure), then splitting on \n. 1509233d2500723e5594f3e7c70896ffeeef32b9c950ywan # To verify that the file ends in \n, we just have to make sure the 1510233d2500723e5594f3e7c70896ffeeef32b9c950ywan # last-but-two element of lines() exists and is empty. 1511233d2500723e5594f3e7c70896ffeeef32b9c950ywan if len(lines) < 3 or lines[-2]: 1512233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, len(lines) - 2, 'whitespace/ending_newline', 5, 1513233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Could not find a newline character at the end of the file.') 1514233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1515233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1516233d2500723e5594f3e7c70896ffeeef32b9c950ywandef CheckForMultilineCommentsAndStrings(filename, clean_lines, linenum, error): 1517233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Logs an error if we see /* ... */ or "..." that extend past one line. 1518233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1519233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* ... */ comments are legit inside macros, for one line. 1520233d2500723e5594f3e7c70896ffeeef32b9c950ywan Otherwise, we prefer // comments, so it's ok to warn about the 1521233d2500723e5594f3e7c70896ffeeef32b9c950ywan other. Likewise, it's ok for strings to extend across multiple 1522233d2500723e5594f3e7c70896ffeeef32b9c950ywan lines, as long as a line continuation character (backslash) 1523233d2500723e5594f3e7c70896ffeeef32b9c950ywan terminates each line. Although not currently prohibited by the C++ 1524233d2500723e5594f3e7c70896ffeeef32b9c950ywan style guide, it's ugly and unnecessary. We don't do well with either 1525233d2500723e5594f3e7c70896ffeeef32b9c950ywan in this lint program, so we warn about both. 1526233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1527233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 1528233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename: The name of the current file. 1529233d2500723e5594f3e7c70896ffeeef32b9c950ywan clean_lines: A CleansedLines instance containing the file. 1530233d2500723e5594f3e7c70896ffeeef32b9c950ywan linenum: The number of the line to check. 1531233d2500723e5594f3e7c70896ffeeef32b9c950ywan error: The function to call with any errors found. 1532233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 1533233d2500723e5594f3e7c70896ffeeef32b9c950ywan line = clean_lines.elided[linenum] 1534233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1535233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Remove all \\ (escaped backslashes) from the line. They are OK, and the 1536233d2500723e5594f3e7c70896ffeeef32b9c950ywan # second (escaped) slash may trigger later \" detection erroneously. 1537233d2500723e5594f3e7c70896ffeeef32b9c950ywan line = line.replace('\\\\', '') 1538233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1539233d2500723e5594f3e7c70896ffeeef32b9c950ywan if line.count('/*') > line.count('*/'): 1540233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'readability/multiline_comment', 5, 1541233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Complex multi-line /*...*/-style comment found. ' 1542233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Lint may give bogus warnings. ' 1543233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Consider replacing these with //-style comments, ' 1544233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'with #if 0...#endif, ' 1545233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'or with more clearly structured multi-line comments.') 1546233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1547233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (line.count('"') - line.count('\\"')) % 2: 1548233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'readability/multiline_string', 5, 1549233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Multi-line string ("...") found. This lint script doesn\'t ' 1550233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'do well with such strings, and may give bogus warnings. ' 1551233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Use C++11 raw strings or concatenation instead.') 1552233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1553233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1554233d2500723e5594f3e7c70896ffeeef32b9c950ywanthreading_list = ( 1555233d2500723e5594f3e7c70896ffeeef32b9c950ywan ('asctime(', 'asctime_r('), 1556233d2500723e5594f3e7c70896ffeeef32b9c950ywan ('ctime(', 'ctime_r('), 1557233d2500723e5594f3e7c70896ffeeef32b9c950ywan ('getgrgid(', 'getgrgid_r('), 1558233d2500723e5594f3e7c70896ffeeef32b9c950ywan ('getgrnam(', 'getgrnam_r('), 1559233d2500723e5594f3e7c70896ffeeef32b9c950ywan ('getlogin(', 'getlogin_r('), 1560233d2500723e5594f3e7c70896ffeeef32b9c950ywan ('getpwnam(', 'getpwnam_r('), 1561233d2500723e5594f3e7c70896ffeeef32b9c950ywan ('getpwuid(', 'getpwuid_r('), 1562233d2500723e5594f3e7c70896ffeeef32b9c950ywan ('gmtime(', 'gmtime_r('), 1563233d2500723e5594f3e7c70896ffeeef32b9c950ywan ('localtime(', 'localtime_r('), 1564233d2500723e5594f3e7c70896ffeeef32b9c950ywan ('rand(', 'rand_r('), 1565233d2500723e5594f3e7c70896ffeeef32b9c950ywan ('strtok(', 'strtok_r('), 1566233d2500723e5594f3e7c70896ffeeef32b9c950ywan ('ttyname(', 'ttyname_r('), 1567233d2500723e5594f3e7c70896ffeeef32b9c950ywan ) 1568233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1569233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1570233d2500723e5594f3e7c70896ffeeef32b9c950ywandef CheckPosixThreading(filename, clean_lines, linenum, error): 1571233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Checks for calls to thread-unsafe functions. 1572233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1573233d2500723e5594f3e7c70896ffeeef32b9c950ywan Much code has been originally written without consideration of 1574233d2500723e5594f3e7c70896ffeeef32b9c950ywan multi-threading. Also, engineers are relying on their old experience; 1575233d2500723e5594f3e7c70896ffeeef32b9c950ywan they have learned posix before threading extensions were added. These 1576233d2500723e5594f3e7c70896ffeeef32b9c950ywan tests guide the engineers to use thread-safe functions (when using 1577233d2500723e5594f3e7c70896ffeeef32b9c950ywan posix directly). 1578233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1579233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 1580233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename: The name of the current file. 1581233d2500723e5594f3e7c70896ffeeef32b9c950ywan clean_lines: A CleansedLines instance containing the file. 1582233d2500723e5594f3e7c70896ffeeef32b9c950ywan linenum: The number of the line to check. 1583233d2500723e5594f3e7c70896ffeeef32b9c950ywan error: The function to call with any errors found. 1584233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 1585233d2500723e5594f3e7c70896ffeeef32b9c950ywan line = clean_lines.elided[linenum] 1586233d2500723e5594f3e7c70896ffeeef32b9c950ywan for single_thread_function, multithread_safe_function in threading_list: 1587233d2500723e5594f3e7c70896ffeeef32b9c950ywan ix = line.find(single_thread_function) 1588233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Comparisons made explicit for clarity -- pylint: disable=g-explicit-bool-comparison 1589233d2500723e5594f3e7c70896ffeeef32b9c950ywan if ix >= 0 and (ix == 0 or (not line[ix - 1].isalnum() and 1590233d2500723e5594f3e7c70896ffeeef32b9c950ywan line[ix - 1] not in ('_', '.', '>'))): 1591233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'runtime/threadsafe_fn', 2, 1592233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Consider using ' + multithread_safe_function + 1593233d2500723e5594f3e7c70896ffeeef32b9c950ywan '...) instead of ' + single_thread_function + 1594233d2500723e5594f3e7c70896ffeeef32b9c950ywan '...) for improved thread safety.') 1595233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1596233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1597233d2500723e5594f3e7c70896ffeeef32b9c950ywandef CheckVlogArguments(filename, clean_lines, linenum, error): 1598233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Checks that VLOG() is only used for defining a logging level. 1599233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1600233d2500723e5594f3e7c70896ffeeef32b9c950ywan For example, VLOG(2) is correct. VLOG(INFO), VLOG(WARNING), VLOG(ERROR), and 1601233d2500723e5594f3e7c70896ffeeef32b9c950ywan VLOG(FATAL) are not. 1602233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1603233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 1604233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename: The name of the current file. 1605233d2500723e5594f3e7c70896ffeeef32b9c950ywan clean_lines: A CleansedLines instance containing the file. 1606233d2500723e5594f3e7c70896ffeeef32b9c950ywan linenum: The number of the line to check. 1607233d2500723e5594f3e7c70896ffeeef32b9c950ywan error: The function to call with any errors found. 1608233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 1609233d2500723e5594f3e7c70896ffeeef32b9c950ywan line = clean_lines.elided[linenum] 1610233d2500723e5594f3e7c70896ffeeef32b9c950ywan if Search(r'\bVLOG\((INFO|ERROR|WARNING|DFATAL|FATAL)\)', line): 1611233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'runtime/vlog', 5, 1612233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'VLOG() should be used with numeric verbosity level. ' 1613233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Use LOG() if you want symbolic severity levels.') 1614233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1615233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1616233d2500723e5594f3e7c70896ffeeef32b9c950ywan# Matches invalid increment: *count++, which moves pointer instead of 1617233d2500723e5594f3e7c70896ffeeef32b9c950ywan# incrementing a value. 1618233d2500723e5594f3e7c70896ffeeef32b9c950ywan_RE_PATTERN_INVALID_INCREMENT = re.compile( 1619233d2500723e5594f3e7c70896ffeeef32b9c950ywan r'^\s*\*\w+(\+\+|--);') 1620233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1621233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1622233d2500723e5594f3e7c70896ffeeef32b9c950ywandef CheckInvalidIncrement(filename, clean_lines, linenum, error): 1623233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Checks for invalid increment *count++. 1624233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1625233d2500723e5594f3e7c70896ffeeef32b9c950ywan For example following function: 1626233d2500723e5594f3e7c70896ffeeef32b9c950ywan void increment_counter(int* count) { 1627233d2500723e5594f3e7c70896ffeeef32b9c950ywan *count++; 1628233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 1629233d2500723e5594f3e7c70896ffeeef32b9c950ywan is invalid, because it effectively does count++, moving pointer, and should 1630233d2500723e5594f3e7c70896ffeeef32b9c950ywan be replaced with ++*count, (*count)++ or *count += 1. 1631233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1632233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 1633233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename: The name of the current file. 1634233d2500723e5594f3e7c70896ffeeef32b9c950ywan clean_lines: A CleansedLines instance containing the file. 1635233d2500723e5594f3e7c70896ffeeef32b9c950ywan linenum: The number of the line to check. 1636233d2500723e5594f3e7c70896ffeeef32b9c950ywan error: The function to call with any errors found. 1637233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 1638233d2500723e5594f3e7c70896ffeeef32b9c950ywan line = clean_lines.elided[linenum] 1639233d2500723e5594f3e7c70896ffeeef32b9c950ywan if _RE_PATTERN_INVALID_INCREMENT.match(line): 1640233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'runtime/invalid_increment', 5, 1641233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Changing pointer instead of value (or unused value of operator*).') 1642233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1643233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1644233d2500723e5594f3e7c70896ffeeef32b9c950ywanclass _BlockInfo(object): 1645233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Stores information about a generic block of code.""" 1646233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1647233d2500723e5594f3e7c70896ffeeef32b9c950ywan def __init__(self, seen_open_brace): 1648233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.seen_open_brace = seen_open_brace 1649233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.open_parentheses = 0 1650233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.inline_asm = _NO_ASM 1651233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1652233d2500723e5594f3e7c70896ffeeef32b9c950ywan def CheckBegin(self, filename, clean_lines, linenum, error): 1653233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Run checks that applies to text up to the opening brace. 1654233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1655233d2500723e5594f3e7c70896ffeeef32b9c950ywan This is mostly for checking the text after the class identifier 1656233d2500723e5594f3e7c70896ffeeef32b9c950ywan and the "{", usually where the base class is specified. For other 1657233d2500723e5594f3e7c70896ffeeef32b9c950ywan blocks, there isn't much to check, so we always pass. 1658233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1659233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 1660233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename: The name of the current file. 1661233d2500723e5594f3e7c70896ffeeef32b9c950ywan clean_lines: A CleansedLines instance containing the file. 1662233d2500723e5594f3e7c70896ffeeef32b9c950ywan linenum: The number of the line to check. 1663233d2500723e5594f3e7c70896ffeeef32b9c950ywan error: The function to call with any errors found. 1664233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 1665233d2500723e5594f3e7c70896ffeeef32b9c950ywan pass 1666233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1667233d2500723e5594f3e7c70896ffeeef32b9c950ywan def CheckEnd(self, filename, clean_lines, linenum, error): 1668233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Run checks that applies to text after the closing brace. 1669233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1670233d2500723e5594f3e7c70896ffeeef32b9c950ywan This is mostly used for checking end of namespace comments. 1671233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1672233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 1673233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename: The name of the current file. 1674233d2500723e5594f3e7c70896ffeeef32b9c950ywan clean_lines: A CleansedLines instance containing the file. 1675233d2500723e5594f3e7c70896ffeeef32b9c950ywan linenum: The number of the line to check. 1676233d2500723e5594f3e7c70896ffeeef32b9c950ywan error: The function to call with any errors found. 1677233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 1678233d2500723e5594f3e7c70896ffeeef32b9c950ywan pass 1679233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1680233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1681233d2500723e5594f3e7c70896ffeeef32b9c950ywanclass _ClassInfo(_BlockInfo): 1682233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Stores information about a class.""" 1683233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1684233d2500723e5594f3e7c70896ffeeef32b9c950ywan def __init__(self, name, class_or_struct, clean_lines, linenum): 1685233d2500723e5594f3e7c70896ffeeef32b9c950ywan _BlockInfo.__init__(self, False) 1686233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.name = name 1687233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.starting_linenum = linenum 1688233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.is_derived = False 1689233d2500723e5594f3e7c70896ffeeef32b9c950ywan if class_or_struct == 'struct': 1690233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.access = 'public' 1691233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.is_struct = True 1692233d2500723e5594f3e7c70896ffeeef32b9c950ywan else: 1693233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.access = 'private' 1694233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.is_struct = False 1695233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1696233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Remember initial indentation level for this class. Using raw_lines here 1697233d2500723e5594f3e7c70896ffeeef32b9c950ywan # instead of elided to account for leading comments. 1698233d2500723e5594f3e7c70896ffeeef32b9c950ywan initial_indent = Match(r'^( *)\S', clean_lines.raw_lines[linenum]) 1699233d2500723e5594f3e7c70896ffeeef32b9c950ywan if initial_indent: 1700233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.class_indent = len(initial_indent.group(1)) 1701233d2500723e5594f3e7c70896ffeeef32b9c950ywan else: 1702233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.class_indent = 0 1703233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1704233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Try to find the end of the class. This will be confused by things like: 1705233d2500723e5594f3e7c70896ffeeef32b9c950ywan # class A { 1706233d2500723e5594f3e7c70896ffeeef32b9c950ywan # } *x = { ... 1707233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 1708233d2500723e5594f3e7c70896ffeeef32b9c950ywan # But it's still good enough for CheckSectionSpacing. 1709233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.last_line = 0 1710233d2500723e5594f3e7c70896ffeeef32b9c950ywan depth = 0 1711233d2500723e5594f3e7c70896ffeeef32b9c950ywan for i in range(linenum, clean_lines.NumLines()): 1712233d2500723e5594f3e7c70896ffeeef32b9c950ywan line = clean_lines.elided[i] 1713233d2500723e5594f3e7c70896ffeeef32b9c950ywan depth += line.count('{') - line.count('}') 1714233d2500723e5594f3e7c70896ffeeef32b9c950ywan if not depth: 1715233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.last_line = i 1716233d2500723e5594f3e7c70896ffeeef32b9c950ywan break 1717233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1718233d2500723e5594f3e7c70896ffeeef32b9c950ywan def CheckBegin(self, filename, clean_lines, linenum, error): 1719233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Look for a bare ':' 1720233d2500723e5594f3e7c70896ffeeef32b9c950ywan if Search('(^|[^:]):($|[^:])', clean_lines.elided[linenum]): 1721233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.is_derived = True 1722233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1723233d2500723e5594f3e7c70896ffeeef32b9c950ywan def CheckEnd(self, filename, clean_lines, linenum, error): 1724233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Check that closing brace is aligned with beginning of the class. 1725233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Only do this if the closing brace is indented by only whitespaces. 1726233d2500723e5594f3e7c70896ffeeef32b9c950ywan # This means we will not check single-line class definitions. 1727233d2500723e5594f3e7c70896ffeeef32b9c950ywan indent = Match(r'^( *)\}', clean_lines.elided[linenum]) 1728233d2500723e5594f3e7c70896ffeeef32b9c950ywan if indent and len(indent.group(1)) != self.class_indent: 1729233d2500723e5594f3e7c70896ffeeef32b9c950ywan if self.is_struct: 1730233d2500723e5594f3e7c70896ffeeef32b9c950ywan parent = 'struct ' + self.name 1731233d2500723e5594f3e7c70896ffeeef32b9c950ywan else: 1732233d2500723e5594f3e7c70896ffeeef32b9c950ywan parent = 'class ' + self.name 1733233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'whitespace/indent', 3, 1734233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Closing brace should be aligned with beginning of %s' % parent) 1735233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1736233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1737233d2500723e5594f3e7c70896ffeeef32b9c950ywanclass _NamespaceInfo(_BlockInfo): 1738233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Stores information about a namespace.""" 1739233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1740233d2500723e5594f3e7c70896ffeeef32b9c950ywan def __init__(self, name, linenum): 1741233d2500723e5594f3e7c70896ffeeef32b9c950ywan _BlockInfo.__init__(self, False) 1742233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.name = name or '' 1743233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.starting_linenum = linenum 1744233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1745233d2500723e5594f3e7c70896ffeeef32b9c950ywan def CheckEnd(self, filename, clean_lines, linenum, error): 1746233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Check end of namespace comments.""" 1747233d2500723e5594f3e7c70896ffeeef32b9c950ywan line = clean_lines.raw_lines[linenum] 1748233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1749233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Check how many lines is enclosed in this namespace. Don't issue 1750233d2500723e5594f3e7c70896ffeeef32b9c950ywan # warning for missing namespace comments if there aren't enough 1751233d2500723e5594f3e7c70896ffeeef32b9c950ywan # lines. However, do apply checks if there is already an end of 1752233d2500723e5594f3e7c70896ffeeef32b9c950ywan # namespace comment and it's incorrect. 1753233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 1754233d2500723e5594f3e7c70896ffeeef32b9c950ywan # TODO(unknown): We always want to check end of namespace comments 1755233d2500723e5594f3e7c70896ffeeef32b9c950ywan # if a namespace is large, but sometimes we also want to apply the 1756233d2500723e5594f3e7c70896ffeeef32b9c950ywan # check if a short namespace contained nontrivial things (something 1757233d2500723e5594f3e7c70896ffeeef32b9c950ywan # other than forward declarations). There is currently no logic on 1758233d2500723e5594f3e7c70896ffeeef32b9c950ywan # deciding what these nontrivial things are, so this check is 1759233d2500723e5594f3e7c70896ffeeef32b9c950ywan # triggered by namespace size only, which works most of the time. 1760233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (linenum - self.starting_linenum < 10 1761233d2500723e5594f3e7c70896ffeeef32b9c950ywan and not Match(r'};*\s*(//|/\*).*\bnamespace\b', line)): 1762233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 1763233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1764233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Look for matching comment at end of namespace. 1765233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 1766233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Note that we accept C style "/* */" comments for terminating 1767233d2500723e5594f3e7c70896ffeeef32b9c950ywan # namespaces, so that code that terminate namespaces inside 1768233d2500723e5594f3e7c70896ffeeef32b9c950ywan # preprocessor macros can be cpplint clean. 1769233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 1770233d2500723e5594f3e7c70896ffeeef32b9c950ywan # We also accept stuff like "// end of namespace <name>." with the 1771233d2500723e5594f3e7c70896ffeeef32b9c950ywan # period at the end. 1772233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 1773233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Besides these, we don't accept anything else, otherwise we might 1774233d2500723e5594f3e7c70896ffeeef32b9c950ywan # get false negatives when existing comment is a substring of the 1775233d2500723e5594f3e7c70896ffeeef32b9c950ywan # expected namespace. 1776233d2500723e5594f3e7c70896ffeeef32b9c950ywan if self.name: 1777233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Named namespace 1778233d2500723e5594f3e7c70896ffeeef32b9c950ywan if not Match((r'};*\s*(//|/\*).*\bnamespace\s+' + re.escape(self.name) + 1779233d2500723e5594f3e7c70896ffeeef32b9c950ywan r'[\*/\.\\\s]*$'), 1780233d2500723e5594f3e7c70896ffeeef32b9c950ywan line): 1781233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'readability/namespace', 5, 1782233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Namespace should be terminated with "// namespace %s"' % 1783233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.name) 1784233d2500723e5594f3e7c70896ffeeef32b9c950ywan else: 1785233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Anonymous namespace 1786233d2500723e5594f3e7c70896ffeeef32b9c950ywan if not Match(r'};*\s*(//|/\*).*\bnamespace[\*/\.\\\s]*$', line): 1787233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'readability/namespace', 5, 1788233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Namespace should be terminated with "// namespace"') 1789233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1790233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1791233d2500723e5594f3e7c70896ffeeef32b9c950ywanclass _PreprocessorInfo(object): 1792233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Stores checkpoints of nesting stacks when #if/#else is seen.""" 1793233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1794233d2500723e5594f3e7c70896ffeeef32b9c950ywan def __init__(self, stack_before_if): 1795233d2500723e5594f3e7c70896ffeeef32b9c950ywan # The entire nesting stack before #if 1796233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.stack_before_if = stack_before_if 1797233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1798233d2500723e5594f3e7c70896ffeeef32b9c950ywan # The entire nesting stack up to #else 1799233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.stack_before_else = [] 1800233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1801233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Whether we have already seen #else or #elif 1802233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.seen_else = False 1803233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1804233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1805233d2500723e5594f3e7c70896ffeeef32b9c950ywanclass _NestingState(object): 1806233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Holds states related to parsing braces.""" 1807233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1808233d2500723e5594f3e7c70896ffeeef32b9c950ywan def __init__(self): 1809233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Stack for tracking all braces. An object is pushed whenever we 1810233d2500723e5594f3e7c70896ffeeef32b9c950ywan # see a "{", and popped when we see a "}". Only 3 types of 1811233d2500723e5594f3e7c70896ffeeef32b9c950ywan # objects are possible: 1812233d2500723e5594f3e7c70896ffeeef32b9c950ywan # - _ClassInfo: a class or struct. 1813233d2500723e5594f3e7c70896ffeeef32b9c950ywan # - _NamespaceInfo: a namespace. 1814233d2500723e5594f3e7c70896ffeeef32b9c950ywan # - _BlockInfo: some other type of block. 1815233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.stack = [] 1816233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1817233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Stack of _PreprocessorInfo objects. 1818233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.pp_stack = [] 1819233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1820233d2500723e5594f3e7c70896ffeeef32b9c950ywan def SeenOpenBrace(self): 1821233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Check if we have seen the opening brace for the innermost block. 1822233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1823233d2500723e5594f3e7c70896ffeeef32b9c950ywan Returns: 1824233d2500723e5594f3e7c70896ffeeef32b9c950ywan True if we have seen the opening brace, False if the innermost 1825233d2500723e5594f3e7c70896ffeeef32b9c950ywan block is still expecting an opening brace. 1826233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 1827233d2500723e5594f3e7c70896ffeeef32b9c950ywan return (not self.stack) or self.stack[-1].seen_open_brace 1828233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1829233d2500723e5594f3e7c70896ffeeef32b9c950ywan def InNamespaceBody(self): 1830233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Check if we are currently one level inside a namespace body. 1831233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1832233d2500723e5594f3e7c70896ffeeef32b9c950ywan Returns: 1833233d2500723e5594f3e7c70896ffeeef32b9c950ywan True if top of the stack is a namespace block, False otherwise. 1834233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 1835233d2500723e5594f3e7c70896ffeeef32b9c950ywan return self.stack and isinstance(self.stack[-1], _NamespaceInfo) 1836233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1837233d2500723e5594f3e7c70896ffeeef32b9c950ywan def UpdatePreprocessor(self, line): 1838233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Update preprocessor stack. 1839233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1840233d2500723e5594f3e7c70896ffeeef32b9c950ywan We need to handle preprocessors due to classes like this: 1841233d2500723e5594f3e7c70896ffeeef32b9c950ywan #ifdef SWIG 1842233d2500723e5594f3e7c70896ffeeef32b9c950ywan struct ResultDetailsPageElementExtensionPoint { 1843233d2500723e5594f3e7c70896ffeeef32b9c950ywan #else 1844233d2500723e5594f3e7c70896ffeeef32b9c950ywan struct ResultDetailsPageElementExtensionPoint : public Extension { 1845233d2500723e5594f3e7c70896ffeeef32b9c950ywan #endif 1846233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1847233d2500723e5594f3e7c70896ffeeef32b9c950ywan We make the following assumptions (good enough for most files): 1848233d2500723e5594f3e7c70896ffeeef32b9c950ywan - Preprocessor condition evaluates to true from #if up to first 1849233d2500723e5594f3e7c70896ffeeef32b9c950ywan #else/#elif/#endif. 1850233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1851233d2500723e5594f3e7c70896ffeeef32b9c950ywan - Preprocessor condition evaluates to false from #else/#elif up 1852233d2500723e5594f3e7c70896ffeeef32b9c950ywan to #endif. We still perform lint checks on these lines, but 1853233d2500723e5594f3e7c70896ffeeef32b9c950ywan these do not affect nesting stack. 1854233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1855233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 1856233d2500723e5594f3e7c70896ffeeef32b9c950ywan line: current line to check. 1857233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 1858233d2500723e5594f3e7c70896ffeeef32b9c950ywan if Match(r'^\s*#\s*(if|ifdef|ifndef)\b', line): 1859233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Beginning of #if block, save the nesting stack here. The saved 1860233d2500723e5594f3e7c70896ffeeef32b9c950ywan # stack will allow us to restore the parsing state in the #else case. 1861233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.pp_stack.append(_PreprocessorInfo(copy.deepcopy(self.stack))) 1862233d2500723e5594f3e7c70896ffeeef32b9c950ywan elif Match(r'^\s*#\s*(else|elif)\b', line): 1863233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Beginning of #else block 1864233d2500723e5594f3e7c70896ffeeef32b9c950ywan if self.pp_stack: 1865233d2500723e5594f3e7c70896ffeeef32b9c950ywan if not self.pp_stack[-1].seen_else: 1866233d2500723e5594f3e7c70896ffeeef32b9c950ywan # This is the first #else or #elif block. Remember the 1867233d2500723e5594f3e7c70896ffeeef32b9c950ywan # whole nesting stack up to this point. This is what we 1868233d2500723e5594f3e7c70896ffeeef32b9c950ywan # keep after the #endif. 1869233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.pp_stack[-1].seen_else = True 1870233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.pp_stack[-1].stack_before_else = copy.deepcopy(self.stack) 1871233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1872233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Restore the stack to how it was before the #if 1873233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.stack = copy.deepcopy(self.pp_stack[-1].stack_before_if) 1874233d2500723e5594f3e7c70896ffeeef32b9c950ywan else: 1875233d2500723e5594f3e7c70896ffeeef32b9c950ywan # TODO(unknown): unexpected #else, issue warning? 1876233d2500723e5594f3e7c70896ffeeef32b9c950ywan pass 1877233d2500723e5594f3e7c70896ffeeef32b9c950ywan elif Match(r'^\s*#\s*endif\b', line): 1878233d2500723e5594f3e7c70896ffeeef32b9c950ywan # End of #if or #else blocks. 1879233d2500723e5594f3e7c70896ffeeef32b9c950ywan if self.pp_stack: 1880233d2500723e5594f3e7c70896ffeeef32b9c950ywan # If we saw an #else, we will need to restore the nesting 1881233d2500723e5594f3e7c70896ffeeef32b9c950ywan # stack to its former state before the #else, otherwise we 1882233d2500723e5594f3e7c70896ffeeef32b9c950ywan # will just continue from where we left off. 1883233d2500723e5594f3e7c70896ffeeef32b9c950ywan if self.pp_stack[-1].seen_else: 1884233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Here we can just use a shallow copy since we are the last 1885233d2500723e5594f3e7c70896ffeeef32b9c950ywan # reference to it. 1886233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.stack = self.pp_stack[-1].stack_before_else 1887233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Drop the corresponding #if 1888233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.pp_stack.pop() 1889233d2500723e5594f3e7c70896ffeeef32b9c950ywan else: 1890233d2500723e5594f3e7c70896ffeeef32b9c950ywan # TODO(unknown): unexpected #endif, issue warning? 1891233d2500723e5594f3e7c70896ffeeef32b9c950ywan pass 1892233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1893233d2500723e5594f3e7c70896ffeeef32b9c950ywan def Update(self, filename, clean_lines, linenum, error): 1894233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Update nesting state with current line. 1895233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1896233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 1897233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename: The name of the current file. 1898233d2500723e5594f3e7c70896ffeeef32b9c950ywan clean_lines: A CleansedLines instance containing the file. 1899233d2500723e5594f3e7c70896ffeeef32b9c950ywan linenum: The number of the line to check. 1900233d2500723e5594f3e7c70896ffeeef32b9c950ywan error: The function to call with any errors found. 1901233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 1902233d2500723e5594f3e7c70896ffeeef32b9c950ywan line = clean_lines.elided[linenum] 1903233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1904233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Update pp_stack first 1905233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.UpdatePreprocessor(line) 1906233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1907233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Count parentheses. This is to avoid adding struct arguments to 1908233d2500723e5594f3e7c70896ffeeef32b9c950ywan # the nesting stack. 1909233d2500723e5594f3e7c70896ffeeef32b9c950ywan if self.stack: 1910233d2500723e5594f3e7c70896ffeeef32b9c950ywan inner_block = self.stack[-1] 1911233d2500723e5594f3e7c70896ffeeef32b9c950ywan depth_change = line.count('(') - line.count(')') 1912233d2500723e5594f3e7c70896ffeeef32b9c950ywan inner_block.open_parentheses += depth_change 1913233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1914233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Also check if we are starting or ending an inline assembly block. 1915233d2500723e5594f3e7c70896ffeeef32b9c950ywan if inner_block.inline_asm in (_NO_ASM, _END_ASM): 1916233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (depth_change != 0 and 1917233d2500723e5594f3e7c70896ffeeef32b9c950ywan inner_block.open_parentheses == 1 and 1918233d2500723e5594f3e7c70896ffeeef32b9c950ywan _MATCH_ASM.match(line)): 1919233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Enter assembly block 1920233d2500723e5594f3e7c70896ffeeef32b9c950ywan inner_block.inline_asm = _INSIDE_ASM 1921233d2500723e5594f3e7c70896ffeeef32b9c950ywan else: 1922233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Not entering assembly block. If previous line was _END_ASM, 1923233d2500723e5594f3e7c70896ffeeef32b9c950ywan # we will now shift to _NO_ASM state. 1924233d2500723e5594f3e7c70896ffeeef32b9c950ywan inner_block.inline_asm = _NO_ASM 1925233d2500723e5594f3e7c70896ffeeef32b9c950ywan elif (inner_block.inline_asm == _INSIDE_ASM and 1926233d2500723e5594f3e7c70896ffeeef32b9c950ywan inner_block.open_parentheses == 0): 1927233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Exit assembly block 1928233d2500723e5594f3e7c70896ffeeef32b9c950ywan inner_block.inline_asm = _END_ASM 1929233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1930233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Consume namespace declaration at the beginning of the line. Do 1931233d2500723e5594f3e7c70896ffeeef32b9c950ywan # this in a loop so that we catch same line declarations like this: 1932233d2500723e5594f3e7c70896ffeeef32b9c950ywan # namespace proto2 { namespace bridge { class MessageSet; } } 1933233d2500723e5594f3e7c70896ffeeef32b9c950ywan while True: 1934233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Match start of namespace. The "\b\s*" below catches namespace 1935233d2500723e5594f3e7c70896ffeeef32b9c950ywan # declarations even if it weren't followed by a whitespace, this 1936233d2500723e5594f3e7c70896ffeeef32b9c950ywan # is so that we don't confuse our namespace checker. The 1937233d2500723e5594f3e7c70896ffeeef32b9c950ywan # missing spaces will be flagged by CheckSpacing. 1938233d2500723e5594f3e7c70896ffeeef32b9c950ywan namespace_decl_match = Match(r'^\s*namespace\b\s*([:\w]+)?(.*)$', line) 1939233d2500723e5594f3e7c70896ffeeef32b9c950ywan if not namespace_decl_match: 1940233d2500723e5594f3e7c70896ffeeef32b9c950ywan break 1941233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1942233d2500723e5594f3e7c70896ffeeef32b9c950ywan new_namespace = _NamespaceInfo(namespace_decl_match.group(1), linenum) 1943233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.stack.append(new_namespace) 1944233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1945233d2500723e5594f3e7c70896ffeeef32b9c950ywan line = namespace_decl_match.group(2) 1946233d2500723e5594f3e7c70896ffeeef32b9c950ywan if line.find('{') != -1: 1947233d2500723e5594f3e7c70896ffeeef32b9c950ywan new_namespace.seen_open_brace = True 1948233d2500723e5594f3e7c70896ffeeef32b9c950ywan line = line[line.find('{') + 1:] 1949233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1950233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Look for a class declaration in whatever is left of the line 1951233d2500723e5594f3e7c70896ffeeef32b9c950ywan # after parsing namespaces. The regexp accounts for decorated classes 1952233d2500723e5594f3e7c70896ffeeef32b9c950ywan # such as in: 1953233d2500723e5594f3e7c70896ffeeef32b9c950ywan # class LOCKABLE API Object { 1954233d2500723e5594f3e7c70896ffeeef32b9c950ywan # }; 1955233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 1956233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Templates with class arguments may confuse the parser, for example: 1957233d2500723e5594f3e7c70896ffeeef32b9c950ywan # template <class T 1958233d2500723e5594f3e7c70896ffeeef32b9c950ywan # class Comparator = less<T>, 1959233d2500723e5594f3e7c70896ffeeef32b9c950ywan # class Vector = vector<T> > 1960233d2500723e5594f3e7c70896ffeeef32b9c950ywan # class HeapQueue { 1961233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 1962233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Because this parser has no nesting state about templates, by the 1963233d2500723e5594f3e7c70896ffeeef32b9c950ywan # time it saw "class Comparator", it may think that it's a new class. 1964233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Nested templates have a similar problem: 1965233d2500723e5594f3e7c70896ffeeef32b9c950ywan # template < 1966233d2500723e5594f3e7c70896ffeeef32b9c950ywan # typename ExportedType, 1967233d2500723e5594f3e7c70896ffeeef32b9c950ywan # typename TupleType, 1968233d2500723e5594f3e7c70896ffeeef32b9c950ywan # template <typename, typename> class ImplTemplate> 1969233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 1970233d2500723e5594f3e7c70896ffeeef32b9c950ywan # To avoid these cases, we ignore classes that are followed by '=' or '>' 1971233d2500723e5594f3e7c70896ffeeef32b9c950ywan class_decl_match = Match( 1972233d2500723e5594f3e7c70896ffeeef32b9c950ywan r'\s*(template\s*<[\w\s<>,:]*>\s*)?' 1973233d2500723e5594f3e7c70896ffeeef32b9c950ywan r'(class|struct)\s+([A-Z_]+\s+)*(\w+(?:::\w+)*)' 1974233d2500723e5594f3e7c70896ffeeef32b9c950ywan r'(([^=>]|<[^<>]*>|<[^<>]*<[^<>]*>\s*>)*)$', line) 1975233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (class_decl_match and 1976233d2500723e5594f3e7c70896ffeeef32b9c950ywan (not self.stack or self.stack[-1].open_parentheses == 0)): 1977233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.stack.append(_ClassInfo( 1978233d2500723e5594f3e7c70896ffeeef32b9c950ywan class_decl_match.group(4), class_decl_match.group(2), 1979233d2500723e5594f3e7c70896ffeeef32b9c950ywan clean_lines, linenum)) 1980233d2500723e5594f3e7c70896ffeeef32b9c950ywan line = class_decl_match.group(5) 1981233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1982233d2500723e5594f3e7c70896ffeeef32b9c950ywan # If we have not yet seen the opening brace for the innermost block, 1983233d2500723e5594f3e7c70896ffeeef32b9c950ywan # run checks here. 1984233d2500723e5594f3e7c70896ffeeef32b9c950ywan if not self.SeenOpenBrace(): 1985233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.stack[-1].CheckBegin(filename, clean_lines, linenum, error) 1986233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1987233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Update access control if we are inside a class/struct 1988233d2500723e5594f3e7c70896ffeeef32b9c950ywan if self.stack and isinstance(self.stack[-1], _ClassInfo): 1989233d2500723e5594f3e7c70896ffeeef32b9c950ywan classinfo = self.stack[-1] 1990233d2500723e5594f3e7c70896ffeeef32b9c950ywan access_match = Match( 1991233d2500723e5594f3e7c70896ffeeef32b9c950ywan r'^(.*)\b(public|private|protected|signals)(\s+(?:slots\s*)?)?' 1992233d2500723e5594f3e7c70896ffeeef32b9c950ywan r':(?:[^:]|$)', 1993233d2500723e5594f3e7c70896ffeeef32b9c950ywan line) 1994233d2500723e5594f3e7c70896ffeeef32b9c950ywan if access_match: 1995233d2500723e5594f3e7c70896ffeeef32b9c950ywan classinfo.access = access_match.group(2) 1996233d2500723e5594f3e7c70896ffeeef32b9c950ywan 1997233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Check that access keywords are indented +1 space. Skip this 1998233d2500723e5594f3e7c70896ffeeef32b9c950ywan # check if the keywords are not preceded by whitespaces. 1999233d2500723e5594f3e7c70896ffeeef32b9c950ywan indent = access_match.group(1) 2000233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (len(indent) != classinfo.class_indent + 1 and 2001233d2500723e5594f3e7c70896ffeeef32b9c950ywan Match(r'^\s*$', indent)): 2002233d2500723e5594f3e7c70896ffeeef32b9c950ywan if classinfo.is_struct: 2003233d2500723e5594f3e7c70896ffeeef32b9c950ywan parent = 'struct ' + classinfo.name 2004233d2500723e5594f3e7c70896ffeeef32b9c950ywan else: 2005233d2500723e5594f3e7c70896ffeeef32b9c950ywan parent = 'class ' + classinfo.name 2006233d2500723e5594f3e7c70896ffeeef32b9c950ywan slots = '' 2007233d2500723e5594f3e7c70896ffeeef32b9c950ywan if access_match.group(3): 2008233d2500723e5594f3e7c70896ffeeef32b9c950ywan slots = access_match.group(3) 2009233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'whitespace/indent', 3, 2010233d2500723e5594f3e7c70896ffeeef32b9c950ywan '%s%s: should be indented +1 space inside %s' % ( 2011233d2500723e5594f3e7c70896ffeeef32b9c950ywan access_match.group(2), slots, parent)) 2012233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2013233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Consume braces or semicolons from what's left of the line 2014233d2500723e5594f3e7c70896ffeeef32b9c950ywan while True: 2015233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Match first brace, semicolon, or closed parenthesis. 2016233d2500723e5594f3e7c70896ffeeef32b9c950ywan matched = Match(r'^[^{;)}]*([{;)}])(.*)$', line) 2017233d2500723e5594f3e7c70896ffeeef32b9c950ywan if not matched: 2018233d2500723e5594f3e7c70896ffeeef32b9c950ywan break 2019233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2020233d2500723e5594f3e7c70896ffeeef32b9c950ywan token = matched.group(1) 2021233d2500723e5594f3e7c70896ffeeef32b9c950ywan if token == '{': 2022233d2500723e5594f3e7c70896ffeeef32b9c950ywan # If namespace or class hasn't seen a opening brace yet, mark 2023233d2500723e5594f3e7c70896ffeeef32b9c950ywan # namespace/class head as complete. Push a new block onto the 2024233d2500723e5594f3e7c70896ffeeef32b9c950ywan # stack otherwise. 2025233d2500723e5594f3e7c70896ffeeef32b9c950ywan if not self.SeenOpenBrace(): 2026233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.stack[-1].seen_open_brace = True 2027233d2500723e5594f3e7c70896ffeeef32b9c950ywan else: 2028233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.stack.append(_BlockInfo(True)) 2029233d2500723e5594f3e7c70896ffeeef32b9c950ywan if _MATCH_ASM.match(line): 2030233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.stack[-1].inline_asm = _BLOCK_ASM 2031233d2500723e5594f3e7c70896ffeeef32b9c950ywan elif token == ';' or token == ')': 2032233d2500723e5594f3e7c70896ffeeef32b9c950ywan # If we haven't seen an opening brace yet, but we already saw 2033233d2500723e5594f3e7c70896ffeeef32b9c950ywan # a semicolon, this is probably a forward declaration. Pop 2034233d2500723e5594f3e7c70896ffeeef32b9c950ywan # the stack for these. 2035233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 2036233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Similarly, if we haven't seen an opening brace yet, but we 2037233d2500723e5594f3e7c70896ffeeef32b9c950ywan # already saw a closing parenthesis, then these are probably 2038233d2500723e5594f3e7c70896ffeeef32b9c950ywan # function arguments with extra "class" or "struct" keywords. 2039233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Also pop these stack for these. 2040233d2500723e5594f3e7c70896ffeeef32b9c950ywan if not self.SeenOpenBrace(): 2041233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.stack.pop() 2042233d2500723e5594f3e7c70896ffeeef32b9c950ywan else: # token == '}' 2043233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Perform end of block checks and pop the stack. 2044233d2500723e5594f3e7c70896ffeeef32b9c950ywan if self.stack: 2045233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.stack[-1].CheckEnd(filename, clean_lines, linenum, error) 2046233d2500723e5594f3e7c70896ffeeef32b9c950ywan self.stack.pop() 2047233d2500723e5594f3e7c70896ffeeef32b9c950ywan line = matched.group(2) 2048233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2049233d2500723e5594f3e7c70896ffeeef32b9c950ywan def InnermostClass(self): 2050233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Get class info on the top of the stack. 2051233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2052233d2500723e5594f3e7c70896ffeeef32b9c950ywan Returns: 2053233d2500723e5594f3e7c70896ffeeef32b9c950ywan A _ClassInfo object if we are inside a class, or None otherwise. 2054233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 2055233d2500723e5594f3e7c70896ffeeef32b9c950ywan for i in range(len(self.stack), 0, -1): 2056233d2500723e5594f3e7c70896ffeeef32b9c950ywan classinfo = self.stack[i - 1] 2057233d2500723e5594f3e7c70896ffeeef32b9c950ywan if isinstance(classinfo, _ClassInfo): 2058233d2500723e5594f3e7c70896ffeeef32b9c950ywan return classinfo 2059233d2500723e5594f3e7c70896ffeeef32b9c950ywan return None 2060233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2061233d2500723e5594f3e7c70896ffeeef32b9c950ywan def CheckCompletedBlocks(self, filename, error): 2062233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Checks that all classes and namespaces have been completely parsed. 2063233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2064233d2500723e5594f3e7c70896ffeeef32b9c950ywan Call this when all lines in a file have been processed. 2065233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 2066233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename: The name of the current file. 2067233d2500723e5594f3e7c70896ffeeef32b9c950ywan error: The function to call with any errors found. 2068233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 2069233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Note: This test can result in false positives if #ifdef constructs 2070233d2500723e5594f3e7c70896ffeeef32b9c950ywan # get in the way of brace matching. See the testBuildClass test in 2071233d2500723e5594f3e7c70896ffeeef32b9c950ywan # cpplint_unittest.py for an example of this. 2072233d2500723e5594f3e7c70896ffeeef32b9c950ywan for obj in self.stack: 2073233d2500723e5594f3e7c70896ffeeef32b9c950ywan if isinstance(obj, _ClassInfo): 2074233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, obj.starting_linenum, 'build/class', 5, 2075233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Failed to find complete declaration of class %s' % 2076233d2500723e5594f3e7c70896ffeeef32b9c950ywan obj.name) 2077233d2500723e5594f3e7c70896ffeeef32b9c950ywan elif isinstance(obj, _NamespaceInfo): 2078233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, obj.starting_linenum, 'build/namespaces', 5, 2079233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Failed to find complete declaration of namespace %s' % 2080233d2500723e5594f3e7c70896ffeeef32b9c950ywan obj.name) 2081233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2082233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2083233d2500723e5594f3e7c70896ffeeef32b9c950ywandef CheckForNonStandardConstructs(filename, clean_lines, linenum, 2084233d2500723e5594f3e7c70896ffeeef32b9c950ywan nesting_state, error): 2085233d2500723e5594f3e7c70896ffeeef32b9c950ywan r"""Logs an error if we see certain non-ANSI constructs ignored by gcc-2. 2086233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2087233d2500723e5594f3e7c70896ffeeef32b9c950ywan Complain about several constructs which gcc-2 accepts, but which are 2088233d2500723e5594f3e7c70896ffeeef32b9c950ywan not standard C++. Warning about these in lint is one way to ease the 2089233d2500723e5594f3e7c70896ffeeef32b9c950ywan transition to new compilers. 2090233d2500723e5594f3e7c70896ffeeef32b9c950ywan - put storage class first (e.g. "static const" instead of "const static"). 2091233d2500723e5594f3e7c70896ffeeef32b9c950ywan - "%lld" instead of %qd" in printf-type functions. 2092233d2500723e5594f3e7c70896ffeeef32b9c950ywan - "%1$d" is non-standard in printf-type functions. 2093233d2500723e5594f3e7c70896ffeeef32b9c950ywan - "\%" is an undefined character escape sequence. 2094233d2500723e5594f3e7c70896ffeeef32b9c950ywan - text after #endif is not allowed. 2095233d2500723e5594f3e7c70896ffeeef32b9c950ywan - invalid inner-style forward declaration. 2096233d2500723e5594f3e7c70896ffeeef32b9c950ywan - >? and <? operators, and their >?= and <?= cousins. 2097233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2098233d2500723e5594f3e7c70896ffeeef32b9c950ywan Additionally, check for constructor/destructor style violations and reference 2099233d2500723e5594f3e7c70896ffeeef32b9c950ywan members, as it is very convenient to do so while checking for 2100233d2500723e5594f3e7c70896ffeeef32b9c950ywan gcc-2 compliance. 2101233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2102233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 2103233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename: The name of the current file. 2104233d2500723e5594f3e7c70896ffeeef32b9c950ywan clean_lines: A CleansedLines instance containing the file. 2105233d2500723e5594f3e7c70896ffeeef32b9c950ywan linenum: The number of the line to check. 2106233d2500723e5594f3e7c70896ffeeef32b9c950ywan nesting_state: A _NestingState instance which maintains information about 2107233d2500723e5594f3e7c70896ffeeef32b9c950ywan the current stack of nested blocks being parsed. 2108233d2500723e5594f3e7c70896ffeeef32b9c950ywan error: A callable to which errors are reported, which takes 4 arguments: 2109233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename, line number, error level, and message 2110233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 2111233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2112233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Remove comments from the line, but leave in strings for now. 2113233d2500723e5594f3e7c70896ffeeef32b9c950ywan line = clean_lines.lines[linenum] 2114233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2115233d2500723e5594f3e7c70896ffeeef32b9c950ywan if Search(r'printf\s*\(.*".*%[-+ ]?\d*q', line): 2116233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'runtime/printf_format', 3, 2117233d2500723e5594f3e7c70896ffeeef32b9c950ywan '%q in format strings is deprecated. Use %ll instead.') 2118233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2119233d2500723e5594f3e7c70896ffeeef32b9c950ywan if Search(r'printf\s*\(.*".*%\d+\$', line): 2120233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'runtime/printf_format', 2, 2121233d2500723e5594f3e7c70896ffeeef32b9c950ywan '%N$ formats are unconventional. Try rewriting to avoid them.') 2122233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2123233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Remove escaped backslashes before looking for undefined escapes. 2124233d2500723e5594f3e7c70896ffeeef32b9c950ywan line = line.replace('\\\\', '') 2125233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2126233d2500723e5594f3e7c70896ffeeef32b9c950ywan if Search(r'("|\').*\\(%|\[|\(|{)', line): 2127233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'build/printf_format', 3, 2128233d2500723e5594f3e7c70896ffeeef32b9c950ywan '%, [, (, and { are undefined character escapes. Unescape them.') 2129233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2130233d2500723e5594f3e7c70896ffeeef32b9c950ywan # For the rest, work with both comments and strings removed. 2131233d2500723e5594f3e7c70896ffeeef32b9c950ywan line = clean_lines.elided[linenum] 2132233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2133233d2500723e5594f3e7c70896ffeeef32b9c950ywan if Search(r'\b(const|volatile|void|char|short|int|long' 2134233d2500723e5594f3e7c70896ffeeef32b9c950ywan r'|float|double|signed|unsigned' 2135233d2500723e5594f3e7c70896ffeeef32b9c950ywan r'|schar|u?int8|u?int16|u?int32|u?int64)' 2136233d2500723e5594f3e7c70896ffeeef32b9c950ywan r'\s+(register|static|extern|typedef)\b', 2137233d2500723e5594f3e7c70896ffeeef32b9c950ywan line): 2138233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'build/storage_class', 5, 2139233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Storage class (static, extern, typedef, etc) should be first.') 2140233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2141233d2500723e5594f3e7c70896ffeeef32b9c950ywan if Match(r'\s*#\s*endif\s*[^/\s]+', line): 2142233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'build/endif_comment', 5, 2143233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Uncommented text after #endif is non-standard. Use a comment.') 2144233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2145233d2500723e5594f3e7c70896ffeeef32b9c950ywan if Match(r'\s*class\s+(\w+\s*::\s*)+\w+\s*;', line): 2146233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'build/forward_decl', 5, 2147233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Inner-style forward declarations are invalid. Remove this line.') 2148233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2149233d2500723e5594f3e7c70896ffeeef32b9c950ywan if Search(r'(\w+|[+-]?\d+(\.\d*)?)\s*(<|>)\?=?\s*(\w+|[+-]?\d+)(\.\d*)?', 2150233d2500723e5594f3e7c70896ffeeef32b9c950ywan line): 2151233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'build/deprecated', 3, 2152233d2500723e5594f3e7c70896ffeeef32b9c950ywan '>? and <? (max and min) operators are non-standard and deprecated.') 2153233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2154233d2500723e5594f3e7c70896ffeeef32b9c950ywan if Search(r'^\s*const\s*string\s*&\s*\w+\s*;', line): 2155233d2500723e5594f3e7c70896ffeeef32b9c950ywan # TODO(unknown): Could it be expanded safely to arbitrary references, 2156233d2500723e5594f3e7c70896ffeeef32b9c950ywan # without triggering too many false positives? The first 2157233d2500723e5594f3e7c70896ffeeef32b9c950ywan # attempt triggered 5 warnings for mostly benign code in the regtest, hence 2158233d2500723e5594f3e7c70896ffeeef32b9c950ywan # the restriction. 2159233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Here's the original regexp, for the reference: 2160233d2500723e5594f3e7c70896ffeeef32b9c950ywan # type_name = r'\w+((\s*::\s*\w+)|(\s*<\s*\w+?\s*>))?' 2161233d2500723e5594f3e7c70896ffeeef32b9c950ywan # r'\s*const\s*' + type_name + '\s*&\s*\w+\s*;' 2162233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'runtime/member_string_references', 2, 2163233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'const string& members are dangerous. It is much better to use ' 2164233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'alternatives, such as pointers or simple constants.') 2165233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2166233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Everything else in this function operates on class declarations. 2167233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Return early if the top of the nesting stack is not a class, or if 2168233d2500723e5594f3e7c70896ffeeef32b9c950ywan # the class head is not completed yet. 2169233d2500723e5594f3e7c70896ffeeef32b9c950ywan classinfo = nesting_state.InnermostClass() 2170233d2500723e5594f3e7c70896ffeeef32b9c950ywan if not classinfo or not classinfo.seen_open_brace: 2171233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 2172233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2173233d2500723e5594f3e7c70896ffeeef32b9c950ywan # The class may have been declared with namespace or classname qualifiers. 2174233d2500723e5594f3e7c70896ffeeef32b9c950ywan # The constructor and destructor will not have those qualifiers. 2175233d2500723e5594f3e7c70896ffeeef32b9c950ywan base_classname = classinfo.name.split('::')[-1] 2176233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2177233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Look for single-argument constructors that aren't marked explicit. 2178233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Technically a valid construct, but against style. 2179233d2500723e5594f3e7c70896ffeeef32b9c950ywan args = Match(r'\s+(?:inline\s+)?%s\s*\(([^,()]+)\)' 2180233d2500723e5594f3e7c70896ffeeef32b9c950ywan % re.escape(base_classname), 2181233d2500723e5594f3e7c70896ffeeef32b9c950ywan line) 2182233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (args and 2183233d2500723e5594f3e7c70896ffeeef32b9c950ywan args.group(1) != 'void' and 2184233d2500723e5594f3e7c70896ffeeef32b9c950ywan not Match(r'(const\s+)?%s(\s+const)?\s*(?:<\w+>\s*)?&' 2185233d2500723e5594f3e7c70896ffeeef32b9c950ywan % re.escape(base_classname), args.group(1).strip())): 2186233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'runtime/explicit', 5, 2187233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Single-argument constructors should be marked explicit.') 2188233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2189233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2190233d2500723e5594f3e7c70896ffeeef32b9c950ywandef CheckSpacingForFunctionCall(filename, line, linenum, error): 2191233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Checks for the correctness of various spacing around function calls. 2192233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2193233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 2194233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename: The name of the current file. 2195233d2500723e5594f3e7c70896ffeeef32b9c950ywan line: The text of the line to check. 2196233d2500723e5594f3e7c70896ffeeef32b9c950ywan linenum: The number of the line to check. 2197233d2500723e5594f3e7c70896ffeeef32b9c950ywan error: The function to call with any errors found. 2198233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 2199233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2200233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Since function calls often occur inside if/for/while/switch 2201233d2500723e5594f3e7c70896ffeeef32b9c950ywan # expressions - which have their own, more liberal conventions - we 2202233d2500723e5594f3e7c70896ffeeef32b9c950ywan # first see if we should be looking inside such an expression for a 2203233d2500723e5594f3e7c70896ffeeef32b9c950ywan # function call, to which we can apply more strict standards. 2204233d2500723e5594f3e7c70896ffeeef32b9c950ywan fncall = line # if there's no control flow construct, look at whole line 2205233d2500723e5594f3e7c70896ffeeef32b9c950ywan for pattern in (r'\bif\s*\((.*)\)\s*{', 2206233d2500723e5594f3e7c70896ffeeef32b9c950ywan r'\bfor\s*\((.*)\)\s*{', 2207233d2500723e5594f3e7c70896ffeeef32b9c950ywan r'\bwhile\s*\((.*)\)\s*[{;]', 2208233d2500723e5594f3e7c70896ffeeef32b9c950ywan r'\bswitch\s*\((.*)\)\s*{'): 2209233d2500723e5594f3e7c70896ffeeef32b9c950ywan match = Search(pattern, line) 2210233d2500723e5594f3e7c70896ffeeef32b9c950ywan if match: 2211233d2500723e5594f3e7c70896ffeeef32b9c950ywan fncall = match.group(1) # look inside the parens for function calls 2212233d2500723e5594f3e7c70896ffeeef32b9c950ywan break 2213233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2214233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Except in if/for/while/switch, there should never be space 2215233d2500723e5594f3e7c70896ffeeef32b9c950ywan # immediately inside parens (eg "f( 3, 4 )"). We make an exception 2216233d2500723e5594f3e7c70896ffeeef32b9c950ywan # for nested parens ( (a+b) + c ). Likewise, there should never be 2217233d2500723e5594f3e7c70896ffeeef32b9c950ywan # a space before a ( when it's a function argument. I assume it's a 2218233d2500723e5594f3e7c70896ffeeef32b9c950ywan # function argument when the char before the whitespace is legal in 2219233d2500723e5594f3e7c70896ffeeef32b9c950ywan # a function name (alnum + _) and we're not starting a macro. Also ignore 2220233d2500723e5594f3e7c70896ffeeef32b9c950ywan # pointers and references to arrays and functions coz they're too tricky: 2221233d2500723e5594f3e7c70896ffeeef32b9c950ywan # we use a very simple way to recognize these: 2222233d2500723e5594f3e7c70896ffeeef32b9c950ywan # " (something)(maybe-something)" or 2223233d2500723e5594f3e7c70896ffeeef32b9c950ywan # " (something)(maybe-something," or 2224233d2500723e5594f3e7c70896ffeeef32b9c950ywan # " (something)[something]" 2225233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Note that we assume the contents of [] to be short enough that 2226233d2500723e5594f3e7c70896ffeeef32b9c950ywan # they'll never need to wrap. 2227233d2500723e5594f3e7c70896ffeeef32b9c950ywan if ( # Ignore control structures. 2228233d2500723e5594f3e7c70896ffeeef32b9c950ywan not Search(r'\b(if|for|while|switch|return|new|delete|catch|sizeof)\b', 2229233d2500723e5594f3e7c70896ffeeef32b9c950ywan fncall) and 2230233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Ignore pointers/references to functions. 2231233d2500723e5594f3e7c70896ffeeef32b9c950ywan not Search(r' \([^)]+\)\([^)]*(\)|,$)', fncall) and 2232233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Ignore pointers/references to arrays. 2233233d2500723e5594f3e7c70896ffeeef32b9c950ywan not Search(r' \([^)]+\)\[[^\]]+\]', fncall)): 2234233d2500723e5594f3e7c70896ffeeef32b9c950ywan if Search(r'\w\s*\(\s(?!\s*\\$)', fncall): # a ( used for a fn call 2235233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'whitespace/parens', 4, 2236233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Extra space after ( in function call') 2237233d2500723e5594f3e7c70896ffeeef32b9c950ywan elif Search(r'\(\s+(?!(\s*\\)|\()', fncall): 2238233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'whitespace/parens', 2, 2239233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Extra space after (') 2240233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (Search(r'\w\s+\(', fncall) and 2241233d2500723e5594f3e7c70896ffeeef32b9c950ywan not Search(r'#\s*define|typedef', fncall) and 2242233d2500723e5594f3e7c70896ffeeef32b9c950ywan not Search(r'\w\s+\((\w+::)*\*\w+\)\(', fncall)): 2243233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'whitespace/parens', 4, 2244233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Extra space before ( in function call') 2245233d2500723e5594f3e7c70896ffeeef32b9c950ywan # If the ) is followed only by a newline or a { + newline, assume it's 2246233d2500723e5594f3e7c70896ffeeef32b9c950ywan # part of a control statement (if/while/etc), and don't complain 2247233d2500723e5594f3e7c70896ffeeef32b9c950ywan if Search(r'[^)]\s+\)\s*[^{\s]', fncall): 2248233d2500723e5594f3e7c70896ffeeef32b9c950ywan # If the closing parenthesis is preceded by only whitespaces, 2249233d2500723e5594f3e7c70896ffeeef32b9c950ywan # try to give a more descriptive error message. 2250233d2500723e5594f3e7c70896ffeeef32b9c950ywan if Search(r'^\s+\)', fncall): 2251233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'whitespace/parens', 2, 2252233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Closing ) should be moved to the previous line') 2253233d2500723e5594f3e7c70896ffeeef32b9c950ywan else: 2254233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'whitespace/parens', 2, 2255233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Extra space before )') 2256233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2257233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2258233d2500723e5594f3e7c70896ffeeef32b9c950ywandef IsBlankLine(line): 2259233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Returns true if the given line is blank. 2260233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2261233d2500723e5594f3e7c70896ffeeef32b9c950ywan We consider a line to be blank if the line is empty or consists of 2262233d2500723e5594f3e7c70896ffeeef32b9c950ywan only white spaces. 2263233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2264233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 2265233d2500723e5594f3e7c70896ffeeef32b9c950ywan line: A line of a string. 2266233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2267233d2500723e5594f3e7c70896ffeeef32b9c950ywan Returns: 2268233d2500723e5594f3e7c70896ffeeef32b9c950ywan True, if the given line is blank. 2269233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 2270233d2500723e5594f3e7c70896ffeeef32b9c950ywan return not line or line.isspace() 2271233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2272233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2273233d2500723e5594f3e7c70896ffeeef32b9c950ywandef CheckForFunctionLengths(filename, clean_lines, linenum, 2274233d2500723e5594f3e7c70896ffeeef32b9c950ywan function_state, error): 2275233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Reports for long function bodies. 2276233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2277233d2500723e5594f3e7c70896ffeeef32b9c950ywan For an overview why this is done, see: 2278233d2500723e5594f3e7c70896ffeeef32b9c950ywan http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Write_Short_Functions 2279233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2280233d2500723e5594f3e7c70896ffeeef32b9c950ywan Uses a simplistic algorithm assuming other style guidelines 2281233d2500723e5594f3e7c70896ffeeef32b9c950ywan (especially spacing) are followed. 2282233d2500723e5594f3e7c70896ffeeef32b9c950ywan Only checks unindented functions, so class members are unchecked. 2283233d2500723e5594f3e7c70896ffeeef32b9c950ywan Trivial bodies are unchecked, so constructors with huge initializer lists 2284233d2500723e5594f3e7c70896ffeeef32b9c950ywan may be missed. 2285233d2500723e5594f3e7c70896ffeeef32b9c950ywan Blank/comment lines are not counted so as to avoid encouraging the removal 2286233d2500723e5594f3e7c70896ffeeef32b9c950ywan of vertical space and comments just to get through a lint check. 2287233d2500723e5594f3e7c70896ffeeef32b9c950ywan NOLINT *on the last line of a function* disables this check. 2288233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2289233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 2290233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename: The name of the current file. 2291233d2500723e5594f3e7c70896ffeeef32b9c950ywan clean_lines: A CleansedLines instance containing the file. 2292233d2500723e5594f3e7c70896ffeeef32b9c950ywan linenum: The number of the line to check. 2293233d2500723e5594f3e7c70896ffeeef32b9c950ywan function_state: Current function name and lines in body so far. 2294233d2500723e5594f3e7c70896ffeeef32b9c950ywan error: The function to call with any errors found. 2295233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 2296233d2500723e5594f3e7c70896ffeeef32b9c950ywan lines = clean_lines.lines 2297233d2500723e5594f3e7c70896ffeeef32b9c950ywan line = lines[linenum] 2298233d2500723e5594f3e7c70896ffeeef32b9c950ywan raw = clean_lines.raw_lines 2299233d2500723e5594f3e7c70896ffeeef32b9c950ywan raw_line = raw[linenum] 2300233d2500723e5594f3e7c70896ffeeef32b9c950ywan joined_line = '' 2301233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2302233d2500723e5594f3e7c70896ffeeef32b9c950ywan starting_func = False 2303233d2500723e5594f3e7c70896ffeeef32b9c950ywan regexp = r'(\w(\w|::|\*|\&|\s)*)\(' # decls * & space::name( ... 2304233d2500723e5594f3e7c70896ffeeef32b9c950ywan match_result = Match(regexp, line) 2305233d2500723e5594f3e7c70896ffeeef32b9c950ywan if match_result: 2306233d2500723e5594f3e7c70896ffeeef32b9c950ywan # If the name is all caps and underscores, figure it's a macro and 2307233d2500723e5594f3e7c70896ffeeef32b9c950ywan # ignore it, unless it's TEST or TEST_F. 2308233d2500723e5594f3e7c70896ffeeef32b9c950ywan function_name = match_result.group(1).split()[-1] 2309233d2500723e5594f3e7c70896ffeeef32b9c950ywan if function_name == 'TEST' or function_name == 'TEST_F' or ( 2310233d2500723e5594f3e7c70896ffeeef32b9c950ywan not Match(r'[A-Z_]+$', function_name)): 2311233d2500723e5594f3e7c70896ffeeef32b9c950ywan starting_func = True 2312233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2313233d2500723e5594f3e7c70896ffeeef32b9c950ywan if starting_func: 2314233d2500723e5594f3e7c70896ffeeef32b9c950ywan body_found = False 2315233d2500723e5594f3e7c70896ffeeef32b9c950ywan for start_linenum in xrange(linenum, clean_lines.NumLines()): 2316233d2500723e5594f3e7c70896ffeeef32b9c950ywan start_line = lines[start_linenum] 2317233d2500723e5594f3e7c70896ffeeef32b9c950ywan joined_line += ' ' + start_line.lstrip() 2318233d2500723e5594f3e7c70896ffeeef32b9c950ywan if Search(r'(;|})', start_line): # Declarations and trivial functions 2319233d2500723e5594f3e7c70896ffeeef32b9c950ywan body_found = True 2320233d2500723e5594f3e7c70896ffeeef32b9c950ywan break # ... ignore 2321233d2500723e5594f3e7c70896ffeeef32b9c950ywan elif Search(r'{', start_line): 2322233d2500723e5594f3e7c70896ffeeef32b9c950ywan body_found = True 2323233d2500723e5594f3e7c70896ffeeef32b9c950ywan function = Search(r'((\w|:)*)\(', line).group(1) 2324233d2500723e5594f3e7c70896ffeeef32b9c950ywan if Match(r'TEST', function): # Handle TEST... macros 2325233d2500723e5594f3e7c70896ffeeef32b9c950ywan parameter_regexp = Search(r'(\(.*\))', joined_line) 2326233d2500723e5594f3e7c70896ffeeef32b9c950ywan if parameter_regexp: # Ignore bad syntax 2327233d2500723e5594f3e7c70896ffeeef32b9c950ywan function += parameter_regexp.group(1) 2328233d2500723e5594f3e7c70896ffeeef32b9c950ywan else: 2329233d2500723e5594f3e7c70896ffeeef32b9c950ywan function += '()' 2330233d2500723e5594f3e7c70896ffeeef32b9c950ywan function_state.Begin(function) 2331233d2500723e5594f3e7c70896ffeeef32b9c950ywan break 2332233d2500723e5594f3e7c70896ffeeef32b9c950ywan if not body_found: 2333233d2500723e5594f3e7c70896ffeeef32b9c950ywan # No body for the function (or evidence of a non-function) was found. 2334233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'readability/fn_size', 5, 2335233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Lint failed to find start of function body.') 2336233d2500723e5594f3e7c70896ffeeef32b9c950ywan elif Match(r'^\}\s*$', line): # function end 2337233d2500723e5594f3e7c70896ffeeef32b9c950ywan function_state.Check(error, filename, linenum) 2338233d2500723e5594f3e7c70896ffeeef32b9c950ywan function_state.End() 2339233d2500723e5594f3e7c70896ffeeef32b9c950ywan elif not Match(r'^\s*$', line): 2340233d2500723e5594f3e7c70896ffeeef32b9c950ywan function_state.Count() # Count non-blank/non-comment lines. 2341233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2342233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2343233d2500723e5594f3e7c70896ffeeef32b9c950ywan_RE_PATTERN_TODO = re.compile(r'^//(\s*)TODO(\(.+?\))?:?(\s|$)?') 2344233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2345233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2346233d2500723e5594f3e7c70896ffeeef32b9c950ywandef CheckComment(comment, filename, linenum, error): 2347233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Checks for common mistakes in TODO comments. 2348233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2349233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 2350233d2500723e5594f3e7c70896ffeeef32b9c950ywan comment: The text of the comment from the line in question. 2351233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename: The name of the current file. 2352233d2500723e5594f3e7c70896ffeeef32b9c950ywan linenum: The number of the line to check. 2353233d2500723e5594f3e7c70896ffeeef32b9c950ywan error: The function to call with any errors found. 2354233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 2355233d2500723e5594f3e7c70896ffeeef32b9c950ywan match = _RE_PATTERN_TODO.match(comment) 2356233d2500723e5594f3e7c70896ffeeef32b9c950ywan if match: 2357233d2500723e5594f3e7c70896ffeeef32b9c950ywan # One whitespace is correct; zero whitespace is handled elsewhere. 2358233d2500723e5594f3e7c70896ffeeef32b9c950ywan leading_whitespace = match.group(1) 2359233d2500723e5594f3e7c70896ffeeef32b9c950ywan if len(leading_whitespace) > 1: 2360233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'whitespace/todo', 2, 2361233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Too many spaces before TODO') 2362233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2363233d2500723e5594f3e7c70896ffeeef32b9c950ywan username = match.group(2) 2364233d2500723e5594f3e7c70896ffeeef32b9c950ywan if not username: 2365233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'readability/todo', 2, 2366233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Missing username in TODO; it should look like ' 2367233d2500723e5594f3e7c70896ffeeef32b9c950ywan '"// TODO(my_username): Stuff."') 2368233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2369233d2500723e5594f3e7c70896ffeeef32b9c950ywan middle_whitespace = match.group(3) 2370233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Comparisons made explicit for correctness -- pylint: disable=g-explicit-bool-comparison 2371233d2500723e5594f3e7c70896ffeeef32b9c950ywan if middle_whitespace != ' ' and middle_whitespace != '': 2372233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'whitespace/todo', 2, 2373233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'TODO(my_username) should be followed by a space') 2374233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2375233d2500723e5594f3e7c70896ffeeef32b9c950ywandef CheckAccess(filename, clean_lines, linenum, nesting_state, error): 2376233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Checks for improper use of DISALLOW* macros. 2377233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2378233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 2379233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename: The name of the current file. 2380233d2500723e5594f3e7c70896ffeeef32b9c950ywan clean_lines: A CleansedLines instance containing the file. 2381233d2500723e5594f3e7c70896ffeeef32b9c950ywan linenum: The number of the line to check. 2382233d2500723e5594f3e7c70896ffeeef32b9c950ywan nesting_state: A _NestingState instance which maintains information about 2383233d2500723e5594f3e7c70896ffeeef32b9c950ywan the current stack of nested blocks being parsed. 2384233d2500723e5594f3e7c70896ffeeef32b9c950ywan error: The function to call with any errors found. 2385233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 2386233d2500723e5594f3e7c70896ffeeef32b9c950ywan line = clean_lines.elided[linenum] # get rid of comments and strings 2387233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2388233d2500723e5594f3e7c70896ffeeef32b9c950ywan matched = Match((r'\s*(DISALLOW_COPY_AND_ASSIGN|' 2389233d2500723e5594f3e7c70896ffeeef32b9c950ywan r'DISALLOW_EVIL_CONSTRUCTORS|' 2390233d2500723e5594f3e7c70896ffeeef32b9c950ywan r'DISALLOW_IMPLICIT_CONSTRUCTORS)'), line) 2391233d2500723e5594f3e7c70896ffeeef32b9c950ywan if not matched: 2392233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 2393233d2500723e5594f3e7c70896ffeeef32b9c950ywan if nesting_state.stack and isinstance(nesting_state.stack[-1], _ClassInfo): 2394233d2500723e5594f3e7c70896ffeeef32b9c950ywan if nesting_state.stack[-1].access != 'private': 2395233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'readability/constructors', 3, 2396233d2500723e5594f3e7c70896ffeeef32b9c950ywan '%s must be in the private: section' % matched.group(1)) 2397233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2398233d2500723e5594f3e7c70896ffeeef32b9c950ywan else: 2399233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Found DISALLOW* macro outside a class declaration, or perhaps it 2400233d2500723e5594f3e7c70896ffeeef32b9c950ywan # was used inside a function when it should have been part of the 2401233d2500723e5594f3e7c70896ffeeef32b9c950ywan # class declaration. We could issue a warning here, but it 2402233d2500723e5594f3e7c70896ffeeef32b9c950ywan # probably resulted in a compiler error already. 2403233d2500723e5594f3e7c70896ffeeef32b9c950ywan pass 2404233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2405233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2406233d2500723e5594f3e7c70896ffeeef32b9c950ywandef FindNextMatchingAngleBracket(clean_lines, linenum, init_suffix): 2407233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Find the corresponding > to close a template. 2408233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2409233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 2410233d2500723e5594f3e7c70896ffeeef32b9c950ywan clean_lines: A CleansedLines instance containing the file. 2411233d2500723e5594f3e7c70896ffeeef32b9c950ywan linenum: Current line number. 2412233d2500723e5594f3e7c70896ffeeef32b9c950ywan init_suffix: Remainder of the current line after the initial <. 2413233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2414233d2500723e5594f3e7c70896ffeeef32b9c950ywan Returns: 2415233d2500723e5594f3e7c70896ffeeef32b9c950ywan True if a matching bracket exists. 2416233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 2417233d2500723e5594f3e7c70896ffeeef32b9c950ywan line = init_suffix 2418233d2500723e5594f3e7c70896ffeeef32b9c950ywan nesting_stack = ['<'] 2419233d2500723e5594f3e7c70896ffeeef32b9c950ywan while True: 2420233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Find the next operator that can tell us whether < is used as an 2421233d2500723e5594f3e7c70896ffeeef32b9c950ywan # opening bracket or as a less-than operator. We only want to 2422233d2500723e5594f3e7c70896ffeeef32b9c950ywan # warn on the latter case. 2423233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 2424233d2500723e5594f3e7c70896ffeeef32b9c950ywan # We could also check all other operators and terminate the search 2425233d2500723e5594f3e7c70896ffeeef32b9c950ywan # early, e.g. if we got something like this "a<b+c", the "<" is 2426233d2500723e5594f3e7c70896ffeeef32b9c950ywan # most likely a less-than operator, but then we will get false 2427233d2500723e5594f3e7c70896ffeeef32b9c950ywan # positives for default arguments and other template expressions. 2428233d2500723e5594f3e7c70896ffeeef32b9c950ywan match = Search(r'^[^<>(),;\[\]]*([<>(),;\[\]])(.*)$', line) 2429233d2500723e5594f3e7c70896ffeeef32b9c950ywan if match: 2430233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Found an operator, update nesting stack 2431233d2500723e5594f3e7c70896ffeeef32b9c950ywan operator = match.group(1) 2432233d2500723e5594f3e7c70896ffeeef32b9c950ywan line = match.group(2) 2433233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2434233d2500723e5594f3e7c70896ffeeef32b9c950ywan if nesting_stack[-1] == '<': 2435233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Expecting closing angle bracket 2436233d2500723e5594f3e7c70896ffeeef32b9c950ywan if operator in ('<', '(', '['): 2437233d2500723e5594f3e7c70896ffeeef32b9c950ywan nesting_stack.append(operator) 2438233d2500723e5594f3e7c70896ffeeef32b9c950ywan elif operator == '>': 2439233d2500723e5594f3e7c70896ffeeef32b9c950ywan nesting_stack.pop() 2440233d2500723e5594f3e7c70896ffeeef32b9c950ywan if not nesting_stack: 2441233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Found matching angle bracket 2442233d2500723e5594f3e7c70896ffeeef32b9c950ywan return True 2443233d2500723e5594f3e7c70896ffeeef32b9c950ywan elif operator == ',': 2444233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Got a comma after a bracket, this is most likely a template 2445233d2500723e5594f3e7c70896ffeeef32b9c950ywan # argument. We have not seen a closing angle bracket yet, but 2446233d2500723e5594f3e7c70896ffeeef32b9c950ywan # it's probably a few lines later if we look for it, so just 2447233d2500723e5594f3e7c70896ffeeef32b9c950ywan # return early here. 2448233d2500723e5594f3e7c70896ffeeef32b9c950ywan return True 2449233d2500723e5594f3e7c70896ffeeef32b9c950ywan else: 2450233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Got some other operator. 2451233d2500723e5594f3e7c70896ffeeef32b9c950ywan return False 2452233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2453233d2500723e5594f3e7c70896ffeeef32b9c950ywan else: 2454233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Expecting closing parenthesis or closing bracket 2455233d2500723e5594f3e7c70896ffeeef32b9c950ywan if operator in ('<', '(', '['): 2456233d2500723e5594f3e7c70896ffeeef32b9c950ywan nesting_stack.append(operator) 2457233d2500723e5594f3e7c70896ffeeef32b9c950ywan elif operator in (')', ']'): 2458233d2500723e5594f3e7c70896ffeeef32b9c950ywan # We don't bother checking for matching () or []. If we got 2459233d2500723e5594f3e7c70896ffeeef32b9c950ywan # something like (] or [), it would have been a syntax error. 2460233d2500723e5594f3e7c70896ffeeef32b9c950ywan nesting_stack.pop() 2461233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2462233d2500723e5594f3e7c70896ffeeef32b9c950ywan else: 2463233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Scan the next line 2464233d2500723e5594f3e7c70896ffeeef32b9c950ywan linenum += 1 2465233d2500723e5594f3e7c70896ffeeef32b9c950ywan if linenum >= len(clean_lines.elided): 2466233d2500723e5594f3e7c70896ffeeef32b9c950ywan break 2467233d2500723e5594f3e7c70896ffeeef32b9c950ywan line = clean_lines.elided[linenum] 2468233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2469233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Exhausted all remaining lines and still no matching angle bracket. 2470233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Most likely the input was incomplete, otherwise we should have 2471233d2500723e5594f3e7c70896ffeeef32b9c950ywan # seen a semicolon and returned early. 2472233d2500723e5594f3e7c70896ffeeef32b9c950ywan return True 2473233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2474233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2475233d2500723e5594f3e7c70896ffeeef32b9c950ywandef FindPreviousMatchingAngleBracket(clean_lines, linenum, init_prefix): 2476233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Find the corresponding < that started a template. 2477233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2478233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 2479233d2500723e5594f3e7c70896ffeeef32b9c950ywan clean_lines: A CleansedLines instance containing the file. 2480233d2500723e5594f3e7c70896ffeeef32b9c950ywan linenum: Current line number. 2481233d2500723e5594f3e7c70896ffeeef32b9c950ywan init_prefix: Part of the current line before the initial >. 2482233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2483233d2500723e5594f3e7c70896ffeeef32b9c950ywan Returns: 2484233d2500723e5594f3e7c70896ffeeef32b9c950ywan True if a matching bracket exists. 2485233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 2486233d2500723e5594f3e7c70896ffeeef32b9c950ywan line = init_prefix 2487233d2500723e5594f3e7c70896ffeeef32b9c950ywan nesting_stack = ['>'] 2488233d2500723e5594f3e7c70896ffeeef32b9c950ywan while True: 2489233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Find the previous operator 2490233d2500723e5594f3e7c70896ffeeef32b9c950ywan match = Search(r'^(.*)([<>(),;\[\]])[^<>(),;\[\]]*$', line) 2491233d2500723e5594f3e7c70896ffeeef32b9c950ywan if match: 2492233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Found an operator, update nesting stack 2493233d2500723e5594f3e7c70896ffeeef32b9c950ywan operator = match.group(2) 2494233d2500723e5594f3e7c70896ffeeef32b9c950ywan line = match.group(1) 2495233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2496233d2500723e5594f3e7c70896ffeeef32b9c950ywan if nesting_stack[-1] == '>': 2497233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Expecting opening angle bracket 2498233d2500723e5594f3e7c70896ffeeef32b9c950ywan if operator in ('>', ')', ']'): 2499233d2500723e5594f3e7c70896ffeeef32b9c950ywan nesting_stack.append(operator) 2500233d2500723e5594f3e7c70896ffeeef32b9c950ywan elif operator == '<': 2501233d2500723e5594f3e7c70896ffeeef32b9c950ywan nesting_stack.pop() 2502233d2500723e5594f3e7c70896ffeeef32b9c950ywan if not nesting_stack: 2503233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Found matching angle bracket 2504233d2500723e5594f3e7c70896ffeeef32b9c950ywan return True 2505233d2500723e5594f3e7c70896ffeeef32b9c950ywan elif operator == ',': 2506233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Got a comma before a bracket, this is most likely a 2507233d2500723e5594f3e7c70896ffeeef32b9c950ywan # template argument. The opening angle bracket is probably 2508233d2500723e5594f3e7c70896ffeeef32b9c950ywan # there if we look for it, so just return early here. 2509233d2500723e5594f3e7c70896ffeeef32b9c950ywan return True 2510233d2500723e5594f3e7c70896ffeeef32b9c950ywan else: 2511233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Got some other operator. 2512233d2500723e5594f3e7c70896ffeeef32b9c950ywan return False 2513233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2514233d2500723e5594f3e7c70896ffeeef32b9c950ywan else: 2515233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Expecting opening parenthesis or opening bracket 2516233d2500723e5594f3e7c70896ffeeef32b9c950ywan if operator in ('>', ')', ']'): 2517233d2500723e5594f3e7c70896ffeeef32b9c950ywan nesting_stack.append(operator) 2518233d2500723e5594f3e7c70896ffeeef32b9c950ywan elif operator in ('(', '['): 2519233d2500723e5594f3e7c70896ffeeef32b9c950ywan nesting_stack.pop() 2520233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2521233d2500723e5594f3e7c70896ffeeef32b9c950ywan else: 2522233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Scan the previous line 2523233d2500723e5594f3e7c70896ffeeef32b9c950ywan linenum -= 1 2524233d2500723e5594f3e7c70896ffeeef32b9c950ywan if linenum < 0: 2525233d2500723e5594f3e7c70896ffeeef32b9c950ywan break 2526233d2500723e5594f3e7c70896ffeeef32b9c950ywan line = clean_lines.elided[linenum] 2527233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2528233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Exhausted all earlier lines and still no matching angle bracket. 2529233d2500723e5594f3e7c70896ffeeef32b9c950ywan return False 2530233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2531233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2532233d2500723e5594f3e7c70896ffeeef32b9c950ywandef CheckSpacing(filename, clean_lines, linenum, nesting_state, error): 2533233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Checks for the correctness of various spacing issues in the code. 2534233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2535233d2500723e5594f3e7c70896ffeeef32b9c950ywan Things we check for: spaces around operators, spaces after 2536233d2500723e5594f3e7c70896ffeeef32b9c950ywan if/for/while/switch, no spaces around parens in function calls, two 2537233d2500723e5594f3e7c70896ffeeef32b9c950ywan spaces between code and comment, don't start a block with a blank 2538233d2500723e5594f3e7c70896ffeeef32b9c950ywan line, don't end a function with a blank line, don't add a blank line 2539233d2500723e5594f3e7c70896ffeeef32b9c950ywan after public/protected/private, don't have too many blank lines in a row. 2540233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2541233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 2542233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename: The name of the current file. 2543233d2500723e5594f3e7c70896ffeeef32b9c950ywan clean_lines: A CleansedLines instance containing the file. 2544233d2500723e5594f3e7c70896ffeeef32b9c950ywan linenum: The number of the line to check. 2545233d2500723e5594f3e7c70896ffeeef32b9c950ywan nesting_state: A _NestingState instance which maintains information about 2546233d2500723e5594f3e7c70896ffeeef32b9c950ywan the current stack of nested blocks being parsed. 2547233d2500723e5594f3e7c70896ffeeef32b9c950ywan error: The function to call with any errors found. 2548233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 2549233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2550233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Don't use "elided" lines here, otherwise we can't check commented lines. 2551233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Don't want to use "raw" either, because we don't want to check inside C++11 2552233d2500723e5594f3e7c70896ffeeef32b9c950ywan # raw strings, 2553233d2500723e5594f3e7c70896ffeeef32b9c950ywan raw = clean_lines.lines_without_raw_strings 2554233d2500723e5594f3e7c70896ffeeef32b9c950ywan line = raw[linenum] 2555233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2556233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Before nixing comments, check if the line is blank for no good 2557233d2500723e5594f3e7c70896ffeeef32b9c950ywan # reason. This includes the first line after a block is opened, and 2558233d2500723e5594f3e7c70896ffeeef32b9c950ywan # blank lines at the end of a function (ie, right before a line like '}' 2559233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 2560233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Skip all the blank line checks if we are immediately inside a 2561233d2500723e5594f3e7c70896ffeeef32b9c950ywan # namespace body. In other words, don't issue blank line warnings 2562233d2500723e5594f3e7c70896ffeeef32b9c950ywan # for this block: 2563233d2500723e5594f3e7c70896ffeeef32b9c950ywan # namespace { 2564233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 2565233d2500723e5594f3e7c70896ffeeef32b9c950ywan # } 2566233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 2567233d2500723e5594f3e7c70896ffeeef32b9c950ywan # A warning about missing end of namespace comments will be issued instead. 2568233d2500723e5594f3e7c70896ffeeef32b9c950ywan if IsBlankLine(line) and not nesting_state.InNamespaceBody(): 2569233d2500723e5594f3e7c70896ffeeef32b9c950ywan elided = clean_lines.elided 2570233d2500723e5594f3e7c70896ffeeef32b9c950ywan prev_line = elided[linenum - 1] 2571233d2500723e5594f3e7c70896ffeeef32b9c950ywan prevbrace = prev_line.rfind('{') 2572233d2500723e5594f3e7c70896ffeeef32b9c950ywan # TODO(unknown): Don't complain if line before blank line, and line after, 2573233d2500723e5594f3e7c70896ffeeef32b9c950ywan # both start with alnums and are indented the same amount. 2574233d2500723e5594f3e7c70896ffeeef32b9c950ywan # This ignores whitespace at the start of a namespace block 2575233d2500723e5594f3e7c70896ffeeef32b9c950ywan # because those are not usually indented. 2576233d2500723e5594f3e7c70896ffeeef32b9c950ywan if prevbrace != -1 and prev_line[prevbrace:].find('}') == -1: 2577233d2500723e5594f3e7c70896ffeeef32b9c950ywan # OK, we have a blank line at the start of a code block. Before we 2578233d2500723e5594f3e7c70896ffeeef32b9c950ywan # complain, we check if it is an exception to the rule: The previous 2579233d2500723e5594f3e7c70896ffeeef32b9c950ywan # non-empty line has the parameters of a function header that are indented 2580233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 4 spaces (because they did not fit in a 80 column line when placed on 2581233d2500723e5594f3e7c70896ffeeef32b9c950ywan # the same line as the function name). We also check for the case where 2582233d2500723e5594f3e7c70896ffeeef32b9c950ywan # the previous line is indented 6 spaces, which may happen when the 2583233d2500723e5594f3e7c70896ffeeef32b9c950ywan # initializers of a constructor do not fit into a 80 column line. 2584233d2500723e5594f3e7c70896ffeeef32b9c950ywan exception = False 2585233d2500723e5594f3e7c70896ffeeef32b9c950ywan if Match(r' {6}\w', prev_line): # Initializer list? 2586233d2500723e5594f3e7c70896ffeeef32b9c950ywan # We are looking for the opening column of initializer list, which 2587233d2500723e5594f3e7c70896ffeeef32b9c950ywan # should be indented 4 spaces to cause 6 space indentation afterwards. 2588233d2500723e5594f3e7c70896ffeeef32b9c950ywan search_position = linenum-2 2589233d2500723e5594f3e7c70896ffeeef32b9c950ywan while (search_position >= 0 2590233d2500723e5594f3e7c70896ffeeef32b9c950ywan and Match(r' {6}\w', elided[search_position])): 2591233d2500723e5594f3e7c70896ffeeef32b9c950ywan search_position -= 1 2592233d2500723e5594f3e7c70896ffeeef32b9c950ywan exception = (search_position >= 0 2593233d2500723e5594f3e7c70896ffeeef32b9c950ywan and elided[search_position][:5] == ' :') 2594233d2500723e5594f3e7c70896ffeeef32b9c950ywan else: 2595233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Search for the function arguments or an initializer list. We use a 2596233d2500723e5594f3e7c70896ffeeef32b9c950ywan # simple heuristic here: If the line is indented 4 spaces; and we have a 2597233d2500723e5594f3e7c70896ffeeef32b9c950ywan # closing paren, without the opening paren, followed by an opening brace 2598233d2500723e5594f3e7c70896ffeeef32b9c950ywan # or colon (for initializer lists) we assume that it is the last line of 2599233d2500723e5594f3e7c70896ffeeef32b9c950ywan # a function header. If we have a colon indented 4 spaces, it is an 2600233d2500723e5594f3e7c70896ffeeef32b9c950ywan # initializer list. 2601233d2500723e5594f3e7c70896ffeeef32b9c950ywan exception = (Match(r' {4}\w[^\(]*\)\s*(const\s*)?(\{\s*$|:)', 2602233d2500723e5594f3e7c70896ffeeef32b9c950ywan prev_line) 2603233d2500723e5594f3e7c70896ffeeef32b9c950ywan or Match(r' {4}:', prev_line)) 2604233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2605233d2500723e5594f3e7c70896ffeeef32b9c950ywan if not exception: 2606233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'whitespace/blank_line', 2, 2607233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Redundant blank line at the start of a code block ' 2608233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'should be deleted.') 2609233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Ignore blank lines at the end of a block in a long if-else 2610233d2500723e5594f3e7c70896ffeeef32b9c950ywan # chain, like this: 2611233d2500723e5594f3e7c70896ffeeef32b9c950ywan # if (condition1) { 2612233d2500723e5594f3e7c70896ffeeef32b9c950ywan # // Something followed by a blank line 2613233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 2614233d2500723e5594f3e7c70896ffeeef32b9c950ywan # } else if (condition2) { 2615233d2500723e5594f3e7c70896ffeeef32b9c950ywan # // Something else 2616233d2500723e5594f3e7c70896ffeeef32b9c950ywan # } 2617233d2500723e5594f3e7c70896ffeeef32b9c950ywan if linenum + 1 < clean_lines.NumLines(): 2618233d2500723e5594f3e7c70896ffeeef32b9c950ywan next_line = raw[linenum + 1] 2619233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (next_line 2620233d2500723e5594f3e7c70896ffeeef32b9c950ywan and Match(r'\s*}', next_line) 2621233d2500723e5594f3e7c70896ffeeef32b9c950ywan and next_line.find('} else ') == -1): 2622233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'whitespace/blank_line', 3, 2623233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Redundant blank line at the end of a code block ' 2624233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'should be deleted.') 2625233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2626233d2500723e5594f3e7c70896ffeeef32b9c950ywan matched = Match(r'\s*(public|protected|private):', prev_line) 2627233d2500723e5594f3e7c70896ffeeef32b9c950ywan if matched: 2628233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'whitespace/blank_line', 3, 2629233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Do not leave a blank line after "%s:"' % matched.group(1)) 2630233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2631233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Next, we complain if there's a comment too near the text 2632233d2500723e5594f3e7c70896ffeeef32b9c950ywan commentpos = line.find('//') 2633233d2500723e5594f3e7c70896ffeeef32b9c950ywan if commentpos != -1: 2634233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Check if the // may be in quotes. If so, ignore it 2635233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Comparisons made explicit for clarity -- pylint: disable=g-explicit-bool-comparison 2636233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (line.count('"', 0, commentpos) - 2637233d2500723e5594f3e7c70896ffeeef32b9c950ywan line.count('\\"', 0, commentpos)) % 2 == 0: # not in quotes 2638233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Allow one space for new scopes, two spaces otherwise: 2639233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (not Match(r'^\s*{ //', line) and 2640233d2500723e5594f3e7c70896ffeeef32b9c950ywan ((commentpos >= 1 and 2641233d2500723e5594f3e7c70896ffeeef32b9c950ywan line[commentpos-1] not in string.whitespace) or 2642233d2500723e5594f3e7c70896ffeeef32b9c950ywan (commentpos >= 2 and 2643233d2500723e5594f3e7c70896ffeeef32b9c950ywan line[commentpos-2] not in string.whitespace))): 2644233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'whitespace/comments', 2, 2645233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'At least two spaces is best between code and comments') 2646233d2500723e5594f3e7c70896ffeeef32b9c950ywan # There should always be a space between the // and the comment 2647233d2500723e5594f3e7c70896ffeeef32b9c950ywan commentend = commentpos + 2 2648233d2500723e5594f3e7c70896ffeeef32b9c950ywan if commentend < len(line) and not line[commentend] == ' ': 2649233d2500723e5594f3e7c70896ffeeef32b9c950ywan # but some lines are exceptions -- e.g. if they're big 2650233d2500723e5594f3e7c70896ffeeef32b9c950ywan # comment delimiters like: 2651233d2500723e5594f3e7c70896ffeeef32b9c950ywan # //---------------------------------------------------------- 2652233d2500723e5594f3e7c70896ffeeef32b9c950ywan # or are an empty C++ style Doxygen comment, like: 2653233d2500723e5594f3e7c70896ffeeef32b9c950ywan # /// 2654233d2500723e5594f3e7c70896ffeeef32b9c950ywan # or C++ style Doxygen comments placed after the variable: 2655233d2500723e5594f3e7c70896ffeeef32b9c950ywan # ///< Header comment 2656233d2500723e5594f3e7c70896ffeeef32b9c950ywan # //!< Header comment 2657233d2500723e5594f3e7c70896ffeeef32b9c950ywan # or they begin with multiple slashes followed by a space: 2658233d2500723e5594f3e7c70896ffeeef32b9c950ywan # //////// Header comment 2659233d2500723e5594f3e7c70896ffeeef32b9c950ywan match = (Search(r'[=/-]{4,}\s*$', line[commentend:]) or 2660233d2500723e5594f3e7c70896ffeeef32b9c950ywan Search(r'^/$', line[commentend:]) or 2661233d2500723e5594f3e7c70896ffeeef32b9c950ywan Search(r'^!< ', line[commentend:]) or 2662233d2500723e5594f3e7c70896ffeeef32b9c950ywan Search(r'^/< ', line[commentend:]) or 2663233d2500723e5594f3e7c70896ffeeef32b9c950ywan Search(r'^/+ ', line[commentend:])) 2664233d2500723e5594f3e7c70896ffeeef32b9c950ywan if not match: 2665233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'whitespace/comments', 4, 2666233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Should have a space between // and comment') 2667233d2500723e5594f3e7c70896ffeeef32b9c950ywan CheckComment(line[commentpos:], filename, linenum, error) 2668233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2669233d2500723e5594f3e7c70896ffeeef32b9c950ywan line = clean_lines.elided[linenum] # get rid of comments and strings 2670233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2671233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Don't try to do spacing checks for operator methods 2672233d2500723e5594f3e7c70896ffeeef32b9c950ywan line = re.sub(r'operator(==|!=|<|<<|<=|>=|>>|>)\(', 'operator\(', line) 2673233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2674233d2500723e5594f3e7c70896ffeeef32b9c950ywan # We allow no-spaces around = within an if: "if ( (a=Foo()) == 0 )". 2675233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Otherwise not. Note we only check for non-spaces on *both* sides; 2676233d2500723e5594f3e7c70896ffeeef32b9c950ywan # sometimes people put non-spaces on one side when aligning ='s among 2677233d2500723e5594f3e7c70896ffeeef32b9c950ywan # many lines (not that this is behavior that I approve of...) 2678233d2500723e5594f3e7c70896ffeeef32b9c950ywan if Search(r'[\w.]=[\w.]', line) and not Search(r'\b(if|while) ', line): 2679233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'whitespace/operators', 4, 2680233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Missing spaces around =') 2681233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2682233d2500723e5594f3e7c70896ffeeef32b9c950ywan # It's ok not to have spaces around binary operators like + - * /, but if 2683233d2500723e5594f3e7c70896ffeeef32b9c950ywan # there's too little whitespace, we get concerned. It's hard to tell, 2684233d2500723e5594f3e7c70896ffeeef32b9c950ywan # though, so we punt on this one for now. TODO. 2685233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2686233d2500723e5594f3e7c70896ffeeef32b9c950ywan # You should always have whitespace around binary operators. 2687233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 2688233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Check <= and >= first to avoid false positives with < and >, then 2689233d2500723e5594f3e7c70896ffeeef32b9c950ywan # check non-include lines for spacing around < and >. 2690233d2500723e5594f3e7c70896ffeeef32b9c950ywan match = Search(r'[^<>=!\s](==|!=|<=|>=)[^<>=!\s]', line) 2691233d2500723e5594f3e7c70896ffeeef32b9c950ywan if match: 2692233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'whitespace/operators', 3, 2693233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Missing spaces around %s' % match.group(1)) 2694233d2500723e5594f3e7c70896ffeeef32b9c950ywan # We allow no-spaces around << when used like this: 10<<20, but 2695233d2500723e5594f3e7c70896ffeeef32b9c950ywan # not otherwise (particularly, not when used as streams) 2696233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Also ignore using ns::operator<<; 2697233d2500723e5594f3e7c70896ffeeef32b9c950ywan match = Search(r'(operator|\S)(?:L|UL|ULL|l|ul|ull)?<<(\S)', line) 2698233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (match and 2699233d2500723e5594f3e7c70896ffeeef32b9c950ywan not (match.group(1).isdigit() and match.group(2).isdigit()) and 2700233d2500723e5594f3e7c70896ffeeef32b9c950ywan not (match.group(1) == 'operator' and match.group(2) == ';')): 2701233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'whitespace/operators', 3, 2702233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Missing spaces around <<') 2703233d2500723e5594f3e7c70896ffeeef32b9c950ywan elif not Match(r'#.*include', line): 2704233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Avoid false positives on -> 2705233d2500723e5594f3e7c70896ffeeef32b9c950ywan reduced_line = line.replace('->', '') 2706233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2707233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Look for < that is not surrounded by spaces. This is only 2708233d2500723e5594f3e7c70896ffeeef32b9c950ywan # triggered if both sides are missing spaces, even though 2709233d2500723e5594f3e7c70896ffeeef32b9c950ywan # technically should should flag if at least one side is missing a 2710233d2500723e5594f3e7c70896ffeeef32b9c950ywan # space. This is done to avoid some false positives with shifts. 2711233d2500723e5594f3e7c70896ffeeef32b9c950ywan match = Search(r'[^\s<]<([^\s=<].*)', reduced_line) 2712233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (match and 2713233d2500723e5594f3e7c70896ffeeef32b9c950ywan not FindNextMatchingAngleBracket(clean_lines, linenum, match.group(1))): 2714233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'whitespace/operators', 3, 2715233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Missing spaces around <') 2716233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2717233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Look for > that is not surrounded by spaces. Similar to the 2718233d2500723e5594f3e7c70896ffeeef32b9c950ywan # above, we only trigger if both sides are missing spaces to avoid 2719233d2500723e5594f3e7c70896ffeeef32b9c950ywan # false positives with shifts. 2720233d2500723e5594f3e7c70896ffeeef32b9c950ywan match = Search(r'^(.*[^\s>])>[^\s=>]', reduced_line) 2721233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (match and 2722233d2500723e5594f3e7c70896ffeeef32b9c950ywan not FindPreviousMatchingAngleBracket(clean_lines, linenum, 2723233d2500723e5594f3e7c70896ffeeef32b9c950ywan match.group(1))): 2724233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'whitespace/operators', 3, 2725233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Missing spaces around >') 2726233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2727233d2500723e5594f3e7c70896ffeeef32b9c950ywan # We allow no-spaces around >> for almost anything. This is because 2728233d2500723e5594f3e7c70896ffeeef32b9c950ywan # C++11 allows ">>" to close nested templates, which accounts for 2729233d2500723e5594f3e7c70896ffeeef32b9c950ywan # most cases when ">>" is not followed by a space. 2730233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 2731233d2500723e5594f3e7c70896ffeeef32b9c950ywan # We still warn on ">>" followed by alpha character, because that is 2732233d2500723e5594f3e7c70896ffeeef32b9c950ywan # likely due to ">>" being used for right shifts, e.g.: 2733233d2500723e5594f3e7c70896ffeeef32b9c950ywan # value >> alpha 2734233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 2735233d2500723e5594f3e7c70896ffeeef32b9c950ywan # When ">>" is used to close templates, the alphanumeric letter that 2736233d2500723e5594f3e7c70896ffeeef32b9c950ywan # follows would be part of an identifier, and there should still be 2737233d2500723e5594f3e7c70896ffeeef32b9c950ywan # a space separating the template type and the identifier. 2738233d2500723e5594f3e7c70896ffeeef32b9c950ywan # type<type<type>> alpha 2739233d2500723e5594f3e7c70896ffeeef32b9c950ywan match = Search(r'>>[a-zA-Z_]', line) 2740233d2500723e5594f3e7c70896ffeeef32b9c950ywan if match: 2741233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'whitespace/operators', 3, 2742233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Missing spaces around >>') 2743233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2744233d2500723e5594f3e7c70896ffeeef32b9c950ywan # There shouldn't be space around unary operators 2745233d2500723e5594f3e7c70896ffeeef32b9c950ywan match = Search(r'(!\s|~\s|[\s]--[\s;]|[\s]\+\+[\s;])', line) 2746233d2500723e5594f3e7c70896ffeeef32b9c950ywan if match: 2747233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'whitespace/operators', 4, 2748233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Extra space for operator %s' % match.group(1)) 2749233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2750233d2500723e5594f3e7c70896ffeeef32b9c950ywan # A pet peeve of mine: no spaces after an if, while, switch, or for 2751233d2500723e5594f3e7c70896ffeeef32b9c950ywan match = Search(r' (if\(|for\(|while\(|switch\()', line) 2752233d2500723e5594f3e7c70896ffeeef32b9c950ywan if match: 2753233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'whitespace/parens', 5, 2754233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Missing space before ( in %s' % match.group(1)) 2755233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2756233d2500723e5594f3e7c70896ffeeef32b9c950ywan # For if/for/while/switch, the left and right parens should be 2757233d2500723e5594f3e7c70896ffeeef32b9c950ywan # consistent about how many spaces are inside the parens, and 2758233d2500723e5594f3e7c70896ffeeef32b9c950ywan # there should either be zero or one spaces inside the parens. 2759233d2500723e5594f3e7c70896ffeeef32b9c950ywan # We don't want: "if ( foo)" or "if ( foo )". 2760233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Exception: "for ( ; foo; bar)" and "for (foo; bar; )" are allowed. 2761233d2500723e5594f3e7c70896ffeeef32b9c950ywan match = Search(r'\b(if|for|while|switch)\s*' 2762233d2500723e5594f3e7c70896ffeeef32b9c950ywan r'\(([ ]*)(.).*[^ ]+([ ]*)\)\s*{\s*$', 2763233d2500723e5594f3e7c70896ffeeef32b9c950ywan line) 2764233d2500723e5594f3e7c70896ffeeef32b9c950ywan if match: 2765233d2500723e5594f3e7c70896ffeeef32b9c950ywan if len(match.group(2)) != len(match.group(4)): 2766233d2500723e5594f3e7c70896ffeeef32b9c950ywan if not (match.group(3) == ';' and 2767233d2500723e5594f3e7c70896ffeeef32b9c950ywan len(match.group(2)) == 1 + len(match.group(4)) or 2768233d2500723e5594f3e7c70896ffeeef32b9c950ywan not match.group(2) and Search(r'\bfor\s*\(.*; \)', line)): 2769233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'whitespace/parens', 5, 2770233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Mismatching spaces inside () in %s' % match.group(1)) 2771233d2500723e5594f3e7c70896ffeeef32b9c950ywan if len(match.group(2)) not in [0, 1]: 2772233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'whitespace/parens', 5, 2773233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Should have zero or one spaces inside ( and ) in %s' % 2774233d2500723e5594f3e7c70896ffeeef32b9c950ywan match.group(1)) 2775233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2776233d2500723e5594f3e7c70896ffeeef32b9c950ywan # You should always have a space after a comma (either as fn arg or operator) 2777233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 2778233d2500723e5594f3e7c70896ffeeef32b9c950ywan # This does not apply when the non-space character following the 2779233d2500723e5594f3e7c70896ffeeef32b9c950ywan # comma is another comma, since the only time when that happens is 2780233d2500723e5594f3e7c70896ffeeef32b9c950ywan # for empty macro arguments. 2781233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 2782233d2500723e5594f3e7c70896ffeeef32b9c950ywan # We run this check in two passes: first pass on elided lines to 2783233d2500723e5594f3e7c70896ffeeef32b9c950ywan # verify that lines contain missing whitespaces, second pass on raw 2784233d2500723e5594f3e7c70896ffeeef32b9c950ywan # lines to confirm that those missing whitespaces are not due to 2785233d2500723e5594f3e7c70896ffeeef32b9c950ywan # elided comments. 2786233d2500723e5594f3e7c70896ffeeef32b9c950ywan if Search(r',[^,\s]', line) and Search(r',[^,\s]', raw[linenum]): 2787233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'whitespace/comma', 3, 2788233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Missing space after ,') 2789233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2790233d2500723e5594f3e7c70896ffeeef32b9c950ywan # You should always have a space after a semicolon 2791233d2500723e5594f3e7c70896ffeeef32b9c950ywan # except for few corner cases 2792233d2500723e5594f3e7c70896ffeeef32b9c950ywan # TODO(unknown): clarify if 'if (1) { return 1;}' is requires one more 2793233d2500723e5594f3e7c70896ffeeef32b9c950ywan # space after ; 2794233d2500723e5594f3e7c70896ffeeef32b9c950ywan if Search(r';[^\s};\\)/]', line): 2795233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'whitespace/semicolon', 3, 2796233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Missing space after ;') 2797233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2798233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Next we will look for issues with function calls. 2799233d2500723e5594f3e7c70896ffeeef32b9c950ywan CheckSpacingForFunctionCall(filename, line, linenum, error) 2800233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2801233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Except after an opening paren, or after another opening brace (in case of 2802233d2500723e5594f3e7c70896ffeeef32b9c950ywan # an initializer list, for instance), you should have spaces before your 2803233d2500723e5594f3e7c70896ffeeef32b9c950ywan # braces. And since you should never have braces at the beginning of a line, 2804233d2500723e5594f3e7c70896ffeeef32b9c950ywan # this is an easy test. 2805233d2500723e5594f3e7c70896ffeeef32b9c950ywan match = Match(r'^(.*[^ ({]){', line) 2806233d2500723e5594f3e7c70896ffeeef32b9c950ywan if match: 2807233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Try a bit harder to check for brace initialization. This 2808233d2500723e5594f3e7c70896ffeeef32b9c950ywan # happens in one of the following forms: 2809233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Constructor() : initializer_list_{} { ... } 2810233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Constructor{}.MemberFunction() 2811233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Type variable{}; 2812233d2500723e5594f3e7c70896ffeeef32b9c950ywan # FunctionCall(type{}, ...); 2813233d2500723e5594f3e7c70896ffeeef32b9c950ywan # LastArgument(..., type{}); 2814233d2500723e5594f3e7c70896ffeeef32b9c950ywan # LOG(INFO) << type{} << " ..."; 2815233d2500723e5594f3e7c70896ffeeef32b9c950ywan # map_of_type[{...}] = ...; 2816233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 2817233d2500723e5594f3e7c70896ffeeef32b9c950ywan # We check for the character following the closing brace, and 2818233d2500723e5594f3e7c70896ffeeef32b9c950ywan # silence the warning if it's one of those listed above, i.e. 2819233d2500723e5594f3e7c70896ffeeef32b9c950ywan # "{.;,)<]". 2820233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 2821233d2500723e5594f3e7c70896ffeeef32b9c950ywan # To account for nested initializer list, we allow any number of 2822233d2500723e5594f3e7c70896ffeeef32b9c950ywan # closing braces up to "{;,)<". We can't simply silence the 2823233d2500723e5594f3e7c70896ffeeef32b9c950ywan # warning on first sight of closing brace, because that would 2824233d2500723e5594f3e7c70896ffeeef32b9c950ywan # cause false negatives for things that are not initializer lists. 2825233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Silence this: But not this: 2826233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Outer{ if (...) { 2827233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Inner{...} if (...){ // Missing space before { 2828233d2500723e5594f3e7c70896ffeeef32b9c950ywan # }; } 2829233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 2830233d2500723e5594f3e7c70896ffeeef32b9c950ywan # There is a false negative with this approach if people inserted 2831233d2500723e5594f3e7c70896ffeeef32b9c950ywan # spurious semicolons, e.g. "if (cond){};", but we will catch the 2832233d2500723e5594f3e7c70896ffeeef32b9c950ywan # spurious semicolon with a separate check. 2833233d2500723e5594f3e7c70896ffeeef32b9c950ywan (endline, endlinenum, endpos) = CloseExpression( 2834233d2500723e5594f3e7c70896ffeeef32b9c950ywan clean_lines, linenum, len(match.group(1))) 2835233d2500723e5594f3e7c70896ffeeef32b9c950ywan trailing_text = '' 2836233d2500723e5594f3e7c70896ffeeef32b9c950ywan if endpos > -1: 2837233d2500723e5594f3e7c70896ffeeef32b9c950ywan trailing_text = endline[endpos:] 2838233d2500723e5594f3e7c70896ffeeef32b9c950ywan for offset in xrange(endlinenum + 1, 2839233d2500723e5594f3e7c70896ffeeef32b9c950ywan min(endlinenum + 3, clean_lines.NumLines() - 1)): 2840233d2500723e5594f3e7c70896ffeeef32b9c950ywan trailing_text += clean_lines.elided[offset] 2841233d2500723e5594f3e7c70896ffeeef32b9c950ywan if not Match(r'^[\s}]*[{.;,)<\]]', trailing_text): 2842233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'whitespace/braces', 5, 2843233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Missing space before {') 2844233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2845233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Make sure '} else {' has spaces. 2846233d2500723e5594f3e7c70896ffeeef32b9c950ywan if Search(r'}else', line): 2847233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'whitespace/braces', 5, 2848233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Missing space before else') 2849233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2850233d2500723e5594f3e7c70896ffeeef32b9c950ywan # You shouldn't have spaces before your brackets, except maybe after 2851233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 'delete []' or 'new char * []'. 2852233d2500723e5594f3e7c70896ffeeef32b9c950ywan if Search(r'\w\s+\[', line) and not Search(r'delete\s+\[', line): 2853233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'whitespace/braces', 5, 2854233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Extra space before [') 2855233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2856233d2500723e5594f3e7c70896ffeeef32b9c950ywan # You shouldn't have a space before a semicolon at the end of the line. 2857233d2500723e5594f3e7c70896ffeeef32b9c950ywan # There's a special case for "for" since the style guide allows space before 2858233d2500723e5594f3e7c70896ffeeef32b9c950ywan # the semicolon there. 2859233d2500723e5594f3e7c70896ffeeef32b9c950ywan if Search(r':\s*;\s*$', line): 2860233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'whitespace/semicolon', 5, 2861233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Semicolon defining empty statement. Use {} instead.') 2862233d2500723e5594f3e7c70896ffeeef32b9c950ywan elif Search(r'^\s*;\s*$', line): 2863233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'whitespace/semicolon', 5, 2864233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Line contains only semicolon. If this should be an empty statement, ' 2865233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'use {} instead.') 2866233d2500723e5594f3e7c70896ffeeef32b9c950ywan elif (Search(r'\s+;\s*$', line) and 2867233d2500723e5594f3e7c70896ffeeef32b9c950ywan not Search(r'\bfor\b', line)): 2868233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'whitespace/semicolon', 5, 2869233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Extra space before last semicolon. If this should be an empty ' 2870233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'statement, use {} instead.') 2871233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2872233d2500723e5594f3e7c70896ffeeef32b9c950ywan # In range-based for, we wanted spaces before and after the colon, but 2873233d2500723e5594f3e7c70896ffeeef32b9c950ywan # not around "::" tokens that might appear. 2874233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (Search('for *\(.*[^:]:[^: ]', line) or 2875233d2500723e5594f3e7c70896ffeeef32b9c950ywan Search('for *\(.*[^: ]:[^:]', line)): 2876233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'whitespace/forcolon', 2, 2877233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Missing space around colon in range-based for loop') 2878233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2879233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2880233d2500723e5594f3e7c70896ffeeef32b9c950ywandef CheckSectionSpacing(filename, clean_lines, class_info, linenum, error): 2881233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Checks for additional blank line issues related to sections. 2882233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2883233d2500723e5594f3e7c70896ffeeef32b9c950ywan Currently the only thing checked here is blank line before protected/private. 2884233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2885233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 2886233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename: The name of the current file. 2887233d2500723e5594f3e7c70896ffeeef32b9c950ywan clean_lines: A CleansedLines instance containing the file. 2888233d2500723e5594f3e7c70896ffeeef32b9c950ywan class_info: A _ClassInfo objects. 2889233d2500723e5594f3e7c70896ffeeef32b9c950ywan linenum: The number of the line to check. 2890233d2500723e5594f3e7c70896ffeeef32b9c950ywan error: The function to call with any errors found. 2891233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 2892233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Skip checks if the class is small, where small means 25 lines or less. 2893233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 25 lines seems like a good cutoff since that's the usual height of 2894233d2500723e5594f3e7c70896ffeeef32b9c950ywan # terminals, and any class that can't fit in one screen can't really 2895233d2500723e5594f3e7c70896ffeeef32b9c950ywan # be considered "small". 2896233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 2897233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Also skip checks if we are on the first line. This accounts for 2898233d2500723e5594f3e7c70896ffeeef32b9c950ywan # classes that look like 2899233d2500723e5594f3e7c70896ffeeef32b9c950ywan # class Foo { public: ... }; 2900233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 2901233d2500723e5594f3e7c70896ffeeef32b9c950ywan # If we didn't find the end of the class, last_line would be zero, 2902233d2500723e5594f3e7c70896ffeeef32b9c950ywan # and the check will be skipped by the first condition. 2903233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (class_info.last_line - class_info.starting_linenum <= 24 or 2904233d2500723e5594f3e7c70896ffeeef32b9c950ywan linenum <= class_info.starting_linenum): 2905233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 2906233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2907233d2500723e5594f3e7c70896ffeeef32b9c950ywan matched = Match(r'\s*(public|protected|private):', clean_lines.lines[linenum]) 2908233d2500723e5594f3e7c70896ffeeef32b9c950ywan if matched: 2909233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Issue warning if the line before public/protected/private was 2910233d2500723e5594f3e7c70896ffeeef32b9c950ywan # not a blank line, but don't do this if the previous line contains 2911233d2500723e5594f3e7c70896ffeeef32b9c950ywan # "class" or "struct". This can happen two ways: 2912233d2500723e5594f3e7c70896ffeeef32b9c950ywan # - We are at the beginning of the class. 2913233d2500723e5594f3e7c70896ffeeef32b9c950ywan # - We are forward-declaring an inner class that is semantically 2914233d2500723e5594f3e7c70896ffeeef32b9c950ywan # private, but needed to be public for implementation reasons. 2915233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Also ignores cases where the previous line ends with a backslash as can be 2916233d2500723e5594f3e7c70896ffeeef32b9c950ywan # common when defining classes in C macros. 2917233d2500723e5594f3e7c70896ffeeef32b9c950ywan prev_line = clean_lines.lines[linenum - 1] 2918233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (not IsBlankLine(prev_line) and 2919233d2500723e5594f3e7c70896ffeeef32b9c950ywan not Search(r'\b(class|struct)\b', prev_line) and 2920233d2500723e5594f3e7c70896ffeeef32b9c950ywan not Search(r'\\$', prev_line)): 2921233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Try a bit harder to find the beginning of the class. This is to 2922233d2500723e5594f3e7c70896ffeeef32b9c950ywan # account for multi-line base-specifier lists, e.g.: 2923233d2500723e5594f3e7c70896ffeeef32b9c950ywan # class Derived 2924233d2500723e5594f3e7c70896ffeeef32b9c950ywan # : public Base { 2925233d2500723e5594f3e7c70896ffeeef32b9c950ywan end_class_head = class_info.starting_linenum 2926233d2500723e5594f3e7c70896ffeeef32b9c950ywan for i in range(class_info.starting_linenum, linenum): 2927233d2500723e5594f3e7c70896ffeeef32b9c950ywan if Search(r'\{\s*$', clean_lines.lines[i]): 2928233d2500723e5594f3e7c70896ffeeef32b9c950ywan end_class_head = i 2929233d2500723e5594f3e7c70896ffeeef32b9c950ywan break 2930233d2500723e5594f3e7c70896ffeeef32b9c950ywan if end_class_head < linenum - 1: 2931233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'whitespace/blank_line', 3, 2932233d2500723e5594f3e7c70896ffeeef32b9c950ywan '"%s:" should be preceded by a blank line' % matched.group(1)) 2933233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2934233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2935233d2500723e5594f3e7c70896ffeeef32b9c950ywandef GetPreviousNonBlankLine(clean_lines, linenum): 2936233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Return the most recent non-blank line and its line number. 2937233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2938233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 2939233d2500723e5594f3e7c70896ffeeef32b9c950ywan clean_lines: A CleansedLines instance containing the file contents. 2940233d2500723e5594f3e7c70896ffeeef32b9c950ywan linenum: The number of the line to check. 2941233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2942233d2500723e5594f3e7c70896ffeeef32b9c950ywan Returns: 2943233d2500723e5594f3e7c70896ffeeef32b9c950ywan A tuple with two elements. The first element is the contents of the last 2944233d2500723e5594f3e7c70896ffeeef32b9c950ywan non-blank line before the current line, or the empty string if this is the 2945233d2500723e5594f3e7c70896ffeeef32b9c950ywan first non-blank line. The second is the line number of that line, or -1 2946233d2500723e5594f3e7c70896ffeeef32b9c950ywan if this is the first non-blank line. 2947233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 2948233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2949233d2500723e5594f3e7c70896ffeeef32b9c950ywan prevlinenum = linenum - 1 2950233d2500723e5594f3e7c70896ffeeef32b9c950ywan while prevlinenum >= 0: 2951233d2500723e5594f3e7c70896ffeeef32b9c950ywan prevline = clean_lines.elided[prevlinenum] 2952233d2500723e5594f3e7c70896ffeeef32b9c950ywan if not IsBlankLine(prevline): # if not a blank line... 2953233d2500723e5594f3e7c70896ffeeef32b9c950ywan return (prevline, prevlinenum) 2954233d2500723e5594f3e7c70896ffeeef32b9c950ywan prevlinenum -= 1 2955233d2500723e5594f3e7c70896ffeeef32b9c950ywan return ('', -1) 2956233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2957233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2958233d2500723e5594f3e7c70896ffeeef32b9c950ywandef CheckBraces(filename, clean_lines, linenum, error): 2959233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Looks for misplaced braces (e.g. at the end of line). 2960233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2961233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 2962233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename: The name of the current file. 2963233d2500723e5594f3e7c70896ffeeef32b9c950ywan clean_lines: A CleansedLines instance containing the file. 2964233d2500723e5594f3e7c70896ffeeef32b9c950ywan linenum: The number of the line to check. 2965233d2500723e5594f3e7c70896ffeeef32b9c950ywan error: The function to call with any errors found. 2966233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 2967233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2968233d2500723e5594f3e7c70896ffeeef32b9c950ywan line = clean_lines.elided[linenum] # get rid of comments and strings 2969233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2970233d2500723e5594f3e7c70896ffeeef32b9c950ywan if Match(r'\s*{\s*$', line): 2971233d2500723e5594f3e7c70896ffeeef32b9c950ywan # We allow an open brace to start a line in the case where someone is using 2972233d2500723e5594f3e7c70896ffeeef32b9c950ywan # braces in a block to explicitly create a new scope, which is commonly used 2973233d2500723e5594f3e7c70896ffeeef32b9c950ywan # to control the lifetime of stack-allocated variables. Braces are also 2974233d2500723e5594f3e7c70896ffeeef32b9c950ywan # used for brace initializers inside function calls. We don't detect this 2975233d2500723e5594f3e7c70896ffeeef32b9c950ywan # perfectly: we just don't complain if the last non-whitespace character on 2976233d2500723e5594f3e7c70896ffeeef32b9c950ywan # the previous non-blank line is ',', ';', ':', '(', '{', or '}', or if the 2977233d2500723e5594f3e7c70896ffeeef32b9c950ywan # previous line starts a preprocessor block. 2978233d2500723e5594f3e7c70896ffeeef32b9c950ywan prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0] 2979233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (not Search(r'[,;:}{(]\s*$', prevline) and 2980233d2500723e5594f3e7c70896ffeeef32b9c950ywan not Match(r'\s*#', prevline)): 2981233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'whitespace/braces', 4, 2982233d2500723e5594f3e7c70896ffeeef32b9c950ywan '{ should almost always be at the end of the previous line') 2983233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2984233d2500723e5594f3e7c70896ffeeef32b9c950ywan # An else clause should be on the same line as the preceding closing brace. 2985233d2500723e5594f3e7c70896ffeeef32b9c950ywan if Match(r'\s*else\s*', line): 2986233d2500723e5594f3e7c70896ffeeef32b9c950ywan prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0] 2987233d2500723e5594f3e7c70896ffeeef32b9c950ywan if Match(r'\s*}\s*$', prevline): 2988233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'whitespace/newline', 4, 2989233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'An else should appear on the same line as the preceding }') 2990233d2500723e5594f3e7c70896ffeeef32b9c950ywan 2991233d2500723e5594f3e7c70896ffeeef32b9c950ywan # If braces come on one side of an else, they should be on both. 2992233d2500723e5594f3e7c70896ffeeef32b9c950ywan # However, we have to worry about "else if" that spans multiple lines! 2993233d2500723e5594f3e7c70896ffeeef32b9c950ywan if Search(r'}\s*else[^{]*$', line) or Match(r'[^}]*else\s*{', line): 2994233d2500723e5594f3e7c70896ffeeef32b9c950ywan if Search(r'}\s*else if([^{]*)$', line): # could be multi-line if 2995233d2500723e5594f3e7c70896ffeeef32b9c950ywan # find the ( after the if 2996233d2500723e5594f3e7c70896ffeeef32b9c950ywan pos = line.find('else if') 2997233d2500723e5594f3e7c70896ffeeef32b9c950ywan pos = line.find('(', pos) 2998233d2500723e5594f3e7c70896ffeeef32b9c950ywan if pos > 0: 2999233d2500723e5594f3e7c70896ffeeef32b9c950ywan (endline, _, endpos) = CloseExpression(clean_lines, linenum, pos) 3000233d2500723e5594f3e7c70896ffeeef32b9c950ywan if endline[endpos:].find('{') == -1: # must be brace after if 3001233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'readability/braces', 5, 3002233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'If an else has a brace on one side, it should have it on both') 3003233d2500723e5594f3e7c70896ffeeef32b9c950ywan else: # common case: else not followed by a multi-line if 3004233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'readability/braces', 5, 3005233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'If an else has a brace on one side, it should have it on both') 3006233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3007233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Likewise, an else should never have the else clause on the same line 3008233d2500723e5594f3e7c70896ffeeef32b9c950ywan if Search(r'\belse [^\s{]', line) and not Search(r'\belse if\b', line): 3009233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'whitespace/newline', 4, 3010233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Else clause should never be on same line as else (use 2 lines)') 3011233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3012233d2500723e5594f3e7c70896ffeeef32b9c950ywan # In the same way, a do/while should never be on one line 3013233d2500723e5594f3e7c70896ffeeef32b9c950ywan if Match(r'\s*do [^\s{]', line): 3014233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'whitespace/newline', 4, 3015233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'do/while clauses should not be on a single line') 3016233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3017233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Block bodies should not be followed by a semicolon. Due to C++11 3018233d2500723e5594f3e7c70896ffeeef32b9c950ywan # brace initialization, there are more places where semicolons are 3019233d2500723e5594f3e7c70896ffeeef32b9c950ywan # required than not, so we use a whitelist approach to check these 3020233d2500723e5594f3e7c70896ffeeef32b9c950ywan # rather than a blacklist. These are the places where "};" should 3021233d2500723e5594f3e7c70896ffeeef32b9c950ywan # be replaced by just "}": 3022233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 1. Some flavor of block following closing parenthesis: 3023233d2500723e5594f3e7c70896ffeeef32b9c950ywan # for (;;) {}; 3024233d2500723e5594f3e7c70896ffeeef32b9c950ywan # while (...) {}; 3025233d2500723e5594f3e7c70896ffeeef32b9c950ywan # switch (...) {}; 3026233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Function(...) {}; 3027233d2500723e5594f3e7c70896ffeeef32b9c950ywan # if (...) {}; 3028233d2500723e5594f3e7c70896ffeeef32b9c950ywan # if (...) else if (...) {}; 3029233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 3030233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 2. else block: 3031233d2500723e5594f3e7c70896ffeeef32b9c950ywan # if (...) else {}; 3032233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 3033233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 3. const member function: 3034233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Function(...) const {}; 3035233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 3036233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 4. Block following some statement: 3037233d2500723e5594f3e7c70896ffeeef32b9c950ywan # x = 42; 3038233d2500723e5594f3e7c70896ffeeef32b9c950ywan # {}; 3039233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 3040233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 5. Block at the beginning of a function: 3041233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Function(...) { 3042233d2500723e5594f3e7c70896ffeeef32b9c950ywan # {}; 3043233d2500723e5594f3e7c70896ffeeef32b9c950ywan # } 3044233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 3045233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Note that naively checking for the preceding "{" will also match 3046233d2500723e5594f3e7c70896ffeeef32b9c950ywan # braces inside multi-dimensional arrays, but this is fine since 3047233d2500723e5594f3e7c70896ffeeef32b9c950ywan # that expression will not contain semicolons. 3048233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 3049233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 6. Block following another block: 3050233d2500723e5594f3e7c70896ffeeef32b9c950ywan # while (true) {} 3051233d2500723e5594f3e7c70896ffeeef32b9c950ywan # {}; 3052233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 3053233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 7. End of namespaces: 3054233d2500723e5594f3e7c70896ffeeef32b9c950ywan # namespace {}; 3055233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 3056233d2500723e5594f3e7c70896ffeeef32b9c950ywan # These semicolons seems far more common than other kinds of 3057233d2500723e5594f3e7c70896ffeeef32b9c950ywan # redundant semicolons, possibly due to people converting classes 3058233d2500723e5594f3e7c70896ffeeef32b9c950ywan # to namespaces. For now we do not warn for this case. 3059233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 3060233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Try matching case 1 first. 3061233d2500723e5594f3e7c70896ffeeef32b9c950ywan match = Match(r'^(.*\)\s*)\{', line) 3062233d2500723e5594f3e7c70896ffeeef32b9c950ywan if match: 3063233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Matched closing parenthesis (case 1). Check the token before the 3064233d2500723e5594f3e7c70896ffeeef32b9c950ywan # matching opening parenthesis, and don't warn if it looks like a 3065233d2500723e5594f3e7c70896ffeeef32b9c950ywan # macro. This avoids these false positives: 3066233d2500723e5594f3e7c70896ffeeef32b9c950ywan # - macro that defines a base class 3067233d2500723e5594f3e7c70896ffeeef32b9c950ywan # - multi-line macro that defines a base class 3068233d2500723e5594f3e7c70896ffeeef32b9c950ywan # - macro that defines the whole class-head 3069233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 3070233d2500723e5594f3e7c70896ffeeef32b9c950ywan # But we still issue warnings for macros that we know are safe to 3071233d2500723e5594f3e7c70896ffeeef32b9c950ywan # warn, specifically: 3072233d2500723e5594f3e7c70896ffeeef32b9c950ywan # - TEST, TEST_F, TEST_P, MATCHER, MATCHER_P 3073233d2500723e5594f3e7c70896ffeeef32b9c950ywan # - TYPED_TEST 3074233d2500723e5594f3e7c70896ffeeef32b9c950ywan # - INTERFACE_DEF 3075233d2500723e5594f3e7c70896ffeeef32b9c950ywan # - EXCLUSIVE_LOCKS_REQUIRED, SHARED_LOCKS_REQUIRED, LOCKS_EXCLUDED: 3076233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 3077233d2500723e5594f3e7c70896ffeeef32b9c950ywan # We implement a whitelist of safe macros instead of a blacklist of 3078233d2500723e5594f3e7c70896ffeeef32b9c950ywan # unsafe macros, even though the latter appears less frequently in 3079233d2500723e5594f3e7c70896ffeeef32b9c950ywan # google code and would have been easier to implement. This is because 3080233d2500723e5594f3e7c70896ffeeef32b9c950ywan # the downside for getting the whitelist wrong means some extra 3081233d2500723e5594f3e7c70896ffeeef32b9c950ywan # semicolons, while the downside for getting the blacklist wrong 3082233d2500723e5594f3e7c70896ffeeef32b9c950ywan # would result in compile errors. 3083233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 3084233d2500723e5594f3e7c70896ffeeef32b9c950ywan # In addition to macros, we also don't want to warn on compound 3085233d2500723e5594f3e7c70896ffeeef32b9c950ywan # literals. 3086233d2500723e5594f3e7c70896ffeeef32b9c950ywan closing_brace_pos = match.group(1).rfind(')') 3087233d2500723e5594f3e7c70896ffeeef32b9c950ywan opening_parenthesis = ReverseCloseExpression( 3088233d2500723e5594f3e7c70896ffeeef32b9c950ywan clean_lines, linenum, closing_brace_pos) 3089233d2500723e5594f3e7c70896ffeeef32b9c950ywan if opening_parenthesis[2] > -1: 3090233d2500723e5594f3e7c70896ffeeef32b9c950ywan line_prefix = opening_parenthesis[0][0:opening_parenthesis[2]] 3091233d2500723e5594f3e7c70896ffeeef32b9c950ywan macro = Search(r'\b([A-Z_]+)\s*$', line_prefix) 3092233d2500723e5594f3e7c70896ffeeef32b9c950ywan if ((macro and 3093233d2500723e5594f3e7c70896ffeeef32b9c950ywan macro.group(1) not in ( 3094233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'TEST', 'TEST_F', 'MATCHER', 'MATCHER_P', 'TYPED_TEST', 3095233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'EXCLUSIVE_LOCKS_REQUIRED', 'SHARED_LOCKS_REQUIRED', 3096233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'LOCKS_EXCLUDED', 'INTERFACE_DEF')) or 3097233d2500723e5594f3e7c70896ffeeef32b9c950ywan Search(r'\s+=\s*$', line_prefix)): 3098233d2500723e5594f3e7c70896ffeeef32b9c950ywan match = None 3099233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3100233d2500723e5594f3e7c70896ffeeef32b9c950ywan else: 3101233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Try matching cases 2-3. 3102233d2500723e5594f3e7c70896ffeeef32b9c950ywan match = Match(r'^(.*(?:else|\)\s*const)\s*)\{', line) 3103233d2500723e5594f3e7c70896ffeeef32b9c950ywan if not match: 3104233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Try matching cases 4-6. These are always matched on separate lines. 3105233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 3106233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Note that we can't simply concatenate the previous line to the 3107233d2500723e5594f3e7c70896ffeeef32b9c950ywan # current line and do a single match, otherwise we may output 3108233d2500723e5594f3e7c70896ffeeef32b9c950ywan # duplicate warnings for the blank line case: 3109233d2500723e5594f3e7c70896ffeeef32b9c950ywan # if (cond) { 3110233d2500723e5594f3e7c70896ffeeef32b9c950ywan # // blank line 3111233d2500723e5594f3e7c70896ffeeef32b9c950ywan # } 3112233d2500723e5594f3e7c70896ffeeef32b9c950ywan prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0] 3113233d2500723e5594f3e7c70896ffeeef32b9c950ywan if prevline and Search(r'[;{}]\s*$', prevline): 3114233d2500723e5594f3e7c70896ffeeef32b9c950ywan match = Match(r'^(\s*)\{', line) 3115233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3116233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Check matching closing brace 3117233d2500723e5594f3e7c70896ffeeef32b9c950ywan if match: 3118233d2500723e5594f3e7c70896ffeeef32b9c950ywan (endline, endlinenum, endpos) = CloseExpression( 3119233d2500723e5594f3e7c70896ffeeef32b9c950ywan clean_lines, linenum, len(match.group(1))) 3120233d2500723e5594f3e7c70896ffeeef32b9c950ywan if endpos > -1 and Match(r'^\s*;', endline[endpos:]): 3121233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Current {} pair is eligible for semicolon check, and we have found 3122233d2500723e5594f3e7c70896ffeeef32b9c950ywan # the redundant semicolon, output warning here. 3123233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 3124233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Note: because we are scanning forward for opening braces, and 3125233d2500723e5594f3e7c70896ffeeef32b9c950ywan # outputting warnings for the matching closing brace, if there are 3126233d2500723e5594f3e7c70896ffeeef32b9c950ywan # nested blocks with trailing semicolons, we will get the error 3127233d2500723e5594f3e7c70896ffeeef32b9c950ywan # messages in reversed order. 3128233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, endlinenum, 'readability/braces', 4, 3129233d2500723e5594f3e7c70896ffeeef32b9c950ywan "You don't need a ; after a }") 3130233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3131233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3132233d2500723e5594f3e7c70896ffeeef32b9c950ywandef CheckEmptyBlockBody(filename, clean_lines, linenum, error): 3133233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Look for empty loop/conditional body with only a single semicolon. 3134233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3135233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 3136233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename: The name of the current file. 3137233d2500723e5594f3e7c70896ffeeef32b9c950ywan clean_lines: A CleansedLines instance containing the file. 3138233d2500723e5594f3e7c70896ffeeef32b9c950ywan linenum: The number of the line to check. 3139233d2500723e5594f3e7c70896ffeeef32b9c950ywan error: The function to call with any errors found. 3140233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 3141233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3142233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Search for loop keywords at the beginning of the line. Because only 3143233d2500723e5594f3e7c70896ffeeef32b9c950ywan # whitespaces are allowed before the keywords, this will also ignore most 3144233d2500723e5594f3e7c70896ffeeef32b9c950ywan # do-while-loops, since those lines should start with closing brace. 3145233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 3146233d2500723e5594f3e7c70896ffeeef32b9c950ywan # We also check "if" blocks here, since an empty conditional block 3147233d2500723e5594f3e7c70896ffeeef32b9c950ywan # is likely an error. 3148233d2500723e5594f3e7c70896ffeeef32b9c950ywan line = clean_lines.elided[linenum] 3149233d2500723e5594f3e7c70896ffeeef32b9c950ywan matched = Match(r'\s*(for|while|if)\s*\(', line) 3150233d2500723e5594f3e7c70896ffeeef32b9c950ywan if matched: 3151233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Find the end of the conditional expression 3152233d2500723e5594f3e7c70896ffeeef32b9c950ywan (end_line, end_linenum, end_pos) = CloseExpression( 3153233d2500723e5594f3e7c70896ffeeef32b9c950ywan clean_lines, linenum, line.find('(')) 3154233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3155233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Output warning if what follows the condition expression is a semicolon. 3156233d2500723e5594f3e7c70896ffeeef32b9c950ywan # No warning for all other cases, including whitespace or newline, since we 3157233d2500723e5594f3e7c70896ffeeef32b9c950ywan # have a separate check for semicolons preceded by whitespace. 3158233d2500723e5594f3e7c70896ffeeef32b9c950ywan if end_pos >= 0 and Match(r';', end_line[end_pos:]): 3159233d2500723e5594f3e7c70896ffeeef32b9c950ywan if matched.group(1) == 'if': 3160233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, end_linenum, 'whitespace/empty_conditional_body', 5, 3161233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Empty conditional bodies should use {}') 3162233d2500723e5594f3e7c70896ffeeef32b9c950ywan else: 3163233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, end_linenum, 'whitespace/empty_loop_body', 5, 3164233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Empty loop bodies should use {} or continue') 3165233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3166233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3167233d2500723e5594f3e7c70896ffeeef32b9c950ywandef CheckCheck(filename, clean_lines, linenum, error): 3168233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Checks the use of CHECK and EXPECT macros. 3169233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3170233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 3171233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename: The name of the current file. 3172233d2500723e5594f3e7c70896ffeeef32b9c950ywan clean_lines: A CleansedLines instance containing the file. 3173233d2500723e5594f3e7c70896ffeeef32b9c950ywan linenum: The number of the line to check. 3174233d2500723e5594f3e7c70896ffeeef32b9c950ywan error: The function to call with any errors found. 3175233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 3176233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3177233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Decide the set of replacement macros that should be suggested 3178233d2500723e5594f3e7c70896ffeeef32b9c950ywan lines = clean_lines.elided 3179233d2500723e5594f3e7c70896ffeeef32b9c950ywan check_macro = None 3180233d2500723e5594f3e7c70896ffeeef32b9c950ywan start_pos = -1 3181233d2500723e5594f3e7c70896ffeeef32b9c950ywan for macro in _CHECK_MACROS: 3182233d2500723e5594f3e7c70896ffeeef32b9c950ywan i = lines[linenum].find(macro) 3183233d2500723e5594f3e7c70896ffeeef32b9c950ywan if i >= 0: 3184233d2500723e5594f3e7c70896ffeeef32b9c950ywan check_macro = macro 3185233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3186233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Find opening parenthesis. Do a regular expression match here 3187233d2500723e5594f3e7c70896ffeeef32b9c950ywan # to make sure that we are matching the expected CHECK macro, as 3188233d2500723e5594f3e7c70896ffeeef32b9c950ywan # opposed to some other macro that happens to contain the CHECK 3189233d2500723e5594f3e7c70896ffeeef32b9c950ywan # substring. 3190233d2500723e5594f3e7c70896ffeeef32b9c950ywan matched = Match(r'^(.*\b' + check_macro + r'\s*)\(', lines[linenum]) 3191233d2500723e5594f3e7c70896ffeeef32b9c950ywan if not matched: 3192233d2500723e5594f3e7c70896ffeeef32b9c950ywan continue 3193233d2500723e5594f3e7c70896ffeeef32b9c950ywan start_pos = len(matched.group(1)) 3194233d2500723e5594f3e7c70896ffeeef32b9c950ywan break 3195233d2500723e5594f3e7c70896ffeeef32b9c950ywan if not check_macro or start_pos < 0: 3196233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Don't waste time here if line doesn't contain 'CHECK' or 'EXPECT' 3197233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 3198233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3199233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Find end of the boolean expression by matching parentheses 3200233d2500723e5594f3e7c70896ffeeef32b9c950ywan (last_line, end_line, end_pos) = CloseExpression( 3201233d2500723e5594f3e7c70896ffeeef32b9c950ywan clean_lines, linenum, start_pos) 3202233d2500723e5594f3e7c70896ffeeef32b9c950ywan if end_pos < 0: 3203233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 3204233d2500723e5594f3e7c70896ffeeef32b9c950ywan if linenum == end_line: 3205233d2500723e5594f3e7c70896ffeeef32b9c950ywan expression = lines[linenum][start_pos + 1:end_pos - 1] 3206233d2500723e5594f3e7c70896ffeeef32b9c950ywan else: 3207233d2500723e5594f3e7c70896ffeeef32b9c950ywan expression = lines[linenum][start_pos + 1:] 3208233d2500723e5594f3e7c70896ffeeef32b9c950ywan for i in xrange(linenum + 1, end_line): 3209233d2500723e5594f3e7c70896ffeeef32b9c950ywan expression += lines[i] 3210233d2500723e5594f3e7c70896ffeeef32b9c950ywan expression += last_line[0:end_pos - 1] 3211233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3212233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Parse expression so that we can take parentheses into account. 3213233d2500723e5594f3e7c70896ffeeef32b9c950ywan # This avoids false positives for inputs like "CHECK((a < 4) == b)", 3214233d2500723e5594f3e7c70896ffeeef32b9c950ywan # which is not replaceable by CHECK_LE. 3215233d2500723e5594f3e7c70896ffeeef32b9c950ywan lhs = '' 3216233d2500723e5594f3e7c70896ffeeef32b9c950ywan rhs = '' 3217233d2500723e5594f3e7c70896ffeeef32b9c950ywan operator = None 3218233d2500723e5594f3e7c70896ffeeef32b9c950ywan while expression: 3219233d2500723e5594f3e7c70896ffeeef32b9c950ywan matched = Match(r'^\s*(<<|<<=|>>|>>=|->\*|->|&&|\|\||' 3220233d2500723e5594f3e7c70896ffeeef32b9c950ywan r'==|!=|>=|>|<=|<|\()(.*)$', expression) 3221233d2500723e5594f3e7c70896ffeeef32b9c950ywan if matched: 3222233d2500723e5594f3e7c70896ffeeef32b9c950ywan token = matched.group(1) 3223233d2500723e5594f3e7c70896ffeeef32b9c950ywan if token == '(': 3224233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Parenthesized operand 3225233d2500723e5594f3e7c70896ffeeef32b9c950ywan expression = matched.group(2) 3226233d2500723e5594f3e7c70896ffeeef32b9c950ywan (end, _) = FindEndOfExpressionInLine(expression, 0, 1, '(', ')') 3227233d2500723e5594f3e7c70896ffeeef32b9c950ywan if end < 0: 3228233d2500723e5594f3e7c70896ffeeef32b9c950ywan return # Unmatched parenthesis 3229233d2500723e5594f3e7c70896ffeeef32b9c950ywan lhs += '(' + expression[0:end] 3230233d2500723e5594f3e7c70896ffeeef32b9c950ywan expression = expression[end:] 3231233d2500723e5594f3e7c70896ffeeef32b9c950ywan elif token in ('&&', '||'): 3232233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Logical and/or operators. This means the expression 3233233d2500723e5594f3e7c70896ffeeef32b9c950ywan # contains more than one term, for example: 3234233d2500723e5594f3e7c70896ffeeef32b9c950ywan # CHECK(42 < a && a < b); 3235233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 3236233d2500723e5594f3e7c70896ffeeef32b9c950ywan # These are not replaceable with CHECK_LE, so bail out early. 3237233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 3238233d2500723e5594f3e7c70896ffeeef32b9c950ywan elif token in ('<<', '<<=', '>>', '>>=', '->*', '->'): 3239233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Non-relational operator 3240233d2500723e5594f3e7c70896ffeeef32b9c950ywan lhs += token 3241233d2500723e5594f3e7c70896ffeeef32b9c950ywan expression = matched.group(2) 3242233d2500723e5594f3e7c70896ffeeef32b9c950ywan else: 3243233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Relational operator 3244233d2500723e5594f3e7c70896ffeeef32b9c950ywan operator = token 3245233d2500723e5594f3e7c70896ffeeef32b9c950ywan rhs = matched.group(2) 3246233d2500723e5594f3e7c70896ffeeef32b9c950ywan break 3247233d2500723e5594f3e7c70896ffeeef32b9c950ywan else: 3248233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Unparenthesized operand. Instead of appending to lhs one character 3249233d2500723e5594f3e7c70896ffeeef32b9c950ywan # at a time, we do another regular expression match to consume several 3250233d2500723e5594f3e7c70896ffeeef32b9c950ywan # characters at once if possible. Trivial benchmark shows that this 3251233d2500723e5594f3e7c70896ffeeef32b9c950ywan # is more efficient when the operands are longer than a single 3252233d2500723e5594f3e7c70896ffeeef32b9c950ywan # character, which is generally the case. 3253233d2500723e5594f3e7c70896ffeeef32b9c950ywan matched = Match(r'^([^-=!<>()&|]+)(.*)$', expression) 3254233d2500723e5594f3e7c70896ffeeef32b9c950ywan if not matched: 3255233d2500723e5594f3e7c70896ffeeef32b9c950ywan matched = Match(r'^(\s*\S)(.*)$', expression) 3256233d2500723e5594f3e7c70896ffeeef32b9c950ywan if not matched: 3257233d2500723e5594f3e7c70896ffeeef32b9c950ywan break 3258233d2500723e5594f3e7c70896ffeeef32b9c950ywan lhs += matched.group(1) 3259233d2500723e5594f3e7c70896ffeeef32b9c950ywan expression = matched.group(2) 3260233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3261233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Only apply checks if we got all parts of the boolean expression 3262233d2500723e5594f3e7c70896ffeeef32b9c950ywan if not (lhs and operator and rhs): 3263233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 3264233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3265233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Check that rhs do not contain logical operators. We already know 3266233d2500723e5594f3e7c70896ffeeef32b9c950ywan # that lhs is fine since the loop above parses out && and ||. 3267233d2500723e5594f3e7c70896ffeeef32b9c950ywan if rhs.find('&&') > -1 or rhs.find('||') > -1: 3268233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 3269233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3270233d2500723e5594f3e7c70896ffeeef32b9c950ywan # At least one of the operands must be a constant literal. This is 3271233d2500723e5594f3e7c70896ffeeef32b9c950ywan # to avoid suggesting replacements for unprintable things like 3272233d2500723e5594f3e7c70896ffeeef32b9c950ywan # CHECK(variable != iterator) 3273233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 3274233d2500723e5594f3e7c70896ffeeef32b9c950ywan # The following pattern matches decimal, hex integers, strings, and 3275233d2500723e5594f3e7c70896ffeeef32b9c950ywan # characters (in that order). 3276233d2500723e5594f3e7c70896ffeeef32b9c950ywan lhs = lhs.strip() 3277233d2500723e5594f3e7c70896ffeeef32b9c950ywan rhs = rhs.strip() 3278233d2500723e5594f3e7c70896ffeeef32b9c950ywan match_constant = r'^([-+]?(\d+|0[xX][0-9a-fA-F]+)[lLuU]{0,3}|".*"|\'.*\')$' 3279233d2500723e5594f3e7c70896ffeeef32b9c950ywan if Match(match_constant, lhs) or Match(match_constant, rhs): 3280233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Note: since we know both lhs and rhs, we can provide a more 3281233d2500723e5594f3e7c70896ffeeef32b9c950ywan # descriptive error message like: 3282233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Consider using CHECK_EQ(x, 42) instead of CHECK(x == 42) 3283233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Instead of: 3284233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Consider using CHECK_EQ instead of CHECK(a == b) 3285233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 3286233d2500723e5594f3e7c70896ffeeef32b9c950ywan # We are still keeping the less descriptive message because if lhs 3287233d2500723e5594f3e7c70896ffeeef32b9c950ywan # or rhs gets long, the error message might become unreadable. 3288233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'readability/check', 2, 3289233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Consider using %s instead of %s(a %s b)' % ( 3290233d2500723e5594f3e7c70896ffeeef32b9c950ywan _CHECK_REPLACEMENT[check_macro][operator], 3291233d2500723e5594f3e7c70896ffeeef32b9c950ywan check_macro, operator)) 3292233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3293233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3294233d2500723e5594f3e7c70896ffeeef32b9c950ywandef CheckAltTokens(filename, clean_lines, linenum, error): 3295233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Check alternative keywords being used in boolean expressions. 3296233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3297233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 3298233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename: The name of the current file. 3299233d2500723e5594f3e7c70896ffeeef32b9c950ywan clean_lines: A CleansedLines instance containing the file. 3300233d2500723e5594f3e7c70896ffeeef32b9c950ywan linenum: The number of the line to check. 3301233d2500723e5594f3e7c70896ffeeef32b9c950ywan error: The function to call with any errors found. 3302233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 3303233d2500723e5594f3e7c70896ffeeef32b9c950ywan line = clean_lines.elided[linenum] 3304233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3305233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Avoid preprocessor lines 3306233d2500723e5594f3e7c70896ffeeef32b9c950ywan if Match(r'^\s*#', line): 3307233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 3308233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3309233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Last ditch effort to avoid multi-line comments. This will not help 3310233d2500723e5594f3e7c70896ffeeef32b9c950ywan # if the comment started before the current line or ended after the 3311233d2500723e5594f3e7c70896ffeeef32b9c950ywan # current line, but it catches most of the false positives. At least, 3312233d2500723e5594f3e7c70896ffeeef32b9c950ywan # it provides a way to workaround this warning for people who use 3313233d2500723e5594f3e7c70896ffeeef32b9c950ywan # multi-line comments in preprocessor macros. 3314233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 3315233d2500723e5594f3e7c70896ffeeef32b9c950ywan # TODO(unknown): remove this once cpplint has better support for 3316233d2500723e5594f3e7c70896ffeeef32b9c950ywan # multi-line comments. 3317233d2500723e5594f3e7c70896ffeeef32b9c950ywan if line.find('/*') >= 0 or line.find('*/') >= 0: 3318233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 3319233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3320233d2500723e5594f3e7c70896ffeeef32b9c950ywan for match in _ALT_TOKEN_REPLACEMENT_PATTERN.finditer(line): 3321233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'readability/alt_tokens', 2, 3322233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Use operator %s instead of %s' % ( 3323233d2500723e5594f3e7c70896ffeeef32b9c950ywan _ALT_TOKEN_REPLACEMENT[match.group(1)], match.group(1))) 3324233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3325233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3326233d2500723e5594f3e7c70896ffeeef32b9c950ywandef GetLineWidth(line): 3327233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Determines the width of the line in column positions. 3328233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3329233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 3330233d2500723e5594f3e7c70896ffeeef32b9c950ywan line: A string, which may be a Unicode string. 3331233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3332233d2500723e5594f3e7c70896ffeeef32b9c950ywan Returns: 3333233d2500723e5594f3e7c70896ffeeef32b9c950ywan The width of the line in column positions, accounting for Unicode 3334233d2500723e5594f3e7c70896ffeeef32b9c950ywan combining characters and wide characters. 3335233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 3336233d2500723e5594f3e7c70896ffeeef32b9c950ywan if isinstance(line, unicode): 3337233d2500723e5594f3e7c70896ffeeef32b9c950ywan width = 0 3338233d2500723e5594f3e7c70896ffeeef32b9c950ywan for uc in unicodedata.normalize('NFC', line): 3339233d2500723e5594f3e7c70896ffeeef32b9c950ywan if unicodedata.east_asian_width(uc) in ('W', 'F'): 3340233d2500723e5594f3e7c70896ffeeef32b9c950ywan width += 2 3341233d2500723e5594f3e7c70896ffeeef32b9c950ywan elif not unicodedata.combining(uc): 3342233d2500723e5594f3e7c70896ffeeef32b9c950ywan width += 1 3343233d2500723e5594f3e7c70896ffeeef32b9c950ywan return width 3344233d2500723e5594f3e7c70896ffeeef32b9c950ywan else: 3345233d2500723e5594f3e7c70896ffeeef32b9c950ywan return len(line) 3346233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3347233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3348233d2500723e5594f3e7c70896ffeeef32b9c950ywandef CheckStyle(filename, clean_lines, linenum, file_extension, nesting_state, 3349233d2500723e5594f3e7c70896ffeeef32b9c950ywan error): 3350233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Checks rules from the 'C++ style rules' section of cppguide.html. 3351233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3352233d2500723e5594f3e7c70896ffeeef32b9c950ywan Most of these rules are hard to test (naming, comment style), but we 3353233d2500723e5594f3e7c70896ffeeef32b9c950ywan do what we can. In particular we check for 2-space indents, line lengths, 3354233d2500723e5594f3e7c70896ffeeef32b9c950ywan tab usage, spaces inside code, etc. 3355233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3356233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 3357233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename: The name of the current file. 3358233d2500723e5594f3e7c70896ffeeef32b9c950ywan clean_lines: A CleansedLines instance containing the file. 3359233d2500723e5594f3e7c70896ffeeef32b9c950ywan linenum: The number of the line to check. 3360233d2500723e5594f3e7c70896ffeeef32b9c950ywan file_extension: The extension (without the dot) of the filename. 3361233d2500723e5594f3e7c70896ffeeef32b9c950ywan nesting_state: A _NestingState instance which maintains information about 3362233d2500723e5594f3e7c70896ffeeef32b9c950ywan the current stack of nested blocks being parsed. 3363233d2500723e5594f3e7c70896ffeeef32b9c950ywan error: The function to call with any errors found. 3364233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 3365233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3366233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Don't use "elided" lines here, otherwise we can't check commented lines. 3367233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Don't want to use "raw" either, because we don't want to check inside C++11 3368233d2500723e5594f3e7c70896ffeeef32b9c950ywan # raw strings, 3369233d2500723e5594f3e7c70896ffeeef32b9c950ywan raw_lines = clean_lines.lines_without_raw_strings 3370233d2500723e5594f3e7c70896ffeeef32b9c950ywan line = raw_lines[linenum] 3371233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3372233d2500723e5594f3e7c70896ffeeef32b9c950ywan if line.find('\t') != -1: 3373233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'whitespace/tab', 1, 3374233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Tab found; better to use spaces') 3375233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3376233d2500723e5594f3e7c70896ffeeef32b9c950ywan # One or three blank spaces at the beginning of the line is weird; it's 3377233d2500723e5594f3e7c70896ffeeef32b9c950ywan # hard to reconcile that with 2-space indents. 3378233d2500723e5594f3e7c70896ffeeef32b9c950ywan # NOTE: here are the conditions rob pike used for his tests. Mine aren't 3379233d2500723e5594f3e7c70896ffeeef32b9c950ywan # as sophisticated, but it may be worth becoming so: RLENGTH==initial_spaces 3380233d2500723e5594f3e7c70896ffeeef32b9c950ywan # if(RLENGTH > 20) complain = 0; 3381233d2500723e5594f3e7c70896ffeeef32b9c950ywan # if(match($0, " +(error|private|public|protected):")) complain = 0; 3382233d2500723e5594f3e7c70896ffeeef32b9c950ywan # if(match(prev, "&& *$")) complain = 0; 3383233d2500723e5594f3e7c70896ffeeef32b9c950ywan # if(match(prev, "\\|\\| *$")) complain = 0; 3384233d2500723e5594f3e7c70896ffeeef32b9c950ywan # if(match(prev, "[\",=><] *$")) complain = 0; 3385233d2500723e5594f3e7c70896ffeeef32b9c950ywan # if(match($0, " <<")) complain = 0; 3386233d2500723e5594f3e7c70896ffeeef32b9c950ywan # if(match(prev, " +for \\(")) complain = 0; 3387233d2500723e5594f3e7c70896ffeeef32b9c950ywan # if(prevodd && match(prevprev, " +for \\(")) complain = 0; 3388233d2500723e5594f3e7c70896ffeeef32b9c950ywan initial_spaces = 0 3389233d2500723e5594f3e7c70896ffeeef32b9c950ywan cleansed_line = clean_lines.elided[linenum] 3390233d2500723e5594f3e7c70896ffeeef32b9c950ywan while initial_spaces < len(line) and line[initial_spaces] == ' ': 3391233d2500723e5594f3e7c70896ffeeef32b9c950ywan initial_spaces += 1 3392233d2500723e5594f3e7c70896ffeeef32b9c950ywan if line and line[-1].isspace(): 3393233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'whitespace/end_of_line', 4, 3394233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Line ends in whitespace. Consider deleting these extra spaces.') 3395233d2500723e5594f3e7c70896ffeeef32b9c950ywan # There are certain situations we allow one space, notably for section labels 3396233d2500723e5594f3e7c70896ffeeef32b9c950ywan elif ((initial_spaces == 1 or initial_spaces == 3) and 3397233d2500723e5594f3e7c70896ffeeef32b9c950ywan not Match(r'\s*\w+\s*:\s*$', cleansed_line)): 3398233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'whitespace/indent', 3, 3399233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Weird number of spaces at line-start. ' 3400233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Are you using a 2-space indent?') 3401233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3402233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Check if the line is a header guard. 3403233d2500723e5594f3e7c70896ffeeef32b9c950ywan is_header_guard = False 3404233d2500723e5594f3e7c70896ffeeef32b9c950ywan if file_extension == 'h': 3405233d2500723e5594f3e7c70896ffeeef32b9c950ywan cppvar = GetHeaderGuardCPPVariable(filename) 3406233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (line.startswith('#ifndef %s' % cppvar) or 3407233d2500723e5594f3e7c70896ffeeef32b9c950ywan line.startswith('#define %s' % cppvar) or 3408233d2500723e5594f3e7c70896ffeeef32b9c950ywan line.startswith('#endif // %s' % cppvar)): 3409233d2500723e5594f3e7c70896ffeeef32b9c950ywan is_header_guard = True 3410233d2500723e5594f3e7c70896ffeeef32b9c950ywan # #include lines and header guards can be long, since there's no clean way to 3411233d2500723e5594f3e7c70896ffeeef32b9c950ywan # split them. 3412233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 3413233d2500723e5594f3e7c70896ffeeef32b9c950ywan # URLs can be long too. It's possible to split these, but it makes them 3414233d2500723e5594f3e7c70896ffeeef32b9c950ywan # harder to cut&paste. 3415233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 3416233d2500723e5594f3e7c70896ffeeef32b9c950ywan # The "$Id:...$" comment may also get very long without it being the 3417233d2500723e5594f3e7c70896ffeeef32b9c950ywan # developers fault. 3418233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (not line.startswith('#include') and not is_header_guard and 3419233d2500723e5594f3e7c70896ffeeef32b9c950ywan not Match(r'^\s*//.*http(s?)://\S*$', line) and 3420233d2500723e5594f3e7c70896ffeeef32b9c950ywan not Match(r'^// \$Id:.*#[0-9]+ \$$', line)): 3421233d2500723e5594f3e7c70896ffeeef32b9c950ywan line_width = GetLineWidth(line) 3422233d2500723e5594f3e7c70896ffeeef32b9c950ywan extended_length = int((_line_length * 1.25)) 3423233d2500723e5594f3e7c70896ffeeef32b9c950ywan if line_width > extended_length: 3424233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'whitespace/line_length', 4, 3425233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Lines should very rarely be longer than %i characters' % 3426233d2500723e5594f3e7c70896ffeeef32b9c950ywan extended_length) 3427233d2500723e5594f3e7c70896ffeeef32b9c950ywan elif line_width > _line_length: 3428233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'whitespace/line_length', 2, 3429233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Lines should be <= %i characters long' % _line_length) 3430233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3431233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (cleansed_line.count(';') > 1 and 3432233d2500723e5594f3e7c70896ffeeef32b9c950ywan # for loops are allowed two ;'s (and may run over two lines). 3433233d2500723e5594f3e7c70896ffeeef32b9c950ywan cleansed_line.find('for') == -1 and 3434233d2500723e5594f3e7c70896ffeeef32b9c950ywan (GetPreviousNonBlankLine(clean_lines, linenum)[0].find('for') == -1 or 3435233d2500723e5594f3e7c70896ffeeef32b9c950ywan GetPreviousNonBlankLine(clean_lines, linenum)[0].find(';') != -1) and 3436233d2500723e5594f3e7c70896ffeeef32b9c950ywan # It's ok to have many commands in a switch case that fits in 1 line 3437233d2500723e5594f3e7c70896ffeeef32b9c950ywan not ((cleansed_line.find('case ') != -1 or 3438233d2500723e5594f3e7c70896ffeeef32b9c950ywan cleansed_line.find('default:') != -1) and 3439233d2500723e5594f3e7c70896ffeeef32b9c950ywan cleansed_line.find('break;') != -1)): 3440233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'whitespace/newline', 0, 3441233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'More than one command on the same line') 3442233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3443233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Some more style checks 3444233d2500723e5594f3e7c70896ffeeef32b9c950ywan CheckBraces(filename, clean_lines, linenum, error) 3445233d2500723e5594f3e7c70896ffeeef32b9c950ywan CheckEmptyBlockBody(filename, clean_lines, linenum, error) 3446233d2500723e5594f3e7c70896ffeeef32b9c950ywan CheckAccess(filename, clean_lines, linenum, nesting_state, error) 3447233d2500723e5594f3e7c70896ffeeef32b9c950ywan CheckSpacing(filename, clean_lines, linenum, nesting_state, error) 3448233d2500723e5594f3e7c70896ffeeef32b9c950ywan CheckCheck(filename, clean_lines, linenum, error) 3449233d2500723e5594f3e7c70896ffeeef32b9c950ywan CheckAltTokens(filename, clean_lines, linenum, error) 3450233d2500723e5594f3e7c70896ffeeef32b9c950ywan classinfo = nesting_state.InnermostClass() 3451233d2500723e5594f3e7c70896ffeeef32b9c950ywan if classinfo: 3452233d2500723e5594f3e7c70896ffeeef32b9c950ywan CheckSectionSpacing(filename, clean_lines, classinfo, linenum, error) 3453233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3454233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3455233d2500723e5594f3e7c70896ffeeef32b9c950ywan_RE_PATTERN_INCLUDE_NEW_STYLE = re.compile(r'#include +"[^/]+\.h"') 3456233d2500723e5594f3e7c70896ffeeef32b9c950ywan_RE_PATTERN_INCLUDE = re.compile(r'^\s*#\s*include\s*([<"])([^>"]*)[>"].*$') 3457233d2500723e5594f3e7c70896ffeeef32b9c950ywan# Matches the first component of a filename delimited by -s and _s. That is: 3458233d2500723e5594f3e7c70896ffeeef32b9c950ywan# _RE_FIRST_COMPONENT.match('foo').group(0) == 'foo' 3459233d2500723e5594f3e7c70896ffeeef32b9c950ywan# _RE_FIRST_COMPONENT.match('foo.cc').group(0) == 'foo' 3460233d2500723e5594f3e7c70896ffeeef32b9c950ywan# _RE_FIRST_COMPONENT.match('foo-bar_baz.cc').group(0) == 'foo' 3461233d2500723e5594f3e7c70896ffeeef32b9c950ywan# _RE_FIRST_COMPONENT.match('foo_bar-baz.cc').group(0) == 'foo' 3462233d2500723e5594f3e7c70896ffeeef32b9c950ywan_RE_FIRST_COMPONENT = re.compile(r'^[^-_.]+') 3463233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3464233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3465233d2500723e5594f3e7c70896ffeeef32b9c950ywandef _DropCommonSuffixes(filename): 3466233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Drops common suffixes like _test.cc or -inl.h from filename. 3467233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3468233d2500723e5594f3e7c70896ffeeef32b9c950ywan For example: 3469233d2500723e5594f3e7c70896ffeeef32b9c950ywan >>> _DropCommonSuffixes('foo/foo-inl.h') 3470233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'foo/foo' 3471233d2500723e5594f3e7c70896ffeeef32b9c950ywan >>> _DropCommonSuffixes('foo/bar/foo.cc') 3472233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'foo/bar/foo' 3473233d2500723e5594f3e7c70896ffeeef32b9c950ywan >>> _DropCommonSuffixes('foo/foo_internal.h') 3474233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'foo/foo' 3475233d2500723e5594f3e7c70896ffeeef32b9c950ywan >>> _DropCommonSuffixes('foo/foo_unusualinternal.h') 3476233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'foo/foo_unusualinternal' 3477233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3478233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 3479233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename: The input filename. 3480233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3481233d2500723e5594f3e7c70896ffeeef32b9c950ywan Returns: 3482233d2500723e5594f3e7c70896ffeeef32b9c950ywan The filename with the common suffix removed. 3483233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 3484233d2500723e5594f3e7c70896ffeeef32b9c950ywan for suffix in ('test.cc', 'regtest.cc', 'unittest.cc', 3485233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'inl.h', 'impl.h', 'internal.h'): 3486233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (filename.endswith(suffix) and len(filename) > len(suffix) and 3487233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename[-len(suffix) - 1] in ('-', '_')): 3488233d2500723e5594f3e7c70896ffeeef32b9c950ywan return filename[:-len(suffix) - 1] 3489233d2500723e5594f3e7c70896ffeeef32b9c950ywan return os.path.splitext(filename)[0] 3490233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3491233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3492233d2500723e5594f3e7c70896ffeeef32b9c950ywandef _IsTestFilename(filename): 3493233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Determines if the given filename has a suffix that identifies it as a test. 3494233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3495233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 3496233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename: The input filename. 3497233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3498233d2500723e5594f3e7c70896ffeeef32b9c950ywan Returns: 3499233d2500723e5594f3e7c70896ffeeef32b9c950ywan True if 'filename' looks like a test, False otherwise. 3500233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 3501233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (filename.endswith('_test.cc') or 3502233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename.endswith('_unittest.cc') or 3503233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename.endswith('_regtest.cc')): 3504233d2500723e5594f3e7c70896ffeeef32b9c950ywan return True 3505233d2500723e5594f3e7c70896ffeeef32b9c950ywan else: 3506233d2500723e5594f3e7c70896ffeeef32b9c950ywan return False 3507233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3508233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3509233d2500723e5594f3e7c70896ffeeef32b9c950ywandef _ClassifyInclude(fileinfo, include, is_system): 3510233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Figures out what kind of header 'include' is. 3511233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3512233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 3513233d2500723e5594f3e7c70896ffeeef32b9c950ywan fileinfo: The current file cpplint is running over. A FileInfo instance. 3514233d2500723e5594f3e7c70896ffeeef32b9c950ywan include: The path to a #included file. 3515233d2500723e5594f3e7c70896ffeeef32b9c950ywan is_system: True if the #include used <> rather than "". 3516233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3517233d2500723e5594f3e7c70896ffeeef32b9c950ywan Returns: 3518233d2500723e5594f3e7c70896ffeeef32b9c950ywan One of the _XXX_HEADER constants. 3519233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3520233d2500723e5594f3e7c70896ffeeef32b9c950ywan For example: 3521233d2500723e5594f3e7c70896ffeeef32b9c950ywan >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'stdio.h', True) 3522233d2500723e5594f3e7c70896ffeeef32b9c950ywan _C_SYS_HEADER 3523233d2500723e5594f3e7c70896ffeeef32b9c950ywan >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'string', True) 3524233d2500723e5594f3e7c70896ffeeef32b9c950ywan _CPP_SYS_HEADER 3525233d2500723e5594f3e7c70896ffeeef32b9c950ywan >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'foo/foo.h', False) 3526233d2500723e5594f3e7c70896ffeeef32b9c950ywan _LIKELY_MY_HEADER 3527233d2500723e5594f3e7c70896ffeeef32b9c950ywan >>> _ClassifyInclude(FileInfo('foo/foo_unknown_extension.cc'), 3528233d2500723e5594f3e7c70896ffeeef32b9c950ywan ... 'bar/foo_other_ext.h', False) 3529233d2500723e5594f3e7c70896ffeeef32b9c950ywan _POSSIBLE_MY_HEADER 3530233d2500723e5594f3e7c70896ffeeef32b9c950ywan >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'foo/bar.h', False) 3531233d2500723e5594f3e7c70896ffeeef32b9c950ywan _OTHER_HEADER 3532233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 3533233d2500723e5594f3e7c70896ffeeef32b9c950ywan # This is a list of all standard c++ header files, except 3534233d2500723e5594f3e7c70896ffeeef32b9c950ywan # those already checked for above. 3535233d2500723e5594f3e7c70896ffeeef32b9c950ywan is_cpp_h = include in _CPP_HEADERS 3536233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3537233d2500723e5594f3e7c70896ffeeef32b9c950ywan if is_system: 3538233d2500723e5594f3e7c70896ffeeef32b9c950ywan if is_cpp_h: 3539233d2500723e5594f3e7c70896ffeeef32b9c950ywan return _CPP_SYS_HEADER 3540233d2500723e5594f3e7c70896ffeeef32b9c950ywan else: 3541233d2500723e5594f3e7c70896ffeeef32b9c950ywan return _C_SYS_HEADER 3542233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3543233d2500723e5594f3e7c70896ffeeef32b9c950ywan # If the target file and the include we're checking share a 3544233d2500723e5594f3e7c70896ffeeef32b9c950ywan # basename when we drop common extensions, and the include 3545233d2500723e5594f3e7c70896ffeeef32b9c950ywan # lives in . , then it's likely to be owned by the target file. 3546233d2500723e5594f3e7c70896ffeeef32b9c950ywan target_dir, target_base = ( 3547233d2500723e5594f3e7c70896ffeeef32b9c950ywan os.path.split(_DropCommonSuffixes(fileinfo.RepositoryName()))) 3548233d2500723e5594f3e7c70896ffeeef32b9c950ywan include_dir, include_base = os.path.split(_DropCommonSuffixes(include)) 3549233d2500723e5594f3e7c70896ffeeef32b9c950ywan if target_base == include_base and ( 3550233d2500723e5594f3e7c70896ffeeef32b9c950ywan include_dir == target_dir or 3551233d2500723e5594f3e7c70896ffeeef32b9c950ywan include_dir == os.path.normpath(target_dir + '/../public')): 3552233d2500723e5594f3e7c70896ffeeef32b9c950ywan return _LIKELY_MY_HEADER 3553233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3554233d2500723e5594f3e7c70896ffeeef32b9c950ywan # If the target and include share some initial basename 3555233d2500723e5594f3e7c70896ffeeef32b9c950ywan # component, it's possible the target is implementing the 3556233d2500723e5594f3e7c70896ffeeef32b9c950ywan # include, so it's allowed to be first, but we'll never 3557233d2500723e5594f3e7c70896ffeeef32b9c950ywan # complain if it's not there. 3558233d2500723e5594f3e7c70896ffeeef32b9c950ywan target_first_component = _RE_FIRST_COMPONENT.match(target_base) 3559233d2500723e5594f3e7c70896ffeeef32b9c950ywan include_first_component = _RE_FIRST_COMPONENT.match(include_base) 3560233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (target_first_component and include_first_component and 3561233d2500723e5594f3e7c70896ffeeef32b9c950ywan target_first_component.group(0) == 3562233d2500723e5594f3e7c70896ffeeef32b9c950ywan include_first_component.group(0)): 3563233d2500723e5594f3e7c70896ffeeef32b9c950ywan return _POSSIBLE_MY_HEADER 3564233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3565233d2500723e5594f3e7c70896ffeeef32b9c950ywan return _OTHER_HEADER 3566233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3567233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3568233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3569233d2500723e5594f3e7c70896ffeeef32b9c950ywandef CheckIncludeLine(filename, clean_lines, linenum, include_state, error): 3570233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Check rules that are applicable to #include lines. 3571233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3572233d2500723e5594f3e7c70896ffeeef32b9c950ywan Strings on #include lines are NOT removed from elided line, to make 3573233d2500723e5594f3e7c70896ffeeef32b9c950ywan certain tasks easier. However, to prevent false positives, checks 3574233d2500723e5594f3e7c70896ffeeef32b9c950ywan applicable to #include lines in CheckLanguage must be put here. 3575233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3576233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 3577233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename: The name of the current file. 3578233d2500723e5594f3e7c70896ffeeef32b9c950ywan clean_lines: A CleansedLines instance containing the file. 3579233d2500723e5594f3e7c70896ffeeef32b9c950ywan linenum: The number of the line to check. 3580233d2500723e5594f3e7c70896ffeeef32b9c950ywan include_state: An _IncludeState instance in which the headers are inserted. 3581233d2500723e5594f3e7c70896ffeeef32b9c950ywan error: The function to call with any errors found. 3582233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 3583233d2500723e5594f3e7c70896ffeeef32b9c950ywan fileinfo = FileInfo(filename) 3584233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3585233d2500723e5594f3e7c70896ffeeef32b9c950ywan line = clean_lines.lines[linenum] 3586233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3587233d2500723e5594f3e7c70896ffeeef32b9c950ywan # "include" should use the new style "foo/bar.h" instead of just "bar.h" 3588233d2500723e5594f3e7c70896ffeeef32b9c950ywan if _RE_PATTERN_INCLUDE_NEW_STYLE.search(line): 3589233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'build/include', 4, 3590233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Include the directory when naming .h files') 3591233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3592233d2500723e5594f3e7c70896ffeeef32b9c950ywan # we shouldn't include a file more than once. actually, there are a 3593233d2500723e5594f3e7c70896ffeeef32b9c950ywan # handful of instances where doing so is okay, but in general it's 3594233d2500723e5594f3e7c70896ffeeef32b9c950ywan # not. 3595233d2500723e5594f3e7c70896ffeeef32b9c950ywan match = _RE_PATTERN_INCLUDE.search(line) 3596233d2500723e5594f3e7c70896ffeeef32b9c950ywan if match: 3597233d2500723e5594f3e7c70896ffeeef32b9c950ywan include = match.group(2) 3598233d2500723e5594f3e7c70896ffeeef32b9c950ywan is_system = (match.group(1) == '<') 3599233d2500723e5594f3e7c70896ffeeef32b9c950ywan if include in include_state: 3600233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'build/include', 4, 3601233d2500723e5594f3e7c70896ffeeef32b9c950ywan '"%s" already included at %s:%s' % 3602233d2500723e5594f3e7c70896ffeeef32b9c950ywan (include, filename, include_state[include])) 3603233d2500723e5594f3e7c70896ffeeef32b9c950ywan else: 3604233d2500723e5594f3e7c70896ffeeef32b9c950ywan include_state[include] = linenum 3605233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3606233d2500723e5594f3e7c70896ffeeef32b9c950ywan # We want to ensure that headers appear in the right order: 3607233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 1) for foo.cc, foo.h (preferred location) 3608233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 2) c system files 3609233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 3) cpp system files 3610233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 4) for foo.cc, foo.h (deprecated location) 3611233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 5) other google headers 3612233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 3613233d2500723e5594f3e7c70896ffeeef32b9c950ywan # We classify each include statement as one of those 5 types 3614233d2500723e5594f3e7c70896ffeeef32b9c950ywan # using a number of techniques. The include_state object keeps 3615233d2500723e5594f3e7c70896ffeeef32b9c950ywan # track of the highest type seen, and complains if we see a 3616233d2500723e5594f3e7c70896ffeeef32b9c950ywan # lower type after that. 3617233d2500723e5594f3e7c70896ffeeef32b9c950ywan error_message = include_state.CheckNextIncludeOrder( 3618233d2500723e5594f3e7c70896ffeeef32b9c950ywan _ClassifyInclude(fileinfo, include, is_system)) 3619233d2500723e5594f3e7c70896ffeeef32b9c950ywan if error_message: 3620233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'build/include_order', 4, 3621233d2500723e5594f3e7c70896ffeeef32b9c950ywan '%s. Should be: %s.h, c system, c++ system, other.' % 3622233d2500723e5594f3e7c70896ffeeef32b9c950ywan (error_message, fileinfo.BaseName())) 3623233d2500723e5594f3e7c70896ffeeef32b9c950ywan canonical_include = include_state.CanonicalizeAlphabeticalOrder(include) 3624233d2500723e5594f3e7c70896ffeeef32b9c950ywan if not include_state.IsInAlphabeticalOrder( 3625233d2500723e5594f3e7c70896ffeeef32b9c950ywan clean_lines, linenum, canonical_include): 3626233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'build/include_alpha', 4, 3627233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Include "%s" not in alphabetical order' % include) 3628233d2500723e5594f3e7c70896ffeeef32b9c950ywan include_state.SetLastHeader(canonical_include) 3629233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3630233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Look for any of the stream classes that are part of standard C++. 3631233d2500723e5594f3e7c70896ffeeef32b9c950ywan match = _RE_PATTERN_INCLUDE.match(line) 3632233d2500723e5594f3e7c70896ffeeef32b9c950ywan if match: 3633233d2500723e5594f3e7c70896ffeeef32b9c950ywan include = match.group(2) 3634233d2500723e5594f3e7c70896ffeeef32b9c950ywan if Match(r'(f|ind|io|i|o|parse|pf|stdio|str|)?stream$', include): 3635233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Many unit tests use cout, so we exempt them. 3636233d2500723e5594f3e7c70896ffeeef32b9c950ywan if not _IsTestFilename(filename): 3637233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'readability/streams', 3, 3638233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Streams are highly discouraged.') 3639233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3640233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3641233d2500723e5594f3e7c70896ffeeef32b9c950ywandef _GetTextInside(text, start_pattern): 3642233d2500723e5594f3e7c70896ffeeef32b9c950ywan r"""Retrieves all the text between matching open and close parentheses. 3643233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3644233d2500723e5594f3e7c70896ffeeef32b9c950ywan Given a string of lines and a regular expression string, retrieve all the text 3645233d2500723e5594f3e7c70896ffeeef32b9c950ywan following the expression and between opening punctuation symbols like 3646233d2500723e5594f3e7c70896ffeeef32b9c950ywan (, [, or {, and the matching close-punctuation symbol. This properly nested 3647233d2500723e5594f3e7c70896ffeeef32b9c950ywan occurrences of the punctuations, so for the text like 3648233d2500723e5594f3e7c70896ffeeef32b9c950ywan printf(a(), b(c())); 3649233d2500723e5594f3e7c70896ffeeef32b9c950ywan a call to _GetTextInside(text, r'printf\(') will return 'a(), b(c())'. 3650233d2500723e5594f3e7c70896ffeeef32b9c950ywan start_pattern must match string having an open punctuation symbol at the end. 3651233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3652233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 3653233d2500723e5594f3e7c70896ffeeef32b9c950ywan text: The lines to extract text. Its comments and strings must be elided. 3654233d2500723e5594f3e7c70896ffeeef32b9c950ywan It can be single line and can span multiple lines. 3655233d2500723e5594f3e7c70896ffeeef32b9c950ywan start_pattern: The regexp string indicating where to start extracting 3656233d2500723e5594f3e7c70896ffeeef32b9c950ywan the text. 3657233d2500723e5594f3e7c70896ffeeef32b9c950ywan Returns: 3658233d2500723e5594f3e7c70896ffeeef32b9c950ywan The extracted text. 3659233d2500723e5594f3e7c70896ffeeef32b9c950ywan None if either the opening string or ending punctuation could not be found. 3660233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 3661233d2500723e5594f3e7c70896ffeeef32b9c950ywan # TODO(sugawarayu): Audit cpplint.py to see what places could be profitably 3662233d2500723e5594f3e7c70896ffeeef32b9c950ywan # rewritten to use _GetTextInside (and use inferior regexp matching today). 3663233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3664233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Give opening punctuations to get the matching close-punctuations. 3665233d2500723e5594f3e7c70896ffeeef32b9c950ywan matching_punctuation = {'(': ')', '{': '}', '[': ']'} 3666233d2500723e5594f3e7c70896ffeeef32b9c950ywan closing_punctuation = set(matching_punctuation.itervalues()) 3667233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3668233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Find the position to start extracting text. 3669233d2500723e5594f3e7c70896ffeeef32b9c950ywan match = re.search(start_pattern, text, re.M) 3670233d2500723e5594f3e7c70896ffeeef32b9c950ywan if not match: # start_pattern not found in text. 3671233d2500723e5594f3e7c70896ffeeef32b9c950ywan return None 3672233d2500723e5594f3e7c70896ffeeef32b9c950ywan start_position = match.end(0) 3673233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3674233d2500723e5594f3e7c70896ffeeef32b9c950ywan assert start_position > 0, ( 3675233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'start_pattern must ends with an opening punctuation.') 3676233d2500723e5594f3e7c70896ffeeef32b9c950ywan assert text[start_position - 1] in matching_punctuation, ( 3677233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'start_pattern must ends with an opening punctuation.') 3678233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Stack of closing punctuations we expect to have in text after position. 3679233d2500723e5594f3e7c70896ffeeef32b9c950ywan punctuation_stack = [matching_punctuation[text[start_position - 1]]] 3680233d2500723e5594f3e7c70896ffeeef32b9c950ywan position = start_position 3681233d2500723e5594f3e7c70896ffeeef32b9c950ywan while punctuation_stack and position < len(text): 3682233d2500723e5594f3e7c70896ffeeef32b9c950ywan if text[position] == punctuation_stack[-1]: 3683233d2500723e5594f3e7c70896ffeeef32b9c950ywan punctuation_stack.pop() 3684233d2500723e5594f3e7c70896ffeeef32b9c950ywan elif text[position] in closing_punctuation: 3685233d2500723e5594f3e7c70896ffeeef32b9c950ywan # A closing punctuation without matching opening punctuations. 3686233d2500723e5594f3e7c70896ffeeef32b9c950ywan return None 3687233d2500723e5594f3e7c70896ffeeef32b9c950ywan elif text[position] in matching_punctuation: 3688233d2500723e5594f3e7c70896ffeeef32b9c950ywan punctuation_stack.append(matching_punctuation[text[position]]) 3689233d2500723e5594f3e7c70896ffeeef32b9c950ywan position += 1 3690233d2500723e5594f3e7c70896ffeeef32b9c950ywan if punctuation_stack: 3691233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Opening punctuations left without matching close-punctuations. 3692233d2500723e5594f3e7c70896ffeeef32b9c950ywan return None 3693233d2500723e5594f3e7c70896ffeeef32b9c950ywan # punctuations match. 3694233d2500723e5594f3e7c70896ffeeef32b9c950ywan return text[start_position:position - 1] 3695233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3696233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3697233d2500723e5594f3e7c70896ffeeef32b9c950ywan# Patterns for matching call-by-reference parameters. 3698233d2500723e5594f3e7c70896ffeeef32b9c950ywan# 3699233d2500723e5594f3e7c70896ffeeef32b9c950ywan# Supports nested templates up to 2 levels deep using this messy pattern: 3700233d2500723e5594f3e7c70896ffeeef32b9c950ywan# < (?: < (?: < [^<>]* 3701233d2500723e5594f3e7c70896ffeeef32b9c950ywan# > 3702233d2500723e5594f3e7c70896ffeeef32b9c950ywan# | [^<>] )* 3703233d2500723e5594f3e7c70896ffeeef32b9c950ywan# > 3704233d2500723e5594f3e7c70896ffeeef32b9c950ywan# | [^<>] )* 3705233d2500723e5594f3e7c70896ffeeef32b9c950ywan# > 3706233d2500723e5594f3e7c70896ffeeef32b9c950ywan_RE_PATTERN_IDENT = r'[_a-zA-Z]\w*' # =~ [[:alpha:]][[:alnum:]]* 3707233d2500723e5594f3e7c70896ffeeef32b9c950ywan_RE_PATTERN_TYPE = ( 3708233d2500723e5594f3e7c70896ffeeef32b9c950ywan r'(?:const\s+)?(?:typename\s+|class\s+|struct\s+|union\s+|enum\s+)?' 3709233d2500723e5594f3e7c70896ffeeef32b9c950ywan r'(?:\w|' 3710233d2500723e5594f3e7c70896ffeeef32b9c950ywan r'\s*<(?:<(?:<[^<>]*>|[^<>])*>|[^<>])*>|' 3711233d2500723e5594f3e7c70896ffeeef32b9c950ywan r'::)+') 3712233d2500723e5594f3e7c70896ffeeef32b9c950ywan# A call-by-reference parameter ends with '& identifier'. 3713233d2500723e5594f3e7c70896ffeeef32b9c950ywan_RE_PATTERN_REF_PARAM = re.compile( 3714233d2500723e5594f3e7c70896ffeeef32b9c950ywan r'(' + _RE_PATTERN_TYPE + r'(?:\s*(?:\bconst\b|[*]))*\s*' 3715233d2500723e5594f3e7c70896ffeeef32b9c950ywan r'&\s*' + _RE_PATTERN_IDENT + r')\s*(?:=[^,()]+)?[,)]') 3716233d2500723e5594f3e7c70896ffeeef32b9c950ywan# A call-by-const-reference parameter either ends with 'const& identifier' 3717233d2500723e5594f3e7c70896ffeeef32b9c950ywan# or looks like 'const type& identifier' when 'type' is atomic. 3718233d2500723e5594f3e7c70896ffeeef32b9c950ywan_RE_PATTERN_CONST_REF_PARAM = ( 3719233d2500723e5594f3e7c70896ffeeef32b9c950ywan r'(?:.*\s*\bconst\s*&\s*' + _RE_PATTERN_IDENT + 3720233d2500723e5594f3e7c70896ffeeef32b9c950ywan r'|const\s+' + _RE_PATTERN_TYPE + r'\s*&\s*' + _RE_PATTERN_IDENT + r')') 3721233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3722233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3723233d2500723e5594f3e7c70896ffeeef32b9c950ywandef CheckLanguage(filename, clean_lines, linenum, file_extension, 3724233d2500723e5594f3e7c70896ffeeef32b9c950ywan include_state, nesting_state, error): 3725233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Checks rules from the 'C++ language rules' section of cppguide.html. 3726233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3727233d2500723e5594f3e7c70896ffeeef32b9c950ywan Some of these rules are hard to test (function overloading, using 3728233d2500723e5594f3e7c70896ffeeef32b9c950ywan uint32 inappropriately), but we do the best we can. 3729233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3730233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 3731233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename: The name of the current file. 3732233d2500723e5594f3e7c70896ffeeef32b9c950ywan clean_lines: A CleansedLines instance containing the file. 3733233d2500723e5594f3e7c70896ffeeef32b9c950ywan linenum: The number of the line to check. 3734233d2500723e5594f3e7c70896ffeeef32b9c950ywan file_extension: The extension (without the dot) of the filename. 3735233d2500723e5594f3e7c70896ffeeef32b9c950ywan include_state: An _IncludeState instance in which the headers are inserted. 3736233d2500723e5594f3e7c70896ffeeef32b9c950ywan nesting_state: A _NestingState instance which maintains information about 3737233d2500723e5594f3e7c70896ffeeef32b9c950ywan the current stack of nested blocks being parsed. 3738233d2500723e5594f3e7c70896ffeeef32b9c950ywan error: The function to call with any errors found. 3739233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 3740233d2500723e5594f3e7c70896ffeeef32b9c950ywan # If the line is empty or consists of entirely a comment, no need to 3741233d2500723e5594f3e7c70896ffeeef32b9c950ywan # check it. 3742233d2500723e5594f3e7c70896ffeeef32b9c950ywan line = clean_lines.elided[linenum] 3743233d2500723e5594f3e7c70896ffeeef32b9c950ywan if not line: 3744233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 3745233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3746233d2500723e5594f3e7c70896ffeeef32b9c950ywan match = _RE_PATTERN_INCLUDE.search(line) 3747233d2500723e5594f3e7c70896ffeeef32b9c950ywan if match: 3748233d2500723e5594f3e7c70896ffeeef32b9c950ywan CheckIncludeLine(filename, clean_lines, linenum, include_state, error) 3749233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 3750233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3751233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Reset include state across preprocessor directives. This is meant 3752233d2500723e5594f3e7c70896ffeeef32b9c950ywan # to silence warnings for conditional includes. 3753233d2500723e5594f3e7c70896ffeeef32b9c950ywan if Match(r'^\s*#\s*(?:ifdef|elif|else|endif)\b', line): 3754233d2500723e5594f3e7c70896ffeeef32b9c950ywan include_state.ResetSection() 3755233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3756233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Make Windows paths like Unix. 3757233d2500723e5594f3e7c70896ffeeef32b9c950ywan fullname = os.path.abspath(filename).replace('\\', '/') 3758233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3759233d2500723e5594f3e7c70896ffeeef32b9c950ywan # TODO(unknown): figure out if they're using default arguments in fn proto. 3760233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3761233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Check to see if they're using an conversion function cast. 3762233d2500723e5594f3e7c70896ffeeef32b9c950ywan # I just try to capture the most common basic types, though there are more. 3763233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Parameterless conversion functions, such as bool(), are allowed as they are 3764233d2500723e5594f3e7c70896ffeeef32b9c950ywan # probably a member operator declaration or default constructor. 3765233d2500723e5594f3e7c70896ffeeef32b9c950ywan match = Search( 3766233d2500723e5594f3e7c70896ffeeef32b9c950ywan r'(\bnew\s+)?\b' # Grab 'new' operator, if it's there 3767233d2500723e5594f3e7c70896ffeeef32b9c950ywan r'(int|float|double|bool|char|int32|uint32|int64|uint64)' 3768233d2500723e5594f3e7c70896ffeeef32b9c950ywan r'(\([^)].*)', line) 3769233d2500723e5594f3e7c70896ffeeef32b9c950ywan if match: 3770233d2500723e5594f3e7c70896ffeeef32b9c950ywan matched_new = match.group(1) 3771233d2500723e5594f3e7c70896ffeeef32b9c950ywan matched_type = match.group(2) 3772233d2500723e5594f3e7c70896ffeeef32b9c950ywan matched_funcptr = match.group(3) 3773233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3774233d2500723e5594f3e7c70896ffeeef32b9c950ywan # gMock methods are defined using some variant of MOCK_METHODx(name, type) 3775233d2500723e5594f3e7c70896ffeeef32b9c950ywan # where type may be float(), int(string), etc. Without context they are 3776233d2500723e5594f3e7c70896ffeeef32b9c950ywan # virtually indistinguishable from int(x) casts. Likewise, gMock's 3777233d2500723e5594f3e7c70896ffeeef32b9c950ywan # MockCallback takes a template parameter of the form return_type(arg_type), 3778233d2500723e5594f3e7c70896ffeeef32b9c950ywan # which looks much like the cast we're trying to detect. 3779233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 3780233d2500723e5594f3e7c70896ffeeef32b9c950ywan # std::function<> wrapper has a similar problem. 3781233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 3782233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Return types for function pointers also look like casts if they 3783233d2500723e5594f3e7c70896ffeeef32b9c950ywan # don't have an extra space. 3784233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (matched_new is None and # If new operator, then this isn't a cast 3785233d2500723e5594f3e7c70896ffeeef32b9c950ywan not (Match(r'^\s*MOCK_(CONST_)?METHOD\d+(_T)?\(', line) or 3786233d2500723e5594f3e7c70896ffeeef32b9c950ywan Search(r'\bMockCallback<.*>', line) or 3787233d2500723e5594f3e7c70896ffeeef32b9c950ywan Search(r'\bstd::function<.*>', line)) and 3788233d2500723e5594f3e7c70896ffeeef32b9c950ywan not (matched_funcptr and 3789233d2500723e5594f3e7c70896ffeeef32b9c950ywan Match(r'\((?:[^() ]+::\s*\*\s*)?[^() ]+\)\s*\(', 3790233d2500723e5594f3e7c70896ffeeef32b9c950ywan matched_funcptr))): 3791233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Try a bit harder to catch gmock lines: the only place where 3792233d2500723e5594f3e7c70896ffeeef32b9c950ywan # something looks like an old-style cast is where we declare the 3793233d2500723e5594f3e7c70896ffeeef32b9c950ywan # return type of the mocked method, and the only time when we 3794233d2500723e5594f3e7c70896ffeeef32b9c950ywan # are missing context is if MOCK_METHOD was split across 3795233d2500723e5594f3e7c70896ffeeef32b9c950ywan # multiple lines. The missing MOCK_METHOD is usually one or two 3796233d2500723e5594f3e7c70896ffeeef32b9c950ywan # lines back, so scan back one or two lines. 3797233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 3798233d2500723e5594f3e7c70896ffeeef32b9c950ywan # It's not possible for gmock macros to appear in the first 2 3799233d2500723e5594f3e7c70896ffeeef32b9c950ywan # lines, since the class head + section name takes up 2 lines. 3800233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (linenum < 2 or 3801233d2500723e5594f3e7c70896ffeeef32b9c950ywan not (Match(r'^\s*MOCK_(?:CONST_)?METHOD\d+(?:_T)?\((?:\S+,)?\s*$', 3802233d2500723e5594f3e7c70896ffeeef32b9c950ywan clean_lines.elided[linenum - 1]) or 3803233d2500723e5594f3e7c70896ffeeef32b9c950ywan Match(r'^\s*MOCK_(?:CONST_)?METHOD\d+(?:_T)?\(\s*$', 3804233d2500723e5594f3e7c70896ffeeef32b9c950ywan clean_lines.elided[linenum - 2]))): 3805233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'readability/casting', 4, 3806233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Using deprecated casting style. ' 3807233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Use static_cast<%s>(...) instead' % 3808233d2500723e5594f3e7c70896ffeeef32b9c950ywan matched_type) 3809233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3810233d2500723e5594f3e7c70896ffeeef32b9c950ywan CheckCStyleCast(filename, linenum, line, clean_lines.raw_lines[linenum], 3811233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'static_cast', 3812233d2500723e5594f3e7c70896ffeeef32b9c950ywan r'\((int|float|double|bool|char|u?int(16|32|64))\)', error) 3813233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3814233d2500723e5594f3e7c70896ffeeef32b9c950ywan # This doesn't catch all cases. Consider (const char * const)"hello". 3815233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 3816233d2500723e5594f3e7c70896ffeeef32b9c950ywan # (char *) "foo" should always be a const_cast (reinterpret_cast won't 3817233d2500723e5594f3e7c70896ffeeef32b9c950ywan # compile). 3818233d2500723e5594f3e7c70896ffeeef32b9c950ywan if CheckCStyleCast(filename, linenum, line, clean_lines.raw_lines[linenum], 3819233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'const_cast', r'\((char\s?\*+\s?)\)\s*"', error): 3820233d2500723e5594f3e7c70896ffeeef32b9c950ywan pass 3821233d2500723e5594f3e7c70896ffeeef32b9c950ywan else: 3822233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Check pointer casts for other than string constants 3823233d2500723e5594f3e7c70896ffeeef32b9c950ywan CheckCStyleCast(filename, linenum, line, clean_lines.raw_lines[linenum], 3824233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'reinterpret_cast', r'\((\w+\s?\*+\s?)\)', error) 3825233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3826233d2500723e5594f3e7c70896ffeeef32b9c950ywan # In addition, we look for people taking the address of a cast. This 3827233d2500723e5594f3e7c70896ffeeef32b9c950ywan # is dangerous -- casts can assign to temporaries, so the pointer doesn't 3828233d2500723e5594f3e7c70896ffeeef32b9c950ywan # point where you think. 3829233d2500723e5594f3e7c70896ffeeef32b9c950ywan match = Search( 3830233d2500723e5594f3e7c70896ffeeef32b9c950ywan r'(?:&\(([^)]+)\)[\w(])|' 3831233d2500723e5594f3e7c70896ffeeef32b9c950ywan r'(?:&(static|dynamic|down|reinterpret)_cast\b)', line) 3832233d2500723e5594f3e7c70896ffeeef32b9c950ywan if match and match.group(1) != '*': 3833233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'runtime/casting', 4, 3834233d2500723e5594f3e7c70896ffeeef32b9c950ywan ('Are you taking an address of a cast? ' 3835233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'This is dangerous: could be a temp var. ' 3836233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Take the address before doing the cast, rather than after')) 3837233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3838233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Create an extended_line, which is the concatenation of the current and 3839233d2500723e5594f3e7c70896ffeeef32b9c950ywan # next lines, for more effective checking of code that may span more than one 3840233d2500723e5594f3e7c70896ffeeef32b9c950ywan # line. 3841233d2500723e5594f3e7c70896ffeeef32b9c950ywan if linenum + 1 < clean_lines.NumLines(): 3842233d2500723e5594f3e7c70896ffeeef32b9c950ywan extended_line = line + clean_lines.elided[linenum + 1] 3843233d2500723e5594f3e7c70896ffeeef32b9c950ywan else: 3844233d2500723e5594f3e7c70896ffeeef32b9c950ywan extended_line = line 3845233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3846233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Check for people declaring static/global STL strings at the top level. 3847233d2500723e5594f3e7c70896ffeeef32b9c950ywan # This is dangerous because the C++ language does not guarantee that 3848233d2500723e5594f3e7c70896ffeeef32b9c950ywan # globals with constructors are initialized before the first access. 3849233d2500723e5594f3e7c70896ffeeef32b9c950ywan match = Match( 3850233d2500723e5594f3e7c70896ffeeef32b9c950ywan r'((?:|static +)(?:|const +))string +([a-zA-Z0-9_:]+)\b(.*)', 3851233d2500723e5594f3e7c70896ffeeef32b9c950ywan line) 3852233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Make sure it's not a function. 3853233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Function template specialization looks like: "string foo<Type>(...". 3854233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Class template definitions look like: "string Foo<Type>::Method(...". 3855233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 3856233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Also ignore things that look like operators. These are matched separately 3857233d2500723e5594f3e7c70896ffeeef32b9c950ywan # because operator names cross non-word boundaries. If we change the pattern 3858233d2500723e5594f3e7c70896ffeeef32b9c950ywan # above, we would decrease the accuracy of matching identifiers. 3859233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (match and 3860233d2500723e5594f3e7c70896ffeeef32b9c950ywan not Search(r'\boperator\W', line) and 3861233d2500723e5594f3e7c70896ffeeef32b9c950ywan not Match(r'\s*(<.*>)?(::[a-zA-Z0-9_]+)?\s*\(([^"]|$)', match.group(3))): 3862233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'runtime/string', 4, 3863233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'For a static/global string constant, use a C style string instead: ' 3864233d2500723e5594f3e7c70896ffeeef32b9c950ywan '"%schar %s[]".' % 3865233d2500723e5594f3e7c70896ffeeef32b9c950ywan (match.group(1), match.group(2))) 3866233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3867233d2500723e5594f3e7c70896ffeeef32b9c950ywan if Search(r'\b([A-Za-z0-9_]*_)\(\1\)', line): 3868233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'runtime/init', 4, 3869233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'You seem to be initializing a member variable with itself.') 3870233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3871233d2500723e5594f3e7c70896ffeeef32b9c950ywan if file_extension == 'h': 3872233d2500723e5594f3e7c70896ffeeef32b9c950ywan # TODO(unknown): check that 1-arg constructors are explicit. 3873233d2500723e5594f3e7c70896ffeeef32b9c950ywan # How to tell it's a constructor? 3874233d2500723e5594f3e7c70896ffeeef32b9c950ywan # (handled in CheckForNonStandardConstructs for now) 3875233d2500723e5594f3e7c70896ffeeef32b9c950ywan # TODO(unknown): check that classes have DISALLOW_EVIL_CONSTRUCTORS 3876233d2500723e5594f3e7c70896ffeeef32b9c950ywan # (level 1 error) 3877233d2500723e5594f3e7c70896ffeeef32b9c950ywan pass 3878233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3879233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Check if people are using the verboten C basic types. The only exception 3880233d2500723e5594f3e7c70896ffeeef32b9c950ywan # we regularly allow is "unsigned short port" for port. 3881233d2500723e5594f3e7c70896ffeeef32b9c950ywan if Search(r'\bshort port\b', line): 3882233d2500723e5594f3e7c70896ffeeef32b9c950ywan if not Search(r'\bunsigned short port\b', line): 3883233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'runtime/int', 4, 3884233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Use "unsigned short" for ports, not "short"') 3885233d2500723e5594f3e7c70896ffeeef32b9c950ywan else: 3886233d2500723e5594f3e7c70896ffeeef32b9c950ywan match = Search(r'\b(short|long(?! +double)|long long)\b', line) 3887233d2500723e5594f3e7c70896ffeeef32b9c950ywan if match: 3888233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'runtime/int', 4, 3889233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Use int16/int64/etc, rather than the C type %s' % match.group(1)) 3890233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3891233d2500723e5594f3e7c70896ffeeef32b9c950ywan # When snprintf is used, the second argument shouldn't be a literal. 3892233d2500723e5594f3e7c70896ffeeef32b9c950ywan match = Search(r'snprintf\s*\(([^,]*),\s*([0-9]*)\s*,', line) 3893233d2500723e5594f3e7c70896ffeeef32b9c950ywan if match and match.group(2) != '0': 3894233d2500723e5594f3e7c70896ffeeef32b9c950ywan # If 2nd arg is zero, snprintf is used to calculate size. 3895233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'runtime/printf', 3, 3896233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'If you can, use sizeof(%s) instead of %s as the 2nd arg ' 3897233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'to snprintf.' % (match.group(1), match.group(2))) 3898233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3899233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Check if some verboten C functions are being used. 3900233d2500723e5594f3e7c70896ffeeef32b9c950ywan if Search(r'\bsprintf\b', line): 3901233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'runtime/printf', 5, 3902233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Never use sprintf. Use snprintf instead.') 3903233d2500723e5594f3e7c70896ffeeef32b9c950ywan match = Search(r'\b(strcpy|strcat)\b', line) 3904233d2500723e5594f3e7c70896ffeeef32b9c950ywan if match: 3905233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'runtime/printf', 4, 3906233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Almost always, snprintf is better than %s' % match.group(1)) 3907233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3908233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Check if some verboten operator overloading is going on 3909233d2500723e5594f3e7c70896ffeeef32b9c950ywan # TODO(unknown): catch out-of-line unary operator&: 3910233d2500723e5594f3e7c70896ffeeef32b9c950ywan # class X {}; 3911233d2500723e5594f3e7c70896ffeeef32b9c950ywan # int operator&(const X& x) { return 42; } // unary operator& 3912233d2500723e5594f3e7c70896ffeeef32b9c950ywan # The trick is it's hard to tell apart from binary operator&: 3913233d2500723e5594f3e7c70896ffeeef32b9c950ywan # class Y { int operator&(const Y& x) { return 23; } }; // binary operator& 3914233d2500723e5594f3e7c70896ffeeef32b9c950ywan if Search(r'\boperator\s*&\s*\(\s*\)', line): 3915233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'runtime/operator', 4, 3916233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Unary operator& is dangerous. Do not use it.') 3917233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3918233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Check for suspicious usage of "if" like 3919233d2500723e5594f3e7c70896ffeeef32b9c950ywan # } if (a == b) { 3920233d2500723e5594f3e7c70896ffeeef32b9c950ywan if Search(r'\}\s*if\s*\(', line): 3921233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'readability/braces', 4, 3922233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Did you mean "else if"? If not, start a new line for "if".') 3923233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3924233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Check for potential format string bugs like printf(foo). 3925233d2500723e5594f3e7c70896ffeeef32b9c950ywan # We constrain the pattern not to pick things like DocidForPrintf(foo). 3926233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Not perfect but it can catch printf(foo.c_str()) and printf(foo->c_str()) 3927233d2500723e5594f3e7c70896ffeeef32b9c950ywan # TODO(sugawarayu): Catch the following case. Need to change the calling 3928233d2500723e5594f3e7c70896ffeeef32b9c950ywan # convention of the whole function to process multiple line to handle it. 3929233d2500723e5594f3e7c70896ffeeef32b9c950ywan # printf( 3930233d2500723e5594f3e7c70896ffeeef32b9c950ywan # boy_this_is_a_really_long_variable_that_cannot_fit_on_the_prev_line); 3931233d2500723e5594f3e7c70896ffeeef32b9c950ywan printf_args = _GetTextInside(line, r'(?i)\b(string)?printf\s*\(') 3932233d2500723e5594f3e7c70896ffeeef32b9c950ywan if printf_args: 3933233d2500723e5594f3e7c70896ffeeef32b9c950ywan match = Match(r'([\w.\->()]+)$', printf_args) 3934233d2500723e5594f3e7c70896ffeeef32b9c950ywan if match and match.group(1) != '__VA_ARGS__': 3935233d2500723e5594f3e7c70896ffeeef32b9c950ywan function_name = re.search(r'\b((?:string)?printf)\s*\(', 3936233d2500723e5594f3e7c70896ffeeef32b9c950ywan line, re.I).group(1) 3937233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'runtime/printf', 4, 3938233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Potential format string bug. Do %s("%%s", %s) instead.' 3939233d2500723e5594f3e7c70896ffeeef32b9c950ywan % (function_name, match.group(1))) 3940233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3941233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Check for potential memset bugs like memset(buf, sizeof(buf), 0). 3942233d2500723e5594f3e7c70896ffeeef32b9c950ywan match = Search(r'memset\s*\(([^,]*),\s*([^,]*),\s*0\s*\)', line) 3943233d2500723e5594f3e7c70896ffeeef32b9c950ywan if match and not Match(r"^''|-?[0-9]+|0x[0-9A-Fa-f]$", match.group(2)): 3944233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'runtime/memset', 4, 3945233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Did you mean "memset(%s, 0, %s)"?' 3946233d2500723e5594f3e7c70896ffeeef32b9c950ywan % (match.group(1), match.group(2))) 3947233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3948233d2500723e5594f3e7c70896ffeeef32b9c950ywan if Search(r'\busing namespace\b', line): 3949233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'build/namespaces', 5, 3950233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Do not use namespace using-directives. ' 3951233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Use using-declarations instead.') 3952233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3953233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Detect variable-length arrays. 3954233d2500723e5594f3e7c70896ffeeef32b9c950ywan match = Match(r'\s*(.+::)?(\w+) [a-z]\w*\[(.+)];', line) 3955233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (match and match.group(2) != 'return' and match.group(2) != 'delete' and 3956233d2500723e5594f3e7c70896ffeeef32b9c950ywan match.group(3).find(']') == -1): 3957233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Split the size using space and arithmetic operators as delimiters. 3958233d2500723e5594f3e7c70896ffeeef32b9c950ywan # If any of the resulting tokens are not compile time constants then 3959233d2500723e5594f3e7c70896ffeeef32b9c950ywan # report the error. 3960233d2500723e5594f3e7c70896ffeeef32b9c950ywan tokens = re.split(r'\s|\+|\-|\*|\/|<<|>>]', match.group(3)) 3961233d2500723e5594f3e7c70896ffeeef32b9c950ywan is_const = True 3962233d2500723e5594f3e7c70896ffeeef32b9c950ywan skip_next = False 3963233d2500723e5594f3e7c70896ffeeef32b9c950ywan for tok in tokens: 3964233d2500723e5594f3e7c70896ffeeef32b9c950ywan if skip_next: 3965233d2500723e5594f3e7c70896ffeeef32b9c950ywan skip_next = False 3966233d2500723e5594f3e7c70896ffeeef32b9c950ywan continue 3967233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3968233d2500723e5594f3e7c70896ffeeef32b9c950ywan if Search(r'sizeof\(.+\)', tok): continue 3969233d2500723e5594f3e7c70896ffeeef32b9c950ywan if Search(r'arraysize\(\w+\)', tok): continue 3970233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3971233d2500723e5594f3e7c70896ffeeef32b9c950ywan tok = tok.lstrip('(') 3972233d2500723e5594f3e7c70896ffeeef32b9c950ywan tok = tok.rstrip(')') 3973233d2500723e5594f3e7c70896ffeeef32b9c950ywan if not tok: continue 3974233d2500723e5594f3e7c70896ffeeef32b9c950ywan if Match(r'\d+', tok): continue 3975233d2500723e5594f3e7c70896ffeeef32b9c950ywan if Match(r'0[xX][0-9a-fA-F]+', tok): continue 3976233d2500723e5594f3e7c70896ffeeef32b9c950ywan if Match(r'k[A-Z0-9]\w*', tok): continue 3977233d2500723e5594f3e7c70896ffeeef32b9c950ywan if Match(r'(.+::)?k[A-Z0-9]\w*', tok): continue 3978233d2500723e5594f3e7c70896ffeeef32b9c950ywan if Match(r'(.+::)?[A-Z][A-Z0-9_]*', tok): continue 3979233d2500723e5594f3e7c70896ffeeef32b9c950ywan # A catch all for tricky sizeof cases, including 'sizeof expression', 3980233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 'sizeof(*type)', 'sizeof(const type)', 'sizeof(struct StructName)' 3981233d2500723e5594f3e7c70896ffeeef32b9c950ywan # requires skipping the next token because we split on ' ' and '*'. 3982233d2500723e5594f3e7c70896ffeeef32b9c950ywan if tok.startswith('sizeof'): 3983233d2500723e5594f3e7c70896ffeeef32b9c950ywan skip_next = True 3984233d2500723e5594f3e7c70896ffeeef32b9c950ywan continue 3985233d2500723e5594f3e7c70896ffeeef32b9c950ywan is_const = False 3986233d2500723e5594f3e7c70896ffeeef32b9c950ywan break 3987233d2500723e5594f3e7c70896ffeeef32b9c950ywan if not is_const: 3988233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'runtime/arrays', 1, 3989233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Do not use variable-length arrays. Use an appropriately named ' 3990233d2500723e5594f3e7c70896ffeeef32b9c950ywan "('k' followed by CamelCase) compile-time constant for the size.") 3991233d2500723e5594f3e7c70896ffeeef32b9c950ywan 3992233d2500723e5594f3e7c70896ffeeef32b9c950ywan # If DISALLOW_EVIL_CONSTRUCTORS, DISALLOW_COPY_AND_ASSIGN, or 3993233d2500723e5594f3e7c70896ffeeef32b9c950ywan # DISALLOW_IMPLICIT_CONSTRUCTORS is present, then it should be the last thing 3994233d2500723e5594f3e7c70896ffeeef32b9c950ywan # in the class declaration. 3995233d2500723e5594f3e7c70896ffeeef32b9c950ywan match = Match( 3996233d2500723e5594f3e7c70896ffeeef32b9c950ywan (r'\s*' 3997233d2500723e5594f3e7c70896ffeeef32b9c950ywan r'(DISALLOW_(EVIL_CONSTRUCTORS|COPY_AND_ASSIGN|IMPLICIT_CONSTRUCTORS))' 3998233d2500723e5594f3e7c70896ffeeef32b9c950ywan r'\(.*\);$'), 3999233d2500723e5594f3e7c70896ffeeef32b9c950ywan line) 4000233d2500723e5594f3e7c70896ffeeef32b9c950ywan if match and linenum + 1 < clean_lines.NumLines(): 4001233d2500723e5594f3e7c70896ffeeef32b9c950ywan next_line = clean_lines.elided[linenum + 1] 4002233d2500723e5594f3e7c70896ffeeef32b9c950ywan # We allow some, but not all, declarations of variables to be present 4003233d2500723e5594f3e7c70896ffeeef32b9c950ywan # in the statement that defines the class. The [\w\*,\s]* fragment of 4004233d2500723e5594f3e7c70896ffeeef32b9c950ywan # the regular expression below allows users to declare instances of 4005233d2500723e5594f3e7c70896ffeeef32b9c950ywan # the class or pointers to instances, but not less common types such 4006233d2500723e5594f3e7c70896ffeeef32b9c950ywan # as function pointers or arrays. It's a tradeoff between allowing 4007233d2500723e5594f3e7c70896ffeeef32b9c950ywan # reasonable code and avoiding trying to parse more C++ using regexps. 4008233d2500723e5594f3e7c70896ffeeef32b9c950ywan if not Search(r'^\s*}[\w\*,\s]*;', next_line): 4009233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'readability/constructors', 3, 4010233d2500723e5594f3e7c70896ffeeef32b9c950ywan match.group(1) + ' should be the last thing in the class') 4011233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4012233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Check for use of unnamed namespaces in header files. Registration 4013233d2500723e5594f3e7c70896ffeeef32b9c950ywan # macros are typically OK, so we allow use of "namespace {" on lines 4014233d2500723e5594f3e7c70896ffeeef32b9c950ywan # that end with backslashes. 4015233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (file_extension == 'h' 4016233d2500723e5594f3e7c70896ffeeef32b9c950ywan and Search(r'\bnamespace\s*{', line) 4017233d2500723e5594f3e7c70896ffeeef32b9c950ywan and line[-1] != '\\'): 4018233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'build/namespaces', 4, 4019233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Do not use unnamed namespaces in header files. See ' 4020233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Namespaces' 4021233d2500723e5594f3e7c70896ffeeef32b9c950ywan ' for more information.') 4022233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4023233d2500723e5594f3e7c70896ffeeef32b9c950ywandef CheckForNonConstReference(filename, clean_lines, linenum, 4024233d2500723e5594f3e7c70896ffeeef32b9c950ywan nesting_state, error): 4025233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Check for non-const references. 4026233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4027233d2500723e5594f3e7c70896ffeeef32b9c950ywan Separate from CheckLanguage since it scans backwards from current 4028233d2500723e5594f3e7c70896ffeeef32b9c950ywan line, instead of scanning forward. 4029233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4030233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 4031233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename: The name of the current file. 4032233d2500723e5594f3e7c70896ffeeef32b9c950ywan clean_lines: A CleansedLines instance containing the file. 4033233d2500723e5594f3e7c70896ffeeef32b9c950ywan linenum: The number of the line to check. 4034233d2500723e5594f3e7c70896ffeeef32b9c950ywan nesting_state: A _NestingState instance which maintains information about 4035233d2500723e5594f3e7c70896ffeeef32b9c950ywan the current stack of nested blocks being parsed. 4036233d2500723e5594f3e7c70896ffeeef32b9c950ywan error: The function to call with any errors found. 4037233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 4038233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Do nothing if there is no '&' on current line. 4039233d2500723e5594f3e7c70896ffeeef32b9c950ywan line = clean_lines.elided[linenum] 4040233d2500723e5594f3e7c70896ffeeef32b9c950ywan if '&' not in line: 4041233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 4042233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4043233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Long type names may be broken across multiple lines, usually in one 4044233d2500723e5594f3e7c70896ffeeef32b9c950ywan # of these forms: 4045233d2500723e5594f3e7c70896ffeeef32b9c950ywan # LongType 4046233d2500723e5594f3e7c70896ffeeef32b9c950ywan # ::LongTypeContinued &identifier 4047233d2500723e5594f3e7c70896ffeeef32b9c950ywan # LongType:: 4048233d2500723e5594f3e7c70896ffeeef32b9c950ywan # LongTypeContinued &identifier 4049233d2500723e5594f3e7c70896ffeeef32b9c950ywan # LongType< 4050233d2500723e5594f3e7c70896ffeeef32b9c950ywan # ...>::LongTypeContinued &identifier 4051233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 4052233d2500723e5594f3e7c70896ffeeef32b9c950ywan # If we detected a type split across two lines, join the previous 4053233d2500723e5594f3e7c70896ffeeef32b9c950ywan # line to current line so that we can match const references 4054233d2500723e5594f3e7c70896ffeeef32b9c950ywan # accordingly. 4055233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 4056233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Note that this only scans back one line, since scanning back 4057233d2500723e5594f3e7c70896ffeeef32b9c950ywan # arbitrary number of lines would be expensive. If you have a type 4058233d2500723e5594f3e7c70896ffeeef32b9c950ywan # that spans more than 2 lines, please use a typedef. 4059233d2500723e5594f3e7c70896ffeeef32b9c950ywan if linenum > 1: 4060233d2500723e5594f3e7c70896ffeeef32b9c950ywan previous = None 4061233d2500723e5594f3e7c70896ffeeef32b9c950ywan if Match(r'\s*::(?:[\w<>]|::)+\s*&\s*\S', line): 4062233d2500723e5594f3e7c70896ffeeef32b9c950ywan # previous_line\n + ::current_line 4063233d2500723e5594f3e7c70896ffeeef32b9c950ywan previous = Search(r'\b((?:const\s*)?(?:[\w<>]|::)+[\w<>])\s*$', 4064233d2500723e5594f3e7c70896ffeeef32b9c950ywan clean_lines.elided[linenum - 1]) 4065233d2500723e5594f3e7c70896ffeeef32b9c950ywan elif Match(r'\s*[a-zA-Z_]([\w<>]|::)+\s*&\s*\S', line): 4066233d2500723e5594f3e7c70896ffeeef32b9c950ywan # previous_line::\n + current_line 4067233d2500723e5594f3e7c70896ffeeef32b9c950ywan previous = Search(r'\b((?:const\s*)?(?:[\w<>]|::)+::)\s*$', 4068233d2500723e5594f3e7c70896ffeeef32b9c950ywan clean_lines.elided[linenum - 1]) 4069233d2500723e5594f3e7c70896ffeeef32b9c950ywan if previous: 4070233d2500723e5594f3e7c70896ffeeef32b9c950ywan line = previous.group(1) + line.lstrip() 4071233d2500723e5594f3e7c70896ffeeef32b9c950ywan else: 4072233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Check for templated parameter that is split across multiple lines 4073233d2500723e5594f3e7c70896ffeeef32b9c950ywan endpos = line.rfind('>') 4074233d2500723e5594f3e7c70896ffeeef32b9c950ywan if endpos > -1: 4075233d2500723e5594f3e7c70896ffeeef32b9c950ywan (_, startline, startpos) = ReverseCloseExpression( 4076233d2500723e5594f3e7c70896ffeeef32b9c950ywan clean_lines, linenum, endpos) 4077233d2500723e5594f3e7c70896ffeeef32b9c950ywan if startpos > -1 and startline < linenum: 4078233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Found the matching < on an earlier line, collect all 4079233d2500723e5594f3e7c70896ffeeef32b9c950ywan # pieces up to current line. 4080233d2500723e5594f3e7c70896ffeeef32b9c950ywan line = '' 4081233d2500723e5594f3e7c70896ffeeef32b9c950ywan for i in xrange(startline, linenum + 1): 4082233d2500723e5594f3e7c70896ffeeef32b9c950ywan line += clean_lines.elided[i].strip() 4083233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4084233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Check for non-const references in function parameters. A single '&' may 4085233d2500723e5594f3e7c70896ffeeef32b9c950ywan # found in the following places: 4086233d2500723e5594f3e7c70896ffeeef32b9c950ywan # inside expression: binary & for bitwise AND 4087233d2500723e5594f3e7c70896ffeeef32b9c950ywan # inside expression: unary & for taking the address of something 4088233d2500723e5594f3e7c70896ffeeef32b9c950ywan # inside declarators: reference parameter 4089233d2500723e5594f3e7c70896ffeeef32b9c950ywan # We will exclude the first two cases by checking that we are not inside a 4090233d2500723e5594f3e7c70896ffeeef32b9c950ywan # function body, including one that was just introduced by a trailing '{'. 4091233d2500723e5594f3e7c70896ffeeef32b9c950ywan # TODO(unknwon): Doesn't account for preprocessor directives. 4092233d2500723e5594f3e7c70896ffeeef32b9c950ywan # TODO(unknown): Doesn't account for 'catch(Exception& e)' [rare]. 4093233d2500723e5594f3e7c70896ffeeef32b9c950ywan check_params = False 4094233d2500723e5594f3e7c70896ffeeef32b9c950ywan if not nesting_state.stack: 4095233d2500723e5594f3e7c70896ffeeef32b9c950ywan check_params = True # top level 4096233d2500723e5594f3e7c70896ffeeef32b9c950ywan elif (isinstance(nesting_state.stack[-1], _ClassInfo) or 4097233d2500723e5594f3e7c70896ffeeef32b9c950ywan isinstance(nesting_state.stack[-1], _NamespaceInfo)): 4098233d2500723e5594f3e7c70896ffeeef32b9c950ywan check_params = True # within class or namespace 4099233d2500723e5594f3e7c70896ffeeef32b9c950ywan elif Match(r'.*{\s*$', line): 4100233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (len(nesting_state.stack) == 1 or 4101233d2500723e5594f3e7c70896ffeeef32b9c950ywan isinstance(nesting_state.stack[-2], _ClassInfo) or 4102233d2500723e5594f3e7c70896ffeeef32b9c950ywan isinstance(nesting_state.stack[-2], _NamespaceInfo)): 4103233d2500723e5594f3e7c70896ffeeef32b9c950ywan check_params = True # just opened global/class/namespace block 4104233d2500723e5594f3e7c70896ffeeef32b9c950ywan # We allow non-const references in a few standard places, like functions 4105233d2500723e5594f3e7c70896ffeeef32b9c950ywan # called "swap()" or iostream operators like "<<" or ">>". Do not check 4106233d2500723e5594f3e7c70896ffeeef32b9c950ywan # those function parameters. 4107233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 4108233d2500723e5594f3e7c70896ffeeef32b9c950ywan # We also accept & in static_assert, which looks like a function but 4109233d2500723e5594f3e7c70896ffeeef32b9c950ywan # it's actually a declaration expression. 4110233d2500723e5594f3e7c70896ffeeef32b9c950ywan whitelisted_functions = (r'(?:[sS]wap(?:<\w:+>)?|' 4111233d2500723e5594f3e7c70896ffeeef32b9c950ywan r'operator\s*[<>][<>]|' 4112233d2500723e5594f3e7c70896ffeeef32b9c950ywan r'static_assert|COMPILE_ASSERT' 4113233d2500723e5594f3e7c70896ffeeef32b9c950ywan r')\s*\(') 4114233d2500723e5594f3e7c70896ffeeef32b9c950ywan if Search(whitelisted_functions, line): 4115233d2500723e5594f3e7c70896ffeeef32b9c950ywan check_params = False 4116233d2500723e5594f3e7c70896ffeeef32b9c950ywan elif not Search(r'\S+\([^)]*$', line): 4117233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Don't see a whitelisted function on this line. Actually we 4118233d2500723e5594f3e7c70896ffeeef32b9c950ywan # didn't see any function name on this line, so this is likely a 4119233d2500723e5594f3e7c70896ffeeef32b9c950ywan # multi-line parameter list. Try a bit harder to catch this case. 4120233d2500723e5594f3e7c70896ffeeef32b9c950ywan for i in xrange(2): 4121233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (linenum > i and 4122233d2500723e5594f3e7c70896ffeeef32b9c950ywan Search(whitelisted_functions, clean_lines.elided[linenum - i - 1])): 4123233d2500723e5594f3e7c70896ffeeef32b9c950ywan check_params = False 4124233d2500723e5594f3e7c70896ffeeef32b9c950ywan break 4125233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4126233d2500723e5594f3e7c70896ffeeef32b9c950ywan if check_params: 4127233d2500723e5594f3e7c70896ffeeef32b9c950ywan decls = ReplaceAll(r'{[^}]*}', ' ', line) # exclude function body 4128233d2500723e5594f3e7c70896ffeeef32b9c950ywan for parameter in re.findall(_RE_PATTERN_REF_PARAM, decls): 4129233d2500723e5594f3e7c70896ffeeef32b9c950ywan if not Match(_RE_PATTERN_CONST_REF_PARAM, parameter): 4130233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'runtime/references', 2, 4131233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Is this a non-const reference? ' 4132233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'If so, make const or use a pointer: ' + 4133233d2500723e5594f3e7c70896ffeeef32b9c950ywan ReplaceAll(' *<', '<', parameter)) 4134233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4135233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4136233d2500723e5594f3e7c70896ffeeef32b9c950ywandef CheckCStyleCast(filename, linenum, line, raw_line, cast_type, pattern, 4137233d2500723e5594f3e7c70896ffeeef32b9c950ywan error): 4138233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Checks for a C-style cast by looking for the pattern. 4139233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4140233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 4141233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename: The name of the current file. 4142233d2500723e5594f3e7c70896ffeeef32b9c950ywan linenum: The number of the line to check. 4143233d2500723e5594f3e7c70896ffeeef32b9c950ywan line: The line of code to check. 4144233d2500723e5594f3e7c70896ffeeef32b9c950ywan raw_line: The raw line of code to check, with comments. 4145233d2500723e5594f3e7c70896ffeeef32b9c950ywan cast_type: The string for the C++ cast to recommend. This is either 4146233d2500723e5594f3e7c70896ffeeef32b9c950ywan reinterpret_cast, static_cast, or const_cast, depending. 4147233d2500723e5594f3e7c70896ffeeef32b9c950ywan pattern: The regular expression used to find C-style casts. 4148233d2500723e5594f3e7c70896ffeeef32b9c950ywan error: The function to call with any errors found. 4149233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4150233d2500723e5594f3e7c70896ffeeef32b9c950ywan Returns: 4151233d2500723e5594f3e7c70896ffeeef32b9c950ywan True if an error was emitted. 4152233d2500723e5594f3e7c70896ffeeef32b9c950ywan False otherwise. 4153233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 4154233d2500723e5594f3e7c70896ffeeef32b9c950ywan match = Search(pattern, line) 4155233d2500723e5594f3e7c70896ffeeef32b9c950ywan if not match: 4156233d2500723e5594f3e7c70896ffeeef32b9c950ywan return False 4157233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4158233d2500723e5594f3e7c70896ffeeef32b9c950ywan # e.g., sizeof(int) 4159233d2500723e5594f3e7c70896ffeeef32b9c950ywan sizeof_match = Match(r'.*sizeof\s*$', line[0:match.start(1) - 1]) 4160233d2500723e5594f3e7c70896ffeeef32b9c950ywan if sizeof_match: 4161233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'runtime/sizeof', 1, 4162233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Using sizeof(type). Use sizeof(varname) instead if possible') 4163233d2500723e5594f3e7c70896ffeeef32b9c950ywan return True 4164233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4165233d2500723e5594f3e7c70896ffeeef32b9c950ywan # operator++(int) and operator--(int) 4166233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (line[0:match.start(1) - 1].endswith(' operator++') or 4167233d2500723e5594f3e7c70896ffeeef32b9c950ywan line[0:match.start(1) - 1].endswith(' operator--')): 4168233d2500723e5594f3e7c70896ffeeef32b9c950ywan return False 4169233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4170233d2500723e5594f3e7c70896ffeeef32b9c950ywan # A single unnamed argument for a function tends to look like old 4171233d2500723e5594f3e7c70896ffeeef32b9c950ywan # style cast. If we see those, don't issue warnings for deprecated 4172233d2500723e5594f3e7c70896ffeeef32b9c950ywan # casts, instead issue warnings for unnamed arguments where 4173233d2500723e5594f3e7c70896ffeeef32b9c950ywan # appropriate. 4174233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 4175233d2500723e5594f3e7c70896ffeeef32b9c950ywan # These are things that we want warnings for, since the style guide 4176233d2500723e5594f3e7c70896ffeeef32b9c950ywan # explicitly require all parameters to be named: 4177233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Function(int); 4178233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Function(int) { 4179233d2500723e5594f3e7c70896ffeeef32b9c950ywan # ConstMember(int) const; 4180233d2500723e5594f3e7c70896ffeeef32b9c950ywan # ConstMember(int) const { 4181233d2500723e5594f3e7c70896ffeeef32b9c950ywan # ExceptionMember(int) throw (...); 4182233d2500723e5594f3e7c70896ffeeef32b9c950ywan # ExceptionMember(int) throw (...) { 4183233d2500723e5594f3e7c70896ffeeef32b9c950ywan # PureVirtual(int) = 0; 4184233d2500723e5594f3e7c70896ffeeef32b9c950ywan # 4185233d2500723e5594f3e7c70896ffeeef32b9c950ywan # These are functions of some sort, where the compiler would be fine 4186233d2500723e5594f3e7c70896ffeeef32b9c950ywan # if they had named parameters, but people often omit those 4187233d2500723e5594f3e7c70896ffeeef32b9c950ywan # identifiers to reduce clutter: 4188233d2500723e5594f3e7c70896ffeeef32b9c950ywan # (FunctionPointer)(int); 4189233d2500723e5594f3e7c70896ffeeef32b9c950ywan # (FunctionPointer)(int) = value; 4190233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Function((function_pointer_arg)(int)) 4191233d2500723e5594f3e7c70896ffeeef32b9c950ywan # <TemplateArgument(int)>; 4192233d2500723e5594f3e7c70896ffeeef32b9c950ywan # <(FunctionPointerTemplateArgument)(int)>; 4193233d2500723e5594f3e7c70896ffeeef32b9c950ywan remainder = line[match.end(0):] 4194233d2500723e5594f3e7c70896ffeeef32b9c950ywan if Match(r'^\s*(?:;|const\b|throw\b|=|>|\{|\))', remainder): 4195233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Looks like an unnamed parameter. 4196233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4197233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Don't warn on any kind of template arguments. 4198233d2500723e5594f3e7c70896ffeeef32b9c950ywan if Match(r'^\s*>', remainder): 4199233d2500723e5594f3e7c70896ffeeef32b9c950ywan return False 4200233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4201233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Don't warn on assignments to function pointers, but keep warnings for 4202233d2500723e5594f3e7c70896ffeeef32b9c950ywan # unnamed parameters to pure virtual functions. Note that this pattern 4203233d2500723e5594f3e7c70896ffeeef32b9c950ywan # will also pass on assignments of "0" to function pointers, but the 4204233d2500723e5594f3e7c70896ffeeef32b9c950ywan # preferred values for those would be "nullptr" or "NULL". 4205233d2500723e5594f3e7c70896ffeeef32b9c950ywan matched_zero = Match(r'^\s=\s*(\S+)\s*;', remainder) 4206233d2500723e5594f3e7c70896ffeeef32b9c950ywan if matched_zero and matched_zero.group(1) != '0': 4207233d2500723e5594f3e7c70896ffeeef32b9c950ywan return False 4208233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4209233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Don't warn on function pointer declarations. For this we need 4210233d2500723e5594f3e7c70896ffeeef32b9c950ywan # to check what came before the "(type)" string. 4211233d2500723e5594f3e7c70896ffeeef32b9c950ywan if Match(r'.*\)\s*$', line[0:match.start(0)]): 4212233d2500723e5594f3e7c70896ffeeef32b9c950ywan return False 4213233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4214233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Don't warn if the parameter is named with block comments, e.g.: 4215233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Function(int /*unused_param*/); 4216233d2500723e5594f3e7c70896ffeeef32b9c950ywan if '/*' in raw_line: 4217233d2500723e5594f3e7c70896ffeeef32b9c950ywan return False 4218233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4219233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Passed all filters, issue warning here. 4220233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'readability/function', 3, 4221233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'All parameters should be named in a function') 4222233d2500723e5594f3e7c70896ffeeef32b9c950ywan return True 4223233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4224233d2500723e5594f3e7c70896ffeeef32b9c950ywan # At this point, all that should be left is actual casts. 4225233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'readability/casting', 4, 4226233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Using C-style cast. Use %s<%s>(...) instead' % 4227233d2500723e5594f3e7c70896ffeeef32b9c950ywan (cast_type, match.group(1))) 4228233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4229233d2500723e5594f3e7c70896ffeeef32b9c950ywan return True 4230233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4231233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4232233d2500723e5594f3e7c70896ffeeef32b9c950ywan_HEADERS_CONTAINING_TEMPLATES = ( 4233233d2500723e5594f3e7c70896ffeeef32b9c950ywan ('<deque>', ('deque',)), 4234233d2500723e5594f3e7c70896ffeeef32b9c950ywan ('<functional>', ('unary_function', 'binary_function', 4235233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'plus', 'minus', 'multiplies', 'divides', 'modulus', 4236233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'negate', 4237233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'equal_to', 'not_equal_to', 'greater', 'less', 4238233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'greater_equal', 'less_equal', 4239233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'logical_and', 'logical_or', 'logical_not', 4240233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'unary_negate', 'not1', 'binary_negate', 'not2', 4241233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'bind1st', 'bind2nd', 4242233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'pointer_to_unary_function', 4243233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'pointer_to_binary_function', 4244233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'ptr_fun', 4245233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'mem_fun_t', 'mem_fun', 'mem_fun1_t', 'mem_fun1_ref_t', 4246233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'mem_fun_ref_t', 4247233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'const_mem_fun_t', 'const_mem_fun1_t', 4248233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'const_mem_fun_ref_t', 'const_mem_fun1_ref_t', 4249233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'mem_fun_ref', 4250233d2500723e5594f3e7c70896ffeeef32b9c950ywan )), 4251233d2500723e5594f3e7c70896ffeeef32b9c950ywan ('<limits>', ('numeric_limits',)), 4252233d2500723e5594f3e7c70896ffeeef32b9c950ywan ('<list>', ('list',)), 4253233d2500723e5594f3e7c70896ffeeef32b9c950ywan ('<map>', ('map', 'multimap',)), 4254233d2500723e5594f3e7c70896ffeeef32b9c950ywan ('<memory>', ('allocator',)), 4255233d2500723e5594f3e7c70896ffeeef32b9c950ywan ('<queue>', ('queue', 'priority_queue',)), 4256233d2500723e5594f3e7c70896ffeeef32b9c950ywan ('<set>', ('set', 'multiset',)), 4257233d2500723e5594f3e7c70896ffeeef32b9c950ywan ('<stack>', ('stack',)), 4258233d2500723e5594f3e7c70896ffeeef32b9c950ywan ('<string>', ('char_traits', 'basic_string',)), 4259233d2500723e5594f3e7c70896ffeeef32b9c950ywan ('<utility>', ('pair',)), 4260233d2500723e5594f3e7c70896ffeeef32b9c950ywan ('<vector>', ('vector',)), 4261233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4262233d2500723e5594f3e7c70896ffeeef32b9c950ywan # gcc extensions. 4263233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Note: std::hash is their hash, ::hash is our hash 4264233d2500723e5594f3e7c70896ffeeef32b9c950ywan ('<hash_map>', ('hash_map', 'hash_multimap',)), 4265233d2500723e5594f3e7c70896ffeeef32b9c950ywan ('<hash_set>', ('hash_set', 'hash_multiset',)), 4266233d2500723e5594f3e7c70896ffeeef32b9c950ywan ('<slist>', ('slist',)), 4267233d2500723e5594f3e7c70896ffeeef32b9c950ywan ) 4268233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4269233d2500723e5594f3e7c70896ffeeef32b9c950ywan_RE_PATTERN_STRING = re.compile(r'\bstring\b') 4270233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4271233d2500723e5594f3e7c70896ffeeef32b9c950ywan_re_pattern_algorithm_header = [] 4272233d2500723e5594f3e7c70896ffeeef32b9c950ywanfor _template in ('copy', 'max', 'min', 'min_element', 'sort', 'swap', 4273233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'transform'): 4274233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Match max<type>(..., ...), max(..., ...), but not foo->max, foo.max or 4275233d2500723e5594f3e7c70896ffeeef32b9c950ywan # type::max(). 4276233d2500723e5594f3e7c70896ffeeef32b9c950ywan _re_pattern_algorithm_header.append( 4277233d2500723e5594f3e7c70896ffeeef32b9c950ywan (re.compile(r'[^>.]\b' + _template + r'(<.*?>)?\([^\)]'), 4278233d2500723e5594f3e7c70896ffeeef32b9c950ywan _template, 4279233d2500723e5594f3e7c70896ffeeef32b9c950ywan '<algorithm>')) 4280233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4281233d2500723e5594f3e7c70896ffeeef32b9c950ywan_re_pattern_templates = [] 4282233d2500723e5594f3e7c70896ffeeef32b9c950ywanfor _header, _templates in _HEADERS_CONTAINING_TEMPLATES: 4283233d2500723e5594f3e7c70896ffeeef32b9c950ywan for _template in _templates: 4284233d2500723e5594f3e7c70896ffeeef32b9c950ywan _re_pattern_templates.append( 4285233d2500723e5594f3e7c70896ffeeef32b9c950ywan (re.compile(r'(\<|\b)' + _template + r'\s*\<'), 4286233d2500723e5594f3e7c70896ffeeef32b9c950ywan _template + '<>', 4287233d2500723e5594f3e7c70896ffeeef32b9c950ywan _header)) 4288233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4289233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4290233d2500723e5594f3e7c70896ffeeef32b9c950ywandef FilesBelongToSameModule(filename_cc, filename_h): 4291233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Check if these two filenames belong to the same module. 4292233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4293233d2500723e5594f3e7c70896ffeeef32b9c950ywan The concept of a 'module' here is a as follows: 4294233d2500723e5594f3e7c70896ffeeef32b9c950ywan foo.h, foo-inl.h, foo.cc, foo_test.cc and foo_unittest.cc belong to the 4295233d2500723e5594f3e7c70896ffeeef32b9c950ywan same 'module' if they are in the same directory. 4296233d2500723e5594f3e7c70896ffeeef32b9c950ywan some/path/public/xyzzy and some/path/internal/xyzzy are also considered 4297233d2500723e5594f3e7c70896ffeeef32b9c950ywan to belong to the same module here. 4298233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4299233d2500723e5594f3e7c70896ffeeef32b9c950ywan If the filename_cc contains a longer path than the filename_h, for example, 4300233d2500723e5594f3e7c70896ffeeef32b9c950ywan '/absolute/path/to/base/sysinfo.cc', and this file would include 4301233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'base/sysinfo.h', this function also produces the prefix needed to open the 4302233d2500723e5594f3e7c70896ffeeef32b9c950ywan header. This is used by the caller of this function to more robustly open the 4303233d2500723e5594f3e7c70896ffeeef32b9c950ywan header file. We don't have access to the real include paths in this context, 4304233d2500723e5594f3e7c70896ffeeef32b9c950ywan so we need this guesswork here. 4305233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4306233d2500723e5594f3e7c70896ffeeef32b9c950ywan Known bugs: tools/base/bar.cc and base/bar.h belong to the same module 4307233d2500723e5594f3e7c70896ffeeef32b9c950ywan according to this implementation. Because of this, this function gives 4308233d2500723e5594f3e7c70896ffeeef32b9c950ywan some false positives. This should be sufficiently rare in practice. 4309233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4310233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 4311233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename_cc: is the path for the .cc file 4312233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename_h: is the path for the header path 4313233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4314233d2500723e5594f3e7c70896ffeeef32b9c950ywan Returns: 4315233d2500723e5594f3e7c70896ffeeef32b9c950ywan Tuple with a bool and a string: 4316233d2500723e5594f3e7c70896ffeeef32b9c950ywan bool: True if filename_cc and filename_h belong to the same module. 4317233d2500723e5594f3e7c70896ffeeef32b9c950ywan string: the additional prefix needed to open the header file. 4318233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 4319233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4320233d2500723e5594f3e7c70896ffeeef32b9c950ywan if not filename_cc.endswith('.cc'): 4321233d2500723e5594f3e7c70896ffeeef32b9c950ywan return (False, '') 4322233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename_cc = filename_cc[:-len('.cc')] 4323233d2500723e5594f3e7c70896ffeeef32b9c950ywan if filename_cc.endswith('_unittest'): 4324233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename_cc = filename_cc[:-len('_unittest')] 4325233d2500723e5594f3e7c70896ffeeef32b9c950ywan elif filename_cc.endswith('_test'): 4326233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename_cc = filename_cc[:-len('_test')] 4327233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename_cc = filename_cc.replace('/public/', '/') 4328233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename_cc = filename_cc.replace('/internal/', '/') 4329233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4330233d2500723e5594f3e7c70896ffeeef32b9c950ywan if not filename_h.endswith('.h'): 4331233d2500723e5594f3e7c70896ffeeef32b9c950ywan return (False, '') 4332233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename_h = filename_h[:-len('.h')] 4333233d2500723e5594f3e7c70896ffeeef32b9c950ywan if filename_h.endswith('-inl'): 4334233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename_h = filename_h[:-len('-inl')] 4335233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename_h = filename_h.replace('/public/', '/') 4336233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename_h = filename_h.replace('/internal/', '/') 4337233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4338233d2500723e5594f3e7c70896ffeeef32b9c950ywan files_belong_to_same_module = filename_cc.endswith(filename_h) 4339233d2500723e5594f3e7c70896ffeeef32b9c950ywan common_path = '' 4340233d2500723e5594f3e7c70896ffeeef32b9c950ywan if files_belong_to_same_module: 4341233d2500723e5594f3e7c70896ffeeef32b9c950ywan common_path = filename_cc[:-len(filename_h)] 4342233d2500723e5594f3e7c70896ffeeef32b9c950ywan return files_belong_to_same_module, common_path 4343233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4344233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4345233d2500723e5594f3e7c70896ffeeef32b9c950ywandef UpdateIncludeState(filename, include_state, io=codecs): 4346233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Fill up the include_state with new includes found from the file. 4347233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4348233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 4349233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename: the name of the header to read. 4350233d2500723e5594f3e7c70896ffeeef32b9c950ywan include_state: an _IncludeState instance in which the headers are inserted. 4351233d2500723e5594f3e7c70896ffeeef32b9c950ywan io: The io factory to use to read the file. Provided for testability. 4352233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4353233d2500723e5594f3e7c70896ffeeef32b9c950ywan Returns: 4354233d2500723e5594f3e7c70896ffeeef32b9c950ywan True if a header was succesfully added. False otherwise. 4355233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 4356233d2500723e5594f3e7c70896ffeeef32b9c950ywan headerfile = None 4357233d2500723e5594f3e7c70896ffeeef32b9c950ywan try: 4358233d2500723e5594f3e7c70896ffeeef32b9c950ywan headerfile = io.open(filename, 'r', 'utf8', 'replace') 4359233d2500723e5594f3e7c70896ffeeef32b9c950ywan except IOError: 4360233d2500723e5594f3e7c70896ffeeef32b9c950ywan return False 4361233d2500723e5594f3e7c70896ffeeef32b9c950ywan linenum = 0 4362233d2500723e5594f3e7c70896ffeeef32b9c950ywan for line in headerfile: 4363233d2500723e5594f3e7c70896ffeeef32b9c950ywan linenum += 1 4364233d2500723e5594f3e7c70896ffeeef32b9c950ywan clean_line = CleanseComments(line) 4365233d2500723e5594f3e7c70896ffeeef32b9c950ywan match = _RE_PATTERN_INCLUDE.search(clean_line) 4366233d2500723e5594f3e7c70896ffeeef32b9c950ywan if match: 4367233d2500723e5594f3e7c70896ffeeef32b9c950ywan include = match.group(2) 4368233d2500723e5594f3e7c70896ffeeef32b9c950ywan # The value formatting is cute, but not really used right now. 4369233d2500723e5594f3e7c70896ffeeef32b9c950ywan # What matters here is that the key is in include_state. 4370233d2500723e5594f3e7c70896ffeeef32b9c950ywan include_state.setdefault(include, '%s:%d' % (filename, linenum)) 4371233d2500723e5594f3e7c70896ffeeef32b9c950ywan return True 4372233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4373233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4374233d2500723e5594f3e7c70896ffeeef32b9c950ywandef CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error, 4375233d2500723e5594f3e7c70896ffeeef32b9c950ywan io=codecs): 4376233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Reports for missing stl includes. 4377233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4378233d2500723e5594f3e7c70896ffeeef32b9c950ywan This function will output warnings to make sure you are including the headers 4379233d2500723e5594f3e7c70896ffeeef32b9c950ywan necessary for the stl containers and functions that you use. We only give one 4380233d2500723e5594f3e7c70896ffeeef32b9c950ywan reason to include a header. For example, if you use both equal_to<> and 4381233d2500723e5594f3e7c70896ffeeef32b9c950ywan less<> in a .h file, only one (the latter in the file) of these will be 4382233d2500723e5594f3e7c70896ffeeef32b9c950ywan reported as a reason to include the <functional>. 4383233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4384233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 4385233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename: The name of the current file. 4386233d2500723e5594f3e7c70896ffeeef32b9c950ywan clean_lines: A CleansedLines instance containing the file. 4387233d2500723e5594f3e7c70896ffeeef32b9c950ywan include_state: An _IncludeState instance. 4388233d2500723e5594f3e7c70896ffeeef32b9c950ywan error: The function to call with any errors found. 4389233d2500723e5594f3e7c70896ffeeef32b9c950ywan io: The IO factory to use to read the header file. Provided for unittest 4390233d2500723e5594f3e7c70896ffeeef32b9c950ywan injection. 4391233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 4392233d2500723e5594f3e7c70896ffeeef32b9c950ywan required = {} # A map of header name to linenumber and the template entity. 4393233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Example of required: { '<functional>': (1219, 'less<>') } 4394233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4395233d2500723e5594f3e7c70896ffeeef32b9c950ywan for linenum in xrange(clean_lines.NumLines()): 4396233d2500723e5594f3e7c70896ffeeef32b9c950ywan line = clean_lines.elided[linenum] 4397233d2500723e5594f3e7c70896ffeeef32b9c950ywan if not line or line[0] == '#': 4398233d2500723e5594f3e7c70896ffeeef32b9c950ywan continue 4399233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4400233d2500723e5594f3e7c70896ffeeef32b9c950ywan # String is special -- it is a non-templatized type in STL. 4401233d2500723e5594f3e7c70896ffeeef32b9c950ywan matched = _RE_PATTERN_STRING.search(line) 4402233d2500723e5594f3e7c70896ffeeef32b9c950ywan if matched: 4403233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Don't warn about strings in non-STL namespaces: 4404233d2500723e5594f3e7c70896ffeeef32b9c950ywan # (We check only the first match per line; good enough.) 4405233d2500723e5594f3e7c70896ffeeef32b9c950ywan prefix = line[:matched.start()] 4406233d2500723e5594f3e7c70896ffeeef32b9c950ywan if prefix.endswith('std::') or not prefix.endswith('::'): 4407233d2500723e5594f3e7c70896ffeeef32b9c950ywan required['<string>'] = (linenum, 'string') 4408233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4409233d2500723e5594f3e7c70896ffeeef32b9c950ywan for pattern, template, header in _re_pattern_algorithm_header: 4410233d2500723e5594f3e7c70896ffeeef32b9c950ywan if pattern.search(line): 4411233d2500723e5594f3e7c70896ffeeef32b9c950ywan required[header] = (linenum, template) 4412233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4413233d2500723e5594f3e7c70896ffeeef32b9c950ywan # The following function is just a speed up, no semantics are changed. 4414233d2500723e5594f3e7c70896ffeeef32b9c950ywan if not '<' in line: # Reduces the cpu time usage by skipping lines. 4415233d2500723e5594f3e7c70896ffeeef32b9c950ywan continue 4416233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4417233d2500723e5594f3e7c70896ffeeef32b9c950ywan for pattern, template, header in _re_pattern_templates: 4418233d2500723e5594f3e7c70896ffeeef32b9c950ywan if pattern.search(line): 4419233d2500723e5594f3e7c70896ffeeef32b9c950ywan required[header] = (linenum, template) 4420233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4421233d2500723e5594f3e7c70896ffeeef32b9c950ywan # The policy is that if you #include something in foo.h you don't need to 4422233d2500723e5594f3e7c70896ffeeef32b9c950ywan # include it again in foo.cc. Here, we will look at possible includes. 4423233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Let's copy the include_state so it is only messed up within this function. 4424233d2500723e5594f3e7c70896ffeeef32b9c950ywan include_state = include_state.copy() 4425233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4426233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Did we find the header for this file (if any) and succesfully load it? 4427233d2500723e5594f3e7c70896ffeeef32b9c950ywan header_found = False 4428233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4429233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Use the absolute path so that matching works properly. 4430233d2500723e5594f3e7c70896ffeeef32b9c950ywan abs_filename = FileInfo(filename).FullName() 4431233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4432233d2500723e5594f3e7c70896ffeeef32b9c950ywan # For Emacs's flymake. 4433233d2500723e5594f3e7c70896ffeeef32b9c950ywan # If cpplint is invoked from Emacs's flymake, a temporary file is generated 4434233d2500723e5594f3e7c70896ffeeef32b9c950ywan # by flymake and that file name might end with '_flymake.cc'. In that case, 4435233d2500723e5594f3e7c70896ffeeef32b9c950ywan # restore original file name here so that the corresponding header file can be 4436233d2500723e5594f3e7c70896ffeeef32b9c950ywan # found. 4437233d2500723e5594f3e7c70896ffeeef32b9c950ywan # e.g. If the file name is 'foo_flymake.cc', we should search for 'foo.h' 4438233d2500723e5594f3e7c70896ffeeef32b9c950ywan # instead of 'foo_flymake.h' 4439233d2500723e5594f3e7c70896ffeeef32b9c950ywan abs_filename = re.sub(r'_flymake\.cc$', '.cc', abs_filename) 4440233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4441233d2500723e5594f3e7c70896ffeeef32b9c950ywan # include_state is modified during iteration, so we iterate over a copy of 4442233d2500723e5594f3e7c70896ffeeef32b9c950ywan # the keys. 4443233d2500723e5594f3e7c70896ffeeef32b9c950ywan header_keys = include_state.keys() 4444233d2500723e5594f3e7c70896ffeeef32b9c950ywan for header in header_keys: 4445233d2500723e5594f3e7c70896ffeeef32b9c950ywan (same_module, common_path) = FilesBelongToSameModule(abs_filename, header) 4446233d2500723e5594f3e7c70896ffeeef32b9c950ywan fullpath = common_path + header 4447233d2500723e5594f3e7c70896ffeeef32b9c950ywan if same_module and UpdateIncludeState(fullpath, include_state, io): 4448233d2500723e5594f3e7c70896ffeeef32b9c950ywan header_found = True 4449233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4450233d2500723e5594f3e7c70896ffeeef32b9c950ywan # If we can't find the header file for a .cc, assume it's because we don't 4451233d2500723e5594f3e7c70896ffeeef32b9c950ywan # know where to look. In that case we'll give up as we're not sure they 4452233d2500723e5594f3e7c70896ffeeef32b9c950ywan # didn't include it in the .h file. 4453233d2500723e5594f3e7c70896ffeeef32b9c950ywan # TODO(unknown): Do a better job of finding .h files so we are confident that 4454233d2500723e5594f3e7c70896ffeeef32b9c950ywan # not having the .h file means there isn't one. 4455233d2500723e5594f3e7c70896ffeeef32b9c950ywan if filename.endswith('.cc') and not header_found: 4456233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 4457233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4458233d2500723e5594f3e7c70896ffeeef32b9c950ywan # All the lines have been processed, report the errors found. 4459233d2500723e5594f3e7c70896ffeeef32b9c950ywan for required_header_unstripped in required: 4460233d2500723e5594f3e7c70896ffeeef32b9c950ywan template = required[required_header_unstripped][1] 4461233d2500723e5594f3e7c70896ffeeef32b9c950ywan if required_header_unstripped.strip('<>"') not in include_state: 4462233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, required[required_header_unstripped][0], 4463233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'build/include_what_you_use', 4, 4464233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'Add #include ' + required_header_unstripped + ' for ' + template) 4465233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4466233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4467233d2500723e5594f3e7c70896ffeeef32b9c950ywan_RE_PATTERN_EXPLICIT_MAKEPAIR = re.compile(r'\bmake_pair\s*<') 4468233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4469233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4470233d2500723e5594f3e7c70896ffeeef32b9c950ywandef CheckMakePairUsesDeduction(filename, clean_lines, linenum, error): 4471233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Check that make_pair's template arguments are deduced. 4472233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4473233d2500723e5594f3e7c70896ffeeef32b9c950ywan G++ 4.6 in C++0x mode fails badly if make_pair's template arguments are 4474233d2500723e5594f3e7c70896ffeeef32b9c950ywan specified explicitly, and such use isn't intended in any case. 4475233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4476233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 4477233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename: The name of the current file. 4478233d2500723e5594f3e7c70896ffeeef32b9c950ywan clean_lines: A CleansedLines instance containing the file. 4479233d2500723e5594f3e7c70896ffeeef32b9c950ywan linenum: The number of the line to check. 4480233d2500723e5594f3e7c70896ffeeef32b9c950ywan error: The function to call with any errors found. 4481233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 4482233d2500723e5594f3e7c70896ffeeef32b9c950ywan line = clean_lines.elided[linenum] 4483233d2500723e5594f3e7c70896ffeeef32b9c950ywan match = _RE_PATTERN_EXPLICIT_MAKEPAIR.search(line) 4484233d2500723e5594f3e7c70896ffeeef32b9c950ywan if match: 4485233d2500723e5594f3e7c70896ffeeef32b9c950ywan error(filename, linenum, 'build/explicit_make_pair', 4486233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4, # 4 = high confidence 4487233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'For C++11-compatibility, omit template arguments from make_pair' 4488233d2500723e5594f3e7c70896ffeeef32b9c950ywan ' OR use pair directly OR if appropriate, construct a pair directly') 4489233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4490233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4491233d2500723e5594f3e7c70896ffeeef32b9c950ywandef ProcessLine(filename, file_extension, clean_lines, line, 4492233d2500723e5594f3e7c70896ffeeef32b9c950ywan include_state, function_state, nesting_state, error, 4493233d2500723e5594f3e7c70896ffeeef32b9c950ywan extra_check_functions=[]): 4494233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Processes a single line in the file. 4495233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4496233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 4497233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename: Filename of the file that is being processed. 4498233d2500723e5594f3e7c70896ffeeef32b9c950ywan file_extension: The extension (dot not included) of the file. 4499233d2500723e5594f3e7c70896ffeeef32b9c950ywan clean_lines: An array of strings, each representing a line of the file, 4500233d2500723e5594f3e7c70896ffeeef32b9c950ywan with comments stripped. 4501233d2500723e5594f3e7c70896ffeeef32b9c950ywan line: Number of line being processed. 4502233d2500723e5594f3e7c70896ffeeef32b9c950ywan include_state: An _IncludeState instance in which the headers are inserted. 4503233d2500723e5594f3e7c70896ffeeef32b9c950ywan function_state: A _FunctionState instance which counts function lines, etc. 4504233d2500723e5594f3e7c70896ffeeef32b9c950ywan nesting_state: A _NestingState instance which maintains information about 4505233d2500723e5594f3e7c70896ffeeef32b9c950ywan the current stack of nested blocks being parsed. 4506233d2500723e5594f3e7c70896ffeeef32b9c950ywan error: A callable to which errors are reported, which takes 4 arguments: 4507233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename, line number, error level, and message 4508233d2500723e5594f3e7c70896ffeeef32b9c950ywan extra_check_functions: An array of additional check functions that will be 4509233d2500723e5594f3e7c70896ffeeef32b9c950ywan run on each source line. Each function takes 4 4510233d2500723e5594f3e7c70896ffeeef32b9c950ywan arguments: filename, clean_lines, line, error 4511233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 4512233d2500723e5594f3e7c70896ffeeef32b9c950ywan raw_lines = clean_lines.raw_lines 4513233d2500723e5594f3e7c70896ffeeef32b9c950ywan ParseNolintSuppressions(filename, raw_lines[line], line, error) 4514233d2500723e5594f3e7c70896ffeeef32b9c950ywan nesting_state.Update(filename, clean_lines, line, error) 4515233d2500723e5594f3e7c70896ffeeef32b9c950ywan if nesting_state.stack and nesting_state.stack[-1].inline_asm != _NO_ASM: 4516233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 4517233d2500723e5594f3e7c70896ffeeef32b9c950ywan CheckForFunctionLengths(filename, clean_lines, line, function_state, error) 4518233d2500723e5594f3e7c70896ffeeef32b9c950ywan CheckForMultilineCommentsAndStrings(filename, clean_lines, line, error) 4519233d2500723e5594f3e7c70896ffeeef32b9c950ywan CheckStyle(filename, clean_lines, line, file_extension, nesting_state, error) 4520233d2500723e5594f3e7c70896ffeeef32b9c950ywan CheckLanguage(filename, clean_lines, line, file_extension, include_state, 4521233d2500723e5594f3e7c70896ffeeef32b9c950ywan nesting_state, error) 4522233d2500723e5594f3e7c70896ffeeef32b9c950ywan CheckForNonConstReference(filename, clean_lines, line, nesting_state, error) 4523233d2500723e5594f3e7c70896ffeeef32b9c950ywan CheckForNonStandardConstructs(filename, clean_lines, line, 4524233d2500723e5594f3e7c70896ffeeef32b9c950ywan nesting_state, error) 4525233d2500723e5594f3e7c70896ffeeef32b9c950ywan CheckVlogArguments(filename, clean_lines, line, error) 4526233d2500723e5594f3e7c70896ffeeef32b9c950ywan CheckPosixThreading(filename, clean_lines, line, error) 4527233d2500723e5594f3e7c70896ffeeef32b9c950ywan CheckInvalidIncrement(filename, clean_lines, line, error) 4528233d2500723e5594f3e7c70896ffeeef32b9c950ywan CheckMakePairUsesDeduction(filename, clean_lines, line, error) 4529233d2500723e5594f3e7c70896ffeeef32b9c950ywan for check_fn in extra_check_functions: 4530233d2500723e5594f3e7c70896ffeeef32b9c950ywan check_fn(filename, clean_lines, line, error) 4531233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4532233d2500723e5594f3e7c70896ffeeef32b9c950ywandef ProcessFileData(filename, file_extension, lines, error, 4533233d2500723e5594f3e7c70896ffeeef32b9c950ywan extra_check_functions=[]): 4534233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Performs lint checks and reports any errors to the given error function. 4535233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4536233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 4537233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename: Filename of the file that is being processed. 4538233d2500723e5594f3e7c70896ffeeef32b9c950ywan file_extension: The extension (dot not included) of the file. 4539233d2500723e5594f3e7c70896ffeeef32b9c950ywan lines: An array of strings, each representing a line of the file, with the 4540233d2500723e5594f3e7c70896ffeeef32b9c950ywan last element being empty if the file is terminated with a newline. 4541233d2500723e5594f3e7c70896ffeeef32b9c950ywan error: A callable to which errors are reported, which takes 4 arguments: 4542233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename, line number, error level, and message 4543233d2500723e5594f3e7c70896ffeeef32b9c950ywan extra_check_functions: An array of additional check functions that will be 4544233d2500723e5594f3e7c70896ffeeef32b9c950ywan run on each source line. Each function takes 4 4545233d2500723e5594f3e7c70896ffeeef32b9c950ywan arguments: filename, clean_lines, line, error 4546233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 4547233d2500723e5594f3e7c70896ffeeef32b9c950ywan lines = (['// marker so line numbers and indices both start at 1'] + lines + 4548233d2500723e5594f3e7c70896ffeeef32b9c950ywan ['// marker so line numbers end in a known way']) 4549233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4550233d2500723e5594f3e7c70896ffeeef32b9c950ywan include_state = _IncludeState() 4551233d2500723e5594f3e7c70896ffeeef32b9c950ywan function_state = _FunctionState() 4552233d2500723e5594f3e7c70896ffeeef32b9c950ywan nesting_state = _NestingState() 4553233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4554233d2500723e5594f3e7c70896ffeeef32b9c950ywan ResetNolintSuppressions() 4555233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4556233d2500723e5594f3e7c70896ffeeef32b9c950ywan CheckForCopyright(filename, lines, error) 4557233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4558233d2500723e5594f3e7c70896ffeeef32b9c950ywan if file_extension == 'h': 4559233d2500723e5594f3e7c70896ffeeef32b9c950ywan CheckForHeaderGuard(filename, lines, error) 4560233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4561233d2500723e5594f3e7c70896ffeeef32b9c950ywan RemoveMultiLineComments(filename, lines, error) 4562233d2500723e5594f3e7c70896ffeeef32b9c950ywan clean_lines = CleansedLines(lines) 4563233d2500723e5594f3e7c70896ffeeef32b9c950ywan for line in xrange(clean_lines.NumLines()): 4564233d2500723e5594f3e7c70896ffeeef32b9c950ywan ProcessLine(filename, file_extension, clean_lines, line, 4565233d2500723e5594f3e7c70896ffeeef32b9c950ywan include_state, function_state, nesting_state, error, 4566233d2500723e5594f3e7c70896ffeeef32b9c950ywan extra_check_functions) 4567233d2500723e5594f3e7c70896ffeeef32b9c950ywan nesting_state.CheckCompletedBlocks(filename, error) 4568233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4569233d2500723e5594f3e7c70896ffeeef32b9c950ywan CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error) 4570233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4571233d2500723e5594f3e7c70896ffeeef32b9c950ywan # We check here rather than inside ProcessLine so that we see raw 4572233d2500723e5594f3e7c70896ffeeef32b9c950ywan # lines rather than "cleaned" lines. 4573233d2500723e5594f3e7c70896ffeeef32b9c950ywan CheckForBadCharacters(filename, lines, error) 4574233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4575233d2500723e5594f3e7c70896ffeeef32b9c950ywan CheckForNewlineAtEOF(filename, lines, error) 4576233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4577233d2500723e5594f3e7c70896ffeeef32b9c950ywandef ProcessFile(filename, vlevel, extra_check_functions=[]): 4578233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Does google-lint on a single file. 4579233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4580233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 4581233d2500723e5594f3e7c70896ffeeef32b9c950ywan filename: The name of the file to parse. 4582233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4583233d2500723e5594f3e7c70896ffeeef32b9c950ywan vlevel: The level of errors to report. Every error of confidence 4584233d2500723e5594f3e7c70896ffeeef32b9c950ywan >= verbose_level will be reported. 0 is a good default. 4585233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4586233d2500723e5594f3e7c70896ffeeef32b9c950ywan extra_check_functions: An array of additional check functions that will be 4587233d2500723e5594f3e7c70896ffeeef32b9c950ywan run on each source line. Each function takes 4 4588233d2500723e5594f3e7c70896ffeeef32b9c950ywan arguments: filename, clean_lines, line, error 4589233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 4590233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4591233d2500723e5594f3e7c70896ffeeef32b9c950ywan _SetVerboseLevel(vlevel) 4592233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4593233d2500723e5594f3e7c70896ffeeef32b9c950ywan try: 4594233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Support the UNIX convention of using "-" for stdin. Note that 4595233d2500723e5594f3e7c70896ffeeef32b9c950ywan # we are not opening the file with universal newline support 4596233d2500723e5594f3e7c70896ffeeef32b9c950ywan # (which codecs doesn't support anyway), so the resulting lines do 4597233d2500723e5594f3e7c70896ffeeef32b9c950ywan # contain trailing '\r' characters if we are reading a file that 4598233d2500723e5594f3e7c70896ffeeef32b9c950ywan # has CRLF endings. 4599233d2500723e5594f3e7c70896ffeeef32b9c950ywan # If after the split a trailing '\r' is present, it is removed 4600233d2500723e5594f3e7c70896ffeeef32b9c950ywan # below. If it is not expected to be present (i.e. os.linesep != 4601233d2500723e5594f3e7c70896ffeeef32b9c950ywan # '\r\n' as in Windows), a warning is issued below if this file 4602233d2500723e5594f3e7c70896ffeeef32b9c950ywan # is processed. 4603233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4604233d2500723e5594f3e7c70896ffeeef32b9c950ywan if filename == '-': 4605233d2500723e5594f3e7c70896ffeeef32b9c950ywan lines = codecs.StreamReaderWriter(sys.stdin, 4606233d2500723e5594f3e7c70896ffeeef32b9c950ywan codecs.getreader('utf8'), 4607233d2500723e5594f3e7c70896ffeeef32b9c950ywan codecs.getwriter('utf8'), 4608233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'replace').read().split('\n') 4609233d2500723e5594f3e7c70896ffeeef32b9c950ywan else: 4610233d2500723e5594f3e7c70896ffeeef32b9c950ywan lines = codecs.open(filename, 'r', 'utf8', 'replace').read().split('\n') 4611233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4612233d2500723e5594f3e7c70896ffeeef32b9c950ywan carriage_return_found = False 4613233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Remove trailing '\r'. 4614233d2500723e5594f3e7c70896ffeeef32b9c950ywan for linenum in range(len(lines)): 4615233d2500723e5594f3e7c70896ffeeef32b9c950ywan if lines[linenum].endswith('\r'): 4616233d2500723e5594f3e7c70896ffeeef32b9c950ywan lines[linenum] = lines[linenum].rstrip('\r') 4617233d2500723e5594f3e7c70896ffeeef32b9c950ywan carriage_return_found = True 4618233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4619233d2500723e5594f3e7c70896ffeeef32b9c950ywan except IOError: 4620233d2500723e5594f3e7c70896ffeeef32b9c950ywan sys.stderr.write( 4621233d2500723e5594f3e7c70896ffeeef32b9c950ywan "Skipping input '%s': Can't open for reading\n" % filename) 4622233d2500723e5594f3e7c70896ffeeef32b9c950ywan return 4623233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4624233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Note, if no dot is found, this will give the entire filename as the ext. 4625233d2500723e5594f3e7c70896ffeeef32b9c950ywan file_extension = filename[filename.rfind('.') + 1:] 4626233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4627233d2500723e5594f3e7c70896ffeeef32b9c950ywan # When reading from stdin, the extension is unknown, so no cpplint tests 4628233d2500723e5594f3e7c70896ffeeef32b9c950ywan # should rely on the extension. 4629233d2500723e5594f3e7c70896ffeeef32b9c950ywan if filename != '-' and file_extension not in _valid_extensions: 4630233d2500723e5594f3e7c70896ffeeef32b9c950ywan sys.stderr.write('Ignoring %s; not a valid file name ' 4631233d2500723e5594f3e7c70896ffeeef32b9c950ywan '(%s)\n' % (filename, ', '.join(_valid_extensions))) 4632233d2500723e5594f3e7c70896ffeeef32b9c950ywan else: 4633233d2500723e5594f3e7c70896ffeeef32b9c950ywan ProcessFileData(filename, file_extension, lines, Error, 4634233d2500723e5594f3e7c70896ffeeef32b9c950ywan extra_check_functions) 4635233d2500723e5594f3e7c70896ffeeef32b9c950ywan if carriage_return_found and os.linesep != '\r\n': 4636233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Use 0 for linenum since outputting only one error for potentially 4637233d2500723e5594f3e7c70896ffeeef32b9c950ywan # several lines. 4638233d2500723e5594f3e7c70896ffeeef32b9c950ywan Error(filename, 0, 'whitespace/newline', 1, 4639233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'One or more unexpected \\r (^M) found;' 4640233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'better to use only a \\n') 4641233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4642233d2500723e5594f3e7c70896ffeeef32b9c950ywan sys.stderr.write('Done processing %s\n' % filename) 4643233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4644233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4645233d2500723e5594f3e7c70896ffeeef32b9c950ywandef PrintUsage(message): 4646233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Prints a brief usage string and exits, optionally with an error message. 4647233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4648233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 4649233d2500723e5594f3e7c70896ffeeef32b9c950ywan message: The optional error message. 4650233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 4651233d2500723e5594f3e7c70896ffeeef32b9c950ywan sys.stderr.write(_USAGE) 4652233d2500723e5594f3e7c70896ffeeef32b9c950ywan if message: 4653233d2500723e5594f3e7c70896ffeeef32b9c950ywan sys.exit('\nFATAL ERROR: ' + message) 4654233d2500723e5594f3e7c70896ffeeef32b9c950ywan else: 4655233d2500723e5594f3e7c70896ffeeef32b9c950ywan sys.exit(1) 4656233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4657233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4658233d2500723e5594f3e7c70896ffeeef32b9c950ywandef PrintCategories(): 4659233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Prints a list of all the error-categories used by error messages. 4660233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4661233d2500723e5594f3e7c70896ffeeef32b9c950ywan These are the categories used to filter messages via --filter. 4662233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 4663233d2500723e5594f3e7c70896ffeeef32b9c950ywan sys.stderr.write(''.join(' %s\n' % cat for cat in _ERROR_CATEGORIES)) 4664233d2500723e5594f3e7c70896ffeeef32b9c950ywan sys.exit(0) 4665233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4666233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4667233d2500723e5594f3e7c70896ffeeef32b9c950ywandef ParseArguments(args): 4668233d2500723e5594f3e7c70896ffeeef32b9c950ywan """Parses the command line arguments. 4669233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4670233d2500723e5594f3e7c70896ffeeef32b9c950ywan This may set the output format and verbosity level as side-effects. 4671233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4672233d2500723e5594f3e7c70896ffeeef32b9c950ywan Args: 4673233d2500723e5594f3e7c70896ffeeef32b9c950ywan args: The command line arguments: 4674233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4675233d2500723e5594f3e7c70896ffeeef32b9c950ywan Returns: 4676233d2500723e5594f3e7c70896ffeeef32b9c950ywan The list of filenames to lint. 4677233d2500723e5594f3e7c70896ffeeef32b9c950ywan """ 4678233d2500723e5594f3e7c70896ffeeef32b9c950ywan try: 4679233d2500723e5594f3e7c70896ffeeef32b9c950ywan (opts, filenames) = getopt.getopt(args, '', ['help', 'output=', 'verbose=', 4680233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'counting=', 4681233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'filter=', 4682233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'root=', 4683233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'linelength=', 4684233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'extensions=']) 4685233d2500723e5594f3e7c70896ffeeef32b9c950ywan except getopt.GetoptError: 4686233d2500723e5594f3e7c70896ffeeef32b9c950ywan PrintUsage('Invalid arguments.') 4687233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4688233d2500723e5594f3e7c70896ffeeef32b9c950ywan verbosity = _VerboseLevel() 4689233d2500723e5594f3e7c70896ffeeef32b9c950ywan output_format = _OutputFormat() 4690233d2500723e5594f3e7c70896ffeeef32b9c950ywan filters = '' 4691233d2500723e5594f3e7c70896ffeeef32b9c950ywan counting_style = '' 4692233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4693233d2500723e5594f3e7c70896ffeeef32b9c950ywan for (opt, val) in opts: 4694233d2500723e5594f3e7c70896ffeeef32b9c950ywan if opt == '--help': 4695233d2500723e5594f3e7c70896ffeeef32b9c950ywan PrintUsage(None) 4696233d2500723e5594f3e7c70896ffeeef32b9c950ywan elif opt == '--output': 4697233d2500723e5594f3e7c70896ffeeef32b9c950ywan if val not in ('emacs', 'vs7', 'eclipse'): 4698233d2500723e5594f3e7c70896ffeeef32b9c950ywan PrintUsage('The only allowed output formats are emacs, vs7 and eclipse.') 4699233d2500723e5594f3e7c70896ffeeef32b9c950ywan output_format = val 4700233d2500723e5594f3e7c70896ffeeef32b9c950ywan elif opt == '--verbose': 4701233d2500723e5594f3e7c70896ffeeef32b9c950ywan verbosity = int(val) 4702233d2500723e5594f3e7c70896ffeeef32b9c950ywan elif opt == '--filter': 4703233d2500723e5594f3e7c70896ffeeef32b9c950ywan filters = val 4704233d2500723e5594f3e7c70896ffeeef32b9c950ywan if not filters: 4705233d2500723e5594f3e7c70896ffeeef32b9c950ywan PrintCategories() 4706233d2500723e5594f3e7c70896ffeeef32b9c950ywan elif opt == '--counting': 4707233d2500723e5594f3e7c70896ffeeef32b9c950ywan if val not in ('total', 'toplevel', 'detailed'): 4708233d2500723e5594f3e7c70896ffeeef32b9c950ywan PrintUsage('Valid counting options are total, toplevel, and detailed') 4709233d2500723e5594f3e7c70896ffeeef32b9c950ywan counting_style = val 4710233d2500723e5594f3e7c70896ffeeef32b9c950ywan elif opt == '--root': 4711233d2500723e5594f3e7c70896ffeeef32b9c950ywan global _root 4712233d2500723e5594f3e7c70896ffeeef32b9c950ywan _root = val 4713233d2500723e5594f3e7c70896ffeeef32b9c950ywan elif opt == '--linelength': 4714233d2500723e5594f3e7c70896ffeeef32b9c950ywan global _line_length 4715233d2500723e5594f3e7c70896ffeeef32b9c950ywan try: 4716233d2500723e5594f3e7c70896ffeeef32b9c950ywan _line_length = int(val) 4717233d2500723e5594f3e7c70896ffeeef32b9c950ywan except ValueError: 4718233d2500723e5594f3e7c70896ffeeef32b9c950ywan PrintUsage('Line length must be digits.') 4719233d2500723e5594f3e7c70896ffeeef32b9c950ywan elif opt == '--extensions': 4720233d2500723e5594f3e7c70896ffeeef32b9c950ywan global _valid_extensions 4721233d2500723e5594f3e7c70896ffeeef32b9c950ywan try: 4722233d2500723e5594f3e7c70896ffeeef32b9c950ywan _valid_extensions = set(val.split(',')) 4723233d2500723e5594f3e7c70896ffeeef32b9c950ywan except ValueError: 4724233d2500723e5594f3e7c70896ffeeef32b9c950ywan PrintUsage('Extensions must be comma seperated list.') 4725233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4726233d2500723e5594f3e7c70896ffeeef32b9c950ywan if not filenames: 4727233d2500723e5594f3e7c70896ffeeef32b9c950ywan PrintUsage('No files were specified.') 4728233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4729233d2500723e5594f3e7c70896ffeeef32b9c950ywan _SetOutputFormat(output_format) 4730233d2500723e5594f3e7c70896ffeeef32b9c950ywan _SetVerboseLevel(verbosity) 4731233d2500723e5594f3e7c70896ffeeef32b9c950ywan _SetFilters(filters) 4732233d2500723e5594f3e7c70896ffeeef32b9c950ywan _SetCountingStyle(counting_style) 4733233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4734233d2500723e5594f3e7c70896ffeeef32b9c950ywan return filenames 4735233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4736233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4737233d2500723e5594f3e7c70896ffeeef32b9c950ywandef main(): 4738233d2500723e5594f3e7c70896ffeeef32b9c950ywan filenames = ParseArguments(sys.argv[1:]) 4739233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4740233d2500723e5594f3e7c70896ffeeef32b9c950ywan # Change stderr to write with replacement characters so we don't die 4741233d2500723e5594f3e7c70896ffeeef32b9c950ywan # if we try to print something containing non-ASCII characters. 4742233d2500723e5594f3e7c70896ffeeef32b9c950ywan sys.stderr = codecs.StreamReaderWriter(sys.stderr, 4743233d2500723e5594f3e7c70896ffeeef32b9c950ywan codecs.getreader('utf8'), 4744233d2500723e5594f3e7c70896ffeeef32b9c950ywan codecs.getwriter('utf8'), 4745233d2500723e5594f3e7c70896ffeeef32b9c950ywan 'replace') 4746233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4747233d2500723e5594f3e7c70896ffeeef32b9c950ywan _cpplint_state.ResetErrorCounts() 4748233d2500723e5594f3e7c70896ffeeef32b9c950ywan for filename in filenames: 4749233d2500723e5594f3e7c70896ffeeef32b9c950ywan ProcessFile(filename, _cpplint_state.verbose_level) 4750233d2500723e5594f3e7c70896ffeeef32b9c950ywan _cpplint_state.PrintErrorCounts() 4751233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4752233d2500723e5594f3e7c70896ffeeef32b9c950ywan sys.exit(_cpplint_state.error_count > 0) 4753233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4754233d2500723e5594f3e7c70896ffeeef32b9c950ywan 4755233d2500723e5594f3e7c70896ffeeef32b9c950ywanif __name__ == '__main__': 4756233d2500723e5594f3e7c70896ffeeef32b9c950ywan main() 4757