4020 lines · 155.0 KB · Python
RawDownload
#!/usr/bin/python## Copyright (c) 2009 Google Inc. All rights reserved.## Redistribution and use in source and binary forms, with or without# modification, are permitted provided that the following conditions are# met:##    * Redistributions of source code must retain the above copyright# notice, this list of conditions and the following disclaimer.#    * Redistributions in binary form must reproduce the above# copyright notice, this list of conditions and the following disclaimer# in the documentation and/or other materials provided with the# distribution.#    * Neither the name of Google Inc. nor the names of its# contributors may be used to endorse or promote products derived from# this software without specific prior written permission.## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # Here are some issues that I've had people identify in my code during reviews,# that I think are possible to flag automatically in a lint tool.  If these were# caught by lint, it would save time both for myself and that of my reviewers.# Most likely, some of these are beyond the scope of the current lint framework,# but I think it is valuable to retain these wish-list items even if they cannot# be immediately implemented.##  Suggestions#  -----------#  - Check for no 'explicit' for multi-arg ctor#  - Check for boolean assign RHS in parens#  - Check for ctor initializer-list colon position and spacing#  - Check that if there's a ctor, there should be a dtor#  - Check accessors that return non-pointer member variables are#    declared const#  - Check accessors that return non-const pointer member vars are#    *not* declared const#  - Check for using public includes for testing#  - Check for spaces between brackets in one-line inline method#  - Check for no assert()#  - Check for spaces surrounding operators#  - Check for 0 in pointer context (should be NULL)#  - Check for 0 in char context (should be '\0')#  - Check for camel-case method name conventions for methods#    that are not simple inline getters and setters#  - Do not indent namespace contents#  - Avoid inlining non-trivial constructors in header files#  - Check for old-school (void) cast for call-sites of functions#    ignored return value#  - Check gUnit usage of anonymous namespace#  - Check for class declaration order (typedefs, consts, enums,#    ctor(s?), dtor, friend declarations, methods, member vars)# """Does google-lint on c++ files. The goal of this script is to identify places in the code that *may*be in non-compliance with google style.  It does not attempt to fixup these problems -- the point is to educate.  It does also notattempt to find all problems, or to ensure that everything it doesfind is legitimately a problem. In particular, we can get very confused by /* and // inside strings!We do a small hack, which is to ignore //'s with "'s after them on thesame line, but it is far from perfect (in either direction).""" import codecsimport copyimport getoptimport math  # for logimport osimport reimport sre_compileimport stringimport sysimport unicodedata  _USAGE = """Syntax: cpplint.py [--verbose=#] [--output=vs7] [--filter=-x,+y,...]                   [--counting=total|toplevel|detailed]        <file> [file] ...   The style guidelines this tries to follow are those in    http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml   Every problem is given a confidence score from 1-5, with 5 meaning we are  certain of the problem, and 1 meaning it could be a legitimate construct.  This will miss some errors, and is not a substitute for a code review.   To suppress false-positive errors of a certain category, add a  'NOLINT(category)' comment to the line.  NOLINT or NOLINT(*)  suppresses errors of all categories on that line.   The files passed in will be linted; at least one file must be provided.  Linted extensions are .cc, .cpp, and .h.  Other file types will be ignored.   Flags:     output=vs7      By default, the output is formatted to ease emacs parsing.  Visual Studio      compatible output (vs7) may also be used.  Other formats are unsupported.     verbose=#      Specify a number 0-5 to restrict errors to certain verbosity levels.     filter=-x,+y,...      Specify a comma-separated list of category-filters to apply: only      error messages whose category names pass the filters will be printed.      (Category names are printed with the message and look like      "[whitespace/indent]".)  Filters are evaluated left to right.      "-FOO" and "FOO" means "do not print categories that start with FOO".      "+FOO" means "do print categories that start with FOO".       Examples: --filter=-whitespace,+whitespace/braces                --filter=whitespace,runtime/printf,+runtime/printf_format                --filter=-,+build/include_what_you_use       To see a list of all the categories used in cpplint, pass no arg:         --filter=     counting=total|toplevel|detailed      The total number of errors found is always printed. If      'toplevel' is provided, then the count of errors in each of      the top-level categories like 'build' and 'whitespace' will      also be printed. If 'detailed' is provided, then a count      is provided for each category like 'build/class'.     root=subdir      The root directory used for deriving header guard CPP variable.      By default, the header guard CPP variable is calculated as the relative      path to the directory that contains .git, .hg, or .svn.  When this flag      is specified, the relative path is calculated from the specified      directory. If the specified directory does not exist, this flag is      ignored.       Examples:        Assuing that src/.git exists, the header guard CPP variables for        src/chrome/browser/ui/browser.h are:         No flag => CHROME_BROWSER_UI_BROWSER_H_        --root=chrome => BROWSER_UI_BROWSER_H_        --root=chrome/browser => UI_BROWSER_H_""" # We categorize each error message we print.  Here are the categories.# We want an explicit list so we can list them all in cpplint --filter=.# If you add a new error message with a new category, add it to the list# here!  cpplint_unittest.py should tell you if you forget to do this.# \ used for clearer layout -- pylint: disable-msg=C6013_ERROR_CATEGORIES = [  'build/class',  'build/deprecated',  'build/endif_comment',  'build/explicit_make_pair',  'build/forward_decl',  'build/header_guard',  'build/include',  'build/include_alpha',  'build/include_order',  'build/include_what_you_use',  'build/namespaces',  'build/printf_format',  'build/storage_class',  'legal/copyright',  'readability/alt_tokens',  'readability/braces',  'readability/casting',  'readability/check',  'readability/constructors',  'readability/fn_size',  'readability/function',  'readability/multiline_comment',  'readability/multiline_string',  'readability/namespace',  'readability/nolint',  'readability/streams',  'readability/todo',  'readability/utf8',  'runtime/arrays',  'runtime/casting',  'runtime/explicit',  'runtime/int',  'runtime/init',  'runtime/invalid_increment',  'runtime/member_string_references',  'runtime/memset',  'runtime/operator',  'runtime/printf',  'runtime/printf_format',  'runtime/references',  'runtime/rtti',  'runtime/sizeof',  'runtime/string',  'runtime/threadsafe_fn',  'whitespace/blank_line',  'whitespace/braces',  'whitespace/comma',  'whitespace/comments',  'whitespace/empty_loop_body',  'whitespace/end_of_line',  'whitespace/ending_newline',  'whitespace/forcolon',  'whitespace/indent',  'whitespace/labels',  'whitespace/line_length',  'whitespace/newline',  'whitespace/operators',  'whitespace/parens',  'whitespace/semicolon',  'whitespace/tab',  'whitespace/todo'  ] # The default state of the category filter. This is overrided by the --filter=# flag. By default all errors are on, so only add here categories that should be# off by default (i.e., categories that must be enabled by the --filter= flags).# All entries here should start with a '-' or '+', as in the --filter= flag._DEFAULT_FILTERS = ['-build/include_alpha'] # We used to check for high-bit characters, but after much discussion we# decided those were OK, as long as they were in UTF-8 and didn't represent# hard-coded international strings, which belong in a separate i18n file. # Headers that we consider STL headers._STL_HEADERS = frozenset([    'algobase.h', 'algorithm', 'alloc.h', 'bitset', 'deque', 'exception',    'function.h', 'functional', 'hash_map', 'hash_map.h', 'hash_set',    'hash_set.h', 'iterator', 'list', 'list.h', 'map', 'memory', 'new',    'pair.h', 'pthread_alloc', 'queue', 'set', 'set.h', 'sstream', 'stack',    'stl_alloc.h', 'stl_relops.h', 'type_traits.h',    'utility', 'vector', 'vector.h',    ])  # Non-STL C++ system headers._CPP_HEADERS = frozenset([    'algo.h', 'builtinbuf.h', 'bvector.h', 'cassert', 'cctype',    'cerrno', 'cfloat', 'ciso646', 'climits', 'clocale', 'cmath',    'complex', 'complex.h', 'csetjmp', 'csignal', 'cstdarg', 'cstddef',    'cstdio', 'cstdlib', 'cstring', 'ctime', 'cwchar', 'cwctype',    'defalloc.h', 'deque.h', 'editbuf.h', 'exception', 'fstream',    'fstream.h', 'hashtable.h', 'heap.h', 'indstream.h', 'iomanip',    'iomanip.h', 'ios', 'iosfwd', 'iostream', 'iostream.h', 'istream',    'istream.h', 'iterator.h', 'limits', 'map.h', 'multimap.h', 'multiset.h',    'numeric', 'ostream', 'ostream.h', 'parsestream.h', 'pfstream.h',    'PlotFile.h', 'procbuf.h', 'pthread_alloc.h', 'rope', 'rope.h',    'ropeimpl.h', 'SFile.h', 'slist', 'slist.h', 'stack.h', 'stdexcept',    'stdiostream.h', 'streambuf.h', 'stream.h', 'strfile.h', 'string',    'strstream', 'strstream.h', 'tempbuf.h', 'tree.h', 'typeinfo', 'valarray',    ])  # Assertion macros.  These are defined in base/logging.h and# testing/base/gunit.h.  Note that the _M versions need to come first# for substring matching to work._CHECK_MACROS = [    'DCHECK', 'CHECK',    'EXPECT_TRUE_M', 'EXPECT_TRUE',    'ASSERT_TRUE_M', 'ASSERT_TRUE',    'EXPECT_FALSE_M', 'EXPECT_FALSE',    'ASSERT_FALSE_M', 'ASSERT_FALSE',    ] # Replacement macros for CHECK/DCHECK/EXPECT_TRUE/EXPECT_FALSE_CHECK_REPLACEMENT = dict([(m, {}) for m in _CHECK_MACROS]) for op, replacement in [('==', 'EQ'), ('!=', 'NE'),                        ('>=', 'GE'), ('>', 'GT'),                        ('<=', 'LE'), ('<', 'LT')]:  _CHECK_REPLACEMENT['DCHECK'][op] = 'DCHECK_%s' % replacement  _CHECK_REPLACEMENT['CHECK'][op] = 'CHECK_%s' % replacement  _CHECK_REPLACEMENT['EXPECT_TRUE'][op] = 'EXPECT_%s' % replacement  _CHECK_REPLACEMENT['ASSERT_TRUE'][op] = 'ASSERT_%s' % replacement  _CHECK_REPLACEMENT['EXPECT_TRUE_M'][op] = 'EXPECT_%s_M' % replacement  _CHECK_REPLACEMENT['ASSERT_TRUE_M'][op] = 'ASSERT_%s_M' % replacement for op, inv_replacement in [('==', 'NE'), ('!=', 'EQ'),                            ('>=', 'LT'), ('>', 'LE'),                            ('<=', 'GT'), ('<', 'GE')]:  _CHECK_REPLACEMENT['EXPECT_FALSE'][op] = 'EXPECT_%s' % inv_replacement  _CHECK_REPLACEMENT['ASSERT_FALSE'][op] = 'ASSERT_%s' % inv_replacement  _CHECK_REPLACEMENT['EXPECT_FALSE_M'][op] = 'EXPECT_%s_M' % inv_replacement  _CHECK_REPLACEMENT['ASSERT_FALSE_M'][op] = 'ASSERT_%s_M' % inv_replacement # Alternative tokens and their replacements.  For full list, see section 2.5# Alternative tokens [lex.digraph] in the C++ standard.## Digraphs (such as '%:') are not included here since it's a mess to# match those on a word boundary._ALT_TOKEN_REPLACEMENT = {    'and': '&&',    'bitor': '|',    'or': '||',    'xor': '^',    'compl': '~',    'bitand': '&',    'and_eq': '&=',    'or_eq': '|=',    'xor_eq': '^=',    'not': '!',    'not_eq': '!='    } # Compile regular expression that matches all the above keywords.  The "[ =()]"# bit is meant to avoid matching these keywords outside of boolean expressions.## False positives include C-style multi-line comments (http://go/nsiut )# and multi-line strings (http://go/beujw ), but those have always been# troublesome for cpplint._ALT_TOKEN_REPLACEMENT_PATTERN = re.compile(    r'[ =()](' + ('|'.join(_ALT_TOKEN_REPLACEMENT.keys())) + r')(?=[ (]|$)')  # These constants define types of headers for use with# _IncludeState.CheckNextIncludeOrder()._C_SYS_HEADER = 1_CPP_SYS_HEADER = 2_LIKELY_MY_HEADER = 3_POSSIBLE_MY_HEADER = 4_OTHER_HEADER = 5 # These constants define the current inline assembly state_NO_ASM = 0       # Outside of inline assembly block_INSIDE_ASM = 1   # Inside inline assembly block_END_ASM = 2      # Last line of inline assembly block_BLOCK_ASM = 3    # The whole block is an inline assembly block # Match start of assembly blocks_MATCH_ASM = re.compile(r'^\s*(?:asm|_asm|__asm|__asm__)'                        r'(?:\s+(volatile|__volatile__))?'                        r'\s*[{(]')  _regexp_compile_cache = {} # Finds occurrences of NOLINT or NOLINT(...)._RE_SUPPRESSION = re.compile(r'\bNOLINT\b(\([^)]*\))?') # {str, set(int)}: a map from error categories to sets of linenumbers# on which those errors are expected and should be suppressed._error_suppressions = {} # The root directory used for deriving header guard CPP variable.# This is set by --root flag._root = None def ParseNolintSuppressions(filename, raw_line, linenum, error):  """Updates the global list of error-suppressions.   Parses any NOLINT comments on the current line, updating the global  error_suppressions store.  Reports an error if the NOLINT comment  was malformed.   Args:    filename: str, the name of the input file.    raw_line: str, the line of input text, with comments.    linenum: int, the number of the current line.    error: function, an error handler.  """  # FIXME(adonovan): "NOLINT(" is misparsed as NOLINT(*).  matched = _RE_SUPPRESSION.search(raw_line)  if matched:    category = matched.group(1)    if category in (None, '(*)'):  # => "suppress all"      _error_suppressions.setdefault(None, set()).add(linenum)    else:      if category.startswith('(') and category.endswith(')'):        category = category[1:-1]        if category in _ERROR_CATEGORIES:          _error_suppressions.setdefault(category, set()).add(linenum)        else:          error(filename, linenum, 'readability/nolint', 5,                'Unknown NOLINT error category: %s' % category)  def ResetNolintSuppressions():  "Resets the set of NOLINT suppressions to empty."  _error_suppressions.clear()  def IsErrorSuppressedByNolint(category, linenum):  """Returns true if the specified error category is suppressed on this line.   Consults the global error_suppressions map populated by  ParseNolintSuppressions/ResetNolintSuppressions.   Args:    category: str, the category of the error.    linenum: int, the current line number.  Returns:    bool, True iff the error should be suppressed due to a NOLINT comment.  """  return (linenum in _error_suppressions.get(category, set()) or          linenum in _error_suppressions.get(None, set())) def Match(pattern, s):  """Matches the string with the pattern, caching the compiled regexp."""  # The regexp compilation caching is inlined in both Match and Search for  # performance reasons; factoring it out into a separate function turns out  # to be noticeably expensive.  if not pattern in _regexp_compile_cache:    _regexp_compile_cache[pattern] = sre_compile.compile(pattern)  return _regexp_compile_cache[pattern].match(s)  def Search(pattern, s):  """Searches the string for the pattern, caching the compiled regexp."""  if not pattern in _regexp_compile_cache:    _regexp_compile_cache[pattern] = sre_compile.compile(pattern)  return _regexp_compile_cache[pattern].search(s)  class _IncludeState(dict):  """Tracks line numbers for includes, and the order in which includes appear.   As a dict, an _IncludeState object serves as a mapping between include  filename and line number on which that file was included.   Call CheckNextIncludeOrder() once for each header in the file, passing  in the type constants defined above. Calls in an illegal order will  raise an _IncludeError with an appropriate error message.   """  # self._section will move monotonically through this set. If it ever  # needs to move backwards, CheckNextIncludeOrder will raise an error.  _INITIAL_SECTION = 0  _MY_H_SECTION = 1  _C_SECTION = 2  _CPP_SECTION = 3  _OTHER_H_SECTION = 4   _TYPE_NAMES = {      _C_SYS_HEADER: 'C system header',      _CPP_SYS_HEADER: 'C++ system header',      _LIKELY_MY_HEADER: 'header this file implements',      _POSSIBLE_MY_HEADER: 'header this file may implement',      _OTHER_HEADER: 'other header',      }  _SECTION_NAMES = {      _INITIAL_SECTION: "... nothing. (This can't be an error.)",      _MY_H_SECTION: 'a header this file implements',      _C_SECTION: 'C system header',      _CPP_SECTION: 'C++ system header',      _OTHER_H_SECTION: 'other header',      }   def __init__(self):    dict.__init__(self)    # The name of the current section.    self._section = self._INITIAL_SECTION    # The path of last found header.    self._last_header = ''   def CanonicalizeAlphabeticalOrder(self, header_path):    """Returns a path canonicalized for alphabetical comparison.     - replaces "-" with "_" so they both cmp the same.    - removes '-inl' since we don't require them to be after the main header.    - lowercase everything, just in case.     Args:      header_path: Path to be canonicalized.     Returns:      Canonicalized path.    """    return header_path.replace('-inl.h', '.h').replace('-', '_').lower()   def IsInAlphabeticalOrder(self, header_path):    """Check if a header is in alphabetical order with the previous header.     Args:      header_path: Header to be checked.     Returns:      Returns true if the header is in alphabetical order.    """    canonical_header = self.CanonicalizeAlphabeticalOrder(header_path)    if self._last_header > canonical_header:      return False    self._last_header = canonical_header    return True   def CheckNextIncludeOrder(self, header_type):    """Returns a non-empty error message if the next header is out of order.     This function also updates the internal state to be ready to check    the next include.

Lines 1–500 of 4020.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t