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